From: drh Date: Tue, 30 Jun 2015 02:47:36 +0000 (+0000) Subject: Put BtCursor objects on a singly-linked list instead of a doubly-linked list. X-Git-Tag: version-3.8.11~91 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=27fb746cde8eda3889ebbda44f576db991ba2b5b;p=thirdparty%2Fsqlite.git Put BtCursor objects on a singly-linked list instead of a doubly-linked list. Add the BTCF_Multiple flag. Only invoke saveAllCursors() when using a cursor that has BTCF_Multiple set. FossilOrigin-Name: 429ccef2b36fc46e92914eb54afd5f800b1a40ff --- diff --git a/manifest b/manifest index f1e3876e00..4290efa141 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Convert\sseveral\s5-year-old\sand\solder\sNEVER()\smacros\sinto\sassert(). -D 2015-06-30T01:25:52.068 +C Put\sBtCursor\sobjects\son\sa\ssingly-linked\slist\sinstead\sof\sa\sdoubly-linked\slist.\nAdd\sthe\sBTCF_Multiple\sflag.\s\sOnly\sinvoke\ssaveAllCursors()\swhen\susing\sa\scursor\nthat\shas\sBTCF_Multiple\sset. +D 2015-06-30T02:47:36.537 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 285a0a234ed7610d431d91671c136098c2bd86a9 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -269,9 +269,9 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3 F src/bitvec.c d1f21d7d91690747881f03940584f4cc548c9d3d F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 -F src/btree.c 5d5d48461b3838988bd1f5b197c145df66786805 +F src/btree.c 08ae64b0387e72b8201981a2d7b0f58b92fdff29 F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1 -F src/btreeInt.h 8ca7124af9ee2ce27747a4e5500c27a254dea8eb +F src/btreeInt.h e4eabc722b1ae017ac9c266a75769d4c6a9afde6 F src/build.c b3f15255d5b16e42dafeaa638fd4f8a47c94ed70 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c a5cf5b4b56390cfb7b8636e8f7ddef90258dd575 @@ -1364,7 +1364,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 53fe685d56368af78238c8981cc41704929f7660 -R 0ca8cb603f507b8c27049a9ebf015fe3 +P ed54c14ea8a72d69d69e0c0d7f6936f54efc04c2 +R f3f8b025f26bf8ce4de670023e83b4e0 U drh -Z e0e6efeb2c6c43faed874d1e7ab03448 +Z aa2cb7c94aea3021edb11ed06abf028f diff --git a/manifest.uuid b/manifest.uuid index 412ac12f4f..556c262e4c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ed54c14ea8a72d69d69e0c0d7f6936f54efc04c2 \ No newline at end of file +429ccef2b36fc46e92914eb54afd5f800b1a40ff \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index fded6343e4..ef2a861528 100644 --- a/src/btree.c +++ b/src/btree.c @@ -655,6 +655,15 @@ static int SQLITE_NOINLINE saveCursorsOnList(BtCursor*,Pgno,BtCursor*); ** routine is called just before cursor pExcept is used to modify the ** table, for example in BtreeDelete() or BtreeInsert(). ** +** If there are two or more cursors on the same btree, then all such +** cursors should have their BTCF_Multiple flag set. The btreeCursor() +** routine enforces that rule. This routine only needs to be called in +** the uncommon case when pExpect has the BTCF_Multiple flag set. +** +** If pExpect!=NULL and if no other cursors are found on the same root-page, +** then the BTCF_Multiple flag on pExpect is cleared, to avoid another +** pointless call to this routine. +** ** Implementation note: This routine merely checks to see if any cursors ** need to be saved. It calls out to saveCursorsOnList() in the (unusual) ** event that cursors are in need to being saved. @@ -666,7 +675,9 @@ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ for(p=pBt->pCursor; p; p=p->pNext){ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ) break; } - return p ? saveCursorsOnList(p, iRoot, pExcept) : SQLITE_OK; + if( p ) return saveCursorsOnList(p, iRoot, pExcept); + if( pExcept ) pExcept->curFlags &= ~BTCF_Multiple; + return SQLITE_OK; } /* This helper routine to saveAllCursors does the actual work of saving @@ -4015,6 +4026,7 @@ static int btreeCursor( BtCursor *pCur /* Space for new cursor */ ){ BtShared *pBt = p->pBt; /* Shared b-tree handle */ + BtCursor *pX; /* Looping over other all cursors */ assert( sqlite3BtreeHoldsMutex(p) ); assert( wrFlag==0 || wrFlag==1 ); @@ -4051,10 +4063,15 @@ static int btreeCursor( assert( wrFlag==0 || wrFlag==BTCF_WriteFlag ); pCur->curFlags = wrFlag; pCur->curPagerFlags = wrFlag ? 0 : PAGER_GET_READONLY; - pCur->pNext = pBt->pCursor; - if( pCur->pNext ){ - pCur->pNext->pPrev = pCur; + /* If there are two or more cursors on the same btree, then all such + ** cursors *must* have the BTCF_Multiple flag set. */ + for(pX=pBt->pCursor; pX; pX=pX->pNext){ + if( pX->pgnoRoot==(Pgno)iTable ){ + pX->curFlags |= BTCF_Multiple; + pCur->curFlags |= BTCF_Multiple; + } } + pCur->pNext = pBt->pCursor; pBt->pCursor = pCur; pCur->eState = CURSOR_INVALID; return SQLITE_OK; @@ -4112,13 +4129,18 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){ BtShared *pBt = pCur->pBt; sqlite3BtreeEnter(pBtree); sqlite3BtreeClearCursor(pCur); - if( pCur->pPrev ){ - pCur->pPrev->pNext = pCur->pNext; - }else{ + assert( pBt->pCursor!=0 ); + if( pBt->pCursor==pCur ){ pBt->pCursor = pCur->pNext; - } - if( pCur->pNext ){ - pCur->pNext->pPrev = pCur->pPrev; + }else{ + BtCursor *pPrev = pBt->pCursor; + do{ + if( pPrev->pNext==pCur ){ + pPrev->pNext = pCur->pNext; + break; + } + pPrev = pPrev->pNext; + }while( ALWAYS(pPrev) ); } for(i=0; i<=pCur->iPage; i++){ releasePage(pCur->apPage[i]); @@ -7895,8 +7917,10 @@ int sqlite3BtreeInsert( ** doing any work. To avoid thwarting these optimizations, it is important ** not to clear the cursor here. */ - rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); - if( rc ) return rc; + if( pCur->curFlags & BTCF_Multiple ){ + rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); + if( rc ) return rc; + } if( pCur->pKeyInfo==0 ){ assert( pKey==0 ); @@ -8042,8 +8066,10 @@ int sqlite3BtreeDelete(BtCursor *pCur){ ** deleted writable. Then free any overflow pages associated with the ** entry and finally remove the cell itself from within the page. */ - rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); - if( rc ) return rc; + if( pCur->curFlags & BTCF_Multiple ){ + rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur); + if( rc ) return rc; + } /* If this is a delete operation to remove a row from a table b-tree, ** invalidate any incrblob cursors open on the row being deleted. */ diff --git a/src/btreeInt.h b/src/btreeInt.h index 70aa937c7d..92a4d44692 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -507,7 +507,7 @@ struct CellInfo { struct BtCursor { Btree *pBtree; /* The Btree to which this cursor belongs */ BtShared *pBt; /* The BtShared this cursor points to */ - BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */ + BtCursor *pNext; /* Forms a linked list of all cursors */ Pgno *aOverflow; /* Cache of overflow page locations */ CellInfo info; /* A parse of the cell we are pointing at */ i64 nKey; /* Size of pKey, or last integer key */ @@ -526,6 +526,7 @@ struct BtCursor { i8 iPage; /* Index of current page in apPage */ u8 curIntKey; /* Value of apPage[0]->intKey */ struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */ + void *padding1; /* Make object size a multiple of 16 */ u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */ MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */ }; @@ -538,6 +539,7 @@ struct BtCursor { #define BTCF_ValidOvfl 0x04 /* True if aOverflow is valid */ #define BTCF_AtLast 0x08 /* Cursor is pointing ot the last entry */ #define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */ +#define BTCF_Multiple 0x20 /* Maybe another cursor on the same btree */ /* ** Potential values for BtCursor.eState.