/*** 2008 June 18**** The author disclaims copyright to this source code. In place of** a legal notice, here is a blessing:**** May you do good and not evil.** May you find forgiveness for yourself and forgive others.** May you share freely, never taking more than you give.***************************************************************************** This file contains test logic for the sqlite3_mutex interfaces.*/#if defined(INCLUDE_SQLITE_TCL_H)# include "sqlite_tcl.h"#else# include "tcl.h"#endif#include "sqlite3.h"#include "sqliteInt.h"#include <stdlib.h>#include <assert.h>#include <string.h>#define MAX_MUTEXES (SQLITE_MUTEX_STATIC_VFS3+1)#define STATIC_MUTEXES (MAX_MUTEXES-(SQLITE_MUTEX_RECURSIVE+1))/* defined in main.c */extern const char *sqlite3ErrName(int);static const char *aName[MAX_MUTEXES+1] = {"fast", "recursive", "static_main", "static_mem","static_open", "static_prng", "static_lru", "static_pmem","static_app1", "static_app2", "static_app3", "static_vfs1","static_vfs2", "static_vfs3", 0};/* A countable mutex */struct sqlite3_mutex {sqlite3_mutex *pReal;int eType;};/* State variables */static struct test_mutex_globals {int isInstalled; /* True if installed */int disableInit; /* True to cause sqlite3_initialize() to fail */int disableTry; /* True to force sqlite3_mutex_try() to fail */int isInit; /* True if initialized */sqlite3_mutex_methods m; /* Interface to "real" mutex system */int aCounter[MAX_MUTEXES]; /* Number of grabs of each type of mutex */sqlite3_mutex aStatic[STATIC_MUTEXES]; /* The static mutexes */} g = {0};/* Return true if the countable mutex is currently held */static int counterMutexHeld(sqlite3_mutex *p){return g.m.xMutexHeld(p->pReal);}/* Return true if the countable mutex is not currently held */static int counterMutexNotheld(sqlite3_mutex *p){return g.m.xMutexNotheld(p->pReal);}/* Initialize the countable mutex interface** Or, if g.disableInit is non-zero, then do not initialize but instead** return the value of g.disableInit as the result code. This can be used** to simulate an initialization failure.*/static int counterMutexInit(void){int rc;if( g.disableInit ) return g.disableInit;rc = g.m.xMutexInit();g.isInit = 1;return rc;}/*** Uninitialize the mutex subsystem*/static int counterMutexEnd(void){g.isInit = 0;return g.m.xMutexEnd();}/*** Allocate a countable mutex*/static sqlite3_mutex *counterMutexAlloc(int eType){sqlite3_mutex *pReal;sqlite3_mutex *pRet = 0;assert( g.isInit );assert( eType>=SQLITE_MUTEX_FAST );assert( eType<=SQLITE_MUTEX_STATIC_VFS3 );pReal = g.m.xMutexAlloc(eType);if( !pReal ) return 0;if( eType==SQLITE_MUTEX_FAST || eType==SQLITE_MUTEX_RECURSIVE ){pRet = (sqlite3_mutex *)malloc(sizeof(sqlite3_mutex));}else{int eStaticType = eType - (MAX_MUTEXES - STATIC_MUTEXES);assert( eStaticType>=0 );assert( eStaticType<STATIC_MUTEXES );pRet = &g.aStatic[eStaticType];}pRet->eType = eType;pRet->pReal = pReal;return pRet;}/*** Free a countable mutex*/static void counterMutexFree(sqlite3_mutex *p){assert( g.isInit );g.m.xMutexFree(p->pReal);if( p->eType==SQLITE_MUTEX_FAST || p->eType==SQLITE_MUTEX_RECURSIVE ){free(p);}}/*** Enter a countable mutex. Block until entry is safe.*/static void counterMutexEnter(sqlite3_mutex *p){assert( g.isInit );assert( p->eType>=0 );assert( p->eType<MAX_MUTEXES );g.aCounter[p->eType]++;g.m.xMutexEnter(p->pReal);}/*** Try to enter a mutex. Return true on success.*/static int counterMutexTry(sqlite3_mutex *p){assert( g.isInit );assert( p->eType>=0 );assert( p->eType<MAX_MUTEXES );g.aCounter[p->eType]++;if( g.disableTry ) return SQLITE_BUSY;return g.m.xMutexTry(p->pReal);}/* Leave a mutex*/static void counterMutexLeave(sqlite3_mutex *p){assert( g.isInit );g.m.xMutexLeave(p->pReal);}/*** sqlite3_shutdown*/static int SQLITE_TCLAPI test_shutdown(void * clientData,Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]){int rc;if( objc!=1 ){Tcl_WrongNumArgs(interp, 1, objv, "");return TCL_ERROR;}rc = sqlite3_shutdown();Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);return TCL_OK;}/*** sqlite3_initialize*/static int SQLITE_TCLAPI test_initialize(void * clientData,Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]){int rc;if( objc!=1 ){Tcl_WrongNumArgs(interp, 1, objv, "");return TCL_ERROR;}rc = sqlite3_initialize();Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);return TCL_OK;}/*** install_mutex_counters BOOLEAN*/static int SQLITE_TCLAPI test_install_mutex_counters(void * clientData,Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]){int rc = SQLITE_OK;int isInstall;sqlite3_mutex_methods counter_methods = {counterMutexInit,counterMutexEnd,counterMutexAlloc,counterMutexFree,counterMutexEnter,counterMutexTry,counterMutexLeave,counterMutexHeld,counterMutexNotheld};if( objc!=2 ){Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");return TCL_ERROR;}if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){return TCL_ERROR;}assert(isInstall==0 || isInstall==1);assert(g.isInstalled==0 || g.isInstalled==1);if( isInstall==g.isInstalled ){Tcl_AppendResult(interp, "mutex counters are ", 0);Tcl_AppendResult(interp, isInstall?"already installed":"not installed", 0);return TCL_ERROR;}if( isInstall ){assert( g.m.xMutexAlloc==0 );rc = sqlite3_config(SQLITE_CONFIG_GETMUTEX, &g.m);if( rc==SQLITE_OK ){sqlite3_config(SQLITE_CONFIG_MUTEX, &counter_methods);}g.disableTry = 0;}else{assert( g.m.xMutexAlloc );rc = sqlite3_config(SQLITE_CONFIG_MUTEX, &g.m);memset(&g.m, 0, sizeof(sqlite3_mutex_methods));}if( rc==SQLITE_OK ){g.isInstalled = isInstall;}Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);return TCL_OK;}/*** read_mutex_counters*/static int SQLITE_TCLAPI test_read_mutex_counters(void * clientData,Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]){Tcl_Obj *pRet;int ii;if( objc!=1 ){Tcl_WrongNumArgs(interp, 1, objv, "");return TCL_ERROR;}pRet = Tcl_NewObj();Tcl_IncrRefCount(pRet);for(ii=0; ii<MAX_MUTEXES; ii++){Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(aName[ii], -1));Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(g.aCounter[ii]));}Tcl_SetObjResult(interp, pRet);Tcl_DecrRefCount(pRet);return TCL_OK;}/*** clear_mutex_counters*/static int SQLITE_TCLAPI test_clear_mutex_counters(void * clientData,Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]){int ii;if( objc!=1 ){Tcl_WrongNumArgs(interp, 1, objv, "");return TCL_ERROR;}for(ii=0; ii<MAX_MUTEXES; ii++){g.aCounter[ii] = 0;}return TCL_OK;}/*** Create and free a mutex. Return the mutex pointer. The pointer** will be invalid since the mutex has already been freed. The** return pointer just checks to see if the mutex really was allocated.*/static int SQLITE_TCLAPI test_alloc_mutex(void * clientData,Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]){#if SQLITE_THREADSAFEsqlite3_mutex *p = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);char zBuf[100];sqlite3_mutex_free(p);sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p);Tcl_AppendResult(interp, zBuf, (char*)0);#endifreturn TCL_OK;}/*** sqlite3_config OPTION**** OPTION can be either one of the keywords:**** SQLITE_CONFIG_SINGLETHREAD** SQLITE_CONFIG_MULTITHREAD** SQLITE_CONFIG_SERIALIZED**** Or OPTION can be an raw integer.*/static int SQLITE_TCLAPI test_config(void * clientData,Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]){struct ConfigOption {const char *zName;int iValue;} aOpt[] = {{"singlethread", SQLITE_CONFIG_SINGLETHREAD},{"multithread", SQLITE_CONFIG_MULTITHREAD},{"serialized", SQLITE_CONFIG_SERIALIZED},{0, 0}};int s = sizeof(struct ConfigOption);int i;int rc;if( objc!=2 ){Tcl_WrongNumArgs(interp, 1, objv, "");return TCL_ERROR;}if( Tcl_GetIndexFromObjStruct(interp, objv[1], aOpt, s, "flag", 0, &i) ){if( Tcl_GetIntFromObj(interp, objv[1], &i) ){return TCL_ERROR;}}else{i = aOpt[i].iValue;}rc = sqlite3_config(i);Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);return TCL_OK;}static sqlite3 *getDbPointer(Tcl_Interp *pInterp, Tcl_Obj *pObj){sqlite3 *db;Tcl_CmdInfo info;char *zCmd = Tcl_GetString(pObj);if( Tcl_GetCommandInfo(pInterp, zCmd, &info) ){db = *((sqlite3 **)info.objClientData);}else{db = (sqlite3*)sqlite3TestTextToPtr(zCmd);}assert( db );return db;}static sqlite3_mutex *getStaticMutexPointer(Tcl_Interp *pInterp,Tcl_Obj *pObj){int iMutex;if( Tcl_GetIndexFromObj(pInterp, pObj, aName, "mutex name", 0, &iMutex) ){return 0;}assert( iMutex!=SQLITE_MUTEX_FAST && iMutex!=SQLITE_MUTEX_RECURSIVE );return counterMutexAlloc(iMutex);}static int SQLITE_TCLAPI test_enter_static_mutex(void * clientData,Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]){sqlite3_mutex *pMutex;if( objc!=2 ){Tcl_WrongNumArgs(interp, 1, objv, "NAME");return TCL_ERROR;}pMutex = getStaticMutexPointer(interp, objv[1]);if( !pMutex ){return TCL_ERROR;}sqlite3_mutex_enter(pMutex);return TCL_OK;}static int SQLITE_TCLAPI test_leave_static_mutex(void * clientData,Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]){sqlite3_mutex *pMutex;if( objc!=2 ){Tcl_WrongNumArgs(interp, 1, objv, "NAME");return TCL_ERROR;}pMutex = getStaticMutexPointer(interp, objv[1]);if( !pMutex ){return TCL_ERROR;}sqlite3_mutex_leave(pMutex);return TCL_OK;}static int SQLITE_TCLAPI test_enter_db_mutex(void * clientData,Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]){sqlite3 *db;if( objc!=2 ){Tcl_WrongNumArgs(interp, 1, objv, "DB");return TCL_ERROR;}db = getDbPointer(interp, objv[1]);if( !db ){return TCL_ERROR;}sqlite3_mutex_enter(sqlite3_db_mutex(db));return TCL_OK;}static int SQLITE_TCLAPI test_leave_db_mutex(void * clientData,Tcl_Interp *interp,int objc,Tcl_Obj *CONST objv[]){sqlite3 *db;if( objc!=2 ){Tcl_WrongNumArgs(interp, 1, objv, "DB");return TCL_ERROR;}db = getDbPointer(interp, objv[1]);if( !db ){return TCL_ERROR;}sqlite3_mutex_leave(sqlite3_db_mutex(db));return TCL_OK;}int Sqlitetest_mutex_Init(Tcl_Interp *interp){static struct {char *zName;Tcl_ObjCmdProc *xProc;} aCmd[] = {{ "sqlite3_shutdown", (Tcl_ObjCmdProc*)test_shutdown },{ "sqlite3_initialize", (Tcl_ObjCmdProc*)test_initialize },{ "sqlite3_config", (Tcl_ObjCmdProc*)test_config },{ "enter_static_mutex", (Tcl_ObjCmdProc*)test_enter_static_mutex },{ "leave_static_mutex", (Tcl_ObjCmdProc*)test_leave_static_mutex },{ "enter_db_mutex", (Tcl_ObjCmdProc*)test_enter_db_mutex },{ "leave_db_mutex", (Tcl_ObjCmdProc*)test_leave_db_mutex },{ "alloc_dealloc_mutex", (Tcl_ObjCmdProc*)test_alloc_mutex },{ "install_mutex_counters", (Tcl_ObjCmdProc*)test_install_mutex_counters },{ "read_mutex_counters", (Tcl_ObjCmdProc*)test_read_mutex_counters },{ "clear_mutex_counters", (Tcl_ObjCmdProc*)test_clear_mutex_counters },};int i;for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);}Tcl_LinkVar(interp, "disable_mutex_init",(char*)&g.disableInit, TCL_LINK_INT);Tcl_LinkVar(interp, "disable_mutex_try",(char*)&g.disableTry, TCL_LINK_INT);return SQLITE_OK;}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。