diff options
author | drh <drh@noemail.net> | 2007-08-28 22:24:34 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2007-08-28 22:24:34 +0000 |
commit | d0679edc7a9a41b43ad2984be17a10046b1516c9 (patch) | |
tree | 9b6f17d0d579638fff5f5a4c0b3204c2ec40826f | |
parent | 27a770e044318084cb9640315d83a20bd34d4106 (diff) | |
download | sqlite-d0679edc7a9a41b43ad2984be17a10046b1516c9.tar.gz sqlite-d0679edc7a9a41b43ad2984be17a10046b1516c9.zip |
Clean up the locking in the btree logic. (CVS 4316)
FossilOrigin-Name: 967ab229af462a8ae663090ea36b4cc10e351653
-rw-r--r-- | manifest | 32 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/btree.c | 168 | ||||
-rw-r--r-- | src/btreeInt.h | 12 | ||||
-rw-r--r-- | src/build.c | 4 | ||||
-rw-r--r-- | src/mutex_unix.c | 20 | ||||
-rw-r--r-- | src/pager.c | 9 | ||||
-rw-r--r-- | src/pager.h | 3 | ||||
-rw-r--r-- | src/vdbe.h | 4 | ||||
-rw-r--r-- | src/vdbeInt.h | 1 | ||||
-rw-r--r-- | src/vdbeaux.c | 15 | ||||
-rw-r--r-- | test/shared_err.test | 3 |
12 files changed, 165 insertions, 108 deletions
@@ -1,5 +1,5 @@ -C Fix\smemory\sleak\sof\sInteriorReader.term.\s\sComes\sup\swhen\sdoing\squeries\nagainst\slarge\ssegments.\s(CVS\s4315) -D 2007-08-28T20:36:54 +C Clean\sup\sthe\slocking\sin\sthe\sbtree\slogic.\s(CVS\s4316) +D 2007-08-28T22:24:35 F Makefile.in bfcc303429a5d9dcd552d807ee016c77427418c3 F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -81,10 +81,10 @@ F src/analyze.c a14237d869c6bea0846493b59317e4097e81a0b6 F src/attach.c a52225c75b107be8c5bc144a2b6d20201be3f8f8 F src/auth.c 083c1205b45e3f52291ec539d396b4fc557856b3 F src/btmutex.c 3a19fcb311d0d09e63d397779be881d4273f4518 -F src/btree.c 850cd5de860e01233153ade9b24ffc775a794e8e +F src/btree.c 8796aa42fd16feb587844489a0fce8c66e52ac02 F src/btree.h a8fb26c56b745b57446c2bf29133619261313051 -F src/btreeInt.h c1ba892252bc4dd76ad66da056536c64b23456e3 -F src/build.c 08001e8a12b06178193dc4a8f24610f58de80dae +F src/btreeInt.h 5b1bc919cb80f0dd6baec1cdbae737f9806a7e3b +F src/build.c 99b0b0c44ce7673c00d8c0c97ce536e3b796328b F src/callback.c a542236a68060caad378efa30006ca46cf77b1b2 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 F src/date.c af235f38f50809abd0a96da3bb3e0cc32be6226e @@ -107,7 +107,7 @@ F src/mem2.c 1a2ca756a285b5365d667841508cc1f98938b8d8 F src/mutex.c 40e5ba09d56863895882a0204d93832e9960ea78 F src/mutex.h 4d3babe3a691533ac980967d394da512140b5143 F src/mutex_os2.c d47e9bd495583dd31263d8fe55160a31eb600a3c -F src/mutex_unix.c 84ae0344b0bd6591e3bfea2cb6d375233d39f8a4 +F src/mutex_unix.c ff77650261a245035b79c5c8a174f4e05d3cae8a F src/mutex_w32.c 8716478c5f1829b27fd2c9a0759230a9dc3aa9e3 F src/os.c a8ed3c495161475dbce255f7003144144fb425f1 F src/os.h 2bfbbad126a775e4d8c7d59eb4d9585a5fd7dfb5 @@ -120,8 +120,8 @@ F src/os_unix.c 89bf24aa2475048a7833c45c522e7c6a81b83bb8 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e F src/os_win.c 3ffd3aacff4cb69848284e29dcec0feff23b0752 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c 51ca27639ab25c8838afc856d3cc6045a98752a7 -F src/pager.h 53087c6fb9db01aed17c7fd044662a27507e89b8 +F src/pager.c 97fd0bb853e01e6890ad9aae97e7f9155330ebdc +F src/pager.h a9872db184613ae90ae80921f5fd956aa8f3522e F src/parse.y 2d2ce439dc6184621fb0b86f4fc5aca7f391a590 F src/pragma.c 9b989506a1b7c8aecd6befb8235e2f57a4aba7e5 F src/prepare.c 29ea14cf6b0558f2f80aa53e112bff55f1119e36 @@ -163,10 +163,10 @@ F src/utf.c 4af6259d5906b5a1bf3035cc387c4d7907bdd56e F src/util.c 3f9c0387b54f977726790f52ab92cd3d9379b367 F src/vacuum.c 5ec133b69edf581a232af7e2b01f45c9f2b8be32 F src/vdbe.c 62d210babaac906a5847d7bd4c71e7b114595e85 -F src/vdbe.h 5b3ee0fd91a08579f514713038fa7dbef9edf407 -F src/vdbeInt.h 0681e0b74a43d3adfec65780d73b2db8f826c7c9 +F src/vdbe.h 498e9ddade4baf70f2fc39e585670131dde07caa +F src/vdbeInt.h a9dcd0688783abbd60981aff7ecc5b57a9559765 F src/vdbeapi.c bdd0aea216744482dd1b7fab56de18ba5b6fbdf4 -F src/vdbeaux.c bffdf7b69de21a70520260d359e19df64f31aea4 +F src/vdbeaux.c 0bbc8fbb6bcd610e98ce8eef77d0db660710f9dd F src/vdbeblob.c d12ed95dac0992e1e372d079d76af047cc42f7c7 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6 F src/vdbemem.c 896fa3f8df9d2661eb15c7ce361857741b447268 @@ -403,7 +403,7 @@ F test/server1.test e328b8e641ba8fe9273132cfef497383185dc1f5 F test/shared.test 08b30d5f1939efff0517e7ff8ec7b74ad31c151b F test/shared2.test 0ee9de8964d70e451936a48c41cb161d9134ccf4 F test/shared3.test 01e3e124dbb3859788aabc7cfb82f7ea04421749 -F test/shared_err.test 9fa070e3e7d63022a81b6156ac71f114c0678e3d +F test/shared_err.test 99d3d87924cedc1db2233ef59f38c389dd358698 F test/soak.test 64f9b27fbcdec43335a88c546ce1983e6ba40d7b F test/softheap1.test 0c49aa6eee25e7d32943e85e8d1f20eff566b1dc F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5 @@ -567,7 +567,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P dd43a2de3ed1659d70361370d07a184dd8ece45f -R 70912c36e1c512cb72f986c6f3262b7a -U shess -Z e249b078ef5ae37e1d80116148f5bc5a +P 6c617bd89fc57881a2a308a6360e8ebb42835d46 +R 45b11caba5c119849cdae69b051cb491 +U drh +Z 8c8847e04e8b6bae7d208c08aa3c66c5 diff --git a/manifest.uuid b/manifest.uuid index 620cbac58..849256d4c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6c617bd89fc57881a2a308a6360e8ebb42835d46
\ No newline at end of file +967ab229af462a8ae663090ea36b4cc10e351653
\ No newline at end of file diff --git a/src/btree.c b/src/btree.c index cd7b3e1a5..af8edac35 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.413 2007/08/28 02:27:52 drh Exp $ +** $Id: btree.c,v 1.414 2007/08/28 22:24:35 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -96,6 +96,7 @@ static int queryTableLock(Btree *p, Pgno iTab, u8 eLock){ BtShared *pBt = p->pBt; BtLock *pIter; + assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); assert( sqlite3BtreeMutexHeld(pBt->mutex) ); /* This is a no-op if the shared-cache is not enabled */ @@ -148,6 +149,7 @@ static int lockTable(Btree *p, Pgno iTable, u8 eLock){ BtLock *pLock = 0; BtLock *pIter; + assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); assert( sqlite3BtreeMutexHeld(pBt->mutex) ); /* This is a no-op if the shared-cache is not enabled */ @@ -214,6 +216,7 @@ static int lockTable(Btree *p, Pgno iTable, u8 eLock){ static void unlockAllTables(Btree *p){ BtLock **ppIter = &p->pBt->pLock; + assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); assert( sqlite3BtreeMutexHeld(p->pBt->mutex) ); assert( p->sharable || 0==*ppIter ); @@ -236,6 +239,7 @@ static void releasePage(MemPage *pPage); /* Forward reference */ ** Invalidate the overflow page-list cache for cursor pCur, if any. */ static void invalidateOverflowCache(BtCursor *pCur){ + assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); sqlite3_free(pCur->aOverflow); pCur->aOverflow = 0; } @@ -265,7 +269,7 @@ static int saveCursorPosition(BtCursor *pCur){ assert( CURSOR_VALID==pCur->eState ); assert( 0==pCur->pKey ); - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); + assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); @@ -308,6 +312,7 @@ static int saveCursorPosition(BtCursor *pCur){ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ BtCursor *p; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( pExcept==0 || pExcept->pBt==pBt ); for(p=pBt->pCursor; p; p=p->pNext){ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) && p->eState==CURSOR_VALID ){ @@ -324,7 +329,7 @@ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ ** Clear the current cursor position. */ static void clearCursorPosition(BtCursor *pCur){ - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); + assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); sqlite3_free(pCur->pKey); pCur->pKey = 0; pCur->eState = CURSOR_INVALID; @@ -343,6 +348,7 @@ static void clearCursorPosition(BtCursor *pCur){ */ int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){ int rc; + assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); assert( pCur->eState==CURSOR_REQUIRESEEK ); #ifndef SQLITE_OMIT_INCRBLOB if( pCur->isIncrblobHandle ){ @@ -1052,9 +1058,11 @@ static void pageDestructor(DbPage *pData, int pageSize){ MemPage *pPage; assert( (pageSize & 7)==0 ); pPage = (MemPage *)sqlite3PagerGetExtra(pData); + assert( pPage->isInit==0 || sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); if( pPage->pParent ){ MemPage *pParent = pPage->pParent; - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( pPage->isInit==1 ); + assert( pParent->pBt==pPage->pBt ); pPage->pParent = 0; releasePage(pParent); } @@ -1115,13 +1123,10 @@ int sqlite3BtreeOpen( #endif #endif - if( pSqlite ){ - pVfs = pSqlite->pVfs; - }else{ - pVfs = sqlite3_vfs_find(0); - } - assert( sqlite3BtreeMutexHeld(pSqlite->mutex) ); + assert( pSqlite!=0 ); + assert( sqlite3_mutex_held(pSqlite->mutex) ); + pVfs = pSqlite->pVfs; p = sqlite3MallocZero(sizeof(Btree)); if( !p ){ return SQLITE_NOMEM; @@ -1136,7 +1141,7 @@ int sqlite3BtreeOpen( */ if( (flags & BTREE_PRIVATE)==0 && isMemdb==0 - && (pSqlite==0 || (pSqlite->flags &SQLITE_Vtab)==0) + && (pSqlite->flags & SQLITE_Vtab)==0 && zFilename && zFilename[0] && sqlite3SharedCacheEnabled ){ @@ -1155,7 +1160,8 @@ int sqlite3BtreeOpen( sqlite3_mutex_enter(mutexShared); for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){ assert( pBt->nRef>0 ); - if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager)) ){ + if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager)) + && sqlite3PagerVfs(pBt->pPager)==pVfs ){ p->pBt = pBt; pBt->nRef++; break; @@ -1338,6 +1344,7 @@ int sqlite3BtreeClose(Btree *p){ BtCursor *pCur; /* Close all cursors opened via this handle. */ + assert( sqlite3_mutex_held(p->pSqlite->mutex) ); sqlite3BtreeEnter(p); pCur = pBt->pCursor; while( pCur ){ @@ -1390,12 +1397,8 @@ int sqlite3BtreeClose(Btree *p){ /* ** Short-cuts for entering and leaving mutexes on a cursor. */ -static void cursorLeave(BtCursor *p){ - sqlite3BtreeLeave(p->pBtree); -} -static void cursorEnter(BtCursor *pCur){ - sqlite3BtreeEnter(pCur->pBtree); -} +# define cursorEnter(X) assert( sqlite3_mutex_held(X->pBt->mutex) ) +# define cursorLeave(X) #else # define cursorEnter(X) # define cursorLeave(X) @@ -1406,6 +1409,7 @@ static void cursorEnter(BtCursor *pCur){ */ int sqlite3BtreeSetBusyHandler(Btree *p, BusyHandler *pHandler){ BtShared *pBt = p->pBt; + assert( sqlite3_mutex_held(p->pSqlite->mutex) ); sqlite3BtreeEnter(p); pBt->pBusyHandler = pHandler; sqlite3PagerSetBusyhandler(pBt->pPager, pHandler); @@ -1430,6 +1434,7 @@ int sqlite3BtreeSetBusyHandler(Btree *p, BusyHandler *pHandler){ */ int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ BtShared *pBt = p->pBt; + assert( sqlite3_mutex_held(p->pSqlite->mutex) ); sqlite3BtreeEnter(p); sqlite3PagerSetCachesize(pBt->pPager, mxPage); sqlite3BtreeLeave(p); @@ -1447,6 +1452,7 @@ int sqlite3BtreeSetCacheSize(Btree *p, int mxPage){ #ifndef SQLITE_OMIT_PAGER_PRAGMAS int sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync){ BtShared *pBt = p->pBt; + assert( sqlite3_mutex_held(p->pSqlite->mutex) ); sqlite3BtreeEnter(p); sqlite3PagerSetSafetyLevel(pBt->pPager, level, fullSync); sqlite3BtreeLeave(p); @@ -1461,8 +1467,9 @@ int sqlite3BtreeSetSafetyLevel(Btree *p, int level, int fullSync){ int sqlite3BtreeSyncDisabled(Btree *p){ BtShared *pBt = p->pBt; int rc; - assert( pBt && pBt->pPager ); + assert( sqlite3_mutex_held(p->pSqlite->mutex) ); sqlite3BtreeEnter(p); + assert( pBt && pBt->pPager ); rc = sqlite3PagerNosync(pBt->pPager); sqlite3BtreeLeave(p); return rc; @@ -1986,6 +1993,7 @@ static int relocatePage( assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( pDbPage->pBt==pBt ); /* Move page iDbPage from it's current location to page number iFreePage */ TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", @@ -2595,6 +2603,7 @@ static int btreeCursor( BtShared *pBt = p->pBt; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); *ppCur = 0; if( wrFlag ){ if( pBt->readOnly ){ @@ -2636,6 +2645,7 @@ static int btreeCursor( pCur->xCompare = xCmp ? xCmp : dfltCompare; pCur->pArg = pArg; pCur->pBtree = p; + pCur->pBt = pBt; pCur->wrFlag = wrFlag; pCur->pNext = pBt->pCursor; if( pCur->pNext ){ @@ -2676,9 +2686,10 @@ int sqlite3BtreeCursor( ** when the last cursor is closed. */ int sqlite3BtreeCloseCursor(BtCursor *pCur){ - BtShared *pBt = pCur->pBtree->pBt; + BtShared *pBt = pCur->pBt; - cursorEnter(pCur); + assert( sqlite3_mutex_held(pCur->pBt->mutex) ); + assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) ); clearCursorPosition(pCur); if( pCur->pPrev ){ pCur->pPrev->pNext = pCur->pNext; @@ -2691,7 +2702,6 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){ releasePage(pCur->pPage); unlockBtreeIfUnused(pBt); invalidateOverflowCache(pCur); - cursorLeave(pCur); sqlite3_free(pCur); return SQLITE_OK; } @@ -2701,14 +2711,14 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){ ** The temporary cursor is not on the cursor list for the Btree. */ void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur){ + cursorEnter(pCur); memcpy(pTempCur, pCur, sizeof(*pCur)); pTempCur->pNext = 0; pTempCur->pPrev = 0; if( pTempCur->pPage ){ - cursorEnter(pCur); sqlite3PagerRef(pTempCur->pPage->pDbPage); - cursorLeave(pCur); } + cursorLeave(pCur); } /* @@ -2716,11 +2726,11 @@ void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur){ ** function above. */ void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ + cursorEnter(pCur); if( pCur->pPage ){ - cursorEnter(pCur); sqlite3PagerUnref(pCur->pPage->pDbPage); - cursorLeave(pCur); } + cursorLeave(pCur); } /* @@ -2778,7 +2788,7 @@ void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ int rc; - sqlite3BtreeEnter(pCur->pBtree); + assert( sqlite3_mutex_held(pCur->pBt->mutex) ); rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); @@ -2789,7 +2799,6 @@ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ *pSize = pCur->info.nKey; } } - sqlite3BtreeLeave(pCur->pBtree); return rc; } @@ -2803,7 +2812,7 @@ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ int rc; - sqlite3BtreeEnter(pCur->pBtree); + assert( sqlite3_mutex_held(pCur->pBt->mutex) ); rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); @@ -2815,7 +2824,6 @@ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ *pSize = pCur->info.nData; } } - sqlite3BtreeLeave(pCur->pBtree); return rc; } @@ -2978,14 +2986,14 @@ static int accessPayload( int rc = SQLITE_OK; u32 nKey; int iIdx = 0; - MemPage *pPage = pCur->pPage; /* Btree page of current cursor entry */ - BtShared *pBt = pCur->pBtree->pBt; /* Btree this cursor belongs to */ + MemPage *pPage = pCur->pPage; /* Btree page of current cursor entry */ + BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */ assert( pPage ); assert( pCur->eState==CURSOR_VALID ); assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); assert( offset>=0 ); - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); + assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); getCellInfo(pCur); aPayload = pCur->info.pCell + pCur->info.nHeader; @@ -3111,20 +3119,20 @@ static int accessPayload( int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ int rc; - sqlite3BtreeEnter(pCur->pBtree); + cursorEnter(pCur); rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->pPage!=0 ); if( pCur->pPage->intKey ){ - sqlite3BtreeLeave(pCur->pBtree); + cursorLeave(pCur); return SQLITE_CORRUPT_BKPT; } assert( pCur->pPage->intKey==0 ); assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell ); rc = accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0, 0); } - sqlite3BtreeLeave(pCur->pBtree); + cursorLeave(pCur); return rc; } @@ -3140,7 +3148,7 @@ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ int rc; - sqlite3BtreeEnter(pCur->pBtree); + cursorEnter(pCur); rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); @@ -3148,7 +3156,7 @@ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell ); rc = accessPayload(pCur, offset, amt, pBuf, 1, 0); } - sqlite3BtreeLeave(pCur->pBtree); + cursorLeave(pCur); return rc; } @@ -3183,7 +3191,7 @@ static const unsigned char *fetchPayload( assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->eState==CURSOR_VALID ); - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); + assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); pPage = pCur->pPage; assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); getCellInfo(pCur); @@ -3223,14 +3231,14 @@ static const unsigned char *fetchPayload( ** in the common case where no overflow pages are used. */ const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int *pAmt){ - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); + assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); if( pCur->eState==CURSOR_VALID ){ return (const void*)fetchPayload(pCur, pAmt, 0); } return 0; } const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){ - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); + assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); if( pCur->eState==CURSOR_VALID ){ return (const void*)fetchPayload(pCur, pAmt, 1); } @@ -3246,7 +3254,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ int rc; MemPage *pNewPage; MemPage *pOldPage; - BtShared *pBt = pCur->pBtree->pBt; + BtShared *pBt = pCur->pBt; assert( sqlite3BtreeMutexHeld(pBt->mutex) ); assert( pCur->eState==CURSOR_VALID ); @@ -3298,7 +3306,7 @@ void sqlite3BtreeMoveToParent(BtCursor *pCur){ MemPage *pPage; int idxParent; - sqlite3BtreeEnter(pCur->pBtree); + cursorEnter(pCur); assert( pCur->eState==CURSOR_VALID ); pPage = pCur->pPage; assert( pPage!=0 ); @@ -3312,7 +3320,7 @@ void sqlite3BtreeMoveToParent(BtCursor *pCur){ pCur->info.nSize = 0; assert( pParent->idxShift==0 ); pCur->idx = idxParent; - sqlite3BtreeLeave(pCur->pBtree); + cursorLeave(pCur); } /* @@ -3324,7 +3332,6 @@ static int moveToRoot(BtCursor *pCur){ Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; - assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); assert( sqlite3BtreeMutexHeld(pBt->mutex) ); if( pCur->eState==CURSOR_REQUIRESEEK ){ clearCursorPosition(pCur); @@ -3368,8 +3375,7 @@ static int moveToLeftmost(BtCursor *pCur){ int rc = SQLITE_OK; MemPage *pPage; - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); + assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); assert( pCur->eState==CURSOR_VALID ); while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); @@ -3394,8 +3400,7 @@ static int moveToRightmost(BtCursor *pCur){ int rc = SQLITE_OK; MemPage *pPage; - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); + assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); assert( pCur->eState==CURSOR_VALID ); while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); @@ -3416,7 +3421,7 @@ static int moveToRightmost(BtCursor *pCur){ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ int rc; - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); + assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ @@ -3440,7 +3445,7 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ int rc; - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); + assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ @@ -3493,7 +3498,7 @@ int sqlite3BtreeMoveto( ){ int rc; - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); + assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); rc = moveToRoot(pCur); if( rc ){ @@ -3621,6 +3626,7 @@ int sqlite3BtreeEof(BtCursor *pCur){ ** Return the database connection handle for a cursor. */ sqlite3 *sqlite3BtreeCursorDb(const BtCursor *pCur){ + assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) ); return pCur->pBtree->pSqlite; } @@ -3634,6 +3640,7 @@ static int btreeNext(BtCursor *pCur, int *pRes){ int rc; MemPage *pPage; + assert( sqlite3_mutex_held(pCur->pBt->mutex) ); rc = restoreOrClearCursorPosition(pCur); if( rc!=SQLITE_OK ){ return rc; @@ -3708,6 +3715,7 @@ static int btreePrevious(BtCursor *pCur, int *pRes){ Pgno pgno; MemPage *pPage; + assert( sqlite3_mutex_held(pCur->pBt->mutex) ); rc = restoreOrClearCursorPosition(pCur); if( rc!=SQLITE_OK ){ return rc; @@ -5486,20 +5494,20 @@ int sqlite3BtreeInsert( unsigned char *oldCell; unsigned char *newCell = 0; - sqlite3BtreeEnter(p); + cursorEnter(pCur); if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction before doing an insert */ rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; - sqlite3BtreeLeave(p); + cursorLeave(pCur); return rc; } assert( !pBt->readOnly ); if( !pCur->wrFlag ){ - sqlite3BtreeLeave(p); + cursorLeave(pCur); return SQLITE_PERM; /* Cursor not open for writing */ } if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){ - sqlite3BtreeLeave(p); + cursorLeave(pCur); return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } @@ -5509,7 +5517,7 @@ int sqlite3BtreeInsert( SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc)) ){ - sqlite3BtreeLeave(p); + cursorLeave(pCur); return rc; } @@ -5558,7 +5566,7 @@ int sqlite3BtreeInsert( } end_insert: sqlite3_free(newCell); - sqlite3BtreeLeave(p); + cursorLeave(pCur); return rc; } @@ -5574,25 +5582,25 @@ int sqlite3BtreeDelete(BtCursor *pCur){ Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; - sqlite3BtreeEnter(p); + cursorEnter(pCur); assert( pPage->isInit ); if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction before doing a delete */ rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; - sqlite3BtreeLeave(p); + cursorLeave(pCur); return rc; } assert( !pBt->readOnly ); if( pCur->idx >= pPage->nCell ){ - sqlite3BtreeLeave(p); + cursorLeave(pCur); return SQLITE_ERROR; /* The cursor is not pointing to anything */ } if( !pCur->wrFlag ){ - sqlite3BtreeLeave(p); + cursorLeave(pCur); return SQLITE_PERM; /* Did not open this cursor for writing */ } if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){ - sqlite3BtreeLeave(p); + cursorLeave(pCur); return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } @@ -5606,7 +5614,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){ (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur))!=0 || (rc = sqlite3PagerWrite(pPage->pDbPage))!=0 ){ - sqlite3BtreeLeave(p); + cursorLeave(pCur); return rc; } @@ -5620,7 +5628,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){ } rc = clearCell(pPage, pCell); if( rc ){ - sqlite3BtreeLeave(p); + cursorLeave(pCur); return rc; } @@ -5679,7 +5687,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){ if( rc==SQLITE_OK ){ moveToRoot(pCur); } - sqlite3BtreeLeave(p); + cursorLeave(pCur); return rc; } @@ -5700,6 +5708,8 @@ static int btreeCreateTable(Btree *p, int *piTable, int flags){ Pgno pgnoRoot; int rc; + assert( sqlite3_mutex_held(p->pSqlite->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction first */ rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; @@ -6131,6 +6141,7 @@ int sqlite3BtreeFlags(BtCursor *pCur){ */ MemPage *pPage = pCur->pPage; assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( pPage->pBt==pCur->pBt ); return pPage ? pPage->aData[pPage->hdrOffset] : 0; } @@ -6140,8 +6151,6 @@ int sqlite3BtreeFlags(BtCursor *pCur){ ** testing and debugging only. */ Pager *sqlite3BtreePager(Btree *p){ - assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); - assert( sqlite3BtreeMutexHeld(p->pBt->mutex) ); return p->pBt->pPager; } @@ -6585,17 +6594,25 @@ char *sqlite3BtreeIntegrityCheck( /* ** Return the full pathname of the underlying database file. +** +** The pager filename is invariant as long as the pager is +** open so it is safe to access without the BtShared mutex. */ const char *sqlite3BtreeGetFilename(Btree *p){ assert( p->pBt->pPager!=0 ); + assert( sqlite3_mutex_held(p->pSqlite->mutex) ); return sqlite3PagerFilename(p->pBt->pPager); } /* ** Return the pathname of the directory that contains the database file. +** +** The pager directory name is invariant as long as the pager is +** open so it is safe to access without the BtShared mutex. */ const char *sqlite3BtreeGetDirname(Btree *p){ assert( p->pBt->pPager!=0 ); + assert( sqlite3_mutex_held(p->pSqlite->mutex) ); return sqlite3PagerDirname(p->pBt->pPager); } @@ -6603,9 +6620,13 @@ const char *sqlite3BtreeGetDirname(Btree *p){ ** Return the pathname of the journal file for this database. The return ** value of this routine is the same regardless of whether the journal file ** has been created or not. +** +** The pager journal filename is invariant as long as the pager is +** open so it is safe to access without the BtShared mutex. */ const char *sqlite3BtreeGetJournalname(Btree *p){ assert( p->pBt->pPager!=0 ); + assert( sqlite3_mutex_held(p->pSqlite->mutex) ); return sqlite3PagerJournalname(p->pBt->pPager); } @@ -6685,7 +6706,7 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ ** Return non-zero if a transaction is active. */ int sqlite3BtreeIsInTrans(Btree *p){ - assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); + assert( p==0 || sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); return (p && (p->inTrans==TRANS_WRITE)); } @@ -6724,7 +6745,6 @@ int sqlite3BtreeIsInReadTrans(Btree *p){ */ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ BtShared *pBt = p->pBt; - assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); sqlite3BtreeEnter(p); if( !pBt->pSchema ){ pBt->pSchema = sqlite3MallocZero(nBytes); @@ -6776,7 +6796,7 @@ int sqlite3BtreeLockTable(Btree *p, int iTab, u8 isWriteLock){ ** to change the length of the data stored. */ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ - assert( sqlite3BtreeMutexHeld(pCsr->pBtree->pBt->mutex) ); + assert( sqlite3BtreeMutexHeld(pCsr->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCsr->pBtree->pSqlite->mutex) ); assert(pCsr->isIncrblobHandle); if( pCsr->eState==CURSOR_REQUIRESEEK ){ @@ -6791,8 +6811,8 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ if( !pCsr->wrFlag ){ return SQLITE_READONLY; } - assert( !pCsr->pBtree->pBt->readOnly - && pCsr->pBtree->pBt->inTransaction==TRANS_WRITE ); + assert( !pCsr->pBt->readOnly + && pCsr->pBt->inTransaction==TRANS_WRITE ); if( checkReadLocks(pCsr->pBtree, pCsr->pgnoRoot, pCsr) ){ return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } @@ -6814,7 +6834,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ ** sqlite3BtreePutData()). */ void sqlite3BtreeCacheOverflow(BtCursor *pCur){ - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pBt->mutex) ); + assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); assert(!pCur->isIncrblobHandle); assert(!pCur->aOverflow); diff --git a/src/btreeInt.h b/src/btreeInt.h index a491c8a2f..47f78ca02 100644 --- a/src/btreeInt.h +++ b/src/btreeInt.h @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btreeInt.h,v 1.10 2007/08/27 21:49:34 drh Exp $ +** $Id: btreeInt.h,v 1.11 2007/08/28 22:24:35 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -318,7 +318,11 @@ struct MemPage { ** schema associated with the database file are all contained within ** the BtShared object. ** -** All fields in this structure are accessed under the sqlite3.mutex. +** All fields in this structure are accessed under sqlite3.mutex. +** The pBt pointer itself may not be changed while there exists cursors +** in the referenced BtShared that point back to this Btree since those +** cursors have to do go through this Btree to find their BtShared and +** they often do so without holding sqlite3.mutex. */ struct Btree { sqlite3 *pSqlite; /* The database connection holding this btree */ @@ -419,11 +423,11 @@ struct CellInfo { ** particular database connection identified BtCursor.pBtree.pSqlite. ** ** Fields in this structure are accessed under the BtShared.mutex -** mutex. The pBtree field is safe to access under the -** BtShared->pBtree->pSqlite->mutex mutex. +** found at self->pBt->mutex. */ 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 */ int (*xCompare)(void*,int,const void*,int,const void*); /* Key comp func */ void *pArg; /* First arg to xCompare() */ diff --git a/src/build.c b/src/build.c index a3cb28067..8369df50b 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.439 2007/08/28 02:27:52 drh Exp $ +** $Id: build.c,v 1.440 2007/08/28 22:24:35 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -164,7 +164,7 @@ void sqlite3FinishCoding(Parse *pParse){ sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){ if( (mask & pParse->cookieMask)==0 ) continue; - sqlite3VdbeAddMutexBtree(v, db->aDb[iDb].pBt); + sqlite3VdbeUsesBtree(v, iDb, db->aDb[iDb].pBt); sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0); sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); } diff --git a/src/mutex_unix.c b/src/mutex_unix.c index 287a173c5..ff088fb53 100644 --- a/src/mutex_unix.c +++ b/src/mutex_unix.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains the C functions that implement mutexes for pthreads ** -** $Id: mutex_unix.c,v 1.1 2007/08/28 16:34:43 drh Exp $ +** $Id: mutex_unix.c,v 1.2 2007/08/28 22:24:35 drh Exp $ */ #include "sqliteInt.h" @@ -34,6 +34,9 @@ struct sqlite3_mutex { int id; /* Mutex type */ int nRef; /* Number of entrances */ pthread_t owner; /* Thread that is within this mutex */ +#ifdef SQLITE_DEBUG + int trace; /* True to trace changes */ +#endif }; /* @@ -149,6 +152,11 @@ void sqlite3_mutex_enter(sqlite3_mutex *p){ pthread_mutex_lock(&p->mutex); p->owner = pthread_self(); p->nRef++; +#ifdef SQLITE_DEBUG + if( p->trace ){ + printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); + } +#endif } int sqlite3_mutex_try(sqlite3_mutex *p){ int rc; @@ -158,6 +166,11 @@ int sqlite3_mutex_try(sqlite3_mutex *p){ p->owner = pthread_self(); p->nRef++; rc = SQLITE_OK; +#ifdef SQLITE_DEBUG + if( p->trace ){ + printf("enter mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); + } +#endif }else{ rc = SQLITE_BUSY; } @@ -175,6 +188,11 @@ void sqlite3_mutex_leave(sqlite3_mutex *p){ assert( sqlite3_mutex_held(p) ); p->nRef--; assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE ); +#ifdef SQLITE_DEBUG + if( p->trace ){ + printf("leave mutex %p (%d) with nRef=%d\n", p, p->trace, p->nRef); + } +#endif pthread_mutex_unlock(&p->mutex); } diff --git a/src/pager.c b/src/pager.c index a2595243b..9bbb640ea 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.378 2007/08/28 08:00:18 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.379 2007/08/28 22:24:35 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -4797,6 +4797,13 @@ const char *sqlite3PagerFilename(Pager *pPager){ } /* +** Return the VFS structure for the pager. +*/ +const sqlite3_vfs *sqlite3PagerVfs(Pager *pPager){ + return pPager->pVfs; +} + +/* ** Return the directory of the database file. */ const char *sqlite3PagerDirname(Pager *pPager){ diff --git a/src/pager.h b/src/pager.h index 554c4999a..41d7f66c8 100644 --- a/src/pager.h +++ b/src/pager.h @@ -13,7 +13,7 @@ ** subsystem. The page cache subsystem reads and writes a file a page ** at a time and provides a journal for rollback. ** -** @(#) $Id: pager.h,v 1.62 2007/08/17 15:53:37 danielk1977 Exp $ +** @(#) $Id: pager.h,v 1.63 2007/08/28 22:24:35 drh Exp $ */ #ifndef _PAGER_H_ @@ -85,6 +85,7 @@ void sqlite3PagerDontWrite(DbPage*); int sqlite3PagerRefcount(Pager*); void sqlite3PagerSetSafetyLevel(Pager*,int,int); const char *sqlite3PagerFilename(Pager*); +const sqlite3_vfs *sqlite3PagerVfs(Pager*); const char *sqlite3PagerDirname(Pager*); const char *sqlite3PagerJournalname(Pager*); int sqlite3PagerNosync(Pager*); diff --git a/src/vdbe.h b/src/vdbe.h index 0f3500a75..181121385 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -15,7 +15,7 @@ ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.111 2007/08/28 02:27:52 drh Exp $ +** $Id: vdbe.h,v 1.112 2007/08/28 22:24:35 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -120,7 +120,7 @@ void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeJumpHere(Vdbe*, int addr); void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N); void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N); -void sqlite3VdbeAddMutexBtree(Vdbe*, Btree*); +void sqlite3VdbeUsesBtree(Vdbe*, int, Btree*); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeDelete(Vdbe*); diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 78e76c29a..dc1b4b00d 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -332,6 +332,7 @@ struct Vdbe { u8 inVtabMethod; /* See comments above */ int nChange; /* Number of db changes made since last reset */ i64 startTime; /* Time when query started - used for profiling */ + int btreeMask; /* Bitmask of db->aDb[] entries referenced */ BtreeMutexSet mtxSet; /* Set of Btree mutexes */ int nSql; /* Number of bytes in zSql */ char *zSql; /* Text of the SQL statement that generated this */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 80e14b17e..53a43255e 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -659,9 +659,14 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){ #endif /* -** Add a btree to the set of btrees that might need a mutex. +** Declare to the Vdbe that the BTree object at db->aDb[i] is used. +** */ -void sqlite3VdbeAddMutexBtree(Vdbe *p, Btree *pBtree){ +void sqlite3VdbeUsesBtree(Vdbe *p, int i, Btree *pBtree){ + assert( i>=0 && i<p->db->nDb ); + assert( i<sizeof(p->btreeMask)*8 ); + assert( p->db->aDb[i].pBt==pBtree ); + p->btreeMask |= 1<<i; sqlite3BtreeMutexSetInsert(&p->mtxSet, pBtree); } @@ -1091,7 +1096,7 @@ static int vdbeCommit(sqlite3 *db){ */ for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; - if( pBt && sqlite3BtreeIsInTrans(pBt) ){ + if( sqlite3BtreeIsInTrans(pBt) ){ needXcommit = 1; if( i!=1 ) nTrans++; } @@ -1183,7 +1188,7 @@ static int vdbeCommit(sqlite3 *db){ for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( i==1 ) continue; /* Ignore the TEMP database */ - if( pBt && sqlite3BtreeIsInTrans(pBt) ){ + if( sqlite3BtreeIsInTrans(pBt) ){ char const *zFile = sqlite3BtreeGetJournalname(pBt); if( zFile[0]==0 ) continue; /* Ignore :memory: databases */ if( !needSync && !sqlite3BtreeSyncDisabled(pBt) ){ @@ -1225,7 +1230,7 @@ static int vdbeCommit(sqlite3 *db){ */ for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; - if( pBt && sqlite3BtreeIsInTrans(pBt) ){ + if( pBt ){ rc = sqlite3BtreeCommitPhaseOne(pBt, zMaster); } } diff --git a/test/shared_err.test b/test/shared_err.test index 2272cf34b..11cef5a4c 100644 --- a/test/shared_err.test +++ b/test/shared_err.test @@ -13,7 +13,7 @@ # cache context. What happens to connection B if one connection A encounters # an IO-error whilst reading or writing the file-system? # -# $Id: shared_err.test,v 1.12 2007/08/25 13:37:49 danielk1977 Exp $ +# $Id: shared_err.test,v 1.13 2007/08/28 22:24:35 drh Exp $ proc skip {args} {} @@ -156,6 +156,7 @@ do_ioerr_test shared_ioerr-3 -tclprep { sqlite3_step $::STMT ;# Cursor points at 001.001.001.001 } -tclbody { +btree_breakpoint execsql { BEGIN; INSERT INTO t1 VALUES('201.201.201.201.201', NULL); |