/ Check-in [3af1feaa]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:When deleting a file with the multiplexor VFS, also delete any overflow files that exist.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | nx-devkit
Files: files | file ages | folders
SHA1: 3af1feaa35d3fb2e7be550cd32a727001b874938
User & Date: dan 2011-12-15 17:00:10
Context
2011-12-16
00:33
Make sure the antipenultimate character of master-journal filenames is a "9" in order to avoid collisions with other files in 8+3 filename mode. Also, limit the number of attempts at finding a unique master-journal filename. check-in: 34a04836 user: drh tags: nx-devkit
2011-12-15
17:00
When deleting a file with the multiplexor VFS, also delete any overflow files that exist. check-in: 3af1feaa user: dan tags: nx-devkit
13:29
Make sure the chunksize in test_multiplex does not cause the pending byte to fall near the end of a chunk. Adjust the chunksize upward as necessary to prevent this. check-in: e05f8a29 user: drh tags: nx-devkit
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/test_multiplex.c.

   211    211   */
   212    212   static int multiplexStrlen30(const char *z){
   213    213     const char *z2 = z;
   214    214     if( z==0 ) return 0;
   215    215     while( *z2 ){ z2++; }
   216    216     return 0x3fffffff & (int)(z2 - z);
   217    217   }
          218  +
          219  +/*
          220  +** Generate the file-name for chunk iChunk of the group with base name
          221  +** zBase. The file-name is written to buffer zOut before returning. Buffer
          222  +** zOut must be allocated by the caller so that it is at least (nBase+4)
          223  +** bytes in size, where nBase is the length of zBase, not including the
          224  +** nul-terminator.
          225  +*/
          226  +static void multiplexFilename(
          227  +  const char *zBase,              /* Filename for chunk 0 */
          228  +  int nBase,                      /* Size of zBase in bytes (without \0) */
          229  +  int flags,                      /* Flags used to open file */
          230  +  int iChunk,                     /* Chunk to generate filename for */
          231  +  char *zOut                      /* Buffer to write generated name to */
          232  +){
          233  +  memcpy(zOut, zBase, nBase+1);
          234  +  if( iChunk!=0 && iChunk!=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){
          235  +    int n = nBase;
          236  +#ifdef SQLITE_ENABLE_8_3_NAMES
          237  +    int i;
          238  +    for(i=n-1; i>0 && i>=n-4 && zOut[i]!='.'; i--){}
          239  +    if( i>=n-4 ) n = i+1;
          240  +    if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
          241  +      /* The extensions on overflow files for main databases are 001, 002,
          242  +       ** 003 and so forth.  To avoid name collisions, add 400 to the 
          243  +       ** extensions of journal files so that they are 401, 402, 403, ....
          244  +       */
          245  +      iChunk += SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET;
          246  +    }
          247  +#endif
          248  +    sqlite3_snprintf(4,&zOut[n],"%03d",iChunk);
          249  +  }
          250  +}
   218    251   
   219    252   /* Compute the filename for the iChunk-th chunk
   220    253   */
   221    254   static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
   222    255     if( iChunk>=pGroup->nReal ){
   223    256       struct multiplexReal *p;
   224    257       p = sqlite3_realloc(pGroup->aReal, (iChunk+1)*sizeof(*p));
................................................................................
   232    265     if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){
   233    266       char *z;
   234    267       int n = pGroup->nName;
   235    268       pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+4 );
   236    269       if( z==0 ){
   237    270         return SQLITE_NOMEM;
   238    271       }
   239         -    memcpy(z, pGroup->zName, n+1);
   240         -    if( iChunk>0 ){
   241         -#ifdef SQLITE_ENABLE_8_3_NAMES
   242         -      int i;
   243         -      for(i=n-1; i>0 && i>=n-4 && z[i]!='.'; i--){}
   244         -      if( i>=n-4 ) n = i+1;
   245         -      if( pGroup->flags & (SQLITE_OPEN_MAIN_JOURNAL|SQLITE_OPEN_TEMP_JOURNAL) ){
   246         -        /* The extensions on overflow files for main databases are 001, 002,
   247         -        ** 003 and so forth.  To avoid name collisions, add 400 to the 
   248         -        ** extensions of journal files so that they are 401, 402, 403, ....
   249         -        */
   250         -        iChunk += SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET;
   251         -      }
   252         -#endif
   253         -      sqlite3_snprintf(4,&z[n],"%03d",iChunk);
   254         -    }
          272  +    multiplexFilename(pGroup->zName, pGroup->nName, pGroup->flags, iChunk, z);
   255    273     }
   256    274     return SQLITE_OK;
   257    275   }
   258    276   
   259    277   /* Translate an sqlite3_file* that is really a multiplexGroup* into
   260    278   ** the sqlite3_file* for the underlying original VFS.
   261    279   */
................................................................................
   479    497         assert( pSubOpen || rc!=SQLITE_OK );
   480    498       }
   481    499       if( rc==SQLITE_OK ){
   482    500         sqlite3_int64 sz;
   483    501   
   484    502         rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
   485    503         if( rc==SQLITE_OK && zName ){
   486         -        int exists;
   487         -
   488         -        /* If the first overflow file exists and if the size of the main file
   489         -        ** is different from the chunk size, that means the chunk size is set
   490         -        ** set incorrectly.  So fix it.
   491         -        **
   492         -        ** Or, if the first overflow file does not exist and the main file is
   493         -        ** larger than the chunk size, that means the chunk size is too small.
   494         -        ** But we have no way of determining the intended chunk size, so 
   495         -        ** just disable the multiplexor all togethre.
   496         -        */
   497         -        rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
   498         -            SQLITE_ACCESS_EXISTS, &exists);
   499         -        if( rc==SQLITE_OK && exists && sz==(sz&0xffff0000) && sz>0
   500         -            && sz!=pGroup->szChunk ){
   501         -          pGroup->szChunk = sz;
   502         -        }else if( rc==SQLITE_OK && !exists && sz>pGroup->szChunk ){
   503         -          pGroup->bEnabled = 0;
          504  +        int bExists;
          505  +        if( sz==0 ){
          506  +          if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
          507  +            /* If opening a main journal file and the first chunk is zero
          508  +            ** bytes in size, delete any subsequent chunks from the 
          509  +            ** file-system. */
          510  +            int iChunk = 1;
          511  +            do {
          512  +              rc = pOrigVfs->xAccess(pOrigVfs, 
          513  +                  pGroup->aReal[iChunk].z, SQLITE_ACCESS_EXISTS, &bExists
          514  +              );
          515  +              if( rc==SQLITE_OK && bExists ){
          516  +                rc = pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
          517  +                if( rc==SQLITE_OK ){
          518  +                  rc = multiplexSubFilename(pGroup, ++iChunk);
          519  +                }
          520  +              }
          521  +            }while( rc==SQLITE_OK && bExists );
          522  +          }
          523  +        }else{
          524  +          /* If the first overflow file exists and if the size of the main file
          525  +           ** is different from the chunk size, that means the chunk size is set
          526  +           ** set incorrectly.  So fix it.
          527  +           **
          528  +           ** Or, if the first overflow file does not exist and the main file is
          529  +           ** larger than the chunk size, that means the chunk size is too small.
          530  +           ** But we have no way of determining the intended chunk size, so 
          531  +           ** just disable the multiplexor all togethre.
          532  +           */
          533  +          rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
          534  +              SQLITE_ACCESS_EXISTS, &bExists);
          535  +          if( rc==SQLITE_OK && bExists && sz==(sz&0xffff0000) && sz>0
          536  +              && sz!=pGroup->szChunk ){
          537  +            pGroup->szChunk = sz;
          538  +          }else if( rc==SQLITE_OK && !bExists && sz>pGroup->szChunk ){
          539  +            pGroup->bEnabled = 0;
          540  +          }
   504    541           }
   505    542         }
   506    543       }
   507    544   
   508    545       if( rc==SQLITE_OK ){
   509    546         if( pSubOpen->pMethods->iVersion==1 ){
   510    547           pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1;
................................................................................
   530    567   ** It attempts to delete the filename specified.
   531    568   */
   532    569   static int multiplexDelete(
   533    570     sqlite3_vfs *pVfs,         /* The multiplex VFS */
   534    571     const char *zName,         /* Name of file to delete */
   535    572     int syncDir
   536    573   ){
          574  +  int rc;
   537    575     sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
   538         -  return pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
          576  +  rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
          577  +  if( rc==SQLITE_OK ){
          578  +    /* If the main chunk was deleted successfully, also delete any subsequent
          579  +    ** chunks - starting with the last (highest numbered). 
          580  +    */
          581  +    int nName = strlen(zName);
          582  +    char *z;
          583  +    z = sqlite3_malloc(nName + 4);
          584  +    if( z==0 ){
          585  +      rc = SQLITE_IOERR_NOMEM;
          586  +    }else{
          587  +      int iChunk = 0;
          588  +      int bExists;
          589  +      do{
          590  +        multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, ++iChunk, z);
          591  +        rc = pOrigVfs->xAccess(pOrigVfs, z, SQLITE_ACCESS_EXISTS, &bExists);
          592  +      }while( rc==SQLITE_OK && bExists );
          593  +      while( rc==SQLITE_OK && iChunk>1 ){
          594  +        multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, --iChunk, z);
          595  +        rc = pOrigVfs->xDelete(pOrigVfs, z, syncDir);
          596  +      }
          597  +    }
          598  +    sqlite3_free(z);
          599  +  }
          600  +  return rc;
   539    601   }
   540    602   
   541    603   static int multiplexAccess(sqlite3_vfs *a, const char *b, int c, int *d){
   542    604     return gMultiplex.pOrigVfs->xAccess(gMultiplex.pOrigVfs, b, c, d);
   543    605   }
   544    606   static int multiplexFullPathname(sqlite3_vfs *a, const char *b, int c, char *d){
   545    607     return gMultiplex.pOrigVfs->xFullPathname(gMultiplex.pOrigVfs, b, c, d);