]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
If a database file with the WAL flag set is opened in exclusive-locking mode, use...
authordan <dan@noemail.net>
Mon, 1 Nov 2010 17:38:24 +0000 (17:38 +0000)
committerdan <dan@noemail.net>
Mon, 1 Nov 2010 17:38:24 +0000 (17:38 +0000)
FossilOrigin-Name: 8dd5c69198619866923c6053b71899c1fb8c4c67

12 files changed:
manifest
manifest.uuid
src/pager.c
src/test_vfs.c
src/wal.c
src/wal.h
test/pager1.test
test/permutations.test
test/tester.tcl
test/wal2.test
test/walfault.test
test/walnoshm.test [new file with mode: 0644]

index 147d5a4acca2d1db18efd6eb5148f8b66c1d5f8d..2590bc11f47cfd4963557e4e704bdd644b369edb 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,8 +1,5 @@
------BEGIN PGP SIGNED MESSAGE-----
-Hash: SHA1
-
-C Change\sthe\sversion\snumber\sto\s3.7.4.
-D 2010-11-01T14:34:31
+C If\sa\sdatabase\sfile\swith\sthe\sWAL\sflag\sset\sis\sopened\sin\sexclusive-locking\smode,\suse\sheap\smemory\sto\sstore\sthe\swal-index\sinstead\sof\sshared-memory.
+D 2010-11-01T17:38:25
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 2c8cefd962eca0147132c7cf9eaa4bb24c656f3f
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -165,7 +162,7 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
 F src/os_os2.c 72d0b2e562952a2464308c4ce5f7913ac10bef3e
 F src/os_unix.c 00a4a84aba46b61439913bebf0c10d408e42a630
 F src/os_win.c 2f90f7bdec714fad51cd31b4ecad3cc1b4bb5aad
-F src/pager.c d9858b47b216e3bcb0431bd50ef17d070ac0b92c
+F src/pager.c c19b0e8d49220825fd382236fbbcb3063c48ce2d
 F src/pager.h 8167a1e720d0b7a2790079007128e594010220ad
 F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
 F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
@@ -221,7 +218,7 @@ F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6
 F src/test_stat.c f682704b5d1ba8e1d4e7e882a6d7922e2dcf066c
 F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
 F src/test_thread.c bedd05cad673dba53326f3aa468cc803038896c0
-F src/test_vfs.c 702e52636113f6b9721da90ef1bf26e07fff414d
+F src/test_vfs.c e10fcca756cafa89438311b31522ac1f95bf784b
 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/tokenize.c 604607d6813e9551cf5189d899e0a25c12681080
 F src/trigger.c b8bedb9c0084ceb51a40f54fcca2ce048c8de852
@@ -238,8 +235,8 @@ F src/vdbeblob.c e0ce3c54cc0c183af2ec67b63a289acf92251df4
 F src/vdbemem.c 23723a12cd3ba7ab3099193094cbb2eb78956aa9
 F src/vdbetrace.c 864cef96919323482ebd9986f2132435115e9cc2
 F src/vtab.c b297e8fa656ab5e66244ab15680d68db0adbec30
-F src/wal.c 0dc7eb9e907a2c280cdcde876d313e07ea4ad811
-F src/wal.h 96669b645e27cd5a111ba59f0cae7743a207bc3c
+F src/wal.c f26b8d297bd11cb792e609917f9d4c6718ac8e0e
+F src/wal.h c1aac6593a0b02b15dc625987e619edeab39292e
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
 F src/where.c d9a31eb3d59466b6c53567c8c9a6c2fe68bbd565
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -569,7 +566,7 @@ F test/notify3.test d60923e186e0900f4812a845fcdfd8eea096e33a
 F test/notnull.test cc7c78340328e6112a13c3e311a9ab3127114347
 F test/null.test a8b09b8ed87852742343b33441a9240022108993
 F test/openv2.test af02ed0a9cbc0d2a61b8f35171d4d117e588e4ec
-F test/pager1.test 12ad20280db1ba25f1f0d7ddebf0971a305d8f80
+F test/pager1.test fa74657dc832f0e21dc3ce60829feaee143296ba
 F test/pager2.test 0fbb6b6dc40ce1fecfe758c555a748ad2e9beaa3
 F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
 F test/pagerfault.test 3cd3537bf2efb4baef26c74878718f4a32926da4
@@ -578,7 +575,7 @@ F test/pageropt.test 8146bf448cf09e87bb1867c2217b921fb5857806
 F test/pagesize.test 76aa9f23ecb0741a4ed9d2e16c5fa82671f28efb
 F test/pcache.test 4118a183908ecaed343a06fcef3ba82e87e0129d
 F test/pcache2.test 0d85f2ab6963aee28c671d4c71bec038c00a1d16
-F test/permutations.test da40da6433f050b50e65a8ae37265ab6c89f876c
+F test/permutations.test e54d5fc34708ecb4a67f2a18f7b8719b175a1652
 F test/pragma.test fdfc09067ea104a0c247a1a79d8093b56656f850
 F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47
 F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea
@@ -655,7 +652,7 @@ F test/tclsqlite.test 8c154101e704170c2be10f137a5499ac2c6da8d3
 F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
 F test/temptable.test f42121a0d29a62f00f93274464164177ab1cc24a
 F test/temptrigger.test b0273db072ce5f37cf19140ceb1f0d524bbe9f05
-F test/tester.tcl b9c732d1228f0daab41bbbeddd6d0861394b23aa
+F test/tester.tcl fa48313dcf20f9c6def1af485e284e29100d709e
 F test/thread001.test a3e6a7254d1cb057836cb3145b60c10bf5b7e60f
 F test/thread002.test afd20095e6e845b405df4f2c920cb93301ca69db
 F test/thread003.test b824d4f52b870ae39fc5bae4d8070eca73085dca
@@ -823,7 +820,7 @@ F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
 F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
 F test/vtab_shared.test 0eff9ce4f19facbe0a3e693f6c14b80711a4222d
 F test/wal.test 70227190e713b3e7eb2a7d5ec3510b66db01f327
-F test/wal2.test 223f3e14d475730af772a7f5862d4bcfa7565c3a
+F test/wal2.test c794b8b257af54190bb913678ad3984cbf3311b9
 F test/wal3.test 957a5f2a8fe8a6ff01de1a15285ecf2f376fcaf8
 F test/wal4.test 3404b048fa5e10605facaf70384e6d2943412e30
 F test/wal_common.tcl 895d76138043b86bdccf36494054bdabcf65837b
@@ -832,9 +829,10 @@ F test/walbig.test e882bc1d014afffbfa2b6ba36e0f07d30a633ad0
 F test/walcksum.test a37b36375c595e61bdb7e1ec49b5f0979b6fc7ce
 F test/walcrash.test e763841551d6b23677ccb419797c1589dcbdbaf5
 F test/walcrash2.test 019d60b89d96c1937adb2b30b850ac7e86e5a142
-F test/walfault.test 05c470688d742688e455dd56816bd6bcffa298f8
+F test/walfault.test 1211c3c5f35142d93940c709c61fbaf58c3afab6
 F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
 F test/walmode.test 22ddccd073c817ac9ead62b88ac446e8dedc7d2c
+F test/walnoshm.test 732391f72af2785d2758aaa8f9ae563d6d519b20
 F test/walshared.test 6dda2293880c300baf5d791c307f653094585761
 F test/walslow.test d21625e2e99e11c032ce949e8a94661576548933
 F test/walthread.test a25a393c068a2b42b44333fa3fdaae9072f1617c
@@ -884,14 +882,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 582db83294599ffd7265d3ab2db2765e7e4fbb8d
-R a1ed7a266761633aef3d19047277de6a
-U drh
-Z 4f48c9a1b8040f4fd58227e590b304c6
------BEGIN PGP SIGNATURE-----
-Version: GnuPG v1.4.6 (GNU/Linux)
-
-iD8DBQFMzs/6oxKgR168RlERAuCbAJ9uimmTB547wDq4mUtvniDAfA0HTwCeNbhj
-lkScdJYDKuse8cKgqrNrUF4=
-=7Gng
------END PGP SIGNATURE-----
+P db64843b540d23c58fe4de199a7fc40d44900bc4
+R 2b6e847446dd321925fabfa8d797522d
+U dan
+Z 4b3ff964892084a664463cd0c913ef99
index faac2fc344967982b4e14098be4e6d78cf6b15e8..0c247a0a336fabfc6b1cdd0d1b2cd950fcf34095 100644 (file)
@@ -1 +1 @@
-db64843b540d23c58fe4de199a7fc40d44900bc4
\ No newline at end of file
+8dd5c69198619866923c6053b71899c1fb8c4c67
\ No newline at end of file
index a1cc4e0500226f39e1a79da337c40e963daf014a..f748a443ef9abf9d3e76fa712321dc18ee706694 100644 (file)
@@ -1050,7 +1050,7 @@ static int write32bits(sqlite3_file *fd, i64 offset, u32 val){
 static int pagerUnlockDb(Pager *pPager, int eLock){
   int rc = SQLITE_OK;
 
-  assert( !pPager->exclusiveMode );
+  assert( !pPager->exclusiveMode || pPager->eLock==eLock );
   assert( eLock==NO_LOCK || eLock==SHARED_LOCK );
   assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
   if( isOpen(pPager->fd) ){
@@ -6350,7 +6350,8 @@ int sqlite3PagerLockingMode(Pager *pPager, int eMode){
             || eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
   assert( PAGER_LOCKINGMODE_QUERY<0 );
   assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 );
-  if( eMode>=0 && !pPager->tempFile ){
+  assert( pPager->exclusiveMode || 0==sqlite3WalHeapMemory(pPager->pWal) );
+  if( eMode>=0 && !pPager->tempFile && !sqlite3WalHeapMemory(pPager->pWal) ){
     pPager->exclusiveMode = (u8)eMode;
   }
   return (int)pPager->exclusiveMode;
@@ -6537,9 +6538,61 @@ int sqlite3PagerWalCallback(Pager *pPager){
 */
 int sqlite3PagerWalSupported(Pager *pPager){
   const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
-  return pMethods->iVersion>=2 && pMethods->xShmMap!=0;
+  return pPager->exclusiveMode || (pMethods->iVersion>=2 && pMethods->xShmMap);
 }
 
+/*
+** Attempt to take an exclusive lock on the database file. If a PENDING lock
+** is obtained instead, immediately release it.
+*/
+static int pagerExclusiveLock(Pager *pPager){
+  int rc;                         /* Return code */
+
+  assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
+  rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
+  if( rc!=SQLITE_OK ){
+    /* If the attempt to grab the pending lock failed, release the 
+    ** exclusive lock that may have been obtained instead.  */
+    pagerUnlockDb(pPager, SHARED_LOCK);
+  }
+
+  return rc;
+}
+
+/*
+** Call sqlite3WalOpen() to open the WAL handle. If the pager is in 
+** exclusive-locking mode when this function is called, take an EXCLUSIVE
+** lock on the database file and use heap-memory to store the wal-index
+** in. Otherwise, use the normal shared-memory.
+*/
+static int pagerOpenWal(Pager *pPager){
+  int rc = SQLITE_OK;
+
+  assert( pPager->pWal==0 && pPager->tempFile==0 );
+  assert( pPager->eLock==SHARED_LOCK || pPager->eLock==EXCLUSIVE_LOCK );
+
+  /* If the pager is already in exclusive-mode, the WAL module will use 
+  ** heap-memory for the wal-index instead of the VFS shared-memory 
+  ** implementation. Take the exclusive lock now, before opening the WAL
+  ** file, to make sure this is safe.
+  */
+  if( pPager->exclusiveMode ){
+    rc = pagerExclusiveLock(pPager);
+  }
+
+  /* Open the connection to the log file. If this operation fails, 
+  ** (e.g. due to malloc() failure), return an error code.
+  */
+  if( rc==SQLITE_OK ){
+    rc = sqlite3WalOpen(pPager->pVfs, 
+        pPager->fd, pPager->zWal, pPager->exclusiveMode, &pPager->pWal
+    );
+  }
+
+  return rc;
+}
+
+
 /*
 ** The caller must be holding a SHARED lock on the database file to call
 ** this function.
@@ -6573,11 +6626,7 @@ int sqlite3PagerOpenWal(
     /* Close any rollback journal previously open */
     sqlite3OsClose(pPager->jfd);
 
-    /* Open the connection to the log file. If this operation fails, 
-    ** (e.g. due to malloc() failure), unlock the database file and 
-    ** return an error code.
-    */
-    rc = sqlite3WalOpen(pPager->pVfs, pPager->fd, pPager->zWal, &pPager->pWal);
+    rc = pagerOpenWal(pPager);
     if( rc==SQLITE_OK ){
       pPager->journalMode = PAGER_JOURNALMODE_WAL;
       pPager->eState = PAGER_OPEN;
@@ -6616,8 +6665,7 @@ int sqlite3PagerCloseWal(Pager *pPager){
       );
     }
     if( rc==SQLITE_OK && logexists ){
-      rc = sqlite3WalOpen(pPager->pVfs, pPager->fd,
-                          pPager->zWal, &pPager->pWal);
+      rc = pagerOpenWal(pPager);
     }
   }
     
@@ -6625,17 +6673,13 @@ int sqlite3PagerCloseWal(Pager *pPager){
   ** the database file, the log and log-summary files will be deleted.
   */
   if( rc==SQLITE_OK && pPager->pWal ){
-    rc = pagerLockDb(pPager, EXCLUSIVE_LOCK);
+    rc = pagerExclusiveLock(pPager);
     if( rc==SQLITE_OK ){
       rc = sqlite3WalClose(pPager->pWal,
-                           (pPager->noSync ? 0 : pPager->sync_flags), 
-        pPager->pageSize, (u8*)pPager->pTmpSpace
+          (pPager->noSync ? 0 : pPager->sync_flags), 
+          pPager->pageSize, (u8*)pPager->pTmpSpace
       );
       pPager->pWal = 0;
-    }else{
-      /* If we cannot get an EXCLUSIVE lock, downgrade the PENDING lock
-      ** that we did get back to SHARED. */
-      pagerUnlockDb(pPager, SQLITE_LOCK_SHARED);
     }
   }
   return rc;
index c606cfbe5c59e3457b7129945730217e1223eef4..ebe4a576a4d1be35394bef0bfd58be91ba99702f 100644 (file)
@@ -26,6 +26,7 @@
 **   -default    BOOLEAN        (True to make the vfs default. Default false)
 **   -szosfile   INTEGER        (Value for sqlite3_vfs.szOsFile)
 **   -mxpathname INTEGER        (Value for sqlite3_vfs.mxPathname)
+**   -iversion   INTEGER        (Value for sqlite3_vfs.iVersion)
 */
 
 #include "sqlite3.h"
index f90faa238d4d0ed0914cf1acce2438ff5c3ad030..3b217908b77335ffbdc8fd93e703d88dcad57f70 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -428,6 +428,13 @@ struct Wal {
 #endif
 };
 
+/*
+** Candidate values for Wal.exclusiveMode.
+*/
+#define WAL_NORMAL_MODE     0
+#define WAL_EXCLUSIVE_MODE  1     
+#define WAL_HEAPMEMORY_MODE 2
+
 /*
 ** Each page of the wal-index mapping contains a hash-table made up of
 ** an array of HASHTABLE_NSLOT elements of the following type.
@@ -514,9 +521,14 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
 
   /* Request a pointer to the required page from the VFS */
   if( pWal->apWiData[iPage]==0 ){
-    rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, 
-        pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
-    );
+    if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
+      pWal->apWiData[iPage] = (u32 volatile *)sqlite3MallocZero(WALINDEX_PGSZ);
+      if( !pWal->apWiData[iPage] ) rc = SQLITE_NOMEM;
+    }else{
+      rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, 
+          pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
+      );
+    }
   }
 
   *ppPage = pWal->apWiData[iPage];
@@ -599,6 +611,12 @@ static void walChecksumBytes(
   aOut[1] = s2;
 }
 
+static void walShmBarrier(Wal *pWal){
+  if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
+    sqlite3OsShmBarrier(pWal->pDbFd);
+  }
+}
+
 /*
 ** Write the header information in pWal->hdr into the wal-index.
 **
@@ -613,7 +631,7 @@ static void walIndexWriteHdr(Wal *pWal){
   pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
   walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
   memcpy((void *)&aHdr[1], (void *)&pWal->hdr, sizeof(WalIndexHdr));
-  sqlite3OsShmBarrier(pWal->pDbFd);
+  walShmBarrier(pWal);
   memcpy((void *)&aHdr[0], (void *)&pWal->hdr, sizeof(WalIndexHdr));
 }
 
@@ -1185,7 +1203,15 @@ recovery_error:
 ** Close an open wal-index.
 */
 static void walIndexClose(Wal *pWal, int isDelete){
-  sqlite3OsShmUnmap(pWal->pDbFd, isDelete);
+  if( pWal->exclusiveMode==WAL_HEAPMEMORY_MODE ){
+    int i;
+    for(i=0; i<pWal->nWiData; i++){
+      sqlite3_free((void *)pWal->apWiData[i]);
+      pWal->apWiData[i] = 0;
+    }
+  }else{
+    sqlite3OsShmUnmap(pWal->pDbFd, isDelete);
+  }
 }
 
 /* 
@@ -1207,6 +1233,7 @@ int sqlite3WalOpen(
   sqlite3_vfs *pVfs,              /* vfs module to open wal and wal-index */
   sqlite3_file *pDbFd,            /* The open database file */
   const char *zWalName,           /* Name of the WAL file */
+  int bNoShm,                     /* True to run in heap-memory mode */
   Wal **ppWal                     /* OUT: Allocated Wal handle */
 ){
   int rc;                         /* Return Code */
@@ -1240,6 +1267,7 @@ int sqlite3WalOpen(
   pRet->pDbFd = pDbFd;
   pRet->readLock = -1;
   pRet->zWalName = zWalName;
+  pRet->exclusiveMode = (bNoShm ? WAL_HEAPMEMORY_MODE: WAL_NORMAL_MODE);
 
   /* Open file handle on the write-ahead log file. */
   flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_WAL);
@@ -1673,7 +1701,9 @@ int sqlite3WalClose(
     */
     rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
     if( rc==SQLITE_OK ){
-      pWal->exclusiveMode = 1;
+      if( pWal->exclusiveMode==WAL_NORMAL_MODE ){
+        pWal->exclusiveMode = WAL_EXCLUSIVE_MODE;
+      }
       rc = sqlite3WalCheckpoint(pWal, sync_flags, nBuf, zBuf);
       if( rc==SQLITE_OK ){
         isDelete = 1;
@@ -1729,7 +1759,7 @@ static int walIndexTryHdr(Wal *pWal, int *pChanged){
   */
   aHdr = walIndexHdr(pWal);
   memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
-  sqlite3OsShmBarrier(pWal->pDbFd);
+  walShmBarrier(pWal);
   memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
 
   if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
@@ -1930,7 +1960,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
     ** and can be safely ignored.
     */
     rc = walLockShared(pWal, WAL_READ_LOCK(0));
-    sqlite3OsShmBarrier(pWal->pDbFd);
+    walShmBarrier(pWal);
     if( rc==SQLITE_OK ){
       if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
         /* It is not safe to allow the reader to continue here if frames
@@ -2024,7 +2054,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
     ** log-wrap (either of which would require an exclusive lock on
     ** WAL_READ_LOCK(mxI)) has not occurred since the snapshot was valid.
     */
-    sqlite3OsShmBarrier(pWal->pDbFd);
+    walShmBarrier(pWal);
     if( pInfo->aReadMark[mxI]!=mxReadMark
      || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr))
     ){
@@ -2667,13 +2697,14 @@ int sqlite3WalCallback(Wal *pWal){
 ** on the main database file before invoking this operation.
 **
 ** If op is negative, then do a dry-run of the op==1 case but do
-** not actually change anything.  The pager uses this to see if it
+** not actually change anything. The pager uses this to see if it
 ** should acquire the database exclusive lock prior to invoking
 ** the op==1 case.
 */
 int sqlite3WalExclusiveMode(Wal *pWal, int op){
   int rc;
   assert( pWal->writeLock==0 );
+  assert( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE || op==-1 );
 
   /* pWal->readLock is usually set, but might be -1 if there was a 
   ** prior error while attempting to acquire are read-lock. This cannot 
@@ -2707,4 +2738,13 @@ int sqlite3WalExclusiveMode(Wal *pWal, int op){
   return rc;
 }
 
+/* 
+** Return true if the argument is non-NULL and the WAL module is using
+** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
+** WAL module is using shared-memory, return false. 
+*/
+int sqlite3WalHeapMemory(Wal *pWal){
+  return (pWal && pWal->exclusiveMode==WAL_HEAPMEMORY_MODE );
+}
+
 #endif /* #ifndef SQLITE_OMIT_WAL */
index f20dfa8e17586bed8cf039d21b39d28cd79107aa..35f695c88ab35536d6dec28eb96da5b05ce8ccb4 100644 (file)
--- a/src/wal.h
+++ b/src/wal.h
@@ -35,6 +35,7 @@
 # define sqlite3WalCheckpoint(u,v,w,x)         0
 # define sqlite3WalCallback(z)                 0
 # define sqlite3WalExclusiveMode(y,z)          0
+# define sqlite3WalHeapMemory(z)               0
 #else
 
 #define WAL_SAVEPOINT_NDATA 4
@@ -45,7 +46,7 @@
 typedef struct Wal Wal;
 
 /* Open and close a connection to a write-ahead log. */
-int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *zName, Wal**);
+int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *zName, int, Wal**);
 int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
 
 /* Used by readers to open (lock) and close (unlock) a snapshot.  A 
@@ -102,5 +103,11 @@ int sqlite3WalCallback(Wal *pWal);
 */
 int sqlite3WalExclusiveMode(Wal *pWal, int op);
 
+/* Return true if the argument is non-NULL and the WAL module is using
+** heap-memory for the wal-index. Otherwise, if the argument is NULL or the
+** WAL module is using shared-memory, return false. 
+*/
+int sqlite3WalHeapMemory(Wal *pWal);
+
 #endif /* ifndef SQLITE_OMIT_WAL */
 #endif /* _WAL_H_ */
index b09730d5293955dde9d83f73c37ee3b958c907dc..1e162654fe2a8b0e70d2fc41e75d9fa2cb18d22b 100644 (file)
@@ -1107,10 +1107,10 @@ ifcapable wal {
       COMMIT;
     } {1 2} 0 -1
   
-    4  { PRAGMA journal_mode = WAL }    wal    -1 -1
-    5  { INSERT INTO t1 VALUES(3, 4) }  {}     -1 [wal_file_size 1 1024]
-    6  { PRAGMA locking_mode = NORMAL } normal -1 [wal_file_size 1 1024]
-    7  { INSERT INTO t1 VALUES(5, 6); } {}     -1 [wal_file_size 2 1024]
+    4  { PRAGMA journal_mode = WAL }    wal       -1 -1
+    5  { INSERT INTO t1 VALUES(3, 4) }  {}        -1 [wal_file_size 1 1024]
+    6  { PRAGMA locking_mode = NORMAL } exclusive -1 [wal_file_size 1 1024]
+    7  { INSERT INTO t1 VALUES(5, 6); } {}        -1 [wal_file_size 2 1024]
   
     8  { PRAGMA journal_mode = TRUNCATE } truncate          0 -1
     9  { INSERT INTO t1 VALUES(7, 8) }    {}                0 -1
index 83ee11e53c8a7017085685c48f2c407b872237ca..14cf3abfe620bbccce38c8d928d5e89fb6ca4646 100644 (file)
@@ -183,7 +183,7 @@ test_suite "coverage-wal" -description {
 } -files {
   wal.test       wal2.test     wal3.test       walmode.test    
   walbak.test    walhook.test  walcrash2.test  walcksum.test
-  walfault.test  walbig.test
+  walfault.test  walbig.test   walnoshm.test
 } 
 
 test_suite "coverage-pager" -description {
index 00692ef09fd17cc8a208a3d80e8aef067102d6e6..22586fbd3054125772863475af4195ebabb15c63 100644 (file)
@@ -303,6 +303,8 @@ proc do_test {name cmd expected} {
 
   global argv cmdlinearg
 
+  fix_testname name
+
   sqlite3_memdebug_settitle $name
 
 #  if {[llength $argv]==0} { 
index 03c0018f498200eca6b483d55ef6033a190563f7..a62e9b99e6554b7f3aa8469a44cfe050b3c6d493 100644 (file)
@@ -430,13 +430,16 @@ do_test wal2-6.1.1 {
   sqlite3 db test.db
   execsql {
     Pragma Journal_Mode = Wal;
-    Pragma Locking_Mode = Exclusive;
   }
-} {wal exclusive}
+} {wal}
 do_test wal2-6.1.2 {
   execsql { PRAGMA lock_status }
 } {main unlocked temp closed}
 do_test wal2-6.1.3 {
+  execsql {
+    SELECT * FROM sqlite_master;
+    Pragma Locking_Mode = Exclusive;
+  }
   execsql {
     BEGIN;
       CREATE TABLE t1(a, b);
@@ -486,6 +489,7 @@ do_test wal2-6.2.2 {
 do_test wal2-6.2.3 {
   db close
   sqlite3 db test.db
+  execsql { SELECT * FROM sqlite_master }
   execsql { PRAGMA LOCKING_MODE = EXCLUSIVE }
 } {exclusive}
 do_test wal2-6.2.4 {
@@ -732,6 +736,7 @@ do_test wal2-6.6.1 {
   T script lock_control
   T filter {}
   sqlite3 db test.db -vfs T
+  execsql { SELECT * FROM sqlite_master }
   execsql { PRAGMA locking_mode = exclusive }
   execsql { INSERT INTO t2 VALUES('V', 'VI') }
 } {}
@@ -755,7 +760,7 @@ do_test wal2-6.6.2 {
   T filter {}
   execsql { INSERT INTO t2 VALUES('IX', 'X') }
 } {}
-do_test wal2-6.6.3 {
+do_test wal2-6.6.4 {
   # This time, we have successfully exited exclusive mode. So the second
   # connection can read the database.
   sqlite3 db2 test.db -vfs T
index f22a40ecfd2d484d80aa9b557216af9c205ad0f5..5fd71bc04d01255dd16886e0db9d55630cd42bfd 100644 (file)
@@ -446,5 +446,73 @@ do_faultsim_test walfault-12 -prep {
   faultsim_test_result {0 {}}
 }
 
+#-------------------------------------------------------------------------
+# Test simple recovery, reading and writing a database file using a 
+# heap-memory wal-index.
+# 
+do_test walfault-13-pre-1 {
+  faultsim_delete_and_reopen
+  execsql {
+    PRAGMA journal_mode = WAL;
+    PRAGMA wal_autocheckpoint = 0;
+    BEGIN;
+      CREATE TABLE abc(a PRIMARY KEY);
+      INSERT INTO abc VALUES(randomblob(1500));
+      INSERT INTO abc VALUES(randomblob(1500));
+    COMMIT;
+  }
+  faultsim_save_and_close
+  file delete sv_test.db-shm
+} {}
+
+do_faultsim_test walfault-13.1 -prep {
+  faultsim_restore_and_reopen
+} -body {
+  db eval { PRAGMA locking_mode = exclusive }
+  db eval { SELECT count(*) FROM abc }
+} -test {
+  faultsim_test_result {0 2}
+  if {[file exists test.db-shm]} { error "Not using heap-memory mode" }
+  faultsim_integrity_check
+}
+
+do_faultsim_test walfault-13.2 -prep {
+  faultsim_restore_and_reopen
+  db eval { PRAGMA locking_mode = exclusive }
+} -body {
+  db eval { PRAGMA journal_mode = delete }
+} -test {
+  faultsim_test_result {0 delete}
+  if {[file exists test.db-shm]} { error "Not using heap-memory mode" }
+  faultsim_integrity_check
+}
+
+do_test walfault-13-pre-2 {
+  faultsim_delete_and_reopen
+  execsql {
+    BEGIN;
+      CREATE TABLE abc(a PRIMARY KEY);
+      INSERT INTO abc VALUES(randomblob(1500));
+      INSERT INTO abc VALUES(randomblob(1500));
+    COMMIT;
+  }
+  faultsim_save_and_close
+} {}
+
+do_faultsim_test walfault-13.3 -prep {
+  faultsim_restore_and_reopen
+} -body {
+  db eval { 
+    PRAGMA locking_mode = exclusive;
+    PRAGMA journal_mode = WAL;
+    INSERT INTO abc VALUES(randomblob(1500));
+  }
+} -test {
+  faultsim_test_result {0 {exclusive wal}}
+  if {[file exists test.db-shm]} { error "Not using heap-memory mode" }
+  faultsim_integrity_check
+  set nRow [db eval {SELECT count(*) FROM abc}]
+  if {!(($nRow==2 && $testrc) || $nRow==3)} { error "Bad db content" }
+}
 
 finish_test
diff --git a/test/walnoshm.test b/test/walnoshm.test
new file mode 100644 (file)
index 0000000..a2f1900
--- /dev/null
@@ -0,0 +1,146 @@
+# 2010 November 1
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.  The
+# focus of this file is testing that WAL databases may be accessed without
+# using the xShm primitives if the connection is in exclusive-mode.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix walnoshm
+ifcapable !wal {finish_test ; return }
+
+db close
+testvfs tvfsshm
+testvfs tvfs -default 1 -iversion 1 
+sqlite3 db test.db
+
+#--------------------------------------------------------------------------
+# Test that when using a version 1 VFS, a database can only be converted
+# to WAL mode after setting locking_mode=EXCLUSIVE. Also, test that if a
+# WAL database is opened using heap-memory for the WAL index, the connection
+# cannot change back to locking_mode=NORMAL while the database is still in
+# WAL mode.
+#
+do_execsql_test 1.1 {
+  CREATE TABLE t1(x, y);
+  INSERT INTO t1 VALUES(1, 2);
+}
+
+do_execsql_test 1.2 { 
+  PRAGMA journal_mode = WAL;
+  SELECT * FROM t1;
+} {delete 1 2}
+do_test 1.3 { file exists test.db-wal } {0}
+
+do_execsql_test 1.4 { 
+  PRAGMA locking_mode = exclusive;
+  PRAGMA journal_mode = WAL;
+  SELECT * FROM t1;
+} {exclusive wal 1 2}
+do_test 1.5 { file exists test.db-wal } {1}
+
+do_execsql_test 1.6 { INSERT INTO t1 VALUES(3, 4) }
+
+do_execsql_test 1.7 {
+  PRAGMA locking_mode = normal;
+} {exclusive}
+do_execsql_test 1.8 {
+  PRAGMA journal_mode = delete;
+  PRAGMA main.locking_mode;
+} {delete exclusive}
+do_execsql_test 1.9 {
+  PRAGMA locking_mode = normal;
+} {normal}
+do_execsql_test 1.10 {
+  SELECT * FROM t1;
+} {1 2 3 4}
+do_test 1.11 { file exists test.db-wal } {0}
+
+#-------------------------------------------------------------------------
+#
+# 2.1.*: Test that a connection using a version 1 VFS can open a WAL database
+#        and convert it to rollback mode if it is set to use
+#        locking_mode=exclusive.
+#
+# 2.2.*: Test that if the exclusive lock cannot be obtained while attempting
+#        the above, the operation fails and the WAL file is not opened.
+#
+do_execsql_test 2.1.1 {
+  CREATE TABLE t2(x, y);
+  INSERT INTO t2 VALUES('a', 'b');
+  INSERT INTO t2 VALUES('c', 'd');
+}
+do_execsql_test 2.1.2 {
+  PRAGMA locking_mode = exclusive;
+  PRAGMA journal_mode = WAL;
+  INSERT INTO t2 VALUES('e', 'f');
+  INSERT INTO t2 VALUES('g', 'h');
+} {exclusive wal}
+
+do_test 2.1.3 {
+  file copy -force test.db     test2.db
+  file copy -force test.db-wal test2.db-wal
+  sqlite3 db2 test2.db
+  catchsql { SELECT * FROM t2 } db2
+} {1 {unable to open database file}}
+do_test 2.1.4 {
+  catchsql { PRAGMA journal_mode = delete } db2
+} {1 {unable to open database file}}
+do_test 2.1.5 {
+  execsql { 
+    PRAGMA locking_mode = exclusive; 
+    PRAGMA journal_mode = delete;
+    SELECT * FROM t2;
+  } db2
+} {exclusive delete a b c d e f g h}
+
+do_test 2.2.1 {
+  file copy -force test.db     test2.db
+  file copy -force test.db-wal test2.db-wal
+  sqlite3 db3 test2.db -vfs tvfsshm
+  sqlite3 db2 test2.db
+  execsql { SELECT * FROM t2 } db3
+} {a b c d e f g h}
+
+do_test 2.2.2 {
+  execsql  { PRAGMA locking_mode = exclusive }  db2
+  catchsql { PRAGMA journal_mode = delete } db2
+} {1 {database is locked}}
+
+do_test 2.2.3 {
+  # This is to test that [db2] is not holding a PENDING lock (which can 
+  # happen when an attempt to obtain an EXCLUSIVE lock fails).
+  sqlite3 db4 test2.db -vfs tvfsshm
+  execsql { SELECT * FROM t2 } db4
+} {a b c d e f g h}
+
+do_test 2.2.4 {
+  catchsql { SELECT * FROM t2 } db2
+} {1 {database is locked}}
+
+do_test 2.2.5 {
+  db4 close
+  sqlite3 db4 test2.db -vfs tvfsshm
+  execsql { SELECT * FROM t2 } db4
+} {a b c d e f g h}
+
+do_test 2.2.6 {
+  db3 close
+  db4 close
+  execsql { SELECT * FROM t2 } db2
+} {a b c d e f g h}
+
+db2 close
+
+
+finish_test
+