AryaWu/sqlite
0
1/*2** 2009 August 173**4** The author disclaims copyright to this source code. In place of5** 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** The code in this file is used for testing SQLite. It is not part of14** the source code used in production systems.15**16** Specifically, this file tests the effect of errors while initializing17** the various pluggable sub-systems from within sqlite3_initialize().18** If an error occurs in sqlite3_initialize() the following should be19** true:20**21** 1) An error code is returned to the user, and22** 2) A subsequent call to sqlite3_shutdown() calls the shutdown method23** of those subsystems that were initialized, and24** 3) A subsequent call to sqlite3_initialize() attempts to initialize25** the remaining, uninitialized, subsystems.26*/27 28#include "sqliteInt.h"29#include <string.h>30#include "tclsqlite.h"31 32static struct Wrapped {33 sqlite3_pcache_methods2 pcache;34 sqlite3_mem_methods mem;35 sqlite3_mutex_methods mutex;36 37 int mem_init; /* True if mem subsystem is initialized */38 int mem_fail; /* True to fail mem subsystem initialization */39 int mutex_init; /* True if mutex subsystem is initialized */40 int mutex_fail; /* True to fail mutex subsystem initialization */41 int pcache_init; /* True if pcache subsystem is initialized */42 int pcache_fail; /* True to fail pcache subsystem initialization */43} wrapped;44 45static int wrMemInit(void *pAppData){46 int rc;47 if( wrapped.mem_fail ){48 rc = SQLITE_ERROR;49 }else{50 rc = wrapped.mem.xInit(wrapped.mem.pAppData);51 }52 if( rc==SQLITE_OK ){53 wrapped.mem_init = 1;54 }55 return rc;56}57static void wrMemShutdown(void *pAppData){58 wrapped.mem.xShutdown(wrapped.mem.pAppData);59 wrapped.mem_init = 0;60}61static void *wrMemMalloc(int n) {return wrapped.mem.xMalloc(n);}62static void wrMemFree(void *p) {wrapped.mem.xFree(p);}63static void *wrMemRealloc(void *p, int n) {return wrapped.mem.xRealloc(p, n);}64static int wrMemSize(void *p) {return wrapped.mem.xSize(p);}65static int wrMemRoundup(int n) {return wrapped.mem.xRoundup(n);}66 67 68static int wrMutexInit(void){69 int rc;70 if( wrapped.mutex_fail ){71 rc = SQLITE_ERROR;72 }else{73 rc = wrapped.mutex.xMutexInit();74 }75 if( rc==SQLITE_OK ){76 wrapped.mutex_init = 1;77 }78 return rc;79}80static int wrMutexEnd(void){81 wrapped.mutex.xMutexEnd();82 wrapped.mutex_init = 0;83 return SQLITE_OK;84}85static sqlite3_mutex *wrMutexAlloc(int e){86 return wrapped.mutex.xMutexAlloc(e);87}88static void wrMutexFree(sqlite3_mutex *p){89 wrapped.mutex.xMutexFree(p);90}91static void wrMutexEnter(sqlite3_mutex *p){92 wrapped.mutex.xMutexEnter(p);93}94static int wrMutexTry(sqlite3_mutex *p){95 return wrapped.mutex.xMutexTry(p);96}97static void wrMutexLeave(sqlite3_mutex *p){98 wrapped.mutex.xMutexLeave(p);99}100static int wrMutexHeld(sqlite3_mutex *p){101 return wrapped.mutex.xMutexHeld(p);102}103static int wrMutexNotheld(sqlite3_mutex *p){104 return wrapped.mutex.xMutexNotheld(p);105}106 107 108 109static int wrPCacheInit(void *pArg){110 int rc;111 if( wrapped.pcache_fail ){112 rc = SQLITE_ERROR;113 }else{114 rc = wrapped.pcache.xInit(wrapped.pcache.pArg);115 }116 if( rc==SQLITE_OK ){117 wrapped.pcache_init = 1;118 }119 return rc;120}121static void wrPCacheShutdown(void *pArg){122 wrapped.pcache.xShutdown(wrapped.pcache.pArg);123 wrapped.pcache_init = 0;124}125 126static sqlite3_pcache *wrPCacheCreate(int a, int b, int c){127 return wrapped.pcache.xCreate(a, b, c);128} 129static void wrPCacheCachesize(sqlite3_pcache *p, int n){130 wrapped.pcache.xCachesize(p, n);131} 132static int wrPCachePagecount(sqlite3_pcache *p){133 return wrapped.pcache.xPagecount(p);134} 135static sqlite3_pcache_page *wrPCacheFetch(sqlite3_pcache *p, unsigned a, int b){136 return wrapped.pcache.xFetch(p, a, b);137} 138static void wrPCacheUnpin(sqlite3_pcache *p, sqlite3_pcache_page *a, int b){139 wrapped.pcache.xUnpin(p, a, b);140} 141static void wrPCacheRekey(142 sqlite3_pcache *p, 143 sqlite3_pcache_page *a, 144 unsigned b, 145 unsigned c146){147 wrapped.pcache.xRekey(p, a, b, c);148} 149static void wrPCacheTruncate(sqlite3_pcache *p, unsigned a){150 wrapped.pcache.xTruncate(p, a);151} 152static void wrPCacheDestroy(sqlite3_pcache *p){153 wrapped.pcache.xDestroy(p);154} 155 156static void installInitWrappers(void){157 sqlite3_mutex_methods mutexmethods = {158 wrMutexInit, wrMutexEnd, wrMutexAlloc,159 wrMutexFree, wrMutexEnter, wrMutexTry,160 wrMutexLeave, wrMutexHeld, wrMutexNotheld161 };162 sqlite3_pcache_methods2 pcachemethods = {163 1, 0,164 wrPCacheInit, wrPCacheShutdown, wrPCacheCreate, 165 wrPCacheCachesize, wrPCachePagecount, wrPCacheFetch,166 wrPCacheUnpin, wrPCacheRekey, wrPCacheTruncate, 167 wrPCacheDestroy168 };169 sqlite3_mem_methods memmethods = {170 wrMemMalloc, wrMemFree, wrMemRealloc,171 wrMemSize, wrMemRoundup, wrMemInit,172 wrMemShutdown,173 0174 };175 176 memset(&wrapped, 0, sizeof(wrapped));177 178 sqlite3_shutdown();179 sqlite3_config(SQLITE_CONFIG_GETMUTEX, &wrapped.mutex);180 sqlite3_config(SQLITE_CONFIG_GETMALLOC, &wrapped.mem);181 sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &wrapped.pcache);182 sqlite3_config(SQLITE_CONFIG_MUTEX, &mutexmethods);183 sqlite3_config(SQLITE_CONFIG_MALLOC, &memmethods);184 sqlite3_config(SQLITE_CONFIG_PCACHE2, &pcachemethods);185}186 187static int SQLITE_TCLAPI init_wrapper_install(188 ClientData clientData, /* Unused */189 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */190 int objc, /* Number of arguments */191 Tcl_Obj *CONST objv[] /* Command arguments */192){193 int i;194 installInitWrappers();195 for(i=1; i<objc; i++){196 char *z = Tcl_GetString(objv[i]);197 if( strcmp(z, "mem")==0 ){198 wrapped.mem_fail = 1;199 }else if( strcmp(z, "mutex")==0 ){200 wrapped.mutex_fail = 1;201 }else if( strcmp(z, "pcache")==0 ){202 wrapped.pcache_fail = 1;203 }else{204 Tcl_AppendResult(interp, "Unknown argument: \"", z, "\"", NULL);205 return TCL_ERROR;206 }207 }208 return TCL_OK;209}210 211static int SQLITE_TCLAPI init_wrapper_uninstall(212 ClientData clientData, /* Unused */213 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */214 int objc, /* Number of arguments */215 Tcl_Obj *CONST objv[] /* Command arguments */216){217 if( objc!=1 ){218 Tcl_WrongNumArgs(interp, 1, objv, "");219 return TCL_ERROR;220 }221 222 sqlite3_shutdown();223 sqlite3_config(SQLITE_CONFIG_MUTEX, &wrapped.mutex);224 sqlite3_config(SQLITE_CONFIG_MALLOC, &wrapped.mem);225 sqlite3_config(SQLITE_CONFIG_PCACHE2, &wrapped.pcache);226 return TCL_OK;227}228 229static int SQLITE_TCLAPI init_wrapper_clear(230 ClientData clientData, /* Unused */231 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */232 int objc, /* Number of arguments */233 Tcl_Obj *CONST objv[] /* Command arguments */234){235 if( objc!=1 ){236 Tcl_WrongNumArgs(interp, 1, objv, "");237 return TCL_ERROR;238 }239 240 wrapped.mem_fail = 0;241 wrapped.mutex_fail = 0;242 wrapped.pcache_fail = 0;243 return TCL_OK;244}245 246static int SQLITE_TCLAPI init_wrapper_query(247 ClientData clientData, /* Unused */248 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */249 int objc, /* Number of arguments */250 Tcl_Obj *CONST objv[] /* Command arguments */251){252 Tcl_Obj *pRet;253 254 if( objc!=1 ){255 Tcl_WrongNumArgs(interp, 1, objv, "");256 return TCL_ERROR;257 }258 259 pRet = Tcl_NewObj();260 if( wrapped.mutex_init ){261 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("mutex", -1));262 }263 if( wrapped.mem_init ){264 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("mem", -1));265 }266 if( wrapped.pcache_init ){267 Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("pcache", -1));268 }269 270 Tcl_SetObjResult(interp, pRet);271 return TCL_OK;272}273 274int Sqlitetest_init_Init(Tcl_Interp *interp){275 static struct {276 char *zName;277 Tcl_ObjCmdProc *xProc;278 } aObjCmd[] = {279 {"init_wrapper_install", init_wrapper_install},280 {"init_wrapper_query", init_wrapper_query },281 {"init_wrapper_uninstall", init_wrapper_uninstall},282 {"init_wrapper_clear", init_wrapper_clear}283 };284 int i;285 286 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){287 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);288 }289 290 return TCL_OK;291}292 