From: dan Date: Thu, 15 Dec 2011 17:00:10 +0000 (+0000) Subject: When deleting a file with the multiplexor VFS, also delete any overflow files that... X-Git-Tag: version-3.7.10~19^2~55^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e712b5823e8c984491a8ac34e43fb5e50a995058;p=thirdparty%2Fsqlite.git When deleting a file with the multiplexor VFS, also delete any overflow files that exist. FossilOrigin-Name: 3af1feaa35d3fb2e7be550cd32a727001b874938 --- diff --git a/manifest b/manifest index 21cbee27f3..aec2b27521 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index ce1d054b8f..e4ed76872d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e05f8a2998f4f4cbdb65702baa65893c538b3d38 \ No newline at end of file +3af1feaa35d3fb2e7be550cd32a727001b874938 \ No newline at end of file diff --git a/src/test_multiplex.c b/src/test_multiplex.c index 12e420fb5d..d844604ab5 100644 --- a/src/test_multiplex.c +++ b/src/test_multiplex.c @@ -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){