]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
When deleting a file with the multiplexor VFS, also delete any overflow files that...
authordan <dan@noemail.net>
Thu, 15 Dec 2011 17:00:10 +0000 (17:00 +0000)
committerdan <dan@noemail.net>
Thu, 15 Dec 2011 17:00:10 +0000 (17:00 +0000)
FossilOrigin-Name: 3af1feaa35d3fb2e7be550cd32a727001b874938

manifest
manifest.uuid
src/test_multiplex.c

index 21cbee27f3db4b45d2c695c8b9e585a6c7ee1ca5..aec2b275213b90b94c08a4876bee1b36ec373245 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Make\ssure\sthe\schunksize\sin\stest_multiplex\sdoes\snot\scause\sthe\spending\sbyte\nto\sfall\snear\sthe\send\sof\sa\schunk.\s\sAdjust\sthe\schunksize\supward\sas\snecessary\nto\sprevent\sthis.
-D 2011-12-15T13:29:12.575
+C When\sdeleting\sa\sfile\swith\sthe\smultiplexor\sVFS,\salso\sdelete\sany\soverflow\sfiles\sthat\sexist.
+D 2011-12-15T17:00:10.854
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 5b4a3e12a850b021547e43daf886b25133b44c07
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -214,7 +214,7 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
 F src/test_journal.c 03313c693cca72959dcaaf79f8d76f21c01e19ff
 F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
 F src/test_malloc.c 8d416f29ad8573f32601f6056c9d2b17472e9ad5
-F src/test_multiplex.c 7b65eea8b390dd223bd6e0ba9d7879389bd075c0
+F src/test_multiplex.c c87d27283e2f578c17a8db7a8cac095f576f4323
 F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d
 F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
 F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
@@ -978,7 +978,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
-P 2d50f78188e3297e8cefdf73cff51fa0a3b36e65
-R db6d46332c6333123f8fa60ccb204a1d
-U drh
-Z f65d5d73aa828ce8ac2cca0eb8289aa5
+P e05f8a2998f4f4cbdb65702baa65893c538b3d38
+R 45b2cf463e6285a0d96697332c4d9aa9
+U dan
+Z 16b7798bc9bd7dfe8e0e630d52e6558b
index ce1d054b8f12a17e1683c2c5df36440977e33c9e..e4ed76872dc2e38f2c760df9093e9342e2b749e5 100644 (file)
@@ -1 +1 @@
-e05f8a2998f4f4cbdb65702baa65893c538b3d38
\ No newline at end of file
+3af1feaa35d3fb2e7be550cd32a727001b874938
\ No newline at end of file
index 12e420fb5da75d670720f45263642d9d2f4f9894..d844604ab5c6687ca15c76e5a3e8d92bd889add2 100644 (file)
@@ -216,6 +216,39 @@ static int multiplexStrlen30(const char *z){
   return 0x3fffffff & (int)(z2 - z);
 }
 
+/*
+** Generate the file-name for chunk iChunk of the group with base name
+** zBase. The file-name is written to buffer zOut before returning. Buffer
+** zOut must be allocated by the caller so that it is at least (nBase+4)
+** bytes in size, where nBase is the length of zBase, not including the
+** nul-terminator.
+*/
+static void multiplexFilename(
+  const char *zBase,              /* Filename for chunk 0 */
+  int nBase,                      /* Size of zBase in bytes (without \0) */
+  int flags,                      /* Flags used to open file */
+  int iChunk,                     /* Chunk to generate filename for */
+  char *zOut                      /* Buffer to write generated name to */
+){
+  memcpy(zOut, zBase, nBase+1);
+  if( iChunk!=0 && iChunk!=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){
+    int n = nBase;
+#ifdef SQLITE_ENABLE_8_3_NAMES
+    int i;
+    for(i=n-1; i>0 && i>=n-4 && zOut[i]!='.'; i--){}
+    if( i>=n-4 ) n = i+1;
+    if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
+      /* The extensions on overflow files for main databases are 001, 002,
+       ** 003 and so forth.  To avoid name collisions, add 400 to the 
+       ** extensions of journal files so that they are 401, 402, 403, ....
+       */
+      iChunk += SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET;
+    }
+#endif
+    sqlite3_snprintf(4,&zOut[n],"%03d",iChunk);
+  }
+}
+
 /* Compute the filename for the iChunk-th chunk
 */
 static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
@@ -236,22 +269,7 @@ static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
     if( z==0 ){
       return SQLITE_NOMEM;
     }
-    memcpy(z, pGroup->zName, n+1);
-    if( iChunk>0 ){
-#ifdef SQLITE_ENABLE_8_3_NAMES
-      int i;
-      for(i=n-1; i>0 && i>=n-4 && z[i]!='.'; i--){}
-      if( i>=n-4 ) n = i+1;
-      if( pGroup->flags & (SQLITE_OPEN_MAIN_JOURNAL|SQLITE_OPEN_TEMP_JOURNAL) ){
-        /* The extensions on overflow files for main databases are 001, 002,
-        ** 003 and so forth.  To avoid name collisions, add 400 to the 
-        ** extensions of journal files so that they are 401, 402, 403, ....
-        */
-        iChunk += SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET;
-      }
-#endif
-      sqlite3_snprintf(4,&z[n],"%03d",iChunk);
-    }
+    multiplexFilename(pGroup->zName, pGroup->nName, pGroup->flags, iChunk, z);
   }
   return SQLITE_OK;
 }
@@ -483,24 +501,43 @@ static int multiplexOpen(
 
       rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
       if( rc==SQLITE_OK && zName ){
-        int exists;
-
-        /* If the first overflow file exists and if the size of the main file
-        ** is different from the chunk size, that means the chunk size is set
-        ** set incorrectly.  So fix it.
-        **
-        ** Or, if the first overflow file does not exist and the main file is
-        ** larger than the chunk size, that means the chunk size is too small.
-        ** But we have no way of determining the intended chunk size, so 
-        ** just disable the multiplexor all togethre.
-        */
-        rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
-            SQLITE_ACCESS_EXISTS, &exists);
-        if( rc==SQLITE_OK && exists && sz==(sz&0xffff0000) && sz>0
-            && sz!=pGroup->szChunk ){
-          pGroup->szChunk = sz;
-        }else if( rc==SQLITE_OK && !exists && sz>pGroup->szChunk ){
-          pGroup->bEnabled = 0;
+        int bExists;
+        if( sz==0 ){
+          if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
+            /* If opening a main journal file and the first chunk is zero
+            ** bytes in size, delete any subsequent chunks from the 
+            ** file-system. */
+            int iChunk = 1;
+            do {
+              rc = pOrigVfs->xAccess(pOrigVfs, 
+                  pGroup->aReal[iChunk].z, SQLITE_ACCESS_EXISTS, &bExists
+              );
+              if( rc==SQLITE_OK && bExists ){
+                rc = pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
+                if( rc==SQLITE_OK ){
+                  rc = multiplexSubFilename(pGroup, ++iChunk);
+                }
+              }
+            }while( rc==SQLITE_OK && bExists );
+          }
+        }else{
+          /* If the first overflow file exists and if the size of the main file
+           ** is different from the chunk size, that means the chunk size is set
+           ** set incorrectly.  So fix it.
+           **
+           ** Or, if the first overflow file does not exist and the main file is
+           ** larger than the chunk size, that means the chunk size is too small.
+           ** But we have no way of determining the intended chunk size, so 
+           ** just disable the multiplexor all togethre.
+           */
+          rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
+              SQLITE_ACCESS_EXISTS, &bExists);
+          if( rc==SQLITE_OK && bExists && sz==(sz&0xffff0000) && sz>0
+              && sz!=pGroup->szChunk ){
+            pGroup->szChunk = sz;
+          }else if( rc==SQLITE_OK && !bExists && sz>pGroup->szChunk ){
+            pGroup->bEnabled = 0;
+          }
         }
       }
     }
@@ -534,8 +571,33 @@ static int multiplexDelete(
   const char *zName,         /* Name of file to delete */
   int syncDir
 ){
+  int rc;
   sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
-  return pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
+  rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
+  if( rc==SQLITE_OK ){
+    /* If the main chunk was deleted successfully, also delete any subsequent
+    ** chunks - starting with the last (highest numbered). 
+    */
+    int nName = strlen(zName);
+    char *z;
+    z = sqlite3_malloc(nName + 4);
+    if( z==0 ){
+      rc = SQLITE_IOERR_NOMEM;
+    }else{
+      int iChunk = 0;
+      int bExists;
+      do{
+        multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, ++iChunk, z);
+        rc = pOrigVfs->xAccess(pOrigVfs, z, SQLITE_ACCESS_EXISTS, &bExists);
+      }while( rc==SQLITE_OK && bExists );
+      while( rc==SQLITE_OK && iChunk>1 ){
+        multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, --iChunk, z);
+        rc = pOrigVfs->xDelete(pOrigVfs, z, syncDir);
+      }
+    }
+    sqlite3_free(z);
+  }
+  return rc;
 }
 
 static int multiplexAccess(sqlite3_vfs *a, const char *b, int c, int *d){