]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Remove the requirement to open the wal file before sqlite3_snapshot_recover()
authordan <dan@noemail.net>
Sat, 19 Nov 2016 18:31:37 +0000 (18:31 +0000)
committerdan <dan@noemail.net>
Sat, 19 Nov 2016 18:31:37 +0000 (18:31 +0000)
is called. Also add some comments to new functions.

FossilOrigin-Name: 28393c413cc4505b94411730e728583c5d4baaae

manifest
manifest.uuid
src/main.c
src/sqlite.h.in
src/wal.c
test/snapshot2.test

index c697bbdef61b22972377d5483125fd6969387e78..21ea07385c4e604cef72a08402f9b9831671b8de 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Test\ssome\sextra\serror\sconditions\sin\ssqlite3_recover_snapshot().
-D 2016-11-19T17:30:57.131
+C Remove\sthe\srequirement\sto\sopen\sthe\swal\sfile\sbefore\ssqlite3_snapshot_recover()\nis\scalled.\sAlso\sadd\ssome\scomments\sto\snew\sfunctions.
+D 2016-11-19T18:31:37.017
 F Makefile.in 6b572807415d3f0a379cebc9461416d8df4a12c8
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc bb4d970894abbbe0e88d00aac29bd52af8bc95f4
@@ -352,7 +352,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c 0d6e59f9eea62db772eabc0f07901ec26fe01968
 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e
 F src/loadext.c 5d6642d141c07d366e43d359e94ec9de47add41d
-F src/main.c de55e68145758d5512e9397728c9a8f4ff0ffa78
+F src/main.c 5669ae83c6bd47f090aee26a6b548a882d69e9e1
 F src/malloc.c 5ee7c2d3dcb1b0a902c9c6d0115deef54736bdfa
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
@@ -389,7 +389,7 @@ F src/resolve.c bb070cf5f23611c44ab7e4788803684e385fc3fb
 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
 F src/select.c 672b1af237ad257149fc5189f3277dcbca036eeb
 F src/shell.c f04e4af75c5517735397d060ed0b4a874104bb41
-F src/sqlite.h.in d9b7b5942a18bb83b560c7699aff3925b4f9af90
+F src/sqlite.h.in 631cc94108c1c03190d5f1edb70e7797c522a37a
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
 F src/sqliteInt.h c471d791b10c0f2164c8b7a87adc338e703c09cc
@@ -465,7 +465,7 @@ F src/vdbesort.c 91fda3909326860382b0ca8aa251e609c6a9d62c
 F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
 F src/vtab.c e02cacb5c7ae742631edeb9ae9f53d399f093fd8
 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
-F src/wal.c 006eec60874fc502afc9e95639bbd446125cfab5
+F src/wal.c 56bba6f4101b55054145ce164951bea4a1b09548
 F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
 F src/walker.c 91a6df7435827e41cff6bb7df50ea00934ee78b0
 F src/where.c 952f76e7a03727480b274b66ca6641b1657cd591
@@ -1103,7 +1103,7 @@ F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
 F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
 F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b
 F test/snapshot.test 85735bd997a4f6d710140c28fd860519a299649f
-F test/snapshot2.test 706498fdd1f03163473965faedd56b137ff7ec50
+F test/snapshot2.test eb083df2e617708a4a93d70965f14268d4934120
 F test/snapshot_fault.test 52c5e97ebd218846a8ae2da4d147d3e77d71f963
 F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
 F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
@@ -1535,7 +1535,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 7e040406138669bd67dd6ecae016b3e50dbfaaf8
-R 8677d727bb420bd9cae1a19aef039ec1
+P db314213c08f27dd0ff5ede3c6a8eda36560809a
+R 0c1e63a3653bf6d9b725483fda2de4a1
 U dan
-Z 6dc3dd1ccc30316098a970a98f898ad5
+Z 573fa32a4bef0fb7a3cf7415ded5b3fe
index a26ea4d37dfe0d0771ddf65a45950f4e26bb2a2f..d4754cb8fa18c712eef91bf89275c1fde8799c00 100644 (file)
@@ -1 +1 @@
-db314213c08f27dd0ff5ede3c6a8eda36560809a
\ No newline at end of file
+28393c413cc4505b94411730e728583c5d4baaae
\ No newline at end of file
index c0494135ca2ce7decc01bb8b7a06755ee6f6bb31..5980dbcc37fca9d27201e6e35a61d933f32bc313 100644 (file)
@@ -4064,7 +4064,11 @@ int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb){
   if( iDb==0 || iDb>1 ){
     Btree *pBt = db->aDb[iDb].pBt;
     if( 0==sqlite3BtreeIsInReadTrans(pBt) ){
-      rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt));
+      rc = sqlite3BtreeBeginTrans(pBt, 0);
+      if( rc==SQLITE_OK ){
+        rc = sqlite3PagerSnapshotRecover(sqlite3BtreePager(pBt));
+        sqlite3BtreeCommit(pBt);
+      }
     }
   }
   sqlite3_mutex_leave(db->mutex);
index 9c921b8c993052a699bb479039ca93a456fd6fe2..563b21f24e9bf8821c8ac073f2664c2b70e02202 100644 (file)
@@ -8417,6 +8417,22 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_cmp(
 /*
 ** CAPI3REF: Recover snapshots from a wal file
 ** EXPERIMENTAL
+**
+** If all connections disconnect from a database file but do not perform
+** a checkpoint, the existing wal file is opened along with the database
+** file the next time the database is opened. At this point it is only
+** possible to successfully call sqlite3_snapshot_open() to open the most
+** recent snapshot of the database (the one at the head of the wal file),
+** even though the wal file may contain other valid snapshots for which
+** clients have sqlite3_snapshot handles.
+**
+** This function attempts to scan the wal file associated with database zDb
+** of database handle db and make all valid snapshots available to
+** sqlite3_snapshot_open(). It is an error if there is already a read
+** transaction open on the database, or if the database is not a wal mode
+** database.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code otherwise.
 */
 SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
 
index 4819d65c27da68fe8e64a5992f72d36dcf112e18..52e44ad550419b7a7fba97af190db015d79b3ef8 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -2380,70 +2380,76 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
 }
 
 /*
-** Recover as many snapshots as possible from the wal file.
+** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted 
+** variable so that older snapshots can be accessed. To do this, loop
+** through all wal frames from nBackfillAttempted to (nBackfill+1), 
+** comparing their content to the corresponding page with the database
+** file, if any. Set nBackfillAttempted to the frame number of the
+** first frame for which the wal file content matches the db file.
+**
+** This is only really safe if the file-system is such that any page 
+** writes made by earlier checkpointers were atomic operations, which 
+** is not always true. It is also possible that nBackfillAttempted
+** may be left set to a value larger than expected, if a wal frame
+** contains content that duplicate of an earlier version of the same
+** page.
+**
+** SQLITE_OK is returned if successful, or an SQLite error code if an
+** error occurs. It is not an error if nBackfillAttempted cannot be
+** decreased at all.
 */
 int sqlite3WalSnapshotRecover(Wal *pWal){
-  int dummy;
   int rc;
 
-  rc = sqlite3WalBeginReadTransaction(pWal, &dummy);
+  assert( pWal->readLock>=0 );
+  rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
   if( rc==SQLITE_OK ){
-    rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
-    if( rc==SQLITE_OK ){
-      volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
-      int szPage = (int)pWal->szPage;
-      i64 szDb;                   /* Size of db file in bytes */
+    volatile WalCkptInfo *pInfo = walCkptInfo(pWal);
+    int szPage = (int)pWal->szPage;
+    i64 szDb;                   /* Size of db file in bytes */
 
-      rc = sqlite3OsFileSize(pWal->pDbFd, &szDb);
-      if( rc==SQLITE_OK ){
-        void *pBuf1 = sqlite3_malloc(szPage);
-        void *pBuf2 = sqlite3_malloc(szPage);
-        if( pBuf1==0 || pBuf2==0 ){
-          rc = SQLITE_NOMEM;
-        }else{
-          u32 i = pInfo->nBackfillAttempted;
-          for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){
-            volatile ht_slot *dummy;
-            volatile u32 *aPgno;      /* Array of page numbers */
-            u32 iZero;                /* Frame corresponding to aPgno[0] */
-            u32 pgno;                 /* Page number in db file */
-            i64 iDbOff;               /* Offset of db file entry */
-            i64 iWalOff;              /* Offset of wal file entry */
-
-            rc = walHashGet(pWal, walFramePage(i), &dummy, &aPgno, &iZero);
-            if( rc!=SQLITE_OK ) break;
-            pgno = aPgno[i-iZero];
-            iDbOff = (i64)(pgno-1) * szPage;
-
-            if( iDbOff+szPage<=szDb ){
-              iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE;
-              rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff);
-
-              if( rc==SQLITE_OK ){
-                rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff);
-              }
-
-              if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){
-                break;
-              }
+    rc = sqlite3OsFileSize(pWal->pDbFd, &szDb);
+    if( rc==SQLITE_OK ){
+      void *pBuf1 = sqlite3_malloc(szPage);
+      void *pBuf2 = sqlite3_malloc(szPage);
+      if( pBuf1==0 || pBuf2==0 ){
+        rc = SQLITE_NOMEM;
+      }else{
+        u32 i = pInfo->nBackfillAttempted;
+        for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){
+          volatile ht_slot *dummy;
+          volatile u32 *aPgno;      /* Array of page numbers */
+          u32 iZero;                /* Frame corresponding to aPgno[0] */
+          u32 pgno;                 /* Page number in db file */
+          i64 iDbOff;               /* Offset of db file entry */
+          i64 iWalOff;              /* Offset of wal file entry */
+
+          rc = walHashGet(pWal, walFramePage(i), &dummy, &aPgno, &iZero);
+          if( rc!=SQLITE_OK ) break;
+          pgno = aPgno[i-iZero];
+          iDbOff = (i64)(pgno-1) * szPage;
+
+          if( iDbOff+szPage<=szDb ){
+            iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE;
+            rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff);
+
+            if( rc==SQLITE_OK ){
+              rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff);
             }
 
-            pInfo->nBackfillAttempted = i-1;
+            if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){
+              break;
+            }
           }
-        }
 
-        sqlite3_free(pBuf1);
-        sqlite3_free(pBuf2);
+          pInfo->nBackfillAttempted = i-1;
+        }
       }
-      walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
-    }
 
-    /* End the read transaction opened above. Also zero the cache of the
-    ** wal-index header to force the pager-cache to be flushed when the next
-    ** read transaction is open, as it may not match the current contents of
-    ** pWal->hdr. */
-    sqlite3WalEndReadTransaction(pWal);
-    memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
+      sqlite3_free(pBuf1);
+      sqlite3_free(pBuf2);
+    }
+    walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
   }
 
   return rc;
index b13bbe8862722802f052245cde992f24dc656126..62d3070ecd9c97e2658cae8c1edb1d2ad97aab09 100644 (file)
@@ -131,7 +131,6 @@ do_test 2.5 {
   db close
   sqlite3 db test.db
 
-  execsql {SELECT * FROM sqlite_master}
   sqlite3_snapshot_recover db main
   execsql BEGIN
   list [catch { sqlite3_snapshot_open_blob db main $snap } msg] $msg