aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordanielk1977 <danielk1977@noemail.net>2009-04-02 18:28:08 +0000
committerdanielk1977 <danielk1977@noemail.net>2009-04-02 18:28:08 +0000
commitfa542f1fc80c7c27012b427da9a098eb20f629d6 (patch)
treeb42e39e2ed4f35a4cb425a188afa84c4a060ae91 /src
parente1fb65a0b83dd38692cdd81b37f6e1096f9b883f (diff)
downloadsqlite-fa542f1fc80c7c27012b427da9a098eb20f629d6.tar.gz
sqlite-fa542f1fc80c7c27012b427da9a098eb20f629d6.zip
Fix a problem causing the BtShared.isPending flag to be cleared to early. Also coverage improvements for btree.c. (CVS 6440)
FossilOrigin-Name: 8f1423445b29a5f52ed907de6db82128a96ebfe2
Diffstat (limited to 'src')
-rw-r--r--src/btree.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/src/btree.c b/src/btree.c
index 69264f42a..09412080f 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.587 2009/04/01 19:07:04 danielk1977 Exp $
+** $Id: btree.c,v 1.588 2009/04/02 18:28:08 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
@@ -248,6 +248,10 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
/*
** Release all the table locks (locks obtained via calls to
** the setSharedCacheTableLock() procedure) held by Btree handle p.
+**
+** This function assumes that handle p has an open read or write
+** transaction. If it does not, then the BtShared.isPending variable
+** may be incorrectly cleared.
*/
static void clearAllSharedCacheTableLocks(Btree *p){
BtShared *pBt = p->pBt;
@@ -255,10 +259,12 @@ static void clearAllSharedCacheTableLocks(Btree *p){
assert( sqlite3BtreeHoldsMutex(p) );
assert( p->sharable || 0==*ppIter );
+ assert( p->inTrans>0 );
while( *ppIter ){
BtLock *pLock = *ppIter;
assert( pBt->isExclusive==0 || pBt->pWriter==pLock->pBtree );
+ assert( pLock->pBtree->inTrans>=pLock->eLock );
if( pLock->pBtree==p ){
*ppIter = pLock->pNext;
sqlite3_free(pLock);
@@ -2261,7 +2267,7 @@ set_child_ptrmaps_out:
}
/*
-** Somewhere on pPage, which is guarenteed to be a btree page, not an overflow
+** Somewhere on pPage, which is guaranteed to be a btree page, not an overflow
** page, is a pointer to page iFrom. Modify this pointer so that it points to
** iTo. Parameter eType describes the type of pointer to be modified, as
** follows:
@@ -2424,6 +2430,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
Pgno nFreeList; /* Number of pages still on the free-list */
assert( sqlite3_mutex_held(pBt->mutex) );
+ assert( iLastPg>nFin );
if( !PTRMAP_ISPAGE(pBt, iLastPg) && iLastPg!=PENDING_BYTE_PAGE(pBt) ){
int rc;
@@ -2431,7 +2438,7 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
Pgno iPtrPage;
nFreeList = get4byte(&pBt->pPage1->aData[36]);
- if( nFreeList==0 || nFin==iLastPg ){
+ if( nFreeList==0 ){
return SQLITE_DONE;
}
@@ -2688,7 +2695,6 @@ int sqlite3BtreeCommitPhaseTwo(Btree *p){
}
pBt->inTransaction = TRANS_READ;
}
- clearAllSharedCacheTableLocks(p);
/* If the handle has any kind of transaction open, decrement the transaction
** count of the shared btree. If the transaction count reaches 0, set
@@ -2696,6 +2702,7 @@ int sqlite3BtreeCommitPhaseTwo(Btree *p){
** will unlock the pager.
*/
if( p->inTrans!=TRANS_NONE ){
+ clearAllSharedCacheTableLocks(p);
pBt->nTransaction--;
if( 0==pBt->nTransaction ){
pBt->inTransaction = TRANS_NONE;
@@ -2812,7 +2819,6 @@ int sqlite3BtreeRollback(Btree *p){
}
#endif
btreeIntegrity(p);
- clearAllSharedCacheTableLocks(p);
if( p->inTrans==TRANS_WRITE ){
int rc2;
@@ -2834,6 +2840,7 @@ int sqlite3BtreeRollback(Btree *p){
}
if( p->inTrans!=TRANS_NONE ){
+ clearAllSharedCacheTableLocks(p);
assert( pBt->nTransaction>0 );
pBt->nTransaction--;
if( 0==pBt->nTransaction ){
@@ -6788,8 +6795,14 @@ int sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
if( idx==4 && *pMeta>0 ) pBt->readOnly = 1;
#endif
- /* Grab the read-lock on page 1. */
- rc = setSharedCacheTableLock(p, 1, READ_LOCK);
+ /* If there is currently an open transaction, grab a read-lock
+ ** on page 1 of the database file. This is done to make sure that
+ ** no other connection can modify the meta value just read from
+ ** the database until the transaction is concluded.
+ */
+ if( p->inTrans>0 ){
+ rc = setSharedCacheTableLock(p, 1, READ_LOCK);
+ }
sqlite3BtreeLeave(p);
return rc;
}