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