| OLD | NEW | 
 | (Empty) | 
|    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  |  | 
| OLD | NEW |