/ Check-in [dc076345]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fixes to the file locking. 109 tests are now failing. (CVS 1548)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: dc0763455bbf54c1d8728e16033709caedd6e1c6
User & Date: drh 2004-06-09 17:37:23
Context
2004-06-09
19:03
Remove legacy journal formats. (CVS 1549) check-in: a12bef4a user: drh tags: trunk
17:37
Fixes to the file locking. 109 tests are now failing. (CVS 1548) check-in: dc076345 user: drh tags: trunk
14:17
Add the "lock_status" pragma - only available when SQLITE_DEBUG is defined. Used for testing only. (CVS 1547) check-in: 0ecbba78 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

     5      5   ** a legal notice, here is a blessing:
     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12         -** $Id: btree.c,v 1.161 2004/06/07 16:27:46 drh Exp $
           12  +** $Id: btree.c,v 1.162 2004/06/09 17:37:23 drh Exp $
    13     13   **
    14     14   ** This file implements a external (disk-based) database using BTrees.
    15     15   ** For a detailed discussion of BTrees, refer to
    16     16   **
    17     17   **     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
    18     18   **     "Sorting And Searching", pages 473-480. Addison-Wesley
    19     19   **     Publishing Company, Reading, Massachusetts.
................................................................................
   257    257   **
   258    258   ** The pParent field points back to the parent page.  This allows us to
   259    259   ** walk up the BTree from any leaf to the root.  Care must be taken to
   260    260   ** unref() the parent page pointer when this page is no longer referenced.
   261    261   ** The pageDestructor() routine handles that chore.
   262    262   */
   263    263   struct MemPage {
   264         -  u8 isInit;           /* True if previously initialized */
          264  +  u8 isInit;           /* True if previously initialized. MUST BE FIRST! */
   265    265     u8 idxShift;         /* True if Cell indices have changed */
   266    266     u8 nOverflow;        /* Number of overflow cell bodies in aCell[] */
   267    267     u8 intKey;           /* True if intkey flag is set */
   268    268     u8 leaf;             /* True if leaf flag is set */
   269    269     u8 zeroData;         /* True if table stores keys only */
   270    270     u8 leafData;         /* True if tables stores data on leaves only */
   271    271     u8 hasData;          /* True if this page stores data */
................................................................................
   957    957     if( pPage->pParent ){
   958    958       MemPage *pParent = pPage->pParent;
   959    959       pPage->pParent = 0;
   960    960       releasePage(pParent);
   961    961     }
   962    962     pPage->isInit = 0;
   963    963   }
          964  +
          965  +/*
          966  +** During a rollback, when the pager reloads information into the cache
          967  +** so that the cache is restored to its original state at the start of
          968  +** the transaction, for each page restored this routine is called.
          969  +**
          970  +** This routine needs to reset the extra data section at the end of the
          971  +** page to agree with the restored data.
          972  +*/
          973  +static void pageReinit(void *pData, int pageSize){
          974  +  MemPage *pPage = (MemPage*)&((char*)pData)[pageSize];
          975  +  if( pPage->isInit ){
          976  +    pPage->isInit = 0;
          977  +    initPage(pPage, pPage->pParent);
          978  +  }
          979  +}
   964    980   
   965    981   /*
   966    982   ** Open a new database.
   967    983   **
   968    984   ** Actually, this routine just sets up the internal data structures
   969    985   ** for accessing the database.  We do not open the database file 
   970    986   ** until the first page is loaded.
................................................................................
  1007   1023     if( rc!=SQLITE_OK ){
  1008   1024       if( pBt->pPager ) sqlite3pager_close(pBt->pPager);
  1009   1025       sqliteFree(pBt);
  1010   1026       *ppBtree = 0;
  1011   1027       return rc;
  1012   1028     }
  1013   1029     sqlite3pager_set_destructor(pBt->pPager, pageDestructor);
         1030  +  sqlite3pager_set_reiniter(pBt->pPager, pageReinit);
  1014   1031     pBt->pCursor = 0;
  1015   1032     pBt->pPage1 = 0;
  1016   1033     pBt->readOnly = sqlite3pager_isreadonly(pBt->pPager);
  1017   1034     pBt->pageSize = SQLITE_PAGE_SIZE;  /* FIX ME - read from header */
  1018   1035     pBt->usableSize = pBt->pageSize;
  1019   1036     pBt->maxEmbedFrac = 64;            /* FIX ME - read from header */
  1020   1037     pBt->minEmbedFrac = 32;            /* FIX ME - read from header */

Changes to src/os.h.

   152    152   int sqlite3OsClose(OsFile*);
   153    153   int sqlite3OsRead(OsFile*, void*, int amt);
   154    154   int sqlite3OsWrite(OsFile*, const void*, int amt);
   155    155   int sqlite3OsSeek(OsFile*, off_t offset);
   156    156   int sqlite3OsSync(OsFile*);
   157    157   int sqlite3OsTruncate(OsFile*, off_t size);
   158    158   int sqlite3OsFileSize(OsFile*, off_t *pSize);
   159         -int sqlite3OsReadLock(OsFile*);
   160         -int sqlite3OsWriteLock(OsFile*);
   161         -int sqlite3OsUnlock(OsFile*);
   162    159   int sqlite3OsRandomSeed(char*);
   163    160   int sqlite3OsSleep(int ms);
   164    161   int sqlite3OsCurrentTime(double*);
   165    162   void sqlite3OsEnterMutex(void);
   166    163   void sqlite3OsLeaveMutex(void);
   167    164   char *sqlite3OsFullPathname(const char*);
   168    165   int sqlite3OsLock(OsFile*, int);
   169         -int sqlite3OsCheckWriteLock(OsFile *id);
          166  +int sqlite3OsUnlock(OsFile*, int);
          167  +int sqlite3OsCheckReservedLock(OsFile *id);
   170    168   
   171    169   #endif /* _SQLITE_OS_H_ */

Changes to src/os_common.h.

    39     39   #define TIMER_END         elapse=hwtime()-g_start
    40     40   #define SEEK(X)           last_page=(X)
    41     41   #define TRACE1(X)         if( sqlite3_os_trace ) sqlite3DebugPrintf(X)
    42     42   #define TRACE2(X,Y)       if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y)
    43     43   #define TRACE3(X,Y,Z)     if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z)
    44     44   #define TRACE4(X,Y,Z,A)   if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A)
    45     45   #define TRACE5(X,Y,Z,A,B) if( sqlite3_os_trace ) sqlite3DebugPrintf(X,Y,Z,A,B)
           46  +#define TRACE6(X,Y,Z,A,B,C) if(sqlite3_os_trace) sqlite3DebugPrintf(X,Y,Z,A,B,C)
    46     47   #else
    47     48   #define TIMER_START
    48     49   #define TIMER_END
    49     50   #define SEEK(X)
    50     51   #define TRACE1(X)
    51     52   #define TRACE2(X,Y)
    52     53   #define TRACE3(X,Y,Z)
    53     54   #define TRACE4(X,Y,Z,A)
    54     55   #define TRACE5(X,Y,Z,A,B)
           56  +#define TRACE6(X,Y,Z,A,B,C)
    55     57   #endif
    56     58   
    57     59   
    58     60   /*
    59     61   ** If we compile with the SQLITE_TEST macro set, then the following block
    60     62   ** of code will give us the ability to simulate a disk I/O error.  This
    61     63   ** is used for testing the I/O recovery logic.

Changes to src/os_unix.c.

   338    338   int sqlite3OsOpenReadWrite(
   339    339     const char *zFilename,
   340    340     OsFile *id,
   341    341     int *pReadonly
   342    342   ){
   343    343     int rc;
   344    344     id->dirfd = -1;
   345         -  id->fd = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644);
   346         -  if( id->fd<0 ){
   347         -    id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
   348         -    if( id->fd<0 ){
          345  +  id->h = open(zFilename, O_RDWR|O_CREAT|O_LARGEFILE|O_BINARY, 0644);
          346  +  if( id->h<0 ){
          347  +    id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
          348  +    if( id->h<0 ){
   349    349         return SQLITE_CANTOPEN; 
   350    350       }
   351    351       *pReadonly = 1;
   352    352     }else{
   353    353       *pReadonly = 0;
   354    354     }
   355    355     sqlite3OsEnterMutex();
   356         -  rc = findLockInfo(id->fd, &id->pLock, &id->pOpen);
          356  +  rc = findLockInfo(id->h, &id->pLock, &id->pOpen);
   357    357     sqlite3OsLeaveMutex();
   358    358     if( rc ){
   359         -    close(id->fd);
          359  +    close(id->h);
   360    360       return SQLITE_NOMEM;
   361    361     }
   362    362     id->locktype = 0;
   363         -  TRACE3("OPEN    %-3d %s\n", id->fd, zFilename);
          363  +  TRACE3("OPEN    %-3d %s\n", id->h, zFilename);
   364    364     OpenCounter(+1);
   365    365     return SQLITE_OK;
   366    366   }
   367    367   
   368    368   
   369    369   /*
   370    370   ** Attempt to open a new file for exclusive access by this process.
................................................................................
   382    382   */
   383    383   int sqlite3OsOpenExclusive(const char *zFilename, OsFile *id, int delFlag){
   384    384     int rc;
   385    385     if( access(zFilename, 0)==0 ){
   386    386       return SQLITE_CANTOPEN;
   387    387     }
   388    388     id->dirfd = -1;
   389         -  id->fd = open(zFilename,
          389  +  id->h = open(zFilename,
   390    390                   O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_LARGEFILE|O_BINARY, 0600);
   391         -  if( id->fd<0 ){
          391  +  if( id->h<0 ){
   392    392       return SQLITE_CANTOPEN;
   393    393     }
   394    394     sqlite3OsEnterMutex();
   395         -  rc = findLockInfo(id->fd, &id->pLock, &id->pOpen);
          395  +  rc = findLockInfo(id->h, &id->pLock, &id->pOpen);
   396    396     sqlite3OsLeaveMutex();
   397    397     if( rc ){
   398         -    close(id->fd);
          398  +    close(id->h);
   399    399       unlink(zFilename);
   400    400       return SQLITE_NOMEM;
   401    401     }
   402    402     id->locktype = 0;
   403    403     if( delFlag ){
   404    404       unlink(zFilename);
   405    405     }
   406         -  TRACE3("OPEN-EX %-3d %s\n", id->fd, zFilename);
          406  +  TRACE3("OPEN-EX %-3d %s\n", id->h, zFilename);
   407    407     OpenCounter(+1);
   408    408     return SQLITE_OK;
   409    409   }
   410    410   
   411    411   /*
   412    412   ** Attempt to open a new file for read-only access.
   413    413   **
................................................................................
   414    414   ** On success, write the file handle into *id and return SQLITE_OK.
   415    415   **
   416    416   ** On failure, return SQLITE_CANTOPEN.
   417    417   */
   418    418   int sqlite3OsOpenReadOnly(const char *zFilename, OsFile *id){
   419    419     int rc;
   420    420     id->dirfd = -1;
   421         -  id->fd = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
   422         -  if( id->fd<0 ){
          421  +  id->h = open(zFilename, O_RDONLY|O_LARGEFILE|O_BINARY);
          422  +  if( id->h<0 ){
   423    423       return SQLITE_CANTOPEN;
   424    424     }
   425    425     sqlite3OsEnterMutex();
   426         -  rc = findLockInfo(id->fd, &id->pLock, &id->pOpen);
          426  +  rc = findLockInfo(id->h, &id->pLock, &id->pOpen);
   427    427     sqlite3OsLeaveMutex();
   428    428     if( rc ){
   429         -    close(id->fd);
          429  +    close(id->h);
   430    430       return SQLITE_NOMEM;
   431    431     }
   432    432     id->locktype = 0;
   433         -  TRACE3("OPEN-RO %-3d %s\n", id->fd, zFilename);
          433  +  TRACE3("OPEN-RO %-3d %s\n", id->h, zFilename);
   434    434     OpenCounter(+1);
   435    435     return SQLITE_OK;
   436    436   }
   437    437   
   438    438   /*
   439    439   ** Attempt to open a file descriptor for the directory that contains a
   440    440   ** file.  This file descriptor can be used to fsync() the directory
................................................................................
   451    451   ** On failure, the function returns SQLITE_CANTOPEN and leaves
   452    452   ** *id unchanged.
   453    453   */
   454    454   int sqlite3OsOpenDirectory(
   455    455     const char *zDirname,
   456    456     OsFile *id
   457    457   ){
   458         -  if( id->fd<0 ){
          458  +  if( id->h<0 ){
   459    459       /* Do not open the directory if the corresponding file is not already
   460    460       ** open. */
   461    461       return SQLITE_CANTOPEN;
   462    462     }
   463    463     assert( id->dirfd<0 );
   464    464     id->dirfd = open(zDirname, O_RDONLY|O_BINARY, 0644);
   465    465     if( id->dirfd<0 ){
................................................................................
   506    506     return SQLITE_OK; 
   507    507   }
   508    508   
   509    509   /*
   510    510   ** Close a file.
   511    511   */
   512    512   int sqlite3OsClose(OsFile *id){
   513         -  sqlite3OsUnlock(id);
          513  +  sqlite3OsUnlock(id, NO_LOCK);
   514    514     if( id->dirfd>=0 ) close(id->dirfd);
   515    515     id->dirfd = -1;
   516    516     sqlite3OsEnterMutex();
   517    517     if( id->pOpen->nLock ){
   518    518       /* If there are outstanding locks, do not actually close the file just
   519    519       ** yet because that would clear those locks.  Instead, add the file
   520    520       ** descriptor to pOpen->aPending.  It will be automatically closed when
................................................................................
   524    524       struct openCnt *pOpen = id->pOpen;
   525    525       pOpen->nPending++;
   526    526       aNew = sqliteRealloc( pOpen->aPending, pOpen->nPending*sizeof(int) );
   527    527       if( aNew==0 ){
   528    528         /* If a malloc fails, just leak the file descriptor */
   529    529       }else{
   530    530         pOpen->aPending = aNew;
   531         -      pOpen->aPending[pOpen->nPending-1] = id->fd;
          531  +      pOpen->aPending[pOpen->nPending-1] = id->h;
   532    532       }
   533    533     }else{
   534    534       /* There are no outstanding locks so we can close the file immediately */
   535         -    close(id->fd);
          535  +    close(id->h);
   536    536     }
   537    537     releaseLockInfo(id->pLock);
   538    538     releaseOpenCnt(id->pOpen);
   539    539     sqlite3OsLeaveMutex();
   540         -  TRACE2("CLOSE   %-3d\n", id->fd);
          540  +  TRACE2("CLOSE   %-3d\n", id->h);
   541    541     OpenCounter(-1);
   542    542     return SQLITE_OK;
   543    543   }
   544    544   
   545    545   /*
   546    546   ** Read data from a file into a buffer.  Return SQLITE_OK if all
   547    547   ** bytes were read successfully and SQLITE_IOERR if anything goes
   548    548   ** wrong.
   549    549   */
   550    550   int sqlite3OsRead(OsFile *id, void *pBuf, int amt){
   551    551     int got;
   552    552     SimulateIOError(SQLITE_IOERR);
   553    553     TIMER_START;
   554         -  got = read(id->fd, pBuf, amt);
          554  +  got = read(id->h, pBuf, amt);
   555    555     TIMER_END;
   556         -  TRACE4("READ    %-3d %7d %d\n", id->fd, last_page, elapse);
          556  +  TRACE4("READ    %-3d %7d %d\n", id->h, last_page, elapse);
   557    557     SEEK(0);
   558    558     /* if( got<0 ) got = 0; */
   559    559     if( got==amt ){
   560    560       return SQLITE_OK;
   561    561     }else{
   562    562       return SQLITE_IOERR;
   563    563     }
................................................................................
   567    567   ** Write data from a buffer into a file.  Return SQLITE_OK on success
   568    568   ** or some other error code on failure.
   569    569   */
   570    570   int sqlite3OsWrite(OsFile *id, const void *pBuf, int amt){
   571    571     int wrote = 0;
   572    572     SimulateIOError(SQLITE_IOERR);
   573    573     TIMER_START;
   574         -  while( amt>0 && (wrote = write(id->fd, pBuf, amt))>0 ){
          574  +  while( amt>0 && (wrote = write(id->h, pBuf, amt))>0 ){
   575    575       amt -= wrote;
   576    576       pBuf = &((char*)pBuf)[wrote];
   577    577     }
   578    578     TIMER_END;
   579         -  TRACE4("WRITE   %-3d %7d %d\n", id->fd, last_page, elapse);
          579  +  TRACE4("WRITE   %-3d %7d %d\n", id->h, last_page, elapse);
   580    580     SEEK(0);
   581    581     if( amt>0 ){
   582    582       return SQLITE_FULL;
   583    583     }
   584    584     return SQLITE_OK;
   585    585   }
   586    586   
   587    587   /*
   588    588   ** Move the read/write pointer in a file.
   589    589   */
   590    590   int sqlite3OsSeek(OsFile *id, off_t offset){
   591    591     SEEK(offset/1024 + 1);
   592         -  lseek(id->fd, offset, SEEK_SET);
          592  +  lseek(id->h, offset, SEEK_SET);
   593    593     return SQLITE_OK;
   594    594   }
   595    595   
   596    596   /*
   597    597   ** Make sure all writes to a particular file are committed to disk.
   598    598   **
   599    599   ** Under Unix, also make sure that the directory entry for the file
................................................................................
   602    602   ** entry for the journal might not exist after we reboot.  The next
   603    603   ** SQLite to access the file will not know that the journal exists (because
   604    604   ** the directory entry for the journal was never created) and the transaction
   605    605   ** will not roll back - possibly leading to database corruption.
   606    606   */
   607    607   int sqlite3OsSync(OsFile *id){
   608    608     SimulateIOError(SQLITE_IOERR);
   609         -  TRACE2("SYNC    %-3d\n", id->fd);
   610         -  if( fsync(id->fd) ){
          609  +  TRACE2("SYNC    %-3d\n", id->h);
          610  +  if( fsync(id->h) ){
   611    611       return SQLITE_IOERR;
   612    612     }else{
   613    613       if( id->dirfd>=0 ){
   614    614         TRACE2("DIRSYNC %-3d\n", id->dirfd);
   615    615         fsync(id->dirfd);
   616    616         close(id->dirfd);  /* Only need to sync once, so close the directory */
   617    617         id->dirfd = -1;    /* when we are done. */
................................................................................
   621    621   }
   622    622   
   623    623   /*
   624    624   ** Truncate an open file to a specified size
   625    625   */
   626    626   int sqlite3OsTruncate(OsFile *id, off_t nByte){
   627    627     SimulateIOError(SQLITE_IOERR);
   628         -  return ftruncate(id->fd, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;
          628  +  return ftruncate(id->h, nByte)==0 ? SQLITE_OK : SQLITE_IOERR;
   629    629   }
   630    630   
   631    631   /*
   632    632   ** Determine the current size of a file in bytes
   633    633   */
   634    634   int sqlite3OsFileSize(OsFile *id, off_t *pSize){
   635    635     struct stat buf;
   636    636     SimulateIOError(SQLITE_IOERR);
   637         -  if( fstat(id->fd, &buf)!=0 ){
          637  +  if( fstat(id->h, &buf)!=0 ){
   638    638       return SQLITE_IOERR;
   639    639     }
   640    640     *pSize = buf.st_size;
   641    641     return SQLITE_OK;
   642    642   }
   643    643   
   644    644   /*
   645    645   ** This routine checks if there is a RESERVED lock held on the specified
   646    646   ** file by this or any other process. If such a lock is held, return
   647    647   ** non-zero.  If the file is unlocked or holds only SHARED locks, then
   648    648   ** return zero.
   649    649   */
   650         -int sqlite3OsCheckWriteLock(OsFile *id){
          650  +int sqlite3OsCheckReservedLock(OsFile *id){
   651    651     int r = 0;
   652    652   
   653    653     sqlite3OsEnterMutex(); /* Needed because id->pLock is shared across threads */
   654    654   
   655    655     /* Check if a thread in this process holds such a lock */
   656    656     if( id->pLock->locktype>SHARED_LOCK ){
   657    657       r = 1;
................................................................................
   661    661     */
   662    662     if( !r ){
   663    663       struct flock lock;
   664    664       lock.l_whence = SEEK_SET;
   665    665       lock.l_start = RESERVED_BYTE;
   666    666       lock.l_len = 1;
   667    667       lock.l_type = F_WRLCK;
   668         -    fcntl(id->fd, F_GETLK, &lock);
          668  +    fcntl(id->h, F_GETLK, &lock);
   669    669       if( lock.l_type!=F_UNLCK ){
   670    670         r = 1;
   671    671       }
   672    672     }
   673    673     
   674    674     sqlite3OsLeaveMutex();
   675         -  TRACE3("TEST WR-LOCK %d %d\n", id->fd, r);
          675  +  TRACE3("TEST WR-LOCK %d %d\n", id->h, r);
   676    676   
   677    677     return r;
   678    678   }
   679    679   
   680    680   /*
   681    681   ** Lock the file with the lock specified by parameter locktype - one
   682    682   ** of the following:
................................................................................
   694    694   **
   695    695   **    UNLOCKED -> SHARED
   696    696   **    SHARED -> RESERVED
   697    697   **    SHARED -> (PENDING) -> EXCLUSIVE
   698    698   **    RESERVED -> (PENDING) -> EXCLUSIVE
   699    699   **    PENDING -> EXCLUSIVE
   700    700   **
   701         -** This routine will only increase a lock.  The sqlite3OsUnlock() routine
   702         -** erases all locks at once and returns us immediately to locking level 0.
   703         -** It is not possible to lower the locking level one step at a time.  You
   704         -** must go straight to locking level 0.
          701  +** This routine will only increase a lock.  Use the sqlite3OsUnlock()
          702  +** routine to lower a locking level.
   705    703   */
   706    704   int sqlite3OsLock(OsFile *id, int locktype){
   707    705     int rc = SQLITE_OK;
   708    706     struct lockInfo *pLock = id->pLock;
   709    707     struct flock lock;
   710    708     int s;
   711    709   
   712         -  TRACE5("LOCK %d %d was %d(%d)\n",
   713         -          id->fd, locktype, id->locktype, pLock->locktype);
          710  +  TRACE6("LOCK %d %d was %d(%d,%d)\n",
          711  +          id->h, locktype, id->locktype, pLock->locktype, pLock->cnt);
   714    712   
   715    713     /* If there is already a lock of this type or more restrictive on the
   716    714     ** OsFile, do nothing. Don't use the end_lock: exit path, as
   717    715     ** sqlite3OsEnterMutex() hasn't been called yet.
   718    716     */
   719    717     if( id->locktype>=locktype ){
   720    718       return SQLITE_OK;
................................................................................
   767    765       assert( pLock->locktype==0 );
   768    766     
   769    767       /* Temporarily grab a PENDING lock.  This prevents new SHARED locks from
   770    768       ** being formed if a PENDING lock is already held.
   771    769       */
   772    770       lock.l_type = F_RDLCK;
   773    771       lock.l_start = PENDING_BYTE;
   774         -    s = fcntl(id->fd, F_SETLK, &lock);
          772  +    s = fcntl(id->h, F_SETLK, &lock);
   775    773       if( s ){
   776    774         rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
   777    775         goto end_lock;
   778    776       }
   779    777   
   780    778       /* Now get the read-lock */
   781    779       lock.l_start = SHARED_FIRST;
   782    780       lock.l_len = SHARED_SIZE;
   783         -    s = fcntl(id->fd, F_SETLK, &lock);
          781  +    s = fcntl(id->h, F_SETLK, &lock);
   784    782   
   785    783       /* Drop the temporary PENDING lock */
   786    784       lock.l_start = PENDING_BYTE;
   787    785       lock.l_len = 1L;
   788    786       lock.l_type = F_UNLCK;
   789         -    fcntl(id->fd, F_SETLK, &lock);
          787  +    fcntl(id->h, F_SETLK, &lock);
   790    788       if( s ){
   791    789         rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
   792    790       }else{
   793    791         id->locktype = SHARED_LOCK;
   794    792         id->pOpen->nLock++;
   795    793         pLock->cnt = 1;
   796    794       }
................................................................................
   811    809         case EXCLUSIVE_LOCK:
   812    810           lock.l_start = SHARED_FIRST;
   813    811           lock.l_len = SHARED_SIZE;
   814    812           break;
   815    813         default:
   816    814           assert(0);
   817    815       }
   818         -    s = fcntl(id->fd, F_SETLK, &lock);
          816  +    s = fcntl(id->h, F_SETLK, &lock);
   819    817       if( s ){
   820    818         rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
   821    819       }
   822    820     }
   823    821     
   824    822     if( rc==SQLITE_OK ){
   825    823       id->locktype = locktype;
   826    824       pLock->locktype = locktype;
   827    825     }
   828    826   
   829    827   end_lock:
   830    828     sqlite3OsLeaveMutex();
   831         -  TRACE4("LOCK %d %d %s\n", id->fd, locktype, rc==SQLITE_OK ? "ok" : "failed");
          829  +  TRACE4("LOCK %d %d %s\n", id->h, locktype, rc==SQLITE_OK ? "ok" : "failed");
   832    830     return rc;
   833    831   }
   834    832   
   835    833   /*
   836         -** Unlock the given file descriptor.  If the file descriptor was
   837         -** not previously locked, then this routine is a no-op.  If this
   838         -** library was compiled with large file support (LFS) but LFS is not
   839         -** available on the host, then an SQLITE_NOLFS is returned.
          834  +** Lower the locking level on file descriptor id to locktype.  locktype
          835  +** must be either NO_LOCK or SHARED_LOCK.
          836  +**
          837  +** If the locking level of the file descriptor is already at or below
          838  +** the requested locking level, this routine is a no-op.
          839  +**
          840  +** It is not possible for this routine to fail.
   840    841   */
   841         -int sqlite3OsUnlock(OsFile *id){
   842         -  int rc;
   843         -  if( !id->locktype ) return SQLITE_OK;
   844         -  id->locktype = 0;
          842  +int sqlite3OsUnlock(OsFile *id, int locktype){
          843  +  struct lockInfo *pLock;
          844  +  struct flock lock;
          845  +
          846  +  TRACE6("UNLOCK %d %d was %d(%d,%d)\n",
          847  +          id->h, locktype, id->locktype, id->pLock->locktype, id->pLock->cnt);
          848  +
          849  +  assert( locktype<=SHARED_LOCK );
          850  +  if( id->locktype<=locktype ){
          851  +    return SQLITE_OK;
          852  +  }
   845    853     sqlite3OsEnterMutex();
   846         -  assert( id->pLock->cnt!=0 );
   847         -  if( id->pLock->cnt>1 ){
   848         -    id->pLock->cnt--;
   849         -    rc = SQLITE_OK;
   850         -  }else{
   851         -    struct flock lock;
   852         -    int s;
          854  +  pLock = id->pLock;
          855  +  assert( pLock->cnt!=0 );
          856  +  if( id->locktype>SHARED_LOCK ){
          857  +    assert( pLock->locktype==id->locktype );
   853    858       lock.l_type = F_UNLCK;
   854    859       lock.l_whence = SEEK_SET;
   855         -    lock.l_start = lock.l_len = 0L;
   856         -    s = fcntl(id->fd, F_SETLK, &lock);
   857         -    if( s!=0 ){
   858         -      rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;
   859         -    }else{
   860         -      rc = SQLITE_OK;
   861         -      id->pLock->cnt = 0;
   862         -      id->pLock->locktype = 0;
   863         -    }
          860  +    lock.l_start = PENDING_BYTE;
          861  +    lock.l_len = 2L;  assert( PENDING_BYTE+1==RESERVED_BYTE );
          862  +    fcntl(id->h, F_SETLK, &lock);
          863  +    pLock->locktype = SHARED_LOCK;
   864    864     }
          865  +  if( locktype==NO_LOCK ){
          866  +    struct openCnt *pOpen;
   865    867   
   866         -  if( rc==SQLITE_OK ){
          868  +    /* Decrement the shared lock counter.  Release the lock using an
          869  +    ** OS call only when all threads in this same process have released
          870  +    ** the lock.
          871  +    */
          872  +    pLock->cnt--;
          873  +    if( pLock->cnt==0 ){
          874  +      lock.l_type = F_UNLCK;
          875  +      lock.l_whence = SEEK_SET;
          876  +      lock.l_start = lock.l_len = 0L;
          877  +      fcntl(id->h, F_SETLK, &lock);
          878  +      pLock->locktype = NO_LOCK;
          879  +    }
          880  +
   867    881       /* Decrement the count of locks against this same file.  When the
   868    882       ** count reaches zero, close any other file descriptors whose close
   869    883       ** was deferred because of outstanding locks.
   870    884       */
   871         -    struct openCnt *pOpen = id->pOpen;
          885  +    pOpen = id->pOpen;
   872    886       pOpen->nLock--;
   873    887       assert( pOpen->nLock>=0 );
   874    888       if( pOpen->nLock==0 && pOpen->nPending>0 ){
   875    889         int i;
   876    890         for(i=0; i<pOpen->nPending; i++){
   877    891           close(pOpen->aPending[i]);
   878    892         }
   879    893         sqliteFree(pOpen->aPending);
   880    894         pOpen->nPending = 0;
   881    895         pOpen->aPending = 0;
   882    896       }
   883    897     }
   884    898     sqlite3OsLeaveMutex();
   885         -  id->locktype = 0;
   886         -  return rc;
          899  +  id->locktype = locktype;
          900  +  return SQLITE_OK;
   887    901   }
   888    902   
   889    903   /*
   890    904   ** Get information to seed the random number generator.  The seed
   891    905   ** is written into the buffer zBuf[256].  The calling function must
   892    906   ** supply a sufficiently large buffer.
   893    907   */

Changes to src/os_unix.h.

    60     60   ** OsFile.locktype takes one of the values SHARED_LOCK, RESERVED_LOCK,
    61     61   ** PENDING_LOCK or EXCLUSIVE_LOCK.
    62     62   */
    63     63   typedef struct OsFile OsFile;
    64     64   struct OsFile {
    65     65     struct openCnt *pOpen;    /* Info about all open fd's on this inode */
    66     66     struct lockInfo *pLock;   /* Info about locks on this inode */
    67         -  int fd;                   /* The file descriptor */
           67  +  int h;                    /* The file descriptor */
    68     68     int locktype;             /* The type of lock held on this fd */
    69     69     int dirfd;                /* File descriptor for the directory */
    70     70   };
    71     71   
    72     72   /*
    73     73   ** Maximum number of characters in a temporary file name
    74     74   */

Changes to src/os_win.c.

   504    504   }
   505    505   
   506    506   /*
   507    507   ** This routine checks if there is a RESERVED lock held on the specified
   508    508   ** file by this or any other process. If such a lock is held, return
   509    509   ** non-zero, otherwise zero.
   510    510   */
   511         -int sqlite3OsCheckWriteLock(OsFile *id){
          511  +int sqlite3OsCheckReservedLock(OsFile *id){
   512    512     int rc;
   513    513     if( id->locktype>=RESERVED_LOCK ){
   514    514       rc = 1;
   515    515       TRACE3("TEST WR-LOCK %d %d (local)\n", id->h, rc);
   516    516     }else{
   517    517       rc = LockFile(id->h, RESERVED_BYTE, 0, 1, 0);
   518    518       if( rc ){
................................................................................
   521    521       rc = !rc;
   522    522       TRACE3("TEST WR-LOCK %d %d (remote)\n", id->h, rc);
   523    523     }
   524    524     return rc;
   525    525   }
   526    526   
   527    527   /*
   528         -** Unlock the given file descriptor.  If the file descriptor was
   529         -** not previously locked, then this routine is a no-op.  If this
   530         -** library was compiled with large file support (LFS) but LFS is not
   531         -** available on the host, then an SQLITE_NOLFS is returned.
          528  +** Lower the locking level on file descriptor id to locktype.  locktype
          529  +** must be either NO_LOCK or SHARED_LOCK.
          530  +**
          531  +** If the locking level of the file descriptor is already at or below
          532  +** the requested locking level, this routine is a no-op.
          533  +**
          534  +** It is not possible for this routine to fail.
   532    535   */
   533         -int sqlite3OsUnlock(OsFile *id){
          536  +int sqlite3OsUnlock(OsFile *id, int locktype){
   534    537     int rc, type;
   535         -  TRACE4("UNLOCK %d was %d(%d)\n", id->h, id->locktype, id->sharedLockByte);
          538  +  assert( locktype<=SHARED_LOCK );
          539  +  TRACE4("UNLOCK %d to %d was %d(%d)\n", id->h, locktype,
          540  +          id->locktype, id->sharedLockByte);
   536    541     type = id->locktype;
   537    542     if( type>=EXCLUSIVE_LOCK ){
   538    543       UnlockFile(id->h, SHARED_FIRST, 0, SHARED_SIZE, 0);
   539    544     }
   540    545     if( type>=RESERVED_LOCK ){
   541    546       UnlockFile(id->h, RESERVED_BYTE, 0, 1, 0);
   542    547     }
   543         -  if( type>=SHARED_LOCK && type<EXCLUSIVE_LOCK ){
          548  +  if( locktype==NO_LOCK && type>=SHARED_LOCK && type<EXCLUSIVE_LOCK ){
   544    549       unlockReadLock(id);
   545    550     }
   546    551     if( type>=PENDING_LOCK ){
   547    552       UnlockFile(id->h, PENDING_BYTE, 0, 1, 0);
   548    553     }
   549         -  id->locktype = NO_LOCK;
          554  +  id->locktype = locktype;
   550    555     return SQLITE_OK;
   551    556   }
   552    557   
   553    558   /*
   554    559   ** Get information to seed the random number generator.  The seed
   555    560   ** is written into the buffer zBuf[256].  The calling function must
   556    561   ** supply a sufficiently large buffer.

Changes to src/pager.c.

    14     14   ** The pager is used to access a database disk file.  It implements
    15     15   ** atomic commit and rollback through the use of a journal file that
    16     16   ** is separate from the database file.  The pager also implements file
    17     17   ** locking to prevent two processes from writing the same database
    18     18   ** file simultaneously, or one process from reading the database while
    19     19   ** another is writing.
    20     20   **
    21         -** @(#) $Id: pager.c,v 1.114 2004/06/09 14:17:21 drh Exp $
           21  +** @(#) $Id: pager.c,v 1.115 2004/06/09 17:37:28 drh Exp $
    22     22   */
    23     23   #include "os.h"         /* Must be first to enable large file support */
    24     24   #include "sqliteInt.h"
    25     25   #include "pager.h"
    26     26   #include <assert.h>
    27     27   #include <string.h>
    28     28   
................................................................................
    45     45   #endif
    46     46   
    47     47   
    48     48   /*
    49     49   ** The page cache as a whole is always in one of the following
    50     50   ** states:
    51     51   **
    52         -**   SQLITE_UNLOCK       The page cache is not currently reading or 
           52  +**   PAGER_UNLOCK        The page cache is not currently reading or 
    53     53   **                       writing the database file.  There is no
    54     54   **                       data held in memory.  This is the initial
    55     55   **                       state.
    56     56   **
    57         -**   SQLITE_READLOCK     The page cache is reading the database.
           57  +**   PAGER_SHARED        The page cache is reading the database.
    58     58   **                       Writing is not permitted.  There can be
    59     59   **                       multiple readers accessing the same database
    60     60   **                       file at the same time.
    61     61   **
    62         -**   SQLITE_WRITELOCK    The page cache is writing the database.
           62  +**   PAGER_RESERVED      Writing is permitted to the page cache only.
           63  +**                       The original database file has not been modified.
           64  +**                       Other processes may still be reading the on-disk
           65  +**                       database file.
           66  +**
           67  +**   PAGER_EXCLUSIVE     The page cache is writing the database.
    63     68   **                       Access is exclusive.  No other processes or
    64     69   **                       threads can be reading or writing while one
    65     70   **                       process is writing.
    66     71   **
    67         -** The page cache comes up in SQLITE_UNLOCK.  The first time a
    68         -** sqlite_page_get() occurs, the state transitions to SQLITE_READLOCK.
           72  +** The page cache comes up in PAGER_UNLOCK.  The first time a
           73  +** sqlite_page_get() occurs, the state transitions to PAGER_SHARED.
    69     74   ** After all pages have been released using sqlite_page_unref(),
    70         -** the state transitions back to SQLITE_UNLOCK.  The first time
           75  +** the state transitions back to PAGER_UNLOCK.  The first time
    71     76   ** that sqlite_page_write() is called, the state transitions to
    72         -** SQLITE_WRITELOCK.  (Note that sqlite_page_write() can only be
           77  +** PAGER_RESERVED.  (Note that sqlite_page_write() can only be
    73     78   ** called on an outstanding page which means that the pager must
    74         -** be in SQLITE_READLOCK before it transitions to SQLITE_WRITELOCK.)
           79  +** be in PAGER_SHARED before it transitions to PAGER_RESERVED.)
    75     80   ** The sqlite_page_rollback() and sqlite_page_commit() functions 
    76         -** transition the state from SQLITE_WRITELOCK back to SQLITE_READLOCK.
           81  +** transition the state from PAGER_RESERVED to PAGER_EXCLUSIVE to
           82  +** PAGER_SHARED.
    77     83   */
    78         -#define SQLITE_UNLOCK      0
    79         -#define SQLITE_READLOCK    1
    80         -#define SQLITE_WRITELOCK   2
           84  +#define PAGER_UNLOCK      0
           85  +#define PAGER_SHARED      1
           86  +#define PAGER_RESERVED    2
           87  +#define PAGER_EXCLUSIVE   3
    81     88   
    82     89   
    83     90   /*
    84     91   ** Each in-memory image of a page begins with the following header.
    85     92   ** This header is only visible to this pager module.  The client
    86     93   ** code that calls pager sees only the data that follows the header.
    87     94   **
................................................................................
   178    185     int stmtSize;               /* Size of database (in pages) at stmt_begin() */
   179    186     off_t stmtJSize;            /* Size of journal at stmt_begin() */
   180    187     int nRec;                   /* Number of pages written to the journal */
   181    188     u32 cksumInit;              /* Quasi-random value added to every checksum */
   182    189     int stmtNRec;               /* Number of records in stmt subjournal */
   183    190     int nExtra;                 /* Add this many bytes to each in-memory page */
   184    191     void (*xDestructor)(void*,int); /* Call this routine when freeing pages */
          192  +  void (*xReiniter)(void*,int);   /* Call this routine when reloading pages */
   185    193     int pageSize;               /* Number of bytes in a page */
   186    194     int nPage;                  /* Total number of in-memory pages */
   187    195     int nRef;                   /* Number of in-memory pages with PgHdr.nRef>0 */
   188    196     int mxPage;                 /* Maximum number of pages to hold in cache */
   189    197     int nHit, nMiss, nOvfl;     /* Cache hits, missing, and LRU overflows */
   190    198     void (*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
   191    199     void *pCodecArg;            /* First argument to xCodec() */
................................................................................
   193    201     u8 journalStarted;          /* True if header of journal is synced */
   194    202     u8 useJournal;              /* Use a rollback journal on this file */
   195    203     u8 stmtOpen;                /* True if the statement subjournal is open */
   196    204     u8 stmtInUse;               /* True we are in a statement subtransaction */
   197    205     u8 stmtAutoopen;            /* Open stmt journal when main journal is opened*/
   198    206     u8 noSync;                  /* Do not sync the journal if true */
   199    207     u8 fullSync;                /* Do extra syncs of the journal for robustness */
   200         -  u8 state;                   /* SQLITE_UNLOCK, _READLOCK or _WRITELOCK */
          208  +  u8 state;                   /* PAGER_UNLOCK, _SHARED, _RESERVED, etc. */
   201    209     u8 errMask;                 /* One of several kinds of errors */
   202    210     u8 tempFile;                /* zFilename is a temporary file */
   203    211     u8 readOnly;                /* True for a read-only database */
   204    212     u8 needSync;                /* True if an fsync() is needed on the journal */
   205         -  u8 dirtyFile;               /* True if database file has changed in any way */
          213  +  u8 dirtyCache;              /* True if cached pages have changed */
   206    214     u8 alwaysRollback;          /* Disable dont_rollback() for all pages */
   207    215     u8 memDb;                   /* True to inhibit all file I/O */
   208    216     u8 *aInJournal;             /* One bit for each page in the database file */
   209    217     u8 *aInStmt;                /* One bit for each page in the database */
   210    218     PgHdr *pFirst, *pLast;      /* List of free pages */
   211    219     PgHdr *pFirstSynced;        /* First free page with PgHdr.needSync==0 */
   212    220     PgHdr *pAll;                /* List of all pages */
................................................................................
   475    483     }
   476    484     pPager->pFirst = 0;
   477    485     pPager->pFirstSynced = 0;
   478    486     pPager->pLast = 0;
   479    487     pPager->pAll = 0;
   480    488     memset(pPager->aHash, 0, sizeof(pPager->aHash));
   481    489     pPager->nPage = 0;
   482         -  if( pPager->state>=SQLITE_WRITELOCK ){
          490  +  if( pPager->state>=PAGER_RESERVED ){
   483    491       sqlite3pager_rollback(pPager);
   484    492     }
   485         -  sqlite3OsUnlock(&pPager->fd);
   486         -  pPager->state = SQLITE_UNLOCK;
          493  +  sqlite3OsUnlock(&pPager->fd, NO_LOCK);
          494  +  pPager->state = PAGER_UNLOCK;
   487    495     pPager->dbSize = -1;
   488    496     pPager->nRef = 0;
   489    497     assert( pPager->journalOpen==0 );
   490    498   }
   491    499   
   492    500   /*
   493    501   ** When this routine is called, the pager has the journal file open and
   494         -** a write lock on the database.  This routine releases the database
   495         -** write lock and acquires a read lock in its place.  The journal file
   496         -** is deleted and closed.
          502  +** a RESERVED or EXCLUSIVE lock on the database.  This routine releases
          503  +** the database lock and acquires a SHARED lock in its place.  The journal
          504  +** file is deleted and closed.
   497    505   **
   498    506   ** TODO: Consider keeping the journal file open for temporary databases.
   499    507   ** This might give a performance improvement on windows where opening
   500    508   ** a file is an expensive operation.
   501    509   */
   502    510   static int pager_unwritelock(Pager *pPager){
   503         -  int rc;
   504    511     PgHdr *pPg;
   505         -  if( pPager->state<SQLITE_WRITELOCK ) return SQLITE_OK;
          512  +  if( pPager->state<PAGER_RESERVED ){
          513  +    return SQLITE_OK;
          514  +  }
   506    515     sqlite3pager_stmt_commit(pPager);
   507    516     if( pPager->stmtOpen ){
   508    517       sqlite3OsClose(&pPager->stfd);
   509    518       pPager->stmtOpen = 0;
   510    519     }
   511    520     if( pPager->journalOpen ){
   512    521       sqlite3OsClose(&pPager->jfd);
................................................................................
   516    525       pPager->aInJournal = 0;
   517    526       for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
   518    527         pPg->inJournal = 0;
   519    528         pPg->dirty = 0;
   520    529         pPg->needSync = 0;
   521    530       }
   522    531     }else{
   523         -    assert( pPager->dirtyFile==0 || pPager->useJournal==0 );
          532  +    assert( pPager->dirtyCache==0 || pPager->useJournal==0 );
   524    533     }
   525         -  rc = sqlite3OsLock(&pPager->fd, SHARED_LOCK);
   526         -  if( rc==SQLITE_OK ){
   527         -    pPager->state = SQLITE_READLOCK;
   528         -  }else{
   529         -    /* This can only happen if a process does a BEGIN, then forks and the
   530         -    ** child process does the COMMIT.  Because of the semantics of unix
   531         -    ** file locking, the unlock will fail.
   532         -    */
   533         -    pPager->state = SQLITE_UNLOCK;
   534         -  }
   535         -  return rc;
          534  +  sqlite3OsUnlock(&pPager->fd, SHARED_LOCK);
          535  +  pPager->state = PAGER_SHARED;
          536  +  return SQLITE_OK;
   536    537   }
   537    538   
   538    539   /*
   539    540   ** Compute and return a checksum for the page of data.
   540    541   **
   541    542   ** This is not a real checksum.  It is really just the sum of the 
   542    543   ** random initial value and the page number.  We considered do a checksum
................................................................................
   584    585       }
   585    586     }
   586    587   
   587    588     /* Playback the page.  Update the in-memory copy of the page
   588    589     ** at the same time, if there is one.
   589    590     */
   590    591     pPg = pager_lookup(pPager, pgRec.pgno);
   591         -  TRACE2("PLAYBACK %d\n", pgRec.pgno);
          592  +  TRACE2("PLAYBACK page %d\n", pgRec.pgno);
   592    593     sqlite3OsSeek(&pPager->fd, (pgRec.pgno-1)*(off_t)SQLITE_PAGE_SIZE);
   593    594     rc = sqlite3OsWrite(&pPager->fd, pgRec.aData, SQLITE_PAGE_SIZE);
   594    595     if( pPg ){
   595    596       /* No page should ever be rolled back that is in use, except for page
   596    597       ** 1 which is held in use in order to keep the lock on the database
   597    598       ** active.
   598    599       */
................................................................................
   716    717       sqliteFree(zMasterJournal);
   717    718     }  
   718    719     if( master_open ){
   719    720       sqlite3OsClose(&master);
   720    721     }
   721    722     return rc;
   722    723   }
          724  +
          725  +/*
          726  +** Make every page in the cache agree with what is on disk.  In other words,
          727  +** reread the disk to reset the state of the cache.
          728  +**
          729  +** This routine is called after a rollback in which some of the dirty cache
          730  +** pages had never been written out to disk.  We need to roll back the
          731  +** cache content and the easiest way to do that is to reread the old content
          732  +** back from the disk.
          733  +*/
          734  +static int pager_reload_cache(Pager *pPager){
          735  +  PgHdr *pPg;
          736  +  int rc = SQLITE_OK;
          737  +  for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
          738  +    char zBuf[SQLITE_PAGE_SIZE];
          739  +    if( !pPg->dirty ) continue;
          740  +    if( (int)pPg->pgno <= pPager->origDbSize ){
          741  +      sqlite3OsSeek(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)(pPg->pgno-1));
          742  +      rc = sqlite3OsRead(&pPager->fd, zBuf, SQLITE_PAGE_SIZE);
          743  +      TRACE2("REFETCH page %d\n", pPg->pgno);
          744  +      CODEC(pPager, zBuf, pPg->pgno, 2);
          745  +      if( rc ) break;
          746  +    }else{
          747  +      memset(zBuf, 0, SQLITE_PAGE_SIZE);
          748  +    }
          749  +    if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE) ){
          750  +      memcpy(PGHDR_TO_DATA(pPg), zBuf, SQLITE_PAGE_SIZE);
          751  +      if( pPager->xReiniter ){
          752  +        pPager->xReiniter(PGHDR_TO_DATA(pPg), pPager->pageSize);
          753  +      }else{
          754  +        memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
          755  +      }
          756  +    }
          757  +    pPg->needSync = 0;
          758  +    pPg->dirty = 0;
          759  +  }
          760  +  return rc;
          761  +}
          762  +
   723    763   
   724    764   /*
   725    765   ** Playback the journal and thus restore the database file to
   726    766   ** the state it was in before we started making changes.  
   727    767   **
   728    768   ** The journal file format is as follows: 
   729    769   **
................................................................................
   883    923     }
   884    924   
   885    925     /* Pages that have been written to the journal but never synced
   886    926     ** where not restored by the loop above.  We have to restore those
   887    927     ** pages by reading them back from the original database.
   888    928     */
   889    929     if( rc==SQLITE_OK ){
   890         -    PgHdr *pPg;
   891         -    for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
   892         -      char zBuf[SQLITE_PAGE_SIZE];
   893         -      if( !pPg->dirty ) continue;
   894         -      if( (int)pPg->pgno <= pPager->origDbSize ){
   895         -        sqlite3OsSeek(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)(pPg->pgno-1));
   896         -        rc = sqlite3OsRead(&pPager->fd, zBuf, SQLITE_PAGE_SIZE);
   897         -        TRACE2("REFETCH %d\n", pPg->pgno);
   898         -        CODEC(pPager, zBuf, pPg->pgno, 2);
   899         -        if( rc ) break;
   900         -      }else{
   901         -        memset(zBuf, 0, SQLITE_PAGE_SIZE);
   902         -      }
   903         -      if( pPg->nRef==0 || memcmp(zBuf, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE) ){
   904         -        memcpy(PGHDR_TO_DATA(pPg), zBuf, SQLITE_PAGE_SIZE);
   905         -        memset(PGHDR_TO_EXTRA(pPg), 0, pPager->nExtra);
   906         -      }
   907         -      pPg->needSync = 0;
   908         -      pPg->dirty = 0;
   909         -    }
          930  +    pager_reload_cache(pPager);
   910    931     }
   911    932   
   912    933   end_playback:
   913    934     if( zMaster ){
   914    935       /* If there was a master journal and this routine will return true,
   915    936       ** see if it is possible to delete the master journal. If errors 
   916    937       ** occur during this process, ignore them.
................................................................................
  1161   1182     pPager->nRef = 0;
  1162   1183     pPager->dbSize = memDb-1;
  1163   1184     pPager->pageSize = SQLITE_PAGE_SIZE;
  1164   1185     pPager->stmtSize = 0;
  1165   1186     pPager->stmtJSize = 0;
  1166   1187     pPager->nPage = 0;
  1167   1188     pPager->mxPage = mxPage>5 ? mxPage : 10;
  1168         -  pPager->state = SQLITE_UNLOCK;
         1189  +  pPager->state = PAGER_UNLOCK;
  1169   1190     pPager->errMask = 0;
  1170   1191     pPager->tempFile = tempFile;
  1171   1192     pPager->memDb = memDb;
  1172   1193     pPager->readOnly = readOnly;
  1173   1194     pPager->needSync = 0;
  1174   1195     pPager->noSync = pPager->tempFile || !useJournal;
  1175   1196     pPager->pFirst = 0;
................................................................................
  1189   1210   **
  1190   1211   ** The destructor is not called as a result sqlite3pager_close().  
  1191   1212   ** Destructors are only called by sqlite3pager_unref().
  1192   1213   */
  1193   1214   void sqlite3pager_set_destructor(Pager *pPager, void (*xDesc)(void*,int)){
  1194   1215     pPager->xDestructor = xDesc;
  1195   1216   }
         1217  +
         1218  +/*
         1219  +** Set the reinitializer for this pager.  If not NULL, the reinitializer
         1220  +** is called when the content of a page in cache is restored to its original
         1221  +** value as a result of a rollback.  The callback gives higher-level code
         1222  +** an opportunity to restore the EXTRA section to agree with the restored
         1223  +** page data.
         1224  +*/
         1225  +void sqlite3pager_set_reiniter(Pager *pPager, void (*xReinit)(void*,int)){
         1226  +  pPager->xReiniter = xReinit;
         1227  +}
  1196   1228   
  1197   1229   /*
  1198   1230   ** Return the total number of pages in the disk file associated with
  1199   1231   ** pPager.
  1200   1232   */
  1201   1233   int sqlite3pager_pagecount(Pager *pPager){
  1202   1234     off_t n;
................................................................................
  1205   1237       return pPager->dbSize;
  1206   1238     }
  1207   1239     if( sqlite3OsFileSize(&pPager->fd, &n)!=SQLITE_OK ){
  1208   1240       pPager->errMask |= PAGER_ERR_DISK;
  1209   1241       return 0;
  1210   1242     }
  1211   1243     n /= SQLITE_PAGE_SIZE;
  1212         -  if( pPager->state!=SQLITE_UNLOCK ){
         1244  +  if( pPager->state!=PAGER_UNLOCK ){
  1213   1245       pPager->dbSize = n;
  1214   1246     }
  1215   1247     return n;
  1216   1248   }
  1217   1249   
  1218   1250   /*
  1219   1251   ** Forward declaration
................................................................................
  1326   1358   ** and their memory is freed.  Any attempt to use a page associated
  1327   1359   ** with this page cache after this function returns will likely
  1328   1360   ** result in a coredump.
  1329   1361   */
  1330   1362   int sqlite3pager_close(Pager *pPager){
  1331   1363     PgHdr *pPg, *pNext;
  1332   1364     switch( pPager->state ){
  1333         -    case SQLITE_WRITELOCK: {
         1365  +    case PAGER_RESERVED:
         1366  +    case PAGER_EXCLUSIVE: {
  1334   1367         sqlite3pager_rollback(pPager);
  1335   1368         if( !pPager->memDb ){
  1336         -        sqlite3OsUnlock(&pPager->fd);
         1369  +        sqlite3OsUnlock(&pPager->fd, NO_LOCK);
  1337   1370         }
  1338   1371         assert( pPager->journalOpen==0 );
  1339   1372         break;
  1340   1373       }
  1341         -    case SQLITE_READLOCK: {
         1374  +    case PAGER_SHARED: {
  1342   1375         if( !pPager->memDb ){
  1343         -        sqlite3OsUnlock(&pPager->fd);
         1376  +        sqlite3OsUnlock(&pPager->fd, NO_LOCK);
  1344   1377         }
  1345   1378         break;
  1346   1379       }
  1347   1380       default: {
  1348   1381         /* Do nothing */
  1349   1382         break;
  1350   1383       }
................................................................................
  1481   1514           assert( pPager->nRec*pgSz+hdrSz==jSz );
  1482   1515         }
  1483   1516   #endif
  1484   1517         if( journal_format>=3 ){
  1485   1518           /* Write the nRec value into the journal file header */
  1486   1519           off_t szJ;
  1487   1520           if( pPager->fullSync ){
  1488         -          TRACE1("SYNC\n");
         1521  +          TRACE2("SYNC journal of %d\n", pPager->fd.h);
  1489   1522             rc = sqlite3OsSync(&pPager->jfd);
  1490   1523             if( rc!=0 ) return rc;
  1491   1524           }
  1492   1525           sqlite3OsSeek(&pPager->jfd, sizeof(aJournalMagic1));
  1493   1526           rc = write32bits(&pPager->jfd, pPager->nRec);
  1494   1527           if( rc ) return rc;
  1495   1528   
................................................................................
  1502   1535             if( rc ) return rc;
  1503   1536           }
  1504   1537   
  1505   1538           szJ = JOURNAL_HDR_SZ(pPager, journal_format) +
  1506   1539                    pPager->nRec*JOURNAL_PG_SZ(journal_format);
  1507   1540           sqlite3OsSeek(&pPager->jfd, szJ);
  1508   1541         }
  1509         -      TRACE1("SYNC\n");
         1542  +      TRACE2("SYNC journal of %d\n", pPager->fd.h);
  1510   1543         rc = sqlite3OsSync(&pPager->jfd);
  1511   1544         if( rc!=0 ) return rc;
  1512   1545         pPager->journalStarted = 1;
  1513   1546       }
  1514   1547       pPager->needSync = 0;
  1515   1548   
  1516   1549       /* Erase the needSync flag from every page.
................................................................................
  1550   1583     if( pList==0 ) return SQLITE_OK;
  1551   1584     pPager = pList->pPager;
  1552   1585   
  1553   1586     /* At this point there may be either a RESERVED or EXCLUSIVE lock on the
  1554   1587     ** database file. If there is already an EXCLUSIVE lock, the following
  1555   1588     ** calls to sqlite3OsLock() are no-ops.
  1556   1589     **
  1557         -  ** The upgrade from a RESERVED to PENDING might return SQLITE_BUSY on
  1558         -  ** windows because the windows locking mechanism acquires a transient
  1559         -  ** PENDING lock during its attempts to get a SHARED lock.  So if another
  1560         -  ** process were trying to get a SHARED lock at the same time this process
  1561         -  ** is upgrading from RESERVED to PENDING, the two could collide.
         1590  +  ** Moving the lock from RESERVED to EXCLUSIVE actually involves going
         1591  +  ** through an intermediate state PENDING.   A PENDING lock prevents new
         1592  +  ** readers from attaching to the database but is unsufficient for us to
         1593  +  ** write.  The idea of a PENDING lock is to prevent new readers from
         1594  +  ** coming in while we wait for existing readers to clear.
  1562   1595     **
  1563         -  ** The upgrade from PENDING to EXCLUSIVE can return SQLITE_BUSY if there
  1564         -  ** are still active readers that were created before the PENDING lock
  1565         -  ** was acquired.
         1596  +  ** While the pager is in the RESERVED state, the original database file
         1597  +  ** is unchanged and we can rollback without having to playback the
         1598  +  ** journal into the original database file.  Once we transition to
         1599  +  ** EXCLUSIVE, it means the database file has been changed and any rollback
         1600  +  ** will require a journal playback.
  1566   1601     */
  1567   1602     do {
  1568   1603       rc = sqlite3OsLock(&pPager->fd, EXCLUSIVE_LOCK);
  1569   1604     }while( rc==SQLITE_BUSY && 
  1570   1605         pPager->pBusyHandler && 
  1571   1606         pPager->pBusyHandler->xFunc && 
  1572   1607         pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, "", busy++)
  1573   1608     );
  1574   1609     if( rc!=SQLITE_OK ){
  1575   1610       return rc;
  1576   1611     }
         1612  +  pPager->state = PAGER_EXCLUSIVE;
  1577   1613   
  1578   1614     while( pList ){
  1579   1615       assert( pList->dirty );
  1580   1616       sqlite3OsSeek(&pPager->fd, (pList->pgno-1)*(off_t)SQLITE_PAGE_SIZE);
  1581   1617       CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 6);
  1582         -    TRACE2("STORE %d\n", pList->pgno);
         1618  +    TRACE2("STORE page %d\n", pList->pgno);
  1583   1619       rc = sqlite3OsWrite(&pPager->fd, PGHDR_TO_DATA(pList), SQLITE_PAGE_SIZE);
  1584   1620       CODEC(pPager, PGHDR_TO_DATA(pList), pList->pgno, 0);
  1585   1621       if( rc ) return rc;
  1586   1622       pList->dirty = 0;
  1587   1623       pList = pList->pDirty;
  1588   1624     }
  1589   1625     return SQLITE_OK;
................................................................................
  1653   1689           pPager->pBusyHandler && 
  1654   1690           pPager->pBusyHandler->xFunc && 
  1655   1691           pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, "", busy++)
  1656   1692       );
  1657   1693       if( rc!=SQLITE_OK ){
  1658   1694         return rc;
  1659   1695       }
  1660         -    pPager->state = SQLITE_READLOCK;
         1696  +    pPager->state = PAGER_SHARED;
  1661   1697   
  1662   1698       /* If a journal file exists, and there is no RESERVED lock on the
  1663   1699       ** database file, then it either needs to be played back or deleted.
  1664   1700       */
  1665   1701       if( pPager->useJournal && 
  1666   1702           sqlite3OsFileExists(pPager->zJournal) &&
  1667         -        !sqlite3OsCheckWriteLock(&pPager->fd) 
         1703  +        !sqlite3OsCheckReservedLock(&pPager->fd) 
  1668   1704       ){
  1669   1705          int rc;
  1670   1706   
  1671   1707          /* Get an EXCLUSIVE lock on the database file. */
  1672   1708          rc = sqlite3OsLock(&pPager->fd, EXCLUSIVE_LOCK);
  1673   1709          if( rc!=SQLITE_OK ){
  1674         -         if( sqlite3OsUnlock(&pPager->fd)!=SQLITE_OK ){
  1675         -           /* This should never happen! */
  1676         -           rc = SQLITE_INTERNAL;
  1677         -         }
         1710  +         sqlite3OsUnlock(&pPager->fd, NO_LOCK);
         1711  +         pPager->state = PAGER_UNLOCK;
  1678   1712            return rc;
  1679   1713          }
  1680         -       pPager->state = SQLITE_WRITELOCK;
         1714  +       pPager->state = PAGER_EXCLUSIVE;
  1681   1715   
  1682   1716          /* Open the journal for reading only.  Return SQLITE_BUSY if
  1683   1717          ** we are unable to open the journal file. 
  1684   1718          **
  1685   1719          ** The journal file does not need to be locked itself.  The
  1686   1720          ** journal file is never open unless the main database file holds
  1687   1721          ** a write lock, so there is never any chance of two or more
  1688   1722          ** processes opening the journal at the same time.
  1689   1723          */
  1690   1724          rc = sqlite3OsOpenReadOnly(pPager->zJournal, &pPager->jfd);
  1691   1725          if( rc!=SQLITE_OK ){
  1692         -         rc = sqlite3OsUnlock(&pPager->fd);
  1693         -         assert( rc==SQLITE_OK );
         1726  +         sqlite3OsUnlock(&pPager->fd, NO_LOCK);
         1727  +         pPager->state = PAGER_UNLOCK;
  1694   1728            return SQLITE_BUSY;
  1695   1729          }
  1696   1730          pPager->journalOpen = 1;
  1697   1731          pPager->journalStarted = 0;
  1698   1732   
  1699   1733          /* Playback and delete the journal.  Drop the database write
  1700   1734          ** lock and reacquire the read lock.
................................................................................
  1704   1738            return rc;
  1705   1739          }
  1706   1740       }
  1707   1741       pPg = 0;
  1708   1742     }else{
  1709   1743       /* Search for page in cache */
  1710   1744       pPg = pager_lookup(pPager, pgno);
  1711         -    if( pPager->memDb && pPager->state==SQLITE_UNLOCK ){
  1712         -      pPager->state = SQLITE_READLOCK;
         1745  +    if( pPager->memDb && pPager->state==PAGER_UNLOCK ){
         1746  +      pPager->state = PAGER_SHARED;
  1713   1747       }
  1714   1748     }
  1715   1749     if( pPg==0 ){
  1716   1750       /* The requested page is not in the page cache. */
  1717   1751       int h;
  1718   1752       pPager->nMiss++;
  1719   1753       if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || pPager->memDb ){
................................................................................
  1824   1858       if( pPager->dbSize<(int)pgno ){
  1825   1859         memset(PGHDR_TO_DATA(pPg), 0, SQLITE_PAGE_SIZE);
  1826   1860       }else{
  1827   1861         int rc;
  1828   1862         assert( pPager->memDb==0 );
  1829   1863         sqlite3OsSeek(&pPager->fd, (pgno-1)*(off_t)SQLITE_PAGE_SIZE);
  1830   1864         rc = sqlite3OsRead(&pPager->fd, PGHDR_TO_DATA(pPg), SQLITE_PAGE_SIZE);
  1831         -      TRACE2("FETCH %d\n", pPg->pgno);
         1865  +      TRACE2("FETCH page %d\n", pPg->pgno);
  1832   1866         CODEC(pPager, PGHDR_TO_DATA(pPg), pPg->pgno, 3);
  1833   1867         if( rc!=SQLITE_OK ){
  1834   1868           off_t fileSize;
  1835   1869           if( sqlite3OsFileSize(&pPager->fd,&fileSize)!=SQLITE_OK
  1836   1870                  || fileSize>=pgno*SQLITE_PAGE_SIZE ){
  1837   1871             sqlite3pager_unref(PGHDR_TO_DATA(pPg));
  1838   1872             return rc;
................................................................................
  1923   1957         pager_reset(pPager);
  1924   1958       }
  1925   1959     }
  1926   1960     return SQLITE_OK;
  1927   1961   }
  1928   1962   
  1929   1963   /*
  1930         -** Create a journal file for pPager.  There should already be a write
  1931         -** lock on the database file when this routine is called.
         1964  +** Create a journal file for pPager.  There should already be a RESERVED
         1965  +** or EXCLUSIVE lock on the database file when this routine is called.
  1932   1966   **
  1933   1967   ** Return SQLITE_OK if everything.  Return an error code and release the
  1934   1968   ** write lock if anything goes wrong.
  1935   1969   */
  1936   1970   static int pager_open_journal(Pager *pPager){
  1937   1971     int rc;
  1938         -  assert( pPager->state==SQLITE_WRITELOCK );
         1972  +  assert( pPager->state>=PAGER_RESERVED );
  1939   1973     assert( pPager->journalOpen==0 );
  1940   1974     assert( pPager->useJournal );
  1941   1975     sqlite3pager_pagecount(pPager);
  1942   1976     pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 );
  1943   1977     if( pPager->aInJournal==0 ){
  1944         -    sqlite3OsLock(&pPager->fd, SHARED_LOCK);
  1945         -    pPager->state = SQLITE_READLOCK;
         1978  +    sqlite3OsUnlock(&pPager->fd, SHARED_LOCK);
         1979  +    pPager->state = PAGER_SHARED;
  1946   1980       return SQLITE_NOMEM;
  1947   1981     }
  1948   1982     rc = sqlite3OsOpenExclusive(pPager->zJournal, &pPager->jfd,pPager->tempFile);
  1949   1983     if( rc!=SQLITE_OK ){
  1950   1984       sqliteFree(pPager->aInJournal);
  1951   1985       pPager->aInJournal = 0;
  1952         -    sqlite3OsLock(&pPager->fd, SHARED_LOCK);
  1953         -    pPager->state = SQLITE_READLOCK;
         1986  +    sqlite3OsUnlock(&pPager->fd, SHARED_LOCK);
         1987  +    pPager->state = PAGER_SHARED;
  1954   1988       return SQLITE_CANTOPEN;
  1955   1989     }
  1956   1990     sqlite3OsOpenDirectory(pPager->zDirectory, &pPager->jfd);
  1957   1991     pPager->journalOpen = 1;
  1958   1992     pPager->journalStarted = 0;
  1959   1993     pPager->needSync = 0;
  1960   1994     pPager->alwaysRollback = 0;
................................................................................
  2035   2069   ** The second parameter indicates how much space in bytes to reserve for a
  2036   2070   ** master journal file-name at the start of the journal when it is created.
  2037   2071   **
  2038   2072   ** A journal file is opened if this is not a temporary file.  For temporary
  2039   2073   ** files, the opening of the journal file is deferred until there is an
  2040   2074   ** actual need to write to the journal.
  2041   2075   **
  2042         -** If the database is already write-locked, this routine is a no-op.
         2076  +** If the database is already reserved for writing, this routine is a no-op.
  2043   2077   */
  2044   2078   int sqlite3pager_begin(void *pData, int nMaster){
  2045   2079     PgHdr *pPg = DATA_TO_PGHDR(pData);
  2046   2080     Pager *pPager = pPg->pPager;
  2047   2081     int rc = SQLITE_OK;
  2048   2082     assert( pPg->nRef>0 );
  2049   2083     assert( nMaster>=0 );
  2050         -  assert( pPager->state!=SQLITE_UNLOCK );
  2051         -  if( pPager->state==SQLITE_READLOCK ){
         2084  +  assert( pPager->state!=PAGER_UNLOCK );
         2085  +  if( pPager->state==PAGER_SHARED ){
  2052   2086       assert( pPager->aInJournal==0 );
  2053   2087       if( pPager->memDb ){
  2054         -      pPager->state = SQLITE_WRITELOCK;
         2088  +      pPager->state = PAGER_EXCLUSIVE;
  2055   2089         pPager->origDbSize = pPager->dbSize;
  2056   2090       }else{
  2057   2091         int busy = 1;
  2058   2092         do {
  2059         -	/* If the library grabs an EXCLUSIVE lock here, as in the commented
  2060         -        ** out line, then it exhibits the old locking behaviour - a writer
  2061         -        ** excludes all readers, not just other writers.
  2062         -        */
  2063         -        /* rc = sqlite3OsLock(&pPager->fd, EXCLUSIVE_LOCK); */
  2064   2093           rc = sqlite3OsLock(&pPager->fd, RESERVED_LOCK);
  2065   2094         }while( rc==SQLITE_BUSY && 
  2066   2095             pPager->pBusyHandler && 
  2067   2096             pPager->pBusyHandler->xFunc && 
  2068   2097             pPager->pBusyHandler->xFunc(pPager->pBusyHandler->pArg, "", busy++)
  2069   2098         );
  2070   2099         if( rc!=SQLITE_OK ){
  2071   2100           return rc;
  2072   2101         }
  2073   2102         pPager->nMaster = nMaster;
  2074         -      pPager->state = SQLITE_WRITELOCK;
  2075         -      pPager->dirtyFile = 0;
  2076         -      TRACE1("TRANSACTION\n");
         2103  +      pPager->state = PAGER_RESERVED;
         2104  +      pPager->dirtyCache = 0;
         2105  +      TRACE3("TRANSACTION %d nMaster=%d\n", pPager->fd.h, nMaster);
  2077   2106         if( pPager->useJournal && !pPager->tempFile ){
  2078   2107           rc = pager_open_journal(pPager);
  2079   2108         }
  2080   2109       }
  2081   2110     }
  2082   2111     return rc;
  2083   2112   }
................................................................................
  2084   2113   
  2085   2114   /*
  2086   2115   ** Mark a data page as writeable.  The page is written into the journal 
  2087   2116   ** if it is not there already.  This routine must be called before making
  2088   2117   ** changes to a page.
  2089   2118   **
  2090   2119   ** The first time this routine is called, the pager creates a new
  2091         -** journal and acquires a write lock on the database.  If the write
         2120  +** journal and acquires a RESERVED lock on the database.  If the RESERVED
  2092   2121   ** lock could not be acquired, this routine returns SQLITE_BUSY.  The
  2093   2122   ** calling routine must check for that return value and be careful not to
  2094   2123   ** change any page data until this routine returns SQLITE_OK.
  2095   2124   **
  2096   2125   ** If the journal file could not be written because the disk is full,
  2097   2126   ** then this routine returns SQLITE_FULL and does an immediate rollback.
  2098   2127   ** All subsequent write attempts also return SQLITE_FULL until there
................................................................................
  2114   2143     }
  2115   2144   
  2116   2145     /* Mark the page as dirty.  If the page has already been written
  2117   2146     ** to the journal then we can return right away.
  2118   2147     */
  2119   2148     pPg->dirty = 1;
  2120   2149     if( pPg->inJournal && (pPg->inStmt || pPager->stmtInUse==0) ){
  2121         -    pPager->dirtyFile = 1;
         2150  +    pPager->dirtyCache = 1;
  2122   2151       return SQLITE_OK;
  2123   2152     }
  2124   2153   
  2125   2154     /* If we get this far, it means that the page needs to be
  2126   2155     ** written to the transaction journal or the ckeckpoint journal
  2127   2156     ** or both.
  2128   2157     **
  2129   2158     ** First check to see that the transaction journal exists and
  2130   2159     ** create it if it does not.
  2131   2160     */
  2132         -  assert( pPager->state!=SQLITE_UNLOCK );
         2161  +  assert( pPager->state!=PAGER_UNLOCK );
  2133   2162     rc = sqlite3pager_begin(pData, 0);
  2134   2163     if( rc!=SQLITE_OK ){
  2135   2164       return rc;
  2136   2165     }
  2137         -  assert( pPager->state==SQLITE_WRITELOCK );
         2166  +  assert( pPager->state>=PAGER_RESERVED );
  2138   2167     if( !pPager->journalOpen && pPager->useJournal ){
  2139   2168       rc = pager_open_journal(pPager);
  2140   2169       if( rc!=SQLITE_OK ) return rc;
  2141   2170     }
  2142   2171     assert( pPager->journalOpen || !pPager->useJournal );
  2143         -  pPager->dirtyFile = 1;
         2172  +  pPager->dirtyCache = 1;
  2144   2173   
  2145         -  /* The transaction journal now exists and we have a write lock on the
  2146         -  ** main database file.  Write the current page to the transaction 
  2147         -  ** journal if it is not there already.
         2174  +  /* The transaction journal now exists and we have a RESERVED or an
         2175  +  ** EXCLUSIVE lock on the main database file.  Write the current page to
         2176  +  ** the transaction journal if it is not there already.
  2148   2177     */
  2149   2178     if( !pPg->inJournal && (pPager->useJournal || pPager->memDb) ){
  2150   2179       if( (int)pPg->pgno <= pPager->origDbSize ){
  2151   2180         int szPg;
  2152   2181         u32 saved;
  2153   2182         if( pPager->memDb ){
  2154   2183           PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
  2155         -        TRACE2("JOURNAL %d\n", pPg->pgno);
         2184  +        TRACE2("JOURNAL page %d\n", pPg->pgno);
  2156   2185           assert( pHist->pOrig==0 );
  2157   2186           pHist->pOrig = sqliteMallocRaw( pPager->pageSize );
  2158   2187           if( pHist->pOrig ){
  2159   2188             memcpy(pHist->pOrig, PGHDR_TO_DATA(pPg), pPager->pageSize);
  2160   2189           }
  2161   2190           pPg->inJournal = 1;
  2162   2191         }else{
................................................................................
  2167   2196             szPg = SQLITE_PAGE_SIZE+8;
  2168   2197           }else{
  2169   2198             szPg = SQLITE_PAGE_SIZE+4;
  2170   2199           }
  2171   2200           store32bits(pPg->pgno, pPg, -4);
  2172   2201           CODEC(pPager, pData, pPg->pgno, 7);
  2173   2202           rc = sqlite3OsWrite(&pPager->jfd, &((char*)pData)[-4], szPg);
  2174         -        TRACE3("JOURNAL %d %d\n", pPg->pgno, pPg->needSync);
         2203  +        TRACE3("JOURNAL page %d needSync=%d\n", pPg->pgno, pPg->needSync);
  2175   2204           CODEC(pPager, pData, pPg->pgno, 0);
  2176   2205           if( journal_format>=JOURNAL_FORMAT_3 ){
  2177   2206             *(u32*)PGHDR_TO_EXTRA(pPg) = saved;
  2178   2207           }
  2179   2208           if( rc!=SQLITE_OK ){
  2180   2209             sqlite3pager_rollback(pPager);
  2181   2210             pPager->errMask |= PAGER_ERR_FULL;
................................................................................
  2189   2218           if( pPager->stmtInUse ){
  2190   2219             pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
  2191   2220             page_add_to_stmt_list(pPg);
  2192   2221           }
  2193   2222         }
  2194   2223       }else{
  2195   2224         pPg->needSync = !pPager->journalStarted && !pPager->noSync;
  2196         -      TRACE3("APPEND %d %d\n", pPg->pgno, pPg->needSync);
         2225  +      TRACE3("APPEND page %d needSync=%d\n", pPg->pgno, pPg->needSync);
  2197   2226       }
  2198   2227       if( pPg->needSync ){
  2199   2228         pPager->needSync = 1;
  2200   2229       }
  2201   2230     }
  2202   2231   
  2203   2232     /* If the statement journal is open and the page is not in it,
................................................................................
  2210   2239       if( pPager->memDb ){
  2211   2240         PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
  2212   2241         assert( pHist->pStmt==0 );
  2213   2242         pHist->pStmt = sqliteMallocRaw( pPager->pageSize );
  2214   2243         if( pHist->pStmt ){
  2215   2244           memcpy(pHist->pStmt, PGHDR_TO_DATA(pPg), pPager->pageSize);
  2216   2245         }
  2217         -      TRACE2("STMT-JOURNAL %d\n", pPg->pgno);
         2246  +      TRACE2("STMT-JOURNAL page %d\n", pPg->pgno);
  2218   2247       }else{
  2219   2248         store32bits(pPg->pgno, pPg, -4);
  2220   2249         CODEC(pPager, pData, pPg->pgno, 7);
  2221   2250         rc = sqlite3OsWrite(&pPager->stfd, ((char*)pData)-4, SQLITE_PAGE_SIZE+4);
  2222         -      TRACE2("STMT-JOURNAL %d\n", pPg->pgno);
         2251  +      TRACE2("STMT-JOURNAL page %d\n", pPg->pgno);
  2223   2252         CODEC(pPager, pData, pPg->pgno, 0);
  2224   2253         if( rc!=SQLITE_OK ){
  2225   2254           sqlite3pager_rollback(pPager);
  2226   2255           pPager->errMask |= PAGER_ERR_FULL;
  2227   2256           return rc;
  2228   2257         }
  2229   2258         pPager->stmtNRec++;
................................................................................
  2306   2335         ** When the database file grows, we must make sure that the last page
  2307   2336         ** gets written at least once so that the disk file will be the correct
  2308   2337         ** size. If you do not write this page and the size of the file
  2309   2338         ** on the disk ends up being too small, that can lead to database
  2310   2339         ** corruption during the next transaction.
  2311   2340         */
  2312   2341       }else{
  2313         -      TRACE2("DONT_WRITE %d\n", pgno);
         2342  +      TRACE3("DONT_WRITE page %d of %d\n", pgno, pPager->fd.h);
  2314   2343         pPg->dirty = 0;
  2315   2344       }
  2316   2345     }
  2317   2346   }
  2318   2347   
  2319   2348   /*
  2320   2349   ** A call to this routine tells the pager that if a rollback occurs,
................................................................................
  2322   2351   ** means that the pager does not have to record the given page in the
  2323   2352   ** rollback journal.
  2324   2353   */
  2325   2354   void sqlite3pager_dont_rollback(void *pData){
  2326   2355     PgHdr *pPg = DATA_TO_PGHDR(pData);
  2327   2356     Pager *pPager = pPg->pPager;
  2328   2357   
  2329         -  if( pPager->state!=SQLITE_WRITELOCK || pPager->journalOpen==0 ) return;
         2358  +  if( pPager->state!=PAGER_EXCLUSIVE || pPager->journalOpen==0 ) return;
  2330   2359     if( pPg->alwaysRollback || pPager->alwaysRollback || pPager->memDb ) return;
  2331   2360     if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){
  2332   2361       assert( pPager->aInJournal!=0 );
  2333   2362       pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7);
  2334   2363       pPg->inJournal = 1;
  2335   2364       if( pPager->stmtInUse ){
  2336   2365         pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
  2337   2366         page_add_to_stmt_list(pPg);
  2338   2367       }
  2339         -    TRACE2("DONT_ROLLBACK %d\n", pPg->pgno);
         2368  +    TRACE3("DONT_ROLLBACK page %d of %d\n", pPg->pgno, pPager->fd.h);
  2340   2369     }
  2341   2370     if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){
  2342   2371       assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize );
  2343   2372       assert( pPager->aInStmt!=0 );
  2344   2373       pPager->aInStmt[pPg->pgno/8] |= 1<<(pPg->pgno&7);
  2345   2374       page_add_to_stmt_list(pPg);
  2346   2375     }
................................................................................
  2375   2404       }
  2376   2405       return rc;
  2377   2406     }
  2378   2407     if( pPager->errMask!=0 ){
  2379   2408       rc = pager_errcode(pPager);
  2380   2409       return rc;
  2381   2410     }
  2382         -  if( pPager->state!=SQLITE_WRITELOCK ){
         2411  +  if( pPager->state<PAGER_RESERVED ){
  2383   2412       return SQLITE_ERROR;
  2384   2413     }
  2385         -  TRACE1("COMMIT\n");
         2414  +  TRACE2("COMMIT %d\n", pPager->fd.h);
  2386   2415     if( pPager->memDb ){
  2387   2416       pPg = pager_get_all_dirty_pages(pPager);
  2388   2417       while( pPg ){
  2389   2418         clearHistory(PGHDR_TO_HIST(pPg, pPager));
  2390   2419         pPg->dirty = 0;
  2391   2420         pPg->inJournal = 0;
  2392   2421         pPg->inStmt = 0;
  2393   2422         pPg->pPrevStmt = pPg->pNextStmt = 0;
  2394   2423         pPg = pPg->pDirty;
  2395   2424       }
  2396   2425       pPager->pStmt = 0;
  2397         -    pPager->state = SQLITE_READLOCK;
         2426  +    pPager->state = PAGER_SHARED;
  2398   2427       return SQLITE_OK;
  2399   2428     }
  2400         -#if 0
  2401         -  if( pPager->dirtyFile==0 ){
         2429  +  if( pPager->dirtyCache==0 ){
  2402   2430       /* Exit early (without doing the time-consuming sqlite3OsSync() calls)
  2403   2431       ** if there have been no changes to the database file. */
  2404   2432       assert( pPager->needSync==0 );
  2405   2433       rc = pager_unwritelock(pPager);
  2406   2434       pPager->dbSize = -1;
  2407   2435       return rc;
  2408   2436     }
  2409   2437     assert( pPager->journalOpen );
         2438  +#if 0
  2410   2439     rc = syncJournal(pPager, 0);
  2411   2440     if( rc!=SQLITE_OK ){
  2412   2441       goto commit_abort;
  2413   2442     }
  2414   2443     pPg = pager_get_all_dirty_pages(pPager);
  2415   2444     if( pPg ){
  2416   2445       rc = pager_write_pagelist(pPg);
  2417   2446       if( rc || (!pPager->noSync && sqlite3OsSync(&pPager->fd)!=SQLITE_OK) ){
  2418   2447         goto commit_abort;
  2419   2448       }
  2420   2449     }
  2421   2450   #endif
  2422   2451     rc = sqlite3pager_sync(pPager, 0);
  2423         -  if( rc!=SQLITE_OK ) goto commit_abort;
  2424         -
         2452  +  if( rc!=SQLITE_OK ){
         2453  +    goto commit_abort;
         2454  +  }
  2425   2455     rc = pager_unwritelock(pPager);
  2426   2456     pPager->dbSize = -1;
  2427   2457     return rc;
  2428   2458   
  2429   2459     /* Jump here if anything goes wrong during the commit process.
  2430   2460     */
  2431   2461   commit_abort:
................................................................................
  2433   2463     if( rc==SQLITE_OK ){
  2434   2464       rc = SQLITE_FULL;
  2435   2465     }
  2436   2466     return rc;
  2437   2467   }
  2438   2468   
  2439   2469   /*
  2440         -** Rollback all changes.  The database falls back to read-only mode.
         2470  +** Rollback all changes.  The database falls back to PAGER_SHARED mode.
  2441   2471   ** All in-memory cache pages revert to their original data contents.
  2442   2472   ** The journal is deleted.
  2443   2473   **
  2444   2474   ** This routine cannot fail unless some other process is not following
  2445   2475   ** the correct locking protocol (SQLITE_PROTOCOL) or unless some other
  2446   2476   ** process is writing trash into the journal file (SQLITE_CORRUPT) or
  2447   2477   ** unless a prior malloc() failed (SQLITE_NOMEM).  Appropriate error
  2448   2478   ** codes are returned for all these occasions.  Otherwise,
  2449   2479   ** SQLITE_OK is returned.
  2450   2480   */
  2451   2481   int sqlite3pager_rollback(Pager *pPager){
  2452   2482     int rc;
  2453         -  TRACE1("ROLLBACK\n");
         2483  +  TRACE2("ROLLBACK %d\n", pPager->fd.h);
  2454   2484     if( pPager->memDb ){
  2455   2485       PgHdr *p;
  2456   2486       for(p=pPager->pAll; p; p=p->pNextAll){
  2457   2487         PgHistory *pHist;
  2458   2488         if( !p->dirty ) continue;
  2459   2489         pHist = PGHDR_TO_HIST(p, pPager);
  2460   2490         if( pHist->pOrig ){
................................................................................
  2469   2499         p->inStmt = 0;
  2470   2500         p->pPrevStmt = p->pNextStmt = 0;
  2471   2501       }
  2472   2502       pPager->pStmt = 0;
  2473   2503       pPager->dbSize = pPager->origDbSize;
  2474   2504       memoryTruncate(pPager);
  2475   2505       pPager->stmtInUse = 0;
  2476         -    pPager->state = SQLITE_READLOCK;
         2506  +    pPager->state = PAGER_SHARED;
  2477   2507       return SQLITE_OK;
  2478   2508     }
  2479   2509   
  2480         -  if( !pPager->dirtyFile || !pPager->journalOpen ){
         2510  +  if( !pPager->dirtyCache || !pPager->journalOpen ){
  2481   2511       rc = pager_unwritelock(pPager);
  2482   2512       pPager->dbSize = -1;
  2483   2513       return rc;
  2484   2514     }
  2485   2515   
  2486   2516     if( pPager->errMask!=0 && pPager->errMask!=PAGER_ERR_FULL ){
  2487         -    if( pPager->state>=SQLITE_WRITELOCK ){
         2517  +    if( pPager->state>=PAGER_EXCLUSIVE ){
  2488   2518         pager_playback(pPager, 1);
  2489   2519       }
  2490   2520       return pager_errcode(pPager);
  2491   2521     }
  2492         -  if( pPager->state!=SQLITE_WRITELOCK ){
  2493         -    return SQLITE_OK;
         2522  +  if( pPager->state==PAGER_RESERVED ){
         2523  +    int rc2;
         2524  +    rc = pager_reload_cache(pPager);
         2525  +    rc2 = pager_unwritelock(pPager);
         2526  +    if( rc==SQLITE_OK ){
         2527  +      rc = rc2;
         2528  +    }
         2529  +  }else{
         2530  +    rc = pager_playback(pPager, 1);
  2494   2531     }
  2495         -  rc = pager_playback(pPager, 1);
  2496   2532     if( rc!=SQLITE_OK ){
  2497   2533       rc = SQLITE_CORRUPT;
  2498   2534       pPager->errMask |= PAGER_ERR_CORRUPT;
  2499   2535     }
  2500   2536     pPager->dbSize = -1;
  2501   2537     return rc;
  2502   2538   }
................................................................................
  2533   2569   ** open.  A new statement journal is created that can be used to rollback
  2534   2570   ** changes of a single SQL command within a larger transaction.
  2535   2571   */
  2536   2572   int sqlite3pager_stmt_begin(Pager *pPager){
  2537   2573     int rc;
  2538   2574     char zTemp[SQLITE_TEMPNAME_SIZE];
  2539   2575     assert( !pPager->stmtInUse );
  2540         -  TRACE1("STMT-BEGIN\n");
         2576  +  TRACE2("STMT-BEGIN %d\n", pPager->fd.h);
  2541   2577     if( pPager->memDb ){
  2542   2578       pPager->stmtInUse = 1;
  2543   2579       pPager->stmtSize = pPager->dbSize;
  2544   2580       return SQLITE_OK;
  2545   2581     }
  2546   2582     if( !pPager->journalOpen ){
  2547   2583       pPager->stmtAutoopen = 1;
................................................................................
  2582   2618   
  2583   2619   /*
  2584   2620   ** Commit a statement.
  2585   2621   */
  2586   2622   int sqlite3pager_stmt_commit(Pager *pPager){
  2587   2623     if( pPager->stmtInUse ){
  2588   2624       PgHdr *pPg, *pNext;
  2589         -    TRACE1("STMT-COMMIT\n");
         2625  +    TRACE2("STMT-COMMIT %d\n", pPager->fd.h);
  2590   2626       if( !pPager->memDb ){
  2591   2627         sqlite3OsSeek(&pPager->stfd, 0);
  2592   2628         /* sqlite3OsTruncate(&pPager->stfd, 0); */
  2593   2629         sqliteFree( pPager->aInStmt );
  2594   2630         pPager->aInStmt = 0;
  2595   2631       }
  2596   2632       for(pPg=pPager->pStmt; pPg; pPg=pNext){
................................................................................
  2614   2650   
  2615   2651   /*
  2616   2652   ** Rollback a statement.
  2617   2653   */
  2618   2654   int sqlite3pager_stmt_rollback(Pager *pPager){
  2619   2655     int rc;
  2620   2656     if( pPager->stmtInUse ){
  2621         -    TRACE1("STMT-ROLLBACK\n");
         2657  +    TRACE2("STMT-ROLLBACK %d\n", pPager->fd.h);
  2622   2658       if( pPager->memDb ){
  2623   2659         PgHdr *pPg;
  2624   2660         for(pPg=pPager->pStmt; pPg; pPg=pPg->pNextStmt){
  2625   2661           PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager);
  2626   2662           if( pHist->pStmt ){
  2627   2663             memcpy(PGHDR_TO_DATA(pPg), pHist->pStmt, pPager->pageSize);
  2628   2664             sqliteFree(pHist->pStmt);
................................................................................
  2678   2714   */
  2679   2715   int sqlite3pager_sync(Pager *pPager, const char *zMaster){
  2680   2716     int rc = SQLITE_OK;
  2681   2717   
  2682   2718     /* If this is an in-memory db, or no pages have been written to, this
  2683   2719     ** function is a no-op.
  2684   2720     */
  2685         -  if( !pPager->memDb && pPager->dirtyFile ){
         2721  +  if( !pPager->memDb && pPager->dirtyCache ){
  2686   2722       PgHdr *pPg;
  2687   2723       assert( pPager->journalOpen );
  2688   2724   
  2689   2725       /* Sync the journal file */
  2690   2726       rc = syncJournal(pPager, zMaster);
  2691   2727       if( rc!=SQLITE_OK ) goto sync_exit;
  2692   2728   

Changes to src/pager.h.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This header file defines the interface that the sqlite page cache
    13     13   ** subsystem.  The page cache subsystem reads and writes a file a page
    14     14   ** at a time and provides a journal for rollback.
    15     15   **
    16         -** @(#) $Id: pager.h,v 1.32 2004/06/09 14:17:21 drh Exp $
           16  +** @(#) $Id: pager.h,v 1.33 2004/06/09 17:37:28 drh Exp $
    17     17   */
    18     18   
    19     19   /*
    20     20   ** The size of a page.
    21     21   **
    22     22   ** You can change this value to another (reasonable) value you want.
    23     23   ** It need not be a power of two, though the interface to the disk
................................................................................
    69     69   ** See source code comments for a detailed description of the following
    70     70   ** routines:
    71     71   */
    72     72   int sqlite3pager_open(Pager **ppPager, const char *zFilename,
    73     73                        int nPage, int nExtra, int useJournal,
    74     74                        void *pBusyHandler);
    75     75   void sqlite3pager_set_destructor(Pager*, void(*)(void*,int));
           76  +void sqlite3pager_set_reiniter(Pager*, void(*)(void*,int));
    76     77   void sqlite3pager_set_cachesize(Pager*, int);
    77     78   int sqlite3pager_close(Pager *pPager);
    78     79   int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage);
    79     80   void *sqlite3pager_lookup(Pager *pPager, Pgno pgno);
    80     81   int sqlite3pager_ref(void*);
    81     82   int sqlite3pager_unref(void*);
    82     83   Pgno sqlite3pager_pagenumber(void*);

Changes to src/test1.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Code for testing the printf() interface to SQLite.  This code
    13     13   ** is not included in the SQLite library.  It is used for automated
    14     14   ** testing of the SQLite library.
    15     15   **
    16         -** $Id: test1.c,v 1.73 2004/06/09 14:01:51 drh Exp $
           16  +** $Id: test1.c,v 1.74 2004/06/09 17:37:28 drh Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "tcl.h"
    20     20   #include "os.h"
    21     21   #include <stdlib.h>
    22     22   #include <string.h>
    23     23   
................................................................................
  1778   1778          Tcl_GetString(objv[0]), " filehandle", 0);
  1779   1779       return TCL_ERROR;
  1780   1780     }
  1781   1781   
  1782   1782     if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
  1783   1783       return TCL_ERROR;
  1784   1784     }
  1785         -  rc = sqlite3OsUnlock(pFile);
         1785  +  rc = sqlite3OsUnlock(pFile, NO_LOCK);
  1786   1786     if( rc!=SQLITE_OK ){
  1787   1787       Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
  1788   1788       return TCL_ERROR;
  1789   1789     }
  1790   1790     return TCL_OK;
  1791   1791   }
  1792   1792   

Changes to src/vdbeaux.c.

   930    930       }
   931    931     }
   932    932   
   933    933     /* The simple case - no more than one database file (not counting the TEMP
   934    934     ** database) has a transaction active.   There is no need for the
   935    935     ** master-journal.
   936    936     */
   937         -  if( nTrans<=1 ){
          937  +  if( nTrans<=100 ){  /**** FIX ME ****/
   938    938       for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ 
   939    939         Btree *pBt = db->aDb[i].pBt;
   940    940         if( pBt ){
   941    941           rc = sqlite3BtreeSync(pBt, 0);
   942    942         }
   943    943       }
   944    944   
................................................................................
   960    960     else{
   961    961       char *zMaster = 0;   /* File-name for the master journal */
   962    962       char const *zMainFile = sqlite3BtreeGetFilename(db->aDb[0].pBt);
   963    963       OsFile master;
   964    964   
   965    965       /* Select a master journal file name */
   966    966       do {
   967         -      int random;
   968         -      if( zMaster ){
   969         -        sqliteFree(zMaster);
   970         -      }    
          967  +      u32 random;
          968  +      sqliteFree(zMaster);
   971    969         sqlite3Randomness(sizeof(random), &random);
   972         -      zMaster = sqlite3_mprintf("%s%d", zMainFile, random);
          970  +      zMaster = sqlite3MPrintf("%s-mj%08X", zMainFile, random);
   973    971         if( !zMaster ){
   974    972           return SQLITE_NOMEM;
   975    973         }
   976    974       }while( sqlite3OsFileExists(zMaster) );
   977    975   
   978    976       /* Open the master journal. */
   979    977       rc = sqlite3OsOpenExclusive(zMaster, &master, 0);

Changes to test/attach2.test.

     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this script is testing the ATTACH and DETACH commands
    13     13   # and related functionality.
    14     14   #
    15         -# $Id: attach2.test,v 1.13 2004/06/09 14:01:58 drh Exp $
           15  +# $Id: attach2.test,v 1.14 2004/06/09 17:37:29 drh Exp $
    16     16   #
    17         -set sqlite_os_trace 0
    18     17   
    19     18   set testdir [file dirname $argv0]
    20     19   source $testdir/tester.tcl
    21     20   
    22     21   
    23     22   # Ticket #354
    24     23   #
................................................................................
   143    142     set rc
   144    143   } {0}
   145    144   
   146    145   db close
   147    146   for {set i 2} {$i<=15} {incr i} {
   148    147     catch {db$i close}
   149    148   }
          149  +
          150  +# A procedure to verify the status of locks on a database.
          151  +#
          152  +proc lock_status {testnum db expected_result} {
          153  +  do_test attach2-$testnum [subst {
          154  +    execsql {PRAGMA lock_status} $db
          155  +  }] $expected_result
          156  +}
   150    157   set sqlite_os_trace 0
   151    158   
   152    159   # Tests attach2-4.* test that read-locks work correctly with attached
   153    160   # databases.
   154    161   do_test attach2-4.1 {
   155    162     sqlite db test.db
   156    163     sqlite db2 test.db
   157    164     execsql {ATTACH 'test2.db' as file2}
   158    165     execsql {ATTACH 'test2.db' as file2} db2
   159    166   } {}
   160    167   
          168  +lock_status 4.1.1 db {main unlocked temp unlocked file2 unlocked}
          169  +lock_status 4.1.2 db2 {main unlocked temp unlocked file2 unlocked}
          170  +
   161    171   do_test attach2-4.2 {
   162    172     # Handle 'db' read-locks test.db
   163    173     execsql {BEGIN}
   164    174     execsql {SELECT * FROM t1}
   165    175     # Lock status:
   166    176     #    db  - shared(main)
   167    177     #    db2 -
   168    178   } {}
          179  +
          180  +lock_status 4.2.1 db {main shared temp shared file2 unlocked}
          181  +lock_status 4.2.2 db2 {main unlocked temp unlocked file2 unlocked}
          182  +
   169    183   do_test attach2-4.3 {
   170    184     # The read lock held by db does not prevent db2 from reading test.db
   171    185     execsql {SELECT * FROM t1} db2
   172    186   } {}
          187  +
          188  +lock_status 4.3.1 db {main shared temp shared file2 unlocked}
          189  +lock_status 4.3.2 db2 {main unlocked temp unlocked file2 unlocked}
          190  +
   173    191   do_test attach2-4.4 {
   174    192     # db is holding a read lock on test.db, so we should not be able
   175    193     # to commit a write to test.db from db2
   176    194     catchsql {
   177    195       INSERT INTO t1 VALUES(1, 2)
   178    196     } db2 
   179    197   } {1 {database is locked}}
          198  +
          199  +lock_status 4.4.1 db {main shared temp shared file2 unlocked}
          200  +lock_status 4.4.2 db2 {main unlocked temp unlocked file2 unlocked}
          201  +
   180    202   do_test attach2-4.5 {
   181    203     # Handle 'db2' reserves file2.
   182    204     execsql {BEGIN} db2
   183    205     execsql {INSERT INTO file2.t1 VALUES(1, 2)} db2
   184    206     # Lock status:
   185    207     #    db  - shared(main)
   186    208     #    db2 - reserved(file2)
   187    209   } {}
          210  +
          211  +lock_status 4.5.1 db {main shared temp shared file2 unlocked}
          212  +lock_status 4.5.2 db2 {main unlocked temp reserved file2 reserved}
          213  +
   188    214   do_test attach2-4.6.1 {
   189    215     # Reads are allowed against a reserved database.
   190    216     catchsql {
   191    217       SELECT * FROM file2.t1;
   192    218     }
   193    219     # Lock status:
   194    220     #    db  - shared(main), shared(file2)
   195    221     #    db2 - reserved(file2)
   196    222   } {0 {}}
          223  +
          224  +lock_status 4.6.1.1 db {main shared temp shared file2 shared}
          225  +lock_status 4.6.1.2 db2 {main unlocked temp reserved file2 reserved}
          226  +
   197    227   do_test attach2-4.6.2 {
   198    228     # Writes against a reserved database are not allowed.
   199    229     catchsql {
   200    230       UPDATE file2.t1 SET a=0;
   201    231     }
   202    232   } {1 {database is locked}}
          233  +
          234  +lock_status 4.6.2.1 db {main shared temp reserved file2 shared}
          235  +lock_status 4.6.2.2 db2 {main unlocked temp reserved file2 reserved}
          236  +
   203    237   do_test attach2-4.7 {
   204    238     # Ensure handle 'db' retains the lock on the main file after
   205    239     # failing to obtain a write-lock on file2.
   206    240     catchsql {
   207    241       INSERT INTO t1 VALUES(1, 2)
   208    242     } db2 
   209         -} {1 {database is locked}}
          243  +} {0 {}}
          244  +
          245  +lock_status 4.7.1 db {main shared temp reserved file2 shared}
          246  +lock_status 4.7.2 db2 {main reserved temp reserved file2 reserved}
          247  +
   210    248   do_test attach2-4.8 {
   211         -  # Read lock the main file with db2. Now both db and db2 have a read lock
   212         -  # on the main file, db2 has a write-lock on file2.
          249  +  # We should still be able to read test.db from db2
   213    250     execsql {SELECT * FROM t1} db2
   214         -  # Lock status:
   215         -  #    db  - shared(main), shared(file2)
   216         -  #    db2 - shared(main), reserved(file2)
   217         -} {}
          251  +} {1 2}
          252  +
          253  +lock_status 4.8.1 db {main shared temp reserved file2 shared}
          254  +lock_status 4.8.2 db2 {main reserved temp reserved file2 reserved}
          255  +
   218    256   do_test attach2-4.9 {
   219    257     # Try to upgrade the handle 'db' lock.
   220    258     catchsql {
   221    259       INSERT INTO t1 VALUES(1, 2)
   222    260     }
   223         -  list $r $msg
   224    261   } {1 {database is locked}}
          262  +
          263  +lock_status 4.9.1 db {main shared temp reserved file2 shared}
          264  +lock_status 4.9.2 db2 {main reserved temp reserved file2 reserved}
          265  +
   225    266   do_test attach2-4.10 {
   226    267     # Release the locks held by handle 'db2'
   227    268     execsql {COMMIT} db2
   228    269   } {}
          270  +
          271  +lock_status 4.10.1 db {main shared temp reserved file2 shared}
          272  +lock_status 4.10.2 db2 {main unlocked temp unlocked file2 unlocked}
          273  +
   229    274   do_test attach2-4.11 {
   230    275     execsql {SELECT * FROM file2.t1}
   231    276   } {1 2}
   232    277   do_test attach2-4.12 {
   233    278     execsql {INSERT INTO t1 VALUES(1, 2)}
   234    279   } {}
   235    280   do_test attach2-4.13 {