1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Fixes for error handling with temp databases. And for errors that occur within OS locking primitives.

FossilOrigin-Name: f99a902f9b3d0bf6f607c4ba641b4096fbbef5d5
This commit is contained in:
dan
2010-08-05 15:30:22 +00:00
parent 431b0b4291
commit 4e004aa6b9
3 changed files with 102 additions and 93 deletions

View File

@@ -1,5 +1,5 @@
C Fix\ssome\sproblems\swith\serror\srecovery\sintroduced\swhile\sreworking\spager\sstate. C Fixes\sfor\serror\shandling\swith\stemp\sdatabases.\sAnd\sfor\serrors\sthat\soccur\swithin\sOS\slocking\sprimitives.
D 2010-08-04T19:14:22 D 2010-08-05T15:30:22
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e F Makefile.in ec08dc838fd8110fe24c92e5130bcd91cbb1ff2e
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -156,7 +156,7 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e
F src/os_unix.c ae5ca8a6031380708f3fec7be325233d49944914 F src/os_unix.c ae5ca8a6031380708f3fec7be325233d49944914
F src/os_win.c 51cb62f76262d961ea4249489383d714501315a7 F src/os_win.c 51cb62f76262d961ea4249489383d714501315a7
F src/pager.c d181fe863c886da94d7c19cf62385858e610384e F src/pager.c c09ca0cf83f928f0299be6620322acd9c38fa3ce
F src/pager.h 80726162dc3942f59ab27b738fb667b9ba0a89d5 F src/pager.h 80726162dc3942f59ab27b738fb667b9ba0a89d5
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58 F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
F src/pcache.c 1e9aa2dbc0845b52e1b51cc39753b6d1e041cb07 F src/pcache.c 1e9aa2dbc0845b52e1b51cc39753b6d1e041cb07
@@ -842,7 +842,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P 15368a9f8523d5fb611cd576080daed2cf2f1500 P 77eaab6f77c53cc4f429b65dfcf287ad6084c2da
R 38aa93658d08e993fa60d40008fca82a R 002859c356edc1f0f7f124dc9ba8ad0d
U dan U dan
Z 9ffe03344bd2caf8cb58c57ef391fd3e Z f6fbebc4624605af3301d8eb4f042add

View File

@@ -1 +1 @@
77eaab6f77c53cc4f429b65dfcf287ad6084c2da f99a902f9b3d0bf6f607c4ba641b4096fbbef5d5

View File

@@ -345,6 +345,8 @@ int sqlite3PagerTrace=1; /* True to enable tracing */
#define PAGER_EXCLUSIVE 4 /* same as EXCLUSIVE_LOCK */ #define PAGER_EXCLUSIVE 4 /* same as EXCLUSIVE_LOCK */
#define PAGER_SYNCED 5 #define PAGER_SYNCED 5
#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1)
/* /*
** A macro used for invoking the codec if there is one ** A macro used for invoking the codec if there is one
*/ */
@@ -721,17 +723,18 @@ static int assert_pager_state(Pager *p){
switch( p->eState ){ switch( p->eState ){
case PAGER_NONE: case PAGER_NONE:
assert( !MEMDB ); assert( !MEMDB );
assert( !p->tempFile );
assert( pPager->errCode==SQLITE_OK ); assert( pPager->errCode==SQLITE_OK );
assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); assert( sqlite3PcacheRefCount(pPager->pPCache)==0 || pPager->tempFile );
break; break;
case PAGER_READER: case PAGER_READER:
assert( pPager->errCode==SQLITE_OK ); assert( pPager->errCode==SQLITE_OK );
assert( p->eLock!=UNKNOWN_LOCK );
assert( p->eLock>=SHARED_LOCK || p->noReadlock ); assert( p->eLock>=SHARED_LOCK || p->noReadlock );
break; break;
case PAGER_WRITER_INITIAL: case PAGER_WRITER_INITIAL:
assert( p->eLock!=UNKNOWN_LOCK );
assert( pPager->errCode==SQLITE_OK ); assert( pPager->errCode==SQLITE_OK );
if( !pagerUseWal(pPager) ){ if( !pagerUseWal(pPager) ){
assert( p->eLock>=RESERVED_LOCK ); assert( p->eLock>=RESERVED_LOCK );
@@ -742,6 +745,7 @@ static int assert_pager_state(Pager *p){
break; break;
case PAGER_WRITER_CACHEMOD: case PAGER_WRITER_CACHEMOD:
assert( p->eLock!=UNKNOWN_LOCK );
assert( pPager->errCode==SQLITE_OK ); assert( pPager->errCode==SQLITE_OK );
if( !pagerUseWal(pPager) ){ if( !pagerUseWal(pPager) ){
/* It is possible that if journal_mode=wal here that neither the /* It is possible that if journal_mode=wal here that neither the
@@ -759,9 +763,10 @@ static int assert_pager_state(Pager *p){
break; break;
case PAGER_WRITER_DBMOD: case PAGER_WRITER_DBMOD:
assert( p->eLock==EXCLUSIVE_LOCK );
assert( pPager->errCode==SQLITE_OK ); assert( pPager->errCode==SQLITE_OK );
assert( !pagerUseWal(pPager) ); assert( !pagerUseWal(pPager) );
assert( p->eLock>=EXCLUSIVE_LOCK || pagerUseWal(pPager) ); assert( p->eLock>=EXCLUSIVE_LOCK );
assert( isOpen(p->jfd) assert( isOpen(p->jfd)
|| p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_OFF
|| p->journalMode==PAGER_JOURNALMODE_WAL || p->journalMode==PAGER_JOURNALMODE_WAL
@@ -769,9 +774,9 @@ static int assert_pager_state(Pager *p){
break; break;
case PAGER_WRITER_FINISHED: case PAGER_WRITER_FINISHED:
assert( p->eLock==EXCLUSIVE_LOCK );
assert( pPager->errCode==SQLITE_OK ); assert( pPager->errCode==SQLITE_OK );
assert( !pagerUseWal(pPager) ); assert( !pagerUseWal(pPager) );
assert( p->eLock>=EXCLUSIVE_LOCK || pagerUseWal(pPager) );
assert( isOpen(p->jfd) assert( isOpen(p->jfd)
|| p->journalMode==PAGER_JOURNALMODE_OFF || p->journalMode==PAGER_JOURNALMODE_OFF
|| p->journalMode==PAGER_JOURNALMODE_WAL || p->journalMode==PAGER_JOURNALMODE_WAL
@@ -798,11 +803,12 @@ static char *print_pager_state(Pager *p){
static char zRet[1024]; static char zRet[1024];
sqlite3_snprintf(1024, zRet, sqlite3_snprintf(1024, zRet,
"State: %s\n" "State: %s errCode=%d\n"
"Lock: %s\n" "Lock: %s\n"
"Locking mode: locking_mode=%s\n" "Locking mode: locking_mode=%s\n"
"Journal mode: journal_mode=%s\n" "Journal mode: journal_mode=%s\n"
"Backing store: tempFile=%d memDb=%d useJournal=%d\n" "Backing store: tempFile=%d memDb=%d useJournal=%d\n"
"Journal: journalOff=%lld journalHdr=%lld\n"
, p->eState==PAGER_NONE ? "NONE" : , p->eState==PAGER_NONE ? "NONE" :
p->eState==PAGER_READER ? "READER" : p->eState==PAGER_READER ? "READER" :
p->eState==PAGER_WRITER_INITIAL ? "WRITER_INITIAL" : p->eState==PAGER_WRITER_INITIAL ? "WRITER_INITIAL" :
@@ -810,10 +816,12 @@ static char *print_pager_state(Pager *p){
p->eState==PAGER_WRITER_DBMOD ? "WRITER_DBMOD" : p->eState==PAGER_WRITER_DBMOD ? "WRITER_DBMOD" :
p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" : p->eState==PAGER_WRITER_FINISHED ? "WRITER_FINISHED" :
p->eState==PAGER_ERROR ? "ERROR" : "?error?" p->eState==PAGER_ERROR ? "ERROR" : "?error?"
, (int)p->errCode
, p->eLock==NO_LOCK ? "NONE" : , p->eLock==NO_LOCK ? "NONE" :
p->eLock==RESERVED_LOCK ? "RESERVED" : p->eLock==RESERVED_LOCK ? "RESERVED" :
p->eLock==EXCLUSIVE_LOCK ? "EXCLUSIVE" : p->eLock==EXCLUSIVE_LOCK ? "EXCLUSIVE" :
p->eLock==SHARED_LOCK ? "SHARED" : "?error?" p->eLock==SHARED_LOCK ? "SHARED" :
p->eLock==UNKNOWN_LOCK ? "UNKNOWN" : "?error?"
, p->exclusiveMode ? "exclusive" : "normal" , p->exclusiveMode ? "exclusive" : "normal"
, p->journalMode==PAGER_JOURNALMODE_MEMORY ? "memory" : , p->journalMode==PAGER_JOURNALMODE_MEMORY ? "memory" :
p->journalMode==PAGER_JOURNALMODE_OFF ? "off" : p->journalMode==PAGER_JOURNALMODE_OFF ? "off" :
@@ -822,6 +830,7 @@ static char *print_pager_state(Pager *p){
p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" : p->journalMode==PAGER_JOURNALMODE_TRUNCATE ? "truncate" :
p->journalMode==PAGER_JOURNALMODE_WAL ? "wal" : "?error?" p->journalMode==PAGER_JOURNALMODE_WAL ? "wal" : "?error?"
, (int)p->tempFile, (int)p->memDb, (int)p->useJournal , (int)p->tempFile, (int)p->memDb, (int)p->useJournal
, p->journalOff, p->journalHdr
); );
return zRet; return zRet;
@@ -890,31 +899,35 @@ static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
} }
/* /*
** If file pFd is open, call sqlite3OsUnlock() on it. ** This function and pagerLockDb() are wrappers around sqlite3OsLock() and
** sqlite3OsUnlock() that set the Pager.eLock variable to reflect the
** current lock held on the database file.
*/ */
static int osUnlock(Pager *pPager, int eLock){ static int pagerUnlockDb(Pager *pPager, int eLock){
int rc = SQLITE_OK; int rc = SQLITE_OK;
assert( !pPager->exclusiveMode );
if( isOpen(pPager->fd) ){ if( isOpen(pPager->fd) ){
assert( pPager->eLock>=eLock ); assert( pPager->eLock>=eLock );
assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 ); assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
rc = sqlite3OsUnlock(pPager->fd, eLock); rc = sqlite3OsUnlock(pPager->fd, eLock);
if( rc==SQLITE_OK ){ if( pPager->eLock!=UNKNOWN_LOCK ){
pPager->eLock = eLock; pPager->eLock = eLock;
} }
IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
} }
return rc; return rc;
} }
static int osLock(Pager *pPager, int eLock){ static int pagerLockDb(Pager *pPager, int eLock){
int rc; int rc;
assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK ); assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
if( pPager->eLock>=eLock ){ if( pPager->eLock>=eLock && pPager->eLock!=UNKNOWN_LOCK ){
rc = SQLITE_OK; rc = SQLITE_OK;
}else{ }else{
rc = sqlite3OsLock(pPager->fd, eLock); rc = sqlite3OsLock(pPager->fd, eLock);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
pPager->eLock = eLock; pPager->eLock = eLock;
IOTRACE(("LOCK %p %d\n", pPager, locktype)) IOTRACE(("LOCK %p %d\n", pPager, eLock))
} }
} }
return rc; return rc;
@@ -1550,6 +1563,7 @@ static void pager_unlock(Pager *pPager){
sqlite3WalEndReadTransaction(pPager->pWal); sqlite3WalEndReadTransaction(pPager->pWal);
pPager->eState = PAGER_NONE; pPager->eState = PAGER_NONE;
}else if( !pPager->exclusiveMode ){ }else if( !pPager->exclusiveMode ){
int rc; /* Error code returned by pagerUnlockDb() */
int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0; int iDc = isOpen(pPager->fd)?sqlite3OsDeviceCharacteristics(pPager->fd):0;
/* If the operating system support deletion of open files, then /* If the operating system support deletion of open files, then
@@ -1568,7 +1582,11 @@ static void pager_unlock(Pager *pPager){
){ ){
sqlite3OsClose(pPager->jfd); sqlite3OsClose(pPager->jfd);
} }
osUnlock(pPager, NO_LOCK);
rc = pagerUnlockDb(pPager, NO_LOCK);
if( rc!=SQLITE_OK && pPager->eState==PAGER_ERROR ){
pPager->eLock = UNKNOWN_LOCK;
}
/* The pager state may be changed from PAGER_ERROR to PAGER_NONE here /* The pager state may be changed from PAGER_ERROR to PAGER_NONE here
** without clearing the error code. This is intentional - the error ** without clearing the error code. This is intentional - the error
@@ -1577,7 +1595,6 @@ static void pager_unlock(Pager *pPager){
assert( pPager->errCode || pPager->eState!=PAGER_ERROR ); assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
pPager->changeCountDone = 0; pPager->changeCountDone = 0;
pPager->eState = PAGER_NONE; pPager->eState = PAGER_NONE;
IOTRACE(("UNLOCK %p\n", pPager))
} }
/* If Pager.errCode is set, the contents of the pager cache cannot be /* If Pager.errCode is set, the contents of the pager cache cannot be
@@ -1585,12 +1602,16 @@ static void pager_unlock(Pager *pPager){
** it can safely move back to PAGER_NONE state. This happens in both ** it can safely move back to PAGER_NONE state. This happens in both
** normal and exclusive-locking mode. ** normal and exclusive-locking mode.
*/ */
if( pPager->errCode && !pPager->tempFile ){ if( pPager->errCode && !MEMDB ){
pager_reset(pPager); pager_reset(pPager);
pPager->changeCountDone = 0; pPager->changeCountDone = pPager->tempFile;
pPager->eState = PAGER_NONE; pPager->eState = PAGER_NONE;
pPager->errCode = SQLITE_OK; pPager->errCode = SQLITE_OK;
} }
pPager->journalOff = 0;
pPager->journalHdr = 0;
pPager->setMaster = 0;
} }
/* /*
@@ -1752,7 +1773,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
if( !pPager->exclusiveMode if( !pPager->exclusiveMode
&& (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0)) && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
){ ){
rc2 = osUnlock(pPager, SHARED_LOCK); rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
pPager->changeCountDone = 0; pPager->changeCountDone = 0;
} }
pPager->eState = PAGER_READER; pPager->eState = PAGER_READER;
@@ -1934,7 +1955,9 @@ static int pager_playback_one_page(
if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){ if( pDone && (rc = sqlite3BitvecSet(pDone, pgno))!=SQLITE_OK ){
return rc; return rc;
} }
assert( pPager->eState>=PAGER_WRITER_CACHEMOD ); assert( pPager->eState>=PAGER_WRITER_CACHEMOD
|| (pPager->eState==PAGER_NONE && isMainJrnl)
);
/* When playing back page 1, restore the nReserve setting /* When playing back page 1, restore the nReserve setting
*/ */
@@ -1990,7 +2013,7 @@ static int pager_playback_one_page(
}else{ }else{
isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC)); isSynced = (pPg==0 || 0==(pPg->flags & PGHDR_NEED_SYNC));
} }
if( (pPager->eState>=PAGER_WRITER_DBMOD) if( (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_NONE)
&& isOpen(pPager->fd) && isOpen(pPager->fd)
&& isSynced && isSynced
){ ){
@@ -2239,7 +2262,11 @@ delmaster_out:
static int pager_truncate(Pager *pPager, Pgno nPage){ static int pager_truncate(Pager *pPager, Pgno nPage){
int rc = SQLITE_OK; int rc = SQLITE_OK;
assert( pPager->eState!=PAGER_ERROR ); assert( pPager->eState!=PAGER_ERROR );
if( pPager->eState>=PAGER_WRITER_DBMOD && isOpen(pPager->fd) ){ assert( pPager->eState!=PAGER_READER );
if( isOpen(pPager->fd)
&& (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_NONE)
){
i64 currentSize, newSize; i64 currentSize, newSize;
/* TODO: Is it safe to use Pager.dbFileSize here? */ /* TODO: Is it safe to use Pager.dbFileSize here? */
rc = sqlite3OsFileSize(pPager->fd, &currentSize); rc = sqlite3OsFileSize(pPager->fd, &currentSize);
@@ -2817,7 +2844,7 @@ static int pagerOpenWalIfPresent(Pager *pPager){
} }
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
if( isWal ){ if( isWal ){
assert( sqlite3PcachePagecount(pPager->pPCache)==0 ); testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
rc = sqlite3PagerOpenWal(pPager, 0); rc = sqlite3PagerOpenWal(pPager, 0);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = pagerBeginReadTransaction(pPager); rc = pagerBeginReadTransaction(pPager);
@@ -3144,7 +3171,6 @@ int sqlite3PagerSetPagesize(Pager *pPager, u16 *pPageSize, int nReserve){
if( !pNew ){ if( !pNew ){
rc = SQLITE_NOMEM; rc = SQLITE_NOMEM;
}else{ }else{
assert( pPager->eState==PAGER_NONE || pPager->eState==PAGER_READER );
pager_reset(pPager); pager_reset(pPager);
pPager->dbSize = nByte/pageSize; pPager->dbSize = nByte/pageSize;
pPager->pageSize = pageSize; pPager->pageSize = pageSize;
@@ -3297,13 +3323,9 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
|| (pPager->eLock==RESERVED_LOCK && locktype==EXCLUSIVE_LOCK) || (pPager->eLock==RESERVED_LOCK && locktype==EXCLUSIVE_LOCK)
); );
if( pPager->eLock>=locktype ){ do {
rc = SQLITE_OK; rc = pagerLockDb(pPager, locktype);
}else{ }while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) );
do {
rc = osLock(pPager, locktype);
}while( rc==SQLITE_BUSY && pPager->xBusyHandler(pPager->pBusyHandlerArg) );
}
return rc; return rc;
} }
@@ -4300,9 +4322,9 @@ static int hasHotJournal(Pager *pPager, int *pExists){
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
if( nPage==0 ){ if( nPage==0 ){
sqlite3BeginBenignMalloc(); sqlite3BeginBenignMalloc();
if( osLock(pPager, RESERVED_LOCK)==SQLITE_OK ){ if( pagerLockDb(pPager, RESERVED_LOCK)==SQLITE_OK ){
sqlite3OsDelete(pVfs, pPager->zJournal, 0); sqlite3OsDelete(pVfs, pPager->zJournal, 0);
osUnlock(pPager, SHARED_LOCK); pagerUnlockDb(pPager, SHARED_LOCK);
} }
sqlite3EndBenignMalloc(); sqlite3EndBenignMalloc();
}else{ }else{
@@ -4388,14 +4410,14 @@ int sqlite3PagerSharedLock(Pager *pPager){
** exclusive access mode. ** exclusive access mode.
*/ */
assert( sqlite3PcacheRefCount(pPager->pPCache)==0 ); assert( sqlite3PcacheRefCount(pPager->pPCache)==0 );
assert( pPager->eState==PAGER_NONE || pPager->eState==PAGER_READER );
assert( assert_pager_state(pPager) ); assert( assert_pager_state(pPager) );
assert( pPager->eState==PAGER_NONE || pPager->eState==PAGER_READER );
if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; } if( NEVER(MEMDB && pPager->errCode) ){ return pPager->errCode; }
if( !pagerUseWal(pPager) && pPager->eState==PAGER_NONE ){ if( !pagerUseWal(pPager) && pPager->eState==PAGER_NONE ){
int bHotJournal = 1; /* True if there exists a hot journal-file */ int bHotJournal = 1; /* True if there exists a hot journal-file */
assert( !MEMDB && !pPager->tempFile ); assert( !MEMDB );
assert( pPager->noReadlock==0 || pPager->readOnly ); assert( pPager->noReadlock==0 || pPager->readOnly );
if( pPager->noReadlock==0 ){ if( pPager->noReadlock==0 ){
@@ -4431,7 +4453,7 @@ int sqlite3PagerSharedLock(Pager *pPager){
** Unless the pager is in locking_mode=exclusive mode, the lock is ** Unless the pager is in locking_mode=exclusive mode, the lock is
** downgraded to SHARED_LOCK before this function returns. ** downgraded to SHARED_LOCK before this function returns.
*/ */
rc = osLock(pPager, EXCLUSIVE_LOCK); rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
goto failed; goto failed;
} }
@@ -4466,17 +4488,6 @@ int sqlite3PagerSharedLock(Pager *pPager){
} }
} }
} }
if( rc!=SQLITE_OK ){
goto failed;
}
/* Reset the journal status fields to indicates that we have no
** rollback journal at this time. */
pPager->journalOff = 0;
pPager->setMaster = 0;
pPager->journalHdr = 0;
/* Make sure the journal file has been synced to disk. */
/* Playback and delete the journal. Drop the database write /* Playback and delete the journal. Drop the database write
** lock and reacquire the read lock. Purge the cache before ** lock and reacquire the read lock. Purge the cache before
@@ -4485,24 +4496,21 @@ int sqlite3PagerSharedLock(Pager *pPager){
** it back since the process that crashed and left the hot journal ** it back since the process that crashed and left the hot journal
** probably did not sync it and we are required to always sync ** probably did not sync it and we are required to always sync
** the journal before playing it back. ** the journal before playing it back.
**
** Even if an error occurs while syncing or rolling back the
** hot-journal, there is no need to enter the ERROR state here, as
** the pager never left state NONE anyhow.
*/ */
if( isOpen(pPager->jfd) ){ if( isOpen(pPager->jfd) ){
assert( rc==SQLITE_OK );
rc = pagerSyncHotJournal(pPager); rc = pagerSyncHotJournal(pPager);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
assert( pPager->eState==PAGER_NONE );
pPager->eState = PAGER_WRITER_FINISHED;
rc = pager_playback(pPager, 1); rc = pager_playback(pPager, 1);
pPager->eState = PAGER_NONE; pPager->eState = PAGER_NONE;
} }
if( rc!=SQLITE_OK ){ }else if( !pPager->exclusiveMode ){
goto failed; pagerUnlockDb(pPager, SHARED_LOCK);
} }
}else{
osUnlock(pPager, SHARED_LOCK); if( rc!=SQLITE_OK ){
pager_error(pPager, rc);
goto failed;
} }
assert( pPager->eState==PAGER_NONE ); assert( pPager->eState==PAGER_NONE );
@@ -4511,7 +4519,9 @@ int sqlite3PagerSharedLock(Pager *pPager){
); );
} }
if( pPager->pBackup || sqlite3PcachePagecount(pPager->pPCache)>0 ){ if( !pPager->tempFile
&& (pPager->pBackup || sqlite3PcachePagecount(pPager->pPCache)>0)
){
/* The shared-lock has just been acquired on the database file /* The shared-lock has just been acquired on the database file
** and there are already pages in the cache (from a previous ** and there are already pages in the cache (from a previous
** read or write transaction). Check to see if the database ** read or write transaction). Check to see if the database
@@ -4906,7 +4916,7 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
** exclusive lock on the database is not already held, obtain it now. ** exclusive lock on the database is not already held, obtain it now.
*/ */
if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){ if( pPager->exclusiveMode && sqlite3WalExclusiveMode(pPager->pWal, -1) ){
rc = osLock(pPager, EXCLUSIVE_LOCK); rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
return rc; return rc;
} }
@@ -4925,7 +4935,7 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
** busy-handler callback can be used when upgrading to the EXCLUSIVE ** busy-handler callback can be used when upgrading to the EXCLUSIVE
** lock, but not when obtaining the RESERVED lock. ** lock, but not when obtaining the RESERVED lock.
*/ */
rc = osLock(pPager, RESERVED_LOCK); rc = pagerLockDb(pPager, RESERVED_LOCK);
if( rc==SQLITE_OK && exFlag ){ if( rc==SQLITE_OK && exFlag ){
rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
} }
@@ -5874,12 +5884,12 @@ int sqlite3PagerOpenSavepoint(Pager *pPager, int nSavepoint){
** savepoint. If no errors occur, SQLITE_OK is returned. ** savepoint. If no errors occur, SQLITE_OK is returned.
*/ */
int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
int rc = SQLITE_OK; int rc = pPager->errCode; /* Return code */
assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK ); assert( op==SAVEPOINT_RELEASE || op==SAVEPOINT_ROLLBACK );
assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK ); assert( iSavepoint>=0 || op==SAVEPOINT_ROLLBACK );
if( iSavepoint<pPager->nSavepoint ){ if( rc==SQLITE_OK && iSavepoint<pPager->nSavepoint ){
int ii; /* Iterator variable */ int ii; /* Iterator variable */
int nNew; /* Number of remaining savepoints after this op. */ int nNew; /* Number of remaining savepoints after this op. */
@@ -5915,8 +5925,8 @@ int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint){
rc = pagerPlaybackSavepoint(pPager, pSavepoint); rc = pagerPlaybackSavepoint(pPager, pSavepoint);
assert(rc!=SQLITE_DONE); assert(rc!=SQLITE_DONE);
} }
} }
return rc; return rc;
} }
@@ -6092,6 +6102,16 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
sqlite3PcacheMove(pPg, pgno); sqlite3PcacheMove(pPg, pgno);
sqlite3PcacheMakeDirty(pPg); sqlite3PcacheMakeDirty(pPg);
/* For an in-memory database, make sure the original page continues
** to exist, in case the transaction needs to roll back. Use pPgOld
** as the original page since it has already been allocated.
*/
if( MEMDB ){
assert( pPgOld );
sqlite3PcacheMove(pPgOld, origPgno);
sqlite3PagerUnref(pPgOld);
}
if( needSyncPgno ){ if( needSyncPgno ){
/* If needSyncPgno is non-zero, then the journal file needs to be /* If needSyncPgno is non-zero, then the journal file needs to be
** sync()ed before any data is written to database file page needSyncPgno. ** sync()ed before any data is written to database file page needSyncPgno.
@@ -6121,16 +6141,6 @@ int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, int isCommit){
sqlite3PagerUnref(pPgHdr); sqlite3PagerUnref(pPgHdr);
} }
/*
** For an in-memory database, make sure the original page continues
** to exist, in case the transaction needs to roll back. Use pPgOld
** as the original page since it has already been allocated.
*/
if( MEMDB ){
sqlite3PcacheMove(pPgOld, origPgno);
sqlite3PagerUnref(pPgOld);
}
return SQLITE_OK; return SQLITE_OK;
} }
#endif #endif
@@ -6221,14 +6231,6 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
} }
if( eMode!=eOld ){ if( eMode!=eOld ){
/* When changing between rollback modes, close the journal file prior
** to the change. But when changing from a rollback mode to WAL, keep
** the journal open since there is a rollback-style transaction in play
** used to convert the version numbers in the btree header.
*/
if( isOpen(pPager->jfd) && eMode!=PAGER_JOURNALMODE_WAL ){
sqlite3OsClose(pPager->jfd);
}
/* Change the journal mode. */ /* Change the journal mode. */
pPager->journalMode = (u8)eMode; pPager->journalMode = (u8)eMode;
@@ -6247,6 +6249,8 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
assert( isOpen(pPager->fd) || pPager->exclusiveMode ); assert( isOpen(pPager->fd) || pPager->exclusiveMode );
if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){ if( !pPager->exclusiveMode && (eOld & 5)==1 && (eMode & 1)==0 ){
sqlite3OsClose(pPager->jfd);
/* In this case we would like to delete the journal file. If it is /* In this case we would like to delete the journal file. If it is
** not possible, then that is not a problem. Deleting the journal file ** not possible, then that is not a problem. Deleting the journal file
** here is an optimization only. ** here is an optimization only.
@@ -6262,13 +6266,13 @@ int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
} }
if( pPager->eState==PAGER_READER ){ if( pPager->eState==PAGER_READER ){
assert( rc==SQLITE_OK ); assert( rc==SQLITE_OK );
rc = osLock(pPager, RESERVED_LOCK); rc = pagerLockDb(pPager, RESERVED_LOCK);
} }
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
} }
if( rc==SQLITE_OK && state==PAGER_READER ){ if( rc==SQLITE_OK && state==PAGER_READER ){
osUnlock(pPager, SHARED_LOCK); pagerUnlockDb(pPager, SHARED_LOCK);
}else if( state==PAGER_NONE ){ }else if( state==PAGER_NONE ){
pager_unlock(pPager); pager_unlock(pPager);
} }
@@ -6293,6 +6297,7 @@ int sqlite3PagerGetJournalMode(Pager *pPager){
** is unmodified. ** is unmodified.
*/ */
int sqlite3PagerOkToChangeJournalMode(Pager *pPager){ int sqlite3PagerOkToChangeJournalMode(Pager *pPager){
assert( assert_pager_state(pPager) );
if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0; if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0;
if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0; if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0;
return 1; return 1;
@@ -6380,6 +6385,10 @@ int sqlite3PagerOpenWal(
if( !pPager->tempFile && !pPager->pWal ){ if( !pPager->tempFile && !pPager->pWal ){
if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN; if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
if( isOpen(pPager->jfd) ){
sqlite3OsClose(pPager->jfd);
}
/* Open the connection to the log file. If this operation fails, /* Open the connection to the log file. If this operation fails,
** (e.g. due to malloc() failure), unlock the database file and ** (e.g. due to malloc() failure), unlock the database file and
** return an error code. ** return an error code.
@@ -6416,7 +6425,7 @@ int sqlite3PagerCloseWal(Pager *pPager){
*/ */
if( !pPager->pWal ){ if( !pPager->pWal ){
int logexists = 0; int logexists = 0;
rc = osLock(pPager, SHARED_LOCK); rc = pagerLockDb(pPager, SHARED_LOCK);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = sqlite3OsAccess( rc = sqlite3OsAccess(
pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &logexists
@@ -6432,7 +6441,7 @@ int sqlite3PagerCloseWal(Pager *pPager){
** the database file, the log and log-summary files will be deleted. ** the database file, the log and log-summary files will be deleted.
*/ */
if( rc==SQLITE_OK && pPager->pWal ){ if( rc==SQLITE_OK && pPager->pWal ){
rc = osLock(pPager, EXCLUSIVE_LOCK); rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
rc = sqlite3WalClose(pPager->pWal, rc = sqlite3WalClose(pPager->pWal,
(pPager->noSync ? 0 : pPager->sync_flags), (pPager->noSync ? 0 : pPager->sync_flags),
@@ -6442,7 +6451,7 @@ int sqlite3PagerCloseWal(Pager *pPager){
}else{ }else{
/* If we cannot get an EXCLUSIVE lock, downgrade the PENDING lock /* If we cannot get an EXCLUSIVE lock, downgrade the PENDING lock
** that we did get back to SHARED. */ ** that we did get back to SHARED. */
osUnlock(pPager, SQLITE_LOCK_SHARED); pagerUnlockDb(pPager, SQLITE_LOCK_SHARED);
} }
} }
return rc; return rc;