Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Btree fixes related to multiple client tests. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
58f72822114449bad7a89f89f8251f54 |
User & Date: | dan 2013-10-30 19:57:25.996 |
Context
2013-10-31
| ||
16:31 | Fix some problems causing multi-threaded btree tests to fail. Some still remain. check-in: 67b28147ea user: dan tags: trunk | |
2013-10-30
| ||
19:57 | Btree fixes related to multiple client tests. check-in: 58f7282211 user: dan tags: trunk | |
18:37 | Add sub-transactions to btree module. check-in: 9e00823074 user: dan tags: trunk | |
Changes
Changes to lsm-test/lsmtest_main.c.
︙ | ︙ | |||
61 62 63 64 65 66 67 68 69 70 71 72 73 74 | TestDb *pDb, /* Database handle */ void *pKey, int nKey, /* Key to query database for */ void *pVal, int nVal, /* Value to write */ int *pRc /* IN/OUT: Error code */ ){ if( *pRc==0 ){ int rc; rc = tdb_write(pDb, pKey, nKey, pVal, nVal); testSetError(rc); } } void testDelete( TestDb *pDb, /* Database handle */ void *pKey, int nKey, /* Key to query database for */ | > > | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | TestDb *pDb, /* Database handle */ void *pKey, int nKey, /* Key to query database for */ void *pVal, int nVal, /* Value to write */ int *pRc /* IN/OUT: Error code */ ){ if( *pRc==0 ){ int rc; static int nCall = 0; nCall++; rc = tdb_write(pDb, pKey, nKey, pVal, nVal); testSetError(rc); } } void testDelete( TestDb *pDb, /* Database handle */ void *pKey, int nKey, /* Key to query database for */ |
︙ | ︙ |
Changes to src/bt_lock.c.
︙ | ︙ | |||
107 108 109 110 111 112 113 | assert( iLock>=0 && iLock<(BT_LOCK_READER0 + BT_NREADER) ); assert( (BT_LOCK_READER0+BT_NREADER)<=32 ); assert( eOp==BT_LOCK_UNLOCK || eOp==BT_LOCK_SHARED || eOp==BT_LOCK_EXCL ); /* Check for a no-op. Proceed only if this is not one of those. */ if( (eOp==BT_LOCK_UNLOCK && (mask & (p->mExclLock|p->mSharedLock))!=0) | | | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | assert( iLock>=0 && iLock<(BT_LOCK_READER0 + BT_NREADER) ); assert( (BT_LOCK_READER0+BT_NREADER)<=32 ); assert( eOp==BT_LOCK_UNLOCK || eOp==BT_LOCK_SHARED || eOp==BT_LOCK_EXCL ); /* Check for a no-op. Proceed only if this is not one of those. */ if( (eOp==BT_LOCK_UNLOCK && (mask & (p->mExclLock|p->mSharedLock))!=0) || (eOp==BT_LOCK_SHARED && (mask & p->mSharedLock)==0) || (eOp==BT_LOCK_EXCL && (mask & p->mExclLock)==0) ){ BtLock *pIter; int nExcl = 0; /* Number of connections holding EXCLUSIVE */ int nShared = 0; /* Number of connections holding SHARED */ sqlite4_mutex_enter(pShared->pClientMutex); /* Figure out the locks currently held by this process on iLock, not ** including any held by this connection. */ for(pIter=pShared->pLock; pIter; pIter=pIter->pNext){ assert( (pIter->mExclLock & pIter->mSharedLock)==0 ); if( pIter!=p ){ assert( (pIter->mExclLock & p->mSharedLock)==0 ); assert( (pIter->mSharedLock & p->mExclLock)==0 ); if( mask & pIter->mExclLock ){ nExcl++; }else if( mask & pIter->mSharedLock ){ nShared++; |
︙ | ︙ | |||
168 169 170 171 172 173 174 | if( nExcl || nShared ){ rc = SQLITE4_BUSY; }else{ #if 0 rc = lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_EXCL); #endif if( rc==SQLITE4_OK ){ | | | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | if( nExcl || nShared ){ rc = SQLITE4_BUSY; }else{ #if 0 rc = lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_EXCL); #endif if( rc==SQLITE4_OK ){ p->mSharedLock &= ~mask; p->mExclLock |= mask; } } break; } sqlite4_mutex_leave(p->pClientMutex); |
︙ | ︙ | |||
356 357 358 359 360 361 362 | ** the entire log has been checkpointed (and iFirst is the "next" ** frame to use). Handle this case in the same way as an empty ** log file. ** ** It is also possible that the iFirst value (read from the shared-memory ** checkpoint header) is much newer than the aLog[] values (read from ** the snapshot header). If so, the caller will figure it out. */ | | | | > > > > | | > > > > > < > > > > > > | > > | 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 | ** the entire log has been checkpointed (and iFirst is the "next" ** frame to use). Handle this case in the same way as an empty ** log file. ** ** It is also possible that the iFirst value (read from the shared-memory ** checkpoint header) is much newer than the aLog[] values (read from ** the snapshot header). If so, the caller will figure it out. */ if( (iFirst<aLog[0] || iFirst>aLog[1]) && (iFirst<aLog[2] || iFirst>aLog[3]) && (iFirst<aLog[4] || iFirst>aLog[5]) ){ iLast = 0; } if( iLast==0 ){ rc = btLockLockop(pLock, BT_LOCK_READER_DBONLY, BT_LOCK_SHARED, 0); }else{ int nAttempt = 100; /* Remaining lock attempts */ while( rc==SQLITE4_BUSY && (nAttempt--)>0 ){ int iIdxFirst = sqlite4BtLogFrameToIdx(aLog, iFirst); int iIdxLast = sqlite4BtLogFrameToIdx(aLog, iLast); assert( iIdxFirst>=0 && iIdxLast>=0 ); /* Try to find a slot populated with the values required. */ for(i=0; i<BT_NREADER; i++){ if( aSlot[i].iFirst==iFirst && aSlot[i].iLast==iLast ) break; } /* Or, if there is no slot with the required values - try to create one */ if( i==BT_NREADER ){ for(i=0; i<BT_NREADER; i++){ rc = btLockLockop(pLock, BT_LOCK_READER0 + i, BT_LOCK_EXCL, 0); if( rc==SQLITE4_OK ){ /* The EXCLUSIVE lock obtained by the successful call to ** btLockLockop() is released below by the call to obtain ** a SHARED lock on the same locking slot. */ aSlot[i].iFirst = iFirst; aSlot[i].iLast = iLast; break; }else if( rc!=SQLITE4_BUSY ){ return rc; } } } /* If no existing slot with the required values was found, and the ** attempt to create one failed, search for any usable slot. A ** usable slot is one where both the "iFirst" and "iLast" values ** occur at the same point or earlier in the log than the required ** iFirst/iLast values, respectively. */ if( i==BT_NREADER ){ for(i=0; i<BT_NREADER; i++){ int iSlotFirst = sqlite4BtLogFrameToIdx(aLog, aSlot[i].iFirst); int iSlotLast = sqlite4BtLogFrameToIdx(aLog, aSlot[i].iLast); if( iSlotFirst<0 || iSlotLast<0 ) continue; if( iSlotFirst<=iIdxFirst && iSlotLast<=iIdxLast ) break; } } if( i<BT_NREADER ){ rc = btLockLockop(pLock, BT_LOCK_READER0 + i, BT_LOCK_SHARED, 0); if( rc==SQLITE4_OK ){ int iSF = sqlite4BtLogFrameToIdx(aLog, aSlot[i].iFirst); int iSL = sqlite4BtLogFrameToIdx(aLog, aSlot[i].iLast); if( iSF>iIdxFirst || iSL>iIdxLast || iSF<0 || iSL<0 ){ btLockLockop(pLock, BT_LOCK_READER0 + i, BT_LOCK_UNLOCK, 0); rc = SQLITE4_BUSY; } } } } } |
︙ | ︙ |
Changes to src/bt_pager.c.
︙ | ︙ | |||
381 382 383 384 385 386 387 388 389 390 391 392 393 394 | rc = sqlite4BtLockDisconnect((BtLock*)p, btCheckpoint, btCleanup); if( p->btl.pFd ){ p->btl.pVfs->xClose(p->btl.pFd); } btCloseSavepoints(p, 0); btPurgeCache(p); sqlite4BtLogClose(p->pLog, 0); sqlite4_free(p->btl.pEnv, p->zFile); sqlite4_free(p->btl.pEnv, p->aSavepoint); sqlite4_free(p->btl.pEnv, p); return rc; | > | 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 | rc = sqlite4BtLockDisconnect((BtLock*)p, btCheckpoint, btCleanup); if( p->btl.pFd ){ p->btl.pVfs->xClose(p->btl.pFd); } p->iTransactionLevel = 0; btCloseSavepoints(p, 0); btPurgeCache(p); sqlite4BtLogClose(p->pLog, 0); sqlite4_free(p->btl.pEnv, p->zFile); sqlite4_free(p->btl.pEnv, p->aSavepoint); sqlite4_free(p->btl.pEnv, p); return rc; |
︙ | ︙ |