/ Check-in [a49713db]
Login

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

Overview
Comment:Add further test cases for the logic in sqlite3WalBeginReadTransaction().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: a49713db39d0d6940b368206d4e669aa69aa1fe5
User & Date: dan 2010-06-05 19:18:59
Context
2010-06-07
06:11
Add a couple of extra coverage tests for wal.c. check-in: cfe60254 user: dan tags: trunk
2010-06-05
19:18
Add further test cases for the logic in sqlite3WalBeginReadTransaction(). check-in: a49713db user: dan tags: trunk
18:34
Clarify the purpose of a test for a race-condition in sqlite3WalBeginReadTransaction(). check-in: c041c6a9 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/wal.c.

  1743   1743     if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame ){
  1744   1744       /* The WAL has been completely backfilled (or it is empty).
  1745   1745       ** and can be safely ignored.
  1746   1746       */
  1747   1747       rc = walLockShared(pWal, WAL_READ_LOCK(0));
  1748   1748       sqlite3OsShmBarrier(pWal->pDbFd);
  1749   1749       if( rc==SQLITE_OK ){
  1750         -      if( memcmp(pHdr, &pWal->hdr, sizeof(WalIndexHdr)) ){
         1750  +      if( memcmp((void *)pHdr, &pWal->hdr, sizeof(WalIndexHdr)) ){
  1751   1751           /* It is not safe to allow the reader to continue here if frames
  1752   1752           ** may have been appended to the log before READ_LOCK(0) was obtained.
  1753   1753           ** When holding READ_LOCK(0), the reader ignores the entire log file,
  1754   1754           ** which implies that the database file contains a trustworthy
  1755   1755           ** snapshoT. Since holding READ_LOCK(0) prevents a checkpoint from
  1756   1756           ** happening, this is usually correct.
  1757   1757           **
................................................................................
  1828   1828       ** that the log file may have been wrapped by a writer, or that frames
  1829   1829       ** that occur later in the log than pWal->hdr.mxFrame may have been
  1830   1830       ** copied into the database by a checkpointer. If either of these things
  1831   1831       ** happened, then reading the database with the current value of
  1832   1832       ** pWal->hdr.mxFrame risks reading a corrupted snapshot. So, retry
  1833   1833       ** instead.
  1834   1834       **
  1835         -    ** This does not guarantee that the copy wal-index header is up to
  1836         -    ** date before proceeding. This would not be possible without somehow
  1837         -    ** blocking writers. It only guarantees that a damaging checkpoint or 
         1835  +    ** This does not guarantee that the copy of the wal-index header is up to
         1836  +    ** date before proceeding. That would not be possible without somehow
         1837  +    ** blocking writers. It only guarantees that a dangerous checkpoint or 
  1838   1838       ** log-wrap (either of which would require an exclusive lock on
  1839   1839       ** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid.
  1840   1840       */
  1841   1841       sqlite3OsShmBarrier(pWal->pDbFd);
  1842   1842       if( pInfo->aReadMark[mxI]!=mxReadMark
  1843         -     || memcmp(pHdr, &pWal->hdr, sizeof(WalIndexHdr))
         1843  +     || memcmp((void *)pHdr, &pWal->hdr, sizeof(WalIndexHdr))
  1844   1844       ){
  1845   1845         walUnlockShared(pWal, WAL_READ_LOCK(mxI));
  1846   1846         return WAL_RETRY;
  1847   1847       }else{
  1848   1848         pWal->readLock = mxI;
  1849   1849       }
  1850   1850     }

Changes to test/wal3.test.

   416    416   
   417    417   db close
   418    418   T delete
   419    419   
   420    420   #-------------------------------------------------------------------------
   421    421   # When opening a read-transaction on a database, if the entire log has
   422    422   # already been copied to the database file, the reader grabs a special
   423         -# kind of read lock (on aReadMark[0]). This test case tests the outcome
   424         -# of the following:
          423  +# kind of read lock (on aReadMark[0]). This set of test cases tests the 
          424  +# outcome of the following:
   425    425   #
   426    426   #   + The reader discovering that between the time when it determined 
   427    427   #     that the log had been completely backfilled and the lock is obtained
   428    428   #     that a writer has written to the log. In this case the reader should
   429    429   #     acquire a different read-lock (not aReadMark[0]) and read the new
   430    430   #     snapshot.
   431    431   #
................................................................................
   559    559     expr {$sz2 == $sz1}
   560    560   } {1}
   561    561    
   562    562   db2 close
   563    563   db close
   564    564   T delete
   565    565   
          566  +#-------------------------------------------------------------------------
          567  +# When opening a read-transaction on a database, if the entire log has
          568  +# not yet been copied to the database file, the reader grabs a read
          569  +# lock on aReadMark[x], where x>0. The following test cases experiment
          570  +# with the outcome of the following:
          571  +#
          572  +#   + The reader discovering that between the time when it read the
          573  +#     wal-index header and the lock was obtained that a writer has 
          574  +#     written to the log. In this case the reader should re-read the 
          575  +#     wal-index header and lock a snapshot corresponding to the new 
          576  +#     header.
          577  +#
          578  +#   + The value in the aReadMark[x] slot has been modified since it was
          579  +#     read.
          580  +#
          581  +catch {db close}
          582  +testvfs T -default 1
          583  +do_test wal3-7.1.1 {
          584  +  file delete -force test.db test.db-journal test.db wal
          585  +  sqlite3 db test.db
          586  +  execsql {
          587  +    PRAGMA journal_mode = WAL;
          588  +    CREATE TABLE blue(red PRIMARY KEY, green);
          589  +  }
          590  +} {wal}
          591  +
          592  +T script method_callback
          593  +T filter xOpen
          594  +proc method_callback {method args} {
          595  +  if {$method == "xOpen"} { return "reader" }
          596  +}
          597  +do_test wal3-7.1.2 {
          598  +  sqlite3 db2 test.db
          599  +  execsql { SELECT * FROM blue } db2
          600  +} {}
          601  +
          602  +T filter xShmLock
          603  +set ::locks [list]
          604  +proc method_callback {method file handle spec} {
          605  +  if {$handle != "reader" } { return }
          606  +  if {$method == "xShmLock"} {
          607  +    catch { execsql { INSERT INTO blue VALUES(1, 2) } }
          608  +    catch { execsql { INSERT INTO blue VALUES(3, 4) } }
          609  +  }
          610  +  lappend ::locks $spec
          611  +}
          612  +do_test wal3-7.1.3 {
          613  +  execsql { SELECT * FROM blue } db2
          614  +} {1 2 3 4}
          615  +do_test wal3-7.1.4 {
          616  +  set ::locks
          617  +} {{4 1 lock shared} {4 1 unlock shared} {5 1 lock shared} {5 1 unlock shared}}
          618  +
          619  +set ::locks [list]
          620  +proc method_callback {method file handle spec} {
          621  +  if {$handle != "reader" } { return }
          622  +  if {$method == "xShmLock"} {
          623  +    catch { execsql { INSERT INTO blue VALUES(5, 6) } }
          624  +  }
          625  +  lappend ::locks $spec
          626  +}
          627  +do_test wal3-7.2.1 {
          628  +  execsql { SELECT * FROM blue } db2
          629  +} {1 2 3 4 5 6}
          630  +do_test wal3-7.2.2 {
          631  +  set ::locks
          632  +} {{5 1 lock shared} {5 1 unlock shared} {4 1 lock shared} {4 1 unlock shared}}
          633  +
          634  +db close
          635  +db2 close
          636  +T delete
   566    637   
   567    638   finish_test
   568    639