]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Avoid creating any extra files ("<target>-vacuum") when running an RBU vacuum. Ensure...
authordan <dan@noemail.net>
Sat, 16 Apr 2016 17:53:14 +0000 (17:53 +0000)
committerdan <dan@noemail.net>
Sat, 16 Apr 2016 17:53:14 +0000 (17:53 +0000)
FossilOrigin-Name: dc19aacc7e99213edca9bb57b5c11a8a1ac99113

ext/rbu/sqlite3rbu.c
manifest
manifest.uuid

index e71690769bf5d3757e1583049af07533a7060da8..ff01f307257d735ef9df04d8e03b277c5b7d46a5 100644 (file)
@@ -2323,6 +2323,7 @@ static RbuState *rbuLoadState(sqlite3rbu *p){
 static void rbuOpenDatabase(sqlite3rbu *p){
   assert( p->rc==SQLITE_OK );
   assert( p->dbMain==0 && p->dbRbu==0 );
+  assert( rbuIsVacuum(p) || p->zTarget!=0 );
 
   /* Open the RBU database */
   p->dbRbu = rbuOpenDbhandle(p, p->zRbu);
@@ -2355,16 +2356,21 @@ static void rbuOpenDatabase(sqlite3rbu *p){
 
   p->eStage = 0;
   if( p->dbMain==0 ){
-    if( p->zTarget ){
+    if( !rbuIsVacuum(p) ){
       p->dbMain = rbuOpenDbhandle(p, p->zTarget);
     }else{
-      char *zTarget = sqlite3_mprintf("%s-vacuum", p->zRbu);
+      char *zTarget = sqlite3_mprintf("file:%s-vacuum?rbu_memory=1", p->zRbu);
       if( zTarget==0 ){
         p->rc = SQLITE_NOMEM;
         return;
       }
       p->dbMain = rbuOpenDbhandle(p, zTarget);
       sqlite3_free(zTarget);
+      if( p->rc==SQLITE_OK ){
+        p->rc = sqlite3_exec(p->dbMain, 
+            "PRAGMA journal_mode=off; BEGIN EXCLUSIVE; COMMIT;", 0, 0, 0
+        );
+      }
     }
   }
 
@@ -2641,14 +2647,15 @@ static LPWSTR rbuWinUtf8ToUnicode(const char *zFilename){
 */
 static void rbuMoveOalFile(sqlite3rbu *p){
   const char *zBase = sqlite3_db_filename(p->dbMain, "main");
-  char *zOal = sqlite3_mprintf("%s-oal", zBase);
+  const char *zMove = zBase;
+  char *zOal;
   char *zWal;
 
   if( rbuIsVacuum(p) ){
-    zWal = sqlite3_mprintf("%s-wal", sqlite3_db_filename(p->dbRbu, "main"));
-  }else{
-    zWal = sqlite3_mprintf("%s-wal", zBase);
+    zMove = sqlite3_db_filename(p->dbRbu, "main");
   }
+  zOal = sqlite3_mprintf("%s-oal", zMove);
+  zWal = sqlite3_mprintf("%s-wal", zMove);
 
   assert( p->eStage==RBU_STAGE_MOVE );
   assert( p->rc==SQLITE_OK && p->zErrmsg==0 );
@@ -2928,13 +2935,18 @@ static int rbuStep(sqlite3rbu *p){
 
 /*
 ** Increment the schema cookie of the main database opened by p->dbMain.
+**
+** Or, if this is an RBU vacuum, set the schema cookie of the main db
+** opened by p->dbMain to one more than the schema cookie of the main
+** db opened by p->dbRbu.
 */
 static void rbuIncrSchemaCookie(sqlite3rbu *p){
   if( p->rc==SQLITE_OK ){
+    sqlite3 *dbread = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain);
     int iCookie = 1000000;
     sqlite3_stmt *pStmt;
 
-    p->rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg, 
+    p->rc = prepareAndCollectError(dbread, &pStmt, &p->zErrmsg, 
         "PRAGMA schema_version"
     );
     if( p->rc==SQLITE_OK ){
@@ -3408,6 +3420,7 @@ static sqlite3rbu *openRbuHandle(
     }
 
     if( p->rc==SQLITE_OK
+     && !rbuIsVacuum(p)
      && (p->eStage==RBU_STAGE_OAL || p->eStage==RBU_STAGE_MOVE)
      && pState->eStage!=0 && p->pTargetFd->iCookie!=pState->iCookie
     ){   
@@ -3803,34 +3816,6 @@ static int rbuVfsRead(
       memset(zBuf, 0, iAmt);
     }else{
       rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
-      /* If this is being called to read the first page of the target 
-      ** database as part of an rbu vacuum operation, synthesize the 
-      ** contents of the first page if it does not yet exist. Otherwise,
-      ** SQLite will not check for a *-wal file.  */
-      if( p->pRbu && rbuIsVacuum(p->pRbu) 
-       && rc==SQLITE_IOERR_SHORT_READ && iOfst==0
-       && (p->openFlags & SQLITE_OPEN_MAIN_DB)
-      ){
-        sqlite3_file *pFd = 0;
-        rc = sqlite3_file_control(
-            p->pRbu->dbRbu, "main", SQLITE_FCNTL_FILE_POINTER, (void*)&pFd
-        );
-        if( rc==SQLITE_OK ){
-          rc = pFd->pMethods->xRead(pFd, zBuf, iAmt, iOfst);
-        }
-        if( rc==SQLITE_OK ){
-          rbuPutU32(&zBuf[52], 0);          /* largest root page number */
-          rbuPutU32(&zBuf[36], 0);          /* number of free pages */
-          rbuPutU32(&zBuf[32], 0);          /* first page on free list trunk */
-          rbuPutU32(&zBuf[28], 1);          /* size of db file in pages */
-
-          if( iAmt>100 ){
-            assert( iAmt>=101 );
-            memset(&zBuf[101], 0, iAmt-101);
-            rbuPutU16(&zBuf[105], iAmt & 0xFFFF);
-          }
-        }
-      }
     }
     if( rc==SQLITE_OK && iOfst==0 && (p->openFlags & SQLITE_OPEN_MAIN_DB) ){
       /* These look like magic numbers. But they are stable, as they are part
@@ -3838,6 +3823,13 @@ static int rbuVfsRead(
       u8 *pBuf = (u8*)zBuf;
       p->iCookie = rbuGetU32(&pBuf[24]);
       p->iWriteVer = pBuf[19];
+      if( pRbu && rbuIsVacuum(p->pRbu) ){
+        rbu_file *pRbuFd = 0;
+        sqlite3_file_control(pRbu->dbRbu, "main", 
+            SQLITE_FCNTL_FILE_POINTER, (void*)&pRbuFd
+        );
+        rbuPutU32(&pBuf[24], pRbuFd->iCookie+1);
+      }
     }
   }
   return rc;
@@ -3905,20 +3897,7 @@ static int rbuVfsSync(sqlite3_file *pFile, int flags){
 */
 static int rbuVfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
   rbu_file *p = (rbu_file *)pFile;
-  int rc;
-  rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
-
-  /* If this is an RBU vacuum operation and this is the target database,
-  ** pretend that it has at least one page. Otherwise, SQLite will not
-  ** check for the existance of a *-wal file. rbuVfsRead() contains 
-  ** similar logic.  */
-  if( rc==SQLITE_OK && *pSize==0 
-   && p->pRbu && rbuIsVacuum(p->pRbu) 
-   && (p->openFlags & SQLITE_OPEN_MAIN_DB)
-  ){
-    *pSize = 1024;
-  }
-  return rc;
+  return p->pReal->pMethods->xFileSize(p->pReal, pSize);
 }
 
 /*
@@ -4156,6 +4135,33 @@ static rbu_file *rbuFindMaindb(rbu_vfs *pRbuVfs, const char *zWal){
   return pDb;
 }
 
+/* 
+** A main database named zName has just been opened. The following 
+** function returns a pointer to a buffer owned by SQLite that contains
+** the name of the *-wal file this db connection will use. SQLite
+** happens to pass a pointer to this buffer when using xAccess()
+** or xOpen() to operate on the *-wal file.  
+*/
+static const char *rbuMainToWal(const char *zName, int flags){
+  int n = (int)strlen(zName);
+  const char *z = &zName[n];
+  if( flags & SQLITE_OPEN_URI ){
+    int odd = 0;
+    while( 1 ){
+      if( z[0]==0 ){
+        odd = 1 - odd;
+        if( odd && z[1]==0 ) break;
+      }
+      z++;
+    }
+    z += 2;
+  }else{
+    while( *z==0 ) z++;
+  }
+  z += (n + 8 + 1);
+  return z;
+}
+
 /*
 ** Open an rbu file handle.
 */
@@ -4191,6 +4197,7 @@ static int rbuVfsOpen(
   rbu_file *pFd = (rbu_file *)pFile;
   int rc = SQLITE_OK;
   const char *zOpen = zName;
+  int oflags = flags;
 
   memset(pFd, 0, sizeof(rbu_file));
   pFd->pReal = (sqlite3_file*)&pFd[1];
@@ -4203,23 +4210,7 @@ static int rbuVfsOpen(
       ** the name of the *-wal file this db connection will use. SQLite
       ** happens to pass a pointer to this buffer when using xAccess()
       ** or xOpen() to operate on the *-wal file.  */
-      int n = (int)strlen(zName);
-      const char *z = &zName[n];
-      if( flags & SQLITE_OPEN_URI ){
-        int odd = 0;
-        while( 1 ){
-          if( z[0]==0 ){
-            odd = 1 - odd;
-            if( odd && z[1]==0 ) break;
-          }
-          z++;
-        }
-        z += 2;
-      }else{
-        while( *z==0 ) z++;
-      }
-      z += (n + 8 + 1);
-      pFd->zWal = z;
+      pFd->zWal = rbuMainToWal(zName, flags);
     }
     else if( flags & SQLITE_OPEN_WAL ){
       rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName);
@@ -4229,10 +4220,17 @@ static int rbuVfsOpen(
           ** code ensures that the string passed to xOpen() is terminated by a
           ** pair of '\0' bytes in case the VFS attempts to extract a URI 
           ** parameter from it.  */
-          size_t nCopy = strlen(zName);
-          char *zCopy = sqlite3_malloc64(nCopy+2);
+          const char *zBase = zName;
+          size_t nCopy;
+          char *zCopy;
+          if( rbuIsVacuum(pDb->pRbu) ){
+            zBase = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
+            zBase = rbuMainToWal(zBase, SQLITE_OPEN_URI);
+          }
+          nCopy = strlen(zBase);
+          zCopy = sqlite3_malloc64(nCopy+2);
           if( zCopy ){
-            memcpy(zCopy, zName, nCopy);
+            memcpy(zCopy, zBase, nCopy);
             zCopy[nCopy-3] = 'o';
             zCopy[nCopy] = '\0';
             zCopy[nCopy+1] = '\0';
@@ -4247,8 +4245,17 @@ static int rbuVfsOpen(
     }
   }
 
+  if( oflags & SQLITE_OPEN_MAIN_DB 
+   && sqlite3_uri_boolean(zName, "rbu_memory", 0) 
+  ){
+    assert( oflags & SQLITE_OPEN_MAIN_DB );
+    oflags =  SQLITE_OPEN_TEMP_DB | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
+              SQLITE_OPEN_EXCLUSIVE | SQLITE_OPEN_DELETEONCLOSE;
+    zOpen = 0;
+  }
+
   if( rc==SQLITE_OK ){
-    rc = pRealVfs->xOpen(pRealVfs, zOpen, pFd->pReal, flags, pOutFlags);
+    rc = pRealVfs->xOpen(pRealVfs, zOpen, pFd->pReal, oflags, pOutFlags);
   }
   if( pFd->pReal->pMethods ){
     /* The xOpen() operation has succeeded. Set the sqlite3_file.pMethods
index eeb8cf07efd1d910117e86296d8bd483910e0825..0e404f7022f59f925b8870fa73b51979be86e6b4 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\scouple\sof\sassert()\sstatements\sthat\swere\sfailing\swith\sOOM\serror\stests.
-D 2016-04-16T15:03:20.537
+C Avoid\screating\sany\sextra\sfiles\s("<target>-vacuum")\swhen\srunning\san\sRBU\svacuum.\sEnsure\sthat\sthe\sOAL\sfile\screated\sis\s"<target>-oal",\snot\s"<target>-vacuum-oal".
+D 2016-04-16T17:53:14.824
 F Makefile.in eba680121821b8a60940a81454316f47a341487a
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc 71b8b16cf9393f68e2e2035486ca104872558836
@@ -247,7 +247,7 @@ F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
 F ext/rbu/rbuprogress.test 2023a7df2c523e3df1cb532eff811cda385a789a
 F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
 F ext/rbu/rbuvacuum.test 75b4231f85622859e814c7f028afad0303f72f60
-F ext/rbu/sqlite3rbu.c 79b8be4a0c8276b2b2b24c88edf3944216ccd35b
+F ext/rbu/sqlite3rbu.c 471b4055618473612e9ae7d7e4f1922559b59aaf
 F ext/rbu/sqlite3rbu.h 1342ab6121e715b8da59ec35c5b5c16060be7a6b
 F ext/rbu/test_rbu.c 430b8b9520c233505371d564d3561e0b554355f4
 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
@@ -1483,7 +1483,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 0216b48f28042ad86711e00802c2da8ce9be3044
-R 0603f47373db6aeb2d2c22dfe403e0e2
+P 8eb3d7d8360530f364bbbebac53e1f0e6753d924
+R 4d03a7f5bef5f70852d283bb46ff80e2
 U dan
-Z 6e5ab10ab6efe323abcf341183f13408
+Z 0a7d529e6f2d77bae387935d2996f1da
index 773e6bf755a46b35fb701b7d69011e66f13f71a5..56172c7c761734dc15ce3a2d5958372df2f029b7 100644 (file)
@@ -1 +1 @@
-8eb3d7d8360530f364bbbebac53e1f0e6753d924
\ No newline at end of file
+dc19aacc7e99213edca9bb57b5c11a8a1ac99113
\ No newline at end of file