Home | History | Annotate | Download | only in src
      1 /*
      2 ** 2004 May 22
      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 that modified the OS layer in order to simulate
     14 ** the effect on the database file of an OS crash or power failure.  This
     15 ** is used to test the ability of SQLite to recover from those situations.
     16 */
     17 #if SQLITE_TEST          /* This file is used for testing only */
     18 #include "sqliteInt.h"
     19 #include "tcl.h"
     20 
     21 #ifndef SQLITE_OMIT_DISKIO  /* This file is a no-op if disk I/O is disabled */
     22 
     23 /* #define TRACE_CRASHTEST */
     24 
     25 typedef struct CrashFile CrashFile;
     26 typedef struct CrashGlobal CrashGlobal;
     27 typedef struct WriteBuffer WriteBuffer;
     28 
     29 /*
     30 ** Method:
     31 **
     32 **   This layer is implemented as a wrapper around the "real"
     33 **   sqlite3_file object for the host system. Each time data is
     34 **   written to the file object, instead of being written to the
     35 **   underlying file, the write operation is stored in an in-memory
     36 **   structure (type WriteBuffer). This structure is placed at the
     37 **   end of a global ordered list (the write-list).
     38 **
     39 **   When data is read from a file object, the requested region is
     40 **   first retrieved from the real file. The write-list is then
     41 **   traversed and data copied from any overlapping WriteBuffer
     42 **   structures to the output buffer. i.e. a read() operation following
     43 **   one or more write() operations works as expected, even if no
     44 **   data has actually been written out to the real file.
     45 **
     46 **   When a fsync() operation is performed, an operating system crash
     47 **   may be simulated, in which case exit(-1) is called (the call to
     48 **   xSync() never returns). Whether or not a crash is simulated,
     49 **   the data associated with a subset of the WriteBuffer structures
     50 **   stored in the write-list is written to the real underlying files
     51 **   and the entries removed from the write-list. If a crash is simulated,
     52 **   a subset of the buffers may be corrupted before the data is written.
     53 **
     54 **   The exact subset of the write-list written and/or corrupted is
     55 **   determined by the simulated device characteristics and sector-size.
     56 **
     57 ** "Normal" mode:
     58 **
     59 **   Normal mode is used when the simulated device has none of the
     60 **   SQLITE_IOCAP_XXX flags set.
     61 **
     62 **   In normal mode, if the fsync() is not a simulated crash, the
     63 **   write-list is traversed from beginning to end. Each WriteBuffer
     64 **   structure associated with the file handle used to call xSync()
     65 **   is written to the real file and removed from the write-list.
     66 **
     67 **   If a crash is simulated, one of the following takes place for
     68 **   each WriteBuffer in the write-list, regardless of which
     69 **   file-handle it is associated with:
     70 **
     71 **     1. The buffer is correctly written to the file, just as if
     72 **        a crash were not being simulated.
     73 **
     74 **     2. Nothing is done.
     75 **
     76 **     3. Garbage data is written to all sectors of the file that
     77 **        overlap the region specified by the WriteBuffer. Or garbage
     78 **        data is written to some contiguous section within the
     79 **        overlapped sectors.
     80 **
     81 ** Device Characteristic flag handling:
     82 **
     83 **   If the IOCAP_ATOMIC flag is set, then option (3) above is
     84 **   never selected.
     85 **
     86 **   If the IOCAP_ATOMIC512 flag is set, and the WriteBuffer represents
     87 **   an aligned write() of an integer number of 512 byte regions, then
     88 **   option (3) above is never selected. Instead, each 512 byte region
     89 **   is either correctly written or left completely untouched. Similar
     90 **   logic governs the behaviour if any of the other ATOMICXXX flags
     91 **   is set.
     92 **
     93 **   If either the IOCAP_SAFEAPPEND or IOCAP_SEQUENTIAL flags are set
     94 **   and a crash is being simulated, then an entry of the write-list is
     95 **   selected at random. Everything in the list after the selected entry
     96 **   is discarded before processing begins.
     97 **
     98 **   If IOCAP_SEQUENTIAL is set and a crash is being simulated, option
     99 **   (1) is selected for all write-list entries except the last. If a
    100 **   crash is not being simulated, then all entries in the write-list
    101 **   that occur before at least one write() on the file-handle specified
    102 **   as part of the xSync() are written to their associated real files.
    103 **
    104 **   If IOCAP_SAFEAPPEND is set and the first byte written by the write()
    105 **   operation is one byte past the current end of the file, then option
    106 **   (1) is always selected.
    107 */
    108 
    109 /*
    110 ** Each write operation in the write-list is represented by an instance
    111 ** of the following structure.
    112 **
    113 ** If zBuf is 0, then this structure represents a call to xTruncate(),
    114 ** not xWrite(). In that case, iOffset is the size that the file is
    115 ** truncated to.
    116 */
    117 struct WriteBuffer {
    118   i64 iOffset;                 /* Byte offset of the start of this write() */
    119   int nBuf;                    /* Number of bytes written */
    120   u8 *zBuf;                    /* Pointer to copy of written data */
    121   CrashFile *pFile;            /* File this write() applies to */
    122 
    123   WriteBuffer *pNext;          /* Next in CrashGlobal.pWriteList */
    124 };
    125 
    126 struct CrashFile {
    127   const sqlite3_io_methods *pMethod;   /* Must be first */
    128   sqlite3_file *pRealFile;             /* Underlying "real" file handle */
    129   char *zName;
    130   int flags;                           /* Flags the file was opened with */
    131 
    132   /* Cache of the entire file. This is used to speed up OsRead() and
    133   ** OsFileSize() calls. Although both could be done by traversing the
    134   ** write-list, in practice this is impractically slow.
    135   */
    136   int iSize;                           /* Size of file in bytes */
    137   int nData;                           /* Size of buffer allocated at zData */
    138   u8 *zData;                           /* Buffer containing file contents */
    139 };
    140 
    141 struct CrashGlobal {
    142   WriteBuffer *pWriteList;     /* Head of write-list */
    143   WriteBuffer *pWriteListEnd;  /* End of write-list */
    144 
    145   int iSectorSize;             /* Value of simulated sector size */
    146   int iDeviceCharacteristics;  /* Value of simulated device characteristics */
    147 
    148   int iCrash;                  /* Crash on the iCrash'th call to xSync() */
    149   char zCrashFile[500];        /* Crash during an xSync() on this file */
    150 };
    151 
    152 static CrashGlobal g = {0, 0, SQLITE_DEFAULT_SECTOR_SIZE, 0, 0};
    153 
    154 /*
    155 ** Set this global variable to 1 to enable crash testing.
    156 */
    157 static int sqlite3CrashTestEnable = 0;
    158 
    159 static void *crash_malloc(int nByte){
    160   return (void *)Tcl_Alloc((size_t)nByte);
    161 }
    162 static void crash_free(void *p){
    163   Tcl_Free(p);
    164 }
    165 static void *crash_realloc(void *p, int n){
    166   return (void *)Tcl_Realloc(p, (size_t)n);
    167 }
    168 
    169 /*
    170 ** Wrapper around the sqlite3OsWrite() function that avoids writing to the
    171 ** 512 byte block begining at offset PENDING_BYTE.
    172 */
    173 static int writeDbFile(CrashFile *p, u8 *z, i64 iAmt, i64 iOff){
    174   int rc = SQLITE_OK;
    175   int iSkip = 0;
    176   if( iOff==PENDING_BYTE && (p->flags&SQLITE_OPEN_MAIN_DB) ){
    177     iSkip = 512;
    178   }
    179   if( (iAmt-iSkip)>0 ){
    180     rc = sqlite3OsWrite(p->pRealFile, &z[iSkip], iAmt-iSkip, iOff+iSkip);
    181   }
    182   return rc;
    183 }
    184 
    185 /*
    186 ** Flush the write-list as if xSync() had been called on file handle
    187 ** pFile. If isCrash is true, simulate a crash.
    188 */
    189 static int writeListSync(CrashFile *pFile, int isCrash){
    190   int rc = SQLITE_OK;
    191   int iDc = g.iDeviceCharacteristics;
    192 
    193   WriteBuffer *pWrite;
    194   WriteBuffer **ppPtr;
    195 
    196   /* If this is not a crash simulation, set pFinal to point to the
    197   ** last element of the write-list that is associated with file handle
    198   ** pFile.
    199   **
    200   ** If this is a crash simulation, set pFinal to an arbitrarily selected
    201   ** element of the write-list.
    202   */
    203   WriteBuffer *pFinal = 0;
    204   if( !isCrash ){
    205     for(pWrite=g.pWriteList; pWrite; pWrite=pWrite->pNext){
    206       if( pWrite->pFile==pFile ){
    207         pFinal = pWrite;
    208       }
    209     }
    210   }else if( iDc&(SQLITE_IOCAP_SEQUENTIAL|SQLITE_IOCAP_SAFE_APPEND) ){
    211     int nWrite = 0;
    212     int iFinal;
    213     for(pWrite=g.pWriteList; pWrite; pWrite=pWrite->pNext) nWrite++;
    214     sqlite3_randomness(sizeof(int), &iFinal);
    215     iFinal = ((iFinal<0)?-1*iFinal:iFinal)%nWrite;
    216     for(pWrite=g.pWriteList; iFinal>0; pWrite=pWrite->pNext) iFinal--;
    217     pFinal = pWrite;
    218   }
    219 
    220 #ifdef TRACE_CRASHTEST
    221   printf("Sync %s (is %s crash)\n", pFile->zName, (isCrash?"a":"not a"));
    222 #endif
    223 
    224   ppPtr = &g.pWriteList;
    225   for(pWrite=*ppPtr; rc==SQLITE_OK && pWrite; pWrite=*ppPtr){
    226     sqlite3_file *pRealFile = pWrite->pFile->pRealFile;
    227 
    228     /* (eAction==1)      -> write block out normally,
    229     ** (eAction==2)      -> do nothing,
    230     ** (eAction==3)      -> trash sectors.
    231     */
    232     int eAction = 0;
    233     if( !isCrash ){
    234       eAction = 2;
    235       if( (pWrite->pFile==pFile || iDc&SQLITE_IOCAP_SEQUENTIAL) ){
    236         eAction = 1;
    237       }
    238     }else{
    239       char random;
    240       sqlite3_randomness(1, &random);
    241 
    242       /* Do not select option 3 (sector trashing) if the IOCAP_ATOMIC flag
    243       ** is set or this is an OsTruncate(), not an Oswrite().
    244       */
    245       if( (iDc&SQLITE_IOCAP_ATOMIC) || (pWrite->zBuf==0) ){
    246         random &= 0x01;
    247       }
    248 
    249       /* If IOCAP_SEQUENTIAL is set and this is not the final entry
    250       ** in the truncated write-list, always select option 1 (write
    251       ** out correctly).
    252       */
    253       if( (iDc&SQLITE_IOCAP_SEQUENTIAL && pWrite!=pFinal) ){
    254         random = 0;
    255       }
    256 
    257       /* If IOCAP_SAFE_APPEND is set and this OsWrite() operation is
    258       ** an append (first byte of the written region is 1 byte past the
    259       ** current EOF), always select option 1 (write out correctly).
    260       */
    261       if( iDc&SQLITE_IOCAP_SAFE_APPEND && pWrite->zBuf ){
    262         i64 iSize;
    263         sqlite3OsFileSize(pRealFile, &iSize);
    264         if( iSize==pWrite->iOffset ){
    265           random = 0;
    266         }
    267       }
    268 
    269       if( (random&0x06)==0x06 ){
    270         eAction = 3;
    271       }else{
    272         eAction = ((random&0x01)?2:1);
    273       }
    274     }
    275 
    276     switch( eAction ){
    277       case 1: {               /* Write out correctly */
    278         if( pWrite->zBuf ){
    279           rc = writeDbFile(
    280               pWrite->pFile, pWrite->zBuf, pWrite->nBuf, pWrite->iOffset
    281           );
    282         }else{
    283           rc = sqlite3OsTruncate(pRealFile, pWrite->iOffset);
    284         }
    285         *ppPtr = pWrite->pNext;
    286 #ifdef TRACE_CRASHTEST
    287         if( isCrash ){
    288           printf("Writing %d bytes @ %d (%s)\n",
    289             pWrite->nBuf, (int)pWrite->iOffset, pWrite->pFile->zName
    290           );
    291         }
    292 #endif
    293         crash_free(pWrite);
    294         break;
    295       }
    296       case 2: {               /* Do nothing */
    297         ppPtr = &pWrite->pNext;
    298 #ifdef TRACE_CRASHTEST
    299         if( isCrash ){
    300           printf("Omiting %d bytes @ %d (%s)\n",
    301             pWrite->nBuf, (int)pWrite->iOffset, pWrite->pFile->zName
    302           );
    303         }
    304 #endif
    305         break;
    306       }
    307       case 3: {               /* Trash sectors */
    308         u8 *zGarbage;
    309         int iFirst = (pWrite->iOffset/g.iSectorSize);
    310         int iLast = (pWrite->iOffset+pWrite->nBuf-1)/g.iSectorSize;
    311 
    312         assert(pWrite->zBuf);
    313 
    314 #ifdef TRACE_CRASHTEST
    315         printf("Trashing %d sectors @ sector %d (%s)\n",
    316             1+iLast-iFirst, iFirst, pWrite->pFile->zName
    317         );
    318 #endif
    319 
    320         zGarbage = crash_malloc(g.iSectorSize);
    321         if( zGarbage ){
    322           sqlite3_int64 i;
    323           for(i=iFirst; rc==SQLITE_OK && i<=iLast; i++){
    324             sqlite3_randomness(g.iSectorSize, zGarbage);
    325             rc = writeDbFile(
    326               pWrite->pFile, zGarbage, g.iSectorSize, i*g.iSectorSize
    327             );
    328           }
    329           crash_free(zGarbage);
    330         }else{
    331           rc = SQLITE_NOMEM;
    332         }
    333 
    334         ppPtr = &pWrite->pNext;
    335         break;
    336       }
    337 
    338       default:
    339         assert(!"Cannot happen");
    340     }
    341 
    342     if( pWrite==pFinal ) break;
    343   }
    344 
    345   if( rc==SQLITE_OK && isCrash ){
    346     exit(-1);
    347   }
    348 
    349   for(pWrite=g.pWriteList; pWrite && pWrite->pNext; pWrite=pWrite->pNext);
    350   g.pWriteListEnd = pWrite;
    351 
    352   return rc;
    353 }
    354 
    355 /*
    356 ** Add an entry to the end of the write-list.
    357 */
    358 static int writeListAppend(
    359   sqlite3_file *pFile,
    360   sqlite3_int64 iOffset,
    361   const u8 *zBuf,
    362   int nBuf
    363 ){
    364   WriteBuffer *pNew;
    365 
    366   assert((zBuf && nBuf) || (!nBuf && !zBuf));
    367 
    368   pNew = (WriteBuffer *)crash_malloc(sizeof(WriteBuffer) + nBuf);
    369   if( pNew==0 ){
    370     fprintf(stderr, "out of memory in the crash simulator\n");
    371   }
    372   memset(pNew, 0, sizeof(WriteBuffer)+nBuf);
    373   pNew->iOffset = iOffset;
    374   pNew->nBuf = nBuf;
    375   pNew->pFile = (CrashFile *)pFile;
    376   if( zBuf ){
    377     pNew->zBuf = (u8 *)&pNew[1];
    378     memcpy(pNew->zBuf, zBuf, nBuf);
    379   }
    380 
    381   if( g.pWriteList ){
    382     assert(g.pWriteListEnd);
    383     g.pWriteListEnd->pNext = pNew;
    384   }else{
    385     g.pWriteList = pNew;
    386   }
    387   g.pWriteListEnd = pNew;
    388 
    389   return SQLITE_OK;
    390 }
    391 
    392 /*
    393 ** Close a crash-file.
    394 */
    395 static int cfClose(sqlite3_file *pFile){
    396   CrashFile *pCrash = (CrashFile *)pFile;
    397   writeListSync(pCrash, 0);
    398   sqlite3OsClose(pCrash->pRealFile);
    399   return SQLITE_OK;
    400 }
    401 
    402 /*
    403 ** Read data from a crash-file.
    404 */
    405 static int cfRead(
    406   sqlite3_file *pFile,
    407   void *zBuf,
    408   int iAmt,
    409   sqlite_int64 iOfst
    410 ){
    411   CrashFile *pCrash = (CrashFile *)pFile;
    412 
    413   /* Check the file-size to see if this is a short-read */
    414   if( pCrash->iSize<(iOfst+iAmt) ){
    415     return SQLITE_IOERR_SHORT_READ;
    416   }
    417 
    418   memcpy(zBuf, &pCrash->zData[iOfst], iAmt);
    419   return SQLITE_OK;
    420 }
    421 
    422 /*
    423 ** Write data to a crash-file.
    424 */
    425 static int cfWrite(
    426   sqlite3_file *pFile,
    427   const void *zBuf,
    428   int iAmt,
    429   sqlite_int64 iOfst
    430 ){
    431   CrashFile *pCrash = (CrashFile *)pFile;
    432   if( iAmt+iOfst>pCrash->iSize ){
    433     pCrash->iSize = iAmt+iOfst;
    434   }
    435   while( pCrash->iSize>pCrash->nData ){
    436     u8 *zNew;
    437     int nNew = (pCrash->nData*2) + 4096;
    438     zNew = crash_realloc(pCrash->zData, nNew);
    439     if( !zNew ){
    440       return SQLITE_NOMEM;
    441     }
    442     memset(&zNew[pCrash->nData], 0, nNew-pCrash->nData);
    443     pCrash->nData = nNew;
    444     pCrash->zData = zNew;
    445   }
    446   memcpy(&pCrash->zData[iOfst], zBuf, iAmt);
    447   return writeListAppend(pFile, iOfst, zBuf, iAmt);
    448 }
    449 
    450 /*
    451 ** Truncate a crash-file.
    452 */
    453 static int cfTruncate(sqlite3_file *pFile, sqlite_int64 size){
    454   CrashFile *pCrash = (CrashFile *)pFile;
    455   assert(size>=0);
    456   if( pCrash->iSize>size ){
    457     pCrash->iSize = size;
    458   }
    459   return writeListAppend(pFile, size, 0, 0);
    460 }
    461 
    462 /*
    463 ** Sync a crash-file.
    464 */
    465 static int cfSync(sqlite3_file *pFile, int flags){
    466   CrashFile *pCrash = (CrashFile *)pFile;
    467   int isCrash = 0;
    468 
    469   const char *zName = pCrash->zName;
    470   const char *zCrashFile = g.zCrashFile;
    471   int nName = strlen(zName);
    472   int nCrashFile = strlen(zCrashFile);
    473 
    474   if( nCrashFile>0 && zCrashFile[nCrashFile-1]=='*' ){
    475     nCrashFile--;
    476     if( nName>nCrashFile ) nName = nCrashFile;
    477   }
    478 
    479   if( nName==nCrashFile && 0==memcmp(zName, zCrashFile, nName) ){
    480     if( (--g.iCrash)==0 ) isCrash = 1;
    481   }
    482 
    483   return writeListSync(pCrash, isCrash);
    484 }
    485 
    486 /*
    487 ** Return the current file-size of the crash-file.
    488 */
    489 static int cfFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
    490   CrashFile *pCrash = (CrashFile *)pFile;
    491   *pSize = (i64)pCrash->iSize;
    492   return SQLITE_OK;
    493 }
    494 
    495 /*
    496 ** Calls related to file-locks are passed on to the real file handle.
    497 */
    498 static int cfLock(sqlite3_file *pFile, int eLock){
    499   return sqlite3OsLock(((CrashFile *)pFile)->pRealFile, eLock);
    500 }
    501 static int cfUnlock(sqlite3_file *pFile, int eLock){
    502   return sqlite3OsUnlock(((CrashFile *)pFile)->pRealFile, eLock);
    503 }
    504 static int cfCheckReservedLock(sqlite3_file *pFile, int *pResOut){
    505   return sqlite3OsCheckReservedLock(((CrashFile *)pFile)->pRealFile, pResOut);
    506 }
    507 static int cfFileControl(sqlite3_file *pFile, int op, void *pArg){
    508   return sqlite3OsFileControl(((CrashFile *)pFile)->pRealFile, op, pArg);
    509 }
    510 
    511 /*
    512 ** The xSectorSize() and xDeviceCharacteristics() functions return
    513 ** the global values configured by the [sqlite_crashparams] tcl
    514 *  interface.
    515 */
    516 static int cfSectorSize(sqlite3_file *pFile){
    517   return g.iSectorSize;
    518 }
    519 static int cfDeviceCharacteristics(sqlite3_file *pFile){
    520   return g.iDeviceCharacteristics;
    521 }
    522 
    523 /*
    524 ** Pass-throughs for WAL support.
    525 */
    526 static int cfShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
    527   return sqlite3OsShmLock(((CrashFile*)pFile)->pRealFile, ofst, n, flags);
    528 }
    529 static void cfShmBarrier(sqlite3_file *pFile){
    530   sqlite3OsShmBarrier(((CrashFile*)pFile)->pRealFile);
    531 }
    532 static int cfShmUnmap(sqlite3_file *pFile, int delFlag){
    533   return sqlite3OsShmUnmap(((CrashFile*)pFile)->pRealFile, delFlag);
    534 }
    535 static int cfShmMap(
    536   sqlite3_file *pFile,            /* Handle open on database file */
    537   int iRegion,                    /* Region to retrieve */
    538   int sz,                         /* Size of regions */
    539   int w,                          /* True to extend file if necessary */
    540   void volatile **pp              /* OUT: Mapped memory */
    541 ){
    542   return sqlite3OsShmMap(((CrashFile*)pFile)->pRealFile, iRegion, sz, w, pp);
    543 }
    544 
    545 static const sqlite3_io_methods CrashFileVtab = {
    546   2,                            /* iVersion */
    547   cfClose,                      /* xClose */
    548   cfRead,                       /* xRead */
    549   cfWrite,                      /* xWrite */
    550   cfTruncate,                   /* xTruncate */
    551   cfSync,                       /* xSync */
    552   cfFileSize,                   /* xFileSize */
    553   cfLock,                       /* xLock */
    554   cfUnlock,                     /* xUnlock */
    555   cfCheckReservedLock,          /* xCheckReservedLock */
    556   cfFileControl,                /* xFileControl */
    557   cfSectorSize,                 /* xSectorSize */
    558   cfDeviceCharacteristics,      /* xDeviceCharacteristics */
    559   cfShmMap,                     /* xShmMap */
    560   cfShmLock,                    /* xShmLock */
    561   cfShmBarrier,                 /* xShmBarrier */
    562   cfShmUnmap                    /* xShmUnmap */
    563 };
    564 
    565 /*
    566 ** Application data for the crash VFS
    567 */
    568 struct crashAppData {
    569   sqlite3_vfs *pOrig;                   /* Wrapped vfs structure */
    570 };
    571 
    572 /*
    573 ** Open a crash-file file handle.
    574 **
    575 ** The caller will have allocated pVfs->szOsFile bytes of space
    576 ** at pFile. This file uses this space for the CrashFile structure
    577 ** and allocates space for the "real" file structure using
    578 ** sqlite3_malloc(). The assumption here is (pVfs->szOsFile) is
    579 ** equal or greater than sizeof(CrashFile).
    580 */
    581 static int cfOpen(
    582   sqlite3_vfs *pCfVfs,
    583   const char *zName,
    584   sqlite3_file *pFile,
    585   int flags,
    586   int *pOutFlags
    587 ){
    588   sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
    589   int rc;
    590   CrashFile *pWrapper = (CrashFile *)pFile;
    591   sqlite3_file *pReal = (sqlite3_file*)&pWrapper[1];
    592 
    593   memset(pWrapper, 0, sizeof(CrashFile));
    594   rc = sqlite3OsOpen(pVfs, zName, pReal, flags, pOutFlags);
    595 
    596   if( rc==SQLITE_OK ){
    597     i64 iSize;
    598     pWrapper->pMethod = &CrashFileVtab;
    599     pWrapper->zName = (char *)zName;
    600     pWrapper->pRealFile = pReal;
    601     rc = sqlite3OsFileSize(pReal, &iSize);
    602     pWrapper->iSize = (int)iSize;
    603     pWrapper->flags = flags;
    604   }
    605   if( rc==SQLITE_OK ){
    606     pWrapper->nData = (4096 + pWrapper->iSize);
    607     pWrapper->zData = crash_malloc(pWrapper->nData);
    608     if( pWrapper->zData ){
    609       /* os_unix.c contains an assert() that fails if the caller attempts
    610       ** to read data from the 512-byte locking region of a file opened
    611       ** with the SQLITE_OPEN_MAIN_DB flag. This region of a database file
    612       ** never contains valid data anyhow. So avoid doing such a read here.
    613       */
    614       const int isDb = (flags&SQLITE_OPEN_MAIN_DB);
    615       i64 iChunk = pWrapper->iSize;
    616       if( iChunk>PENDING_BYTE && isDb ){
    617         iChunk = PENDING_BYTE;
    618       }
    619       memset(pWrapper->zData, 0, pWrapper->nData);
    620       rc = sqlite3OsRead(pReal, pWrapper->zData, iChunk, 0);
    621       if( SQLITE_OK==rc && pWrapper->iSize>(PENDING_BYTE+512) && isDb ){
    622         i64 iOff = PENDING_BYTE+512;
    623         iChunk = pWrapper->iSize - iOff;
    624         rc = sqlite3OsRead(pReal, &pWrapper->zData[iOff], iChunk, iOff);
    625       }
    626     }else{
    627       rc = SQLITE_NOMEM;
    628     }
    629   }
    630   if( rc!=SQLITE_OK && pWrapper->pMethod ){
    631     sqlite3OsClose(pFile);
    632   }
    633   return rc;
    634 }
    635 
    636 static int cfDelete(sqlite3_vfs *pCfVfs, const char *zPath, int dirSync){
    637   sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
    638   return pVfs->xDelete(pVfs, zPath, dirSync);
    639 }
    640 static int cfAccess(
    641   sqlite3_vfs *pCfVfs,
    642   const char *zPath,
    643   int flags,
    644   int *pResOut
    645 ){
    646   sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
    647   return pVfs->xAccess(pVfs, zPath, flags, pResOut);
    648 }
    649 static int cfFullPathname(
    650   sqlite3_vfs *pCfVfs,
    651   const char *zPath,
    652   int nPathOut,
    653   char *zPathOut
    654 ){
    655   sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
    656   return pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
    657 }
    658 static void *cfDlOpen(sqlite3_vfs *pCfVfs, const char *zPath){
    659   sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
    660   return pVfs->xDlOpen(pVfs, zPath);
    661 }
    662 static void cfDlError(sqlite3_vfs *pCfVfs, int nByte, char *zErrMsg){
    663   sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
    664   pVfs->xDlError(pVfs, nByte, zErrMsg);
    665 }
    666 static void (*cfDlSym(sqlite3_vfs *pCfVfs, void *pH, const char *zSym))(void){
    667   sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
    668   return pVfs->xDlSym(pVfs, pH, zSym);
    669 }
    670 static void cfDlClose(sqlite3_vfs *pCfVfs, void *pHandle){
    671   sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
    672   pVfs->xDlClose(pVfs, pHandle);
    673 }
    674 static int cfRandomness(sqlite3_vfs *pCfVfs, int nByte, char *zBufOut){
    675   sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
    676   return pVfs->xRandomness(pVfs, nByte, zBufOut);
    677 }
    678 static int cfSleep(sqlite3_vfs *pCfVfs, int nMicro){
    679   sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
    680   return pVfs->xSleep(pVfs, nMicro);
    681 }
    682 static int cfCurrentTime(sqlite3_vfs *pCfVfs, double *pTimeOut){
    683   sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
    684   return pVfs->xCurrentTime(pVfs, pTimeOut);
    685 }
    686 
    687 static int processDevSymArgs(
    688   Tcl_Interp *interp,
    689   int objc,
    690   Tcl_Obj *CONST objv[],
    691   int *piDeviceChar,
    692   int *piSectorSize
    693 ){
    694   struct DeviceFlag {
    695     char *zName;
    696     int iValue;
    697   } aFlag[] = {
    698     { "atomic",      SQLITE_IOCAP_ATOMIC      },
    699     { "atomic512",   SQLITE_IOCAP_ATOMIC512   },
    700     { "atomic1k",    SQLITE_IOCAP_ATOMIC1K    },
    701     { "atomic2k",    SQLITE_IOCAP_ATOMIC2K    },
    702     { "atomic4k",    SQLITE_IOCAP_ATOMIC4K    },
    703     { "atomic8k",    SQLITE_IOCAP_ATOMIC8K    },
    704     { "atomic16k",   SQLITE_IOCAP_ATOMIC16K   },
    705     { "atomic32k",   SQLITE_IOCAP_ATOMIC32K   },
    706     { "atomic64k",   SQLITE_IOCAP_ATOMIC64K   },
    707     { "sequential",  SQLITE_IOCAP_SEQUENTIAL  },
    708     { "safe_append", SQLITE_IOCAP_SAFE_APPEND },
    709     { 0, 0 }
    710   };
    711 
    712   int i;
    713   int iDc = 0;
    714   int iSectorSize = 0;
    715   int setSectorsize = 0;
    716   int setDeviceChar = 0;
    717 
    718   for(i=0; i<objc; i+=2){
    719     int nOpt;
    720     char *zOpt = Tcl_GetStringFromObj(objv[i], &nOpt);
    721 
    722     if( (nOpt>11 || nOpt<2 || strncmp("-sectorsize", zOpt, nOpt))
    723      && (nOpt>16 || nOpt<2 || strncmp("-characteristics", zOpt, nOpt))
    724     ){
    725       Tcl_AppendResult(interp,
    726         "Bad option: \"", zOpt,
    727         "\" - must be \"-characteristics\" or \"-sectorsize\"", 0
    728       );
    729       return TCL_ERROR;
    730     }
    731     if( i==objc-1 ){
    732       Tcl_AppendResult(interp, "Option requires an argument: \"", zOpt, "\"",0);
    733       return TCL_ERROR;
    734     }
    735 
    736     if( zOpt[1]=='s' ){
    737       if( Tcl_GetIntFromObj(interp, objv[i+1], &iSectorSize) ){
    738         return TCL_ERROR;
    739       }
    740       setSectorsize = 1;
    741     }else{
    742       int j;
    743       Tcl_Obj **apObj;
    744       int nObj;
    745       if( Tcl_ListObjGetElements(interp, objv[i+1], &nObj, &apObj) ){
    746         return TCL_ERROR;
    747       }
    748       for(j=0; j<nObj; j++){
    749         int rc;
    750         int iChoice;
    751         Tcl_Obj *pFlag = Tcl_DuplicateObj(apObj[j]);
    752         Tcl_IncrRefCount(pFlag);
    753         Tcl_UtfToLower(Tcl_GetString(pFlag));
    754 
    755         rc = Tcl_GetIndexFromObjStruct(
    756             interp, pFlag, aFlag, sizeof(aFlag[0]), "no such flag", 0, &iChoice
    757         );
    758         Tcl_DecrRefCount(pFlag);
    759         if( rc ){
    760           return TCL_ERROR;
    761         }
    762 
    763         iDc |= aFlag[iChoice].iValue;
    764       }
    765       setDeviceChar = 1;
    766     }
    767   }
    768 
    769   if( setDeviceChar ){
    770     *piDeviceChar = iDc;
    771   }
    772   if( setSectorsize ){
    773     *piSectorSize = iSectorSize;
    774   }
    775 
    776   return TCL_OK;
    777 }
    778 
    779 /*
    780 ** tclcmd:   sqlite_crash_enable ENABLE
    781 **
    782 ** Parameter ENABLE must be a boolean value. If true, then the "crash"
    783 ** vfs is added to the system. If false, it is removed.
    784 */
    785 static int crashEnableCmd(
    786   void * clientData,
    787   Tcl_Interp *interp,
    788   int objc,
    789   Tcl_Obj *CONST objv[]
    790 ){
    791   int isEnable;
    792   static sqlite3_vfs crashVfs = {
    793     2,                  /* iVersion */
    794     0,                  /* szOsFile */
    795     0,                  /* mxPathname */
    796     0,                  /* pNext */
    797     "crash",            /* zName */
    798     0,                  /* pAppData */
    799 
    800     cfOpen,               /* xOpen */
    801     cfDelete,             /* xDelete */
    802     cfAccess,             /* xAccess */
    803     cfFullPathname,       /* xFullPathname */
    804     cfDlOpen,             /* xDlOpen */
    805     cfDlError,            /* xDlError */
    806     cfDlSym,              /* xDlSym */
    807     cfDlClose,            /* xDlClose */
    808     cfRandomness,         /* xRandomness */
    809     cfSleep,              /* xSleep */
    810     cfCurrentTime,        /* xCurrentTime */
    811     0,                    /* xGetlastError */
    812     0,                    /* xCurrentTimeInt64 */
    813   };
    814 
    815   if( objc!=2 ){
    816     Tcl_WrongNumArgs(interp, 1, objv, "ENABLE");
    817     return TCL_ERROR;
    818   }
    819 
    820   if( Tcl_GetBooleanFromObj(interp, objv[1], &isEnable) ){
    821     return TCL_ERROR;
    822   }
    823 
    824   if( (isEnable && crashVfs.pAppData) || (!isEnable && !crashVfs.pAppData) ){
    825     return TCL_OK;
    826   }
    827 
    828   if( crashVfs.pAppData==0 ){
    829     sqlite3_vfs *pOriginalVfs = sqlite3_vfs_find(0);
    830     crashVfs.mxPathname = pOriginalVfs->mxPathname;
    831     crashVfs.pAppData = (void *)pOriginalVfs;
    832     crashVfs.szOsFile = sizeof(CrashFile) + pOriginalVfs->szOsFile;
    833     sqlite3_vfs_register(&crashVfs, 0);
    834   }else{
    835     crashVfs.pAppData = 0;
    836     sqlite3_vfs_unregister(&crashVfs);
    837   }
    838 
    839   return TCL_OK;
    840 }
    841 
    842 /*
    843 ** tclcmd:   sqlite_crashparams ?OPTIONS? DELAY CRASHFILE
    844 **
    845 ** This procedure implements a TCL command that enables crash testing
    846 ** in testfixture.  Once enabled, crash testing cannot be disabled.
    847 **
    848 ** Available options are "-characteristics" and "-sectorsize". Both require
    849 ** an argument. For -sectorsize, this is the simulated sector size in
    850 ** bytes. For -characteristics, the argument must be a list of io-capability
    851 ** flags to simulate. Valid flags are "atomic", "atomic512", "atomic1K",
    852 ** "atomic2K", "atomic4K", "atomic8K", "atomic16K", "atomic32K",
    853 ** "atomic64K", "sequential" and "safe_append".
    854 **
    855 ** Example:
    856 **
    857 **   sqlite_crashparams -sect 1024 -char {atomic sequential} ./test.db 1
    858 **
    859 */
    860 static int crashParamsObjCmd(
    861   void * clientData,
    862   Tcl_Interp *interp,
    863   int objc,
    864   Tcl_Obj *CONST objv[]
    865 ){
    866   int iDelay;
    867   const char *zCrashFile;
    868   int nCrashFile, iDc, iSectorSize;
    869 
    870   iDc = -1;
    871   iSectorSize = -1;
    872 
    873   if( objc<3 ){
    874     Tcl_WrongNumArgs(interp, 1, objv, "?OPTIONS? DELAY CRASHFILE");
    875     goto error;
    876   }
    877 
    878   zCrashFile = Tcl_GetStringFromObj(objv[objc-1], &nCrashFile);
    879   if( nCrashFile>=sizeof(g.zCrashFile) ){
    880     Tcl_AppendResult(interp, "Filename is too long: \"", zCrashFile, "\"", 0);
    881     goto error;
    882   }
    883   if( Tcl_GetIntFromObj(interp, objv[objc-2], &iDelay) ){
    884     goto error;
    885   }
    886 
    887   if( processDevSymArgs(interp, objc-3, &objv[1], &iDc, &iSectorSize) ){
    888     return TCL_ERROR;
    889   }
    890 
    891   if( iDc>=0 ){
    892     g.iDeviceCharacteristics = iDc;
    893   }
    894   if( iSectorSize>=0 ){
    895     g.iSectorSize = iSectorSize;
    896   }
    897 
    898   g.iCrash = iDelay;
    899   memcpy(g.zCrashFile, zCrashFile, nCrashFile+1);
    900   sqlite3CrashTestEnable = 1;
    901   return TCL_OK;
    902 
    903 error:
    904   return TCL_ERROR;
    905 }
    906 
    907 static int devSymObjCmd(
    908   void * clientData,
    909   Tcl_Interp *interp,
    910   int objc,
    911   Tcl_Obj *CONST objv[]
    912 ){
    913   void devsym_register(int iDeviceChar, int iSectorSize);
    914 
    915   int iDc = -1;
    916   int iSectorSize = -1;
    917 
    918   if( processDevSymArgs(interp, objc-1, &objv[1], &iDc, &iSectorSize) ){
    919     return TCL_ERROR;
    920   }
    921   devsym_register(iDc, iSectorSize);
    922 
    923   return TCL_OK;
    924 }
    925 
    926 /*
    927 ** tclcmd: register_jt_vfs ?-default? PARENT-VFS
    928 */
    929 static int jtObjCmd(
    930   void * clientData,
    931   Tcl_Interp *interp,
    932   int objc,
    933   Tcl_Obj *CONST objv[]
    934 ){
    935   int jt_register(char *, int);
    936   char *zParent = 0;
    937 
    938   if( objc!=2 && objc!=3 ){
    939     Tcl_WrongNumArgs(interp, 1, objv, "?-default? PARENT-VFS");
    940     return TCL_ERROR;
    941   }
    942   zParent = Tcl_GetString(objv[1]);
    943   if( objc==3 ){
    944     if( strcmp(zParent, "-default") ){
    945       Tcl_AppendResult(interp,
    946           "bad option \"", zParent, "\": must be -default", 0
    947       );
    948       return TCL_ERROR;
    949     }
    950     zParent = Tcl_GetString(objv[2]);
    951   }
    952 
    953   if( !(*zParent) ){
    954     zParent = 0;
    955   }
    956   if( jt_register(zParent, objc==3) ){
    957     Tcl_AppendResult(interp, "Error in jt_register", 0);
    958     return TCL_ERROR;
    959   }
    960 
    961   return TCL_OK;
    962 }
    963 
    964 /*
    965 ** tclcmd: unregister_jt_vfs
    966 */
    967 static int jtUnregisterObjCmd(
    968   void * clientData,
    969   Tcl_Interp *interp,
    970   int objc,
    971   Tcl_Obj *CONST objv[]
    972 ){
    973   void jt_unregister(void);
    974 
    975   if( objc!=1 ){
    976     Tcl_WrongNumArgs(interp, 1, objv, "");
    977     return TCL_ERROR;
    978   }
    979 
    980   jt_unregister();
    981   return TCL_OK;
    982 }
    983 
    984 #endif /* SQLITE_OMIT_DISKIO */
    985 
    986 /*
    987 ** This procedure registers the TCL procedures defined in this file.
    988 */
    989 int Sqlitetest6_Init(Tcl_Interp *interp){
    990 #ifndef SQLITE_OMIT_DISKIO
    991   Tcl_CreateObjCommand(interp, "sqlite3_crash_enable", crashEnableCmd, 0, 0);
    992   Tcl_CreateObjCommand(interp, "sqlite3_crashparams", crashParamsObjCmd, 0, 0);
    993   Tcl_CreateObjCommand(interp, "sqlite3_simulate_device", devSymObjCmd, 0, 0);
    994   Tcl_CreateObjCommand(interp, "register_jt_vfs", jtObjCmd, 0, 0);
    995   Tcl_CreateObjCommand(interp, "unregister_jt_vfs", jtUnregisterObjCmd, 0, 0);
    996 #endif
    997   return TCL_OK;
    998 }
    999 
   1000 #endif /* SQLITE_TEST */
   1001