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_methods2 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, int c){
127: return wrapped.pcache.xCreate(a, b, c);
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 sqlite3_pcache_page *wrPCacheFetch(sqlite3_pcache *p, unsigned a, int b){
136: return wrapped.pcache.xFetch(p, a, b);
137: }
138: static void wrPCacheUnpin(sqlite3_pcache *p, sqlite3_pcache_page *a, int b){
139: wrapped.pcache.xUnpin(p, a, b);
140: }
141: static void wrPCacheRekey(
142: sqlite3_pcache *p,
143: sqlite3_pcache_page *a,
144: unsigned b,
145: unsigned c
146: ){
147: wrapped.pcache.xRekey(p, a, b, c);
148: }
149: static void wrPCacheTruncate(sqlite3_pcache *p, unsigned a){
150: wrapped.pcache.xTruncate(p, a);
151: }
152: static void wrPCacheDestroy(sqlite3_pcache *p){
153: wrapped.pcache.xDestroy(p);
154: }
155:
156: static void installInitWrappers(void){
157: sqlite3_mutex_methods mutexmethods = {
158: wrMutexInit, wrMutexEnd, wrMutexAlloc,
159: wrMutexFree, wrMutexEnter, wrMutexTry,
160: wrMutexLeave, wrMutexHeld, wrMutexNotheld
161: };
162: sqlite3_pcache_methods2 pcachemethods = {
163: 1, 0,
164: wrPCacheInit, wrPCacheShutdown, wrPCacheCreate,
165: wrPCacheCachesize, wrPCachePagecount, wrPCacheFetch,
166: wrPCacheUnpin, wrPCacheRekey, wrPCacheTruncate,
167: wrPCacheDestroy
168: };
169: sqlite3_mem_methods memmethods = {
170: wrMemMalloc, wrMemFree, wrMemRealloc,
171: wrMemSize, wrMemRoundup, wrMemInit,
172: wrMemShutdown,
173: 0
174: };
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:
187: static int 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, "\"");
205: return TCL_ERROR;
206: }
207: }
208: return TCL_OK;
209: }
210:
211: static int 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: memset(&wrapped, 0, sizeof(&wrapped));
223: sqlite3_shutdown();
224: sqlite3_config(SQLITE_CONFIG_MUTEX, &wrapped.mutex);
225: sqlite3_config(SQLITE_CONFIG_MALLOC, &wrapped.mem);
226: sqlite3_config(SQLITE_CONFIG_PCACHE2, &wrapped.pcache);
227: return TCL_OK;
228: }
229:
230: static int init_wrapper_clear(
231: ClientData clientData, /* Unused */
232: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
233: int objc, /* Number of arguments */
234: Tcl_Obj *CONST objv[] /* Command arguments */
235: ){
236: if( objc!=1 ){
237: Tcl_WrongNumArgs(interp, 1, objv, "");
238: return TCL_ERROR;
239: }
240:
241: wrapped.mem_fail = 0;
242: wrapped.mutex_fail = 0;
243: wrapped.pcache_fail = 0;
244: return TCL_OK;
245: }
246:
247: static int init_wrapper_query(
248: ClientData clientData, /* Unused */
249: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
250: int objc, /* Number of arguments */
251: Tcl_Obj *CONST objv[] /* Command arguments */
252: ){
253: Tcl_Obj *pRet;
254:
255: if( objc!=1 ){
256: Tcl_WrongNumArgs(interp, 1, objv, "");
257: return TCL_ERROR;
258: }
259:
260: pRet = Tcl_NewObj();
261: if( wrapped.mutex_init ){
262: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("mutex", -1));
263: }
264: if( wrapped.mem_init ){
265: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("mem", -1));
266: }
267: if( wrapped.pcache_init ){
268: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("pcache", -1));
269: }
270:
271: Tcl_SetObjResult(interp, pRet);
272: return TCL_OK;
273: }
274:
275: int Sqlitetest_init_Init(Tcl_Interp *interp){
276: static struct {
277: char *zName;
278: Tcl_ObjCmdProc *xProc;
279: } aObjCmd[] = {
280: {"init_wrapper_install", init_wrapper_install},
281: {"init_wrapper_query", init_wrapper_query },
282: {"init_wrapper_uninstall", init_wrapper_uninstall},
283: {"init_wrapper_clear", init_wrapper_clear}
284: };
285: int i;
286:
287: for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
288: Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
289: }
290:
291: return TCL_OK;
292: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>