diff options
author | dan <dan@noemail.net> | 2011-02-07 15:12:12 +0000 |
---|---|---|
committer | dan <dan@noemail.net> | 2011-02-07 15:12:12 +0000 |
commit | 9c5e3680dfa359da2cf77202b561bd7e7df1c628 (patch) | |
tree | b41fea8ba8d7ccdb50423ab3ea8bb91d2d883e40 /src | |
parent | 2fe88b7ca4b1318d5499b552bcde5e12b84cd1cc (diff) | |
download | sqlite-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.c | 6 | ||||
-rw-r--r-- | src/test1.c | 68 | ||||
-rw-r--r-- | src/wal.c | 16 |
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 }, }; @@ -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); } } |