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

Use the read and write version fields of the database header to mark a database as operating in wal-mode.

FossilOrigin-Name: 96bef18c1411c3e0348295886f105e1646c46320
This commit is contained in:
dan
2010-04-20 18:53:15 +00:00
parent 8d22a17411
commit e04dc88be5
10 changed files with 327 additions and 128 deletions

View File

@@ -1405,9 +1405,11 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
/* This branch may be executed with Pager.journalMode==MEMORY if
** a hot-journal was just rolled back. In this case the journal
** file should be closed and deleted. If this connection writes to
** the database file, it will do so using an in-memory journal. */
** the database file, it will do so using an in-memory journal.
*/
assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE
|| pPager->journalMode==PAGER_JOURNALMODE_MEMORY
|| pPager->journalMode==PAGER_JOURNALMODE_WAL
);
sqlite3OsClose(pPager->jfd);
if( !pPager->tempFile ){
@@ -3724,54 +3726,6 @@ static int hasHotJournal(Pager *pPager, int *pExists){
return rc;
}
/*
** Open a connection to the write-ahead log file for pager pPager. If
** the log connection is already open, this function is a no-op.
*/
static int pagerOpenLog(Pager *pPager){
if( !pPager->pLog ){
int rc; /* Return code */
/* Before opening the log file, obtain a SHARED lock on the database
** file. This lock will not be released until after the log file
** connection has been closed. The purpose of this lock is to stop
** any other process from unlinking the log or log-summary files while
** this connection still has them open. An EXCLUSIVE lock on the
** database file is required to unlink either of those two files.
*/
assert( pPager->state==PAGER_UNLOCK );
rc = pager_wait_on_lock(pPager, SHARED_LOCK);
if( rc!=SQLITE_OK ){
assert( pPager->state==PAGER_UNLOCK );
return pager_error(pPager, rc);
}
assert( pPager->state>=SHARED_LOCK );
/* Open the connection to the log file. If this operation fails,
** (e.g. due to malloc() failure), unlock the database file and
** return an error code.
*/
rc = sqlite3LogOpen(pPager->pVfs, pPager->zFilename, &pPager->pLog);
if( rc!=SQLITE_OK ){
osUnlock(pPager->fd, SQLITE_LOCK_NONE);
pPager->state = PAGER_UNLOCK;
return rc;
}
}else{
/* If the log file was already open, check that the pager is still holding
** the required SHARED lock on the database file.
*/
#ifdef SQLITE_DEBUG
int locktype;
sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCKSTATE, &locktype);
assert( locktype==SQLITE_LOCK_SHARED );
#endif
pPager->state = PAGER_SHARED;
}
return SQLITE_OK;
}
/*
** This function is called to obtain a shared lock on the database file.
@@ -3826,16 +3780,9 @@ int sqlite3PagerSharedLock(Pager *pPager){
pager_reset(pPager);
}
if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
if( pagerUseLog(pPager) ){
int changed = 0; /* True if the cache must be flushed */
/* Open the log file, if it is not already open. */
rc = pagerOpenLog(pPager);
if( rc!=SQLITE_OK ){
return rc;
}
/* Open a log snapshot to read from. */
rc = sqlite3LogOpenSnapshot(pPager->pLog, &changed);
if( rc==SQLITE_OK ){
@@ -3846,6 +3793,8 @@ int sqlite3PagerSharedLock(Pager *pPager){
}
rc = sqlite3PagerPagecount(pPager, &dummy);
}
pPager->state = PAGER_SHARED;
}else if( pPager->state==PAGER_UNLOCK || isErrorReset ){
sqlite3_vfs * const pVfs = pPager->pVfs;
int isHotJournal = 0;
@@ -4002,6 +3951,10 @@ int sqlite3PagerSharedLock(Pager *pPager){
}
}
assert( pPager->exclusiveMode || pPager->state==PAGER_SHARED );
if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
pPager->journalMode = PAGER_JOURNALMODE_DELETE;
}
}
failed:
@@ -4384,6 +4337,7 @@ int sqlite3PagerBegin(Pager *pPager, int exFlag, int subjInMemory){
if( rc==SQLITE_OK ){
pPager->dbOrigSize = pPager->dbSize;
pPager->state = PAGER_RESERVED;
pPager->journalOff = 0;
}
}else{
/* Obtain a RESERVED lock on the database file. If the exFlag parameter
@@ -4485,7 +4439,7 @@ static int pager_write(PgHdr *pPg){
}
if( !isOpen(pPager->jfd)
&& pPager->journalMode!=PAGER_JOURNALMODE_OFF
&& pPager->journalMode!=PAGER_JOURNALMODE_WAL
&& !pagerUseLog(pPager)
){
assert( pPager->useJournal );
rc = pager_open_journal(pPager);
@@ -5621,7 +5575,7 @@ int sqlite3PagerLockingMode(Pager *pPager, int eMode){
** PAGER_JOURNALMODE_WAL
**
** If the parameter is not _QUERY, then the journal_mode is set to the
** value specified if the change is allowed. The change is disallowed
** value specified if the change is allowed. The change may be disallowed
** for the following reasons:
**
** * An in-memory database can only have its journal_mode set to _OFF
@@ -5640,7 +5594,12 @@ int sqlite3PagerJournalMode(Pager *pPager, int eMode){
|| eMode==PAGER_JOURNALMODE_WAL
|| eMode==PAGER_JOURNALMODE_MEMORY );
assert( PAGER_JOURNALMODE_QUERY<0 );
if( eMode>=0
if( eMode==PAGER_JOURNALMODE_WAL
&& pPager->journalMode==PAGER_JOURNALMODE_DELETE
){
pPager->journalMode = PAGER_JOURNALMODE_WAL;
}else if( eMode>=0
&& (pPager->tempFile==0 || eMode!=PAGER_JOURNALMODE_WAL)
&& (!MEMDB || eMode==PAGER_JOURNALMODE_MEMORY||eMode==PAGER_JOURNALMODE_OFF)
&& !pPager->dbModified
@@ -5659,13 +5618,6 @@ int sqlite3PagerJournalMode(Pager *pPager, int eMode){
sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0);
}
/* Switching into WAL mode can only take place when no
** locks are held on the database file.
*/
if( eMode==PAGER_JOURNALMODE_WAL && pPager->state!=PAGER_UNLOCK ){
return (int)pPager->journalMode;
}
pPager->journalMode = (u8)eMode;
}
return (int)pPager->journalMode;
@@ -5713,4 +5665,77 @@ int sqlite3PagerLogCallback(Pager *pPager){
return sqlite3LogCallback(pPager->pLog);
}
/*
** Open a connection to the write-ahead log file for pager pPager. If
** the log connection is already open, this function is a no-op.
**
** The caller must be holding a SHARED lock on the database file to call
** this function.
*/
int sqlite3PagerOpenLog(Pager *pPager, int *pisOpen){
int rc = SQLITE_OK; /* Return code */
#ifdef SQLITE_DEBUG
int locktype;
sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCKSTATE, &locktype);
assert( locktype==SQLITE_LOCK_SHARED );
assert( pPager->state>=PAGER_SHARED );
#endif
if( !pPager->pLog ){
/* Open the connection to the log file. If this operation fails,
** (e.g. due to malloc() failure), unlock the database file and
** return an error code.
*/
rc = sqlite3LogOpen(pPager->pVfs, pPager->zFilename, &pPager->pLog);
if( rc==SQLITE_OK ){
pPager->journalMode = PAGER_JOURNALMODE_WAL;
}
}else{
*pisOpen = 1;
}
return rc;
}
/*
** This function is called to close the connection to the log file prior
** to switching from WAL to rollback mode.
**
** Before closing the log file, this function attempts to take an
** EXCLUSIVE lock on the database file. If this cannot be obtained, an
** error (SQLITE_BUSY) is returned and the log connection is not closed.
** If successful, the EXCLUSIVE lock is not released before returning.
*/
int sqlite3PagerCloseLog(Pager *pPager){
int rc = SQLITE_OK;
if( pPager->pLog ){
/* Try to obtain an EXCLUSIVE lock on the database file. */
rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK);
/* If the EXCLUSIVE lock was obtained, checkpoint and close the log. */
if( rc==SQLITE_OK ){
rc = sqlite3LogClose(pPager->pLog, pPager->fd,
(pPager->noSync ? 0 : pPager->sync_flags),
(u8*)pPager->pTmpSpace
);
pPager->pLog = 0;
}
/* Make sure the EXCLUSIVE lock has not been lost somehow */
#ifdef SQLITE_DEBUG
{
int locktype;
sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCKSTATE, &locktype);
assert( locktype==SQLITE_LOCK_EXCLUSIVE );
}
#endif
}
return rc;
}
#endif /* SQLITE_OMIT_DISKIO */