xref: /sqlite-3.40.0/src/status.c (revision af89fe66)
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