diff options
-rw-r--r-- | manifest | 20 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/alter.c | 6 | ||||
-rw-r--r-- | src/analyze.c | 10 | ||||
-rw-r--r-- | src/btmutex.c | 102 | ||||
-rw-r--r-- | src/btree.c | 243 | ||||
-rw-r--r-- | src/btree.h | 9 |
7 files changed, 207 insertions, 185 deletions
@@ -1,5 +1,5 @@ -C More\slocking\sfixes.\s\sNow\smakes\sit\sall\sthe\sway\sthrough\squick.test.\s\sThere\nare\serrors\sbut\sno\sassertion\sfaults.\s\sProgress.\s(CVS\s4319) -D 2007-08-29T00:33:07 +C Better\sasserts().\s\sBut\snow\ssome\sof\sthe\stests\sare\sbusted\sagain.\s(CVS\s4320) +D 2007-08-29T04:00:58 F Makefile.in bfcc303429a5d9dcd552d807ee016c77427418c3 F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -76,13 +76,13 @@ F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2 F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4 F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a -F src/alter.c fd78c6005456c727a6cb7c01c5266f2aacf6d401 -F src/analyze.c a14237d869c6bea0846493b59317e4097e81a0b6 +F src/alter.c 977eeee31adc5c2b7b41c256ccbb84342e7e2ed4 +F src/analyze.c a28b43a5f79bfa7616ab506bb917077242098469 F src/attach.c a52225c75b107be8c5bc144a2b6d20201be3f8f8 F src/auth.c 083c1205b45e3f52291ec539d396b4fc557856b3 -F src/btmutex.c 0abcf98bd6eff466c2c471c96259635169d53981 -F src/btree.c 0241f79766d718d524a28857c3899aee7a728194 -F src/btree.h 21cea6453a7ed73c90535329b44910610f3c635e +F src/btmutex.c c04e67d99d949a12beb17209f307950f21313980 +F src/btree.c f9ea7d1e30d58cb1708aaa0c4c81a2761bd2bd13 +F src/btree.h 7391b9e78ae441fe0fb3a6d3ae772770d35a4375 F src/btreeInt.h 1fa6510aa8601dc0358a5240d191335236d3cf76 F src/build.c 99b0b0c44ce7673c00d8c0c97ce536e3b796328b F src/callback.c a542236a68060caad378efa30006ca46cf77b1b2 @@ -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 f093a0d7b29a819605e0527bf23a047e16c32688 -R 61c7afc6574f5208f9d0bca844fc0424 +P 844d40b8379d3374130e2d94f6e32c2cda34e0ca +R cf2e80aed60a12c772fc5c9b86deea93 U drh -Z b78638b8a0836a1559717f1c34999b51 +Z b6b3d6523c723ce59d75a6cacc6da8b8 diff --git a/manifest.uuid b/manifest.uuid index cfa5f5bc2..fb88b7b37 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -844d40b8379d3374130e2d94f6e32c2cda34e0ca
\ No newline at end of file +e8060f85e7871572e2a38dc96f03e6e1f34cc8fd
\ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 1d0137dd1..bd87bb184 100644 --- a/src/alter.c +++ b/src/alter.c @@ -12,7 +12,7 @@ ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** -** $Id: alter.c,v 1.30 2007/08/25 13:09:26 danielk1977 Exp $ +** $Id: alter.c,v 1.31 2007/08/29 04:00:58 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -234,6 +234,7 @@ static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){ v = sqlite3GetVdbe(pParse); if( !v ) return; + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); assert( iDb>=0 ); @@ -288,6 +289,7 @@ void sqlite3AlterRenameTable( if( db->mallocFailed ) goto exit_rename_table; assert( pSrc->nSrc==1 ); + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase); if( !pTab ) goto exit_rename_table; @@ -446,6 +448,7 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ assert( pNew ); db = pParse->db; + assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pNew->pSchema); zDb = db->aDb[iDb].zName; zTab = pNew->zName; @@ -556,6 +559,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ /* Look up the table being altered. */ assert( pParse->pNewTable==0 ); + assert( sqlite3BtreeHoldsAllMutexes(db) ); if( db->mallocFailed ) goto exit_begin_add_column; pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase); if( !pTab ) goto exit_begin_add_column; diff --git a/src/analyze.c b/src/analyze.c index 497fe7294..ae4b5ceb9 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code associated with the ANALYZE command. ** -** @(#) $Id: analyze.c,v 1.21 2007/08/16 10:09:02 danielk1977 Exp $ +** @(#) $Id: analyze.c,v 1.22 2007/08/29 04:00:58 drh Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" @@ -37,6 +37,8 @@ static void openStatTable( Vdbe *v = sqlite3GetVdbe(pParse); if( v==0 ) return; + assert( sqlite3BtreeHoldsAllMutexes(db) ); + assert( sqlite3VdbeDb(v)==db ); pDb = &db->aDb[iDb]; if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){ /* The sqlite_stat1 tables does not exist. Create it. @@ -100,7 +102,7 @@ static void analyzeOneTable( /* Do no analysis for tables that have no indices */ return; } - + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); assert( iDb>=0 ); #ifndef SQLITE_OMIT_AUTHORIZATION @@ -258,6 +260,7 @@ static void analyzeTable(Parse *pParse, Table *pTab){ int iStatCur; assert( pTab!=0 ); + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema); sqlite3BeginWriteOperation(pParse, 0, iDb); iStatCur = pParse->nTab++; @@ -288,6 +291,7 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ /* Read the database schema. If an error occurs, leave an error message ** and code in pParse and return NULL. */ + assert( sqlite3BtreeHoldsAllMutexes(pParse->db) ); if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){ return; } @@ -382,6 +386,8 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){ char *zSql; int rc; + assert( sqlite3BtreeHoldsAllMutexes(db) ); + /* Clear any prior statistics */ for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){ Index *pIdx = sqliteHashData(i); diff --git a/src/btmutex.c b/src/btmutex.c index b3dbc3641..7df445770 100644 --- a/src/btmutex.c +++ b/src/btmutex.c @@ -10,7 +10,7 @@ ** ************************************************************************* ** -** $Id: btmutex.c,v 1.4 2007/08/29 00:33:07 drh Exp $ +** $Id: btmutex.c,v 1.5 2007/08/29 04:00:58 drh Exp $ ** ** This file contains code used to implement mutexes on Btree objects. ** This code really belongs in btree.c. But btree.c is getting too @@ -55,7 +55,7 @@ void sqlite3BtreeEnter(Btree *p){ assert( p->sharable || p->wantToLock==0 ); /* We should already hold a lock on the database connection */ - assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); + assert( sqlite3_mutex_held(p->pSqlite->mutex) ); if( !p->sharable ) return; p->wantToLock++; @@ -109,6 +109,20 @@ void sqlite3BtreeLeave(Btree *p){ } } +#ifndef NDEBUG +/* +** Return true if a mutex is held on the btree. +** +** This routine is used only from within assert() statements. +*/ +int sqlite3BtreeHoldsMutex(Btree *p){ + return sqlite3_mutex_held(p->pSqlite->mutex) && + (p->sharable==0 || + (p->locked && p->wantToLock && sqlite3_mutex_held(p->pBt->mutex))); +} +#endif + + /* ** Enter the mutex on every Btree associated with a database ** connection. This is needed (for example) prior to parsing @@ -125,24 +139,28 @@ void sqlite3BtreeLeave(Btree *p){ */ void sqlite3BtreeEnterAll(sqlite3 *db){ int i; - Btree *p; + Btree *p, *pLater; assert( sqlite3_mutex_held(db->mutex) ); - for(i=0; i<db->nDb && ((p = db->aDb[i].pBt)==0 || p->sharable==0); i++){} - if( i<db->nDb ){ - while( p->pNext ) p = p->pNext; - while( 1 ){ - if( p->locked ){ - sqlite3_mutex_leave(p->pBt->mutex); - p->locked = 0; - } - if( p->pPrev==0 ) break; - p = p->pPrev; - } - while( p ){ + for(i=0; i<db->nDb; i++){ + p = db->aDb[i].pBt; + if( p && p->sharable ){ p->wantToLock++; - sqlite3_mutex_enter(p->pBt->mutex); - p->locked = 1; - p = p->pNext; + if( !p->locked ){ + assert( p->wantToLock==1 ); + while( p->pPrev ) p = p->pPrev; + while( p->locked && p->pNext ) p = p->pNext; + for(pLater = p->pNext; pLater; pLater=pLater->pNext){ + if( pLater->locked ){ + sqlite3_mutex_leave(pLater->pBt->mutex); + pLater->locked = 0; + } + } + while( p ){ + sqlite3_mutex_enter(p->pBt->mutex); + p->locked++; + p = p->pNext; + } + } } } } @@ -150,20 +168,44 @@ void sqlite3BtreeLeaveAll(sqlite3 *db){ int i; Btree *p; assert( sqlite3_mutex_held(db->mutex) ); - for(i=0; i<db->nDb && ((p = db->aDb[i].pBt)==0 || p->sharable==0); i++){} - if( i<db->nDb ){ - while( p->pPrev ) p = p->pPrev; - while( p ){ + for(i=0; i<db->nDb; i++){ + p = db->aDb[i].pBt; + if( p && p->sharable ){ + assert( p->wantToLock>0 ); p->wantToLock--; if( p->wantToLock==0 ){ + assert( p->locked ); sqlite3_mutex_leave(p->pBt->mutex); p->locked = 0; } - p = p->pNext; } } } +#ifndef NDEBUG +/* +** Return true if the current thread holds the database connection +** mutex and all required BtShared mutexes. +** +** This routine is used inside assert() statements only. +*/ +int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){ + int i; + if( !sqlite3_mutex_held(db->mutex) ){ + return 0; + } + for(i=0; i<db->nDb; i++){ + Btree *p; + p = db->aDb[i].pBt; + if( p && p->sharable && + (p->wantToLock==0 || !sqlite3_mutex_held(p->pBt->mutex)) ){ + return 0; + } + } + return 1; +} +#endif /* NDEBUG */ + /* ** Potentially dd a new Btree pointer to a BtreeMutexArray. ** Really only add the Btree if it can possibly be shared with @@ -180,7 +222,7 @@ void sqlite3BtreeLeaveAll(sqlite3 *db){ void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){ int i, j; BtShared *pBt; - if( !pBtree->sharable ) return; + if( pBtree->sharable==0 ) return; #ifndef NDEBUG { for(i=0; i<pArray->nMutex; i++){ @@ -217,13 +259,12 @@ void sqlite3BtreeMutexArrayEnter(BtreeMutexArray *pArray){ /* Some basic sanity checking */ assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt ); assert( !p->locked || p->wantToLock>0 ); - assert( p->sharable ); /* We should already hold a lock on the database connection */ - assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); + assert( sqlite3_mutex_held(p->pSqlite->mutex) ); p->wantToLock++; - if( !p->locked ){ + if( !p->locked && p->sharable ){ sqlite3_mutex_enter(p->pBt->mutex); p->locked = 1; } @@ -239,15 +280,14 @@ void sqlite3BtreeMutexArrayLeave(BtreeMutexArray *pArray){ Btree *p = pArray->aBtree[i]; /* Some basic sanity checking */ assert( i==0 || pArray->aBtree[i-1]->pBt<p->pBt ); - assert( p->locked ); - assert( p->sharable ); + assert( p->locked || !p->sharable ); assert( p->wantToLock>0 ); /* We should already hold a lock on the database connection */ - assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); + assert( sqlite3_mutex_held(p->pSqlite->mutex) ); p->wantToLock--; - if( p->wantToLock==0 ){ + if( p->wantToLock==0 && p->locked ){ sqlite3_mutex_leave(p->pBt->mutex); p->locked = 0; } diff --git a/src/btree.c b/src/btree.c index 800ea0508..a955b384c 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.415 2007/08/28 23:28:08 drh Exp $ +** $Id: btree.c,v 1.416 2007/08/29 04:00:58 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -96,8 +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) ); + assert( sqlite3BtreeHoldsMutex(p) ); /* This is a no-op if the shared-cache is not enabled */ if( !p->sharable ){ @@ -149,8 +148,7 @@ static int lockTable(Btree *p, Pgno iTable, u8 eLock){ BtLock *pLock = 0; BtLock *pIter; - assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3BtreeHoldsMutex(p) ); /* This is a no-op if the shared-cache is not enabled */ if( !p->sharable ){ @@ -216,8 +214,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( sqlite3BtreeHoldsMutex(p) ); assert( p->sharable || 0==*ppIter ); while( *ppIter ){ @@ -234,12 +231,22 @@ static void unlockAllTables(Btree *p){ static void releasePage(MemPage *pPage); /* Forward reference */ +/* +** Verify that the cursor holds a mutex on the BtShared +*/ +#ifndef NDEBUG +static int cursorHoldsMutex(BtCursor *p){ + return sqlite3BtreeHoldsMutex(p->pBtree); +} +#endif + + #ifndef SQLITE_OMIT_INCRBLOB /* ** Invalidate the overflow page-list cache for cursor pCur, if any. */ static void invalidateOverflowCache(BtCursor *pCur){ - assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); sqlite3_free(pCur->aOverflow); pCur->aOverflow = 0; } @@ -250,7 +257,7 @@ static void invalidateOverflowCache(BtCursor *pCur){ */ static void invalidateAllOverflowCache(BtShared *pBt){ BtCursor *p; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); for(p=pBt->pCursor; p; p=p->pNext){ invalidateOverflowCache(p); } @@ -269,7 +276,7 @@ static int saveCursorPosition(BtCursor *pCur){ assert( CURSOR_VALID==pCur->eState ); assert( 0==pCur->pKey ); - assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); @@ -311,7 +318,7 @@ static int saveCursorPosition(BtCursor *pCur){ */ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ BtCursor *p; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); assert( pExcept==0 || pExcept->pBt==pBt ); for(p=pBt->pCursor; p; p=p->pNext){ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) && @@ -329,7 +336,7 @@ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){ ** Clear the current cursor position. */ static void clearCursorPosition(BtCursor *pCur){ - assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); sqlite3_free(pCur->pKey); pCur->pKey = 0; pCur->eState = CURSOR_INVALID; @@ -348,7 +355,7 @@ static void clearCursorPosition(BtCursor *pCur){ */ int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){ int rc; - assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_REQUIRESEEK ); #ifndef SQLITE_OMIT_INCRBLOB if( pCur->isIncrblobHandle ){ @@ -378,7 +385,7 @@ int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){ */ static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){ int nPagesPerMapPage, iPtrMap, ret; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); nPagesPerMapPage = (pBt->usableSize/5)+1; iPtrMap = (pgno-2)/nPagesPerMapPage; ret = (iPtrMap*nPagesPerMapPage) + 2; @@ -402,7 +409,7 @@ static int ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent){ int offset; /* Offset in pointer map page */ int rc; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); /* The master-journal page number must never be used as a pointer map page */ assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) ); @@ -445,7 +452,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ int offset; /* Offset of entry in pointer map */ int rc; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); iPtrmap = PTRMAP_PAGENO(pBt, key); rc = sqlite3PagerGet(pBt->pPager, iPtrmap, &pDbPage); @@ -489,7 +496,7 @@ u8 *sqlite3BtreeFindCell(MemPage *pPage, int iCell){ */ static u8 *findOverflowCell(MemPage *pPage, int iCell){ int i; - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); for(i=pPage->nOverflow-1; i>=0; i--){ int k; struct _OvflCell *pOvfl; @@ -522,7 +529,7 @@ void sqlite3BtreeParseCellPtr( int n; /* Number bytes in cell content header */ u32 nPayload; /* Number of bytes of cell payload */ - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); pInfo->pCell = pCell; assert( pPage->leaf==0 || pPage->leaf==1 ); @@ -636,7 +643,7 @@ static int ptrmapPutOvflPtr(MemPage *pPage, u8 *pCell){ */ static int ptrmapPutOvfl(MemPage *pPage, int iCell){ u8 *pCell; - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); pCell = findOverflowCell(pPage, iCell); return ptrmapPutOvflPtr(pPage, pCell); } @@ -666,7 +673,7 @@ static int defragmentPage(MemPage *pPage){ assert( pPage->pBt!=0 ); assert( pPage->pBt->usableSize <= SQLITE_MAX_PAGE_SIZE ); assert( pPage->nOverflow==0 ); - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); temp = sqlite3_malloc( pPage->pBt->pageSize ); if( temp==0 ) return SQLITE_NOMEM; data = pPage->aData; @@ -723,7 +730,7 @@ static int allocateSpace(MemPage *pPage, int nByte){ data = pPage->aData; assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( pPage->pBt ); - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); if( nByte<4 ) nByte = 4; if( pPage->nFree<nByte || pPage->nOverflow>0 ) return 0; pPage->nFree -= nByte; @@ -782,7 +789,7 @@ static void freeSpace(MemPage *pPage, int start, int size){ assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( start>=pPage->hdrOffset+6+(pPage->leaf?0:4) ); assert( (start + size)<=pPage->pBt->usableSize ); - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); if( size<4 ) size = 4; #ifdef SQLITE_SECURE_DELETE @@ -843,7 +850,7 @@ static void decodeFlags(MemPage *pPage, int flagByte){ BtShared *pBt; /* A copy of pPage->pBt */ assert( pPage->hdrOffset==(pPage->pgno==1 ? 100 : 0) ); - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); pPage->intKey = (flagByte & (PTF_INTKEY|PTF_LEAFDATA))!=0; pPage->zeroData = (flagByte & PTF_ZERODATA)!=0; pPage->leaf = (flagByte & PTF_LEAF)!=0; @@ -890,7 +897,7 @@ int sqlite3BtreeInitPage( pBt = pPage->pBt; assert( pBt!=0 ); assert( pParent==0 || pParent->pBt==pBt ); - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) ); assert( pPage->aData == &((unsigned char*)pPage)[-pBt->pageSize] ); if( pPage->pParent!=pParent && (pPage->pParent!=0 || pPage->isInit) ){ @@ -961,7 +968,7 @@ static void zeroPage(MemPage *pPage, int flags){ assert( sqlite3PagerPagenumber(pPage->pDbPage)==pPage->pgno ); assert( &data[pBt->pageSize] == (unsigned char*)pPage ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); memset(&data[hdr], 0, pBt->usableSize - hdr); data[hdr] = flags; first = hdr + 8 + 4*((flags&PTF_LEAF)==0); @@ -999,7 +1006,7 @@ int sqlite3BtreeGetPage( MemPage *pPage; DbPage *pDbPage; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent); if( rc ) return rc; pPage = (MemPage *)sqlite3PagerGetExtra(pDbPage); @@ -1024,7 +1031,7 @@ static int getAndInitPage( MemPage *pParent /* Parent of the page */ ){ int rc; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno==0 ){ return SQLITE_CORRUPT_BKPT; } @@ -1044,7 +1051,7 @@ static void releasePage(MemPage *pPage){ assert( pPage->aData ); assert( pPage->pBt ); assert( &pPage->aData[pPage->pBt->pageSize]==(unsigned char*)pPage ); - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); sqlite3PagerUnref(pPage->pDbPage); } } @@ -1058,7 +1065,7 @@ 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) ); + assert( pPage->isInit==0 || sqlite3_mutex_held(pPage->pBt->mutex) ); if( pPage->pParent ){ MemPage *pParent = pPage->pParent; assert( pPage->isInit==1 ); @@ -1082,7 +1089,7 @@ static void pageReinit(DbPage *pData, int pageSize){ assert( (pageSize & 7)==0 ); pPage = (MemPage *)sqlite3PagerGetExtra(pData); if( pPage->isInit ){ - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); pPage->isInit = 0; sqlite3BtreeInitPage(pPage, pPage->pParent); } @@ -1393,17 +1400,6 @@ int sqlite3BtreeClose(Btree *p){ return SQLITE_OK; } -#if SQLITE_THREADSAFE && !defined(SQLITE_OMIT_SHARED_CACHE) -/* -** Short-cuts for entering and leaving mutexes on a cursor. -*/ -# define cursorEnter(X) assert( sqlite3_mutex_held(X->pBt->mutex) ) -# define cursorLeave(X) -#else -# define cursorEnter(X) -# define cursorLeave(X) -#endif /* !SQLITE_OMIT_SHARED_CACHE */ - /* ** Change the busy handler callback function. */ @@ -1599,7 +1595,7 @@ static int lockBtree(BtShared *pBt){ int rc, pageSize; MemPage *pPage1; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); if( pBt->pPage1 ) return SQLITE_OK; rc = sqlite3BtreeGetPage(pBt, 1, &pPage1, 0); if( rc!=SQLITE_OK ) return rc; @@ -1676,8 +1672,7 @@ page1_init_failed: static int lockBtreeWithRetry(Btree *pRef){ int rc = SQLITE_OK; - assert( sqlite3BtreeMutexHeld(pRef->pSqlite->mutex) ); - assert( sqlite3BtreeMutexHeld(pRef->pBt->mutex) ); + assert( sqlite3BtreeHoldsMutex(pRef) ); if( pRef->inTrans==TRANS_NONE ){ u8 inTransaction = pRef->pBt->inTransaction; btreeIntegrity(pRef); @@ -1704,7 +1699,7 @@ static int lockBtreeWithRetry(Btree *pRef){ ** If there is a transaction in progress, this routine is a no-op. */ static void unlockBtreeIfUnused(BtShared *pBt){ - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); if( pBt->inTransaction==TRANS_NONE && pBt->pCursor==0 && pBt->pPage1!=0 ){ if( sqlite3PagerRefcount(pBt->pPager)>=1 ){ if( pBt->pPage1->aData==0 ){ @@ -1729,7 +1724,7 @@ static int newDatabase(BtShared *pBt){ unsigned char *data; int rc; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); if( sqlite3PagerPagecount(pBt->pPager)>0 ) return SQLITE_OK; pP1 = pBt->pPage1; assert( pP1!=0 ); @@ -1878,7 +1873,7 @@ static int setChildPtrmaps(MemPage *pPage){ int isInitOrig = pPage->isInit; Pgno pgno = pPage->pgno; - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); rc = sqlite3BtreeInitPage(pPage, pPage->pParent); if( rc!=SQLITE_OK ){ goto set_child_ptrmaps_out; @@ -1926,7 +1921,7 @@ set_child_ptrmaps_out: ** overflow page in the list. */ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); if( eType==PTRMAP_OVERFLOW2 ){ /* The pointer is always the first 4 bytes of the page in this case. */ if( get4byte(pPage->aData)!=iFrom ){ @@ -1992,7 +1987,7 @@ static int relocatePage( assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); assert( pDbPage->pBt==pBt ); /* Move page iDbPage from it's current location to page number iFreePage */ @@ -2072,7 +2067,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin){ Pgno iLastPg; /* Last page in the database */ Pgno nFreeList; /* Number of pages still on the free-list */ - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); iLastPg = pBt->nTrunc; if( iLastPg==0 ){ iLastPg = sqlite3PagerPagecount(pBt->pPager); @@ -2198,7 +2193,7 @@ static int autoVacuumCommit(BtShared *pBt, Pgno *pnTrunc){ int nRef = sqlite3PagerRefcount(pPager); #endif - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); invalidateAllOverflowCache(pBt); assert(pBt->autoVacuum); if( !pBt->incrVacuum ){ @@ -2605,8 +2600,7 @@ static int btreeCursor( BtCursor *pCur; BtShared *pBt = p->pBt; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); - assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); + assert( sqlite3BtreeHoldsMutex(p) ); *ppCur = 0; if( wrFlag ){ if( pBt->readOnly ){ @@ -2691,7 +2685,7 @@ int sqlite3BtreeCursor( int sqlite3BtreeCloseCursor(BtCursor *pCur){ BtShared *pBt = pCur->pBt; - assert( sqlite3_mutex_held(pCur->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) ); clearCursorPosition(pCur); if( pCur->pPrev ){ @@ -2714,14 +2708,13 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){ ** The temporary cursor is not on the cursor list for the Btree. */ void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur){ - cursorEnter(pCur); + assert( cursorHoldsMutex(pCur) ); memcpy(pTempCur, pCur, sizeof(*pCur)); pTempCur->pNext = 0; pTempCur->pPrev = 0; if( pTempCur->pPage ){ sqlite3PagerRef(pTempCur->pPage->pDbPage); } - cursorLeave(pCur); } /* @@ -2729,11 +2722,10 @@ void sqlite3BtreeGetTempCursor(BtCursor *pCur, BtCursor *pTempCur){ ** function above. */ void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ - cursorEnter(pCur); + assert( cursorHoldsMutex(pCur) ); if( pCur->pPage ){ sqlite3PagerUnref(pCur->pPage->pDbPage); } - cursorLeave(pCur); } /* @@ -2791,7 +2783,7 @@ void sqlite3BtreeReleaseTempCursor(BtCursor *pCur){ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ int rc; - assert( sqlite3_mutex_held(pCur->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); @@ -2815,7 +2807,7 @@ int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){ int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){ int rc; - assert( sqlite3_mutex_held(pCur->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_INVALID || pCur->eState==CURSOR_VALID ); @@ -2856,7 +2848,7 @@ static int getOverflowPage( Pgno next = 0; int rc; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); /* One of these must not be NULL. Otherwise, why call this function? */ assert(ppPage || pPgnoNext); @@ -2996,7 +2988,7 @@ static int accessPayload( assert( pCur->eState==CURSOR_VALID ); assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); assert( offset>=0 ); - assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); getCellInfo(pCur); aPayload = pCur->info.pCell + pCur->info.nHeader; @@ -3122,20 +3114,18 @@ static int accessPayload( int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ int rc; - cursorEnter(pCur); + assert( cursorHoldsMutex(pCur) ); rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); assert( pCur->pPage!=0 ); if( pCur->pPage->intKey ){ - 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); } - cursorLeave(pCur); return rc; } @@ -3151,7 +3141,7 @@ int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){ int rc; - cursorEnter(pCur); + assert( cursorHoldsMutex(pCur) ); rc = restoreOrClearCursorPosition(pCur); if( rc==SQLITE_OK ){ assert( pCur->eState==CURSOR_VALID ); @@ -3159,7 +3149,6 @@ 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); } - cursorLeave(pCur); return rc; } @@ -3194,7 +3183,7 @@ static const unsigned char *fetchPayload( assert( pCur!=0 && pCur->pPage!=0 ); assert( pCur->eState==CURSOR_VALID ); - assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); pPage = pCur->pPage; assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); getCellInfo(pCur); @@ -3234,14 +3223,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->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); if( pCur->eState==CURSOR_VALID ){ return (const void*)fetchPayload(pCur, pAmt, 0); } return 0; } const void *sqlite3BtreeDataFetch(BtCursor *pCur, int *pAmt){ - assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); if( pCur->eState==CURSOR_VALID ){ return (const void*)fetchPayload(pCur, pAmt, 1); } @@ -3259,7 +3248,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ MemPage *pOldPage; BtShared *pBt = pCur->pBt; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); rc = getAndInitPage(pBt, newPgno, &pNewPage, pCur->pPage); if( rc ) return rc; @@ -3288,7 +3277,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){ int sqlite3BtreeIsRootPage(MemPage *pPage){ MemPage *pParent; - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); pParent = pPage->pParent; if( pParent==0 ) return 1; if( pParent->pgno>1 ) return 0; @@ -3309,7 +3298,7 @@ void sqlite3BtreeMoveToParent(BtCursor *pCur){ MemPage *pPage; int idxParent; - cursorEnter(pCur); + assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); pPage = pCur->pPage; assert( pPage!=0 ); @@ -3323,7 +3312,6 @@ void sqlite3BtreeMoveToParent(BtCursor *pCur){ pCur->info.nSize = 0; assert( pParent->idxShift==0 ); pCur->idx = idxParent; - cursorLeave(pCur); } /* @@ -3335,7 +3323,7 @@ static int moveToRoot(BtCursor *pCur){ Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); if( pCur->eState==CURSOR_REQUIRESEEK ){ clearCursorPosition(pCur); } @@ -3378,7 +3366,7 @@ static int moveToLeftmost(BtCursor *pCur){ int rc = SQLITE_OK; MemPage *pPage; - assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ assert( pCur->idx>=0 && pCur->idx<pPage->nCell ); @@ -3403,7 +3391,7 @@ static int moveToRightmost(BtCursor *pCur){ int rc = SQLITE_OK; MemPage *pPage; - assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); assert( pCur->eState==CURSOR_VALID ); while( rc==SQLITE_OK && !(pPage = pCur->pPage)->leaf ){ pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]); @@ -3424,8 +3412,8 @@ static int moveToRightmost(BtCursor *pCur){ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ int rc; - assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) ); rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ if( pCur->eState==CURSOR_INVALID ){ @@ -3448,8 +3436,8 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ int rc; - assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) ); rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ if( CURSOR_INVALID==pCur->eState ){ @@ -3501,8 +3489,8 @@ int sqlite3BtreeMoveto( ){ int rc; - assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) ); rc = moveToRoot(pCur); if( rc ){ return rc; @@ -3643,7 +3631,7 @@ static int btreeNext(BtCursor *pCur, int *pRes){ int rc; MemPage *pPage; - assert( sqlite3_mutex_held(pCur->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); rc = restoreOrClearCursorPosition(pCur); if( rc!=SQLITE_OK ){ return rc; @@ -3700,9 +3688,8 @@ static int btreeNext(BtCursor *pCur, int *pRes){ } int sqlite3BtreeNext(BtCursor *pCur, int *pRes){ int rc; - cursorEnter(pCur); + assert( cursorHoldsMutex(pCur) ); rc = btreeNext(pCur, pRes); - cursorLeave(pCur); return rc; } @@ -3718,7 +3705,7 @@ static int btreePrevious(BtCursor *pCur, int *pRes){ Pgno pgno; MemPage *pPage; - assert( sqlite3_mutex_held(pCur->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); rc = restoreOrClearCursorPosition(pCur); if( rc!=SQLITE_OK ){ return rc; @@ -3767,9 +3754,8 @@ static int btreePrevious(BtCursor *pCur, int *pRes){ } int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){ int rc; - cursorEnter(pCur); + assert( cursorHoldsMutex(pCur) ); rc = btreePrevious(pCur, pRes); - cursorLeave(pCur); return rc; } @@ -3808,7 +3794,7 @@ static int allocateBtreePage( MemPage *pTrunk = 0; MemPage *pPrevTrunk = 0; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); pPage1 = pBt->pPage1; n = get4byte(&pPage1->aData[36]); if( n>0 ){ @@ -4041,7 +4027,7 @@ static int freePage(MemPage *pPage){ int rc, n, k; /* Prepare the page for freeing */ - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( pPage->pgno>1 ); pPage->isInit = 0; releasePage(pPage->pParent); @@ -4124,7 +4110,7 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){ int nOvfl; int ovflPageSize; - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); sqlite3BtreeParseCellPtr(pPage, pCell, &info); if( info.iOverflow==0 ){ return SQLITE_OK; /* No overflow pages. Return without doing anything */ @@ -4181,7 +4167,7 @@ static int fillInCell( int nHeader; CellInfo info; - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); /* Fill in the header. */ nHeader = 0; @@ -4295,7 +4281,7 @@ static int reparentPage(BtShared *pBt, Pgno pgno, MemPage *pNewParent, int idx){ MemPage *pThis; DbPage *pDbPage; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); assert( pNewParent!=0 ); if( pgno==0 ) return SQLITE_OK; assert( pBt->pPager!=0 ); @@ -4339,7 +4325,7 @@ static int reparentChildPages(MemPage *pPage){ BtShared *pBt = pPage->pBt; int rc = SQLITE_OK; - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); if( pPage->leaf ) return SQLITE_OK; for(i=0; i<pPage->nCell; i++){ @@ -4374,7 +4360,7 @@ static void dropCell(MemPage *pPage, int idx, int sz){ assert( idx>=0 && idx<pPage->nCell ); assert( sz==cellSize(pPage, idx) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); data = pPage->aData; ptr = &data[pPage->cellOffset + 2*idx]; pc = get2byte(ptr); @@ -4427,7 +4413,7 @@ static int insertCell( assert( i>=0 && i<=pPage->nCell+pPage->nOverflow ); assert( sz==cellSizePtr(pPage, pCell) ); - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); if( pPage->nOverflow || sz+2>pPage->nFree ){ if( pTemp ){ memcpy(pTemp+nSkip, pCell+nSkip, sz-nSkip); @@ -4507,7 +4493,7 @@ static void assemblePage( u8 *data; /* Data for the page */ assert( pPage->nOverflow==0 ); - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); totalSize = 0; for(i=0; i<nCell; i++){ totalSize += aSize[i]; @@ -4582,7 +4568,7 @@ static int balance_quick(MemPage *pPage, MemPage *pParent){ int parentSize; /* Size of new divider cell */ u8 parentCell[64]; /* Space for the new divider cell */ - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); /* Allocate a new page. Insert the overflow cell from pPage ** into it. Then remove the overflow cell from pPage. @@ -4708,7 +4694,7 @@ static int balance_nonroot(MemPage *pPage){ u8 *aFrom = 0; #endif - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); /* ** Find the parent page. @@ -5261,7 +5247,7 @@ static int balance_shallower(MemPage *pPage){ assert( pPage->pParent==0 ); assert( pPage->nCell==0 ); - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); pBt = pPage->pBt; mxCellPerPage = MX_CELL(pBt); apCell = sqlite3_malloc( mxCellPerPage*(sizeof(u8*)+sizeof(int)) ); @@ -5366,7 +5352,7 @@ static int balance_deeper(MemPage *pPage){ assert( pPage->pParent==0 ); assert( pPage->nOverflow>0 ); pBt = pPage->pBt; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); rc = allocateBtreePage(pBt, &pChild, &pgnoChild, pPage->pgno, 0); if( rc ) return rc; assert( sqlite3PagerIswriteable(pChild->pDbPage) ); @@ -5415,7 +5401,7 @@ balancedeeper_out: */ static int balance(MemPage *pPage, int insert){ int rc = SQLITE_OK; - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( sqlite3_mutex_held(pPage->pBt->mutex) ); if( pPage->pParent==0 ){ rc = sqlite3PagerWrite(pPage->pDbPage); if( rc==SQLITE_OK && pPage->nOverflow>0 ){ @@ -5453,8 +5439,7 @@ static int checkReadLocks(Btree *pBtree, Pgno pgnoRoot, BtCursor *pExclude){ BtCursor *p; BtShared *pBt = pBtree->pBt; sqlite3 *db = pBtree->pSqlite; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); - assert( sqlite3BtreeMutexHeld(db->mutex) ); + assert( sqlite3BtreeHoldsMutex(pBtree) ); for(p=pBt->pCursor; p; p=p->pNext){ if( p==pExclude ) continue; if( p->eState!=CURSOR_VALID ) continue; @@ -5497,20 +5482,17 @@ int sqlite3BtreeInsert( unsigned char *oldCell; unsigned char *newCell = 0; - cursorEnter(pCur); + assert( cursorHoldsMutex(pCur) ); if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction before doing an insert */ rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; - cursorLeave(pCur); return rc; } assert( !pBt->readOnly ); if( !pCur->wrFlag ){ - cursorLeave(pCur); return SQLITE_PERM; /* Cursor not open for writing */ } if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){ - cursorLeave(pCur); return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } @@ -5520,7 +5502,6 @@ int sqlite3BtreeInsert( SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc)) ){ - cursorLeave(pCur); return rc; } @@ -5569,7 +5550,6 @@ int sqlite3BtreeInsert( } end_insert: sqlite3_free(newCell); - cursorLeave(pCur); return rc; } @@ -5585,25 +5565,21 @@ int sqlite3BtreeDelete(BtCursor *pCur){ Btree *p = pCur->pBtree; BtShared *pBt = p->pBt; - cursorEnter(pCur); + assert( cursorHoldsMutex(pCur) ); assert( pPage->isInit ); if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction before doing a delete */ rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; - cursorLeave(pCur); return rc; } assert( !pBt->readOnly ); if( pCur->idx >= pPage->nCell ){ - cursorLeave(pCur); return SQLITE_ERROR; /* The cursor is not pointing to anything */ } if( !pCur->wrFlag ){ - cursorLeave(pCur); return SQLITE_PERM; /* Did not open this cursor for writing */ } if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){ - cursorLeave(pCur); return SQLITE_LOCKED; /* The table pCur points to has a read lock */ } @@ -5617,7 +5593,6 @@ int sqlite3BtreeDelete(BtCursor *pCur){ (rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur))!=0 || (rc = sqlite3PagerWrite(pPage->pDbPage))!=0 ){ - cursorLeave(pCur); return rc; } @@ -5631,7 +5606,6 @@ int sqlite3BtreeDelete(BtCursor *pCur){ } rc = clearCell(pPage, pCell); if( rc ){ - cursorLeave(pCur); return rc; } @@ -5690,7 +5664,6 @@ int sqlite3BtreeDelete(BtCursor *pCur){ if( rc==SQLITE_OK ){ moveToRoot(pCur); } - cursorLeave(pCur); return rc; } @@ -5711,8 +5684,7 @@ 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) ); + assert( sqlite3BtreeHoldsMutex(p) ); if( pBt->inTransaction!=TRANS_WRITE ){ /* Must start a transaction first */ rc = pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; @@ -5860,7 +5832,7 @@ static int clearDatabasePage( unsigned char *pCell; int i; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno>sqlite3PagerPagecount(pBt->pPager) ){ return SQLITE_CORRUPT_BKPT; } @@ -5942,7 +5914,7 @@ static int btreeDropTable(Btree *p, int iTable, int *piMoved){ MemPage *pPage = 0; BtShared *pBt = p->pBt; - assert( sqlite3BtreeMutexHeld(pBt->mutex) ); + assert( sqlite3BtreeHoldsMutex(p) ); if( p->inTrans!=TRANS_WRITE ){ return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR; } @@ -6143,7 +6115,7 @@ int sqlite3BtreeFlags(BtCursor *pCur){ ** restoreOrClearCursorPosition() here. */ MemPage *pPage = pCur->pPage; - assert( sqlite3BtreeMutexHeld(pPage->pBt->mutex) ); + assert( cursorHoldsMutex(pCur) ); assert( pPage->pBt==pCur->pBt ); return pPage ? pPage->aData[pPage->hdrOffset] : 0; } @@ -6603,7 +6575,7 @@ char *sqlite3BtreeIntegrityCheck( */ const char *sqlite3BtreeGetFilename(Btree *p){ assert( p->pBt->pPager!=0 ); - assert( sqlite3_mutex_held(p->pSqlite->mutex) ); + /* assert( sqlite3BtreeHoldsMutex(p) ); */ return sqlite3PagerFilename(p->pBt->pPager); } @@ -6615,7 +6587,7 @@ const char *sqlite3BtreeGetFilename(Btree *p){ */ const char *sqlite3BtreeGetDirname(Btree *p){ assert( p->pBt->pPager!=0 ); - assert( sqlite3_mutex_held(p->pSqlite->mutex) ); + assert( sqlite3BtreeHoldsMutex(p) ); return sqlite3PagerDirname(p->pBt->pPager); } @@ -6629,7 +6601,7 @@ const char *sqlite3BtreeGetDirname(Btree *p){ */ const char *sqlite3BtreeGetJournalname(Btree *p){ assert( p->pBt->pPager!=0 ); - assert( sqlite3_mutex_held(p->pSqlite->mutex) ); + assert( sqlite3BtreeHoldsMutex(p) ); return sqlite3PagerJournalname(p->pBt->pPager); } @@ -6709,7 +6681,7 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ ** Return non-zero if a transaction is active. */ int sqlite3BtreeIsInTrans(Btree *p){ - assert( p==0 || sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); + assert( p==0 || sqlite3_mutex_held(p->pSqlite->mutex) ); return (p && (p->inTrans==TRANS_WRITE)); } @@ -6717,8 +6689,7 @@ int sqlite3BtreeIsInTrans(Btree *p){ ** Return non-zero if a statement transaction is active. */ int sqlite3BtreeIsInStmt(Btree *p){ - assert( sqlite3BtreeMutexHeld(p->pBt->mutex) ); - assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); + assert( sqlite3BtreeHoldsMutex(p) ); return (p->pBt && p->pBt->inStmt); } @@ -6726,7 +6697,7 @@ int sqlite3BtreeIsInStmt(Btree *p){ ** Return non-zero if a read (or write) transaction is active. */ int sqlite3BtreeIsInReadTrans(Btree *p){ - assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); + assert( sqlite3_mutex_held(p->pSqlite->mutex) ); return (p && (p->inTrans!=TRANS_NONE)); } @@ -6763,7 +6734,7 @@ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){ */ int sqlite3BtreeSchemaLocked(Btree *p){ int rc; - assert( sqlite3BtreeMutexHeld(p->pSqlite->mutex) ); + assert( sqlite3_mutex_held(p->pSqlite->mutex) ); sqlite3BtreeEnter(p); rc = (queryTableLock(p, MASTER_ROOT, READ_LOCK)!=SQLITE_OK); sqlite3BtreeLeave(p); @@ -6799,8 +6770,8 @@ 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->pBt->mutex) ); - assert( sqlite3BtreeMutexHeld(pCsr->pBtree->pSqlite->mutex) ); + assert( cursorHoldsMutex(pCsr) ); + assert( sqlite3_mutex_held(pCsr->pBtree->pSqlite->mutex) ); assert(pCsr->isIncrblobHandle); if( pCsr->eState==CURSOR_REQUIRESEEK ){ return SQLITE_ABORT; @@ -6837,8 +6808,8 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){ ** sqlite3BtreePutData()). */ void sqlite3BtreeCacheOverflow(BtCursor *pCur){ - assert( sqlite3BtreeMutexHeld(pCur->pBt->mutex) ); - assert( sqlite3BtreeMutexHeld(pCur->pBtree->pSqlite->mutex) ); + assert( cursorHoldsMutex(pCur) ); + assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) ); assert(!pCur->isIncrblobHandle); assert(!pCur->aOverflow); pCur->isIncrblobHandle = 1; diff --git a/src/btree.h b/src/btree.h index a7f71fe35..6733daa50 100644 --- a/src/btree.h +++ b/src/btree.h @@ -13,7 +13,7 @@ ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.89 2007/08/29 00:33:07 drh Exp $ +** @(#) $Id: btree.h,v 1.90 2007/08/29 04:00:58 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -175,23 +175,24 @@ int sqlite3BtreePageDump(Btree*, int, int recursive); #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE void sqlite3BtreeEnter(Btree*); void sqlite3BtreeLeave(Btree*); -# define sqlite3BtreeMutexHeld(X) sqlite3_mutex_held(X) + int sqlite3BtreeHoldsMutex(Btree*); void sqlite3BtreeEnterAll(sqlite3*); void sqlite3BtreeLeaveAll(sqlite3*); + int sqlite3BtreeHoldsAllMutexes(sqlite3*); void sqlite3BtreeMutexArrayEnter(BtreeMutexArray*); void sqlite3BtreeMutexArrayLeave(BtreeMutexArray*); void sqlite3BtreeMutexArrayInsert(BtreeMutexArray*, Btree*); #else # define sqlite3BtreeEnter(X) # define sqlite3BtreeLeave(X) -# define sqlite3BtreeMutexHeld(X) 1 +# define sqlite3BtreeHoldsMutex(X) 1 # define sqlite3BtreeEnterAll(X) # define sqlite3BtreeLeaveAll(X) +# define sqlite3BtreeHoldsAllMutexes(X) 1 # define sqlite3BtreeMutexArrayEnter(X) # define sqlite3BtreeMutexArrayLeave(X) # define sqlite3BtreeMutexArrayInsert(X,Y) #endif - #endif /* _BTREE_H_ */ |