Team Ai
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 10mo agoView on Hugging Face
0likes
test_malloc.c1514 linesDownload Raw Back to src
1/*2** 2007 August 153**4** The author disclaims copyright to this source code.  In place of5** 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 the14** memory allocation subsystem.15*/16#include "sqliteInt.h"17#include "tclsqlite.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*/26static 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  int nOkBefore;          /* Successful allocations prior to the first fault */32  int nOkAfter;           /* Successful allocations after a fault */33  u8 enable;              /* True if enabled */34  int isInstalled;        /* True if the fault simulation layer is installed */35  int isBenignMode;       /* True if malloc failures are considered benign */36  sqlite3_mem_methods m;  /* 'Real' malloc implementation */37} memfault;38 39/*40** This routine exists as a place to set a breakpoint that will41** fire on any simulated malloc() failure.42*/43static void sqlite3Fault(void){44  static u64 cnt = 0;45  cnt++;46  if( cnt>((u64)1<<63) ) abort();47}48 49/*50** This routine exists as a place to set a breakpoint that will51** fire the first time any malloc() fails on a single test case.52** The sqlite3Fault() routine above runs on every malloc() failure.53** This routine only runs on the first such failure.54*/55static void sqlite3FirstFault(void){56  static u64 cnt2 = 0;57  cnt2++;58  if( cnt2>((u64)1<<63) ) abort();59}60 61/*62** Check to see if a fault should be simulated.  Return true to simulate63** the fault.  Return false if the fault should not be simulated.64*/65static int faultsimStep(void){66  if( likely(!memfault.enable) ){67    memfault.nOkAfter++;68    return 0;69  }70  if( memfault.iCountdown>0 ){71    memfault.iCountdown--;72    memfault.nOkBefore++;73    return 0;74  }75  if( memfault.nFail==0 ) sqlite3FirstFault();76  sqlite3Fault();77  memfault.nFail++;78  if( memfault.isBenignMode>0 ){79    memfault.nBenign++;80  }81  memfault.nRepeat--;82  if( memfault.nRepeat<=0 ){83    memfault.enable = 0;84  }85  return 1;  86}87 88/*89** A version of sqlite3_mem_methods.xMalloc() that includes fault simulation90** logic.91*/92static void *faultsimMalloc(int n){93  void *p = 0;94  if( !faultsimStep() ){95    p = memfault.m.xMalloc(n);96  }97  return p;98}99 100 101/*102** A version of sqlite3_mem_methods.xRealloc() that includes fault simulation103** logic.104*/105static void *faultsimRealloc(void *pOld, int n){106  void *p = 0;107  if( !faultsimStep() ){108    p = memfault.m.xRealloc(pOld, n);109  }110  return p;111}112 113/*114** This routine configures the malloc failure simulation.  After115** calling this routine, the next nDelay mallocs will succeed, followed116** by a block of nRepeat failures, after which malloc() calls will begin117** to succeed again.118*/119static void faultsimConfig(int nDelay, int nRepeat){120  memfault.iCountdown = nDelay;121  memfault.nRepeat = nRepeat;122  memfault.nBenign = 0;123  memfault.nFail = 0;124  memfault.nOkBefore = 0;125  memfault.nOkAfter = 0;126  memfault.enable = nDelay>=0;127 128  /* Sometimes, when running multi-threaded tests, the isBenignMode 129  ** variable is not properly incremented/decremented so that it is130  ** 0 when not inside a benign malloc block. This doesn't affect131  ** the multi-threaded tests, as they do not use this system. But132  ** it does affect OOM tests run later in the same process. So133  ** zero the variable here, just to be sure.134  */135  memfault.isBenignMode = 0;136}137 138/*139** Return the number of faults (both hard and benign faults) that have140** occurred since the injector was last configured.141*/142static int faultsimFailures(void){143  return memfault.nFail;144}145 146/*147** Return the number of benign faults that have occurred since the148** injector was last configured.149*/150static int faultsimBenignFailures(void){151  return memfault.nBenign;152}153 154/*155** Return the number of successes that will occur before the next failure.156** If no failures are scheduled, return -1.157*/158static int faultsimPending(void){159  if( memfault.enable ){160    return memfault.iCountdown;161  }else{162    return -1;163  }164}165 166 167static void faultsimBeginBenign(void){168  memfault.isBenignMode++;169}170static void faultsimEndBenign(void){171  memfault.isBenignMode--;172}173 174/*175** Add or remove the fault-simulation layer using sqlite3_config(). If176** the argument is non-zero, the 177*/178static int faultsimInstall(int install){179  int rc;180 181  install = (install ? 1 : 0);182  assert(memfault.isInstalled==1 || memfault.isInstalled==0);183 184  if( install==memfault.isInstalled ){185    return SQLITE_ERROR;186  }187 188  if( install ){189    rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);190    assert(memfault.m.xMalloc);191    if( rc==SQLITE_OK ){192      sqlite3_mem_methods m = memfault.m;193      m.xMalloc = faultsimMalloc;194      m.xRealloc = faultsimRealloc;195      rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);196    }197    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, 198        faultsimBeginBenign, faultsimEndBenign199    );200  }else{201    sqlite3_mem_methods m2;202    assert(memfault.m.xMalloc);203 204    /* One should be able to reset the default memory allocator by storing205    ** a zeroed allocator then calling GETMALLOC. */206    memset(&m2, 0, sizeof(m2));207    sqlite3_config(SQLITE_CONFIG_MALLOC, &m2);208    sqlite3_config(SQLITE_CONFIG_GETMALLOC, &m2);209    assert( memcmp(&m2, &memfault.m, sizeof(m2))==0 );210 211    rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &memfault.m);212    sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,213        (void*)0, (void*)0);214  }215 216  if( rc==SQLITE_OK ){217    memfault.isInstalled = 1;218  }219  return rc;220}221 222#ifdef SQLITE_TEST223 224/*225** This function is implemented in main.c. Returns a pointer to a static226** buffer containing the symbolic SQLite error code that corresponds to227** the least-significant 8-bits of the integer passed as an argument.228** For example:229**230**   sqlite3ErrName(1) -> "SQLITE_ERROR"231*/232extern const char *sqlite3ErrName(int);233 234/*235** Transform pointers to text and back again236*/237static void pointerToText(void *p, char *z){238  static const char zHex[] = "0123456789abcdef";239  int i, k;240  unsigned int u;241  sqlite3_uint64 n;242  if( p==0 ){243    strcpy(z, "0");244    return;245  }246  if( sizeof(n)==sizeof(p) ){247    memcpy(&n, &p, sizeof(p));248  }else if( sizeof(u)==sizeof(p) ){249    memcpy(&u, &p, sizeof(u));250    n = u;251  }else{252    assert( 0 );253  }254  for(i=0, k=sizeof(p)*2-1; i<sizeof(p)*2; i++, k--){255    z[k] = zHex[n&0xf];256    n >>= 4;257  }258  z[sizeof(p)*2] = 0;259}260static int hexToInt(int h){261  if( h>='0' && h<='9' ){262    return h - '0';263  }else if( h>='a' && h<='f' ){264    return h - 'a' + 10;265  }else{266    return -1;267  }268}269static int textToPointer(const char *z, void **pp){270  sqlite3_uint64 n = 0;271  int i;272  unsigned int u;273  for(i=0; i<sizeof(void*)*2 && z[0]; i++){274    int v;275    v = hexToInt(*z++);276    if( v<0 ) return TCL_ERROR;277    n = n*16 + v;278  }279  if( *z!=0 ) return TCL_ERROR;280  if( sizeof(n)==sizeof(*pp) ){281    memcpy(pp, &n, sizeof(n));282  }else if( sizeof(u)==sizeof(*pp) ){283    u = (unsigned int)n;284    memcpy(pp, &u, sizeof(u));285  }else{286    assert( 0 );287  }288  return TCL_OK;289}290 291/*292** Usage:    sqlite3_malloc  NBYTES293**294** Raw test interface for sqlite3_malloc().295*/296static int SQLITE_TCLAPI test_malloc(297  void * clientData,298  Tcl_Interp *interp,299  int objc,300  Tcl_Obj *CONST objv[]301){302  int nByte;303  void *p;304  char zOut[100];305  if( objc!=2 ){306    Tcl_WrongNumArgs(interp, 1, objv, "NBYTES");307    return TCL_ERROR;308  }309  if( Tcl_GetIntFromObj(interp, objv[1], &nByte) ) return TCL_ERROR;310  p = sqlite3_malloc((unsigned)nByte);311  pointerToText(p, zOut);312  Tcl_AppendResult(interp, zOut, NULL);313  return TCL_OK;314}315 316/*317** Usage:    sqlite3_realloc  PRIOR  NBYTES318**319** Raw test interface for sqlite3_realloc().320*/321static int SQLITE_TCLAPI test_realloc(322  void * clientData,323  Tcl_Interp *interp,324  int objc,325  Tcl_Obj *CONST objv[]326){327  int nByte;328  void *pPrior, *p;329  char zOut[100];330  if( objc!=3 ){331    Tcl_WrongNumArgs(interp, 1, objv, "PRIOR NBYTES");332    return TCL_ERROR;333  }334  if( Tcl_GetIntFromObj(interp, objv[2], &nByte) ) return TCL_ERROR;335  if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){336    Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);337    return TCL_ERROR;338  }339  p = sqlite3_realloc(pPrior, (unsigned)nByte);340  pointerToText(p, zOut);341  Tcl_AppendResult(interp, zOut, NULL);342  return TCL_OK;343}344 345/*346** Usage:    sqlite3_free  PRIOR347**348** Raw test interface for sqlite3_free().349*/350static int SQLITE_TCLAPI test_free(351  void * clientData,352  Tcl_Interp *interp,353  int objc,354  Tcl_Obj *CONST objv[]355){356  void *pPrior;357  if( objc!=2 ){358    Tcl_WrongNumArgs(interp, 1, objv, "PRIOR");359    return TCL_ERROR;360  }361  if( textToPointer(Tcl_GetString(objv[1]), &pPrior) ){362    Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);363    return TCL_ERROR;364  }365  sqlite3_free(pPrior);366  return TCL_OK;367}368 369/*370** These routines are in test_hexio.c371*/372int sqlite3TestHexToBin(const char *, int, char *);373int sqlite3TestBinToHex(char*,int);374 375/*376** Usage:    memset  ADDRESS  SIZE  HEX377**378** Set a chunk of memory (obtained from malloc, probably) to a379** specified hex pattern.380*/381static int SQLITE_TCLAPI test_memset(382  void * clientData,383  Tcl_Interp *interp,384  int objc,385  Tcl_Obj *CONST objv[]386){387  void *p;388  int size, i;389  Tcl_Size n;390  char *zHex;391  char *zOut;392  char zBin[100];393 394  if( objc!=4 ){395    Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE HEX");396    return TCL_ERROR;397  }398  if( textToPointer(Tcl_GetString(objv[1]), &p) ){399    Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);400    return TCL_ERROR;401  }402  if( Tcl_GetIntFromObj(interp, objv[2], &size) ){403    return TCL_ERROR;404  }405  if( size<=0 ){406    Tcl_AppendResult(interp, "size must be positive", (char*)0);407    return TCL_ERROR;408  }409  zHex = Tcl_GetStringFromObj(objv[3], &n);410  if( n>sizeof(zBin)*2 ) n = sizeof(zBin)*2;411  n = sqlite3TestHexToBin(zHex, (int)n, zBin);412  if( n==0 ){413    Tcl_AppendResult(interp, "no data", (char*)0);414    return TCL_ERROR;415  }416  zOut = p;417  for(i=0; i<size; i++){418    zOut[i] = zBin[i%n];419  }420  return TCL_OK;421}422 423/*424** Usage:    memget  ADDRESS  SIZE425**426** Return memory as hexadecimal text.427*/428static int SQLITE_TCLAPI test_memget(429  void * clientData,430  Tcl_Interp *interp,431  int objc,432  Tcl_Obj *CONST objv[]433){434  void *p;435  int size, n;436  char *zBin;437  char zHex[100];438 439  if( objc!=3 ){440    Tcl_WrongNumArgs(interp, 1, objv, "ADDRESS SIZE");441    return TCL_ERROR;442  }443  if( textToPointer(Tcl_GetString(objv[1]), &p) ){444    Tcl_AppendResult(interp, "bad pointer: ", Tcl_GetString(objv[1]), (char*)0);445    return TCL_ERROR;446  }447  if( Tcl_GetIntFromObj(interp, objv[2], &size) ){448    return TCL_ERROR;449  }450  if( size<=0 ){451    Tcl_AppendResult(interp, "size must be positive", (char*)0);452    return TCL_ERROR;453  }454  zBin = p;455  while( size>0 ){456    if( size>(sizeof(zHex)-1)/2 ){457      n = (sizeof(zHex)-1)/2;458    }else{459      n = size;460    }461    memcpy(zHex, zBin, n);462    zBin += n;463    size -= n;464    sqlite3TestBinToHex(zHex, n);465    Tcl_AppendResult(interp, zHex, (char*)0);466  }467  return TCL_OK;468}469 470/*471** Usage:    sqlite3_memory_used472**473** Raw test interface for sqlite3_memory_used().474*/475static int SQLITE_TCLAPI test_memory_used(476  void * clientData,477  Tcl_Interp *interp,478  int objc,479  Tcl_Obj *CONST objv[]480){481  Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_memory_used()));482  return TCL_OK;483}484 485/*486** Usage:    sqlite3_memory_highwater ?RESETFLAG?487**488** Raw test interface for sqlite3_memory_highwater().489*/490static int SQLITE_TCLAPI test_memory_highwater(491  void * clientData,492  Tcl_Interp *interp,493  int objc,494  Tcl_Obj *CONST objv[]495){496  int resetFlag = 0;497  if( objc!=1 && objc!=2 ){498    Tcl_WrongNumArgs(interp, 1, objv, "?RESET?");499    return TCL_ERROR;500  }501  if( objc==2 ){502    if( Tcl_GetBooleanFromObj(interp, objv[1], &resetFlag) ) return TCL_ERROR;503  } 504  Tcl_SetObjResult(interp, 505     Tcl_NewWideIntObj(sqlite3_memory_highwater(resetFlag)));506  return TCL_OK;507}508 509/*510** Usage:    sqlite3_memdebug_backtrace DEPTH511**512** Set the depth of backtracing.  If SQLITE_MEMDEBUG is not defined513** then this routine is a no-op.514*/515static int SQLITE_TCLAPI test_memdebug_backtrace(516  void * clientData,517  Tcl_Interp *interp,518  int objc,519  Tcl_Obj *CONST objv[]520){521  int depth;522  if( objc!=2 ){523    Tcl_WrongNumArgs(interp, 1, objv, "DEPT");524    return TCL_ERROR;525  }526  if( Tcl_GetIntFromObj(interp, objv[1], &depth) ) return TCL_ERROR;527#ifdef SQLITE_MEMDEBUG528  {529    extern void sqlite3MemdebugBacktrace(int);530    sqlite3MemdebugBacktrace(depth);531  }532#endif533  return TCL_OK;534}535 536/*537** Usage:    sqlite3_memdebug_dump  FILENAME538**539** Write a summary of unfreed memory to FILENAME.540*/541static int SQLITE_TCLAPI test_memdebug_dump(542  void * clientData,543  Tcl_Interp *interp,544  int objc,545  Tcl_Obj *CONST objv[]546){547  if( objc!=2 ){548    Tcl_WrongNumArgs(interp, 1, objv, "FILENAME");549    return TCL_ERROR;550  }551#if defined(SQLITE_MEMDEBUG) || defined(SQLITE_MEMORY_SIZE) \552     || defined(SQLITE_POW2_MEMORY_SIZE)553  {554    extern void sqlite3MemdebugDump(const char*);555    sqlite3MemdebugDump(Tcl_GetString(objv[1]));556  }557#endif558  return TCL_OK;559}560 561/*562** Usage:    sqlite3_memdebug_malloc_count563**564** Return the total number of times malloc() has been called.565*/566static int SQLITE_TCLAPI test_memdebug_malloc_count(567  void * clientData,568  Tcl_Interp *interp,569  int objc,570  Tcl_Obj *CONST objv[]571){572  int nMalloc = -1;573  if( objc!=1 ){574    Tcl_WrongNumArgs(interp, 1, objv, "");575    return TCL_ERROR;576  }577#if defined(SQLITE_MEMDEBUG)578  {579    extern int sqlite3MemdebugMallocCount();580    nMalloc = sqlite3MemdebugMallocCount();581  }582#endif583  Tcl_SetObjResult(interp, Tcl_NewIntObj(nMalloc));584  return TCL_OK;585}586 587 588/*589** Usage:    sqlite3_memdebug_fail  COUNTER  ?OPTIONS?590**591** where options are:592**593**     -repeat    <count>594**     -benigncnt <varname>595**596** Arrange for a simulated malloc() failure after COUNTER successes.597** If a repeat count is specified, the fault is repeated that many598** times.599**600** Each call to this routine overrides the prior counter value.601** This routine returns the number of simulated failures that have602** happened since the previous call to this routine.603**604** To disable simulated failures, use a COUNTER of -1.605*/606static int SQLITE_TCLAPI test_memdebug_fail(607  void * clientData,608  Tcl_Interp *interp,609  int objc,610  Tcl_Obj *CONST objv[]611){612  int ii;613  int iFail;614  int nRepeat = 1;615  Tcl_Obj *pBenignCnt = 0;616  int nBenign;617  int nFail = 0;618 619  if( objc<2 ){620    Tcl_WrongNumArgs(interp, 1, objv, "COUNTER ?OPTIONS?");621    return TCL_ERROR;622  }623  if( Tcl_GetIntFromObj(interp, objv[1], &iFail) ) return TCL_ERROR;624 625  for(ii=2; ii<objc; ii+=2){626    Tcl_Size nOption;627    char *zOption = Tcl_GetStringFromObj(objv[ii], &nOption);628    char *zErr = 0;629 630    if( nOption>1 && strncmp(zOption, "-repeat", nOption)==0 ){631      if( ii==(objc-1) ){632        zErr = "option requires an argument: ";633      }else{634        if( Tcl_GetIntFromObj(interp, objv[ii+1], &nRepeat) ){635          return TCL_ERROR;636        }637      }638    }else if( nOption>1 && strncmp(zOption, "-benigncnt", nOption)==0 ){639      if( ii==(objc-1) ){640        zErr = "option requires an argument: ";641      }else{642        pBenignCnt = objv[ii+1];643      }644    }else{645      zErr = "unknown option: ";646    }647 648    if( zErr ){649      Tcl_AppendResult(interp, zErr, zOption, NULL);650      return TCL_ERROR;651    }652  }653  654  nBenign = faultsimBenignFailures();655  nFail = faultsimFailures();656  faultsimConfig(iFail, nRepeat);657 658  if( pBenignCnt ){659    Tcl_ObjSetVar2(interp, pBenignCnt, 0, Tcl_NewIntObj(nBenign), 0);660  }661  Tcl_SetObjResult(interp, Tcl_NewIntObj(nFail));662  return TCL_OK;663}664 665/*666** Usage:    sqlite3_memdebug_pending667**668** Return the number of malloc() calls that will succeed before a 669** simulated failure occurs. A negative return value indicates that670** no malloc() failure is scheduled.671*/672static int SQLITE_TCLAPI test_memdebug_pending(673  void * clientData,674  Tcl_Interp *interp,675  int objc,676  Tcl_Obj *CONST objv[]677){678  int nPending;679  if( objc!=1 ){680    Tcl_WrongNumArgs(interp, 1, objv, "");681    return TCL_ERROR;682  }683  nPending = faultsimPending();684  Tcl_SetObjResult(interp, Tcl_NewIntObj(nPending));685  return TCL_OK;686}687 688/*689** The following global variable keeps track of the number of tests690** that have run.  This variable is only useful when running in the691** debugger.692*/693static int sqlite3_memdebug_title_count = 0;694 695/*696** Usage:    sqlite3_memdebug_settitle TITLE697**698** Set a title string stored with each allocation.  The TITLE is699** typically the name of the test that was running when the700** allocation occurred.  The TITLE is stored with the allocation701** and can be used to figure out which tests are leaking memory.702**703** Each title overwrite the previous.704*/705static int SQLITE_TCLAPI test_memdebug_settitle(706  void * clientData,707  Tcl_Interp *interp,708  int objc,709  Tcl_Obj *CONST objv[]710){711  sqlite3_memdebug_title_count++;712  if( objc!=2 ){713    Tcl_WrongNumArgs(interp, 1, objv, "TITLE");714    return TCL_ERROR;715  }716#ifdef SQLITE_MEMDEBUG717  {718    const char *zTitle;719    extern int sqlite3MemdebugSettitle(const char*);720    zTitle = Tcl_GetString(objv[1]);721    sqlite3MemdebugSettitle(zTitle);722  }723#endif724  return TCL_OK;725}726 727#define MALLOC_LOG_FRAMES  10 728#define MALLOC_LOG_KEYINTS (                                              \729    10 * ((sizeof(int)>=sizeof(void*)) ? 1 : sizeof(void*)/sizeof(int))   \730)731static Tcl_HashTable aMallocLog;732static int mallocLogEnabled = 0;733 734typedef struct MallocLog MallocLog;735struct MallocLog {736  int nCall;737  int nByte;738};739 740#ifdef SQLITE_MEMDEBUG741static void test_memdebug_callback(int nByte, int nFrame, void **aFrame){742  if( mallocLogEnabled ){743    MallocLog *pLog;744    Tcl_HashEntry *pEntry;745    int isNew;746 747    int aKey[MALLOC_LOG_KEYINTS];748    unsigned int nKey = sizeof(int)*MALLOC_LOG_KEYINTS;749 750    memset(aKey, 0, nKey);751    if( (sizeof(void*)*nFrame)<nKey ){752      nKey = nFrame*sizeof(void*);753    }754    memcpy(aKey, aFrame, nKey);755 756    pEntry = Tcl_CreateHashEntry(&aMallocLog, (const char *)aKey, &isNew);757    if( isNew ){758      pLog = (MallocLog *)Tcl_Alloc(sizeof(MallocLog));759      memset(pLog, 0, sizeof(MallocLog));760      Tcl_SetHashValue(pEntry, (ClientData)pLog);761    }else{762      pLog = (MallocLog *)Tcl_GetHashValue(pEntry);763    }764 765    pLog->nCall++;766    pLog->nByte += nByte;767  }768}769#endif /* SQLITE_MEMDEBUG */770 771static void test_memdebug_log_clear(void){772  Tcl_HashSearch search;773  Tcl_HashEntry *pEntry;774  for(775    pEntry=Tcl_FirstHashEntry(&aMallocLog, &search);776    pEntry;777    pEntry=Tcl_NextHashEntry(&search)778  ){779    MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry);780    Tcl_Free((char *)pLog);781  }782  Tcl_DeleteHashTable(&aMallocLog);783  Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS);784}785 786static int SQLITE_TCLAPI test_memdebug_log(787  void * clientData,788  Tcl_Interp *interp,789  int objc,790  Tcl_Obj *CONST objv[]791){792  static int isInit = 0;793  int iSub;794 795  static const char *MB_strs[] = { "start", "stop", "dump", "clear", "sync" };796  enum MB_enum { 797      MB_LOG_START, MB_LOG_STOP, MB_LOG_DUMP, MB_LOG_CLEAR, MB_LOG_SYNC 798  };799 800  if( !isInit ){801#ifdef SQLITE_MEMDEBUG802    extern void sqlite3MemdebugBacktraceCallback(803        void (*xBacktrace)(int, int, void **));804    sqlite3MemdebugBacktraceCallback(test_memdebug_callback);805#endif806    Tcl_InitHashTable(&aMallocLog, MALLOC_LOG_KEYINTS);807    isInit = 1;808  }809 810  if( objc<2 ){811    Tcl_WrongNumArgs(interp, 1, objv, "SUB-COMMAND ...");812  }813  if( Tcl_GetIndexFromObj(interp, objv[1], MB_strs, "sub-command", 0, &iSub) ){814    return TCL_ERROR;815  }816 817  switch( (enum MB_enum)iSub ){818    case MB_LOG_START:819      mallocLogEnabled = 1;820      break;821    case MB_LOG_STOP:822      mallocLogEnabled = 0;823      break;824    case MB_LOG_DUMP: {825      Tcl_HashSearch search;826      Tcl_HashEntry *pEntry;827      Tcl_Obj *pRet = Tcl_NewObj();828 829      assert(sizeof(Tcl_WideInt)>=sizeof(void*));830 831      for(832        pEntry=Tcl_FirstHashEntry(&aMallocLog, &search);833        pEntry;834        pEntry=Tcl_NextHashEntry(&search)835      ){836        Tcl_Obj *apElem[MALLOC_LOG_FRAMES+2];837        MallocLog *pLog = (MallocLog *)Tcl_GetHashValue(pEntry);838        Tcl_WideInt *aKey = (Tcl_WideInt *)Tcl_GetHashKey(&aMallocLog, pEntry);839        int ii;840  841        apElem[0] = Tcl_NewIntObj(pLog->nCall);842        apElem[1] = Tcl_NewIntObj(pLog->nByte);843        for(ii=0; ii<MALLOC_LOG_FRAMES; ii++){844          apElem[ii+2] = Tcl_NewWideIntObj(aKey[ii]);845        }846 847        Tcl_ListObjAppendElement(interp, pRet,848            Tcl_NewListObj(MALLOC_LOG_FRAMES+2, apElem)849        );850      }851 852      Tcl_SetObjResult(interp, pRet);853      break;854    }855    case MB_LOG_CLEAR: {856      test_memdebug_log_clear();857      break;858    }859 860    case MB_LOG_SYNC: {861#ifdef SQLITE_MEMDEBUG862      extern void sqlite3MemdebugSync();863      test_memdebug_log_clear();864      mallocLogEnabled = 1;865      sqlite3MemdebugSync();866#endif867      break;868    }869  }870 871  return TCL_OK;872}873 874/*875** Usage:    sqlite3_config_pagecache SIZE N876**877** Set the page-cache memory buffer using SQLITE_CONFIG_PAGECACHE.878** The buffer is static and is of limited size.  N might be879** adjusted downward as needed to accommodate the requested size.880** The revised value of N is returned.881**882** A negative SIZE causes the buffer pointer to be NULL.883*/884static int SQLITE_TCLAPI test_config_pagecache(885  void * clientData,886  Tcl_Interp *interp,887  int objc,888  Tcl_Obj *CONST objv[]889){890  int sz, N;891  Tcl_Obj *pRes;892  static char *buf = 0;893  if( objc!=3 ){894    Tcl_WrongNumArgs(interp, 1, objv, "SIZE N");895    return TCL_ERROR;896  }897  if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;898  if( Tcl_GetIntFromObj(interp, objv[2], &N) ) return TCL_ERROR;899  free(buf);900  buf = 0;901 902  /* Set the return value */903  pRes = Tcl_NewObj();904  Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(sqlite3GlobalConfig.szPage));905  Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(sqlite3GlobalConfig.nPage));906  Tcl_SetObjResult(interp, pRes);907 908  if( sz<0 ){909    sqlite3_config(SQLITE_CONFIG_PAGECACHE, (void*)0, 0, 0);910  }else{911    buf = malloc( sz*N );912    sqlite3_config(SQLITE_CONFIG_PAGECACHE, buf, sz, N);913  }914  return TCL_OK;915}916 917/*918** Usage:    sqlite3_config_alt_pcache INSTALL_FLAG DISCARD_CHANCE PRNG_SEED919**920** Set up the alternative test page cache.  Install if INSTALL_FLAG is921** true and uninstall (reverting to the default page cache) if INSTALL_FLAG922** is false.  DISCARD_CHANGE is an integer between 0 and 100 inclusive923** which determines the chance of discarding a page when unpinned.  100924** is certainty.  0 is never.  PRNG_SEED is the pseudo-random number generator925** seed.926*/927static int SQLITE_TCLAPI test_alt_pcache(928  void * clientData,929  Tcl_Interp *interp,930  int objc,931  Tcl_Obj *CONST objv[]932){933  int installFlag;934  int discardChance = 0;935  int prngSeed = 0;936  int highStress = 0;937  extern void installTestPCache(int,unsigned,unsigned,unsigned);938  if( objc<2 || objc>5 ){939    Tcl_WrongNumArgs(interp, 1, objv, 940        "INSTALLFLAG DISCARDCHANCE PRNGSEEED HIGHSTRESS");941    return TCL_ERROR;942  }943  if( Tcl_GetIntFromObj(interp, objv[1], &installFlag) ) return TCL_ERROR;944  if( objc>=3 && Tcl_GetIntFromObj(interp, objv[2], &discardChance) ){945     return TCL_ERROR;946  }947  if( objc>=4 && Tcl_GetIntFromObj(interp, objv[3], &prngSeed) ){948     return TCL_ERROR;949  }950  if( objc>=5 && Tcl_GetIntFromObj(interp, objv[4], &highStress) ){951    return TCL_ERROR;952  }953  if( discardChance<0 || discardChance>100 ){954    Tcl_AppendResult(interp, "discard-chance should be between 0 and 100",955                     (char*)0);956    return TCL_ERROR;957  }958  installTestPCache(installFlag, (unsigned)discardChance, (unsigned)prngSeed,959                    (unsigned)highStress);960  return TCL_OK;961}962 963/*964** Usage:    sqlite3_config_memstatus BOOLEAN965**966** Enable or disable memory status reporting using SQLITE_CONFIG_MEMSTATUS.967*/968static int SQLITE_TCLAPI test_config_memstatus(969  void * clientData,970  Tcl_Interp *interp,971  int objc,972  Tcl_Obj *CONST objv[]973){974  int enable, rc;975  if( objc!=2 ){976    Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");977    return TCL_ERROR;978  }979  if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ) return TCL_ERROR;980  rc = sqlite3_config(SQLITE_CONFIG_MEMSTATUS, enable);981  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));982  return TCL_OK;983}984 985/*986** Usage:    sqlite3_config_lookaside  SIZE  COUNT987**988*/989static int SQLITE_TCLAPI test_config_lookaside(990  void * clientData,991  Tcl_Interp *interp,992  int objc,993  Tcl_Obj *CONST objv[]994){995  int sz, cnt;996  Tcl_Obj *pRet;997  if( objc!=3 ){998    Tcl_WrongNumArgs(interp, 1, objv, "SIZE COUNT");999    return TCL_ERROR;1000  }1001  if( Tcl_GetIntFromObj(interp, objv[1], &sz) ) return TCL_ERROR;1002  if( Tcl_GetIntFromObj(interp, objv[2], &cnt) ) return TCL_ERROR;1003  pRet = Tcl_NewObj();1004  Tcl_ListObjAppendElement(1005      interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.szLookaside)1006  );1007  Tcl_ListObjAppendElement(1008      interp, pRet, Tcl_NewIntObj(sqlite3GlobalConfig.nLookaside)1009  );1010  sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, cnt);1011  Tcl_SetObjResult(interp, pRet);1012  return TCL_OK;1013}1014 1015 1016/*1017** Usage:    sqlite3_db_config_lookaside  CONNECTION  BUFID  SIZE  COUNT1018**1019** There are two static buffers with BUFID 1 and 2.   Each static buffer1020** is 10KB in size.  A BUFID of 0 indicates that the buffer should be NULL1021** which will cause sqlite3_db_config() to allocate space on its own.1022*/1023static int SQLITE_TCLAPI test_db_config_lookaside(1024  void * clientData,1025  Tcl_Interp *interp,1026  int objc,1027  Tcl_Obj *CONST objv[]1028){1029  int rc;1030  int sz, cnt;1031  sqlite3 *db;1032  int bufid;1033  static char azBuf[2][10000];1034  extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);1035  if( objc!=5 ){1036    Tcl_WrongNumArgs(interp, 1, objv, "BUFID SIZE COUNT");1037    return TCL_ERROR;1038  }1039  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;1040  if( Tcl_GetIntFromObj(interp, objv[2], &bufid) ) return TCL_ERROR;1041  if( Tcl_GetIntFromObj(interp, objv[3], &sz) ) return TCL_ERROR;1042  if( Tcl_GetIntFromObj(interp, objv[4], &cnt) ) return TCL_ERROR;1043  if( bufid==0 ){1044    rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, (void*)0, sz, cnt);1045  }else if( bufid>=1 && bufid<=2 && sz*cnt<=sizeof(azBuf[0]) ){1046    rc = sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE, azBuf[bufid], sz,cnt);1047  }else{1048    Tcl_AppendResult(interp, "illegal arguments - see documentation", (char*)0);1049    return TCL_ERROR;1050  }1051  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));1052  return TCL_OK;1053}1054 1055/*1056** Usage:    sqlite3_config_heap NBYTE NMINALLOC1057*/1058static int SQLITE_TCLAPI test_config_heap(1059  void * clientData, 1060  Tcl_Interp *interp,1061  int objc,1062  Tcl_Obj *CONST objv[]1063){1064  static char *zBuf; /* Use this memory */1065  int nByte;         /* Size of buffer to pass to sqlite3_config() */1066  int nMinAlloc;     /* Size of minimum allocation */1067  int rc;            /* Return code of sqlite3_config() */1068 1069  Tcl_Obj * CONST *aArg = &objv[1];1070  int nArg = objc-1;1071 1072  if( nArg!=2 ){1073    Tcl_WrongNumArgs(interp, 1, objv, "NBYTE NMINALLOC");1074    return TCL_ERROR;1075  }1076  if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR;1077  if( Tcl_GetIntFromObj(interp, aArg[1], &nMinAlloc) ) return TCL_ERROR;1078 1079  if( nByte==0 ){1080    free( zBuf );1081    zBuf = 0;1082    rc = sqlite3_config(SQLITE_CONFIG_HEAP, (void*)0, 0, 0);1083  }else{1084    zBuf = realloc(zBuf, nByte);1085    rc = sqlite3_config(SQLITE_CONFIG_HEAP, zBuf, nByte, nMinAlloc);1086  }1087 1088  Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);1089  return TCL_OK;1090}1091 1092/*1093** Usage:    sqlite3_config_heap_size NBYTE1094*/1095static int SQLITE_TCLAPI test_config_heap_size(1096  void * clientData, 1097  Tcl_Interp *interp,1098  int objc,1099  Tcl_Obj *CONST objv[]1100){1101  int nByte;         /* Size to pass to sqlite3_config() */1102  int rc;            /* Return code of sqlite3_config() */1103 1104  Tcl_Obj * CONST *aArg = &objv[1];1105  int nArg = objc-1;1106 1107  if( nArg!=1 ){1108    Tcl_WrongNumArgs(interp, 1, objv, "NBYTE");1109    return TCL_ERROR;1110  }1111  if( Tcl_GetIntFromObj(interp, aArg[0], &nByte) ) return TCL_ERROR;1112 1113  rc = sqlite3_config(SQLITE_CONFIG_WIN32_HEAPSIZE, nByte);1114 1115  Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);1116  return TCL_OK;1117}1118 1119/*1120** Usage:    sqlite3_config_error  [DB]1121**1122** Invoke sqlite3_config() or sqlite3_db_config() with invalid1123** opcodes and verify that they return errors.1124*/1125static int SQLITE_TCLAPI test_config_error(1126  void * clientData, 1127  Tcl_Interp *interp,1128  int objc,1129  Tcl_Obj *CONST objv[]1130){1131  sqlite3 *db;1132  extern int getDbPointer(Tcl_Interp*, const char*, sqlite3**);1133 1134  if( objc!=2 && objc!=1 ){1135    Tcl_WrongNumArgs(interp, 1, objv, "[DB]");1136    return TCL_ERROR;1137  }1138  if( objc==2 ){1139    if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;1140    if( sqlite3_db_config(db, 99999)!=SQLITE_ERROR ){1141      Tcl_AppendResult(interp, 1142            "sqlite3_db_config(db, 99999) does not return SQLITE_ERROR",1143            (char*)0);1144      return TCL_ERROR;1145    }1146  }else{1147    if( sqlite3_config(99999)!=SQLITE_ERROR ){1148      Tcl_AppendResult(interp, 1149          "sqlite3_config(99999) does not return SQLITE_ERROR",1150          (char*)0);1151      return TCL_ERROR;1152    }1153  }1154  return TCL_OK;1155}1156 1157/*1158** Usage:    sqlite3_config_uri  BOOLEAN1159**1160** Enables or disables interpretation of URI parameters by default using1161** SQLITE_CONFIG_URI.1162*/1163static int SQLITE_TCLAPI test_config_uri(1164  void * clientData, 1165  Tcl_Interp *interp,1166  int objc,1167  Tcl_Obj *CONST objv[]1168){1169  int rc;1170  int bOpenUri;1171 1172  if( objc!=2 ){1173    Tcl_WrongNumArgs(interp, 1, objv, "BOOL");1174    return TCL_ERROR;1175  }1176  if( Tcl_GetBooleanFromObj(interp, objv[1], &bOpenUri) ){1177    return TCL_ERROR;1178  }1179 1180  rc = sqlite3_config(SQLITE_CONFIG_URI, bOpenUri);1181  Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);1182 1183  return TCL_OK;1184}1185 1186/*1187** Usage:    sqlite3_config_cis  BOOLEAN1188**1189** Enables or disables the use of the covering-index scan optimization.1190** SQLITE_CONFIG_COVERING_INDEX_SCAN.1191*/1192static int SQLITE_TCLAPI test_config_cis(1193  void * clientData, 1194  Tcl_Interp *interp,1195  int objc,1196  Tcl_Obj *CONST objv[]1197){1198  int rc;1199  int bUseCis;1200 

Showing the first 1,200 of 1514 lines. Download the file for the rest.