]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Only open a read-only connection to shared-memory if the "readonly_shm=1" option...
authordan <dan@noemail.net>
Wed, 11 May 2011 14:57:33 +0000 (14:57 +0000)
committerdan <dan@noemail.net>
Wed, 11 May 2011 14:57:33 +0000 (14:57 +0000)
FossilOrigin-Name: 671ba5fc59f7a958e5a4138d2425b1173a442ad7

manifest
manifest.uuid
src/attach.c
src/btree.h
src/main.c
src/pager.c
src/pager.h
src/sqliteInt.h
src/wal.c
src/wal.h
test/walro.test

index 50889411e104d996a9844b7ed2227d35f2707858..3d33b8171b370bc21403f5043b9fa0c6134ed676 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sexperimental\ssupport\sfor\sread-only\sconnections\sto\sWAL\sdatabases.
-D 2011-05-10T17:31:29.338
+C Only\sopen\sa\sread-only\sconnection\sto\sshared-memory\sif\sthe\s"readonly_shm=1"\soption\sis\sspecified\sas\spart\sof\sthe\sdatabase\sfile\sURI\s(and\sif\sa\sread-write\sconnection\sfails).
+D 2011-05-11T14:57:33.029
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 7a4d9524721d40ef9ee26f93f9bd6a51dba106f2
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -117,13 +117,13 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
 F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
 F src/alter.c 280f5c04b11b492703a342222b3de0a999445280
 F src/analyze.c a425d62e8fa9ebcb4359ab84ff0c62c6563d2e2a
-F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f
+F src/attach.c a87bfb77a720f7aa02791434aacfd9bc8feb50cc
 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
 F src/backup.c 986c15232757f2873dff35ee3b35cbf935fc573c
 F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
 F src/btree.c 26f8a9d6169413c5682b89b5397d20437b653154
-F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
+F src/btree.h d796dc4030b3cce7f5a0cc4f2f986d2befa6b8ac
 F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
 F src/build.c 0132bc6631fa617a1d28ef805921f6dbac18a514
 F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
@@ -144,7 +144,7 @@ F src/journal.c 552839e54d1bf76fb8f7abe51868b66acacf6a0e
 F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
 F src/lempar.c 7f026423f4d71d989e719a743f98a1cbd4e6d99e
 F src/loadext.c 3ae0d52da013a6326310655be6473fd472347b85
-F src/main.c f00cee5a27f5df5ed536e7043cb451b3c85ce65c
+F src/main.c 167fb3285720917e4d1a5c633f558c81b751eca3
 F src/malloc.c 591aedb20ae40813f1045f2ef253438a334775d9
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c 00bd8265c81abb665c48fea1e0c234eb3b922206
@@ -165,8 +165,8 @@ F src/os_common.h a8f95b81eca8a1ab8593d23e94f8a35f35d4078f
 F src/os_os2.c 4a75888ba3dfc820ad5e8177025972d74d7f2440
 F src/os_unix.c 03630dd062c3d1fb9f25e2a227048b709c5babff
 F src/os_win.c ff0e14615a5086fa5ba6926e4ec0dc9cfb5a1a84
-F src/pager.c 24b689bc3639d534f5fb292d2c68038b1e720527
-F src/pager.h 3f8c783de1d4706b40b1ac15b64f5f896bcc78d1
+F src/pager.c 4056376f83f85cea9922a11161087c529e39f7dc
+F src/pager.h 34c6b029446f06f40847746d22faac0d354dd909
 F src/parse.y 12b7ebd61ea54f0e1b1083ff69cc2c8ce9353d58
 F src/pcache.c 09d38c44ab275db581f7a2f6ff8b9bc7f8c0faaa
 F src/pcache.h c683390d50f856d4cd8e24342ae62027d1bb6050
@@ -181,7 +181,7 @@ F src/select.c d9d440809025a58547e39f4f268c2a296bfb56ff
 F src/shell.c 72e7e176bf46d5c6518d15ac4ad6847c4bb5df79
 F src/sqlite.h.in e7bbcb330ced6b5e25c9db8089c2c77aaefadf7d
 F src/sqlite3ext.h c90bd5507099f62043832d73f6425d8d5c5da754
-F src/sqliteInt.h b34bd64a7ade4808fcc301e0bb67ef5051ea49c6
+F src/sqliteInt.h 798fb09648cefc159ac9b3ce5e00f5ada1377ed1
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -245,8 +245,8 @@ F src/vdbeblob.c c3ccb7c8732858c680f442932e66ad06bb036562
 F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
 F src/vdbetrace.c 5d0dc3d5fd54878cc8d6d28eb41deb8d5885b114
 F src/vtab.c 48dcef8bc757c2e7b488f68b5ddebb1650da2450
-F src/wal.c 2574b16ee88b1934e97f63ae38025dc48ef45327
-F src/wal.h 7a5fbb00114b7f2cd40c7e1003d4c41ce9d26840
+F src/wal.c adc6c83b650e67e32159e11d557a46594834853e
+F src/wal.h c1e05cdf3d42ed7c9263739ca8f5cdd8761e7de3
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
 F src/where.c 55403ce19c506be6a321c7f129aff693d6103db5
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -883,7 +883,7 @@ F test/walfault.test 58fce626359c9376fe35101b5c0f2df8040aa839
 F test/walhook.test ed00a40ba7255da22d6b66433ab61fab16a63483
 F test/walmode.test 22ddccd073c817ac9ead62b88ac446e8dedc7d2c
 F test/walnoshm.test a074428046408f4eb5c6a00e09df8cc97ff93317
-F test/walro.test 0fb4c79a9dfa1d14f46859e469d3b4844480cd9d
+F test/walro.test c204f62fb6a77839bc6ce5adbdcc9df2aac877ca
 F test/walshared.test 6dda2293880c300baf5d791c307f653094585761
 F test/walslow.test d21625e2e99e11c032ce949e8a94661576548933
 F test/walthread.test a25a393c068a2b42b44333fa3fdaae9072f1617c
@@ -936,10 +936,7 @@ F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P d9bc1c7fe0ca5f6973a85827330958f4d09f8171
-R 864e9c4ee7a6cf5f8240415fb38d1af8
-T *branch * wal-readonly
-T *sym-wal-readonly *
-T -sym-trunk *
+P bb59f9862da45d25fb51d7821130854828c91c98
+R 04ad06f1f1eb20213db6e513d8bb75aa
 U dan
-Z 321776a9f8d852e48652ad186c3a479b
+Z 112f0ce43ba9dc957c26d5146ee2fe50
index e39ce5418fb24cf74a3f1f24fbb885e946156e42..e0664d4e86ef8dc6f20ed5762ac22a9ce32c790f 100644 (file)
@@ -1 +1 @@
-bb59f9862da45d25fb51d7821130854828c91c98
\ No newline at end of file
+671ba5fc59f7a958e5a4138d2425b1173a442ad7
\ No newline at end of file
index 18f8823b314f0b5b632d7139df6c1207259b2630..4b8ea7791773119b48f00bbd5192a558215b1150 100644 (file)
@@ -76,6 +76,8 @@ static void attachFunc(
   Db *aNew;
   char *zErrDyn = 0;
   sqlite3_vfs *pVfs;
+  const char *zVfs = db->pVfs->zName;       /* Name of default (main) VFS */
+  int btflags = 0;
 
   UNUSED_PARAMETER(NotUsed);
 
@@ -129,7 +131,7 @@ static void attachFunc(
   ** or may not be initialised.
   */
   flags = db->openFlags;
-  rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
+  rc = sqlite3ParseUri(zVfs, zFile, &flags, &btflags, &pVfs, &zPath, &zErr);
   if( rc!=SQLITE_OK ){
     if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
     sqlite3_result_error(context, zErr, -1);
@@ -138,7 +140,7 @@ static void attachFunc(
   }
   assert( pVfs );
   flags |= SQLITE_OPEN_MAIN_DB;
-  rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
+  rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, btflags, flags);
   sqlite3_free( zPath );
   db->nDb++;
   if( rc==SQLITE_CONSTRAINT ){
index 9e3a73b3b64d98cafdd9e7afbfa2d7b0210e0ef6..c5abc9c865e283aded4d348012bb992e29839c02 100644 (file)
@@ -61,6 +61,7 @@ int sqlite3BtreeOpen(
 #define BTREE_MEMORY        4  /* This is an in-memory DB */
 #define BTREE_SINGLE        8  /* The file contains at most 1 b-tree */
 #define BTREE_UNORDERED    16  /* Use of a hash implementation is OK */
+#define BTREE_READONLYSHM  32  /* Read-only SHM access is acceptable */
 
 int sqlite3BtreeClose(Btree*);
 int sqlite3BtreeSetCacheSize(Btree*,int);
index 5b46f4b7369df01b67d468d05fc8345b2ab2820e..e986f83225c18cdf98a8d93bbfec67f5c4dcded3 100644 (file)
@@ -1818,6 +1818,7 @@ int sqlite3ParseUri(
   const char *zDefaultVfs,        /* VFS to use if no "vfs=xxx" query option */
   const char *zUri,               /* Nul-terminated URI to parse */
   unsigned int *pFlags,           /* IN/OUT: SQLITE_OPEN_XXX flags */
+  int *pBtflags,                  /* IN/OUT: BTREE_XXX flags */
   sqlite3_vfs **ppVfs,            /* OUT: VFS to use */ 
   char **pzFile,                  /* OUT: Filename component of URI */
   char **pzErrMsg                 /* OUT: Error message (if rc!=SQLITE_OK) */
@@ -1933,6 +1934,12 @@ int sqlite3ParseUri(
 
       if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){
         zVfs = zVal;
+      }else if( nOpt==12 && memcmp("readonly_shm", zOpt, 12)==0 ){
+        if( sqlite3Atoi(zVal) ){
+          *pBtflags |= BTREE_READONLYSHM;
+        }else{
+          *pBtflags &= ~BTREE_READONLYSHM;
+        }
       }else{
         struct OpenMode {
           const char *z;
@@ -2036,6 +2043,7 @@ static int openDatabase(
   int isThreadsafe;               /* True for threadsafe connections */
   char *zOpen = 0;                /* Filename argument to pass to BtreeOpen() */
   char *zErrMsg = 0;              /* Error message from sqlite3ParseUri() */
+  int btflags = 0;                /* Mask of BTREE_XXX flags */
 
   *ppDb = 0;
 #ifndef SQLITE_OMIT_AUTOINIT
@@ -2163,7 +2171,8 @@ static int openDatabase(
                   nocaseCollatingFunc, 0);
 
   /* Parse the filename/URI argument. */
-  rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
+  rc = sqlite3ParseUri(
+      zVfs, zFilename, &flags, &btflags, &db->pVfs, &zOpen, &zErrMsg);
   if( rc!=SQLITE_OK ){
     if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
     sqlite3Error(db, rc, zErrMsg ? "%s" : 0, zErrMsg);
@@ -2173,7 +2182,7 @@ static int openDatabase(
 
   /* Open the backend database driver */
   db->openFlags = flags;
-  rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, 0,
+  rc = sqlite3BtreeOpen(db->pVfs, zOpen, db, &db->aDb[0].pBt, btflags,
                         flags | SQLITE_OPEN_MAIN_DB);
   if( rc!=SQLITE_OK ){
     if( rc==SQLITE_IOERR_NOMEM ){
index 8ad6984f8aad55830926c217c9679ca89fd5d089..56dae0604054372e5ebad3ad9c2c4ef90fffa602 100644 (file)
@@ -620,6 +620,7 @@ struct Pager {
   u8 tempFile;                /* zFilename is a temporary file */
   u8 readOnly;                /* True for a read-only database */
   u8 memDb;                   /* True to inhibit all file I/O */
+  u8 readOnlyShm;             /* True if read-only shm access is Ok */
 
   /**************************************************************************
   ** The following block contains those class members that change during
@@ -3017,6 +3018,7 @@ static int pagerWalFrames(
 static int pagerBeginReadTransaction(Pager *pPager){
   int rc;                         /* Return code */
   int changed = 0;                /* True if cache must be reset */
+  Wal *pWal = pPager->pWal;
 
   assert( pagerUseWal(pPager) );
   assert( pPager->eState==PAGER_OPEN || pPager->eState==PAGER_READER );
@@ -3026,9 +3028,9 @@ static int pagerBeginReadTransaction(Pager *pPager){
   ** are in locking_mode=NORMAL and EndRead() was previously called,
   ** the duplicate call is harmless.
   */
-  sqlite3WalEndReadTransaction(pPager->pWal);
+  sqlite3WalEndReadTransaction(pWal);
 
-  rc = sqlite3WalBeginReadTransaction(pPager->pWal, &changed);
+  rc = sqlite3WalBeginReadTransaction(pWal, pPager->readOnlyShm, &changed);
   if( rc!=SQLITE_OK || changed ){
     pager_reset(pPager);
   }
@@ -4414,6 +4416,7 @@ int sqlite3PagerOpen(
   }
   pPager->pVfs = pVfs;
   pPager->vfsFlags = vfsFlags;
+  pPager->readOnlyShm = (flags & PAGER_READONLYSHM)!=0;
 
   /* Open the pager file.
   */
index eab7ddaf80bb44c3a89c1b7123a8691be19b64fb..c6cb8bcb557ee0efa1848a6816e2b3d1908010e4 100644 (file)
@@ -60,6 +60,7 @@ typedef struct PgHdr DbPage;
 #define PAGER_OMIT_JOURNAL  0x0001    /* Do not use a rollback journal */
 #define PAGER_NO_READLOCK   0x0002    /* Omit readlocks on readonly files */
 #define PAGER_MEMORY        0x0004    /* In-memory database */
+#define PAGER_READONLYSHM   0x0020    /* Read-only SHM access is acceptable */
 
 /*
 ** Valid values for the second argument to sqlite3PagerLockingMode().
index 4a3e45d7c04c2a0d0f58c9764cd534e00cf9300c..cedd780779370dd6457371709871f9f495ff78c7 100644 (file)
@@ -2673,7 +2673,7 @@ void sqlite3AddColumnType(Parse*,Token*);
 void sqlite3AddDefaultValue(Parse*,ExprSpan*);
 void sqlite3AddCollateType(Parse*, Token*);
 void sqlite3EndTable(Parse*,Token*,Token*,Select*);
-int sqlite3ParseUri(const char*,const char*,unsigned int*,
+int sqlite3ParseUri(const char*,const char*,unsigned int*,int*,
                     sqlite3_vfs**,char**,char **);
 
 Bitvec *sqlite3BitvecCreate(u32);
index 707fe12976c3fbdab4695d4cf1e0b6044beb6acf..3d6baf21c8524e7561d492d3dc4ae1cea7a4e9a9 100644 (file)
--- a/src/wal.c
+++ b/src/wal.c
@@ -529,7 +529,8 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
       rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, 
           pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
       );
-      if( rc==SQLITE_CANTOPEN && iPage==0 ){
+      if( rc==SQLITE_CANTOPEN && pWal->readOnlyShm>1 ){
+        assert( iPage==0 );
         sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_READONLY_SHM, (void*)1);
         rc = sqlite3OsShmMap(pWal->pDbFd, iPage, WALINDEX_PGSZ, 
             pWal->writeLock, (void volatile **)&pWal->apWiData[iPage]
@@ -541,9 +542,10 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
       }
     }
   }
-
   *ppPage = pWal->apWiData[iPage];
+
   assert( iPage==0 || *ppPage || rc!=SQLITE_OK );
+  if( pWal->readOnlyShm>1 ) pWal->readOnlyShm = 0;
   return rc;
 }
 
@@ -1909,6 +1911,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
     return rc;
   };
   assert( page0 || pWal->writeLock==0 );
+  assert( pWal->readOnlyShm==0 || pWal->readOnlyShm==1 );
 
   /* If the first page of the wal-index has been mapped, try to read the
   ** wal-index header immediately, without holding any lock. This usually
@@ -2200,13 +2203,18 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
 ** Pager layer will use this to know that is cache is stale and
 ** needs to be flushed.
 */
-int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
+int sqlite3WalBeginReadTransaction(Wal *pWal, int readOnlyShm, int *pChanged){
   int rc;                         /* Return code */
   int cnt = 0;                    /* Number of TryBeginRead attempts */
 
+  if( pWal->nWiData==0 || pWal->apWiData[0]==0 ){
+    assert( readOnlyShm==0 || readOnlyShm==1 );
+    pWal->readOnlyShm = readOnlyShm*2;
+  }
   do{
     rc = walTryBeginRead(pWal, pChanged, 0, ++cnt);
   }while( rc==WAL_RETRY );
+  assert( rc || pWal->readOnlyShm==0 || (readOnlyShm && pWal->readOnlyShm==1) );
   testcase( (rc&0xff)==SQLITE_BUSY );
   testcase( (rc&0xff)==SQLITE_IOERR );
   testcase( rc==SQLITE_PROTOCOL );
index 2039c701cf29bae49a7e984c4b1d59aa76683040..aca5a56a569cc2f4d118af8fd087ac05df7f0855 100644 (file)
--- a/src/wal.h
+++ b/src/wal.h
@@ -22,7 +22,7 @@
 #ifdef SQLITE_OMIT_WAL
 # define sqlite3WalOpen(x,y,z)                   0
 # define sqlite3WalClose(w,x,y,z)                0
-# define sqlite3WalBeginReadTransaction(y,z)     0
+# define sqlite3WalBeginReadTransaction(x,y,z)   0
 # define sqlite3WalEndReadTransaction(z)
 # define sqlite3WalRead(v,w,x,y,z)               0
 # define sqlite3WalDbsize(y)                     0
@@ -56,7 +56,7 @@ int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
 ** write to or checkpoint the WAL.  sqlite3WalCloseSnapshot() closes the
 ** transaction and releases the lock.
 */
-int sqlite3WalBeginReadTransaction(Wal *pWal, int *);
+int sqlite3WalBeginReadTransaction(Wal *pWal, int, int *);
 void sqlite3WalEndReadTransaction(Wal *pWal);
 
 /* Read a page from the write-ahead log, if it is present. */
index b558622cad34f413d99623c3235f9b6346c9f417..1025f00e33a3727285e202caff89e9ec73af1d90 100644 (file)
@@ -35,6 +35,13 @@ do_multiclient_test tn {
   forcedelete test.db
   forcedelete walro
 
+  foreach c {code1 code2 code3} {
+    $c {
+      sqlite3_shutdown
+      sqlite3_config_uri 1
+    }
+  }
+
   file mkdir walro
 
   do_test 1.1.1 {
@@ -49,7 +56,7 @@ do_multiclient_test tn {
 
   do_test 1.1.2 {
     file attributes test.db-shm -permissions r--r--r--
-    code1 { sqlite3 db test.db }
+    code1 { sqlite3 db file:test.db?readonly_shm=1 }
   } {}
 
   do_test 1.1.3 { sql1 "SELECT * FROM t1" }                {a b}
@@ -84,7 +91,7 @@ do_multiclient_test tn {
     list [file exists test.db-wal] [file exists test.db-shm]
   } {1 1}
   do_test 1.2.2 {
-    code1 { sqlite3 db test.db }
+    code1 { sqlite3 db file:test.db?readonly_shm=1 }
     sql1 { SELECT * FROM t1 }
   } {a b c d e f g h i j}
 
@@ -93,7 +100,7 @@ do_multiclient_test tn {
     file attributes test.db-shm -permissions rw-r--r--
     hexio_write test.db-shm 0 01020304 
     file attributes test.db-shm -permissions r--r--r--
-    code1 { sqlite3 db test.db }
+    code1 { sqlite3 db file:test.db?readonly_shm=1 }
     csql1 { SELECT * FROM t1 }
   } {1 {attempt to write a readonly database}}
   do_test 1.2.4 {