Compare commits

...

6 Commits

Author SHA1 Message Date
drh 00b04303de The iInUseDB and iInUseMM variables do not need to be volatile.
FossilOrigin-Name: bb18f5785283e1067338b6b85098e8f2ff3b093a
2010-01-30 23:08:24 +00:00
drh 5b6532a272 Always hold the MEM2 mutex when initially marking a pager as in use by its
database connection.

FossilOrigin-Name: 622c17177af6851fec11bdec8fb6246c13135b2f
2010-01-30 22:28:46 +00:00
drh 20d8778d82 Avoid a race condition in the sqlite3_release_memory() logic within pager.c.
FossilOrigin-Name: a718e6634795a48b5dd5c08833ab561e6381a62d
2010-01-30 19:17:07 +00:00
drh 88aee1b7ea Remove all cache pages from the LRU list prior to removing the pager from the
pager list when closing a pager.

FossilOrigin-Name: 9d13acc4493ee8be9e6cbf887cd7876d6239b952
2010-01-30 19:00:55 +00:00
drh 19fc303116 Add additional pagerMutexHeld() macros to better verify the correct operation
of pager.c.

FossilOrigin-Name: c50e972f1bea2e357f64ffd5df868bf51d942e2d
2010-01-30 18:22:56 +00:00
drh 10f1b20a69 Fix a missing mutex on page cache truncation during vacuum and auto-vacuum
when SQLITE_ENABLE_MEMORY_MANAGEMENT is engaged.

FossilOrigin-Name: ea3b941a7182851117fab9851e98e175ebb356e2
2010-01-29 21:23:35 +00:00
3 changed files with 57 additions and 28 deletions
+16 -6
View File
@@ -1,5 +1,8 @@
C Version\s3.5.9\s(CVS\s5131)
D 2008-05-14T16:18:11
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
C The\siInUseDB\sand\siInUseMM\svariables\sdo\snot\sneed\sto\sbe\svolatile.
D 2010-01-30T23:08:24
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in 79aeba12300a54903f1b1257c1e7c190234045dd
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -121,7 +124,7 @@ F src/os_common.h e8b748b2f2ecc8a498e50bfe5d8721f189c19d2a
F src/os_os2.c 0c3a5802bc4fdb7cb5f66771552b081c4e48a216
F src/os_unix.c a810e2aefdaddacf479407f76f8f4ca381d231b2
F src/os_win.c 3a60bddd07ea6f8adb2314dd5996ac97b988f403
F src/pager.c 2607309c4848bfb8a5766d94d74157b54a44c6c0
F src/pager.c 8e6b147f46c80fe31ee4d202d2478f461aa7ce18
F src/pager.h 4f051fd856de6fd3c19aef5f82eace54122b9173
F src/parse.y fc4bd35c6088901f7c8daead26c6fb11c87d22e7
F src/pragma.c 2e4bb2e76e48a32750529fdc4bfe86ac5f54e01b
@@ -634,7 +637,14 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
P e4aab150042bd22868ab02645151cb69a1c02ba0
R c25ac8c50b83839e3cddbf23a801f9cb
P 622c17177af6851fec11bdec8fb6246c13135b2f
R e9eaccaf9f16fa14643ac18463a7e091
U drh
Z 5d9759a5b998826f7607e53c2a3b8fed
Z ba00ac2997800f42b378226025ca0d50
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFLZLvqoxKgR168RlERAizUAJ9Di56YC1Zc+ZRYvDwFKYstmzdmgACdGglw
1AHQmR5SOB5iTAk/+APTz0g=
=9KoF
-----END PGP SIGNATURE-----
+1 -1
View File
@@ -1 +1 @@
b6129f4cc28f6ba55d19039545555b33857ffd72
bb18f5785283e1067338b6b85098e8f2ff3b093a
+40 -21
View File
@@ -401,8 +401,9 @@ struct Pager {
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
Pager *pNext; /* Doubly linked list of pagers on which */
Pager *pPrev; /* sqlite3_release_memory() will work */
int iInUseMM; /* Non-zero if unavailable to MM */
int iInUseDB; /* Non-zero if in sqlite3_release_memory() */
u8 iInUseMM; /* Non-zero if unavailable to MM */
u8 onPagerList; /* True if part of the sqlite3PagerList */
#endif
char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
char dbFileVers[16]; /* Changes whenever database file changes */
@@ -511,29 +512,35 @@ static const unsigned char aJournalMagic[] = {
** function. It does not prevent, for example, two Btrees from accessing
** the same pager at the same time. Other general-purpose mutexes in
** the btree layer handle that chore.
**
** The pagerMutexHeld(X) macro is for sanity checking. This macro verifies
** that the database-connection mutex is held for pager X and asserts if it
** is not.
*/
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
static void pagerEnter(Pager *p){
p->iInUseDB++;
if( p->iInUseMM && p->iInUseDB==1 ){
if( p->iInUseDB>0 ){
p->iInUseDB++;
}else{
#ifndef SQLITE_MUTEX_NOOP
sqlite3_mutex *mutex;
mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MEM2);
#endif
p->iInUseDB = 0;
sqlite3_mutex_enter(mutex);
assert( p->iInUseMM==0 );
p->iInUseDB = 1;
sqlite3_mutex_leave(mutex);
}
assert( p->iInUseMM==0 );
}
static void pagerLeave(Pager *p){
p->iInUseDB--;
assert( p->iInUseDB>=0 );
}
# define pagerMutexHeld(X) assert( (X)->iInUseDB>0 || !(X)->onPagerList )
#else
# define pagerEnter(X)
# define pagerLeave(X)
# define pagerMutexHeld(X)
#endif
/*
@@ -699,6 +706,7 @@ static void pager_resize_hash_table(Pager *pPager, int N){
sqlite3_free(pPager->aHash);
pPager->nHash = N;
pPager->aHash = aHash;
pagerMutexHeld(pPager);
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
int h;
if( pPg->pgno==0 ){
@@ -1273,6 +1281,7 @@ static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
static void pager_reset(Pager *pPager){
PgHdr *pPg, *pNext;
if( pPager->errCode ) return;
pagerMutexHeld(pPager);
for(pPg=pPager->pAll; pPg; pPg=pNext){
IOTRACE(("PGFREE %p %d\n", pPager, pPg->pgno));
PAGER_INCR(sqlite3_pager_pgfree_count);
@@ -1416,6 +1425,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
}
sqlite3BitvecDestroy(pPager->pInJournal);
pPager->pInJournal = 0;
pagerMutexHeld(pPager);
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
pPg->inJournal = 0;
pPg->dirty = 0;
@@ -2373,6 +2383,7 @@ int sqlite3PagerOpen(
}
pPager->pPrev = 0;
sqlite3PagerList = pPager;
pPager->onPagerList = 1;
sqlite3_mutex_leave(mutex);
}
#endif
@@ -2637,6 +2648,7 @@ static void pager_truncate_cache(Pager *pPager){
PgHdr **ppPg;
int dbSize = pPager->dbSize;
pagerMutexHeld(pPager);
ppPg = &pPager->pAll;
while( (pPg = *ppPg)!=0 ){
if( pPg->pgno<=dbSize ){
@@ -2707,7 +2719,9 @@ int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
}
if( MEMDB ){
pPager->dbSize = nPage;
pagerEnter(pPager);
pager_truncate_cache(pPager);
pagerLeave(pPager);
return SQLITE_OK;
}
pagerEnter(pPager);
@@ -2720,12 +2734,10 @@ int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
/* Get an exclusive lock on the database before truncating. */
pagerEnter(pPager);
rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
pagerLeave(pPager);
if( rc!=SQLITE_OK ){
return rc;
if( rc==SQLITE_OK ){
rc = pager_truncate(pPager, nPage);
}
rc = pager_truncate(pPager, nPage);
pagerLeave(pPager);
return rc;
}
@@ -2744,6 +2756,10 @@ int sqlite3PagerTruncate(Pager *pPager, Pgno nPage){
** to the caller.
*/
int sqlite3PagerClose(Pager *pPager){
pagerEnter(pPager);
pPager->errCode = 0;
pager_reset(pPager);
pagerLeave(pPager);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
if( !MEMDB ){
#ifndef SQLITE_MUTEX_NOOP
@@ -2759,14 +2775,12 @@ int sqlite3PagerClose(Pager *pPager){
pPager->pNext->pPrev = pPager->pPrev;
}
sqlite3_mutex_leave(mutex);
pPager->onPagerList = 0;
}
#endif
disable_simulated_io_errors();
sqlite3FaultBeginBenign(-1);
pPager->errCode = 0;
pPager->exclusiveMode = 0;
pager_reset(pPager);
pagerUnlockAndRollback(pPager);
enable_simulated_io_errors();
sqlite3FaultEndBenign(-1);
@@ -2930,6 +2944,7 @@ static int syncJournal(Pager *pPager){
** invariant is true.
*/
else{
pagerMutexHeld(pPager);
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
assert( pPg->needSync==0 );
}
@@ -3168,7 +3183,7 @@ static int pager_recycle(Pager *pPager, PgHdr **ppPg){
/* It is illegal to call this function unless the pager object
** pointed to by pPager has at least one free page (page with nRef==0).
*/
*/
assert(!MEMDB);
assert(pPager->lru.pFirst);
@@ -3279,7 +3294,6 @@ int sqlite3PagerReleaseMemory(int nReq){
while( rc==SQLITE_OK && (nReq<0 || nReleased<nReq) ){
PgHdr *pPg;
PgHdr *pRecycled;
/* Try to find a page to recycle that does not require a sync(). If
** this is not possible, find one that does require a sync().
@@ -3304,14 +3318,12 @@ int sqlite3PagerReleaseMemory(int nReq){
if( !pPg ) break;
pPager = pPg->pPager;
assert(!pPg->needSync || pPg==pPager->lru.pFirst);
assert(pPg->needSync || pPg==pPager->lru.pFirstSynced);
assert( pPager->iInUseDB==0 );
savedBusy = pPager->pBusyHandler;
pPager->pBusyHandler = 0;
rc = pager_recycle(pPager, &pRecycled);
rc = pager_recycle(pPager, &pPg);
assert( pPager->iInUseDB==0 );
pPager->pBusyHandler = savedBusy;
assert(pRecycled==pPg || rc!=SQLITE_OK);
if( rc==SQLITE_OK ){
/* We've found a page to free. At this point the page has been
** removed from the page hash-table, free-list and synced-list
@@ -3618,8 +3630,11 @@ static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){
PgHdr *pPg;
int nByteHdr;
/* Create a new PgHdr if any of the four conditions defined
** above are met: */
** above are met:
*/
pagerMutexHeld(pPager);
if( pPager->nPage<pPager->mxPage
|| pPager->lru.pFirst==0
|| MEMDB
@@ -3653,11 +3668,13 @@ static int pagerAllocatePage(Pager *pPager, PgHdr **ppPg){
memset(pPg, 0, nByteHdr);
pPg->pData = pData;
pPg->pPager = pPager;
pagerMutexHeld(pPager);
pPg->pNextAll = pPager->pAll;
pPager->pAll = pPg;
pPager->nPage++;
}else{
/* Recycle an existing page with a zero ref-count. */
pagerMutexHeld(pPager);
rc = pager_recycle(pPager, &pPg);
if( rc==SQLITE_BUSY ){
rc = SQLITE_IOERR_BLOCKED;
@@ -4704,6 +4721,7 @@ int sqlite3PagerCommitPhaseOne(
#endif
rc = writeMasterJournal(pPager, zMaster);
if( rc!=SQLITE_OK ) goto sync_exit;
pagerMutexHeld(pPager);
rc = syncJournal(pPager);
}
if( rc!=SQLITE_OK ) goto sync_exit;
@@ -4831,6 +4849,7 @@ int sqlite3PagerRollback(Pager *pPager){
PAGERTRACE2("ROLLBACK %d\n", PAGERID(pPager));
if( MEMDB ){
PgHdr *p;
pagerMutexHeld(pPager);
for(p=pPager->pAll; p; p=p->pNextAll){
PgHistory *pHist;
assert( !p->alwaysRollback );