-C Add\sexperimental\scommand\s"PRAGMA\swal_blocking_checkpoint",\swhich\suses\sthe\sbusy-handler\sto\sblock\suntil\sall\sreaders\shave\sfinished\sin\sorder\sto\sensure\sthe\snext\swriter\swill\sbe\sable\sto\swrap\saround\sto\sthe\sstart\sof\sthe\slog\sfile.
-D 2010-11-16T18:56:51
+C Modify\sthe\sinterface\sto\sthe\sblocking\swal-checkpoint\sfunctionality.
+D 2010-11-18T12:11:05
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in e7a59672eaeb04408d1fa8501618d7501a3c5e39
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/backup.c d5b0137bc20327af08c14772227cc35134839c30
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff
-F src/btree.c 444aae4fc60cc57d6c97615358e1020f6884cca6
-F src/btree.h d1144d38d790a8b7b2e215043f8d068f4f37de07
+F src/btree.c d90149f6e0a6f715b58b272ef1028fa249a2a088
+F src/btree.h 1d62748eb7d129292782cf65b891b85cbfa024d4
F src/btreeInt.h c424f2f131cc61ddf130f9bd736b3df12c8a51f0
F src/build.c 00a327120d81ace6267e714ae8010c997d55de5d
F src/callback.c a1d1b1c9c85415dff013af033e2fed9c8382d33b
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
F src/loadext.c 8af9fcc75708d60b88636ccba38b4a7b3c155c3e
-F src/main.c 89c658ae9a610a61ff856a110bda50606e9227d6
+F src/main.c 91465f2658911ddb51be89e7b8ee01af8584308f
F src/malloc.c 3d7284cd9346ab6e3945535761e68c23c6cf40ef
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206
F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e
F src/os_unix.c de5be4cdbf3d07018059934eaf7e5d8d594a895c
F src/os_win.c 2f90f7bdec714fad51cd31b4ecad3cc1b4bb5aad
-F src/pager.c 7f7587c2f11126d13ee1925ac8960a9e7ab13e8a
-F src/pager.h ad7d8db0fbcee7546dbc02ffe0d0d44ea868ef52
+F src/pager.c b46a78a196d99bc855eec3c602777a1bc8db5122
+F src/pager.h e2485f2f2fa5264f2bb68d1783c149d3d57d3637
F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
F src/pcache1.c e9578a3beac26f229ee558a4e16c863f2498185f
-F src/pragma.c 66a8b53d1e74635011fbb0bb54b7ecc402684bae
+F src/pragma.c f843c877845ddbb911f10eea50c9290bc8354b03
F src/prepare.c c2b318037d626fed27905c9446730b560637217a
F src/printf.c 8ae5082dd38a1b5456030c3755ec3a392cd51506
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c 550d67688f5e8bc8022faf6d014838afba1415af
F src/shell.c 8517fc1f9c59ae4007e6cc8b9af91ab231ea2056
-F src/sqlite.h.in f47e09412fc9a129f759fa4d96ef21f4b3d529eb
+F src/sqlite.h.in 4645a3bddf4481fcc9422ba41acf4e71c1c81e22
F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
-F src/sqliteInt.h fe1cb073b2707001985f06dee9ee256247e4d0ce
+F src/sqliteInt.h 4e7045f17606296bc8e7898d69567fc3cd06b761
F src/sqliteLimit.h a17dcd3fb775d63b64a43a55c54cb282f9726f44
F src/status.c 496913d4e8441195f6f2a75b1c95993a45b9b30b
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685
F src/util.c cd78524566fe45671863eee78685969a4bfd4e4c
F src/vacuum.c 924bd1bcee2dfb05376f79845bd3b4cec7b54b2f
-F src/vdbe.c b86b09beb3dcf2e6d5922acee48b8a1c16b68bfd
+F src/vdbe.c 4bec828e70654c698ef843c29b557bee2c8a0a00
F src/vdbe.h 4de0efb4b0fdaaa900cf419b35c458933ef1c6d2
F src/vdbeInt.h 7f4cf1b2b69bef3a432b1f23dfebef57275436b4
F src/vdbeapi.c 5368714fa750270cf6430160287c21adff44582d
F src/vdbemem.c 23723a12cd3ba7ab3099193094cbb2eb78956aa9
F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
F src/vtab.c b297e8fa656ab5e66244ab15680d68db0adbec30
-F src/wal.c 400624ce58acce44f0bf0d47ed2f435da290fb04
-F src/wal.h d5bbc11242d7fd14e9dc6a74f68d3ccaf01a9e48
+F src/wal.c 8eca619a28a70a667c913e5927131250836377a2
+F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840
F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
F src/where.c d5cc65f51661a038a2c6a663a945d5cf4c277b81
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/wal2.test c794b8b257af54190bb913678ad3984cbf3311b9
F test/wal3.test 957a5f2a8fe8a6ff01de1a15285ecf2f376fcaf8
F test/wal4.test 3404b048fa5e10605facaf70384e6d2943412e30
-F test/wal5.test e0f1abdff4f76d3a8531f5d0f4cb237e5eff891c
+F test/wal5.test 4e2854d7584dd97a73e7ce0f47bcbbe5c592fe29
F test/wal_common.tcl a98f17fba96206122eff624db0ab13ec377be4fe
F test/walbak.test 4df1c7369da0301caeb9a48fa45997fd592380e4
F test/walbig.test e882bc1d014afffbfa2b6ba36e0f07d30a633ad0
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 56bbc539246a6dc9f1ae1edb898db7a4f6f6d322
-R 75a04ae738d792c76538f98d6f9ad655
-T *branch * experimental
-T *sym-experimental *
-T -sym-trunk *
+P 7e3fc2c833a5baa08820c499867b6902bdc2ed5a
+R 1672f1722e4277222ee64bddb8543abf
U dan
-Z b1cbb492cf90106bd968e524fdd11e16
+Z 2e080f5eeb72d6f9662d3b3c376a7b7c
-7e3fc2c833a5baa08820c499867b6902bdc2ed5a
\ No newline at end of file
+72787c010c8944e8fcf9c98aa4482f129142d8e9
\ No newline at end of file
** Return SQLITE_LOCKED if this or any other connection has an open
** transaction on the shared-cache the argument Btree is connected to.
**
-** If parameter bBlock is true, then the layers below invoke the
-** busy-handler callback while waiting for readers to release locks so
-** that the entire WAL can be checkpointed. If it is false, then as
-** much as possible of the WAL is checkpointed without waiting for readers
-** to finish. bBlock is true for "PRAGMA wal_blocking_checkpoint" and false
-** for "PRAGMA wal_checkpoint".
-*/
-int sqlite3BtreeCheckpoint(Btree *p, int bBlock){
+** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
+*/
+int sqlite3BtreeCheckpoint(Btree *p, int eMode, int *pnLog, int *pnCkpt){
int rc = SQLITE_OK;
if( p ){
BtShared *pBt = p->pBt;
if( pBt->inTransaction!=TRANS_NONE ){
rc = SQLITE_LOCKED;
}else{
- rc = sqlite3PagerCheckpoint(pBt->pPager, bBlock);
+ rc = sqlite3PagerCheckpoint(pBt->pPager, eMode, pnLog, pnCkpt);
}
sqlite3BtreeLeave(p);
}
#endif
#ifndef SQLITE_OMIT_WAL
- int sqlite3BtreeCheckpoint(Btree*, int);
+ int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
#endif
/*
#endif
}
-
/*
-** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points
-** to contains a zero-length string, all attached databases are
-** checkpointed.
-*/
-int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
+** Checkpoint database zDb.
+*/
+int sqlite3_wal_checkpoint_v2(
+ sqlite3 *db, /* Database handle */
+ const char *zDb, /* Name of attached database (or NULL) */
+ int eMode, /* SQLITE_CHECKPOINT_* value */
+ int *pnLog, /* OUT: Size of WAL log in frames */
+ int *pnCkpt /* OUT: Total number of frames checkpointed */
+){
#ifdef SQLITE_OMIT_WAL
return SQLITE_OK;
#else
int rc; /* Return code */
int iDb = SQLITE_MAX_ATTACHED; /* sqlite3.aDb[] index of db to checkpoint */
+ if( eMode!=SQLITE_CHECKPOINT_PASSIVE
+ && eMode!=SQLITE_CHECKPOINT_FULL
+ && eMode!=SQLITE_CHECKPOINT_RESTART
+ ){
+ return SQLITE_MISUSE;
+ }
+
sqlite3_mutex_enter(db->mutex);
if( zDb && zDb[0] ){
iDb = sqlite3FindDbName(db, zDb);
rc = SQLITE_ERROR;
sqlite3Error(db, SQLITE_ERROR, "unknown database: %s", zDb);
}else{
- rc = sqlite3Checkpoint(db, iDb, 0);
+ rc = sqlite3Checkpoint(db, iDb, eMode, pnLog, pnCkpt);
sqlite3Error(db, rc, 0);
}
rc = sqlite3ApiExit(db, rc);
#endif
}
+
+/*
+** Checkpoint database zDb. If zDb is NULL, or if the buffer zDb points
+** to contains a zero-length string, all attached databases are
+** checkpointed.
+*/
+int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
+ return sqlite3_wal_checkpoint_v2(db, zDb, SQLITE_CHECKPOINT_PASSIVE, 0, 0);
+}
+
#ifndef SQLITE_OMIT_WAL
/*
** Run a checkpoint on database iDb. This is a no-op if database iDb is
** checkpointed. If an error is encountered it is returned immediately -
** no attempt is made to checkpoint any remaining databases.
**
-** Parameter bBlock is true for a blocking-checkpoint, false for an
-** ordinary, non-blocking, checkpoint.
+** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
*/
-int sqlite3Checkpoint(sqlite3 *db, int iDb, int bBlock){
+int sqlite3Checkpoint(sqlite3 *db, int iDb, int eMode, int *pnLog, int *pnCkpt){
int rc = SQLITE_OK; /* Return code */
int i; /* Used to iterate through attached dbs */
for(i=0; i<db->nDb && rc==SQLITE_OK; i++){
if( i==iDb || iDb==SQLITE_MAX_ATTACHED ){
- rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt, bBlock);
+ rc = sqlite3BtreeCheckpoint(db->aDb[i].pBt, eMode, pnLog, pnCkpt);
}
}
** "PRAGMA wal_blocking_checkpoint" or calls the sqlite3_wal_checkpoint()
** or wal_blocking_checkpoint() API functions.
**
-** Parameter bBlock is true for a blocking-checkpoint, false for an
-** ordinary, non-blocking, checkpoint.
+** Parameter eMode is one of SQLITE_CHECKPOINT_PASSIVE, FULL or RESTART.
*/
-int sqlite3PagerCheckpoint(Pager *pPager, int bBlock){
+int sqlite3PagerCheckpoint(Pager *pPager, int eMode, int *pnLog, int *pnCkpt){
int rc = SQLITE_OK;
if( pPager->pWal ){
- u8 *zBuf = (u8 *)pPager->pTmpSpace;
- rc = sqlite3WalCheckpoint(pPager->pWal,
- (bBlock ? pPager->xBusyHandler : 0), pPager->pBusyHandlerArg,
+ rc = sqlite3WalCheckpoint(pPager->pWal, eMode,
+ pPager->xBusyHandler, pPager->pBusyHandlerArg,
(pPager->noSync ? 0 : pPager->sync_flags),
- pPager->pageSize, zBuf
+ pPager->pageSize, (u8 *)pPager->pTmpSpace,
+ pnLog, pnCkpt
);
}
return rc;
int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
int sqlite3PagerSharedLock(Pager *pPager);
-int sqlite3PagerCheckpoint(Pager *pPager, int);
+int sqlite3PagerCheckpoint(Pager *pPager, int, int*, int*);
int sqlite3PagerWalSupported(Pager *pPager);
int sqlite3PagerWalCallback(Pager *pPager);
int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
#ifndef SQLITE_OMIT_WAL
/*
- ** PRAGMA [database.]wal_checkpoint
- ** PRAGMA [database.]wal_blocking_checkpoint
+ ** PRAGMA [database.]wal_checkpoint = passive|full|restart
**
** Checkpoint the database.
*/
- if( sqlite3StrICmp(zLeft, "wal_checkpoint")==0
- || sqlite3StrICmp(zLeft, "wal_blocking_checkpoint")==0
- ){
- int bBlock = (zLeft[14]!=0);
+ if( sqlite3StrICmp(zLeft, "wal_checkpoint")==0 ){
int iBt = (pId2->z?iDb:SQLITE_MAX_ATTACHED);
- assert( bBlock==(sqlite3StrICmp(zLeft, "wal_checkpoint")!=0) );
+ int eMode = SQLITE_CHECKPOINT_PASSIVE;
+ if( zRight ){
+ if( sqlite3StrICmp(zRight, "full")==0 ){
+ eMode = SQLITE_CHECKPOINT_FULL;
+ }else if( sqlite3StrICmp(zRight, "restart")==0 ){
+ eMode = SQLITE_CHECKPOINT_RESTART;
+ }
+ }
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
- sqlite3VdbeAddOp2(v, OP_Checkpoint, iBt, bBlock);
+ sqlite3VdbeSetNumCols(v, 3);
+ pParse->nMem = 3;
+ sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "busy", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "log", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "checkpointed", SQLITE_STATIC);
+
+ sqlite3VdbeAddOp2(v, OP_Checkpoint, iBt, eMode);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
}else
/*
*/
int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
+/*
+**
+** CAPI3REF: Checkpoint a database
+**
+** Run a checkpoint operation on WAL database zDb attached to database
+** handle db. The specific operation is determined by the value of the
+** eMode parameter:
+**
+** <dl>
+** <dt>SQLITE_CHECKPOINT_PASSIVE<dd>
+** Checkpoint as many frames as possible without waiting for any database
+** readers or writers to finish. Sync the db file if all frames in the log
+** are checkpointed. This mode is the same as calling
+** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
+**
+** <dt>SQLITE_CHECKPOINT_FULL<dd>
+** This mode blocks (calls the busy-handler callback) until there is no
+** database writer and all readers are reading from the most recent database
+** snapshot. It then checkpoints all frames in the log file and syncs the
+** database file. This call blocks database writers while it is running,
+** but not database readers.
+**
+** <dt>SQLITE_CHECKPOINT_RESTART<dd>
+** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
+** checkpointing the log file it blocks (calls the busy-handler callback)
+** until all readers are reading from the database file only. This ensures
+** that the next client to write to the database file restarts the log file
+** from the beginning. This call blocks database writers while it is running,
+** but not database readers.
+** </dl>
+**
+** If pnLog is not NULL, then *pnLog is set to the total number of frames in
+** the log file before returning. If pnCkpt is not NULL, then *pnCkpt is set to
+** the total number of checkpointed frames (including any that were already
+** checkpointed when this function is called). *pnLog and *pnCkpt may be
+** populated even if sqlite3_wal_checkpoint_v2() returns other than SQLITE_OK.
+** If no values are available because of an error, they are both set to -1
+** before returning to communicate this to the caller.
+**
+** All calls obtain an exclusive "checkpoint" lock on the database file. If
+** any other process is running a checkpoint operation at the same time, the
+** lock cannot be obtained and SQLITE_BUSY is returned. Even if there is a
+** busy-handler configured, it will not be invoked in this case.
+**
+** The SQLITE_CHECKPOINT_FULL and RESTART modes also obtain the exclusive
+** "writer" lock on the database file. 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. The busy-handler is also invoked while waiting for
+** database readers as described above. If the busy-handler returns 0 before
+** the writer lock is obtained or while waiting for database readers, the
+** checkpoint operation proceeds from that point in the same way as
+** SQLITE_CHECKPOINT_PASSIVE - checkpointing as many frames as possible
+** without blocking any further. SQLITE_BUSY is returned in this case.
+**
+** If parameter zDb is NULL or points to a zero length string, then the
+** specified operation is attempted on all WAL databases. In this case the
+** values written to output parameters *pnLog and *pnCkpt are undefined. If
+** an SQLITE_BUSY error is encountered when processing one or more of the
+** attached WAL databases, the operation is still attempted on any remaining
+** attached databases and SQLITE_BUSY is returned to the caller. If any other
+** error occurs while processing an attached database, processing is abandoned
+** and the error code returned to the caller immediately. If no error
+** (SQLITE_BUSY or otherwise) is encountered while processing the attached
+** databases, SQLITE_OK is returned.
+**
+** If database zDb is the name of an attached database that is not in WAL
+** mode, SQLITE_OK is returned and both *pnLog and *pnCkpt set to -1. If
+** zDb is not NULL (or a zero length string) and is not the name of any
+** attached database, SQLITE_ERROR is returned to the caller.
+*/
+int sqlite3_wal_checkpoint_v2(
+ sqlite3 *db, /* Database handle */
+ const char *zDb, /* Name of attached database (or NULL) */
+ int eMode, /* SQLITE_CHECKPOINT_* value */
+ int *pnLog, /* OUT: Size of WAL log in frames */
+ int *pnCkpt /* OUT: Total number of frames checkpointed */
+);
+#define SQLITE_CHECKPOINT_PASSIVE 0
+#define SQLITE_CHECKPOINT_FULL 1
+#define SQLITE_CHECKPOINT_RESTART 2
+
+
/*
** Undo the hack that converts floating point types to integer for
** builds on processors without floating point support.
int sqlite3TempInMemory(const sqlite3*);
VTable *sqlite3GetVTable(sqlite3*, Table*);
const char *sqlite3JournalModename(int);
-int sqlite3Checkpoint(sqlite3*, int, int);
+int sqlite3Checkpoint(sqlite3*, int, int, int*, int*);
int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int);
/* Declarations for functions in fkey.c. All of these are replaced by
}
#ifndef SQLITE_OMIT_WAL
-/* Opcode: Checkpoint P1 P2 * * *
+/* Opcode: Checkpoint P1 P2 P3 * *
**
** Checkpoint database P1. This is a no-op if P1 is not currently in
-** WAL mode. If P2 is non-zero, this is a blocking checkpoint.
+** WAL mode. Parameter P2 is one of SQLITE_CHECKPOINT_PASSIVE, FULL
+** or RESTART.
*/
case OP_Checkpoint: {
- rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2);
+ int nLog = -1; /* Number of pages in WAL log */
+ int nCkpt = -1; /* Number of checkpointed pages */
+ int bBusy = 0;
+ assert( pOp->p2==SQLITE_CHECKPOINT_PASSIVE
+ || pOp->p2==SQLITE_CHECKPOINT_FULL
+ || pOp->p2==SQLITE_CHECKPOINT_RESTART
+ );
+ rc = sqlite3Checkpoint(db, pOp->p1, pOp->p2, &nLog, &nCkpt);
+ if( rc==SQLITE_BUSY ){
+ rc = SQLITE_OK;
+ bBusy = 1;
+ }
+
+ aMem[1].u.i = bBusy;
+ aMem[2].u.i = nLog;
+ aMem[3].u.i = nCkpt;
+ MemSetTypeFlag(&aMem[1], MEM_Int);
+ MemSetTypeFlag(&aMem[2], MEM_Int);
+ MemSetTypeFlag(&aMem[3], MEM_Int);
+
break;
};
#endif
*/
static int walCheckpoint(
Wal *pWal, /* Wal connection */
+ int eMode, /* One of PASSIVE, FULL or RESTART */
int (*xBusy)(void*), /* Function to call when busy */
void *pBusyArg, /* Context argument for xBusyHandler */
int sync_flags, /* Flags for OsSync() (or 0) */
int nBuf, /* Size of zBuf in bytes */
- u8 *zBuf /* Temporary buffer to use */
+ u8 *zBuf, /* Temporary buffer to use */
+ int *pnCkpt /* Total frames checkpointed */
){
int rc; /* Return code */
int szPage; /* Database page-size */
goto walcheckpoint_out;
}
+ pInfo = walCkptInfo(pWal);
+ mxPage = pWal->hdr.nPage;
+ if( pnCkpt ) *pnCkpt = pInfo->nBackfill;
+
/* Compute in mxSafeFrame the index of the last frame of the WAL that is
** safe to write into the database. Frames beyond mxSafeFrame might
** overwrite database pages that are in use by active readers and thus
*/
do {
mxSafeFrame = pWal->hdr.mxFrame;
- mxPage = pWal->hdr.nPage;
- pInfo = walCkptInfo(pWal);
for(i=1; i<WAL_NREADER; i++){
u32 y = pInfo->aReadMark[i];
if( mxSafeFrame>=y ){
}
}
}
- }while( xBusy && mxSafeFrame<pWal->hdr.mxFrame && xBusy(pBusyArg) );
+ }while( eMode!=SQLITE_CHECKPOINT_PASSIVE
+ && xBusy && mxSafeFrame<pWal->hdr.mxFrame && xBusy(pBusyArg) );
if( pInfo->nBackfill<mxSafeFrame
&& (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0), 1))==SQLITE_OK
}
if( rc==SQLITE_OK ){
pInfo->nBackfill = mxSafeFrame;
+ if( pnCkpt ) *pnCkpt = mxSafeFrame;
}
}
/* Release the reader lock held while backfilling */
walUnlockExclusive(pWal, WAL_READ_LOCK(0), 1);
-
- if( xBusy && rc==SQLITE_OK && pWal->hdr.mxFrame==mxSafeFrame ){
- assert( pWal->writeLock );
- rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1);
- if( rc==SQLITE_OK ){
- walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
- }
- }
}
if( rc==SQLITE_BUSY ){
rc = SQLITE_OK;
}
+ if( rc==SQLITE_OK
+ && eMode==SQLITE_CHECKPOINT_RESTART
+ && pWal->hdr.mxFrame==mxSafeFrame
+ ){
+ assert( pWal->writeLock );
+ rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(1), WAL_NREADER-1);
+ if( rc==SQLITE_OK ){
+ walUnlockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
+ }
+ }
+
walcheckpoint_out:
walIteratorFree(pIter);
return rc;
if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
}
- rc = sqlite3WalCheckpoint(pWal, 0, 0, sync_flags, nBuf, zBuf);
+ rc = sqlite3WalCheckpoint(
+ pWal, SQLITE_CHECKPOINT_PASSIVE, 0, 0, sync_flags, nBuf, zBuf, 0, 0
+ );
if( rc==SQLITE_OK ){
isDelete = 1;
}
*/
int sqlite3WalCheckpoint(
Wal *pWal, /* Wal connection */
+ int eMode, /* PASSIVE, FULL or RESTART */
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) */
int nBuf, /* Size of temporary buffer */
- u8 *zBuf /* Temporary buffer to use */
+ u8 *zBuf, /* Temporary buffer to use */
+ int *pnLog, /* OUT: Number of frames in WAL */
+ int *pnCkpt /* OUT: Number of backfilled frames in WAL */
){
int rc; /* Return code */
int isChanged = 0; /* True if a new wal-index header is loaded */
** to prevent any writers from running while the checkpoint is underway.
** This has to be done before the call to walIndexReadHdr() below.
*/
- if( xBusy ){
+ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
if( rc==SQLITE_OK ) pWal->writeLock = 1;
}
rc = walIndexReadHdr(pWal, &isChanged);
}
if( rc==SQLITE_OK ){
- rc = walCheckpoint(pWal, xBusy, pBusyArg, sync_flags, nBuf, zBuf);
+ if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame;
+ rc = walCheckpoint(
+ pWal, eMode, xBusy, pBusyArg, sync_flags, nBuf, zBuf, pnCkpt);
}
if( isChanged ){
/* If a new wal-index header was loaded before the checkpoint was
#include "sqliteInt.h"
#ifdef SQLITE_OMIT_WAL
-# define sqlite3WalOpen(x,y,z) 0
-# define sqlite3WalClose(w,x,y,z) 0
-# define sqlite3WalBeginReadTransaction(y,z) 0
+# define sqlite3WalOpen(x,y,z) 0
+# define sqlite3WalClose(w,x,y,z) 0
+# define sqlite3WalBeginReadTransaction(y,z) 0
# define sqlite3WalEndReadTransaction(z)
-# define sqlite3WalRead(v,w,x,y,z) 0
-# define sqlite3WalDbsize(y) 0
-# define sqlite3WalBeginWriteTransaction(y) 0
-# define sqlite3WalEndWriteTransaction(x) 0
-# define sqlite3WalUndo(x,y,z) 0
+# define sqlite3WalRead(v,w,x,y,z) 0
+# define sqlite3WalDbsize(y) 0
+# define sqlite3WalBeginWriteTransaction(y) 0
+# define sqlite3WalEndWriteTransaction(x) 0
+# define sqlite3WalUndo(x,y,z) 0
# define sqlite3WalSavepoint(y,z)
-# define sqlite3WalSavepointUndo(y,z) 0
-# define sqlite3WalFrames(u,v,w,x,y,z) 0
-# define sqlite3WalCheckpoint(u,v,w,x,y,z) 0
-# define sqlite3WalCallback(z) 0
-# define sqlite3WalExclusiveMode(y,z) 0
-# define sqlite3WalHeapMemory(z) 0
+# define sqlite3WalSavepointUndo(y,z) 0
+# define sqlite3WalFrames(u,v,w,x,y,z) 0
+# define sqlite3WalCheckpoint(r,s,t,u,v,w,x,y,z) 0
+# define sqlite3WalCallback(z) 0
+# define sqlite3WalExclusiveMode(y,z) 0
+# define sqlite3WalHeapMemory(z) 0
#else
#define WAL_SAVEPOINT_NDATA 4
/* Copy pages from the log to the database file */
int sqlite3WalCheckpoint(
Wal *pWal, /* Write-ahead log connection */
+ int eMode, /* One of PASSIVE, FULL and RESTART */
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) */
int nBuf, /* Size of buffer nBuf */
- u8 *zBuf /* Temporary buffer to use */
+ u8 *zBuf, /* Temporary buffer to use */
+ int *pnLog, /* OUT: Number of frames in WAL */
+ int *pnCkpt /* OUT: Number of backfilled frames in WAL */
);
/* Return the value to pass to a sqlite3_wal_hook callback, the
#
set ::busy_handler_script { if {$n==5} { sql2 COMMIT } }
do_test 1.$tn.5 {
- sql1 { PRAGMA wal_blocking_checkpoint }
+ sql1 { PRAGMA wal_checkpoint = RESTART }
list [db_page_count] [wal_page_count] $::nBusyHandler
} {6 12 6}
do_test 1.$tn.6 {
if {$n==7} { sql3 COMMIT }
}
do_test 1.$tn.11 {
- sql1 { PRAGMA wal_blocking_checkpoint }
+breakpoint
+ sql1 { PRAGMA wal_checkpoint = RESTART }
list [db_page_count] [wal_page_count] $::nBusyHandler
} {10 5 8}
do_test 1.$tn.12 { set ::db_file_size } 10