status.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. ** 2008 June 18
  3. **
  4. ** The author disclaims copyright to this source code. In place of
  5. ** a legal notice, here is a blessing:
  6. **
  7. ** May you do good and not evil.
  8. ** May you find forgiveness for yourself and forgive others.
  9. ** May you share freely, never taking more than you give.
  10. **
  11. *************************************************************************
  12. **
  13. ** This module implements the sqlite3_status() interface and related
  14. ** functionality.
  15. */
  16. #include "sqliteInt.h"
  17. #include "vdbeInt.h"
  18. /*
  19. ** Variables in which to record status information.
  20. */
  21. typedef struct sqlite3StatType sqlite3StatType;
  22. static SQLITE_WSD struct sqlite3StatType {
  23. int nowValue[10]; /* Current value */
  24. int mxValue[10]; /* Maximum value */
  25. } sqlite3Stat = { {0,}, {0,} };
  26. /* The "wsdStat" macro will resolve to the status information
  27. ** state vector. If writable static data is unsupported on the target,
  28. ** we have to locate the state vector at run-time. In the more common
  29. ** case where writable static data is supported, wsdStat can refer directly
  30. ** to the "sqlite3Stat" state vector declared above.
  31. */
  32. #ifdef SQLITE_OMIT_WSD
  33. # define wsdStatInit sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat)
  34. # define wsdStat x[0]
  35. #else
  36. # define wsdStatInit
  37. # define wsdStat sqlite3Stat
  38. #endif
  39. /*
  40. ** Return the current value of a status parameter.
  41. */
  42. int sqlite3StatusValue(int op){
  43. wsdStatInit;
  44. assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
  45. return wsdStat.nowValue[op];
  46. }
  47. /*
  48. ** Add N to the value of a status record. It is assumed that the
  49. ** caller holds appropriate locks.
  50. */
  51. void sqlite3StatusAdd(int op, int N){
  52. wsdStatInit;
  53. assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
  54. wsdStat.nowValue[op] += N;
  55. if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
  56. wsdStat.mxValue[op] = wsdStat.nowValue[op];
  57. }
  58. }
  59. /*
  60. ** Set the value of a status to X.
  61. */
  62. void sqlite3StatusSet(int op, int X){
  63. wsdStatInit;
  64. assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
  65. wsdStat.nowValue[op] = X;
  66. if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
  67. wsdStat.mxValue[op] = wsdStat.nowValue[op];
  68. }
  69. }
  70. /*
  71. ** Query status information.
  72. **
  73. ** This implementation assumes that reading or writing an aligned
  74. ** 32-bit integer is an atomic operation. If that assumption is not true,
  75. ** then this routine is not threadsafe.
  76. */
  77. int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
  78. wsdStatInit;
  79. if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
  80. return SQLITE_MISUSE_BKPT;
  81. }
  82. *pCurrent = wsdStat.nowValue[op];
  83. *pHighwater = wsdStat.mxValue[op];
  84. if( resetFlag ){
  85. wsdStat.mxValue[op] = wsdStat.nowValue[op];
  86. }
  87. return SQLITE_OK;
  88. }
  89. /*
  90. ** Query status information for a single database connection
  91. */
  92. int sqlite3_db_status(
  93. sqlite3 *db, /* The database connection whose status is desired */
  94. int op, /* Status verb */
  95. int *pCurrent, /* Write current value here */
  96. int *pHighwater, /* Write high-water mark here */
  97. int resetFlag /* Reset high-water mark if true */
  98. ){
  99. int rc = SQLITE_OK; /* Return code */
  100. sqlite3_mutex_enter(db->mutex);
  101. switch( op ){
  102. case SQLITE_DBSTATUS_LOOKASIDE_USED: {
  103. *pCurrent = db->lookaside.nOut;
  104. *pHighwater = db->lookaside.mxOut;
  105. if( resetFlag ){
  106. db->lookaside.mxOut = db->lookaside.nOut;
  107. }
  108. break;
  109. }
  110. case SQLITE_DBSTATUS_LOOKASIDE_HIT:
  111. case SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE:
  112. case SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: {
  113. testcase( op==SQLITE_DBSTATUS_LOOKASIDE_HIT );
  114. testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE );
  115. testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL );
  116. assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 );
  117. assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 );
  118. *pCurrent = 0;
  119. *pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT];
  120. if( resetFlag ){
  121. db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0;
  122. }
  123. break;
  124. }
  125. /*
  126. ** Return an approximation for the amount of memory currently used
  127. ** by all pagers associated with the given database connection. The
  128. ** highwater mark is meaningless and is returned as zero.
  129. */
  130. case SQLITE_DBSTATUS_CACHE_USED: {
  131. int totalUsed = 0;
  132. int i;
  133. sqlite3BtreeEnterAll(db);
  134. for(i=0; i<db->nDb; i++){
  135. Btree *pBt = db->aDb[i].pBt;
  136. if( pBt ){
  137. Pager *pPager = sqlite3BtreePager(pBt);
  138. totalUsed += sqlite3PagerMemUsed(pPager);
  139. }
  140. }
  141. sqlite3BtreeLeaveAll(db);
  142. *pCurrent = totalUsed;
  143. *pHighwater = 0;
  144. break;
  145. }
  146. /*
  147. ** *pCurrent gets an accurate estimate of the amount of memory used
  148. ** to store the schema for all databases (main, temp, and any ATTACHed
  149. ** databases. *pHighwater is set to zero.
  150. */
  151. case SQLITE_DBSTATUS_SCHEMA_USED: {
  152. int i; /* Used to iterate through schemas */
  153. int nByte = 0; /* Used to accumulate return value */
  154. sqlite3BtreeEnterAll(db);
  155. db->pnBytesFreed = &nByte;
  156. for(i=0; i<db->nDb; i++){
  157. Schema *pSchema = db->aDb[i].pSchema;
  158. if( ALWAYS(pSchema!=0) ){
  159. HashElem *p;
  160. nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
  161. pSchema->tblHash.count
  162. + pSchema->trigHash.count
  163. + pSchema->idxHash.count
  164. + pSchema->fkeyHash.count
  165. );
  166. nByte += sqlite3MallocSize(pSchema->tblHash.ht);
  167. nByte += sqlite3MallocSize(pSchema->trigHash.ht);
  168. nByte += sqlite3MallocSize(pSchema->idxHash.ht);
  169. nByte += sqlite3MallocSize(pSchema->fkeyHash.ht);
  170. for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
  171. sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
  172. }
  173. for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
  174. sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
  175. }
  176. }
  177. }
  178. db->pnBytesFreed = 0;
  179. sqlite3BtreeLeaveAll(db);
  180. *pHighwater = 0;
  181. *pCurrent = nByte;
  182. break;
  183. }
  184. /*
  185. ** *pCurrent gets an accurate estimate of the amount of memory used
  186. ** to store all prepared statements.
  187. ** *pHighwater is set to zero.
  188. */
  189. case SQLITE_DBSTATUS_STMT_USED: {
  190. struct Vdbe *pVdbe; /* Used to iterate through VMs */
  191. int nByte = 0; /* Used to accumulate return value */
  192. db->pnBytesFreed = &nByte;
  193. for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
  194. sqlite3VdbeClearObject(db, pVdbe);
  195. sqlite3DbFree(db, pVdbe);
  196. }
  197. db->pnBytesFreed = 0;
  198. *pHighwater = 0;
  199. *pCurrent = nByte;
  200. break;
  201. }
  202. /*
  203. ** Set *pCurrent to the total cache hits or misses encountered by all
  204. ** pagers the database handle is connected to. *pHighwater is always set
  205. ** to zero.
  206. */
  207. case SQLITE_DBSTATUS_CACHE_HIT:
  208. case SQLITE_DBSTATUS_CACHE_MISS:
  209. case SQLITE_DBSTATUS_CACHE_WRITE:{
  210. int i;
  211. int nRet = 0;
  212. assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
  213. assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 );
  214. for(i=0; i<db->nDb; i++){
  215. if( db->aDb[i].pBt ){
  216. Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
  217. sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
  218. }
  219. }
  220. *pHighwater = 0;
  221. *pCurrent = nRet;
  222. break;
  223. }
  224. /* Set *pCurrent to non-zero if there are unresolved deferred foreign
  225. ** key constraints. Set *pCurrent to zero if all foreign key constraints
  226. ** have been satisfied. The *pHighwater is always set to zero.
  227. */
  228. case SQLITE_DBSTATUS_DEFERRED_FKS: {
  229. *pHighwater = 0;
  230. *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0;
  231. break;
  232. }
  233. default: {
  234. rc = SQLITE_ERROR;
  235. }
  236. }
  237. sqlite3_mutex_leave(db->mutex);
  238. return rc;
  239. }