]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix bug in log recovery (last frame in log was being ignored). Also remove an incorre...
authordan <dan@noemail.net>
Fri, 16 Apr 2010 11:30:18 +0000 (11:30 +0000)
committerdan <dan@noemail.net>
Fri, 16 Apr 2010 11:30:18 +0000 (11:30 +0000)
FossilOrigin-Name: 67d2a89ec2d593a077eb19a6ea2b06cb1c2e9ba8

manifest
manifest.uuid
src/log.c
src/pager.c
test/wal.test

index f04ac19026672ea31caa1ed3dad148b65f2da951..547b763339218289ff4d9c6f1d6609e770666ee9 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Allow\swriters\sto\swrite\sdirty\spages\sto\sthe\slog\smid-transaction\sin\sorder\sto\sfree\smemory.
-D 2010-04-15T16:45:35
+C Fix\sbug\sin\slog\srecovery\s(last\sframe\sin\slog\swas\sbeing\signored).\sAlso\sremove\san\sincorrect\sassert\sstatement.
+D 2010-04-16T11:30:18
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 4f2f967b7e58a35bb74fb7ec8ae90e0f4ca7868b
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -131,7 +131,7 @@ F src/journal.c b0ea6b70b532961118ab70301c00a33089f9315c
 F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
 F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
 F src/loadext.c 1c7a61ce1281041f437333f366a96aa0d29bb581
-F src/log.c 3647edbc85ac745db7f18bc1102344aa2ee5259a
+F src/log.c 40e0c5780e7a33556f421142562edbf77f8e6639
 F src/log.h a2654af46ce7b5732f4d5a731abfdd180f0a06d9
 F src/main.c c0e7192bad5b90544508b241eb2487ac661de890
 F src/malloc.c a08f16d134f0bfab6b20c3cd142ebf3e58235a6a
@@ -154,7 +154,7 @@ F src/os_common.h 240c88b163b02c21a9f21f87d49678a0aa21ff30
 F src/os_os2.c 75a8c7b9a00a2cf1a65f9fa4afbc27d46634bb2f
 F src/os_unix.c 5bf0015cebe2f21635da2af983c348eb88b3b4c1
 F src/os_win.c 1c7453c2df4dab26d90ff6f91272aea18bcf7053
-F src/pager.c 80054194c18631342f6b8253e0bb090020c0cd55
+F src/pager.c 35c7e3b5bbad76f04e7143d2d4676a269a8ba9fc
 F src/pager.h ce5d076f3860a5f2d7460c582cd68383343b33cf
 F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e
 F src/pcache.c ace8f6a5ecd4711cc66a1b23053be7109bd437cf
@@ -757,7 +757,7 @@ F test/vtabE.test 7c4693638d7797ce2eda17af74292b97e705cc61
 F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
 F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
-F test/wal.test b0b6c02bbb0b2a647b4edb69325d4c59ac73259b
+F test/wal.test ff3c101453044e1f9930d0421a164e09619a678c
 F test/walcrash.test 45cfbab30bb7cbe0b2e9d5cabe90dbcad10cb89b
 F test/walslow.test 38076d5fad49e3678027be0f8110e6a32d531dc2
 F test/walthread.test 58cd64b06f186251f09f64e4918fb74a7e52c963
@@ -804,7 +804,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P c9ed66cc3994b3b0d67a6c950b552a1a869f2ed2
-R 0dae17f227f2dd17e65e49bd0f5ce0a8
+P ecd828f96909895535d7dc744e5a8530e234e04d
+R 6491b6f312e37bd3163c20e935da6a05
 U dan
-Z b4af52effa56ad5510bfc4469b8a847d
+Z 46ab8b741bc2f3b7a6a7fee62de40d58
index b8f7810b58521cb603a63c15d9a87056bf8adc23..c682fa9a6ac8bebad1971878b215cb2b9e82b24d 100644 (file)
@@ -1 +1 @@
-ecd828f96909895535d7dc744e5a8530e234e04d
\ No newline at end of file
+67d2a89ec2d593a077eb19a6ea2b06cb1c2e9ba8
\ No newline at end of file
index 032b210a28f300c39f6ee75fb409e7c6bcf5b572..67bf9c0841b60d99aff1f59ce6c86bc1a7b97c31 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -12,7 +12,7 @@
 
 typedef struct LogSummaryHdr LogSummaryHdr;
 typedef struct LogSummary LogSummary;
-typedef struct LogCheckpoint LogCheckpoint;
+typedef struct LogIterator LogIterator;
 typedef struct LogLock LogLock;
 
 
@@ -109,14 +109,14 @@ struct Log {
 **
 ** The internals of this structure are only accessed by:
 **
-**   logCheckpointInit() - Create a new iterator,
-**   logCheckpointNext() - Step an iterator,
-**   logCheckpointFree() - Free an iterator.
+**   logIteratorInit() - Create a new iterator,
+**   logIteratorNext() - Step an iterator,
+**   logIteratorFree() - Free an iterator.
 **
 ** This functionality is used by the checkpoint code (see logCheckpoint()).
 */
-struct LogCheckpoint {
-  int nSegment;                   /* Size of LogCheckpoint.aSummary[] array */
+struct LogIterator {
+  int nSegment;                   /* Size of LogIterator.aSegment[] array */
   int nFinal;                     /* Elements in segment nSegment-1 */
   struct LogSegment {
     int iNext;                    /* Next aIndex index */
@@ -346,6 +346,8 @@ static int logDecodeFrame(
   u8 *aData,                      /* Pointer to page data (for checksum) */
   u8 *aFrame                      /* Frame data */
 ){
+  assert( LOG_FRAME_HDRSIZE==20 );
+
   logChecksumBytes(aFrame, 12, aCksum);
   logChecksumBytes(aData, nData, aCksum);
 
@@ -513,7 +515,7 @@ static int logSummaryRecover(LogSummary *pSummary, sqlite3_file *pFd){
     /* Read all frames from the log file. */
     iFrame = 0;
     iOffset = 0;
-    for(iOffset=0; (iOffset+nFrame)<nSize; iOffset+=nFrame){
+    for(iOffset=0; (iOffset+nFrame)<=nSize; iOffset+=nFrame){
       u32 pgno;                   /* Database page number for frame */
       u32 nTruncate;              /* dbsize field from frame header */
       int isValid;                /* True if this frame is valid */
@@ -713,8 +715,8 @@ int sqlite3LogOpen(
   return rc;
 }
 
-static int logCheckpointNext(
-  LogCheckpoint *p,               /* Iterator */
+static int logIteratorNext(
+  LogIterator *p,               /* Iterator */
   u32 *piPage,                    /* OUT: Next db page to write */
   u32 *piFrame                    /* OUT: Log frame to read from */
 ){
@@ -744,9 +746,9 @@ static int logCheckpointNext(
   return (iRet==0xFFFFFFFF);
 }
 
-static LogCheckpoint *logCheckpointInit(Log *pLog){
+static LogIterator *logIteratorInit(Log *pLog){
   u32 *aData = pLog->pSummary->aData;
-  LogCheckpoint *p;               /* Return value */
+  LogIterator *p;                 /* Return value */
   int nSegment;                   /* Number of segments to merge */
   u32 iLast;                      /* Last frame in log */
   int nByte;                      /* Number of bytes to allocate */
@@ -759,8 +761,8 @@ static LogCheckpoint *logCheckpointInit(Log *pLog){
   nSegment = (iLast >> 8) + 1;
   nFinal = (iLast & 0x000000FF);
 
-  nByte = sizeof(LogCheckpoint) + (nSegment-1)*sizeof(struct LogSegment) + 512;
-  p = (LogCheckpoint *)sqlite3_malloc(nByte);
+  nByte = sizeof(LogIterator) + (nSegment-1)*sizeof(struct LogSegment) + 512;
+  p = (LogIterator *)sqlite3_malloc(nByte);
   if( p ){
     memset(p, 0, nByte);
     p->nSegment = nSegment;
@@ -786,9 +788,9 @@ static LogCheckpoint *logCheckpointInit(Log *pLog){
 }
 
 /* 
-** Free a log iterator allocated by logCheckpointInit().
+** Free a log iterator allocated by logIteratorInit().
 */
-static void logCheckpointFree(LogCheckpoint *p){
+static void logIteratorFree(LogIterator *p){
   sqlite3_free(p);
 }
 
@@ -802,7 +804,7 @@ static int logCheckpoint(
 ){
   int rc;                         /* Return code */
   int pgsz = pLog->hdr.pgsz;      /* Database page-size */
-  LogCheckpoint *pIter = 0;       /* Log iterator context */
+  LogIterator *pIter = 0;         /* Log iterator context */
   u32 iDbpage = 0;                /* Next database page to write */
   u32 iFrame = 0;                 /* Log frame containing data for iDbpage */
 
@@ -811,7 +813,7 @@ static int logCheckpoint(
   }
 
   /* Allocate the iterator */
-  pIter = logCheckpointInit(pLog);
+  pIter = logIteratorInit(pLog);
   if( !pIter ) return SQLITE_NOMEM;
 
   /* Sync the log file to disk */
@@ -819,7 +821,7 @@ static int logCheckpoint(
   if( rc!=SQLITE_OK ) goto out;
 
   /* Iterate through the contents of the log, copying data to the db file. */
-  while( 0==logCheckpointNext(pIter, &iDbpage, &iFrame) ){
+  while( 0==logIteratorNext(pIter, &iDbpage, &iFrame) ){
     rc = sqlite3OsRead(pLog->pFd, zBuf, pgsz, 
         (iFrame-1) * (pgsz+LOG_FRAME_HDRSIZE) + LOG_FRAME_HDRSIZE
     );
@@ -861,7 +863,7 @@ static int logCheckpoint(
 #endif
 
  out:
-  logCheckpointFree(pIter);
+  logIteratorFree(pIter);
   return rc;
 }
 
index cd83fdb72c3ba1663d69210e67ddab2cbe6e0bd7..3b16b86dd89f470ab8d3a252ede3e283ac0a3bad 100644 (file)
@@ -3253,9 +3253,9 @@ static int pagerStress(void *p, PgHdr *pPg){
   assert( pPg->pPager==pPager );
   assert( pPg->flags&PGHDR_DIRTY );
 
+  pPg->pDirty = 0;
   if( pagerUseLog(pPager) ){
     /* Write a single frame for this page to the log. */
-    assert( pPg->pDirty==0 );
     rc = sqlite3LogFrames(pPager->pLog, pPager->pageSize, pPg, 0, 0, 0);
   }else{
     /* The doNotSync flag is set by the sqlite3PagerWrite() function while it
@@ -3324,7 +3324,6 @@ static int pagerStress(void *p, PgHdr *pPg){
   
     /* Write the contents of the page out to the database file. */
     if( rc==SQLITE_OK ){
-      pPg->pDirty = 0;
       rc = pager_write_pagelist(pPg);
     }
   }
index 799e49dc810c3024b72b623707c65d6149151381..79b3b52d50726ad1dab7ab5a5fda57d62231ea97 100644 (file)
@@ -621,5 +621,63 @@ do_test wal-11.14 {
 } {37 38}
 
 
+#-------------------------------------------------------------------------
+# This block of tests, wal-12.*, tests a problem...
+#
+reopen_db
+do_test wal-12.1 {
+  execsql {
+    PRAGMA page_size = 1024;
+    CREATE TABLE t1(x, y);
+    CREATE TABLE t2(x, y);
+    INSERT INTO t1 VALUES('A', 1);
+  }
+  list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044]
+} {0 5}
+do_test wal-12.2 {
+  db close
+  sqlite3_wal db test.db
+  execsql {
+    UPDATE t1 SET y = 0 WHERE x = 'A';
+  }
+  list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044]
+} {3 1}
+do_test wal-12.3 {
+  execsql { INSERT INTO t2 VALUES('B', 1) }
+  list [expr [file size test.db]/1024] [expr [file size test.db-wal]/1044]
+} {3 2}
+
+do_test wal-12.4 {
+  file copy -force test.db test2.db
+  file copy -force test.db-wal test2.db-wal
+  sqlite3_wal db2 test2.db
+breakpoint
+  execsql { SELECT * FROM t2 } db2
+} {B 1}
+db2 close
+
+file copy -force test.db-wal A
+do_test wal-12.5 {
+  execsql {
+    PRAGMA checkpoint;
+    UPDATE t2 SET y = 2 WHERE x = 'B'; 
+    PRAGMA checkpoint;
+    UPDATE t1 SET y = 1 WHERE x = 'A';
+    PRAGMA checkpoint;
+    UPDATE t1 SET y = 0 WHERE x = 'A';
+    SELECT * FROM t2;
+  }
+} {B 2}
+file copy -force test.db-wal B
+
+do_test wal-12.4 {
+  file copy -force test.db test2.db
+  file copy -force test.db-wal test2.db-wal
+  sqlite3_wal db2 test2.db
+  execsql { SELECT * FROM t2 } db2
+} {B 2}
+db2 close
+
+
 finish_test