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:
159
src/pager.c
159
src/pager.c
@@ -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 */
|
||||
|
Reference in New Issue
Block a user