modernc.org/cc@v1.0.1/v2/testdata/_sqlite/src/test_journal.c (about)

     1  /*
     2  ** 2008 Jan 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 for a VFS layer that acts as a wrapper around
    14  ** an existing VFS. The code in this file attempts to verify that SQLite
    15  ** correctly populates and syncs a journal file before writing to a
    16  ** corresponding database file.
    17  **
    18  ** INTERFACE
    19  **
    20  **   The public interface to this wrapper VFS is two functions:
    21  **
    22  **     jt_register()
    23  **     jt_unregister()
    24  **
    25  **   See header comments associated with those two functions below for 
    26  **   details.
    27  **
    28  ** LIMITATIONS
    29  **
    30  **   This wrapper will not work if "PRAGMA synchronous = off" is used.
    31  **
    32  ** OPERATION
    33  **
    34  **  Starting a Transaction:
    35  **
    36  **   When a write-transaction is started, the contents of the database is
    37  **   inspected and the following data stored as part of the database file 
    38  **   handle (type struct jt_file):
    39  **
    40  **     a) The page-size of the database file.
    41  **     b) The number of pages that are in the database file.
    42  **     c) The set of page numbers corresponding to free-list leaf pages.
    43  **     d) A check-sum for every page in the database file.
    44  **
    45  **   The start of a write-transaction is deemed to have occurred when a 
    46  **   28-byte journal header is written to byte offset 0 of the journal 
    47  **   file.
    48  **
    49  **  Syncing the Journal File:
    50  **
    51  **   Whenever the xSync method is invoked to sync a journal-file, the
    52  **   contents of the journal file are read. For each page written to
    53  **   the journal file, a check-sum is calculated and compared to the  
    54  **   check-sum calculated for the corresponding database page when the
    55  **   write-transaction was initialized. The success of the comparison
    56  **   is assert()ed. So if SQLite has written something other than the
    57  **   original content to the database file, an assert() will fail.
    58  **
    59  **   Additionally, the set of page numbers for which records exist in
    60  **   the journal file is added to (unioned with) the set of page numbers
    61  **   corresponding to free-list leaf pages collected when the 
    62  **   write-transaction was initialized. This set comprises the page-numbers 
    63  **   corresponding to those pages that SQLite may now safely modify.
    64  **
    65  **  Writing to the Database File:
    66  **
    67  **   When a block of data is written to a database file, the following
    68  **   invariants are asserted:
    69  **
    70  **     a) That the block of data is an aligned block of page-size bytes.
    71  **
    72  **     b) That if the page being written did not exist when the 
    73  **        transaction was started (i.e. the database file is growing), then
    74  **        the journal-file must have been synced at least once since
    75  **        the start of the transaction.
    76  **
    77  **     c) That if the page being written did exist when the transaction 
    78  **        was started, then the page must have either been a free-list
    79  **        leaf page at the start of the transaction, or else must have
    80  **        been stored in the journal file prior to the most recent sync.
    81  **
    82  **  Closing a Transaction:
    83  **
    84  **   When a transaction is closed, all data collected at the start of
    85  **   the transaction, or following an xSync of a journal-file, is 
    86  **   discarded. The end of a transaction is recognized when any one 
    87  **   of the following occur:
    88  **
    89  **     a) A block of zeroes (or anything else that is not a valid 
    90  **        journal-header) is written to the start of the journal file.
    91  **
    92  **     b) A journal file is truncated to zero bytes in size using xTruncate.
    93  **
    94  **     c) The journal file is deleted using xDelete.
    95  */
    96  #if SQLITE_TEST          /* This file is used for testing only */
    97  
    98  #include "sqlite3.h"
    99  #include "sqliteInt.h"
   100  
   101  /*
   102  ** Maximum pathname length supported by the jt backend.
   103  */
   104  #define JT_MAX_PATHNAME 512
   105  
   106  /*
   107  ** Name used to identify this VFS.
   108  */
   109  #define JT_VFS_NAME "jt"
   110  
   111  typedef struct jt_file jt_file;
   112  struct jt_file {
   113    sqlite3_file base;
   114    const char *zName;       /* Name of open file */
   115    int flags;               /* Flags the file was opened with */
   116  
   117    /* The following are only used by database file file handles */
   118    int eLock;               /* Current lock held on the file */
   119    u32 nPage;               /* Size of file in pages when transaction started */
   120    u32 nPagesize;           /* Page size when transaction started */
   121    Bitvec *pWritable;       /* Bitvec of pages that may be written to the file */
   122    u32 *aCksum;             /* Checksum for first nPage pages */
   123    int nSync;               /* Number of times journal file has been synced */
   124  
   125    /* Only used by journal file-handles */
   126    sqlite3_int64 iMaxOff;   /* Maximum offset written to this transaction */
   127  
   128    jt_file *pNext;          /* All files are stored in a linked list */
   129    sqlite3_file *pReal;     /* The file handle for the underlying vfs */
   130  };
   131  
   132  /*
   133  ** Method declarations for jt_file.
   134  */
   135  static int jtClose(sqlite3_file*);
   136  static int jtRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
   137  static int jtWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
   138  static int jtTruncate(sqlite3_file*, sqlite3_int64 size);
   139  static int jtSync(sqlite3_file*, int flags);
   140  static int jtFileSize(sqlite3_file*, sqlite3_int64 *pSize);
   141  static int jtLock(sqlite3_file*, int);
   142  static int jtUnlock(sqlite3_file*, int);
   143  static int jtCheckReservedLock(sqlite3_file*, int *);
   144  static int jtFileControl(sqlite3_file*, int op, void *pArg);
   145  static int jtSectorSize(sqlite3_file*);
   146  static int jtDeviceCharacteristics(sqlite3_file*);
   147  
   148  /*
   149  ** Method declarations for jt_vfs.
   150  */
   151  static int jtOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
   152  static int jtDelete(sqlite3_vfs*, const char *zName, int syncDir);
   153  static int jtAccess(sqlite3_vfs*, const char *zName, int flags, int *);
   154  static int jtFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
   155  static void *jtDlOpen(sqlite3_vfs*, const char *zFilename);
   156  static void jtDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
   157  static void (*jtDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
   158  static void jtDlClose(sqlite3_vfs*, void*);
   159  static int jtRandomness(sqlite3_vfs*, int nByte, char *zOut);
   160  static int jtSleep(sqlite3_vfs*, int microseconds);
   161  static int jtCurrentTime(sqlite3_vfs*, double*);
   162  static int jtCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
   163  static int jtGetLastError(sqlite3_vfs*, int, char*);
   164  
   165  static sqlite3_vfs jt_vfs = {
   166    2,                             /* iVersion */
   167    sizeof(jt_file),               /* szOsFile */
   168    JT_MAX_PATHNAME,               /* mxPathname */
   169    0,                             /* pNext */
   170    JT_VFS_NAME,                   /* zName */
   171    0,                             /* pAppData */
   172    jtOpen,                        /* xOpen */
   173    jtDelete,                      /* xDelete */
   174    jtAccess,                      /* xAccess */
   175    jtFullPathname,                /* xFullPathname */
   176    jtDlOpen,                      /* xDlOpen */
   177    jtDlError,                     /* xDlError */
   178    jtDlSym,                       /* xDlSym */
   179    jtDlClose,                     /* xDlClose */
   180    jtRandomness,                  /* xRandomness */
   181    jtSleep,                       /* xSleep */
   182    jtCurrentTime,                 /* xCurrentTime */
   183    jtGetLastError,                /* xGetLastError */
   184    jtCurrentTimeInt64             /* xCurrentTimeInt64 */
   185  };
   186  
   187  static sqlite3_io_methods jt_io_methods = {
   188    1,                             /* iVersion */
   189    jtClose,                       /* xClose */
   190    jtRead,                        /* xRead */
   191    jtWrite,                       /* xWrite */
   192    jtTruncate,                    /* xTruncate */
   193    jtSync,                        /* xSync */
   194    jtFileSize,                    /* xFileSize */
   195    jtLock,                        /* xLock */
   196    jtUnlock,                      /* xUnlock */
   197    jtCheckReservedLock,           /* xCheckReservedLock */
   198    jtFileControl,                 /* xFileControl */
   199    jtSectorSize,                  /* xSectorSize */
   200    jtDeviceCharacteristics        /* xDeviceCharacteristics */
   201  };
   202  
   203  struct JtGlobal {
   204    sqlite3_vfs *pVfs;             /* Parent VFS */
   205    jt_file *pList;                /* List of all open files */
   206  };
   207  static struct JtGlobal g = {0, 0};
   208  
   209  /*
   210  ** Functions to obtain and relinquish a mutex to protect g.pList. The
   211  ** STATIC_PRNG mutex is reused, purely for the sake of convenience.
   212  */
   213  static void enterJtMutex(void){
   214    sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PRNG));
   215  }
   216  static void leaveJtMutex(void){
   217    sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_PRNG));
   218  }
   219  
   220  extern int sqlite3_io_error_pending;
   221  extern int sqlite3_io_error_hit;
   222  static void stop_ioerr_simulation(int *piSave, int *piSave2){
   223    *piSave = sqlite3_io_error_pending;
   224    *piSave2 = sqlite3_io_error_hit;
   225    sqlite3_io_error_pending = -1;
   226    sqlite3_io_error_hit = 0;
   227  }
   228  static void start_ioerr_simulation(int iSave, int iSave2){
   229    sqlite3_io_error_pending = iSave;
   230    sqlite3_io_error_hit = iSave2;
   231  }
   232  
   233  /*
   234  ** The jt_file pointed to by the argument may or may not be a file-handle
   235  ** open on a main database file. If it is, and a transaction is currently
   236  ** opened on the file, then discard all transaction related data.
   237  */
   238  static void closeTransaction(jt_file *p){
   239    sqlite3BitvecDestroy(p->pWritable);
   240    sqlite3_free(p->aCksum);
   241    p->pWritable = 0;
   242    p->aCksum = 0;
   243    p->nSync = 0;
   244  }
   245  
   246  /*
   247  ** Close an jt-file.
   248  */
   249  static int jtClose(sqlite3_file *pFile){
   250    jt_file **pp;
   251    jt_file *p = (jt_file *)pFile;
   252  
   253    closeTransaction(p);
   254    enterJtMutex();
   255    if( p->zName ){
   256      for(pp=&g.pList; *pp!=p; pp=&(*pp)->pNext);
   257      *pp = p->pNext;
   258    }
   259    leaveJtMutex();
   260    sqlite3OsClose(p->pReal);
   261    return SQLITE_OK;
   262  }
   263  
   264  /*
   265  ** Read data from an jt-file.
   266  */
   267  static int jtRead(
   268    sqlite3_file *pFile, 
   269    void *zBuf, 
   270    int iAmt, 
   271    sqlite_int64 iOfst
   272  ){
   273    jt_file *p = (jt_file *)pFile;
   274    return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
   275  }
   276  
   277  /*
   278  ** Parameter zJournal is the name of a journal file that is currently 
   279  ** open. This function locates and returns the handle opened on the
   280  ** corresponding database file by the pager that currently has the
   281  ** journal file opened. This file-handle is identified by the 
   282  ** following properties:
   283  **
   284  **   a) SQLITE_OPEN_MAIN_DB was specified when the file was opened.
   285  **
   286  **   b) The file-name specified when the file was opened matches
   287  **      all but the final 8 characters of the journal file name.
   288  **
   289  **   c) There is currently a reserved lock on the file. This 
   290  **      condition is waived if the noLock argument is non-zero.
   291  **/
   292  static jt_file *locateDatabaseHandle(const char *zJournal, int noLock){
   293    jt_file *pMain = 0;
   294    enterJtMutex();
   295    for(pMain=g.pList; pMain; pMain=pMain->pNext){
   296      int nName = (int)(strlen(zJournal) - strlen("-journal"));
   297      if( (pMain->flags&SQLITE_OPEN_MAIN_DB)
   298       && ((int)strlen(pMain->zName)==nName)
   299       && 0==memcmp(pMain->zName, zJournal, nName)
   300       && ((pMain->eLock>=SQLITE_LOCK_RESERVED) || noLock)
   301      ){
   302        break;
   303      }
   304    }
   305    leaveJtMutex();
   306    return pMain;
   307  }
   308  
   309  /*
   310  ** Parameter z points to a buffer of 4 bytes in size containing a 
   311  ** unsigned 32-bit integer stored in big-endian format. Decode the 
   312  ** integer and return its value.
   313  */
   314  static u32 decodeUint32(const unsigned char *z){
   315    return (z[0]<<24) + (z[1]<<16) + (z[2]<<8) + z[3];
   316  }
   317  
   318  /*
   319  ** Calculate a checksum from the buffer of length n bytes pointed to
   320  ** by parameter z.
   321  */
   322  static u32 genCksum(const unsigned char *z, int n){
   323    int i;
   324    u32 cksum = 0;
   325    for(i=0; i<n; i++){
   326      cksum = cksum + z[i] + (cksum<<3);
   327    }
   328    return cksum;
   329  }
   330  
   331  /*
   332  ** The first argument, zBuf, points to a buffer containing a 28 byte
   333  ** serialized journal header. This function deserializes four of the
   334  ** integer fields contained in the journal header and writes their
   335  ** values to the output variables.
   336  **
   337  ** SQLITE_OK is returned if the journal-header is successfully 
   338  ** decoded. Otherwise, SQLITE_ERROR.
   339  */
   340  static int decodeJournalHdr(
   341    const unsigned char *zBuf,         /* Input: 28 byte journal header */
   342    u32 *pnRec,                        /* Out: Number of journalled records */
   343    u32 *pnPage,                       /* Out: Original database page count */
   344    u32 *pnSector,                     /* Out: Sector size in bytes */
   345    u32 *pnPagesize                    /* Out: Page size in bytes */
   346  ){
   347    unsigned char aMagic[] = { 0xd9, 0xd5, 0x05, 0xf9, 0x20, 0xa1, 0x63, 0xd7 };
   348    if( memcmp(aMagic, zBuf, 8) ) return SQLITE_ERROR;
   349    if( pnRec ) *pnRec = decodeUint32(&zBuf[8]);
   350    if( pnPage ) *pnPage = decodeUint32(&zBuf[16]);
   351    if( pnSector ) *pnSector = decodeUint32(&zBuf[20]);
   352    if( pnPagesize ) *pnPagesize = decodeUint32(&zBuf[24]);
   353    return SQLITE_OK;
   354  }
   355  
   356  /*
   357  ** This function is called when a new transaction is opened, just after
   358  ** the first journal-header is written to the journal file.
   359  */
   360  static int openTransaction(jt_file *pMain, jt_file *pJournal){
   361    unsigned char *aData;
   362    sqlite3_file *p = pMain->pReal;
   363    int rc = SQLITE_OK;
   364  
   365    closeTransaction(pMain);
   366    aData = sqlite3_malloc(pMain->nPagesize);
   367    pMain->pWritable = sqlite3BitvecCreate(pMain->nPage);
   368    pMain->aCksum = sqlite3_malloc(sizeof(u32) * (pMain->nPage + 1));
   369    pJournal->iMaxOff = 0;
   370  
   371    if( !pMain->pWritable || !pMain->aCksum || !aData ){
   372      rc = SQLITE_IOERR_NOMEM;
   373    }else if( pMain->nPage>0 ){
   374      u32 iTrunk;
   375      int iSave;
   376      int iSave2;
   377  
   378      stop_ioerr_simulation(&iSave, &iSave2);
   379  
   380      /* Read the database free-list. Add the page-number for each free-list
   381      ** leaf to the jt_file.pWritable bitvec.
   382      */
   383      rc = sqlite3OsRead(p, aData, pMain->nPagesize, 0);
   384      if( rc==SQLITE_OK ){
   385        u32 nDbsize = decodeUint32(&aData[28]);
   386        if( nDbsize>0 && memcmp(&aData[24], &aData[92], 4)==0 ){
   387          u32 iPg;
   388          for(iPg=nDbsize+1; iPg<=pMain->nPage; iPg++){
   389            sqlite3BitvecSet(pMain->pWritable, iPg);
   390          }
   391        }
   392      }
   393      iTrunk = decodeUint32(&aData[32]);
   394      while( rc==SQLITE_OK && iTrunk>0 ){
   395        u32 nLeaf;
   396        u32 iLeaf;
   397        sqlite3_int64 iOff = (i64)(iTrunk-1)*pMain->nPagesize;
   398        rc = sqlite3OsRead(p, aData, pMain->nPagesize, iOff);
   399        nLeaf = decodeUint32(&aData[4]);
   400        for(iLeaf=0; rc==SQLITE_OK && iLeaf<nLeaf; iLeaf++){
   401          u32 pgno = decodeUint32(&aData[8+4*iLeaf]);
   402          sqlite3BitvecSet(pMain->pWritable, pgno);
   403        }
   404        iTrunk = decodeUint32(aData);
   405      }
   406  
   407      /* Calculate and store a checksum for each page in the database file. */
   408      if( rc==SQLITE_OK ){
   409        int ii;
   410        for(ii=0; rc==SQLITE_OK && ii<(int)pMain->nPage; ii++){
   411          i64 iOff = (i64)(pMain->nPagesize) * (i64)ii;
   412          if( iOff==PENDING_BYTE ) continue;
   413          rc = sqlite3OsRead(pMain->pReal, aData, pMain->nPagesize, iOff);
   414          pMain->aCksum[ii] = genCksum(aData, pMain->nPagesize);
   415          if( ii+1==(int)pMain->nPage && rc==SQLITE_IOERR_SHORT_READ ){
   416            rc = SQLITE_OK;
   417          }
   418        }
   419      }
   420  
   421      start_ioerr_simulation(iSave, iSave2);
   422    }
   423  
   424    sqlite3_free(aData);
   425    return rc;
   426  }
   427  
   428  /*
   429  ** The first argument to this function is a handle open on a journal file.
   430  ** This function reads the journal file and adds the page number for each
   431  ** page in the journal to the Bitvec object passed as the second argument.
   432  */
   433  static int readJournalFile(jt_file *p, jt_file *pMain){
   434    int rc = SQLITE_OK;
   435    unsigned char zBuf[28];
   436    sqlite3_file *pReal = p->pReal;
   437    sqlite3_int64 iOff = 0;
   438    sqlite3_int64 iSize = p->iMaxOff;
   439    unsigned char *aPage;
   440    int iSave;
   441    int iSave2;
   442  
   443    aPage = sqlite3_malloc(pMain->nPagesize);
   444    if( !aPage ){
   445      return SQLITE_IOERR_NOMEM;
   446    }
   447  
   448    stop_ioerr_simulation(&iSave, &iSave2);
   449  
   450    while( rc==SQLITE_OK && iOff<iSize ){
   451      u32 nRec, nPage, nSector, nPagesize;
   452      u32 ii;
   453  
   454      /* Read and decode the next journal-header from the journal file. */
   455      rc = sqlite3OsRead(pReal, zBuf, 28, iOff);
   456      if( rc!=SQLITE_OK 
   457       || decodeJournalHdr(zBuf, &nRec, &nPage, &nSector, &nPagesize) 
   458      ){
   459        goto finish_rjf;
   460      }
   461      iOff += nSector;
   462  
   463      if( nRec==0 ){
   464        /* A trick. There might be another journal-header immediately 
   465        ** following this one. In this case, 0 records means 0 records, 
   466        ** not "read until the end of the file". See also ticket #2565.
   467        */
   468        if( iSize>=(iOff+nSector) ){
   469          rc = sqlite3OsRead(pReal, zBuf, 28, iOff);
   470          if( rc!=SQLITE_OK || 0==decodeJournalHdr(zBuf, 0, 0, 0, 0) ){
   471            continue;
   472          }
   473        }
   474        nRec = (u32)((iSize-iOff) / (pMain->nPagesize+8));
   475      }
   476  
   477      /* Read all the records that follow the journal-header just read. */
   478      for(ii=0; rc==SQLITE_OK && ii<nRec && iOff<iSize; ii++){
   479        u32 pgno;
   480        rc = sqlite3OsRead(pReal, zBuf, 4, iOff);
   481        if( rc==SQLITE_OK ){
   482          pgno = decodeUint32(zBuf);
   483          if( pgno>0 && pgno<=pMain->nPage ){
   484            if( 0==sqlite3BitvecTest(pMain->pWritable, pgno) ){
   485              rc = sqlite3OsRead(pReal, aPage, pMain->nPagesize, iOff+4);
   486              if( rc==SQLITE_OK ){
   487                u32 cksum = genCksum(aPage, pMain->nPagesize);
   488                assert( cksum==pMain->aCksum[pgno-1] );
   489              }
   490            }
   491            sqlite3BitvecSet(pMain->pWritable, pgno);
   492          }
   493          iOff += (8 + pMain->nPagesize);
   494        }
   495      }
   496  
   497      iOff = ((iOff + (nSector-1)) / nSector) * nSector;
   498    }
   499  
   500  finish_rjf:
   501    start_ioerr_simulation(iSave, iSave2);
   502    sqlite3_free(aPage);
   503    if( rc==SQLITE_IOERR_SHORT_READ ){
   504      rc = SQLITE_OK;
   505    }
   506    return rc;
   507  }
   508  
   509  /*
   510  ** Write data to an jt-file.
   511  */
   512  static int jtWrite(
   513    sqlite3_file *pFile, 
   514    const void *zBuf, 
   515    int iAmt, 
   516    sqlite_int64 iOfst
   517  ){
   518    int rc;
   519    jt_file *p = (jt_file *)pFile;
   520    if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){
   521      if( iOfst==0 ){
   522        jt_file *pMain = locateDatabaseHandle(p->zName, 0);
   523        assert( pMain );
   524    
   525        if( iAmt==28 ){
   526          /* Zeroing the first journal-file header. This is the end of a
   527          ** transaction. */
   528          closeTransaction(pMain);
   529        }else if( iAmt!=12 ){
   530          /* Writing the first journal header to a journal file. This happens
   531          ** when a transaction is first started.  */
   532          u8 *z = (u8 *)zBuf;
   533          pMain->nPage = decodeUint32(&z[16]);
   534          pMain->nPagesize = decodeUint32(&z[24]);
   535          if( SQLITE_OK!=(rc=openTransaction(pMain, p)) ){
   536            return rc;
   537          }
   538        }
   539      }
   540      if( p->iMaxOff<(iOfst + iAmt) ){
   541        p->iMaxOff = iOfst + iAmt;
   542      }
   543    }
   544  
   545    if( p->flags&SQLITE_OPEN_MAIN_DB && p->pWritable ){
   546      if( iAmt<(int)p->nPagesize 
   547       && p->nPagesize%iAmt==0 
   548       && iOfst>=(PENDING_BYTE+512) 
   549       && iOfst+iAmt<=PENDING_BYTE+p->nPagesize
   550      ){
   551        /* No-op. This special case is hit when the backup code is copying a
   552        ** to a database with a larger page-size than the source database and
   553        ** it needs to fill in the non-locking-region part of the original
   554        ** pending-byte page.
   555        */
   556      }else{
   557        u32 pgno = (u32)(iOfst/p->nPagesize + 1);
   558        assert( (iAmt==1||iAmt==(int)p->nPagesize) &&
   559                ((iOfst+iAmt)%p->nPagesize)==0 );
   560        /* The following assert() statements may fail if this layer is used
   561        ** with a connection in "PRAGMA synchronous=off" mode. If they
   562        ** fail with sync=normal or sync=full, this may indicate problem.  */
   563        assert( pgno<=p->nPage || p->nSync>0 );
   564        assert( pgno>p->nPage || sqlite3BitvecTest(p->pWritable, pgno) );
   565      }
   566    }
   567  
   568    rc = sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
   569    if( (p->flags&SQLITE_OPEN_MAIN_JOURNAL) && iAmt==12 ){
   570      jt_file *pMain = locateDatabaseHandle(p->zName, 0);
   571      int rc2 = readJournalFile(p, pMain);
   572      if( rc==SQLITE_OK ) rc = rc2;
   573    }
   574    return rc;
   575  }
   576  
   577  /*
   578  ** Truncate an jt-file.
   579  */
   580  static int jtTruncate(sqlite3_file *pFile, sqlite_int64 size){
   581    jt_file *p = (jt_file *)pFile;
   582    if( p->flags&SQLITE_OPEN_MAIN_JOURNAL && size==0 ){
   583      /* Truncating a journal file. This is the end of a transaction. */
   584      jt_file *pMain = locateDatabaseHandle(p->zName, 0);
   585      closeTransaction(pMain);
   586    }
   587    if( p->flags&SQLITE_OPEN_MAIN_DB && p->pWritable ){
   588      u32 pgno;
   589      u32 locking_page = (u32)(PENDING_BYTE/p->nPagesize+1);
   590      for(pgno=(u32)(size/p->nPagesize+1); pgno<=p->nPage; pgno++){
   591        assert( pgno==locking_page || sqlite3BitvecTest(p->pWritable, pgno) );
   592      }
   593    }
   594    return sqlite3OsTruncate(p->pReal, size);
   595  }
   596  
   597  /*
   598  ** Sync an jt-file.
   599  */
   600  static int jtSync(sqlite3_file *pFile, int flags){
   601    jt_file *p = (jt_file *)pFile;
   602  
   603    if( p->flags&SQLITE_OPEN_MAIN_JOURNAL ){
   604      int rc;
   605      jt_file *pMain;                   /* The associated database file */
   606  
   607      /* The journal file is being synced. At this point, we inspect the 
   608      ** contents of the file up to this point and set each bit in the 
   609      ** jt_file.pWritable bitvec of the main database file associated with
   610      ** this journal file.
   611      */
   612      pMain = locateDatabaseHandle(p->zName, 0);
   613  
   614      /* Set the bitvec values */
   615      if( pMain && pMain->pWritable ){
   616        pMain->nSync++;
   617        rc = readJournalFile(p, pMain);
   618        if( rc!=SQLITE_OK ){
   619          return rc;
   620        }
   621      }
   622    }
   623  
   624    return sqlite3OsSync(p->pReal, flags);
   625  }
   626  
   627  /*
   628  ** Return the current file-size of an jt-file.
   629  */
   630  static int jtFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
   631    jt_file *p = (jt_file *)pFile;
   632    return sqlite3OsFileSize(p->pReal, pSize);
   633  }
   634  
   635  /*
   636  ** Lock an jt-file.
   637  */
   638  static int jtLock(sqlite3_file *pFile, int eLock){
   639    int rc;
   640    jt_file *p = (jt_file *)pFile;
   641    rc = sqlite3OsLock(p->pReal, eLock);
   642    if( rc==SQLITE_OK && eLock>p->eLock ){
   643      p->eLock = eLock;
   644    }
   645    return rc;
   646  }
   647  
   648  /*
   649  ** Unlock an jt-file.
   650  */
   651  static int jtUnlock(sqlite3_file *pFile, int eLock){
   652    int rc;
   653    jt_file *p = (jt_file *)pFile;
   654    rc = sqlite3OsUnlock(p->pReal, eLock);
   655    if( rc==SQLITE_OK && eLock<p->eLock ){
   656      p->eLock = eLock;
   657    }
   658    return rc;
   659  }
   660  
   661  /*
   662  ** Check if another file-handle holds a RESERVED lock on an jt-file.
   663  */
   664  static int jtCheckReservedLock(sqlite3_file *pFile, int *pResOut){
   665    jt_file *p = (jt_file *)pFile;
   666    return sqlite3OsCheckReservedLock(p->pReal, pResOut);
   667  }
   668  
   669  /*
   670  ** File control method. For custom operations on an jt-file.
   671  */
   672  static int jtFileControl(sqlite3_file *pFile, int op, void *pArg){
   673    jt_file *p = (jt_file *)pFile;
   674    return p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
   675  }
   676  
   677  /*
   678  ** Return the sector-size in bytes for an jt-file.
   679  */
   680  static int jtSectorSize(sqlite3_file *pFile){
   681    jt_file *p = (jt_file *)pFile;
   682    return sqlite3OsSectorSize(p->pReal);
   683  }
   684  
   685  /*
   686  ** Return the device characteristic flags supported by an jt-file.
   687  */
   688  static int jtDeviceCharacteristics(sqlite3_file *pFile){
   689    jt_file *p = (jt_file *)pFile;
   690    return sqlite3OsDeviceCharacteristics(p->pReal);
   691  }
   692  
   693  /*
   694  ** Open an jt file handle.
   695  */
   696  static int jtOpen(
   697    sqlite3_vfs *pVfs,
   698    const char *zName,
   699    sqlite3_file *pFile,
   700    int flags,
   701    int *pOutFlags
   702  ){
   703    int rc;
   704    jt_file *p = (jt_file *)pFile;
   705    pFile->pMethods = 0;
   706    p->pReal = (sqlite3_file *)&p[1];
   707    p->pReal->pMethods = 0;
   708    rc = sqlite3OsOpen(g.pVfs, zName, p->pReal, flags, pOutFlags);
   709    assert( rc==SQLITE_OK || p->pReal->pMethods==0 );
   710    if( rc==SQLITE_OK ){
   711      pFile->pMethods = &jt_io_methods;
   712      p->eLock = 0;
   713      p->zName = zName;
   714      p->flags = flags;
   715      p->pNext = 0;
   716      p->pWritable = 0;
   717      p->aCksum = 0;
   718      enterJtMutex();
   719      if( zName ){
   720        p->pNext = g.pList;
   721        g.pList = p;
   722      }
   723      leaveJtMutex();
   724    }
   725    return rc;
   726  }
   727  
   728  /*
   729  ** Delete the file located at zPath. If the dirSync argument is true,
   730  ** ensure the file-system modifications are synced to disk before
   731  ** returning.
   732  */
   733  static int jtDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
   734    int nPath = (int)strlen(zPath);
   735    if( nPath>8 && 0==strcmp("-journal", &zPath[nPath-8]) ){
   736      /* Deleting a journal file. The end of a transaction. */
   737      jt_file *pMain = locateDatabaseHandle(zPath, 0);
   738      if( pMain ){
   739        closeTransaction(pMain);
   740      }
   741    }
   742  
   743    return sqlite3OsDelete(g.pVfs, zPath, dirSync);
   744  }
   745  
   746  /*
   747  ** Test for access permissions. Return true if the requested permission
   748  ** is available, or false otherwise.
   749  */
   750  static int jtAccess(
   751    sqlite3_vfs *pVfs, 
   752    const char *zPath, 
   753    int flags, 
   754    int *pResOut
   755  ){
   756    return sqlite3OsAccess(g.pVfs, zPath, flags, pResOut);
   757  }
   758  
   759  /*
   760  ** Populate buffer zOut with the full canonical pathname corresponding
   761  ** to the pathname in zPath. zOut is guaranteed to point to a buffer
   762  ** of at least (JT_MAX_PATHNAME+1) bytes.
   763  */
   764  static int jtFullPathname(
   765    sqlite3_vfs *pVfs, 
   766    const char *zPath, 
   767    int nOut, 
   768    char *zOut
   769  ){
   770    return sqlite3OsFullPathname(g.pVfs, zPath, nOut, zOut);
   771  }
   772  
   773  /*
   774  ** Open the dynamic library located at zPath and return a handle.
   775  */
   776  static void *jtDlOpen(sqlite3_vfs *pVfs, const char *zPath){
   777    return g.pVfs->xDlOpen(g.pVfs, zPath);
   778  }
   779  
   780  /*
   781  ** Populate the buffer zErrMsg (size nByte bytes) with a human readable
   782  ** utf-8 string describing the most recent error encountered associated 
   783  ** with dynamic libraries.
   784  */
   785  static void jtDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
   786    g.pVfs->xDlError(g.pVfs, nByte, zErrMsg);
   787  }
   788  
   789  /*
   790  ** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
   791  */
   792  static void (*jtDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
   793    return g.pVfs->xDlSym(g.pVfs, p, zSym);
   794  }
   795  
   796  /*
   797  ** Close the dynamic library handle pHandle.
   798  */
   799  static void jtDlClose(sqlite3_vfs *pVfs, void *pHandle){
   800    g.pVfs->xDlClose(g.pVfs, pHandle);
   801  }
   802  
   803  /*
   804  ** Populate the buffer pointed to by zBufOut with nByte bytes of 
   805  ** random data.
   806  */
   807  static int jtRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
   808    return sqlite3OsRandomness(g.pVfs, nByte, zBufOut);
   809  }
   810  
   811  /*
   812  ** Sleep for nMicro microseconds. Return the number of microseconds 
   813  ** actually slept.
   814  */
   815  static int jtSleep(sqlite3_vfs *pVfs, int nMicro){
   816    return sqlite3OsSleep(g.pVfs, nMicro);
   817  }
   818  
   819  /*
   820  ** Return the current time as a Julian Day number in *pTimeOut.
   821  */
   822  static int jtCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
   823    return g.pVfs->xCurrentTime(g.pVfs, pTimeOut);
   824  }
   825  /*
   826  ** Return the current time as a Julian Day number in *pTimeOut.
   827  */
   828  static int jtCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *pTimeOut){
   829    return g.pVfs->xCurrentTimeInt64(g.pVfs, pTimeOut);
   830  }
   831  
   832  static int jtGetLastError(sqlite3_vfs *pVfs, int n, char *z){
   833    return g.pVfs->xGetLastError(g.pVfs, n, z);
   834  }
   835  
   836  /**************************************************************************
   837  ** Start of public API.
   838  */
   839  
   840  /*
   841  ** Configure the jt VFS as a wrapper around the VFS named by parameter 
   842  ** zWrap. If the isDefault parameter is true, then the jt VFS is installed
   843  ** as the new default VFS for SQLite connections. If isDefault is not
   844  ** true, then the jt VFS is installed as non-default. In this case it
   845  ** is available via its name, "jt".
   846  */
   847  int jt_register(char *zWrap, int isDefault){
   848    g.pVfs = sqlite3_vfs_find(zWrap);
   849    if( g.pVfs==0 ){
   850      return SQLITE_ERROR;
   851    }
   852    jt_vfs.szOsFile = sizeof(jt_file) + g.pVfs->szOsFile;
   853    if( g.pVfs->iVersion==1 ){
   854      jt_vfs.iVersion = 1;
   855    }else if( g.pVfs->xCurrentTimeInt64==0 ){
   856      jt_vfs.xCurrentTimeInt64 = 0;
   857    }
   858    sqlite3_vfs_register(&jt_vfs, isDefault);
   859    return SQLITE_OK;
   860  }
   861  
   862  /*
   863  ** Uninstall the jt VFS, if it is installed.
   864  */
   865  void jt_unregister(void){
   866    sqlite3_vfs_unregister(&jt_vfs);
   867  }
   868  
   869  #endif