From: dan Date: Mon, 3 May 2010 08:04:49 +0000 (+0000) Subject: Add the sqlite3_wal_checkpoint() and sqlite3_wal_autocheckpoint() APIs. X-Git-Tag: version-3.7.2~455^2~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=586b9c8a9470c36697f5ec04ef3533c9e26c5c89;p=thirdparty%2Fsqlite.git Add the sqlite3_wal_checkpoint() and sqlite3_wal_autocheckpoint() APIs. FossilOrigin-Name: 9803196dec85e3aa4105cc477e9cfe98d370e486 --- diff --git a/manifest b/manifest index 5a53af92b1..ee782bfe90 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,5 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -C Define\san\sinvariant\sto\sguarantee\sdeadlock-free\soperation\sof\sSHM\sin\sos_unix.c\nand\scheck\sthat\sinvariant\swith\sassert()\sstatements. -D 2010-05-01T17:57:36 +C Add\sthe\ssqlite3_wal_checkpoint()\sand\ssqlite3_wal_autocheckpoint()\sAPIs. +D 2010-05-03T08:04:49 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in d83a0ffef3dcbfb08b410a6c6dd6c009ec9167fb F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -134,7 +131,7 @@ F src/journal.c b0ea6b70b532961118ab70301c00a33089f9315c F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e F src/loadext.c 1c7a61ce1281041f437333f366a96aa0d29bb581 -F src/main.c b672c4af58f033c54398999dec5db9d4b6d99331 +F src/main.c 7aab969e23fea0140bdc2cc6d2b8978e8d9b0090 F src/malloc.c a08f16d134f0bfab6b20c3cd142ebf3e58235a6a F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 89d4ea8d5cdd55635cbaa48ad53132af6294cbb2 @@ -161,7 +158,7 @@ F src/parse.y ace5c7a125d9f2a410e431ee3209034105045f7e F src/pcache.c ace8f6a5ecd4711cc66a1b23053be7109bd437cf F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050 F src/pcache1.c 6dc1871ce8ead9187161c370a58cd06c84221f76 -F src/pragma.c 3d4ba9c35438b296360dc09ebf86c417cf996667 +F src/pragma.c 97c6054d7867b8c5b13023d3dc566274057cd853 F src/prepare.c fd1398cb1da54385ba5bd68d93928f10d10a1d9c F src/printf.c 5f5b65a83e63f2096a541a340722a509fa0240a7 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 @@ -169,9 +166,9 @@ F src/resolve.c ac5f1a713cd1ae77f08b83cc69581e11bf5ae6f9 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/select.c c03d8a0565febcde8c6a12c5d77d065fddae889b F src/shell.c c40427c7245535a04a9cb4a417b6cc05c022e6a4 -F src/sqlite.h.in 6e91727c0c3f9e1365e8fea2b07369a09830f47f +F src/sqlite.h.in dcf9cfc4e9c75d00b822d1a0d07f28cb970932bf F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89 -F src/sqliteInt.h 3eb613c8ba7f5159be0acf3fc148d41ec49add86 +F src/sqliteInt.h 1f81585797162269a0f18b77c815d552dad636c2 F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6 F src/status.c 4df6fe7dce2d256130b905847c6c60055882bdbe F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -215,7 +212,7 @@ F src/update.c c0dc6b75ad28b76b619042d934f337b02acee208 F src/utf.c 1baeeac91707a4df97ccc6141ec0f808278af685 F src/util.c 32aebf04c10e51ad3977a928b7416bed671b620b F src/vacuum.c 8e7d9a6fd076774bb6e211cad335c7337948a164 -F src/vdbe.c b2e2b70e9518c6cc986e74eca99607700904f4bd +F src/vdbe.c 8be37a1b18786b5c026adcb2e9edc93e3a940885 F src/vdbe.h 471f6a3dcec4817ca33596fe7f6654d56c0e75f3 F src/vdbeInt.h 19ebc8c2a2e938340051ee65af3f377fb99102d1 F src/vdbeapi.c 810abe698db3ccaf67c5a8982f8cd4f31c6c902f @@ -256,7 +253,7 @@ F test/autoindex1.test ffb06a246e2c1f89cfbe3d93eca513c9e78d4063 F test/autovacuum.test 25f891bc343a8bf5d9229e2e9ddab9f31a9ab5ec F test/autovacuum_ioerr2.test 598b0663074d3673a9c1bc9a16e80971313bafe6 F test/avtrans.test 7a26ffc6a355b7fbff2a082f56180ede863b126c -F test/backup.test b1e874fa9b01de9dd5137a8371d060b76a435162 +F test/backup.test 5f7f66d067e695a6040be3295a5abc289f823838 F test/backup2.test 159419073d9769fdb1780ed7e5b391a046f898d5 F test/backup_ioerr.test 1f012e692f42c0442ae652443258f70e9f20fa38 F test/backup_malloc.test 1e063c6d75143d0d6e0ae77971dd690070369387 @@ -767,7 +764,7 @@ F test/walcrash.test 20ebd86c0ea1bfdec97987c3cf667118f5c74a84 F test/walhook.test 5ee5fd35cdc3763d5674da0dd9974f6f70c07bed F test/walmode.test bac6f06544a8554588a1543def996bbe2fc41792 F test/walslow.test 9be52d033e871cb608a18fa4425a6dc64b625377 -F test/walthread.test 16559527eb1f1a6e9eff21cc92f7fa51fb0b5a32 +F test/walthread.test 4ef06a22d0d207aecba8cd11add820f6e7e94c43 F test/where.test de337a3fe0a459ec7c93db16a519657a90552330 F test/where2.test 43d4becaf5a5df854e6c21d624a1cb84c6904554 F test/where3.test aa44a9b29e8c9f3d7bb94a3bb3a95b31627d520d @@ -811,14 +808,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 1a0f69bef2c489e81a3d4b910b426972e9ed4054 -R 9a63fdaeb48f811dfa07166dc0124f9e -U drh -Z 0ec029f9a2c3c35cece8a5840fe4c2a0 ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.6 (GNU/Linux) - -iD8DBQFL3GuToxKgR168RlERAruJAJ93UG+yjpg4IAjppTK82HawrL2+6ACfZrj+ -F2hwX359XH9Tj7T1X7t3awQ= -=0PFi ------END PGP SIGNATURE----- +P 6af2dca75b8139134ea394c1d71aefc6523f02e9 +R c94ad925a665396e6feea1ca0a681bf5 +U dan +Z 86d18456fd55c8daa32a6607f2d982a8 diff --git a/manifest.uuid b/manifest.uuid index 1b197ea0b1..c8b15e0043 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6af2dca75b8139134ea394c1d71aefc6523f02e9 \ No newline at end of file +9803196dec85e3aa4105cc477e9cfe98d370e486 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 57ea9736a3..c714e03fff 100644 --- a/src/main.c +++ b/src/main.c @@ -1186,6 +1186,42 @@ void *sqlite3_rollback_hook( return pRet; } +#ifndef SQLITE_OMIT_WAL +/* +** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint(). +** Return non-zero, indicating to the caller that a checkpoint should be run, +** if the number of frames in the log file is greater than +** sqlite3.nDefaultCheckpoint (the value configured by wal_autocheckpoint()). +*/ +static int defaultWalHook(void *p, sqlite3 *db, const char *z, int nFrame){ + UNUSED_PARAMETER(p); + UNUSED_PARAMETER(z); + return ( nFrame>=db->nDefaultCheckpoint ); +} + +/* +** Configure an sqlite3_wal_hook() callback to automatically checkpoint +** a database after committing a transaction if there are nFrame or +** more frames in the log file. Passing zero or a negative value as the +** nFrame parameter disables automatic checkpoints entirely. +** +** The callback registered by this function replaces any existing callback +** registered using sqlite3_wal_hook(). Likewise, registering a callback +** using sqlite3_wal_hook() disables the automatic checkpoint mechanism +** configured by this function. +*/ +int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ + sqlite3_mutex_enter(db->mutex); + if( nFrame>0 ){ + db->nDefaultCheckpoint = nFrame; + sqlite3_wal_hook(db, defaultWalHook, 0); + }else{ + sqlite3_wal_hook(db, 0, 0); + } + sqlite3_mutex_leave(db->mutex); + return SQLITE_OK; +} + /* ** Register a callback to be invoked each time a transaction is written ** into the write-ahead-log by this database connection. @@ -1195,7 +1231,6 @@ void *sqlite3_wal_hook( int(*xCallback)(void *, sqlite3*, const char*, int), void *pArg /* First argument passed to xCallback() */ ){ -#ifndef SQLITE_OMIT_WAL void *pRet; sqlite3_mutex_enter(db->mutex); pRet = db->pWalArg; @@ -1203,10 +1238,77 @@ void *sqlite3_wal_hook( db->pWalArg = pArg; sqlite3_mutex_leave(db->mutex); return pRet; -#else +} + +/* +** Checkpoint database zDb. If zDb is NULL, the main database is checkpointed. +*/ +int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ + int rc; /* Return code */ + int iDb = 0; /* sqlite3.aDb[] index of db to checkpoint */ + + sqlite3_mutex_enter(db->mutex); + if( zDb ){ + iDb = sqlite3FindDbName(db, zDb); + } + if( iDb<0 ){ + rc = SQLITE_ERROR; + }else{ + rc = sqlite3Checkpoint(db, iDb); + } + sqlite3_mutex_leave(db->mutex); + + return rc; +} + +/* +** Run a checkpoint on database iDb. This is a no-op if database iDb is +** not currently open in WAL mode. +** +** If a transaction is open at either the database handle (db) or b-tree +** level, this function returns SQLITE_LOCKED and a checkpoint is not +** attempted. If an error occurs while running the checkpoint, an SQLite +** error code is returned (i.e. SQLITE_IOERR). Otherwise, SQLITE_OK. +** +** The mutex on database handle db should be held by the caller. The mutex +** associated with the specific b-tree being checkpointed is taken by +** this function while the checkpoint is running. +*/ +int sqlite3Checkpoint(sqlite3 *db, int iDb){ + Btree *pBt; /* Btree handle to checkpoint */ + int rc; /* Return code */ + + assert( sqlite3_mutex_held(db->mutex) ); + + pBt = db->aDb[iDb].pBt; + if( sqlite3BtreeIsInReadTrans(pBt) ){ + rc = SQLITE_LOCKED; + }else{ + sqlite3BtreeEnter(pBt); + rc = sqlite3PagerCheckpoint(sqlite3BtreePager(pBt)); + sqlite3BtreeLeave(pBt); + } + + return rc; +} +#else /* ifndef SQLITE_OMIT_WAL */ +/* +** If SQLITE_OMIT_WAL is defined, the following API functions are no-ops: +** +** sqlite3_wal_hook() +** sqlite3_wal_checkpoint() +** sqlite3_wal_autocheckpoint() +*/ +void *sqlite3_wal_hook( + sqlite3 *x, + int(*xCallback)(void *, sqlite3*, const char*, int), + void *pArg +){ return 0; -#endif } +int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){ return SQLITE_OK; } +int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ return SQLITE_OK; } +#endif /* ** This function returns true if main-memory should be used instead of @@ -1768,6 +1870,8 @@ static int openDatabase( setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside, sqlite3GlobalConfig.nLookaside); + sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_CACHE_SIZE); + opendb_out: if( db ){ assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 ); diff --git a/src/pragma.c b/src/pragma.c index 263b7fc0cb..7e4c0b3f6b 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1407,7 +1407,6 @@ void sqlite3Pragma( ** Checkpoint the database. */ if( sqlite3StrICmp(zLeft, "checkpoint")==0 ){ - sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp3(v, OP_Checkpoint, iDb, 0, 0); }else #endif diff --git a/src/sqlite.h.in b/src/sqlite.h.in index d2ce5396f2..21ad68ead7 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -5797,6 +5797,16 @@ void *sqlite3_wal_hook( void* ); +/* +** CAPI3REF: Configure an auto-checkpoint +*/ +int sqlite3_wal_autocheckpoint(sqlite3 *db, int N); + +/* +** CAPI3REF: Checkpoint a database +*/ +int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb); + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 28268104ca..ccc03432af 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -824,6 +824,7 @@ struct sqlite3 { void *pUpdateArg; void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); #ifndef SQLITE_OMIT_WAL + int nDefaultCheckpoint; /* Value configured by wal_autocheckpoint() */ int (*xWalCallback)(void *, sqlite3 *, const char *, int); void *pWalArg; #endif @@ -2998,6 +2999,7 @@ CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *); int sqlite3TempInMemory(const sqlite3*); VTable *sqlite3GetVTable(sqlite3*, Table*); const char *sqlite3JournalModename(int); +int sqlite3Checkpoint(sqlite3*, int); /* Declarations for functions in fkey.c. All of these are replaced by ** no-op macros if OMIT_FOREIGN_KEY is defined. In this case no foreign diff --git a/src/vdbe.c b/src/vdbe.c index c040fb8d2e..11c723b74b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -5193,12 +5193,7 @@ case OP_AggFinal: { ** WAL mode. */ case OP_Checkpoint: { - Btree *pBt; /* Btree to checkpoint */ - - assert( pOp->p1>=0 && pOp->p1nDb ); - assert( (p->btreeMask & (1<p1))!=0 ); - pBt = db->aDb[pOp->p1].pBt; - rc = sqlite3PagerCheckpoint(sqlite3BtreePager(pBt)); + rc = sqlite3Checkpoint(db, pOp->p1); break; }; #endif diff --git a/test/backup.test b/test/backup.test index ca8de8ecca..97945da4f1 100644 --- a/test/backup.test +++ b/test/backup.test @@ -489,6 +489,7 @@ db2 close # 3) Backing up memory-to-file. # set iTest 0 +file delete -force bak.db-wal foreach {writer file} {db test.db db3 test.db db :memory:} { incr iTest catch { file delete bak.db } diff --git a/test/walthread.test b/test/walthread.test index 54f3eb4f7d..59f38d3e99 100644 --- a/test/walthread.test +++ b/test/walthread.test @@ -462,30 +462,6 @@ do_thread_test2 walthread-4 -seconds $seconds(walthread-4) -init { # very large wal file (one that requires a wal-index larger than the # initial default allocation of 64KB). # -# When recovering a log file, mutexes are usually obtained and released -# as follows: -# -# xShmGet ENTER mutexBuf -# xShmLock(RECOVER) ENTER mutexRecov -# -# xShmLock(READ) LEAVE mutexRecov -# xShmRelease LEAVE mutexBuf -# -# However, if the initial wal-index allocation needs to be enlarged during -# the recovery process, the mutex operations become: -# -# xShmGet ENTER mutexBuf -# xShmLock(RECOVER) ENTER mutexRecov -# -# xShmRelease LEAVE mutexBuf -# xShmSize -# xShmGet ENTER mutexBuf -# -# xShmLock(READ) LEAVE mutexRecov -# xShmRelease LEAVE mutexBuf -# -# If multiple threads attempt the above simultaneously, deadlock can occur. -# do_thread_test walthread-5 -seconds $seconds(walthread-5) -init { proc log_file_size {nFrame pgsz} {