Annotation of embedaddon/sqlite3/src/test_mutex.c, revision 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>