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 /* 20 ** Variables in which to record status information. 21 */ 22 typedef struct sqlite3StatType sqlite3StatType; 23 static SQLITE_WSD struct sqlite3StatType { 24 sqlite3_int64 nowValue[10]; /* Current value */ 25 sqlite3_int64 mxValue[10]; /* Maximum value */ 26 } sqlite3Stat = { {0,}, {0,} }; 27 28 /* 29 ** Elements of sqlite3Stat[] are protected by either the memory allocator 30 ** mutex, or by the pcache1 mutex. The following array determines which. 31 */ 32 static const char statMutex[] = { 33 0, /* SQLITE_STATUS_MEMORY_USED */ 34 1, /* SQLITE_STATUS_PAGECACHE_USED */ 35 1, /* SQLITE_STATUS_PAGECACHE_OVERFLOW */ 36 0, /* SQLITE_STATUS_SCRATCH_USED */ 37 0, /* SQLITE_STATUS_SCRATCH_OVERFLOW */ 38 0, /* SQLITE_STATUS_MALLOC_SIZE */ 39 0, /* SQLITE_STATUS_PARSER_STACK */ 40 1, /* SQLITE_STATUS_PAGECACHE_SIZE */ 41 0, /* SQLITE_STATUS_SCRATCH_SIZE */ 42 0, /* SQLITE_STATUS_MALLOC_COUNT */ 43 }; 44 45 46 /* The "wsdStat" macro will resolve to the status information 47 ** state vector. If writable static data is unsupported on the target, 48 ** we have to locate the state vector at run-time. In the more common 49 ** case where writable static data is supported, wsdStat can refer directly 50 ** to the "sqlite3Stat" state vector declared above. 51 */ 52 #ifdef SQLITE_OMIT_WSD 53 # define wsdStatInit sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat) 54 # define wsdStat x[0] 55 #else 56 # define wsdStatInit 57 # define wsdStat sqlite3Stat 58 #endif 59 60 /* 61 ** Return the current value of a status parameter. The caller must 62 ** be holding the appropriate mutex. 63 */ 64 sqlite3_int64 sqlite3StatusValue(int op){ 65 wsdStatInit; 66 assert( op>=0 && op<ArraySize(wsdStat.nowValue) ); 67 assert( op>=0 && op<ArraySize(statMutex) ); 68 assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex() 69 : sqlite3MallocMutex()) ); 70 return wsdStat.nowValue[op]; 71 } 72 73 /* 74 ** Add N to the value of a status record. The caller must hold the 75 ** appropriate mutex. (Locking is checked by assert()). 76 ** 77 ** The StatusUp() routine can accept positive or negative values for N. 78 ** The value of N is added to the current status value and the high-water 79 ** mark is adjusted if necessary. 80 ** 81 ** The StatusDown() routine lowers the current value by N. The highwater 82 ** mark is unchanged. N must be non-negative for StatusDown(). 83 */ 84 void sqlite3StatusUp(int op, int N){ 85 wsdStatInit; 86 assert( op>=0 && op<ArraySize(wsdStat.nowValue) ); 87 assert( op>=0 && op<ArraySize(statMutex) ); 88 assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex() 89 : sqlite3MallocMutex()) ); 90 wsdStat.nowValue[op] += N; 91 if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){ 92 wsdStat.mxValue[op] = wsdStat.nowValue[op]; 93 } 94 } 95 void sqlite3StatusDown(int op, int N){ 96 wsdStatInit; 97 assert( N>=0 ); 98 assert( op>=0 && op<ArraySize(statMutex) ); 99 assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex() 100 : sqlite3MallocMutex()) ); 101 assert( op>=0 && op<ArraySize(wsdStat.nowValue) ); 102 wsdStat.nowValue[op] -= N; 103 } 104 105 /* 106 ** Set the value of a status to X. The highwater mark is adjusted if 107 ** necessary. The caller must hold the appropriate mutex. 108 */ 109 void sqlite3StatusSet(int op, int X){ 110 wsdStatInit; 111 assert( op>=0 && op<ArraySize(wsdStat.nowValue) ); 112 assert( op>=0 && op<ArraySize(statMutex) ); 113 assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex() 114 : sqlite3MallocMutex()) ); 115 wsdStat.nowValue[op] = X; 116 if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){ 117 wsdStat.mxValue[op] = wsdStat.nowValue[op]; 118 } 119 } 120 121 /* 122 ** Query status information. 123 */ 124 int sqlite3_status64( 125 int op, 126 sqlite3_int64 *pCurrent, 127 sqlite3_int64 *pHighwater, 128 int resetFlag 129 ){ 130 wsdStatInit; 131 sqlite3_mutex *pMutex; 132 if( op<0 || op>=ArraySize(wsdStat.nowValue) ){ 133 return SQLITE_MISUSE_BKPT; 134 } 135 #ifdef SQLITE_ENABLE_API_ARMOR 136 if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; 137 #endif 138 pMutex = statMutex[op] ? sqlite3Pcache1Mutex() : sqlite3MallocMutex(); 139 sqlite3_mutex_enter(pMutex); 140 *pCurrent = wsdStat.nowValue[op]; 141 *pHighwater = wsdStat.mxValue[op]; 142 if( resetFlag ){ 143 wsdStat.mxValue[op] = wsdStat.nowValue[op]; 144 } 145 sqlite3_mutex_leave(pMutex); 146 return SQLITE_OK; 147 } 148 int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ 149 sqlite3_int64 iCur, iHwtr; 150 int rc; 151 #ifdef SQLITE_ENABLE_API_ARMOR 152 if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; 153 #endif 154 rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag); 155 *pCurrent = (int)iCur; 156 *pHighwater = (int)iHwtr; 157 return rc; 158 } 159 160 /* 161 ** Query status information for a single database connection 162 */ 163 int sqlite3_db_status( 164 sqlite3 *db, /* The database connection whose status is desired */ 165 int op, /* Status verb */ 166 int *pCurrent, /* Write current value here */ 167 int *pHighwater, /* Write high-water mark here */ 168 int resetFlag /* Reset high-water mark if true */ 169 ){ 170 int rc = SQLITE_OK; /* Return code */ 171 #ifdef SQLITE_ENABLE_API_ARMOR 172 if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwater==0 ){ 173 return SQLITE_MISUSE_BKPT; 174 } 175 #endif 176 sqlite3_mutex_enter(db->mutex); 177 switch( op ){ 178 case SQLITE_DBSTATUS_LOOKASIDE_USED: { 179 *pCurrent = db->lookaside.nOut; 180 *pHighwater = db->lookaside.mxOut; 181 if( resetFlag ){ 182 db->lookaside.mxOut = db->lookaside.nOut; 183 } 184 break; 185 } 186 187 case SQLITE_DBSTATUS_LOOKASIDE_HIT: 188 case SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE: 189 case SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: { 190 testcase( op==SQLITE_DBSTATUS_LOOKASIDE_HIT ); 191 testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE ); 192 testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL ); 193 assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 ); 194 assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 ); 195 *pCurrent = 0; 196 *pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT]; 197 if( resetFlag ){ 198 db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0; 199 } 200 break; 201 } 202 203 /* 204 ** Return an approximation for the amount of memory currently used 205 ** by all pagers associated with the given database connection. The 206 ** highwater mark is meaningless and is returned as zero. 207 */ 208 case SQLITE_DBSTATUS_CACHE_USED: { 209 int totalUsed = 0; 210 int i; 211 sqlite3BtreeEnterAll(db); 212 for(i=0; i<db->nDb; i++){ 213 Btree *pBt = db->aDb[i].pBt; 214 if( pBt ){ 215 Pager *pPager = sqlite3BtreePager(pBt); 216 totalUsed += sqlite3PagerMemUsed(pPager); 217 } 218 } 219 sqlite3BtreeLeaveAll(db); 220 *pCurrent = totalUsed; 221 *pHighwater = 0; 222 break; 223 } 224 225 /* 226 ** *pCurrent gets an accurate estimate of the amount of memory used 227 ** to store the schema for all databases (main, temp, and any ATTACHed 228 ** databases. *pHighwater is set to zero. 229 */ 230 case SQLITE_DBSTATUS_SCHEMA_USED: { 231 int i; /* Used to iterate through schemas */ 232 int nByte = 0; /* Used to accumulate return value */ 233 234 sqlite3BtreeEnterAll(db); 235 db->pnBytesFreed = &nByte; 236 for(i=0; i<db->nDb; i++){ 237 Schema *pSchema = db->aDb[i].pSchema; 238 if( ALWAYS(pSchema!=0) ){ 239 HashElem *p; 240 241 nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * ( 242 pSchema->tblHash.count 243 + pSchema->trigHash.count 244 + pSchema->idxHash.count 245 + pSchema->fkeyHash.count 246 ); 247 nByte += sqlite3MallocSize(pSchema->tblHash.ht); 248 nByte += sqlite3MallocSize(pSchema->trigHash.ht); 249 nByte += sqlite3MallocSize(pSchema->idxHash.ht); 250 nByte += sqlite3MallocSize(pSchema->fkeyHash.ht); 251 252 for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){ 253 sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p)); 254 } 255 for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){ 256 sqlite3DeleteTable(db, (Table *)sqliteHashData(p)); 257 } 258 } 259 } 260 db->pnBytesFreed = 0; 261 sqlite3BtreeLeaveAll(db); 262 263 *pHighwater = 0; 264 *pCurrent = nByte; 265 break; 266 } 267 268 /* 269 ** *pCurrent gets an accurate estimate of the amount of memory used 270 ** to store all prepared statements. 271 ** *pHighwater is set to zero. 272 */ 273 case SQLITE_DBSTATUS_STMT_USED: { 274 struct Vdbe *pVdbe; /* Used to iterate through VMs */ 275 int nByte = 0; /* Used to accumulate return value */ 276 277 db->pnBytesFreed = &nByte; 278 for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){ 279 sqlite3VdbeClearObject(db, pVdbe); 280 sqlite3DbFree(db, pVdbe); 281 } 282 db->pnBytesFreed = 0; 283 284 *pHighwater = 0; /* IMP: R-64479-57858 */ 285 *pCurrent = nByte; 286 287 break; 288 } 289 290 /* 291 ** Set *pCurrent to the total cache hits or misses encountered by all 292 ** pagers the database handle is connected to. *pHighwater is always set 293 ** to zero. 294 */ 295 case SQLITE_DBSTATUS_CACHE_HIT: 296 case SQLITE_DBSTATUS_CACHE_MISS: 297 case SQLITE_DBSTATUS_CACHE_WRITE:{ 298 int i; 299 int nRet = 0; 300 assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 ); 301 assert( SQLITE_DBSTATUS_CACHE_WRITE==SQLITE_DBSTATUS_CACHE_HIT+2 ); 302 303 for(i=0; i<db->nDb; i++){ 304 if( db->aDb[i].pBt ){ 305 Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt); 306 sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet); 307 } 308 } 309 *pHighwater = 0; /* IMP: R-42420-56072 */ 310 /* IMP: R-54100-20147 */ 311 /* IMP: R-29431-39229 */ 312 *pCurrent = nRet; 313 break; 314 } 315 316 /* Set *pCurrent to non-zero if there are unresolved deferred foreign 317 ** key constraints. Set *pCurrent to zero if all foreign key constraints 318 ** have been satisfied. The *pHighwater is always set to zero. 319 */ 320 case SQLITE_DBSTATUS_DEFERRED_FKS: { 321 *pHighwater = 0; /* IMP: R-11967-56545 */ 322 *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0; 323 break; 324 } 325 326 default: { 327 rc = SQLITE_ERROR; 328 } 329 } 330 sqlite3_mutex_leave(db->mutex); 331 return rc; 332 } 333