mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Add evidence marks and assert()s used as evidence for checkpoint requirements.
FossilOrigin-Name: b2da8afc7657266fbe8e683c6e50fe18216cbcf3
This commit is contained in:
45
src/wal.c
45
src/wal.c
@@ -1689,7 +1689,7 @@ static void walRestartHdr(Wal *pWal, u32 salt1){
|
||||
static int walCheckpoint(
|
||||
Wal *pWal, /* Wal connection */
|
||||
int eMode, /* One of PASSIVE, FULL or RESTART */
|
||||
int (*xBusyCall)(void*), /* Function to call when busy */
|
||||
int (*xBusy)(void*), /* Function to call when busy */
|
||||
void *pBusyArg, /* Context argument for xBusyHandler */
|
||||
int sync_flags, /* Flags for OsSync() (or 0) */
|
||||
u8 *zBuf /* Temporary buffer to use */
|
||||
@@ -1703,7 +1703,6 @@ static int walCheckpoint(
|
||||
u32 mxPage; /* Max database page to write */
|
||||
int i; /* Loop counter */
|
||||
volatile WalCkptInfo *pInfo; /* The checkpoint status information */
|
||||
int (*xBusy)(void*) = 0; /* Function to call when waiting for locks */
|
||||
|
||||
szPage = walPagesize(pWal);
|
||||
testcase( szPage<=32768 );
|
||||
@@ -1718,7 +1717,9 @@ static int walCheckpoint(
|
||||
}
|
||||
assert( pIter );
|
||||
|
||||
if( eMode!=SQLITE_CHECKPOINT_PASSIVE ) xBusy = xBusyCall;
|
||||
/* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
|
||||
** in the SQLITE_CHECKPOINT_PASSIVE mode. */
|
||||
assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
|
||||
|
||||
/* Compute in mxSafeFrame the index of the last frame of the WAL that is
|
||||
** safe to write into the database. Frames beyond mxSafeFrame might
|
||||
@@ -2943,7 +2944,7 @@ int sqlite3WalFrames(
|
||||
*/
|
||||
int sqlite3WalCheckpoint(
|
||||
Wal *pWal, /* Wal connection */
|
||||
int eMode, /* PASSIVE, FULL or RESTART */
|
||||
int eMode, /* PASSIVE, FULL, RESTART, or TRUNCATE */
|
||||
int (*xBusy)(void*), /* Function to call when busy */
|
||||
void *pBusyArg, /* Context argument for xBusyHandler */
|
||||
int sync_flags, /* Flags to sync db file with (or 0) */
|
||||
@@ -2955,29 +2956,42 @@ int sqlite3WalCheckpoint(
|
||||
int rc; /* Return code */
|
||||
int isChanged = 0; /* True if a new wal-index header is loaded */
|
||||
int eMode2 = eMode; /* Mode to pass to walCheckpoint() */
|
||||
int (*xBusy2)(void*) = xBusy; /* Busy handler for eMode2 */
|
||||
|
||||
assert( pWal->ckptLock==0 );
|
||||
assert( pWal->writeLock==0 );
|
||||
|
||||
/* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked
|
||||
** in the SQLITE_CHECKPOINT_PASSIVE mode. */
|
||||
assert( eMode!=SQLITE_CHECKPOINT_PASSIVE || xBusy==0 );
|
||||
|
||||
if( pWal->readOnly ) return SQLITE_READONLY;
|
||||
WALTRACE(("WAL%p: checkpoint begins\n", pWal));
|
||||
|
||||
/* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
|
||||
** "checkpoint" lock on the database file. */
|
||||
rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
|
||||
if( rc ){
|
||||
/* Usually this is SQLITE_BUSY meaning that another thread or process
|
||||
** is already running a checkpoint, or maybe a recovery. But it might
|
||||
** also be SQLITE_IOERR. */
|
||||
/* EVIDENCE-OF: R-10421-19736 If any other process is running a
|
||||
** checkpoint operation at the same time, the lock cannot be obtained and
|
||||
** SQLITE_BUSY is returned.
|
||||
** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
|
||||
** it will not be invoked in this case.
|
||||
*/
|
||||
testcase( rc==SQLITE_BUSY );
|
||||
testcase( xBusy!=0 );
|
||||
return rc;
|
||||
}
|
||||
pWal->ckptLock = 1;
|
||||
|
||||
/* If this is a blocking-checkpoint, then obtain the write-lock as well
|
||||
** to prevent any writers from running while the checkpoint is underway.
|
||||
** This has to be done before the call to walIndexReadHdr() below.
|
||||
/* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
|
||||
** TRUNCATE modes also obtain the exclusive "writer" lock on the database
|
||||
** file.
|
||||
**
|
||||
** If the writer lock cannot be obtained, then a passive checkpoint is
|
||||
** run instead. Since the checkpointer is not holding the writer lock,
|
||||
** there is no point in blocking waiting for any readers. Assuming no
|
||||
** other error occurs, this function will return SQLITE_BUSY to the caller.
|
||||
** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
|
||||
** immediately, and a busy-handler is configured, it is invoked and the
|
||||
** writer lock retried until either the busy-handler returns 0 or the
|
||||
** lock is successfully obtained.
|
||||
*/
|
||||
if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
|
||||
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
|
||||
@@ -2985,6 +2999,7 @@ int sqlite3WalCheckpoint(
|
||||
pWal->writeLock = 1;
|
||||
}else if( rc==SQLITE_BUSY ){
|
||||
eMode2 = SQLITE_CHECKPOINT_PASSIVE;
|
||||
xBusy2 = 0;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
}
|
||||
@@ -3002,7 +3017,7 @@ int sqlite3WalCheckpoint(
|
||||
if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf);
|
||||
rc = walCheckpoint(pWal, eMode2, xBusy2, pBusyArg, sync_flags, zBuf);
|
||||
}
|
||||
|
||||
/* If no error occurred, set the output variables. */
|
||||
|
Reference in New Issue
Block a user