]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Make sure the change-counter and SQLite-version fields of the header are
authordrh <drh@noemail.net>
Sun, 20 Feb 2011 03:32:54 +0000 (03:32 +0000)
committerdrh <drh@noemail.net>
Sun, 20 Feb 2011 03:32:54 +0000 (03:32 +0000)
set correctly even after vacuuming.  This is a backport of changes
[0be92a7576] and [04fa1e1690] to address ticket [5de63f876cc].

FossilOrigin-Name: 442be1358e7dff17548718c0c7c031ec320d135d

manifest
manifest.uuid
src/pager.c
test/exclusive2.test

index c83c67403a4df6b265075c9d6ce633c0e8238c02..aabe5693ce373322e1d32f6740fddab62e85a031 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,8 @@
 -----BEGIN PGP SIGNED MESSAGE-----
 Hash: SHA1
 
-C Do\snot\sraise\san\sSQLITE_CORRUPT\serror\sin\sRecoverymode\sif\sthe\sdatabase\ssize\nin\sthe\sheader\sis\slarger\sthan\sthe\sphysical\sfile\ssize.\s\sThis\sis\sa\scherrypick\nof\scheckin\s[114640d920e16c8]
-D 2011-02-20T03:27:52.324
+C Make\ssure\sthe\schange-counter\sand\sSQLite-version\sfields\sof\sthe\sheader\sare\nset\scorrectly\seven\safter\svacuuming.\s\sThis\sis\sa\sbackport\sof\schanges\n[0be92a7576]\sand\s[04fa1e1690]\sto\saddress\sticket\s[5de63f876cc].
+D 2011-02-20T03:32:54.731
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 4547616ad2286053af6ccccefa242dc925e49bf0
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -165,7 +165,7 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
 F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e
 F src/os_unix.c 0240c5b547b4cf585c8cac351a95c3e85ce00772
 F src/os_win.c 2f90f7bdec714fad51cd31b4ecad3cc1b4bb5aad
-F src/pager.c c0aca5c733c15a16fe158c3215d857841a4e5381
+F src/pager.c 5b2210b4307c626a3b3ed7312161ec533958c094
 F src/pager.h 0ea59db2a33bc6c2c02cae34de33367e1effdf76
 F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
 F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
@@ -376,7 +376,7 @@ F test/enc4.test 4b575ef09e0eff896e73bd24076f96c2aa6a42de
 F test/eqp.test 69670e7919030f21de29fb99bf1d68f97aedcbdb
 F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
 F test/exclusive.test 53e1841b422e554cecf0160f937c473d6d0e3062
-F test/exclusive2.test 76e63c05349cb70d09d60b99d2ae625525ff5155
+F test/exclusive2.test c2f2b2242dc436a12df8dd531e06843053bd3b9a
 F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
 F test/expr.test 620a636cf7b7d4e5834a0b9d83a4da372e24a7b7
 F test/fallocate.test 43dc34b8c24be6baffadc3b4401ee15710ce83c6
@@ -897,14 +897,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 29597a71d0848cd5faeb68b606a9127910c8dc57
-R 4765ab892066a2cf596b52ac188daaa7
+P 7701b07759d63537408a68bac85cb1b8b27160b7
+R 1af9cda1d47f108dd79a57e892ab3d60
 U drh
-Z 0fd913631bd65c1d6b88eece64aed780
+Z d17b6d73dc0e258c19674947beb8c07b
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.6 (GNU/Linux)
 
-iD8DBQFNYIo8oxKgR168RlERAtxOAJ0W2UlkzgKSsQgJHB8/MuaurrnAOACeIEqH
-2d5x+c+4cCHEyAOLiV5KRVk=
-=mpQI
+iD8DBQFNYItqoxKgR168RlERAkvGAJ456/IGVD5IaXa+SVUvWNJiAFQjWwCdEmc5
+sY0984PvfU6Cksq4hCEZCN0=
+=PbW4
 -----END PGP SIGNATURE-----
index f75cc684ef3cbd1ede4200d58c2e585bf3a8a8c0..0a7ea22276cbe0e57a050fd9be89babd1a1edda5 100644 (file)
@@ -1 +1 @@
-7701b07759d63537408a68bac85cb1b8b27160b7
\ No newline at end of file
+442be1358e7dff17548718c0c7c031ec320d135d
\ No newline at end of file
index 5fcee322bc2dcb6a49cb005d31b727c878c4ea0b..2b267b189518585e63405677e9f3af0a9a95dafc 100644 (file)
@@ -2915,11 +2915,37 @@ static int pagerRollbackWal(Pager *pPager){
   return rc;
 }
 
+
+/*
+** Update the value of the change-counter at offsets 24 and 92 in
+** the header and the sqlite version number at offset 96.
+**
+** This is an unconditional update.  See also the pager_incr_changecounter()
+** routine which only updates the change-counter if the update is actually
+** needed, as determined by the pPager->changeCountDone state variable.
+*/
+static void pager_write_changecounter(PgHdr *pPg){
+  u32 change_counter;
+
+  /* Increment the value just read and write it back to byte 24. */
+  change_counter = sqlite3Get4byte((u8*)pPg->pPager->dbFileVers)+1;
+  put32bits(((char*)pPg->pData)+24, change_counter);
+
+  /* Also store the SQLite version number in bytes 96..99 and in
+  ** bytes 92..95 store the change counter for which the version number
+  ** is valid. */
+  put32bits(((char*)pPg->pData)+92, change_counter);
+  put32bits(((char*)pPg->pData)+96, SQLITE_VERSION_NUMBER);
+}
+
 /*
 ** This function is a wrapper around sqlite3WalFrames(). As well as logging
 ** the contents of the list of pages headed by pList (connected by pDirty),
 ** this function notifies any active backup processes that the pages have
-** changed. 
+** changed.
+**
+** The list of pages passed into this routine is always sorted by page number.
+** Hence, if page 1 appears anywhere on the list, it will be the first page.
 */ 
 static int pagerWalFrames(
   Pager *pPager,                  /* Pager object */
@@ -2929,8 +2955,19 @@ static int pagerWalFrames(
   int syncFlags                   /* Flags to pass to OsSync() (or 0) */
 ){
   int rc;                         /* Return code */
+#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
+  PgHdr *p;                       /* For looping over pages */
+#endif
 
   assert( pPager->pWal );
+#ifdef SQLITE_DEBUG
+  /* Verify that the page list is in accending order */
+  for(p=pList; p && p->pDirty; p=p->pDirty){
+    assert( p->pgno < p->pDirty->pgno );
+  }
+#endif
+
+  if( pList->pgno==1 ) pager_write_changecounter(pList);
   rc = sqlite3WalFrames(pPager->pWal, 
       pPager->pageSize, pList, nTruncate, isCommit, syncFlags
   );
@@ -2942,9 +2979,8 @@ static int pagerWalFrames(
   }
 
 #ifdef SQLITE_CHECK_PAGES
-  {
-    PgHdr *p;
-    for(p=pList; p; p=p->pDirty) pager_set_pagehash(p);
+  for(p=pList; p; p=p->pDirty){
+    pager_set_pagehash(p);
   }
 #endif
 
@@ -3969,6 +4005,7 @@ static int pager_write_pagelist(Pager *pPager, PgHdr *pList){
       char *pData;                                   /* Data to write */    
 
       assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
+      if( pList->pgno==1 ) pager_write_changecounter(pList);
 
       /* Encode the database */
       CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM, pData);
@@ -5489,7 +5526,13 @@ void sqlite3PagerDontWrite(PgHdr *pPg){
 /*
 ** This routine is called to increment the value of the database file 
 ** change-counter, stored as a 4-byte big-endian integer starting at 
-** byte offset 24 of the pager file.
+** byte offset 24 of the pager file.  The secondary change counter at
+** 92 is also updated, as is the SQLite version number at offset 96.
+**
+** But this only happens if the pPager->changeCountDone flag is false.
+** To avoid excess churning of page 1, the update only happens once.
+** See also the pager_write_changecounter() routine that does an 
+** unconditional update of the change counters.
 **
 ** If the isDirectMode flag is zero, then this is done by calling 
 ** sqlite3PagerWrite() on page 1, then modifying the contents of the
@@ -5530,7 +5573,6 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
 
   if( !pPager->changeCountDone && pPager->dbSize>0 ){
     PgHdr *pPgHdr;                /* Reference to page 1 */
-    u32 change_counter;           /* Initial value of change-counter field */
 
     assert( !pPager->tempFile && isOpen(pPager->fd) );
 
@@ -5543,21 +5585,13 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
     ** direct mode, page 1 is always held in cache and hence the PagerGet()
     ** above is always successful - hence the ALWAYS on rc==SQLITE_OK.
     */
-    if( !DIRECT_MODE && ALWAYS(rc==SQLITE_OK) ){
+    if( !DIRECT_MODE && rc==SQLITE_OK ){
       rc = sqlite3PagerWrite(pPgHdr);
     }
 
     if( rc==SQLITE_OK ){
-      /* Increment the value just read and write it back to byte 24. */
-      change_counter = sqlite3Get4byte((u8*)pPager->dbFileVers);
-      change_counter++;
-      put32bits(((char*)pPgHdr->pData)+24, change_counter);
-
-      /* Also store the SQLite version number in bytes 96..99 and in
-      ** bytes 92..95 store the change counter for which the version number
-      ** is valid. */
-      put32bits(((char*)pPgHdr->pData)+92, change_counter);
-      put32bits(((char*)pPgHdr->pData)+96, SQLITE_VERSION_NUMBER);
+      /* Actually do the update of the change counter */
+      pager_write_changecounter(pPgHdr);
 
       /* If running in direct mode, write the contents of page 1 to the file. */
       if( DIRECT_MODE ){
index 6c3571d23b66a1f70e0273b6bd2933942d947bde..4a167c7f428a340804555993570279a9fe138a3d 100644 (file)
@@ -299,13 +299,13 @@ do_test exclusive2-3.5 {
     INSERT INTO t1 VALUES(randstr(10, 400));
   }
   readPagerChangeCounter test.db
-} {4}
+} {5}
 do_test exclusive2-3.6 {
   execsql {
     INSERT INTO t1 VALUES(randstr(10, 400));
   }
   readPagerChangeCounter test.db
-} {5}
+} {6}
 sqlite3_soft_heap_limit $cmdlinearg(soft-heap-limit)
 
 finish_test