Annotation of embedaddon/sqlite3/src/status.c, revision 1.1.1.1

1.1       misho       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:   int nowValue[10];         /* Current value */
                     25:   int mxValue[10];          /* Maximum value */
                     26: } sqlite3Stat = { {0,}, {0,} };
                     27: 
                     28: 
                     29: /* The "wsdStat" macro will resolve to the status information
                     30: ** 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
                     32: ** case where writable static data is supported, wsdStat can refer directly
                     33: ** to the "sqlite3Stat" state vector declared above.
                     34: */
                     35: #ifdef SQLITE_OMIT_WSD
                     36: # define wsdStatInit  sqlite3StatType *x = &GLOBAL(sqlite3StatType,sqlite3Stat)
                     37: # define wsdStat x[0]
                     38: #else
                     39: # define wsdStatInit
                     40: # define wsdStat sqlite3Stat
                     41: #endif
                     42: 
                     43: /*
                     44: ** Return the current value of a status parameter.
                     45: */
                     46: int sqlite3StatusValue(int op){
                     47:   wsdStatInit;
                     48:   assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
                     49:   return wsdStat.nowValue[op];
                     50: }
                     51: 
                     52: /*
                     53: ** Add N to the value of a status record.  It is assumed that the
                     54: ** caller holds appropriate locks.
                     55: */
                     56: void sqlite3StatusAdd(int op, int N){
                     57:   wsdStatInit;
                     58:   assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
                     59:   wsdStat.nowValue[op] += N;
                     60:   if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
                     61:     wsdStat.mxValue[op] = wsdStat.nowValue[op];
                     62:   }
                     63: }
                     64: 
                     65: /*
                     66: ** Set the value of a status to X.
                     67: */
                     68: void sqlite3StatusSet(int op, int X){
                     69:   wsdStatInit;
                     70:   assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
                     71:   wsdStat.nowValue[op] = X;
                     72:   if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
                     73:     wsdStat.mxValue[op] = wsdStat.nowValue[op];
                     74:   }
                     75: }
                     76: 
                     77: /*
                     78: ** 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: */
                     84: int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
                     85:   wsdStatInit;
                     86:   if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
                     87:     return SQLITE_MISUSE_BKPT;
                     88:   }
                     89:   *pCurrent = wsdStat.nowValue[op];
                     90:   *pHighwater = wsdStat.mxValue[op];
                     91:   if( resetFlag ){
                     92:     wsdStat.mxValue[op] = wsdStat.nowValue[op];
                     93:   }
                     94:   return SQLITE_OK;
                     95: }
                     96: 
                     97: /*
                     98: ** Query status information for a single database connection
                     99: */
                    100: int sqlite3_db_status(
                    101:   sqlite3 *db,          /* The database connection whose status is desired */
                    102:   int op,               /* Status verb */
                    103:   int *pCurrent,        /* Write current value here */
                    104:   int *pHighwater,      /* Write high-water mark here */
                    105:   int resetFlag         /* Reset high-water mark if true */
                    106: ){
                    107:   int rc = SQLITE_OK;   /* Return code */
                    108:   sqlite3_mutex_enter(db->mutex);
                    109:   switch( op ){
                    110:     case SQLITE_DBSTATUS_LOOKASIDE_USED: {
                    111:       *pCurrent = db->lookaside.nOut;
                    112:       *pHighwater = db->lookaside.mxOut;
                    113:       if( resetFlag ){
                    114:         db->lookaside.mxOut = db->lookaside.nOut;
                    115:       }
                    116:       break;
                    117:     }
                    118: 
                    119:     case SQLITE_DBSTATUS_LOOKASIDE_HIT:
                    120:     case SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE:
                    121:     case SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL: {
                    122:       testcase( op==SQLITE_DBSTATUS_LOOKASIDE_HIT );
                    123:       testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE );
                    124:       testcase( op==SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL );
                    125:       assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 );
                    126:       assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 );
                    127:       *pCurrent = 0;
                    128:       *pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT];
                    129:       if( resetFlag ){
                    130:         db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0;
                    131:       }
                    132:       break;
                    133:     }
                    134: 
                    135:     /* 
                    136:     ** Return an approximation for the amount of memory currently used
                    137:     ** by all pagers associated with the given database connection.  The
                    138:     ** highwater mark is meaningless and is returned as zero.
                    139:     */
                    140:     case SQLITE_DBSTATUS_CACHE_USED: {
                    141:       int totalUsed = 0;
                    142:       int i;
                    143:       sqlite3BtreeEnterAll(db);
                    144:       for(i=0; i<db->nDb; i++){
                    145:         Btree *pBt = db->aDb[i].pBt;
                    146:         if( pBt ){
                    147:           Pager *pPager = sqlite3BtreePager(pBt);
                    148:           totalUsed += sqlite3PagerMemUsed(pPager);
                    149:         }
                    150:       }
                    151:       sqlite3BtreeLeaveAll(db);
                    152:       *pCurrent = totalUsed;
                    153:       *pHighwater = 0;
                    154:       break;
                    155:     }
                    156: 
                    157:     /*
                    158:     ** *pCurrent gets an accurate estimate of the amount of memory used
                    159:     ** to store the schema for all databases (main, temp, and any ATTACHed
                    160:     ** databases.  *pHighwater is set to zero.
                    161:     */
                    162:     case SQLITE_DBSTATUS_SCHEMA_USED: {
                    163:       int i;                      /* Used to iterate through schemas */
                    164:       int nByte = 0;              /* Used to accumulate return value */
                    165: 
                    166:       sqlite3BtreeEnterAll(db);
                    167:       db->pnBytesFreed = &nByte;
                    168:       for(i=0; i<db->nDb; i++){
                    169:         Schema *pSchema = db->aDb[i].pSchema;
                    170:         if( ALWAYS(pSchema!=0) ){
                    171:           HashElem *p;
                    172: 
                    173:           nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
                    174:               pSchema->tblHash.count 
                    175:             + pSchema->trigHash.count
                    176:             + pSchema->idxHash.count
                    177:             + pSchema->fkeyHash.count
                    178:           );
                    179:           nByte += sqlite3MallocSize(pSchema->tblHash.ht);
                    180:           nByte += sqlite3MallocSize(pSchema->trigHash.ht);
                    181:           nByte += sqlite3MallocSize(pSchema->idxHash.ht);
                    182:           nByte += sqlite3MallocSize(pSchema->fkeyHash.ht);
                    183: 
                    184:           for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
                    185:             sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
                    186:           }
                    187:           for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
                    188:             sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
                    189:           }
                    190:         }
                    191:       }
                    192:       db->pnBytesFreed = 0;
                    193:       sqlite3BtreeLeaveAll(db);
                    194: 
                    195:       *pHighwater = 0;
                    196:       *pCurrent = nByte;
                    197:       break;
                    198:     }
                    199: 
                    200:     /*
                    201:     ** *pCurrent gets an accurate estimate of the amount of memory used
                    202:     ** to store all prepared statements.
                    203:     ** *pHighwater is set to zero.
                    204:     */
                    205:     case SQLITE_DBSTATUS_STMT_USED: {
                    206:       struct Vdbe *pVdbe;         /* Used to iterate through VMs */
                    207:       int nByte = 0;              /* Used to accumulate return value */
                    208: 
                    209:       db->pnBytesFreed = &nByte;
                    210:       for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
                    211:         sqlite3VdbeDeleteObject(db, pVdbe);
                    212:       }
                    213:       db->pnBytesFreed = 0;
                    214: 
                    215:       *pHighwater = 0;
                    216:       *pCurrent = nByte;
                    217: 
                    218:       break;
                    219:     }
                    220: 
                    221:     /*
                    222:     ** Set *pCurrent to the total cache hits or misses encountered by all
                    223:     ** pagers the database handle is connected to. *pHighwater is always set 
                    224:     ** to zero.
                    225:     */
                    226:     case SQLITE_DBSTATUS_CACHE_HIT:
                    227:     case SQLITE_DBSTATUS_CACHE_MISS: {
                    228:       int i;
                    229:       int nRet = 0;
                    230:       assert( SQLITE_DBSTATUS_CACHE_MISS==SQLITE_DBSTATUS_CACHE_HIT+1 );
                    231: 
                    232:       for(i=0; i<db->nDb; i++){
                    233:         if( db->aDb[i].pBt ){
                    234:           Pager *pPager = sqlite3BtreePager(db->aDb[i].pBt);
                    235:           sqlite3PagerCacheStat(pPager, op, resetFlag, &nRet);
                    236:         }
                    237:       }
                    238:       *pHighwater = 0;
                    239:       *pCurrent = nRet;
                    240:       break;
                    241:     }
                    242: 
                    243:     default: {
                    244:       rc = SQLITE_ERROR;
                    245:     }
                    246:   }
                    247:   sqlite3_mutex_leave(db->mutex);
                    248:   return rc;
                    249: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>