Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(555)

Side by Side Diff: third_party/sqlite/sqlite-src-3080704/src/test_malloc.c

Issue 2363173002: [sqlite] Remove obsolete reference version 3.8.7.4. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 ** 2007 August 15
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 ** This file contains code used to implement test interfaces to the
14 ** memory allocation subsystem.
15 */
16 #include "sqliteInt.h"
17 #include "tcl.h"
18 #include <stdlib.h>
19 #include <string.h>
20 #include <assert.h>
21
22 /*
23 ** This structure is used to encapsulate the global state variables used
24 ** by malloc() fault simulation.
25 */
26 static struct MemFault {
27 int iCountdown; /* Number of pending successes before a failure */
28 int nRepeat; /* Number of times to repeat the failure */
29 int nBenign; /* Number of benign failures seen since last config */
30 int nFail; /* Number of failures seen since last config */
31 u8 enable; /* True if enabled */
32 int isInstalled; /* True if the fault simulation layer is installed */
33 int isBenignMode; /* True if malloc failures are considered benign */
34 sqlite3_mem_methods m; /* 'Real' malloc implementation */
35 } memfault;
36
37 /*
38 ** This routine exists as a place to set a breakpoint that will
39 ** fire on any simulated malloc() failure.
40 */
41 static void sqlite3Fault(void){
42 static int cnt = 0;
43 cnt++;
44 }
45
46 /*
47 ** Check to see if a fault should be simulated. Return true to simulate
48 ** the fault. Return false if the fault should not be simulated.
49 */
50 static int faultsimStep(void){
51 if( likely(!memfault.enable) ){
52 return 0;
53 }
54 if( memfault.iCountdown>0 ){
55 memfault.iCountdown--;
56 return 0;
57 }
58 sqlite3Fault();
59 memfault.nFail++;
60 if( memfault.isBenignMode>0 ){
61 memfault.nBenign++;
62 }
63 memfault.nRepeat--;
64 if( memfault.nRepeat<=0 ){
65 memfault.enable = 0;
66 }
67 return 1;
68 }
69
70 /*
71 ** A version of sqlite3_mem_methods.xMalloc() that includes fault simulation
72 ** logic.
73 */
74 static void *faultsimMalloc(int n){
75 void *p = 0;
76 if( !faultsimStep() ){
77 p = memfault.m.xMalloc(n);
78 }
79 return p;
80 }
81
82
83 /*
84 ** A version of sqlite3_mem_methods.xRealloc() that includes fault simulation
85 ** logic.
86 */
87 static void *faultsimRealloc(void *pOld, int n){
88 void *p = 0;
89 if( !faultsimStep() ){
90 p = memfault.m.xRealloc(pOld, n);
91 }
92 return p;
93 }
94
95 /*
96 ** The following method calls are passed directly through to the underlying
97 ** malloc system:
98 **
99 ** xFree
100 ** xSize
101 ** xRoundup
102 ** xInit
103 ** xShutdown
104 */
105 static void faultsimFree(void *p){
106 memfault.m.xFree(p);
107 }
108 static int faultsimSize(void *p){
109 return memfault.m.xSize(p);
110 }
111 static int faultsimRoundup(int n){
112 return memfault.m.xRoundup(n);
113 }
114 static int faultsimInit(void *p){
115 return memfault.m.xInit(memfault.m.pAppData);
116 }
117 static void faultsimShutdown(void *p){
118 memfault.m.xShutdown(memfault.m.pAppData);
119 }
120
121 /*
122 ** This routine configures the malloc failure simulation. After
123 ** calling this routine, the next nDelay mallocs will succeed, followed
124 ** by a block of nRepeat failures, after which malloc() calls will begin
125 ** to succeed again.
126 */
127 static void faultsimConfig(int nDelay, int nRepeat){
128 memfault.iCountdown = nDelay;
129 memfault.nRepeat = nRepeat;
130 memfault.nBenign = 0;
131 memfault.nFail = 0;
132 memfault.enable = nDelay>=0;
133
134 /* Sometimes, when running multi-threaded tests, the isBenignMode
135 ** variable is not properly incremented/decremented so that it is
136 ** 0 when not inside a benign malloc block. This doesn't affect
137 ** the multi-threaded tests, as they do not use this system. But
138 ** it does affect OOM tests run later in the same process. So
139 ** zero the variable here, just to be sure.
140 */
141 memfault.isBenignMode = 0;
142 }
143
144 /*
145 ** Return the number of faults (both hard and benign faults) that have
146 ** occurred since the injector was last configured.
147 */
148 static int faultsimFailures(void){
149 return memfault.nFail;
150 }
151
152 /*
153 ** Return the number of benign faults that have occurred since the
154 ** injector was last configured.
155 */
156 static int faultsimBenignFailures(void){
157 return memfault.nBenign;
158 }
159
160 /*
161 ** Return the number of successes that will occur before the next failure.
162 ** If no failures are scheduled, return -1.
163 */
164 static int faultsimPending(void){
165 if( memfault.enable ){
166 return memfault.iCountdown;
167 }else{
168 return -1;
169 }
170 }
171
172
173 static void faultsimBeginBenign(void){
174 memfault.isBenignMode++;
175 }
176 static void faultsimEndBenign(void){
177 memfault.isBenignMode--;
178 }
179
180 /*
181 ** Add or remove the fault-simulation layer using sqlite3_config(). If
182 ** the argument is non-zero, the
183 */
184 static int faultsimInstall(int install){
185 static struct sqlite3_mem_methods m = {
186 faultsimMalloc, /* xMalloc */
187 faultsimFree, /* xFree */
188 faultsimRealloc, /* xRealloc */
189 faultsimSize, /* xSize */
190 faultsimRoundup, /* xRoundup */
191 faultsimInit, /* xInit */
192 faultsimShutdown, /* xShutdown */
193 0 /* pAppData */
194 };
195 int rc;
196
197 install = (install ? 1 : 0);
198 assert(memfault.isInstalled==1 || memfault.isInstalled==0);
199
200 if( install==memfault.isInstalled ){
201 return SQLITE_ERROR;
202 }
203
204 if( install ){
205 rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
206 assert(memfault.m.xMalloc);
207 if( rc==SQLITE_OK ){
208 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
209 }
210 sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,
211 faultsimBeginBenign, faultsimEndBenign
212 );
213 }else{
214 sqlite3_mem_methods m;
215 assert(memfault.m.xMalloc);
216
217 /* One should be able to reset the default memory allocator by storing
218 ** a zeroed allocator then calling GETMALLOC. */
219 memset(&m, 0, sizeof(m));
220 sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
221 sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m);
222 assert( memcmp(&m, &memfault.m, sizeof(m))==0 );
223
224 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);
225 sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 0, 0);
226 }
227
228 if( rc==SQLITE_OK ){
229 memfault.isInstalled = 1;
230 }
231 return rc;
232 }
233
234 #ifdef SQLITE_TEST
235
236 /*
237 ** This function is implemented in main.c. Returns a pointer to a static
238 ** buffer containing the symbolic SQLite error code that corresponds to
239 ** the least-significant 8-bits of the integer passed as an argument.
240 ** For example:
241 **
242 ** sqlite3ErrName(1) -> "SQLITE_ERROR"
243 */
244 extern const char *sqlite3ErrName(int);
245
246 /*
247 ** Transform pointers to text and back again
248 */
249 static void pointerToText(void *p, char *z){
250 static const char zHex[] = "0123456789abcdef";
251 int i, k;
252 unsigned int u;
253 sqlite3_uint64 n;
254 if( p==0 ){
255 strcpy(z, "0");
256 return;
257 }
258 if( sizeof(n)==sizeof(p) ){
259 memcpy(&n, &p, sizeof(p));
260 }else if( sizeof(u)==sizeof(p) ){
261 memcpy(&u, &p, sizeof(u));
262 n = u;
263 }else{
264 assert( 0 );
265 }
266 for(i=0, k=sizeof(p)*2-1; i<sizeof(p)*2; i++, k--){
267 z[k] = zHex[n&0xf];
268 n >>= 4;
269 }
270 z[sizeof(p)*2] = 0;
271 }
272 static int hexToInt(int h){
273 if( h>='0' && h<='9' ){
274 return h - '0';
275 }else if( h>='a' && h<='f' ){
276 return h - 'a' + 10;
277 }else{
278 return -1;
279 }
280 }
281 static int textToPointer(const char *z, void **pp){
282 sqlite3_uint64 n = 0;
283 int i;
284 unsigned int u;
285 for(i=0; i<sizeof(void*)*2 && z[0]; i++){
286 int v;
287 v = hexToInt(*z++);
288 if( v<0 ) return TCL_ERROR;
289 n = n*16 + v;
290 }
291 if( *z!=0 ) return TCL_ERROR;
292 if( sizeof(n)==sizeof(*pp) ){
293 memcpy(pp, &n, sizeof(n));
294 }else if( sizeof(u)==sizeof(*pp) ){
295 u = (unsigned int)n;
296 memcpy(pp, &u, sizeof(u));
297 }else{
298 assert( 0 );
299 }
300 return TCL_OK;
301 }
302
303 /*
304 ** Usage: sqlite3_malloc NBYTES
305 **
306 ** Raw test interface for sqlite3_malloc().
307 */
308 static int test_malloc(
309 void * clientData,
310 Tcl_Interp *interp,
311 int objc,
312 Tcl_Obj *CONST objv[]
313 ){
314 int nByte;
315 void *p;
316 char zOut[100];
317 if( objc!=2 ){
318 Tcl_WrongNumArgs(interp, 1, objv, "NBYTES");
319 return TCL_ERROR;
320 }
321 if( Tcl_GetIntFromObj(interp, objv[1], &nByte) ) return TCL_ERROR;
322 p = sqlite3_malloc((unsigned)nByte);
323 pointerToText(p, zOut);
324 Tcl_AppendResult(interp, zOut, NULL);
325 return TCL_OK;
326 }
327
328 /*
329 ** Usage: sqlite3_realloc PRIOR NBYTES
330 **
331 ** Raw test interface for sqlite3_realloc().
332 */
333 static int test_realloc(
334 void * clientData,
335 Tcl_Interp *interp,
336 int objc,
337 Tcl_Obj *CONST objv[]
338 ){
339 int nByte;
340 void *pPrior, *p;
341 char zOut[100];
342 if( objc!=3 ){
343 Tcl_WrongNumArgs(interp, 1, objv, "PRIOR NBYTES");
344 return TCL_ERROR;
345 }
346 if( Tcl_GetIntFromObj(interp, objv[2], &nByte) ) return TCL_ERROR;
347 if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){
348 Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
349 return TCL_ERROR;
350 }
351 p = sqlite3_realloc(pPrior, (unsigned)nByte);
352 pointerToText(p, zOut);
353 Tcl_AppendResult(interp, zOut, NULL);
354 return TCL_OK;
355 }
356
357 /*
358 ** Usage: sqlite3_free PRIOR
359 **
360 ** Raw test interface for sqlite3_free().
361 */
362 static int test_free(
363 void * clientData,
364 Tcl_Interp *interp,
365 int objc,
366 Tcl_Obj *CONST objv[]
367 ){
368 void *pPrior;
369 if( objc!=2 ){
370 Tcl_WrongNumArgs(interp, 1, objv, "PRIOR");
371 return TCL_ERROR;
372 }
373 if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){
374 Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
375 return TCL_ERROR;
376 }
377 sqlite3_free(pPrior);
378 return TCL_OK;
379 }
380
381 /*
382 ** These routines are in test_hexio.c
383 */
384 int sqlite3TestHexToBin(const char *, int, char *);
385 int sqlite3TestBinToHex(char*,int);
386
387 /*
388 ** Usage: memset ADDRESS SIZE HEX
389 **
390 ** Set a chunk of memory (obtained from malloc, probably) to a
391 ** specified hex pattern.
392 */
393 static int test_memset(
394 void * clientData,
395 Tcl_Interp *interp,
396 int objc,
397 Tcl_Obj *CONST objv[]
398 ){
399 void *p;
400 int size, n, i;
401 char *zHex;
402 char *zOut;
403 char zBin[100];
404
405 if( objc!=4 ){
406 Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE HEX");
407 return TCL_ERROR;
408 }
409 if( textToPointer(Tcl_GetString(objv[1]), &p) ){
410 Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
411 return TCL_ERROR;
412 }
413 if( Tcl_GetIntFromObj(interp, objv[2], &size) ){
414 return TCL_ERROR;
415 }
416 if( size<=0 ){
417 Tcl_AppendResult(interp, "size must be positive", (char*)0);
418 return TCL_ERROR;
419 }
420 zHex = Tcl_GetStringFromObj(objv[3], &n);
421 if( n>sizeof(zBin)*2 ) n = sizeof(zBin)*2;
422 n = sqlite3TestHexToBin(zHex, n, zBin);
423 if( n==0 ){
424 Tcl_AppendResult(interp, "no data", (char*)0);
425 return TCL_ERROR;
426 }
427 zOut = p;
428 for(i=0; i<size; i++){
429 zOut[i] = zBin[i%n];
430 }
431 return TCL_OK;
432 }
433
434 /*
435 ** Usage: memget ADDRESS SIZE
436 **
437 ** Return memory as hexadecimal text.
438 */
439 static int test_memget(
440 void * clientData,
441 Tcl_Interp *interp,
442 int objc,
443 Tcl_Obj *CONST objv[]
444 ){
445 void *p;
446 int size, n;
447 char *zBin;
448 char zHex[100];
449
450 if( objc!=3 ){
451 Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE");
452 return TCL_ERROR;
453 }
454 if( textToPointer(Tcl_GetString(objv[1]), &p) ){
455 Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);
456 return TCL_ERROR;
457 }
458 if( Tcl_GetIntFromObj(interp, objv[2], &size) ){
459 return TCL_ERROR;
460 }
461 if( size<=0 ){
462 Tcl_AppendResult(interp, "size must be positive", (char*)0);
463 return TCL_ERROR;
464 }
465 zBin = p;
466 while( size>0 ){
467 if( size>(sizeof(zHex)-1)/2 ){
468 n = (sizeof(zHex)-1)/2;
469 }else{
470 n = size;
471 }
472 memcpy(zHex, zBin, n);
473 zBin += n;
474 size -= n;
475 sqlite3TestBinToHex(zHex, n);
476 Tcl_AppendResult(interp, zHex, (char*)0);
477 }
478 return TCL_OK;
479 }
480
481 /*
482 ** Usage: sqlite3_memory_used
483 **
484 ** Raw test interface for sqlite3_memory_used().
485 */
486 static int test_memory_used(
487 void * clientData,
488 Tcl_Interp *interp,
489 int objc,
490 Tcl_Obj *CONST objv[]
491 ){
492 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_memory_used()));
493 return TCL_OK;
494 }
495
496 /*
497 ** Usage: sqlite3_memory_highwater ?RESETFLAG?
498 **
499 ** Raw test interface for sqlite3_memory_highwater().
500 */
501 static int test_memory_highwater(
502 void * clientData,
503 Tcl_Interp *interp,
504 int objc,
505 Tcl_Obj *CONST objv[]
506 ){
507 int resetFlag = 0;
508 if( objc!=1 && objc!=2 ){
509 Tcl_WrongNumArgs(interp, 1, objv, "?RESET?");
510 return TCL_ERROR;
511 }
512 if( objc==2 ){
513 if( Tcl_GetBooleanFromObj(interp, objv[1], &resetFlag) ) return TCL_ERROR;
514 }
515 Tcl_SetObjResult(interp,
516 Tcl_NewWideIntObj(sqlite3_memory_highwater(resetFlag)));
517 return TCL_OK;
518 }
519
520 /*
521 ** Usage: sqlite3_memdebug_backtrace DEPTH
522 **
523 ** Set the depth of backtracing. If SQLITE_MEMDEBUG is not defined
524 ** then this routine is a no-op.
525 */
526 static int test_memdebug_backtrace(
527 void * clientData,
528 Tcl_Interp *interp,
529 int objc,
530 Tcl_Obj *CONST objv[]
531 ){
532 int depth;
533 if( objc!=2 ){
534 Tcl_WrongNumArgs(interp, 1, objv, "DEPT");
535 return TCL_ERROR;
536 }
537 if( Tcl_GetIntFromObj(interp, objv[1], &depth) ) return TCL_ERROR;
538 #ifdef SQLITE_MEMDEBUG
539 {
540 extern void sqlite3MemdebugBacktrace(int);
541 sqlite3MemdebugBacktrace(depth);
542 }
543 #endif
544 return TCL_OK;
545 }
546
547 /*
548 ** Usage: sqlite3_memdebug_dump FILENAME
549 **
550 ** Write a summary of unfreed memory to FILENAME.
551 */
552 static int test_memdebug_dump(
553 void * clientData,
554 Tcl_Interp *interp,
555 int objc,
556 Tcl_Obj *CONST objv[]
557 ){
558 if( objc!=2 ){
559 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
560 return TCL_ERROR;
561 }
562 #if defined(SQLITE_MEMDEBUG) || defined(SQLITE_MEMORY_SIZE) \
563 || defined(SQLITE_POW2_MEMORY_SIZE)
564 {
565 extern void sqlite3MemdebugDump(const char*);
566 sqlite3MemdebugDump(Tcl_GetString(objv[1]));
567 }
568 #endif
569 return TCL_OK;
570 }
571
572 /*
573 ** Usage: sqlite3_memdebug_malloc_count
574 **
575 ** Return the total number of times malloc() has been called.
576 */
577 static int test_memdebug_malloc_count(
578 void * clientData,
579 Tcl_Interp *interp,
580 int objc,
581 Tcl_Obj *CONST objv[]
582 ){
583 int nMalloc = -1;
584 if( objc!=1 ){
585 Tcl_WrongNumArgs(interp, 1, objv, "");
586 return TCL_ERROR;
587 }
588 #if defined(SQLITE_MEMDEBUG)
589 {
590 extern int sqlite3MemdebugMallocCount();
591 nMalloc = sqlite3MemdebugMallocCount();
592 }
593 #endif
594 Tcl_SetObjResult(interp, Tcl_NewIntObj(nMalloc));
595 return TCL_OK;
596 }
597
598
599 /*
600 ** Usage: sqlite3_memdebug_fail COUNTER ?OPTIONS?
601 **
602 ** where options are:
603 **
604 ** -repeat <count>
605 ** -benigncnt <varname>
606 **
607 ** Arrange for a simulated malloc() failure after COUNTER successes.
608 ** If a repeat count is specified, the fault is repeated that many
609 ** times.
610 **
611 ** Each call to this routine overrides the prior counter value.
612 ** This routine returns the number of simulated failures that have
613 ** happened since the previous call to this routine.
614 **
615 ** To disable simulated failures, use a COUNTER of -1.
616 */
617 static int test_memdebug_fail(
618 void * clientData,
619 Tcl_Interp *interp,
620 int objc,
621 Tcl_Obj *CONST objv[]
622 ){
623 int ii;
624 int iFail;
625 int nRepeat = 1;
626 Tcl_Obj *pBenignCnt = 0;
627 int nBenign;
628 int nFail = 0;
629
630 if( objc<2 ){
631 Tcl_WrongNumArgs(interp, 1, objv, "COUNTER ?OPTIONS?");
632 return TCL_ERROR;
633 }
634 if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR;
635
636 for(ii=2; ii<objc; ii+=2){
637 int nOption;
638 char *zOption = Tcl_GetStringFromObj(objv[ii], &nOption);
639 char *zErr = 0;
640
641 if( nOption>1 && strncmp(zOption, "-repeat", nOption)==0 ){
642 if( ii==(objc-1) ){
643 zErr = "option requires an argument: ";
644 }else{
645 if( Tcl_GetIntFromObj(interp, objv[ii+1], &nRepeat) ){
646 return TCL_ERROR;
647 }
648 }
649 }else if( nOption>1 && strncmp(zOption, "-benigncnt", nOption)==0 ){
650 if( ii==(objc-1) ){
651 zErr = "option requires an argument: ";
652 }else{
653 pBenignCnt = objv[ii+1];
654 }
655 }else{
656 zErr = "unknown option: ";
657 }
658
659 if( zErr ){
660 Tcl_AppendResult(interp, zErr, zOption, 0);
661 return TCL_ERROR;
662 }
663 }
664
665 nBenign = faultsimBenignFailures();
666 nFail = faultsimFailures();
667 faultsimConfig(iFail, nRepeat);
668
669 if( pBenignCnt ){
670 Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0);
671 }
672 Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail));
673 return TCL_OK;
674 }
675
676 /*
677 ** Usage: sqlite3_memdebug_pending
678 **
679 ** Return the number of malloc() calls that will succeed before a
680 ** simulated failure occurs. A negative return value indicates that
681 ** no malloc() failure is scheduled.
682 */
683 static int test_memdebug_pending(
684 void * clientData,
685 Tcl_Interp *interp,
686 int objc,
687 Tcl_Obj *CONST objv[]
688 ){
689 int nPending;
690 if( objc!=1 ){
691 Tcl_WrongNumArgs(interp, 1, objv, "");
692 return TCL_ERROR;
693 }
694 nPending = faultsimPending();
695 Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending));
696 return TCL_OK;
697 }
698
699 /*
700 ** The following global variable keeps track of the number of tests
701 ** that have run. This variable is only useful when running in the
702 ** debugger.
703 */
704 static int sqlite3_memdebug_title_count = 0;
705
706 /*
707 ** Usage: sqlite3_memdebug_settitle TITLE
708 **
709 ** Set a title string stored with each allocation. The TITLE is
710 ** typically the name of the test that was running when the
711 ** allocation occurred. The TITLE is stored with the allocation
712 ** and can be used to figure out which tests are leaking memory.
713 **
714 ** Each title overwrite the previous.
715 */
716 static int test_memdebug_settitle(
717 void * clientData,
718 Tcl_Interp *interp,
719 int objc,
720 Tcl_Obj *CONST objv[]
721 ){
722 sqlite3_memdebug_title_count++;
723 if( objc!=2 ){
724 Tcl_WrongNumArgs(interp, 1, objv, "TITLE");
725 return TCL_ERROR;
726 }
727 #ifdef SQLITE_MEMDEBUG
728 {
729 const char *zTitle;
730 extern int sqlite3MemdebugSettitle(const char*);
731 zTitle = Tcl_GetString(objv[1]);
732 sqlite3MemdebugSettitle(zTitle);
733 }
734 #endif
735 return TCL_OK;
736 }
737
738 #define MALLOC_LOG_FRAMES 10
739 #define MALLOC_LOG_KEYINTS ( \
740 10 * ((sizeof(int)>=sizeof(void*)) ? 1 : sizeof(void*)/sizeof(int)) \
741 )
742 static Tcl_HashTable aMallocLog;
743 static int mallocLogEnabled = 0;
744
745 typedef struct MallocLog MallocLog;
746 struct MallocLog {
747 int nCall;
748 int nByte;
749 };
750
751 #ifdef SQLITE_MEMDEBUG
752 static void test_memdebug_callback(int nByte, int nFrame, void **aFrame){
753 if( mallocLogEnabled ){
754 MallocLog *pLog;
755 Tcl_HashEntry *pEntry;
756 int isNew;
757
758 int aKey[MALLOC_LOG_KEYINTS];
759 unsigned int nKey = sizeof(int)*MALLOC_LOG_KEYINTS;
760
761 memset(aKey, 0, nKey);
762 if( (sizeof(void*)*nFrame)<nKey ){
763 nKey = nFrame*sizeof(void*);
764 }
765 memcpy(aKey, aFrame, nKey);
766
767 pEntry = Tcl_CreateHashEntry(&aMallocLog, (const char *)aKey, &isNew);
768 if( isNew ){
769 pLog = (MallocLog *)Tcl_Alloc(sizeof(MallocLog));
770 memset(pLog, 0, sizeof(MallocLog));
771 Tcl_SetHashValue(pEntry, (ClientData)pLog);
772 }else{
773 pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
774 }
775
776 pLog->nCall++;
777 pLog->nByte += nByte;
778 }
779 }
780 #endif /* SQLITE_MEMDEBUG */
781
782 static void test_memdebug_log_clear(void){
783 Tcl_HashSearch search;
784 Tcl_HashEntry *pEntry;
785 for(
786 pEntry=Tcl_FirstHashEntry(&aMallocLog, &search);
787 pEntry;
788 pEntry=Tcl_NextHashEntry(&search)
789 ){
790 MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
791 Tcl_Free((char *)pLog);
792 }
793 Tcl_DeleteHashTable(&aMallocLog);
794 Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS);
795 }
796
797 static int test_memdebug_log(
798 void * clientData,
799 Tcl_Interp *interp,
800 int objc,
801 Tcl_Obj *CONST objv[]
802 ){
803 static int isInit = 0;
804 int iSub;
805
806 static const char *MB_strs[] = { "start", "stop", "dump", "clear", "sync" };
807 enum MB_enum {
808 MB_LOG_START, MB_LOG_STOP, MB_LOG_DUMP, MB_LOG_CLEAR, MB_LOG_SYNC
809 };
810
811 if( !isInit ){
812 #ifdef SQLITE_MEMDEBUG
813 extern void sqlite3MemdebugBacktraceCallback(
814 void (*xBacktrace)(int, int, void **));
815 sqlite3MemdebugBacktraceCallback(test_memdebug_callback);
816 #endif
817 Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS);
818 isInit = 1;
819 }
820
821 if( objc<2 ){
822 Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");
823 }
824 if( Tcl_GetIndexFromObj(interp, objv[1], MB_strs, "sub-command", 0, &iSub) ){
825 return TCL_ERROR;
826 }
827
828 switch( (enum MB_enum)iSub ){
829 case MB_LOG_START:
830 mallocLogEnabled = 1;
831 break;
832 case MB_LOG_STOP:
833 mallocLogEnabled = 0;
834 break;
835 case MB_LOG_DUMP: {
836 Tcl_HashSearch search;
837 Tcl_HashEntry *pEntry;
838 Tcl_Obj *pRet = Tcl_NewObj();
839
840 assert(sizeof(Tcl_WideInt)>=sizeof(void*));
841
842 for(
843 pEntry=Tcl_FirstHashEntry(&aMallocLog, &search);
844 pEntry;
845 pEntry=Tcl_NextHashEntry(&search)
846 ){
847 Tcl_Obj *apElem[MALLOC_LOG_FRAMES+2];
848 MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry);
849 Tcl_WideInt *aKey = (Tcl_WideInt *)Tcl_GetHashKey(&aMallocLog, pEntry);
850 int ii;
851
852 apElem[0] = Tcl_NewIntObj(pLog->nCall);
853 apElem[1] = Tcl_NewIntObj(pLog->nByte);
854 for(ii=0; ii<MALLOC_LOG_FRAMES; ii++){
855 apElem[ii+2] = Tcl_NewWideIntObj(aKey[ii]);
856 }
857
858 Tcl_ListObjAppendElement(interp, pRet,
859 Tcl_NewListObj(MALLOC_LOG_FRAMES+2, apElem)
860 );
861 }
862
863 Tcl_SetObjResult(interp, pRet);
864 break;
865 }
866 case MB_LOG_CLEAR: {
867 test_memdebug_log_clear();
868 break;
869 }
870
871 case MB_LOG_SYNC: {
872 #ifdef SQLITE_MEMDEBUG
873 extern void sqlite3MemdebugSync();
874 test_memdebug_log_clear();
875 mallocLogEnabled = 1;
876 sqlite3MemdebugSync();
877 #endif
878 break;
879 }
880 }
881
882 return TCL_OK;
883 }
884
885 /*
886 ** Usage: sqlite3_config_scratch SIZE N
887 **
888 ** Set the scratch memory buffer using SQLITE_CONFIG_SCRATCH.
889 ** The buffer is static and is of limited size. N might be
890 ** adjusted downward as needed to accommodate the requested size.
891 ** The revised value of N is returned.
892 **
893 ** A negative SIZE causes the buffer pointer to be NULL.
894 */
895 static int test_config_scratch(
896 void * clientData,
897 Tcl_Interp *interp,
898 int objc,
899 Tcl_Obj *CONST objv[]
900 ){
901 int sz, N, rc;
902 Tcl_Obj *pResult;
903 static char *buf = 0;
904 if( objc!=3 ){
905 Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");
906 return TCL_ERROR;
907 }
908 if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
909 if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR;
910 free(buf);
911 if( sz<0 ){
912 buf = 0;
913 rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, 0, 0, 0);
914 }else{
915 buf = malloc( sz*N + 1 );
916 rc = sqlite3_config(SQLITE_CONFIG_SCRATCH, buf, sz, N);
917 }
918 pResult = Tcl_NewObj();
919 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
920 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N));
921 Tcl_SetObjResult(interp, pResult);
922 return TCL_OK;
923 }
924
925 /*
926 ** Usage: sqlite3_config_pagecache SIZE N
927 **
928 ** Set the page-cache memory buffer using SQLITE_CONFIG_PAGECACHE.
929 ** The buffer is static and is of limited size. N might be
930 ** adjusted downward as needed to accommodate the requested size.
931 ** The revised value of N is returned.
932 **
933 ** A negative SIZE causes the buffer pointer to be NULL.
934 */
935 static int test_config_pagecache(
936 void * clientData,
937 Tcl_Interp *interp,
938 int objc,
939 Tcl_Obj *CONST objv[]
940 ){
941 int sz, N, rc;
942 Tcl_Obj *pResult;
943 static char *buf = 0;
944 if( objc!=3 ){
945 Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");
946 return TCL_ERROR;
947 }
948 if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
949 if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR;
950 free(buf);
951 if( sz<0 ){
952 buf = 0;
953 rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, 0, 0, 0);
954 }else{
955 buf = malloc( sz*N );
956 rc = sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N);
957 }
958 pResult = Tcl_NewObj();
959 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
960 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(N));
961 Tcl_SetObjResult(interp, pResult);
962 return TCL_OK;
963 }
964
965 /*
966 ** Usage: sqlite3_config_alt_pcache INSTALL_FLAG DISCARD_CHANCE PRNG_SEED
967 **
968 ** Set up the alternative test page cache. Install if INSTALL_FLAG is
969 ** true and uninstall (reverting to the default page cache) if INSTALL_FLAG
970 ** is false. DISCARD_CHANGE is an integer between 0 and 100 inclusive
971 ** which determines the chance of discarding a page when unpinned. 100
972 ** is certainty. 0 is never. PRNG_SEED is the pseudo-random number generator
973 ** seed.
974 */
975 static int test_alt_pcache(
976 void * clientData,
977 Tcl_Interp *interp,
978 int objc,
979 Tcl_Obj *CONST objv[]
980 ){
981 int installFlag;
982 int discardChance = 0;
983 int prngSeed = 0;
984 int highStress = 0;
985 extern void installTestPCache(int,unsigned,unsigned,unsigned);
986 if( objc<2 || objc>5 ){
987 Tcl_WrongNumArgs(interp, 1, objv,
988 "INSTALLFLAG DISCARDCHANCE PRNGSEEED HIGHSTRESS");
989 return TCL_ERROR;
990 }
991 if( Tcl_GetIntFromObj(interp, objv[1], &installFlag) ) return TCL_ERROR;
992 if( objc>=3 && Tcl_GetIntFromObj(interp, objv[2], &discardChance) ){
993 return TCL_ERROR;
994 }
995 if( objc>=4 && Tcl_GetIntFromObj(interp, objv[3], &prngSeed) ){
996 return TCL_ERROR;
997 }
998 if( objc>=5 && Tcl_GetIntFromObj(interp, objv[4], &highStress) ){
999 return TCL_ERROR;
1000 }
1001 if( discardChance<0 || discardChance>100 ){
1002 Tcl_AppendResult(interp, "discard-chance should be between 0 and 100",
1003 (char*)0);
1004 return TCL_ERROR;
1005 }
1006 installTestPCache(installFlag, (unsigned)discardChance, (unsigned)prngSeed,
1007 (unsigned)highStress);
1008 return TCL_OK;
1009 }
1010
1011 /*
1012 ** Usage: sqlite3_config_memstatus BOOLEAN
1013 **
1014 ** Enable or disable memory status reporting using SQLITE_CONFIG_MEMSTATUS.
1015 */
1016 static int test_config_memstatus(
1017 void * clientData,
1018 Tcl_Interp *interp,
1019 int objc,
1020 Tcl_Obj *CONST objv[]
1021 ){
1022 int enable, rc;
1023 if( objc!=2 ){
1024 Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
1025 return TCL_ERROR;
1026 }
1027 if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ) return TCL_ERROR;
1028 rc = sqlite3_config(SQLITE_CONFIG_MEMSTATUS, enable);
1029 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
1030 return TCL_OK;
1031 }
1032
1033 /*
1034 ** Usage: sqlite3_config_lookaside SIZE COUNT
1035 **
1036 */
1037 static int test_config_lookaside(
1038 void * clientData,
1039 Tcl_Interp *interp,
1040 int objc,
1041 Tcl_Obj *CONST objv[]
1042 ){
1043 int sz, cnt;
1044 Tcl_Obj *pRet;
1045 if( objc!=3 ){
1046 Tcl_WrongNumArgs(interp, 1, objv, "SIZE COUNT");
1047 return TCL_ERROR;
1048 }
1049 if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;
1050 if( Tcl_GetIntFromObj(interp, objv[2], &cnt) ) return TCL_ERROR;
1051 pRet = Tcl_NewObj();
1052 Tcl_ListObjAppendElement(
1053 interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.szLookaside)
1054 );
1055 Tcl_ListObjAppendElement(
1056 interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.nLookaside)
1057 );
1058 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, cnt);
1059 Tcl_SetObjResult(interp, pRet);
1060 return TCL_OK;
1061 }
1062
1063
1064 /*
1065 ** Usage: sqlite3_db_config_lookaside CONNECTION BUFID SIZE COUNT
1066 **
1067 ** There are two static buffers with BUFID 1 and 2. Each static buffer
1068 ** is 10KB in size. A BUFID of 0 indicates that the buffer should be NULL
1069 ** which will cause sqlite3_db_config() to allocate space on its own.
1070 */
1071 static int test_db_config_lookaside(
1072 void * clientData,
1073 Tcl_Interp *interp,
1074 int objc,
1075 Tcl_Obj *CONST objv[]
1076 ){
1077 int rc;
1078 int sz, cnt;
1079 sqlite3 *db;
1080 int bufid;
1081 static char azBuf[2][10000];
1082 extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
1083 if( objc!=5 ){
1084 Tcl_WrongNumArgs(interp, 1, objv, "BUFID SIZE COUNT");
1085 return TCL_ERROR;
1086 }
1087 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1088 if( Tcl_GetIntFromObj(interp, objv[2], &bufid) ) return TCL_ERROR;
1089 if( Tcl_GetIntFromObj(interp, objv[3], &sz) ) return TCL_ERROR;
1090 if( Tcl_GetIntFromObj(interp, objv[4], &cnt) ) return TCL_ERROR;
1091 if( bufid==0 ){
1092 rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, 0, sz, cnt);
1093 }else if( bufid>=1 && bufid<=2 && sz*cnt<=sizeof(azBuf[0]) ){
1094 rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, azBuf[bufid], sz,cnt);
1095 }else{
1096 Tcl_AppendResult(interp, "illegal arguments - see documentation", (char*)0);
1097 return TCL_ERROR;
1098 }
1099 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
1100 return TCL_OK;
1101 }
1102
1103 /*
1104 ** Usage: sqlite3_config_heap NBYTE NMINALLOC
1105 */
1106 static int test_config_heap(
1107 void * clientData,
1108 Tcl_Interp *interp,
1109 int objc,
1110 Tcl_Obj *CONST objv[]
1111 ){
1112 static char *zBuf; /* Use this memory */
1113 int nByte; /* Size of buffer to pass to sqlite3_config() */
1114 int nMinAlloc; /* Size of minimum allocation */
1115 int rc; /* Return code of sqlite3_config() */
1116
1117 Tcl_Obj * CONST *aArg = &objv[1];
1118 int nArg = objc-1;
1119
1120 if( nArg!=2 ){
1121 Tcl_WrongNumArgs(interp, 1, objv, "NBYTE NMINALLOC");
1122 return TCL_ERROR;
1123 }
1124 if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR;
1125 if( Tcl_GetIntFromObj(interp, aArg[1], &nMinAlloc) ) return TCL_ERROR;
1126
1127 if( nByte==0 ){
1128 free( zBuf );
1129 zBuf = 0;
1130 rc = sqlite3_config(SQLITE_CONFIG_HEAP, (void*)0, 0, 0);
1131 }else{
1132 zBuf = realloc(zBuf, nByte);
1133 rc = sqlite3_config(SQLITE_CONFIG_HEAP, zBuf, nByte, nMinAlloc);
1134 }
1135
1136 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1137 return TCL_OK;
1138 }
1139
1140 /*
1141 ** Usage: sqlite3_config_heap_size NBYTE
1142 */
1143 static int test_config_heap_size(
1144 void * clientData,
1145 Tcl_Interp *interp,
1146 int objc,
1147 Tcl_Obj *CONST objv[]
1148 ){
1149 int nByte; /* Size to pass to sqlite3_config() */
1150 int rc; /* Return code of sqlite3_config() */
1151
1152 Tcl_Obj * CONST *aArg = &objv[1];
1153 int nArg = objc-1;
1154
1155 if( nArg!=1 ){
1156 Tcl_WrongNumArgs(interp, 1, objv, "NBYTE");
1157 return TCL_ERROR;
1158 }
1159 if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR;
1160
1161 rc = sqlite3_config(SQLITE_CONFIG_WIN32_HEAPSIZE, nByte);
1162
1163 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1164 return TCL_OK;
1165 }
1166
1167 /*
1168 ** Usage: sqlite3_config_error [DB]
1169 **
1170 ** Invoke sqlite3_config() or sqlite3_db_config() with invalid
1171 ** opcodes and verify that they return errors.
1172 */
1173 static int test_config_error(
1174 void * clientData,
1175 Tcl_Interp *interp,
1176 int objc,
1177 Tcl_Obj *CONST objv[]
1178 ){
1179 sqlite3 *db;
1180 extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
1181
1182 if( objc!=2 && objc!=1 ){
1183 Tcl_WrongNumArgs(interp, 1, objv, "[DB]");
1184 return TCL_ERROR;
1185 }
1186 if( objc==2 ){
1187 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1188 if( sqlite3_db_config(db, 99999)!=SQLITE_ERROR ){
1189 Tcl_AppendResult(interp,
1190 "sqlite3_db_config(db, 99999) does not return SQLITE_ERROR",
1191 (char*)0);
1192 return TCL_ERROR;
1193 }
1194 }else{
1195 if( sqlite3_config(99999)!=SQLITE_ERROR ){
1196 Tcl_AppendResult(interp,
1197 "sqlite3_config(99999) does not return SQLITE_ERROR",
1198 (char*)0);
1199 return TCL_ERROR;
1200 }
1201 }
1202 return TCL_OK;
1203 }
1204
1205 /*
1206 ** Usage: sqlite3_config_uri BOOLEAN
1207 **
1208 ** Enables or disables interpretation of URI parameters by default using
1209 ** SQLITE_CONFIG_URI.
1210 */
1211 static int test_config_uri(
1212 void * clientData,
1213 Tcl_Interp *interp,
1214 int objc,
1215 Tcl_Obj *CONST objv[]
1216 ){
1217 int rc;
1218 int bOpenUri;
1219
1220 if( objc!=2 ){
1221 Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
1222 return TCL_ERROR;
1223 }
1224 if( Tcl_GetBooleanFromObj(interp, objv[1], &bOpenUri) ){
1225 return TCL_ERROR;
1226 }
1227
1228 rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri);
1229 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1230
1231 return TCL_OK;
1232 }
1233
1234 /*
1235 ** Usage: sqlite3_config_cis BOOLEAN
1236 **
1237 ** Enables or disables the use of the covering-index scan optimization.
1238 ** SQLITE_CONFIG_COVERING_INDEX_SCAN.
1239 */
1240 static int test_config_cis(
1241 void * clientData,
1242 Tcl_Interp *interp,
1243 int objc,
1244 Tcl_Obj *CONST objv[]
1245 ){
1246 int rc;
1247 int bUseCis;
1248
1249 if( objc!=2 ){
1250 Tcl_WrongNumArgs(interp, 1, objv, "BOOL");
1251 return TCL_ERROR;
1252 }
1253 if( Tcl_GetBooleanFromObj(interp, objv[1], &bUseCis) ){
1254 return TCL_ERROR;
1255 }
1256
1257 rc = sqlite3_config(SQLITE_CONFIG_COVERING_INDEX_SCAN, bUseCis);
1258 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1259
1260 return TCL_OK;
1261 }
1262
1263
1264 /*
1265 ** Usage: sqlite3_dump_memsys3 FILENAME
1266 ** sqlite3_dump_memsys5 FILENAME
1267 **
1268 ** Write a summary of unfreed memsys3 allocations to FILENAME.
1269 */
1270 static int test_dump_memsys3(
1271 void * clientData,
1272 Tcl_Interp *interp,
1273 int objc,
1274 Tcl_Obj *CONST objv[]
1275 ){
1276 if( objc!=2 ){
1277 Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");
1278 return TCL_ERROR;
1279 }
1280
1281 switch( SQLITE_PTR_TO_INT(clientData) ){
1282 case 3: {
1283 #ifdef SQLITE_ENABLE_MEMSYS3
1284 extern void sqlite3Memsys3Dump(const char*);
1285 sqlite3Memsys3Dump(Tcl_GetString(objv[1]));
1286 break;
1287 #endif
1288 }
1289 case 5: {
1290 #ifdef SQLITE_ENABLE_MEMSYS5
1291 extern void sqlite3Memsys5Dump(const char*);
1292 sqlite3Memsys5Dump(Tcl_GetString(objv[1]));
1293 break;
1294 #endif
1295 }
1296 }
1297 return TCL_OK;
1298 }
1299
1300 /*
1301 ** Usage: sqlite3_status OPCODE RESETFLAG
1302 **
1303 ** Return a list of three elements which are the sqlite3_status() return
1304 ** code, the current value, and the high-water mark value.
1305 */
1306 static int test_status(
1307 void * clientData,
1308 Tcl_Interp *interp,
1309 int objc,
1310 Tcl_Obj *CONST objv[]
1311 ){
1312 int rc, iValue, mxValue;
1313 int i, op, resetFlag;
1314 const char *zOpName;
1315 static const struct {
1316 const char *zName;
1317 int op;
1318 } aOp[] = {
1319 { "SQLITE_STATUS_MEMORY_USED", SQLITE_STATUS_MEMORY_USED },
1320 { "SQLITE_STATUS_MALLOC_SIZE", SQLITE_STATUS_MALLOC_SIZE },
1321 { "SQLITE_STATUS_PAGECACHE_USED", SQLITE_STATUS_PAGECACHE_USED },
1322 { "SQLITE_STATUS_PAGECACHE_OVERFLOW", SQLITE_STATUS_PAGECACHE_OVERFLOW },
1323 { "SQLITE_STATUS_PAGECACHE_SIZE", SQLITE_STATUS_PAGECACHE_SIZE },
1324 { "SQLITE_STATUS_SCRATCH_USED", SQLITE_STATUS_SCRATCH_USED },
1325 { "SQLITE_STATUS_SCRATCH_OVERFLOW", SQLITE_STATUS_SCRATCH_OVERFLOW },
1326 { "SQLITE_STATUS_SCRATCH_SIZE", SQLITE_STATUS_SCRATCH_SIZE },
1327 { "SQLITE_STATUS_PARSER_STACK", SQLITE_STATUS_PARSER_STACK },
1328 { "SQLITE_STATUS_MALLOC_COUNT", SQLITE_STATUS_MALLOC_COUNT },
1329 };
1330 Tcl_Obj *pResult;
1331 if( objc!=3 ){
1332 Tcl_WrongNumArgs(interp, 1, objv, "PARAMETER RESETFLAG");
1333 return TCL_ERROR;
1334 }
1335 zOpName = Tcl_GetString(objv[1]);
1336 for(i=0; i<ArraySize(aOp); i++){
1337 if( strcmp(aOp[i].zName, zOpName)==0 ){
1338 op = aOp[i].op;
1339 break;
1340 }
1341 }
1342 if( i>=ArraySize(aOp) ){
1343 if( Tcl_GetIntFromObj(interp, objv[1], &op) ) return TCL_ERROR;
1344 }
1345 if( Tcl_GetBooleanFromObj(interp, objv[2], &resetFlag) ) return TCL_ERROR;
1346 iValue = 0;
1347 mxValue = 0;
1348 rc = sqlite3_status(op, &iValue, &mxValue, resetFlag);
1349 pResult = Tcl_NewObj();
1350 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
1351 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue));
1352 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue));
1353 Tcl_SetObjResult(interp, pResult);
1354 return TCL_OK;
1355 }
1356
1357 /*
1358 ** Usage: sqlite3_db_status DATABASE OPCODE RESETFLAG
1359 **
1360 ** Return a list of three elements which are the sqlite3_db_status() return
1361 ** code, the current value, and the high-water mark value.
1362 */
1363 static int test_db_status(
1364 void * clientData,
1365 Tcl_Interp *interp,
1366 int objc,
1367 Tcl_Obj *CONST objv[]
1368 ){
1369 int rc, iValue, mxValue;
1370 int i, op, resetFlag;
1371 const char *zOpName;
1372 sqlite3 *db;
1373 extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
1374 static const struct {
1375 const char *zName;
1376 int op;
1377 } aOp[] = {
1378 { "LOOKASIDE_USED", SQLITE_DBSTATUS_LOOKASIDE_USED },
1379 { "CACHE_USED", SQLITE_DBSTATUS_CACHE_USED },
1380 { "SCHEMA_USED", SQLITE_DBSTATUS_SCHEMA_USED },
1381 { "STMT_USED", SQLITE_DBSTATUS_STMT_USED },
1382 { "LOOKASIDE_HIT", SQLITE_DBSTATUS_LOOKASIDE_HIT },
1383 { "LOOKASIDE_MISS_SIZE", SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE },
1384 { "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL },
1385 { "CACHE_HIT", SQLITE_DBSTATUS_CACHE_HIT },
1386 { "CACHE_MISS", SQLITE_DBSTATUS_CACHE_MISS },
1387 { "CACHE_WRITE", SQLITE_DBSTATUS_CACHE_WRITE },
1388 { "DEFERRED_FKS", SQLITE_DBSTATUS_DEFERRED_FKS }
1389 };
1390 Tcl_Obj *pResult;
1391 if( objc!=4 ){
1392 Tcl_WrongNumArgs(interp, 1, objv, "DB PARAMETER RESETFLAG");
1393 return TCL_ERROR;
1394 }
1395 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1396 zOpName = Tcl_GetString(objv[2]);
1397 if( memcmp(zOpName, "SQLITE_", 7)==0 ) zOpName += 7;
1398 if( memcmp(zOpName, "DBSTATUS_", 9)==0 ) zOpName += 9;
1399 for(i=0; i<ArraySize(aOp); i++){
1400 if( strcmp(aOp[i].zName, zOpName)==0 ){
1401 op = aOp[i].op;
1402 break;
1403 }
1404 }
1405 if( i>=ArraySize(aOp) ){
1406 if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR;
1407 }
1408 if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR;
1409 iValue = 0;
1410 mxValue = 0;
1411 rc = sqlite3_db_status(db, op, &iValue, &mxValue, resetFlag);
1412 pResult = Tcl_NewObj();
1413 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(rc));
1414 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(iValue));
1415 Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(mxValue));
1416 Tcl_SetObjResult(interp, pResult);
1417 return TCL_OK;
1418 }
1419
1420 /*
1421 ** install_malloc_faultsim BOOLEAN
1422 */
1423 static int test_install_malloc_faultsim(
1424 void * clientData,
1425 Tcl_Interp *interp,
1426 int objc,
1427 Tcl_Obj *CONST objv[]
1428 ){
1429 int rc;
1430 int isInstall;
1431
1432 if( objc!=2 ){
1433 Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
1434 return TCL_ERROR;
1435 }
1436 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[1], &isInstall) ){
1437 return TCL_ERROR;
1438 }
1439 rc = faultsimInstall(isInstall);
1440 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1441 return TCL_OK;
1442 }
1443
1444 /*
1445 ** sqlite3_install_memsys3
1446 */
1447 static int test_install_memsys3(
1448 void * clientData,
1449 Tcl_Interp *interp,
1450 int objc,
1451 Tcl_Obj *CONST objv[]
1452 ){
1453 int rc = SQLITE_MISUSE;
1454 #ifdef SQLITE_ENABLE_MEMSYS3
1455 const sqlite3_mem_methods *sqlite3MemGetMemsys3(void);
1456 rc = sqlite3_config(SQLITE_CONFIG_MALLOC, sqlite3MemGetMemsys3());
1457 #endif
1458 Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
1459 return TCL_OK;
1460 }
1461
1462 static int test_vfs_oom_test(
1463 void * clientData,
1464 Tcl_Interp *interp,
1465 int objc,
1466 Tcl_Obj *CONST objv[]
1467 ){
1468 extern int sqlite3_memdebug_vfs_oom_test;
1469 if( objc>2 ){
1470 Tcl_WrongNumArgs(interp, 1, objv, "?INTEGER?");
1471 return TCL_ERROR;
1472 }else if( objc==2 ){
1473 int iNew;
1474 if( Tcl_GetIntFromObj(interp, objv[1], &iNew) ) return TCL_ERROR;
1475 sqlite3_memdebug_vfs_oom_test = iNew;
1476 }
1477 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_memdebug_vfs_oom_test));
1478 return TCL_OK;
1479 }
1480
1481 /*
1482 ** Register commands with the TCL interpreter.
1483 */
1484 int Sqlitetest_malloc_Init(Tcl_Interp *interp){
1485 static struct {
1486 char *zName;
1487 Tcl_ObjCmdProc *xProc;
1488 int clientData;
1489 } aObjCmd[] = {
1490 { "sqlite3_malloc", test_malloc ,0 },
1491 { "sqlite3_realloc", test_realloc ,0 },
1492 { "sqlite3_free", test_free ,0 },
1493 { "memset", test_memset ,0 },
1494 { "memget", test_memget ,0 },
1495 { "sqlite3_memory_used", test_memory_used ,0 },
1496 { "sqlite3_memory_highwater", test_memory_highwater ,0 },
1497 { "sqlite3_memdebug_backtrace", test_memdebug_backtrace ,0 },
1498 { "sqlite3_memdebug_dump", test_memdebug_dump ,0 },
1499 { "sqlite3_memdebug_fail", test_memdebug_fail ,0 },
1500 { "sqlite3_memdebug_pending", test_memdebug_pending ,0 },
1501 { "sqlite3_memdebug_settitle", test_memdebug_settitle ,0 },
1502 { "sqlite3_memdebug_malloc_count", test_memdebug_malloc_count ,0 },
1503 { "sqlite3_memdebug_log", test_memdebug_log ,0 },
1504 { "sqlite3_config_scratch", test_config_scratch ,0 },
1505 { "sqlite3_config_pagecache", test_config_pagecache ,0 },
1506 { "sqlite3_config_alt_pcache", test_alt_pcache ,0 },
1507 { "sqlite3_status", test_status ,0 },
1508 { "sqlite3_db_status", test_db_status ,0 },
1509 { "install_malloc_faultsim", test_install_malloc_faultsim ,0 },
1510 { "sqlite3_config_heap", test_config_heap ,0 },
1511 { "sqlite3_config_heap_size", test_config_heap_size ,0 },
1512 { "sqlite3_config_memstatus", test_config_memstatus ,0 },
1513 { "sqlite3_config_lookaside", test_config_lookaside ,0 },
1514 { "sqlite3_config_error", test_config_error ,0 },
1515 { "sqlite3_config_uri", test_config_uri ,0 },
1516 { "sqlite3_config_cis", test_config_cis ,0 },
1517 { "sqlite3_db_config_lookaside",test_db_config_lookaside ,0 },
1518 { "sqlite3_dump_memsys3", test_dump_memsys3 ,3 },
1519 { "sqlite3_dump_memsys5", test_dump_memsys3 ,5 },
1520 { "sqlite3_install_memsys3", test_install_memsys3 ,0 },
1521 { "sqlite3_memdebug_vfs_oom_test", test_vfs_oom_test ,0 },
1522 };
1523 int i;
1524 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
1525 ClientData c = (ClientData)SQLITE_INT_TO_PTR(aObjCmd[i].clientData);
1526 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, c, 0);
1527 }
1528 return TCL_OK;
1529 }
1530 #endif
OLDNEW
« no previous file with comments | « third_party/sqlite/sqlite-src-3080704/src/test_loadext.c ('k') | third_party/sqlite/sqlite-src-3080704/src/test_multiplex.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698