aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordan <dan@noemail.net>2011-02-07 15:12:12 +0000
committerdan <dan@noemail.net>2011-02-07 15:12:12 +0000
commit9c5e3680dfa359da2cf77202b561bd7e7df1c628 (patch)
treeb41fea8ba8d7ccdb50423ab3ea8bb91d2d883e40 /src
parent2fe88b7ca4b1318d5499b552bcde5e12b84cd1cc (diff)
downloadsqlite-9c5e3680dfa359da2cf77202b561bd7e7df1c628.tar.gz
sqlite-9c5e3680dfa359da2cf77202b561bd7e7df1c628.zip
Change blocking-checkpoint tests so that they run once using "PRAGMA wal_checkpoint" and once using calls to sqlite3_wal_checkpoint_v2(). Also fix edge cases surrounding the output variables set by wal_checkpoint_v2().
FossilOrigin-Name: 5a4b6652cf3780ffed6fe0fe669e8090b0b71e81
Diffstat (limited to 'src')
-rw-r--r--src/main.c6
-rw-r--r--src/test1.c68
-rw-r--r--src/wal.c16
3 files changed, 83 insertions, 7 deletions
diff --git a/src/main.c b/src/main.c
index 9f7d4b1fd..b202ac9e5 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1356,6 +1356,10 @@ int sqlite3_wal_checkpoint_v2(
int rc; /* Return code */
int iDb = SQLITE_MAX_ATTACHED; /* sqlite3.aDb[] index of db to checkpoint */
+ /* Initialize the output variables to -1 in case an error occurs. */
+ if( pnLog ) *pnLog = -1;
+ if( pnCkpt ) *pnCkpt = -1;
+
if( eMode!=SQLITE_CHECKPOINT_PASSIVE
&& eMode!=SQLITE_CHECKPOINT_FULL
&& eMode!=SQLITE_CHECKPOINT_RESTART
@@ -1416,6 +1420,8 @@ int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){
int bBusy = 0; /* True if SQLITE_BUSY has been encountered */
assert( sqlite3_mutex_held(db->mutex) );
+ assert( !pnLog || *pnLog==-1 );
+ assert( !pnCkpt || *pnCkpt==-1 );
for(i=0; i<db->nDb && rc==SQLITE_OK; i++){
if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){
diff --git a/src/test1.c b/src/test1.c
index cf7e06b9c..7f09b2929 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -5187,6 +5187,73 @@ static int test_wal_checkpoint(
}
/*
+** tclcmd: sqlite3_wal_checkpoint_v2 db MODE ?NAME?
+**
+** This command calls the wal_checkpoint_v2() function with the specified
+** mode argument (passive, full or restart). If present, the database name
+** NAME is passed as the second argument to wal_checkpoint_v2(). If it the
+** NAME argument is not present, a NULL pointer is passed instead.
+**
+** If wal_checkpoint_v2() returns any value other than SQLITE_BUSY or
+** SQLITE_OK, then this command returns TCL_ERROR. The Tcl result is set
+** to the error message obtained from sqlite3_errmsg().
+**
+** Otherwise, this command returns a list of three integers. The first integer
+** is 1 if SQLITE_BUSY was returned, or 0 otherwise. The following two integers
+** are the values returned via the output paramaters by wal_checkpoint_v2() -
+** the number of frames in the log and the number of frames in the log
+** that have been checkpointed.
+*/
+static int test_wal_checkpoint_v2(
+ ClientData clientData, /* Unused */
+ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
+ int objc, /* Number of arguments */
+ Tcl_Obj *CONST objv[] /* Command arguments */
+){
+ char *zDb = 0;
+ sqlite3 *db;
+ int rc;
+
+ int eMode;
+ int nLog = -555;
+ int nCkpt = -555;
+ Tcl_Obj *pRet;
+
+ const char * aMode[] = { "passive", "full", "restart", 0 };
+ assert( SQLITE_CHECKPOINT_PASSIVE==0 );
+ assert( SQLITE_CHECKPOINT_FULL==1 );
+ assert( SQLITE_CHECKPOINT_RESTART==2 );
+
+ if( objc!=3 && objc!=4 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?");
+ return TCL_ERROR;
+ }
+
+ if( objc==4 ){
+ zDb = Tcl_GetString(objv[3]);
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
+ || Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode)
+ ){
+ return TCL_ERROR;
+ }
+
+ rc = sqlite3_wal_checkpoint_v2(db, zDb, eMode, &nLog, &nCkpt);
+ if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
+ Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE);
+ return TCL_ERROR;
+ }
+
+ pRet = Tcl_NewObj();
+ Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(rc==SQLITE_BUSY?1:0));
+ Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nLog));
+ Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCkpt));
+ Tcl_SetObjResult(interp, pRet);
+
+ return TCL_OK;
+}
+
+/*
** tclcmd: test_sqlite3_log ?SCRIPT?
*/
static struct LogCallback {
@@ -5572,6 +5639,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_unlock_notify", test_unlock_notify, 0 },
#endif
{ "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 },
+ { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 },
{ "test_sqlite3_log", test_sqlite3_log, 0 },
{ "print_explain_query_plan", test_print_eqp, 0 },
};
diff --git a/src/wal.c b/src/wal.c
index 64c966da9..34fb6cbbc 100644
--- a/src/wal.c
+++ b/src/wal.c
@@ -1623,8 +1623,7 @@ static int walCheckpoint(
int (*xBusyCall)(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 */
- int *pnCkpt /* Total frames checkpointed */
+ u8 *zBuf /* Temporary buffer to use */
){
int rc; /* Return code */
int szPage; /* Database page-size */
@@ -1641,7 +1640,6 @@ static int walCheckpoint(
testcase( szPage<=32768 );
testcase( szPage>=65536 );
pInfo = walCkptInfo(pWal);
- if( pnCkpt ) *pnCkpt = pInfo->nBackfill;
if( pInfo->nBackfill>=pWal->hdr.mxFrame ) return SQLITE_OK;
/* Allocate the iterator */
@@ -1727,7 +1725,6 @@ static int walCheckpoint(
}
if( rc==SQLITE_OK ){
pInfo->nBackfill = mxSafeFrame;
- if( pnCkpt ) *pnCkpt = mxSafeFrame;
}
}
@@ -2764,12 +2761,17 @@ int sqlite3WalCheckpoint(
}
/* Copy data from the log to the database file. */
- if( rc==SQLITE_OK && pWal->hdr.mxFrame ){
- if( walPagesize(pWal)!=nBuf ){
+ if( rc==SQLITE_OK ){
+ if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){
rc = SQLITE_CORRUPT_BKPT;
}else{
+ rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags, zBuf);
+ }
+
+ /* If no error occurred, set the output variables. */
+ if( rc==SQLITE_OK || rc==SQLITE_BUSY ){
if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
- rc = walCheckpoint(pWal, eMode2, xBusy, pBusyArg, sync_flags,zBuf,pnCkpt);
+ if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill);
}
}