OLD | NEW |
1 /* | 1 /* |
2 ** 2008 June 18 | 2 ** 2008 June 18 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
11 ************************************************************************* | 11 ************************************************************************* |
12 ** | 12 ** |
13 ** This module implements the sqlite3_status() interface and related | 13 ** This module implements the sqlite3_status() interface and related |
14 ** functionality. | 14 ** functionality. |
15 */ | 15 */ |
16 #include "sqliteInt.h" | 16 #include "sqliteInt.h" |
17 #include "vdbeInt.h" | 17 #include "vdbeInt.h" |
18 | 18 |
19 /* | 19 /* |
20 ** Variables in which to record status information. | 20 ** Variables in which to record status information. |
21 */ | 21 */ |
| 22 #if SQLITE_PTRSIZE>4 |
| 23 typedef sqlite3_int64 sqlite3StatValueType; |
| 24 #else |
| 25 typedef u32 sqlite3StatValueType; |
| 26 #endif |
22 typedef struct sqlite3StatType sqlite3StatType; | 27 typedef struct sqlite3StatType sqlite3StatType; |
23 static SQLITE_WSD struct sqlite3StatType { | 28 static SQLITE_WSD struct sqlite3StatType { |
24 int nowValue[10]; /* Current value */ | 29 sqlite3StatValueType nowValue[10]; /* Current value */ |
25 int mxValue[10]; /* Maximum value */ | 30 sqlite3StatValueType mxValue[10]; /* Maximum value */ |
26 } sqlite3Stat = { {0,}, {0,} }; | 31 } sqlite3Stat = { {0,}, {0,} }; |
27 | 32 |
| 33 /* |
| 34 ** Elements of sqlite3Stat[] are protected by either the memory allocator |
| 35 ** mutex, or by the pcache1 mutex. The following array determines which. |
| 36 */ |
| 37 static const char statMutex[] = { |
| 38 0, /* SQLITE_STATUS_MEMORY_USED */ |
| 39 1, /* SQLITE_STATUS_PAGECACHE_USED */ |
| 40 1, /* SQLITE_STATUS_PAGECACHE_OVERFLOW */ |
| 41 0, /* SQLITE_STATUS_SCRATCH_USED */ |
| 42 0, /* SQLITE_STATUS_SCRATCH_OVERFLOW */ |
| 43 0, /* SQLITE_STATUS_MALLOC_SIZE */ |
| 44 0, /* SQLITE_STATUS_PARSER_STACK */ |
| 45 1, /* SQLITE_STATUS_PAGECACHE_SIZE */ |
| 46 0, /* SQLITE_STATUS_SCRATCH_SIZE */ |
| 47 0, /* SQLITE_STATUS_MALLOC_COUNT */ |
| 48 }; |
| 49 |
28 | 50 |
29 /* The "wsdStat" macro will resolve to the status information | 51 /* The "wsdStat" macro will resolve to the status information |
30 ** state vector. If writable static data is unsupported on the target, | 52 ** state vector. If writable static data is unsupported on the target, |
31 ** we have to locate the state vector at run-time. In the more common | 53 ** we have to locate the state vector at run-time. In the more common |
32 ** case where writable static data is supported, wsdStat can refer directly | 54 ** case where writable static data is supported, wsdStat can refer directly |
33 ** to the "sqlite3Stat" state vector declared above. | 55 ** to the "sqlite3Stat" state vector declared above. |
34 */ | 56 */ |
35 #ifdef SQLITE_OMIT_WSD | 57 #ifdef SQLITE_OMIT_WSD |
36 # define wsdStatInit sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat) | 58 # define wsdStatInit sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat) |
37 # define wsdStat x[0] | 59 # define wsdStat x[0] |
38 #else | 60 #else |
39 # define wsdStatInit | 61 # define wsdStatInit |
40 # define wsdStat sqlite3Stat | 62 # define wsdStat sqlite3Stat |
41 #endif | 63 #endif |
42 | 64 |
43 /* | 65 /* |
44 ** Return the current value of a status parameter. | 66 ** Return the current value of a status parameter. The caller must |
| 67 ** be holding the appropriate mutex. |
45 */ | 68 */ |
46 int sqlite3StatusValue(int op){ | 69 sqlite3_int64 sqlite3StatusValue(int op){ |
47 wsdStatInit; | 70 wsdStatInit; |
48 assert( op>=0 && op<ArraySize(wsdStat.nowValue) ); | 71 assert( op>=0 && op<ArraySize(wsdStat.nowValue) ); |
| 72 assert( op>=0 && op<ArraySize(statMutex) ); |
| 73 assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex() |
| 74 : sqlite3MallocMutex()) ); |
49 return wsdStat.nowValue[op]; | 75 return wsdStat.nowValue[op]; |
50 } | 76 } |
51 | 77 |
52 /* | 78 /* |
53 ** Add N to the value of a status record. It is assumed that the | 79 ** Add N to the value of a status record. The caller must hold the |
54 ** caller holds appropriate locks. | 80 ** appropriate mutex. (Locking is checked by assert()). |
| 81 ** |
| 82 ** The StatusUp() routine can accept positive or negative values for N. |
| 83 ** The value of N is added to the current status value and the high-water |
| 84 ** mark is adjusted if necessary. |
| 85 ** |
| 86 ** The StatusDown() routine lowers the current value by N. The highwater |
| 87 ** mark is unchanged. N must be non-negative for StatusDown(). |
55 */ | 88 */ |
56 void sqlite3StatusAdd(int op, int N){ | 89 void sqlite3StatusUp(int op, int N){ |
57 wsdStatInit; | 90 wsdStatInit; |
58 assert( op>=0 && op<ArraySize(wsdStat.nowValue) ); | 91 assert( op>=0 && op<ArraySize(wsdStat.nowValue) ); |
| 92 assert( op>=0 && op<ArraySize(statMutex) ); |
| 93 assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex() |
| 94 : sqlite3MallocMutex()) ); |
59 wsdStat.nowValue[op] += N; | 95 wsdStat.nowValue[op] += N; |
60 if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){ | 96 if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){ |
61 wsdStat.mxValue[op] = wsdStat.nowValue[op]; | 97 wsdStat.mxValue[op] = wsdStat.nowValue[op]; |
62 } | 98 } |
63 } | 99 } |
| 100 void sqlite3StatusDown(int op, int N){ |
| 101 wsdStatInit; |
| 102 assert( N>=0 ); |
| 103 assert( op>=0 && op<ArraySize(statMutex) ); |
| 104 assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex() |
| 105 : sqlite3MallocMutex()) ); |
| 106 assert( op>=0 && op<ArraySize(wsdStat.nowValue) ); |
| 107 wsdStat.nowValue[op] -= N; |
| 108 } |
64 | 109 |
65 /* | 110 /* |
66 ** Set the value of a status to X. | 111 ** Adjust the highwater mark if necessary. |
| 112 ** The caller must hold the appropriate mutex. |
67 */ | 113 */ |
68 void sqlite3StatusSet(int op, int X){ | 114 void sqlite3StatusHighwater(int op, int X){ |
| 115 sqlite3StatValueType newValue; |
69 wsdStatInit; | 116 wsdStatInit; |
| 117 assert( X>=0 ); |
| 118 newValue = (sqlite3StatValueType)X; |
70 assert( op>=0 && op<ArraySize(wsdStat.nowValue) ); | 119 assert( op>=0 && op<ArraySize(wsdStat.nowValue) ); |
71 wsdStat.nowValue[op] = X; | 120 assert( op>=0 && op<ArraySize(statMutex) ); |
72 if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){ | 121 assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex() |
73 wsdStat.mxValue[op] = wsdStat.nowValue[op]; | 122 : sqlite3MallocMutex()) ); |
| 123 assert( op==SQLITE_STATUS_MALLOC_SIZE |
| 124 || op==SQLITE_STATUS_PAGECACHE_SIZE |
| 125 || op==SQLITE_STATUS_SCRATCH_SIZE |
| 126 || op==SQLITE_STATUS_PARSER_STACK ); |
| 127 if( newValue>wsdStat.mxValue[op] ){ |
| 128 wsdStat.mxValue[op] = newValue; |
74 } | 129 } |
75 } | 130 } |
76 | 131 |
77 /* | 132 /* |
78 ** Query status information. | 133 ** Query status information. |
79 ** | |
80 ** This implementation assumes that reading or writing an aligned | |
81 ** 32-bit integer is an atomic operation. If that assumption is not true, | |
82 ** then this routine is not threadsafe. | |
83 */ | 134 */ |
84 int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ | 135 int sqlite3_status64( |
| 136 int op, |
| 137 sqlite3_int64 *pCurrent, |
| 138 sqlite3_int64 *pHighwater, |
| 139 int resetFlag |
| 140 ){ |
| 141 sqlite3_mutex *pMutex; |
85 wsdStatInit; | 142 wsdStatInit; |
86 if( op<0 || op>=ArraySize(wsdStat.nowValue) ){ | 143 if( op<0 || op>=ArraySize(wsdStat.nowValue) ){ |
87 return SQLITE_MISUSE_BKPT; | 144 return SQLITE_MISUSE_BKPT; |
88 } | 145 } |
| 146 #ifdef SQLITE_ENABLE_API_ARMOR |
| 147 if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; |
| 148 #endif |
| 149 pMutex = statMutex[op] ? sqlite3Pcache1Mutex() : sqlite3MallocMutex(); |
| 150 sqlite3_mutex_enter(pMutex); |
89 *pCurrent = wsdStat.nowValue[op]; | 151 *pCurrent = wsdStat.nowValue[op]; |
90 *pHighwater = wsdStat.mxValue[op]; | 152 *pHighwater = wsdStat.mxValue[op]; |
91 if( resetFlag ){ | 153 if( resetFlag ){ |
92 wsdStat.mxValue[op] = wsdStat.nowValue[op]; | 154 wsdStat.mxValue[op] = wsdStat.nowValue[op]; |
93 } | 155 } |
| 156 sqlite3_mutex_leave(pMutex); |
| 157 (void)pMutex; /* Prevent warning when SQLITE_THREADSAFE=0 */ |
94 return SQLITE_OK; | 158 return SQLITE_OK; |
95 } | 159 } |
| 160 int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){ |
| 161 sqlite3_int64 iCur, iHwtr; |
| 162 int rc; |
| 163 #ifdef SQLITE_ENABLE_API_ARMOR |
| 164 if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT; |
| 165 #endif |
| 166 rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag); |
| 167 if( rc==0 ){ |
| 168 *pCurrent = (int)iCur; |
| 169 *pHighwater = (int)iHwtr; |
| 170 } |
| 171 return rc; |
| 172 } |
96 | 173 |
97 /* | 174 /* |
98 ** Query status information for a single database connection | 175 ** Query status information for a single database connection |
99 */ | 176 */ |
100 int sqlite3_db_status( | 177 int sqlite3_db_status( |
101 sqlite3 *db, /* The database connection whose status is desired */ | 178 sqlite3 *db, /* The database connection whose status is desired */ |
102 int op, /* Status verb */ | 179 int op, /* Status verb */ |
103 int *pCurrent, /* Write current value here */ | 180 int *pCurrent, /* Write current value here */ |
104 int *pHighwater, /* Write high-water mark here */ | 181 int *pHighwater, /* Write high-water mark here */ |
105 int resetFlag /* Reset high-water mark if true */ | 182 int resetFlag /* Reset high-water mark if true */ |
106 ){ | 183 ){ |
107 int rc = SQLITE_OK; /* Return code */ | 184 int rc = SQLITE_OK; /* Return code */ |
| 185 #ifdef SQLITE_ENABLE_API_ARMOR |
| 186 if( !sqlite3SafetyCheckOk(db) || pCurrent==0|| pHighwater==0 ){ |
| 187 return SQLITE_MISUSE_BKPT; |
| 188 } |
| 189 #endif |
108 sqlite3_mutex_enter(db->mutex); | 190 sqlite3_mutex_enter(db->mutex); |
109 switch( op ){ | 191 switch( op ){ |
110 case SQLITE_DBSTATUS_LOOKASIDE_USED: { | 192 case SQLITE_DBSTATUS_LOOKASIDE_USED: { |
111 *pCurrent = db->lookaside.nOut; | 193 *pCurrent = db->lookaside.nOut; |
112 *pHighwater = db->lookaside.mxOut; | 194 *pHighwater = db->lookaside.mxOut; |
113 if( resetFlag ){ | 195 if( resetFlag ){ |
114 db->lookaside.mxOut = db->lookaside.nOut; | 196 db->lookaside.mxOut = db->lookaside.nOut; |
115 } | 197 } |
116 break; | 198 break; |
117 } | 199 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 Schema *pSchema = db->aDb[i].pSchema; | 251 Schema *pSchema = db->aDb[i].pSchema; |
170 if( ALWAYS(pSchema!=0) ){ | 252 if( ALWAYS(pSchema!=0) ){ |
171 HashElem *p; | 253 HashElem *p; |
172 | 254 |
173 nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * ( | 255 nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * ( |
174 pSchema->tblHash.count | 256 pSchema->tblHash.count |
175 + pSchema->trigHash.count | 257 + pSchema->trigHash.count |
176 + pSchema->idxHash.count | 258 + pSchema->idxHash.count |
177 + pSchema->fkeyHash.count | 259 + pSchema->fkeyHash.count |
178 ); | 260 ); |
179 nByte += sqlite3MallocSize(pSchema->tblHash.ht); | 261 nByte += sqlite3_msize(pSchema->tblHash.ht); |
180 nByte += sqlite3MallocSize(pSchema->trigHash.ht); | 262 nByte += sqlite3_msize(pSchema->trigHash.ht); |
181 nByte += sqlite3MallocSize(pSchema->idxHash.ht); | 263 nByte += sqlite3_msize(pSchema->idxHash.ht); |
182 nByte += sqlite3MallocSize(pSchema->fkeyHash.ht); | 264 nByte += sqlite3_msize(pSchema->fkeyHash.ht); |
183 | 265 |
184 for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){ | 266 for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){ |
185 sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p)); | 267 sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p)); |
186 } | 268 } |
187 for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){ | 269 for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){ |
188 sqlite3DeleteTable(db, (Table *)sqliteHashData(p)); | 270 sqlite3DeleteTable(db, (Table *)sqliteHashData(p)); |
189 } | 271 } |
190 } | 272 } |
191 } | 273 } |
192 db->pnBytesFreed = 0; | 274 db->pnBytesFreed = 0; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 break; | 337 break; |
256 } | 338 } |
257 | 339 |
258 default: { | 340 default: { |
259 rc = SQLITE_ERROR; | 341 rc = SQLITE_ERROR; |
260 } | 342 } |
261 } | 343 } |
262 sqlite3_mutex_leave(db->mutex); | 344 sqlite3_mutex_leave(db->mutex); |
263 return rc; | 345 return rc; |
264 } | 346 } |
OLD | NEW |