]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the sqlite3_wal_checkpoint() and sqlite3_wal_autocheckpoint() APIs.
authordan <dan@noemail.net>
Mon, 3 May 2010 08:04:49 +0000 (08:04 +0000)
committerdan <dan@noemail.net>
Mon, 3 May 2010 08:04:49 +0000 (08:04 +0000)
FossilOrigin-Name: 9803196dec85e3aa4105cc477e9cfe98d370e486

manifest
manifest.uuid
src/main.c
src/pragma.c
src/sqlite.h.in
src/sqliteInt.h
src/vdbe.c
test/backup.test
test/walthread.test

index 5a53af92b170177ba798434d2213191d9dd9de43..ee782bfe90c104aefc0457320e37b6b3ff68ddd9 100644 (file)
--- 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
index 1b197ea0b1bcbe5c6cc492ee62dda373810cab37..c8b15e00439ce77899e3d7b368aff8c9ade3053c 100644 (file)
@@ -1 +1 @@
-6af2dca75b8139134ea394c1d71aefc6523f02e9
\ No newline at end of file
+9803196dec85e3aa4105cc477e9cfe98d370e486
\ No newline at end of file
index 57ea9736a3eeaeb7a01e38208a083d38a1663cc1..c714e03ffff81d0605c124c0da5370507db6b005 100644 (file)
@@ -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 );
index 263b7fc0cbad3dea9b2b82a180b6e8da3f1ea655..7e4c0b3f6bc8fe18a3575bf91a5a3a436cb7265d 100644 (file)
@@ -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
index d2ce5396f2331c502a0b018716e4fb430ade92cb..21ad68ead74bf410670cf660f6371fc6a43334c9 100644 (file)
@@ -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.
index 28268104ca7f30d7cbd76f2263e661d8e9bd8dad..ccc03432af8d6851b6a38c68aff553f8d76c31b9 100644 (file)
@@ -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
index c040fb8d2e48cf18e32536539d97259d4cf6ca9a..11c723b74b3f7837c54226462101c1e15a420940 100644 (file)
@@ -5193,12 +5193,7 @@ case OP_AggFinal: {
 ** WAL mode.
 */
 case OP_Checkpoint: {
-  Btree *pBt;                     /* Btree to checkpoint */
-
-  assert( pOp->p1>=0 && pOp->p1<db->nDb );
-  assert( (p->btreeMask & (1<<pOp->p1))!=0 );
-  pBt = db->aDb[pOp->p1].pBt;
-  rc = sqlite3PagerCheckpoint(sqlite3BtreePager(pBt));
+  rc = sqlite3Checkpoint(db, pOp->p1);
   break;
 };  
 #endif
index ca8de8eccab30a3c24f47586419e46165aaf6152..97945da4f188e6757c1464a3b216e7ba5be50639 100644 (file)
@@ -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 }
index 54f3eb4f7dc7ac11697681046de59bbeb3c239a8..59f38d3e99dc75943b5614ec83be1605344e4bfb 100644 (file)
@@ -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
-#     <do recovery work>
-#   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
-#     <do first part of recovery work>
-#     xShmRelease                   LEAVE mutexBuf
-#     xShmSize
-#     xShmGet                       ENTER mutexBuf
-#     <do second part of recovery work>
-#   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} {