1e1ab2193Sdan /*
2e1ab2193Sdan ** 2009 August 17
3e1ab2193Sdan **
4e1ab2193Sdan ** The author disclaims copyright to this source code. In place of
5e1ab2193Sdan ** a legal notice, here is a blessing:
6e1ab2193Sdan **
7e1ab2193Sdan ** May you do good and not evil.
8e1ab2193Sdan ** May you find forgiveness for yourself and forgive others.
9e1ab2193Sdan ** May you share freely, never taking more than you give.
10e1ab2193Sdan **
11e1ab2193Sdan *************************************************************************
12e1ab2193Sdan **
13e1ab2193Sdan ** The code in this file is used for testing SQLite. It is not part of
14e1ab2193Sdan ** the source code used in production systems.
15e1ab2193Sdan **
16e1ab2193Sdan ** Specifically, this file tests the effect of errors while initializing
17e1ab2193Sdan ** the various pluggable sub-systems from within sqlite3_initialize().
18e1ab2193Sdan ** If an error occurs in sqlite3_initialize() the following should be
19e1ab2193Sdan ** true:
20e1ab2193Sdan **
21e1ab2193Sdan ** 1) An error code is returned to the user, and
22e1ab2193Sdan ** 2) A subsequent call to sqlite3_shutdown() calls the shutdown method
23e1ab2193Sdan ** of those subsystems that were initialized, and
24e1ab2193Sdan ** 3) A subsequent call to sqlite3_initialize() attempts to initialize
25e1ab2193Sdan ** the remaining, uninitialized, subsystems.
26e1ab2193Sdan */
27e1ab2193Sdan
28e1ab2193Sdan #include "sqliteInt.h"
29e1ab2193Sdan #include <string.h>
3052b1dbb5Smistachkin #if defined(INCLUDE_SQLITE_TCL_H)
3152b1dbb5Smistachkin # include "sqlite_tcl.h"
3252b1dbb5Smistachkin #else
3352b1dbb5Smistachkin # include "tcl.h"
3452b1dbb5Smistachkin #endif
35e1ab2193Sdan
36e1ab2193Sdan static struct Wrapped {
3722e21ff4Sdan sqlite3_pcache_methods2 pcache;
38e1ab2193Sdan sqlite3_mem_methods mem;
39e1ab2193Sdan sqlite3_mutex_methods mutex;
40e1ab2193Sdan
41e1ab2193Sdan int mem_init; /* True if mem subsystem is initalized */
42e1ab2193Sdan int mem_fail; /* True to fail mem subsystem inialization */
43e1ab2193Sdan int mutex_init; /* True if mutex subsystem is initalized */
44e1ab2193Sdan int mutex_fail; /* True to fail mutex subsystem inialization */
45e1ab2193Sdan int pcache_init; /* True if pcache subsystem is initalized */
46e1ab2193Sdan int pcache_fail; /* True to fail pcache subsystem inialization */
47e1ab2193Sdan } wrapped;
48e1ab2193Sdan
wrMemInit(void * pAppData)49e1ab2193Sdan static int wrMemInit(void *pAppData){
50e1ab2193Sdan int rc;
51e1ab2193Sdan if( wrapped.mem_fail ){
52e1ab2193Sdan rc = SQLITE_ERROR;
53e1ab2193Sdan }else{
54e1ab2193Sdan rc = wrapped.mem.xInit(wrapped.mem.pAppData);
55e1ab2193Sdan }
56e1ab2193Sdan if( rc==SQLITE_OK ){
57e1ab2193Sdan wrapped.mem_init = 1;
58e1ab2193Sdan }
59e1ab2193Sdan return rc;
60e1ab2193Sdan }
wrMemShutdown(void * pAppData)61e1ab2193Sdan static void wrMemShutdown(void *pAppData){
62e1ab2193Sdan wrapped.mem.xShutdown(wrapped.mem.pAppData);
63e1ab2193Sdan wrapped.mem_init = 0;
64e1ab2193Sdan }
wrMemMalloc(int n)65e1ab2193Sdan static void *wrMemMalloc(int n) {return wrapped.mem.xMalloc(n);}
wrMemFree(void * p)66e1ab2193Sdan static void wrMemFree(void *p) {wrapped.mem.xFree(p);}
wrMemRealloc(void * p,int n)67e1ab2193Sdan static void *wrMemRealloc(void *p, int n) {return wrapped.mem.xRealloc(p, n);}
wrMemSize(void * p)68e1ab2193Sdan static int wrMemSize(void *p) {return wrapped.mem.xSize(p);}
wrMemRoundup(int n)69e1ab2193Sdan static int wrMemRoundup(int n) {return wrapped.mem.xRoundup(n);}
70e1ab2193Sdan
71e1ab2193Sdan
wrMutexInit(void)72e1ab2193Sdan static int wrMutexInit(void){
73e1ab2193Sdan int rc;
74e1ab2193Sdan if( wrapped.mutex_fail ){
75e1ab2193Sdan rc = SQLITE_ERROR;
76e1ab2193Sdan }else{
77e1ab2193Sdan rc = wrapped.mutex.xMutexInit();
78e1ab2193Sdan }
79e1ab2193Sdan if( rc==SQLITE_OK ){
80e1ab2193Sdan wrapped.mutex_init = 1;
81e1ab2193Sdan }
82e1ab2193Sdan return rc;
83e1ab2193Sdan }
wrMutexEnd(void)84e1ab2193Sdan static int wrMutexEnd(void){
85e1ab2193Sdan wrapped.mutex.xMutexEnd();
86e1ab2193Sdan wrapped.mutex_init = 0;
87e1ab2193Sdan return SQLITE_OK;
88e1ab2193Sdan }
wrMutexAlloc(int e)89e1ab2193Sdan static sqlite3_mutex *wrMutexAlloc(int e){
90e1ab2193Sdan return wrapped.mutex.xMutexAlloc(e);
91e1ab2193Sdan }
wrMutexFree(sqlite3_mutex * p)92e1ab2193Sdan static void wrMutexFree(sqlite3_mutex *p){
93e1ab2193Sdan wrapped.mutex.xMutexFree(p);
94e1ab2193Sdan }
wrMutexEnter(sqlite3_mutex * p)95e1ab2193Sdan static void wrMutexEnter(sqlite3_mutex *p){
96e1ab2193Sdan wrapped.mutex.xMutexEnter(p);
97e1ab2193Sdan }
wrMutexTry(sqlite3_mutex * p)98e1ab2193Sdan static int wrMutexTry(sqlite3_mutex *p){
99e1ab2193Sdan return wrapped.mutex.xMutexTry(p);
100e1ab2193Sdan }
wrMutexLeave(sqlite3_mutex * p)101e1ab2193Sdan static void wrMutexLeave(sqlite3_mutex *p){
102e1ab2193Sdan wrapped.mutex.xMutexLeave(p);
103e1ab2193Sdan }
wrMutexHeld(sqlite3_mutex * p)104e1ab2193Sdan static int wrMutexHeld(sqlite3_mutex *p){
105e1ab2193Sdan return wrapped.mutex.xMutexHeld(p);
106e1ab2193Sdan }
wrMutexNotheld(sqlite3_mutex * p)107e1ab2193Sdan static int wrMutexNotheld(sqlite3_mutex *p){
108e1ab2193Sdan return wrapped.mutex.xMutexNotheld(p);
109e1ab2193Sdan }
110e1ab2193Sdan
111e1ab2193Sdan
112e1ab2193Sdan
wrPCacheInit(void * pArg)113e1ab2193Sdan static int wrPCacheInit(void *pArg){
114e1ab2193Sdan int rc;
115e1ab2193Sdan if( wrapped.pcache_fail ){
116e1ab2193Sdan rc = SQLITE_ERROR;
117e1ab2193Sdan }else{
118e1ab2193Sdan rc = wrapped.pcache.xInit(wrapped.pcache.pArg);
119e1ab2193Sdan }
120e1ab2193Sdan if( rc==SQLITE_OK ){
121e1ab2193Sdan wrapped.pcache_init = 1;
122e1ab2193Sdan }
123e1ab2193Sdan return rc;
124e1ab2193Sdan }
wrPCacheShutdown(void * pArg)125e1ab2193Sdan static void wrPCacheShutdown(void *pArg){
126e1ab2193Sdan wrapped.pcache.xShutdown(wrapped.pcache.pArg);
127e1ab2193Sdan wrapped.pcache_init = 0;
128e1ab2193Sdan }
129e1ab2193Sdan
wrPCacheCreate(int a,int b,int c)13022e21ff4Sdan static sqlite3_pcache *wrPCacheCreate(int a, int b, int c){
13122e21ff4Sdan return wrapped.pcache.xCreate(a, b, c);
132e1ab2193Sdan }
wrPCacheCachesize(sqlite3_pcache * p,int n)133e1ab2193Sdan static void wrPCacheCachesize(sqlite3_pcache *p, int n){
134e1ab2193Sdan wrapped.pcache.xCachesize(p, n);
135e1ab2193Sdan }
wrPCachePagecount(sqlite3_pcache * p)136e1ab2193Sdan static int wrPCachePagecount(sqlite3_pcache *p){
137e1ab2193Sdan return wrapped.pcache.xPagecount(p);
138e1ab2193Sdan }
wrPCacheFetch(sqlite3_pcache * p,unsigned a,int b)13922e21ff4Sdan static sqlite3_pcache_page *wrPCacheFetch(sqlite3_pcache *p, unsigned a, int b){
140e1ab2193Sdan return wrapped.pcache.xFetch(p, a, b);
141e1ab2193Sdan }
wrPCacheUnpin(sqlite3_pcache * p,sqlite3_pcache_page * a,int b)14222e21ff4Sdan static void wrPCacheUnpin(sqlite3_pcache *p, sqlite3_pcache_page *a, int b){
143e1ab2193Sdan wrapped.pcache.xUnpin(p, a, b);
144e1ab2193Sdan }
wrPCacheRekey(sqlite3_pcache * p,sqlite3_pcache_page * a,unsigned b,unsigned c)14522e21ff4Sdan static void wrPCacheRekey(
14622e21ff4Sdan sqlite3_pcache *p,
14722e21ff4Sdan sqlite3_pcache_page *a,
14822e21ff4Sdan unsigned b,
14922e21ff4Sdan unsigned c
15022e21ff4Sdan ){
151e1ab2193Sdan wrapped.pcache.xRekey(p, a, b, c);
152e1ab2193Sdan }
wrPCacheTruncate(sqlite3_pcache * p,unsigned a)153e1ab2193Sdan static void wrPCacheTruncate(sqlite3_pcache *p, unsigned a){
154e1ab2193Sdan wrapped.pcache.xTruncate(p, a);
155e1ab2193Sdan }
wrPCacheDestroy(sqlite3_pcache * p)156e1ab2193Sdan static void wrPCacheDestroy(sqlite3_pcache *p){
157e1ab2193Sdan wrapped.pcache.xDestroy(p);
158e1ab2193Sdan }
159e1ab2193Sdan
installInitWrappers(void)160e1ab2193Sdan static void installInitWrappers(void){
161e1ab2193Sdan sqlite3_mutex_methods mutexmethods = {
162e1ab2193Sdan wrMutexInit, wrMutexEnd, wrMutexAlloc,
163e1ab2193Sdan wrMutexFree, wrMutexEnter, wrMutexTry,
164e1ab2193Sdan wrMutexLeave, wrMutexHeld, wrMutexNotheld
165e1ab2193Sdan };
16622e21ff4Sdan sqlite3_pcache_methods2 pcachemethods = {
16781ef0f97Sdrh 1, 0,
168e1ab2193Sdan wrPCacheInit, wrPCacheShutdown, wrPCacheCreate,
169e1ab2193Sdan wrPCacheCachesize, wrPCachePagecount, wrPCacheFetch,
170e1ab2193Sdan wrPCacheUnpin, wrPCacheRekey, wrPCacheTruncate,
171e1ab2193Sdan wrPCacheDestroy
172e1ab2193Sdan };
173e1ab2193Sdan sqlite3_mem_methods memmethods = {
174e1ab2193Sdan wrMemMalloc, wrMemFree, wrMemRealloc,
175e1ab2193Sdan wrMemSize, wrMemRoundup, wrMemInit,
176e1ab2193Sdan wrMemShutdown,
177e1ab2193Sdan 0
178e1ab2193Sdan };
179e1ab2193Sdan
180e1ab2193Sdan memset(&wrapped, 0, sizeof(wrapped));
181e1ab2193Sdan
182e1ab2193Sdan sqlite3_shutdown();
183e1ab2193Sdan sqlite3_config(SQLITE_CONFIG_GETMUTEX, &wrapped.mutex);
184e1ab2193Sdan sqlite3_config(SQLITE_CONFIG_GETMALLOC, &wrapped.mem);
18522e21ff4Sdan sqlite3_config(SQLITE_CONFIG_GETPCACHE2, &wrapped.pcache);
186e1ab2193Sdan sqlite3_config(SQLITE_CONFIG_MUTEX, &mutexmethods);
187e1ab2193Sdan sqlite3_config(SQLITE_CONFIG_MALLOC, &memmethods);
18822e21ff4Sdan sqlite3_config(SQLITE_CONFIG_PCACHE2, &pcachemethods);
189e1ab2193Sdan }
190e1ab2193Sdan
init_wrapper_install(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])191*7617e4a8Smistachkin static int SQLITE_TCLAPI init_wrapper_install(
192e1ab2193Sdan ClientData clientData, /* Unused */
193e1ab2193Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
194e1ab2193Sdan int objc, /* Number of arguments */
195e1ab2193Sdan Tcl_Obj *CONST objv[] /* Command arguments */
196e1ab2193Sdan ){
197e1ab2193Sdan int i;
198e1ab2193Sdan installInitWrappers();
199e1ab2193Sdan for(i=1; i<objc; i++){
200e1ab2193Sdan char *z = Tcl_GetString(objv[i]);
201e1ab2193Sdan if( strcmp(z, "mem")==0 ){
202e1ab2193Sdan wrapped.mem_fail = 1;
203e1ab2193Sdan }else if( strcmp(z, "mutex")==0 ){
204e1ab2193Sdan wrapped.mutex_fail = 1;
205e1ab2193Sdan }else if( strcmp(z, "pcache")==0 ){
206e1ab2193Sdan wrapped.pcache_fail = 1;
207e1ab2193Sdan }else{
208e1ab2193Sdan Tcl_AppendResult(interp, "Unknown argument: \"", z, "\"");
209e1ab2193Sdan return TCL_ERROR;
210e1ab2193Sdan }
211e1ab2193Sdan }
212e1ab2193Sdan return TCL_OK;
213e1ab2193Sdan }
214e1ab2193Sdan
init_wrapper_uninstall(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])215*7617e4a8Smistachkin static int SQLITE_TCLAPI init_wrapper_uninstall(
216e1ab2193Sdan ClientData clientData, /* Unused */
217e1ab2193Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
218e1ab2193Sdan int objc, /* Number of arguments */
219e1ab2193Sdan Tcl_Obj *CONST objv[] /* Command arguments */
220e1ab2193Sdan ){
221e1ab2193Sdan if( objc!=1 ){
222e1ab2193Sdan Tcl_WrongNumArgs(interp, 1, objv, "");
223e1ab2193Sdan return TCL_ERROR;
224e1ab2193Sdan }
225e1ab2193Sdan
226e1ab2193Sdan sqlite3_shutdown();
227e1ab2193Sdan sqlite3_config(SQLITE_CONFIG_MUTEX, &wrapped.mutex);
228e1ab2193Sdan sqlite3_config(SQLITE_CONFIG_MALLOC, &wrapped.mem);
22922e21ff4Sdan sqlite3_config(SQLITE_CONFIG_PCACHE2, &wrapped.pcache);
230e1ab2193Sdan return TCL_OK;
231e1ab2193Sdan }
232e1ab2193Sdan
init_wrapper_clear(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])233*7617e4a8Smistachkin static int SQLITE_TCLAPI init_wrapper_clear(
234e1ab2193Sdan ClientData clientData, /* Unused */
235e1ab2193Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
236e1ab2193Sdan int objc, /* Number of arguments */
237e1ab2193Sdan Tcl_Obj *CONST objv[] /* Command arguments */
238e1ab2193Sdan ){
239e1ab2193Sdan if( objc!=1 ){
240e1ab2193Sdan Tcl_WrongNumArgs(interp, 1, objv, "");
241e1ab2193Sdan return TCL_ERROR;
242e1ab2193Sdan }
243e1ab2193Sdan
244e1ab2193Sdan wrapped.mem_fail = 0;
245e1ab2193Sdan wrapped.mutex_fail = 0;
246e1ab2193Sdan wrapped.pcache_fail = 0;
247e1ab2193Sdan return TCL_OK;
248e1ab2193Sdan }
249e1ab2193Sdan
init_wrapper_query(ClientData clientData,Tcl_Interp * interp,int objc,Tcl_Obj * CONST objv[])250*7617e4a8Smistachkin static int SQLITE_TCLAPI init_wrapper_query(
251e1ab2193Sdan ClientData clientData, /* Unused */
252e1ab2193Sdan Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
253e1ab2193Sdan int objc, /* Number of arguments */
254e1ab2193Sdan Tcl_Obj *CONST objv[] /* Command arguments */
255e1ab2193Sdan ){
256e1ab2193Sdan Tcl_Obj *pRet;
257e1ab2193Sdan
258e1ab2193Sdan if( objc!=1 ){
259e1ab2193Sdan Tcl_WrongNumArgs(interp, 1, objv, "");
260e1ab2193Sdan return TCL_ERROR;
261e1ab2193Sdan }
262e1ab2193Sdan
263e1ab2193Sdan pRet = Tcl_NewObj();
264e1ab2193Sdan if( wrapped.mutex_init ){
265e1ab2193Sdan Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("mutex", -1));
266e1ab2193Sdan }
267e1ab2193Sdan if( wrapped.mem_init ){
268e1ab2193Sdan Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("mem", -1));
269e1ab2193Sdan }
270e1ab2193Sdan if( wrapped.pcache_init ){
271e1ab2193Sdan Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("pcache", -1));
272e1ab2193Sdan }
273e1ab2193Sdan
274e1ab2193Sdan Tcl_SetObjResult(interp, pRet);
275e1ab2193Sdan return TCL_OK;
276e1ab2193Sdan }
277e1ab2193Sdan
Sqlitetest_init_Init(Tcl_Interp * interp)278e1ab2193Sdan int Sqlitetest_init_Init(Tcl_Interp *interp){
279e1ab2193Sdan static struct {
280e1ab2193Sdan char *zName;
281e1ab2193Sdan Tcl_ObjCmdProc *xProc;
282e1ab2193Sdan } aObjCmd[] = {
283e1ab2193Sdan {"init_wrapper_install", init_wrapper_install},
284e1ab2193Sdan {"init_wrapper_query", init_wrapper_query },
285e1ab2193Sdan {"init_wrapper_uninstall", init_wrapper_uninstall},
286e1ab2193Sdan {"init_wrapper_clear", init_wrapper_clear}
287e1ab2193Sdan };
288e1ab2193Sdan int i;
289e1ab2193Sdan
290e1ab2193Sdan for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
291e1ab2193Sdan Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
292e1ab2193Sdan }
293e1ab2193Sdan
294e1ab2193Sdan return TCL_OK;
295e1ab2193Sdan }
296