Annotation of embedaddon/sqlite3/src/test_mutex.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: ** This file contains test logic for the sqlite3_mutex interfaces.
                     13: */
                     14: 
                     15: #include "tcl.h"
                     16: #include "sqlite3.h"
                     17: #include "sqliteInt.h"
                     18: #include <stdlib.h>
                     19: #include <assert.h>
                     20: #include <string.h>
                     21: 
                     22: /* defined in test1.c */
                     23: const char *sqlite3TestErrorName(int);
                     24: 
                     25: /* A countable mutex */
                     26: struct sqlite3_mutex {
                     27:   sqlite3_mutex *pReal;
                     28:   int eType;
                     29: };
                     30: 
                     31: /* State variables */
                     32: static struct test_mutex_globals {
                     33:   int isInstalled;              /* True if installed */
                     34:   int disableInit;              /* True to cause sqlite3_initalize() to fail */
                     35:   int disableTry;               /* True to force sqlite3_mutex_try() to fail */
                     36:   int isInit;                   /* True if initialized */
                     37:   sqlite3_mutex_methods m;      /* Interface to "real" mutex system */
                     38:   int aCounter[8];              /* Number of grabs of each type of mutex */
                     39:   sqlite3_mutex aStatic[6];     /* The six static mutexes */
                     40: } g = {0};
                     41: 
                     42: /* Return true if the countable mutex is currently held */
                     43: static int counterMutexHeld(sqlite3_mutex *p){
                     44:   return g.m.xMutexHeld(p->pReal);
                     45: }
                     46: 
                     47: /* Return true if the countable mutex is not currently held */
                     48: static int counterMutexNotheld(sqlite3_mutex *p){
                     49:   return g.m.xMutexNotheld(p->pReal);
                     50: }
                     51: 
                     52: /* Initialize the countable mutex interface
                     53: ** Or, if g.disableInit is non-zero, then do not initialize but instead
                     54: ** return the value of g.disableInit as the result code.  This can be used
                     55: ** to simulate an initialization failure.
                     56: */
                     57: static int counterMutexInit(void){ 
                     58:   int rc;
                     59:   if( g.disableInit ) return g.disableInit;
                     60:   rc = g.m.xMutexInit();
                     61:   g.isInit = 1;
                     62:   return rc;
                     63: }
                     64: 
                     65: /*
                     66: ** Uninitialize the mutex subsystem
                     67: */
                     68: static int counterMutexEnd(void){ 
                     69:   g.isInit = 0;
                     70:   return g.m.xMutexEnd();
                     71: }
                     72: 
                     73: /*
                     74: ** Allocate a countable mutex
                     75: */
                     76: static sqlite3_mutex *counterMutexAlloc(int eType){
                     77:   sqlite3_mutex *pReal;
                     78:   sqlite3_mutex *pRet = 0;
                     79: 
                     80:   assert( g.isInit );
                     81:   assert(eType<8 && eType>=0);
                     82: 
                     83:   pReal = g.m.xMutexAlloc(eType);
                     84:   if( !pReal ) return 0;
                     85: 
                     86:   if( eType==SQLITE_MUTEX_FAST || eType==SQLITE_MUTEX_RECURSIVE ){
                     87:     pRet = (sqlite3_mutex *)malloc(sizeof(sqlite3_mutex));
                     88:   }else{
                     89:     pRet = &g.aStatic[eType-2];
                     90:   }
                     91: 
                     92:   pRet->eType = eType;
                     93:   pRet->pReal = pReal;
                     94:   return pRet;
                     95: }
                     96: 
                     97: /*
                     98: ** Free a countable mutex
                     99: */
                    100: static void counterMutexFree(sqlite3_mutex *p){
                    101:   assert( g.isInit );
                    102:   g.m.xMutexFree(p->pReal);
                    103:   if( p->eType==SQLITE_MUTEX_FAST || p->eType==SQLITE_MUTEX_RECURSIVE ){
                    104:     free(p);
                    105:   }
                    106: }
                    107: 
                    108: /*
                    109: ** Enter a countable mutex.  Block until entry is safe.
                    110: */
                    111: static void counterMutexEnter(sqlite3_mutex *p){
                    112:   assert( g.isInit );
                    113:   g.aCounter[p->eType]++;
                    114:   g.m.xMutexEnter(p->pReal);
                    115: }
                    116: 
                    117: /*
                    118: ** Try to enter a mutex.  Return true on success.
                    119: */
                    120: static int counterMutexTry(sqlite3_mutex *p){
                    121:   assert( g.isInit );
                    122:   g.aCounter[p->eType]++;
                    123:   if( g.disableTry ) return SQLITE_BUSY;
                    124:   return g.m.xMutexTry(p->pReal);
                    125: }
                    126: 
                    127: /* Leave a mutex
                    128: */
                    129: static void counterMutexLeave(sqlite3_mutex *p){
                    130:   assert( g.isInit );
                    131:   g.m.xMutexLeave(p->pReal);
                    132: }
                    133: 
                    134: /*
                    135: ** sqlite3_shutdown
                    136: */
                    137: static int test_shutdown(
                    138:   void * clientData,
                    139:   Tcl_Interp *interp,
                    140:   int objc,
                    141:   Tcl_Obj *CONST objv[]
                    142: ){
                    143:   int rc;
                    144: 
                    145:   if( objc!=1 ){
                    146:     Tcl_WrongNumArgs(interp, 1, objv, "");
                    147:     return TCL_ERROR;
                    148:   }
                    149: 
                    150:   rc = sqlite3_shutdown();
                    151:   Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
                    152:   return TCL_OK;
                    153: }
                    154: 
                    155: /*
                    156: ** sqlite3_initialize
                    157: */
                    158: static int test_initialize(
                    159:   void * clientData,
                    160:   Tcl_Interp *interp,
                    161:   int objc,
                    162:   Tcl_Obj *CONST objv[]
                    163: ){
                    164:   int rc;
                    165: 
                    166:   if( objc!=1 ){
                    167:     Tcl_WrongNumArgs(interp, 1, objv, "");
                    168:     return TCL_ERROR;
                    169:   }
                    170: 
                    171:   rc = sqlite3_initialize();
                    172:   Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
                    173:   return TCL_OK;
                    174: }
                    175: 
                    176: /*
                    177: ** install_mutex_counters BOOLEAN
                    178: */
                    179: static int test_install_mutex_counters(
                    180:   void * clientData,
                    181:   Tcl_Interp *interp,
                    182:   int objc,
                    183:   Tcl_Obj *CONST objv[]
                    184: ){
                    185:   int rc = SQLITE_OK;
                    186:   int isInstall;
                    187: 
                    188:   sqlite3_mutex_methods counter_methods = {
                    189:     counterMutexInit,
                    190:     counterMutexEnd,
                    191:     counterMutexAlloc,
                    192:     counterMutexFree,
                    193:     counterMutexEnter,
                    194:     counterMutexTry,
                    195:     counterMutexLeave,
                    196:     counterMutexHeld,
                    197:     counterMutexNotheld
                    198:   };
                    199: 
                    200:   if( objc!=2 ){
                    201:     Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
                    202:     return TCL_ERROR;
                    203:   }
                    204:   if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){
                    205:     return TCL_ERROR;
                    206:   }
                    207: 
                    208:   assert(isInstall==0 || isInstall==1);
                    209:   assert(g.isInstalled==0 || g.isInstalled==1);
                    210:   if( isInstall==g.isInstalled ){
                    211:     Tcl_AppendResult(interp, "mutex counters are ", 0);
                    212:     Tcl_AppendResult(interp, isInstall?"already installed":"not installed", 0);
                    213:     return TCL_ERROR;
                    214:   }
                    215: 
                    216:   if( isInstall ){
                    217:     assert( g.m.xMutexAlloc==0 );
                    218:     rc = sqlite3_config(SQLITE_CONFIG_GETMUTEX, &g.m);
                    219:     if( rc==SQLITE_OK ){
                    220:       sqlite3_config(SQLITE_CONFIG_MUTEX, &counter_methods);
                    221:     }
                    222:     g.disableTry = 0;
                    223:   }else{
                    224:     assert( g.m.xMutexAlloc );
                    225:     rc = sqlite3_config(SQLITE_CONFIG_MUTEX, &g.m);
                    226:     memset(&g.m, 0, sizeof(sqlite3_mutex_methods));
                    227:   }
                    228: 
                    229:   if( rc==SQLITE_OK ){
                    230:     g.isInstalled = isInstall;
                    231:   }
                    232: 
                    233:   Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
                    234:   return TCL_OK;
                    235: }
                    236: 
                    237: /*
                    238: ** read_mutex_counters
                    239: */
                    240: static int test_read_mutex_counters(
                    241:   void * clientData,
                    242:   Tcl_Interp *interp,
                    243:   int objc,
                    244:   Tcl_Obj *CONST objv[]
                    245: ){
                    246:   Tcl_Obj *pRet;
                    247:   int ii;
                    248:   char *aName[8] = {
                    249:     "fast",        "recursive",   "static_master", "static_mem", 
                    250:     "static_open", "static_prng", "static_lru",    "static_pmem"
                    251:   };
                    252: 
                    253:   if( objc!=1 ){
                    254:     Tcl_WrongNumArgs(interp, 1, objv, "");
                    255:     return TCL_ERROR;
                    256:   }
                    257: 
                    258:   pRet = Tcl_NewObj();
                    259:   Tcl_IncrRefCount(pRet);
                    260:   for(ii=0; ii<8; ii++){
                    261:     Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(aName[ii], -1));
                    262:     Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(g.aCounter[ii]));
                    263:   }
                    264:   Tcl_SetObjResult(interp, pRet);
                    265:   Tcl_DecrRefCount(pRet);
                    266: 
                    267:   return TCL_OK;
                    268: }
                    269: 
                    270: /*
                    271: ** clear_mutex_counters
                    272: */
                    273: static int test_clear_mutex_counters(
                    274:   void * clientData,
                    275:   Tcl_Interp *interp,
                    276:   int objc,
                    277:   Tcl_Obj *CONST objv[]
                    278: ){
                    279:   int ii;
                    280: 
                    281:   if( objc!=1 ){
                    282:     Tcl_WrongNumArgs(interp, 1, objv, "");
                    283:     return TCL_ERROR;
                    284:   }
                    285: 
                    286:   for(ii=0; ii<8; ii++){
                    287:     g.aCounter[ii] = 0;
                    288:   }
                    289:   return TCL_OK;
                    290: }
                    291: 
                    292: /*
                    293: ** Create and free a mutex.  Return the mutex pointer.  The pointer
                    294: ** will be invalid since the mutex has already been freed.  The
                    295: ** return pointer just checks to see if the mutex really was allocated.
                    296: */
                    297: static int test_alloc_mutex(
                    298:   void * clientData,
                    299:   Tcl_Interp *interp,
                    300:   int objc,
                    301:   Tcl_Obj *CONST objv[]
                    302: ){
                    303: #if SQLITE_THREADSAFE
                    304:   sqlite3_mutex *p = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
                    305:   char zBuf[100];
                    306:   sqlite3_mutex_free(p);
                    307:   sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p);
                    308:   Tcl_AppendResult(interp, zBuf, (char*)0);
                    309: #endif
                    310:   return TCL_OK;
                    311: }
                    312: 
                    313: /*
                    314: ** sqlite3_config OPTION
                    315: **
                    316: ** OPTION can be either one of the keywords:
                    317: **
                    318: **            SQLITE_CONFIG_SINGLETHREAD
                    319: **            SQLITE_CONFIG_MULTITHREAD
                    320: **            SQLITE_CONFIG_SERIALIZED
                    321: **
                    322: ** Or OPTION can be an raw integer.
                    323: */
                    324: static int test_config(
                    325:   void * clientData,
                    326:   Tcl_Interp *interp,
                    327:   int objc,
                    328:   Tcl_Obj *CONST objv[]
                    329: ){
                    330:   struct ConfigOption {
                    331:     const char *zName;
                    332:     int iValue;
                    333:   } aOpt[] = {
                    334:     {"singlethread", SQLITE_CONFIG_SINGLETHREAD},
                    335:     {"multithread",  SQLITE_CONFIG_MULTITHREAD},
                    336:     {"serialized",   SQLITE_CONFIG_SERIALIZED},
                    337:     {0, 0}
                    338:   };
                    339:   int s = sizeof(struct ConfigOption);
                    340:   int i;
                    341:   int rc;
                    342: 
                    343:   if( objc!=2 ){
                    344:     Tcl_WrongNumArgs(interp, 1, objv, "");
                    345:     return TCL_ERROR;
                    346:   }
                    347: 
                    348:   if( Tcl_GetIndexFromObjStruct(interp, objv[1], aOpt, s, "flag", 0, &i) ){
                    349:     if( Tcl_GetIntFromObj(interp, objv[1], &i) ){
                    350:       return TCL_ERROR;
                    351:     }
                    352:   }else{
                    353:     i = aOpt[i].iValue;
                    354:   }
                    355: 
                    356:   rc = sqlite3_config(i);
                    357:   Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
                    358:   return TCL_OK;
                    359: }
                    360: 
                    361: static sqlite3 *getDbPointer(Tcl_Interp *pInterp, Tcl_Obj *pObj){
                    362:   sqlite3 *db;
                    363:   Tcl_CmdInfo info;
                    364:   char *zCmd = Tcl_GetString(pObj);
                    365:   if( Tcl_GetCommandInfo(pInterp, zCmd, &info) ){
                    366:     db = *((sqlite3 **)info.objClientData);
                    367:   }else{
                    368:     db = (sqlite3*)sqlite3TestTextToPtr(zCmd);
                    369:   }
                    370:   assert( db );
                    371:   return db;
                    372: }
                    373: 
                    374: static int test_enter_db_mutex(
                    375:   void * clientData,
                    376:   Tcl_Interp *interp,
                    377:   int objc,
                    378:   Tcl_Obj *CONST objv[]
                    379: ){
                    380:   sqlite3 *db;
                    381:   if( objc!=2 ){
                    382:     Tcl_WrongNumArgs(interp, 1, objv, "DB");
                    383:     return TCL_ERROR;
                    384:   }
                    385:   db = getDbPointer(interp, objv[1]);
                    386:   if( !db ){
                    387:     return TCL_ERROR;
                    388:   }
                    389:   sqlite3_mutex_enter(sqlite3_db_mutex(db));
                    390:   return TCL_OK;
                    391: }
                    392: 
                    393: static int test_leave_db_mutex(
                    394:   void * clientData,
                    395:   Tcl_Interp *interp,
                    396:   int objc,
                    397:   Tcl_Obj *CONST objv[]
                    398: ){
                    399:   sqlite3 *db;
                    400:   if( objc!=2 ){
                    401:     Tcl_WrongNumArgs(interp, 1, objv, "DB");
                    402:     return TCL_ERROR;
                    403:   }
                    404:   db = getDbPointer(interp, objv[1]);
                    405:   if( !db ){
                    406:     return TCL_ERROR;
                    407:   }
                    408:   sqlite3_mutex_leave(sqlite3_db_mutex(db));
                    409:   return TCL_OK;
                    410: }
                    411: 
                    412: int Sqlitetest_mutex_Init(Tcl_Interp *interp){
                    413:   static struct {
                    414:     char *zName;
                    415:     Tcl_ObjCmdProc *xProc;
                    416:   } aCmd[] = {
                    417:     { "sqlite3_shutdown",        (Tcl_ObjCmdProc*)test_shutdown },
                    418:     { "sqlite3_initialize",      (Tcl_ObjCmdProc*)test_initialize },
                    419:     { "sqlite3_config",          (Tcl_ObjCmdProc*)test_config },
                    420: 
                    421:     { "enter_db_mutex",          (Tcl_ObjCmdProc*)test_enter_db_mutex },
                    422:     { "leave_db_mutex",          (Tcl_ObjCmdProc*)test_leave_db_mutex },
                    423: 
                    424:     { "alloc_dealloc_mutex",     (Tcl_ObjCmdProc*)test_alloc_mutex },
                    425:     { "install_mutex_counters",  (Tcl_ObjCmdProc*)test_install_mutex_counters },
                    426:     { "read_mutex_counters",     (Tcl_ObjCmdProc*)test_read_mutex_counters },
                    427:     { "clear_mutex_counters",    (Tcl_ObjCmdProc*)test_clear_mutex_counters },
                    428:   };
                    429:   int i;
                    430:   for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
                    431:     Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
                    432:   }
                    433: 
                    434:   Tcl_LinkVar(interp, "disable_mutex_init", 
                    435:               (char*)&g.disableInit, TCL_LINK_INT);
                    436:   Tcl_LinkVar(interp, "disable_mutex_try", 
                    437:               (char*)&g.disableTry, TCL_LINK_INT);
                    438:   return SQLITE_OK;
                    439: }

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