File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / src / status.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:04:17 2012 UTC (12 years, 7 months ago) by misho
Branches: sqlite3, MAIN
CVS tags: v3_7_10, HEAD
sqlite3

    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>