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

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

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

Powered by Google App Engine
This is Rietveld 408576698