/* ** 2009 August 17 ** ** 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. ** ************************************************************************* ** ** The code in this file is used for testing SQLite. It is not part of ** the source code used in production systems. ** ** Specifically, this file tests the effect of errors while initializing ** the various pluggable sub-systems from within sqlite3_initialize(). ** If an error occurs in sqlite3_initialize() the following should be ** true: ** ** 1) An error code is returned to the user, and ** 2) A subsequent call to sqlite3_shutdown() calls the shutdown method ** of those subsystems that were initialized, and ** 3) A subsequent call to sqlite3_initialize() attempts to initialize ** the remaining, uninitialized, subsystems. */ #include "sqliteInt.h" #include #include static struct Wrapped { sqlite3_pcache_methods pcache; sqlite3_mem_methods mem; sqlite3_mutex_methods mutex; int mem_init; /* True if mem subsystem is initalized */ int mem_fail; /* True to fail mem subsystem inialization */ int mutex_init; /* True if mutex subsystem is initalized */ int mutex_fail; /* True to fail mutex subsystem inialization */ int pcache_init; /* True if pcache subsystem is initalized */ int pcache_fail; /* True to fail pcache subsystem inialization */ } wrapped; static int wrMemInit(void *pAppData){ int rc; if( wrapped.mem_fail ){ rc = SQLITE_ERROR; }else{ rc = wrapped.mem.xInit(wrapped.mem.pAppData); } if( rc==SQLITE_OK ){ wrapped.mem_init = 1; } return rc; } static void wrMemShutdown(void *pAppData){ wrapped.mem.xShutdown(wrapped.mem.pAppData); wrapped.mem_init = 0; } static void *wrMemMalloc(int n) {return wrapped.mem.xMalloc(n);} static void wrMemFree(void *p) {wrapped.mem.xFree(p);} static void *wrMemRealloc(void *p, int n) {return wrapped.mem.xRealloc(p, n);} static int wrMemSize(void *p) {return wrapped.mem.xSize(p);} static int wrMemRoundup(int n) {return wrapped.mem.xRoundup(n);} static int wrMutexInit(void){ int rc; if( wrapped.mutex_fail ){ rc = SQLITE_ERROR; }else{ rc = wrapped.mutex.xMutexInit(); } if( rc==SQLITE_OK ){ wrapped.mutex_init = 1; } return rc; } static int wrMutexEnd(void){ wrapped.mutex.xMutexEnd(); wrapped.mutex_init = 0; return SQLITE_OK; } static sqlite3_mutex *wrMutexAlloc(int e){ return wrapped.mutex.xMutexAlloc(e); } static void wrMutexFree(sqlite3_mutex *p){ wrapped.mutex.xMutexFree(p); } static void wrMutexEnter(sqlite3_mutex *p){ wrapped.mutex.xMutexEnter(p); } static int wrMutexTry(sqlite3_mutex *p){ return wrapped.mutex.xMutexTry(p); } static void wrMutexLeave(sqlite3_mutex *p){ wrapped.mutex.xMutexLeave(p); } static int wrMutexHeld(sqlite3_mutex *p){ return wrapped.mutex.xMutexHeld(p); } static int wrMutexNotheld(sqlite3_mutex *p){ return wrapped.mutex.xMutexNotheld(p); } static int wrPCacheInit(void *pArg){ int rc; if( wrapped.pcache_fail ){ rc = SQLITE_ERROR; }else{ rc = wrapped.pcache.xInit(wrapped.pcache.pArg); } if( rc==SQLITE_OK ){ wrapped.pcache_init = 1; } return rc; } static void wrPCacheShutdown(void *pArg){ wrapped.pcache.xShutdown(wrapped.pcache.pArg); wrapped.pcache_init = 0; } static sqlite3_pcache *wrPCacheCreate(int a, int b){ return wrapped.pcache.xCreate(a, b); } static void wrPCacheCachesize(sqlite3_pcache *p, int n){ wrapped.pcache.xCachesize(p, n); } static int wrPCachePagecount(sqlite3_pcache *p){ return wrapped.pcache.xPagecount(p); } static void *wrPCacheFetch(sqlite3_pcache *p, unsigned a, int b){ return wrapped.pcache.xFetch(p, a, b); } static void wrPCacheUnpin(sqlite3_pcache *p, void *a, int b){ wrapped.pcache.xUnpin(p, a, b); } static void wrPCacheRekey(sqlite3_pcache *p, void *a, unsigned b, unsigned c){ wrapped.pcache.xRekey(p, a, b, c); } static void wrPCacheTruncate(sqlite3_pcache *p, unsigned a){ wrapped.pcache.xTruncate(p, a); } static void wrPCacheDestroy(sqlite3_pcache *p){ wrapped.pcache.xDestroy(p); } static void installInitWrappers(void){ sqlite3_mutex_methods mutexmethods = { wrMutexInit, wrMutexEnd, wrMutexAlloc, wrMutexFree, wrMutexEnter, wrMutexTry, wrMutexLeave, wrMutexHeld, wrMutexNotheld }; sqlite3_pcache_methods pcachemethods = { 0, wrPCacheInit, wrPCacheShutdown, wrPCacheCreate, wrPCacheCachesize, wrPCachePagecount, wrPCacheFetch, wrPCacheUnpin, wrPCacheRekey, wrPCacheTruncate, wrPCacheDestroy }; sqlite3_mem_methods memmethods = { wrMemMalloc, wrMemFree, wrMemRealloc, wrMemSize, wrMemRoundup, wrMemInit, wrMemShutdown, 0 }; memset(&wrapped, 0, sizeof(wrapped)); sqlite3_shutdown(); sqlite3_config(SQLITE_CONFIG_GETMUTEX, &wrapped.mutex); sqlite3_config(SQLITE_CONFIG_GETMALLOC, &wrapped.mem); sqlite3_config(SQLITE_CONFIG_GETPCACHE, &wrapped.pcache); sqlite3_config(SQLITE_CONFIG_MUTEX, &mutexmethods); sqlite3_config(SQLITE_CONFIG_MALLOC, &memmethods); sqlite3_config(SQLITE_CONFIG_PCACHE, &pcachemethods); } static int init_wrapper_install( ClientData clientData, /* Unused */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ int i; installInitWrappers(); for(i=1; i