]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add some testcase() and assert() macros to btree.c to aid with testing
authordrh <drh@noemail.net>
Tue, 30 Sep 2008 17:18:17 +0000 (17:18 +0000)
committerdrh <drh@noemail.net>
Tue, 30 Sep 2008 17:18:17 +0000 (17:18 +0000)
recent changes. (CVS 5757)

FossilOrigin-Name: fb461b78dfc2501fafa8bce03da5487fdfdff959

manifest
manifest.uuid
src/btree.c
src/btreeInt.h

index 3165948ba06a3b13444689edb1b088dd06efde90..ff742b0cd25848ae47dfa31776dc3f0b72cd4320 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\scomment\sin\sbtree.c.\sNo\scode\schanges.\s(CVS\s5756)
-D 2008-09-30T16:48:11
+C Add\ssome\stestcase()\sand\sassert()\smacros\sto\sbtree.c\sto\said\swith\stesting\nrecent\schanges.\s(CVS\s5757)
+D 2008-09-30T17:18:17
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in e4ab842f9a64ef61d57093539a8aab76b12810db
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -99,9 +99,9 @@ F src/attach.c db3f4a60538733c1e4dcb9d0217a6e0d6ccd615b
 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
 F src/bitvec.c 95c86bd18d8fedf0533f5af196192546e10a7e7d
 F src/btmutex.c 709cad2cdca0afd013f0f612363810e53f59ec53
-F src/btree.c d1720e1e26bc6304737aa0bf86fdc8557f2c39d3
+F src/btree.c 64a38df6f0a9997563418ed194984b81e4ab3694
 F src/btree.h 6371c5e599fab391a150c96afbc10062b276d107
-F src/btreeInt.h 3e93c0a6f363bbf68fdd975620f4d3671b6cf7bc
+F src/btreeInt.h e38e9b2b285f40f5bc0a6664f630d4a141622f16
 F src/build.c 160c71acca8f643f436ed6c1ee2f684c88df4dfe
 F src/callback.c 7a40fd44da3eb89e7f6eff30aa6f940c45d73a97
 F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c
@@ -637,7 +637,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 4e536463c1aa9991de85c7efc826c28896ca61d3
-R d230b8ef533fbafc7b1b9585de11f133
-U danielk1977
-Z 11a16b730f49b9e3f152c7fd36e76118
+P 0f3c56330b43fb7c9dc43a444ca38bace9397ede
+R 5a3edf18f89485bee6c0db5078617fd9
+U drh
+Z 6d8b0066d3b484307b936dd03d86c312
index 10ccebfc4621ac72151421458c5a024cef40673d..73ec9a101e4bbe388bca9eb3c0ab7bd5c7b67309 100644 (file)
@@ -1 +1 @@
-0f3c56330b43fb7c9dc43a444ca38bace9397ede
\ No newline at end of file
+fb461b78dfc2501fafa8bce03da5487fdfdff959
\ No newline at end of file
index dedbdbabf031ce92456ecc15562b19d8a6ff3a3b..eae118ef8fac1a991e1c33ec666efbd58a473722 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.523 2008/09/30 16:48:11 danielk1977 Exp $
+** $Id: btree.c,v 1.524 2008/09/30 17:18:17 drh Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** See the header comment on "btreeInt.h" for additional information.
@@ -34,6 +34,20 @@ int sqlite3BtreeTrace=0;  /* True to enable tracing */
 # define TRACE(X)
 #endif
 
+/*
+** Sometimes we need a small amount of code such as a variable initialization
+** to setup for a later assert() statement.  We do not want this code to
+** appear when assert() is disabled.  The following macro is therefore
+** used to contain that setup code.  The "VVA" acronym stands for
+** "Verification, Validation, and Accreditation".  In other words, the
+** code within VVA_ONLY() will only run during verification processes.
+*/
+#ifndef NDEBUG
+# define VVA_ONLY(X)  X
+#else
+# define VVA_ONLY(X)
+#endif
+
 
 
 #ifndef SQLITE_OMIT_SHARED_CACHE
@@ -2356,9 +2370,7 @@ int sqlite3BtreeIncrVacuum(Btree *p){
 static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){
   int rc = SQLITE_OK;
   Pager *pPager = pBt->pPager;
-#ifndef NDEBUG
-  int nRef = sqlite3PagerRefcount(pPager);
-#endif
+  VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager) );
 
   assert( sqlite3_mutex_held(pBt->mutex) );
   invalidateAllOverflowCache(pBt);
@@ -4910,6 +4922,7 @@ static int balance_nonroot(BtCursor *pCur){
 
   pPage = pCur->apPage[pCur->iPage];
   assert( sqlite3_mutex_held(pPage->pBt->mutex) );
+  VVA_ONLY( pCur->pagesShuffled = 1 );
 
   /* 
   ** Find the parent page.
@@ -5492,6 +5505,7 @@ static int balance_shallower(BtCursor *pCur){
     ** for the right-pointer to the child page.  The child page becomes
     ** the virtual root of the tree.
     */
+    VVA_ONLY( pCur->pagesShuffled = 1 );
     pgnoChild = get4byte(&pPage->aData[pPage->hdrOffset+8]);
     assert( pgnoChild>0 );
     assert( pgnoChild<=pagerPagecount(pPage->pBt->pPager) );
@@ -5566,6 +5580,7 @@ static int balance_deeper(BtCursor *pCur){
   assert( pCur->iPage==0 );
   assert( pCur->apPage[0]->nOverflow>0 );
 
+  VVA_ONLY( pCur->pagesShuffled = 1 );
   pPage = pCur->apPage[0];
   pBt = pPage->pBt;
   assert( sqlite3_mutex_held(pBt->mutex) );
@@ -5814,7 +5829,7 @@ end_insert:
 
 /*
 ** Delete the entry that the cursor is pointing to.  The cursor
-** is left pointing at a random location.
+** is left pointing at a arbitrary location.
 */
 int sqlite3BtreeDelete(BtCursor *pCur){
   MemPage *pPage = pCur->apPage[pCur->iPage];
@@ -5913,11 +5928,30 @@ int sqlite3BtreeDelete(BtCursor *pCur){
         rc = insertCell(pPage, idx, pNext-4, szNext+4, tempCell, 0);
       }
 
+
+      /* The "if" statement in the next code block is critical.  The
+      ** slightest error in that statement would allow SQLite to operate
+      ** correctly most of the time but produce very rare failures.  To
+      ** guard against this, the following macros help to verify that
+      ** the "if" statement is well tested.
+      */
+      testcase( pPage->nOverflow==0 && pPage->nFree<pBt->usableSize*2/3 
+                 && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
+      testcase( pPage->nOverflow==0 && pPage->nFree==pBt->usableSize*2/3 
+                 && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
+      testcase( pPage->nOverflow==0 && pPage->nFree==pBt->usableSize*2/3+1 
+                 && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
+      testcase( pPage->nOverflow>0 && pPage->nFree<=pBt->usableSize*2/3
+                 && pLeafPage->nFree+2+szNext > pBt->usableSize*2/3 );
+      testcase( (pPage->nOverflow>0 || (pPage->nFree > pBt->usableSize*2/3))
+                 && pLeafPage->nFree+2+szNext == pBt->usableSize*2/3 );
+
+
       if( (pPage->nOverflow>0 || (pPage->nFree > pBt->usableSize*2/3)) &&
           (pLeafPage->nFree+2+szNext > pBt->usableSize*2/3)
       ){
-        /* This branch is taken if the internal node is now either over or
-        ** underfull and the leaf node will be underfull after the just cell 
+        /* This branch is taken if the internal node is now either overflowing
+        ** or underfull and the leaf node will be underfull after the just cell 
         ** copied to the internal node is deleted from it. This is a special
         ** case because the call to balance() to correct the internal node
         ** may change the tree structure and invalidate the contents of
@@ -5928,11 +5962,14 @@ int sqlite3BtreeDelete(BtCursor *pCur){
         ** The formula used in the expression above are based on facets of
         ** the SQLite file-format that do not change over time.
         */
+        testcase( pPage->nFree==pBt->usableSize*2/3+1 );
+        testcase( pLeafPage->nFree+2+szNext==pBt->usableSize*2/3+1 );
         leafCursorInvalid = 1;
       }        
 
       if( rc==SQLITE_OK ){
         put4byte(findOverflowCell(pPage, idx), pgnoChild);
+        VVA_ONLY( pCur->pagesShuffled = 0 );
         rc = balance(pCur, 0);
       }
 
@@ -5960,9 +5997,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
         ** that needs to be removed, and the leafCur.apPage[] and
         ** leafCur.aiIdx[] arrays are correct.
         */
-      #ifndef NDEBUG
-        Pgno leafPgno = pLeafPage->pgno;
-      #endif
+        VVA_ONLY( Pgno leafPgno = pLeafPage->pgno );
         rc = saveCursorPosition(&leafCur);
         if( rc==SQLITE_OK ){
           rc = sqlite3BtreeNext(&leafCur, &notUsed);
@@ -5974,7 +6009,10 @@ int sqlite3BtreeDelete(BtCursor *pCur){
 
       if( rc==SQLITE_OK ){
         dropCell(pLeafPage, 0, szNext);
+        VVA_ONLY( leafCur.pagesShuffled = 0 );
         rc = balance(&leafCur, 0);
+        assert( leafCursorInvalid || !leafCur.pagesShuffled
+                                   || !pCur->pagesShuffled );
       }
     }
     sqlite3BtreeReleaseTempCursor(&leafCur);
index 14b852bc97f1d00a1a68da01da9176ca48e5f730..92eca75c110ddff2a15f0ec6c2f953deca096b7b 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btreeInt.h,v 1.33 2008/09/29 15:53:26 danielk1977 Exp $
+** $Id: btreeInt.h,v 1.34 2008/09/30 17:18:17 drh Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** For a detailed discussion of BTrees, refer to
@@ -454,7 +454,9 @@ struct BtCursor {
   u8 isIncrblobHandle;      /* True if this cursor is an incr. io handle */
   Pgno *aOverflow;          /* Cache of overflow page locations */
 #endif
-
+#ifndef NDEBUG
+  u8 pagesShuffled;         /* True if Btree pages are rearranged by balance()*/
+#endif
   i16 iPage;                            /* Index of current page in apPage */
   MemPage *apPage[BTCURSOR_MAX_DEPTH];  /* Pages from root to current page */
   u16 aiIdx[BTCURSOR_MAX_DEPTH];        /* Current index in apPage[i] */