]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
When the multiplexor opens an auxiliary file, it now persists the name of that
authordrh <drh@noemail.net>
Wed, 20 Jul 2011 16:35:31 +0000 (16:35 +0000)
committerdrh <drh@noemail.net>
Wed, 20 Jul 2011 16:35:31 +0000 (16:35 +0000)
file until it is closed, as it should.  Remove the limit on the number of
auxiliary files used by the multiplexor.

FossilOrigin-Name: 1ffa542bf913200a18ef77447aec4fc3ca1ed618

manifest
manifest.uuid
src/test_multiplex.c
test/multiplex.test

index dc0a0982a21eac9cfe6d330981d1c2acdcdfc582..c0583658f0462ecee97332adeb1c94dfd683bf8b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Formatting\schanges\son\sthe\smultiplexor\scode\s-\smake\ssure\sno\slines\sexceed\s80\ncharacters.\s\sNo\slogical\schanges.
-D 2011-07-19T18:29:00.027
+C When\sthe\smultiplexor\sopens\san\sauxiliary\sfile,\sit\snow\spersists\sthe\sname\sof\sthat\nfile\suntil\sit\sis\sclosed,\sas\sit\sshould.\s\sRemove\sthe\slimit\son\sthe\snumber\sof\nauxiliary\sfiles\sused\sby\sthe\smultiplexor.
+D 2011-07-20T16:35:31.624
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in c1d7a7f4fd8da6b1815032efca950e3d5125407e
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -213,7 +213,7 @@ F src/test_intarray.h 489edb9068bb926583445cb02589344961054207
 F src/test_journal.c 03313c693cca72959dcaaf79f8d76f21c01e19ff
 F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e
 F src/test_malloc.c 7ca7be34e0e09ef0ed6619544552ed95732e41f6
-F src/test_multiplex.c d1b43de1209bd1bc207b694a738fdb84a162f65b
+F src/test_multiplex.c 282f315fd035c8d8342a4cc59748c60216b61fef
 F src/test_multiplex.h e99c571bc4968b7a9363b661481f3934bfead61d
 F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
 F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
@@ -595,7 +595,7 @@ F test/misc5.test 9f9338f8211c7f5d1cbe16331fa65d019501aa50
 F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
 F test/misc7.test 29032efcd3d826fbd409e2a7af873e7939f4a4e3
 F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
-F test/multiplex.test 555080c87abfc72ba68e2f3df01d4a9a7a4fdf58
+F test/multiplex.test 2256e90e8780de6eeafc07d4084427c3a97d3bcb
 F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
 F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
 F test/nan.test dc212a22b36109fd1ae37154292444ef249c5ec2
@@ -952,7 +952,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5
 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262
-P 4355bf2908b923e844907c1e3c09be3bf469f833
-R 33ae39ed3129fdb3c8dbf2c830ddcfd5
+P ed5f0aad6b21066bacd01521e82c22e96991f400
+R e63c3d9c3ff7ac85b18419c4f45127d4
 U drh
-Z 60f009445613def050e13415b0c93faf
+Z 1541751b97b37082064c8e76500e9b76
index a91085ca7cc7e9fcdcb733a543fb0ceb55b693db..04e86b35f32628953d6a7d5d546c05481ac7241f 100644 (file)
@@ -1 +1 @@
-ed5f0aad6b21066bacd01521e82c22e96991f400
\ No newline at end of file
+1ffa542bf913200a18ef77447aec4fc3ca1ed618
\ No newline at end of file
index 2203c60b5473d2ca6078f89e82cf081067a282cd..b6fe9e8b63d98594f08371c448d45fd27c62de40 100644 (file)
@@ -126,13 +126,15 @@ typedef struct multiplexConn multiplexConn;
 ** group.
 */
 struct multiplexGroup {
-  sqlite3_file **pReal;            /* Handles to each chunk */
-  char *bOpen;                     /* array of bools - 0 if chunk not opened */
+  struct multiplexReal {           /* For each chunk */
+    sqlite3_file *p;                  /* Handle for the chunk */
+    char *z;                          /* Name of this chunk */
+  } *aReal;                        /* list of all chunks */
+  int nReal;                       /* Number of chunks */
   char *zName;                     /* Base filename of this group */
   int nName;                       /* Length of base filename */
   int flags;                       /* Flags used for original opening */
   int nChunkSize;                  /* Chunk size used for this group */
-  int nMaxChunks;                  /* Max number of chunks for this group */
   int bEnabled;                    /* TRUE to use Multiplex VFS for this file */
   multiplexGroup *pNext, *pPrev;   /* Doubly linked list of all group objects */
 };
@@ -191,12 +193,6 @@ static struct {
   /* List of multiplexGroup objects.
   */
   multiplexGroup *pGroups;
-
-  /* Storage for temp file names.  Allocated during 
-  ** initialization to the max pathname of the underlying VFS.
-  */
-  char *zName;
-
 } gMultiplex;
 
 /************************* Utility Routines *********************************/
@@ -287,45 +283,69 @@ static int multiplexGetTempname(sqlite3_vfs *pOrigVfs, int nBuf, char *zBuf){
   return rc;
 }
 
+/* Compute the filename for the iChunk-th chunk
+*/
+static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
+  if( iChunk>=pGroup->nReal ){
+    struct multiplexReal *p;
+    p = sqlite3_realloc(pGroup->aReal, (iChunk+1)*sizeof(*p));
+    if( p==0 ){
+      return SQLITE_NOMEM;
+    }
+    memset(&p[pGroup->nReal], 0, sizeof(p[0])*(iChunk+1-pGroup->nReal));
+    pGroup->aReal = p;
+    pGroup->nReal = iChunk+1;
+  }
+  if( pGroup->aReal[iChunk].z==0 ){
+    char *z;
+    int n = pGroup->nName;
+    pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+3 );
+    if( z==0 ){
+      return SQLITE_NOMEM;
+    }
+    memcpy(z, pGroup->zName, n+1);
+    if( iChunk>0 ){
+#ifdef SQLITE_ENABLE_8_3_NAMES
+      if( n>3 && z[n-3]=='.' ){
+        n--;
+      }else if( n>4 && z[n-4]=='.' ){
+        n -= 2;
+      }
+#endif
+      sqlite3_snprintf(3,&z[n],"%02d",iChunk);
+    }
+  }
+  return SQLITE_OK;
+}
+
 /* Translate an sqlite3_file* that is really a multiplexGroup* into
 ** the sqlite3_file* for the underlying original VFS.
 */
 static sqlite3_file *multiplexSubOpen(
-  multiplexConn *pConn,
+  multiplexGroup *pGroup,
   int iChunk,
   int *rc,
   int *pOutFlags
 ){
-  multiplexGroup *pGroup = pConn->pGroup;
+  sqlite3_file *pSubOpen = 0;
   sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;        /* Real VFS */
-  if( iChunk<pGroup->nMaxChunks ){
-    sqlite3_file *pSubOpen = pGroup->pReal[iChunk];   /* Real file descriptor */
-    if( !pGroup->bOpen[iChunk] ){
-      memcpy(gMultiplex.zName, pGroup->zName, pGroup->nName+1);
-      if( iChunk ){
-#ifdef SQLITE_MULTIPLEX_EXT_OVWR
-        sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1,
-             gMultiplex.zName+pGroup->nName-SQLITE_MULTIPLEX_EXT_SZ,
-             SQLITE_MULTIPLEX_EXT_FMT, iChunk);
-#else
-        sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1,
-             gMultiplex.zName+pGroup->nName,
-             SQLITE_MULTIPLEX_EXT_FMT, iChunk);
-#endif
-      }
-      *rc = pOrigVfs->xOpen(pOrigVfs, gMultiplex.zName, pSubOpen,
-                            pGroup->flags, pOutFlags);
-      if( *rc==SQLITE_OK ){
-        pGroup->bOpen[iChunk] = -1;
-        return pSubOpen;
-      }
-      return NULL;
+  *rc = multiplexSubFilename(pGroup, iChunk);
+  if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){
+    pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile );
+    if( pSubOpen==0 ){
+      *rc = SQLITE_NOMEM;
+      return 0;
+    }
+    pGroup->aReal[iChunk].p = pSubOpen;
+    *rc = pOrigVfs->xOpen(pOrigVfs, pGroup->aReal[iChunk].z, pSubOpen,
+                          pGroup->flags, pOutFlags);
+    if( *rc!=SQLITE_OK ){
+      sqlite3_free(pSubOpen);
+      pGroup->aReal[iChunk].p = 0;
+      return 0;
     }
-    *rc = SQLITE_OK;
-    return pSubOpen;
   }
-  *rc = SQLITE_FULL;
-  return NULL;
+  return pSubOpen;
 }
 
 /*
@@ -384,6 +404,36 @@ static int multiplexFuncInit(
   return rc;
 }
 
+/*
+** Close a single sub-file in the connection group.
+*/
+static void multiplexSubClose(
+  multiplexGroup *pGroup,
+  int iChunk,
+  sqlite3_vfs *pOrigVfs
+){
+  sqlite3_file *pSubOpen = pGroup->aReal[iChunk].p;
+  if( pSubOpen ){
+    if( pOrigVfs ) pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
+    pSubOpen->pMethods->xClose(pSubOpen);
+    sqlite3_free(pGroup->aReal[iChunk].p);
+  }
+  sqlite3_free(pGroup->aReal[iChunk].z);
+  memset(&pGroup->aReal[iChunk], 0, sizeof(pGroup->aReal[iChunk]));
+}
+
+/*
+** Deallocate memory held by a multiplexGroup
+*/
+static void multiplexFreeComponents(multiplexGroup *pGroup){
+  int i;
+  for(i=0; i<pGroup->nReal; i++){ multiplexSubClose(pGroup, i, 0); }
+  sqlite3_free(pGroup->aReal);
+  pGroup->aReal = 0;
+  pGroup->nReal = 0;
+}
+
+
 /************************* VFS Method Wrappers *****************************/
 
 /*
@@ -406,10 +456,11 @@ static int multiplexOpen(
   sqlite3_file *pSubOpen;                        /* Real file descriptor */
   sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
   int nName;
-  int i;
   int sz;
+  char *zToFree = 0;
 
   UNUSED_PARAMETER(pVfs);
+  memset(pConn, 0, pVfs->szOsFile);
 
   /* We need to create a group structure and manage
   ** access to this group of files.
@@ -423,28 +474,22 @@ static int multiplexOpen(
   ** it.
   */
   if( !zName ){
-    rc = multiplexGetTempname(pOrigVfs, pOrigVfs->mxPathname, gMultiplex.zName);
-    zName = gMultiplex.zName;
+    zName = zToFree = sqlite3_malloc( pOrigVfs->mxPathname + 10 );
+    if( zName==0 ){
+      rc = SQLITE_NOMEM;
+    }else{
+      rc = multiplexGetTempname(pOrigVfs, pOrigVfs->mxPathname, zToFree);
+    }
   }
 
   if( rc==SQLITE_OK ){
     /* allocate space for group */
     nName = multiplexStrlen30(zName);
     sz = sizeof(multiplexGroup)                             /* multiplexGroup */
-       + (sizeof(sqlite3_file *)*SQLITE_MULTIPLEX_MAX_CHUNKS)  /* pReal[] */
-       + (pOrigVfs->szOsFile*SQLITE_MULTIPLEX_MAX_CHUNKS)      /* *pReal */
-       + SQLITE_MULTIPLEX_MAX_CHUNKS                           /* bOpen[] */
-       + nName + 1;                                            /* zName */
-#ifndef SQLITE_MULTIPLEX_EXT_OVWR
-    sz += SQLITE_MULTIPLEX_EXT_SZ;
-    assert(nName+SQLITE_MULTIPLEX_EXT_SZ < pOrigVfs->mxPathname);
-#else
-    assert(nName >= SQLITE_MULTIPLEX_EXT_SZ);
-    assert(nName < pOrigVfs->mxPathname);
-#endif
+       + nName + 1;                                         /* zName */
     pGroup = sqlite3_malloc( sz );
     if( pGroup==0 ){
-      rc=SQLITE_NOMEM;
+      rc = SQLITE_NOMEM;
     }
   }
 
@@ -456,27 +501,19 @@ static int multiplexOpen(
     memset(pGroup, 0, sz);
     pGroup->bEnabled = -1;
     pGroup->nChunkSize = SQLITE_MULTIPLEX_CHUNK_SIZE;
-    zChunkSize = sqlite3_uri_parameter(zName, "chunksize");
-    if( zChunkSize ){
-      int n = atoi(zChunkSize);
-      if( n>0 ) pGroup->nChunkSize = (n+0xffff)&~0xffff;
-    }
-    pGroup->nMaxChunks = SQLITE_MULTIPLEX_MAX_CHUNKS;
-    pGroup->pReal = (sqlite3_file **)p;
-    p += (sizeof(sqlite3_file *)*pGroup->nMaxChunks);
-    for(i=0; i<pGroup->nMaxChunks; i++){
-      pGroup->pReal[i] = (sqlite3_file *)p;
-      p += pOrigVfs->szOsFile;
+    if( flags & SQLITE_OPEN_URI ){
+      zChunkSize = sqlite3_uri_parameter(zName, "chunksize");
+      if( zChunkSize ){
+        int n = atoi(zChunkSize);
+        if( n>0 ) pGroup->nChunkSize = (n+0xffff)&~0xffff;
+      }
     }
-    /* bOpen[] vals should all be zero from memset above */
-    pGroup->bOpen = p;
-    p += pGroup->nMaxChunks;
     pGroup->zName = p;
     /* save off base filename, name length, and original open flags  */
     memcpy(pGroup->zName, zName, nName+1);
     pGroup->nName = nName;
     pGroup->flags = flags;
-    pSubOpen = multiplexSubOpen(pMultiplexOpen, 0, &rc, pOutFlags);
+    pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags);
     if( pSubOpen ){
       /* if this file is already larger than chunk size, disable 
       ** the multiplex feature.
@@ -496,17 +533,18 @@ static int multiplexOpen(
       if( gMultiplex.pGroups ) gMultiplex.pGroups->pPrev = pGroup;
       gMultiplex.pGroups = pGroup;
     }else{
+      multiplexFreeComponents(pGroup);
       sqlite3_free(pGroup);
     }
   }
   multiplexLeave();
+  sqlite3_free(zToFree);
   return rc;
 }
 
 /*
 ** This is the xDelete method used for the "multiplex" VFS.
-** It attempts to delete the filename specified, as well
-** as additional files with the SQLITE_MULTIPLEX_EXT_FMT extension.
+** It attempts to delete the filename specified.
 */
 static int multiplexDelete(
   sqlite3_vfs *pVfs,         /* The multiplex VFS */
@@ -514,41 +552,7 @@ static int multiplexDelete(
   int syncDir
 ){
   sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
-  int rc = SQLITE_OK;
-  int nName = multiplexStrlen30(zName);
-  int i;
-
-  UNUSED_PARAMETER(pVfs);
-
-  multiplexEnter();
-  memcpy(gMultiplex.zName, zName, nName+1);
-  for(i=0; i<SQLITE_MULTIPLEX_MAX_CHUNKS; i++){
-    int rc2;
-    int exists = 0;
-    if( i ){
-#ifdef SQLITE_MULTIPLEX_EXT_OVWR
-        sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, 
-            gMultiplex.zName+nName-SQLITE_MULTIPLEX_EXT_SZ, 
-            SQLITE_MULTIPLEX_EXT_FMT, i);
-#else
-        sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, 
-            gMultiplex.zName+nName, 
-            SQLITE_MULTIPLEX_EXT_FMT, i);
-#endif
-    }
-    rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName, 
-        SQLITE_ACCESS_EXISTS, &exists);
-    if( rc2==SQLITE_OK && exists ){
-      /* if it exists, delete it */
-      rc2 = pOrigVfs->xDelete(pOrigVfs, gMultiplex.zName, syncDir);
-      if( rc2!=SQLITE_OK ) rc = rc2;
-    }else{
-      /* stop at first "gap" */
-      break;
-    }
-  }
-  multiplexLeave();
-  return rc;
+  return pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
 }
 
 static int multiplexAccess(sqlite3_vfs *a, const char *b, int c, int *d){
@@ -596,17 +600,8 @@ static int multiplexClose(sqlite3_file *pConn){
   multiplexConn *p = (multiplexConn*)pConn;
   multiplexGroup *pGroup = p->pGroup;
   int rc = SQLITE_OK;
-  int i;
   multiplexEnter();
-  /* close any open handles */
-  for(i=0; i<pGroup->nMaxChunks; i++){
-    if( pGroup->bOpen[i] ){
-      sqlite3_file *pSubOpen = pGroup->pReal[i];
-      int rc2 = pSubOpen->pMethods->xClose(pSubOpen);
-      if( rc2!=SQLITE_OK ) rc = rc2;
-      pGroup->bOpen[i] = 0;
-    }
-  }
+  multiplexFreeComponents(pGroup);
   /* remove from linked list */
   if( pGroup->pNext ) pGroup->pNext->pPrev = pGroup->pPrev;
   if( pGroup->pPrev ){
@@ -634,8 +629,8 @@ static int multiplexRead(
   int rc = SQLITE_OK;
   multiplexEnter();
   if( !pGroup->bEnabled ){
-    sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
-    if( !pSubOpen ){
+    sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
+    if( pSubOpen==0 ){
       rc = SQLITE_IOERR_READ;
     }else{
       rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst);
@@ -643,7 +638,7 @@ static int multiplexRead(
   }else{
     while( iAmt > 0 ){
       int i = (int)(iOfst / pGroup->nChunkSize);
-      sqlite3_file *pSubOpen = multiplexSubOpen(p, i, &rc, NULL);
+      sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
       if( pSubOpen ){
         int extra = ((int)(iOfst % pGroup->nChunkSize) + iAmt) -
                                                         pGroup->nChunkSize;
@@ -680,7 +675,7 @@ static int multiplexWrite(
   int rc = SQLITE_OK;
   multiplexEnter();
   if( !pGroup->bEnabled ){
-    sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+    sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
     if( pSubOpen==0 ){
       rc = SQLITE_IOERR_WRITE;
     }else{
@@ -689,7 +684,7 @@ static int multiplexWrite(
   }else{
     while( iAmt > 0 ){
       int i = (int)(iOfst / pGroup->nChunkSize);
-      sqlite3_file *pSubOpen = multiplexSubOpen(p, i, &rc, NULL);
+      sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
       if( pSubOpen ){
         int extra = ((int)(iOfst % pGroup->nChunkSize) + iAmt) -
                     pGroup->nChunkSize;
@@ -721,7 +716,7 @@ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){
   int rc = SQLITE_OK;
   multiplexEnter();
   if( !pGroup->bEnabled ){
-    sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+    sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
     if( pSubOpen==0 ){
       rc = SQLITE_IOERR_TRUNCATE;
     }else{
@@ -732,29 +727,11 @@ static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){
     int i;
     sqlite3_file *pSubOpen;
     sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
-    memcpy(gMultiplex.zName, pGroup->zName, pGroup->nName+1);
     /* delete the chunks above the truncate limit */
-    for(i=(int)(size / pGroup->nChunkSize)+1; i<pGroup->nMaxChunks; i++){
-      /* close any open chunks before deleting them */
-      if( pGroup->bOpen[i] ){
-        pSubOpen = pGroup->pReal[i];
-        rc2 = pSubOpen->pMethods->xClose(pSubOpen);
-        if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE;
-        pGroup->bOpen[i] = 0;
-      }
-#ifdef SQLITE_MULTIPLEX_EXT_OVWR
-      sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, 
-          gMultiplex.zName+pGroup->nName-SQLITE_MULTIPLEX_EXT_SZ, 
-          SQLITE_MULTIPLEX_EXT_FMT, i);
-#else
-      sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, 
-          gMultiplex.zName+pGroup->nName, 
-          SQLITE_MULTIPLEX_EXT_FMT, i);
-#endif
-      rc2 = pOrigVfs->xDelete(pOrigVfs, gMultiplex.zName, 0);
-      if( rc2!=SQLITE_OK ) rc = SQLITE_IOERR_TRUNCATE;
+    for(i=(int)(size / pGroup->nChunkSize)+1; i<pGroup->nReal; i++){
+      multiplexSubClose(pGroup, i, pOrigVfs);
     }
-    pSubOpen = multiplexSubOpen(p, (int)(size/pGroup->nChunkSize), &rc2, NULL);
+    pSubOpen = multiplexSubOpen(pGroup, (int)(size/pGroup->nChunkSize), &rc2,0);
     if( pSubOpen ){
       rc2 = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->nChunkSize);
       if( rc2!=SQLITE_OK ) rc = rc2;
@@ -774,10 +751,9 @@ static int multiplexSync(sqlite3_file *pConn, int flags){
   int rc = SQLITE_OK;
   int i;
   multiplexEnter();
-  for(i=0; i<pGroup->nMaxChunks; i++){
-    /* if we don't have it open, we don't need to sync it */
-    if( pGroup->bOpen[i] ){
-      sqlite3_file *pSubOpen = pGroup->pReal[i];
+  for(i=0; i<pGroup->nReal; i++){
+    sqlite3_file *pSubOpen = pGroup->aReal[i].p;
+    if( pSubOpen ){
       int rc2 = pSubOpen->pMethods->xSync(pSubOpen, flags);
       if( rc2!=SQLITE_OK ) rc = rc2;
     }
@@ -797,7 +773,7 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
   int i;
   multiplexEnter();
   if( !pGroup->bEnabled ){
-    sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+    sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
     if( pSubOpen==0 ){
       rc = SQLITE_IOERR_FSTAT;
     }else{
@@ -805,35 +781,20 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
     }
   }else{
     *pSize = 0;
-    for(i=0; i<pGroup->nMaxChunks; i++){
-      sqlite3_file *pSubOpen = NULL;
-      /* if not opened already, check to see if the chunk exists */
-      if( pGroup->bOpen[i] ){
-        pSubOpen = pGroup->pReal[i];
+    for(i=0; 1; i++){
+      sqlite3_file *pSubOpen = 0;
+      sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;
+      int exists = 0;
+      rc = multiplexSubFilename(pGroup, i);
+      if( rc ) break;
+      rc2 = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[i].z,
+          SQLITE_ACCESS_EXISTS, &exists);
+      if( rc2==SQLITE_OK && exists){
+        /* if it exists, open it */
+        pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
       }else{
-        sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
-        int exists = 0;
-        memcpy(gMultiplex.zName, pGroup->zName, pGroup->nName+1);
-        if( i ){
-#ifdef SQLITE_MULTIPLEX_EXT_OVWR
-          sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, 
-              gMultiplex.zName+pGroup->nName-SQLITE_MULTIPLEX_EXT_SZ, 
-              SQLITE_MULTIPLEX_EXT_FMT, i);
-#else
-          sqlite3_snprintf(SQLITE_MULTIPLEX_EXT_SZ+1, 
-              gMultiplex.zName+pGroup->nName, 
-              SQLITE_MULTIPLEX_EXT_FMT, i);
-#endif
-        }
-        rc2 = pOrigVfs->xAccess(pOrigVfs, gMultiplex.zName, 
-            SQLITE_ACCESS_EXISTS, &exists);
-        if( rc2==SQLITE_OK && exists){
-          /* if it exists, open it */
-          pSubOpen = multiplexSubOpen(p, i, &rc, NULL);
-        }else{
-          /* stop at first "gap" */
-          break;
-        }
+        /* stop at first "gap" */
+        break;
       }
       if( pSubOpen ){
         sqlite3_int64 sz;
@@ -860,7 +821,7 @@ static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
 static int multiplexLock(sqlite3_file *pConn, int lock){
   multiplexConn *p = (multiplexConn*)pConn;
   int rc;
-  sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
   if( pSubOpen ){
     return pSubOpen->pMethods->xLock(pSubOpen, lock);
   }
@@ -872,7 +833,7 @@ static int multiplexLock(sqlite3_file *pConn, int lock){
 static int multiplexUnlock(sqlite3_file *pConn, int lock){
   multiplexConn *p = (multiplexConn*)pConn;
   int rc;
-  sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
   if( pSubOpen ){
     return pSubOpen->pMethods->xUnlock(pSubOpen, lock);
   }
@@ -884,7 +845,7 @@ static int multiplexUnlock(sqlite3_file *pConn, int lock){
 static int multiplexCheckReservedLock(sqlite3_file *pConn, int *pResOut){
   multiplexConn *p = (multiplexConn*)pConn;
   int rc;
-  sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
   if( pSubOpen ){
     return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut);
   }
@@ -924,15 +885,7 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
       }
       break;
     case MULTIPLEX_CTRL_SET_MAX_CHUNKS:
-      if( pArg ) {
-        int nMaxChunks = *(int *)pArg;
-        if(( nMaxChunks<1 ) || ( nMaxChunks>SQLITE_MULTIPLEX_MAX_CHUNKS )){
-          rc = SQLITE_MISUSE;
-        }else{
-          pGroup->nMaxChunks = nMaxChunks;
-          rc = SQLITE_OK;
-        }
-      }
+      rc = SQLITE_OK;
       break;
     case SQLITE_FCNTL_SIZE_HINT:
     case SQLITE_FCNTL_CHUNK_SIZE:
@@ -940,7 +893,7 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
       rc = SQLITE_OK;
       break;
     default:
-      pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+      pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
       if( pSubOpen ){
         rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
       }
@@ -954,7 +907,7 @@ static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
 static int multiplexSectorSize(sqlite3_file *pConn){
   multiplexConn *p = (multiplexConn*)pConn;
   int rc;
-  sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
   if( pSubOpen ){
     return pSubOpen->pMethods->xSectorSize(pSubOpen);
   }
@@ -966,7 +919,7 @@ static int multiplexSectorSize(sqlite3_file *pConn){
 static int multiplexDeviceCharacteristics(sqlite3_file *pConn){
   multiplexConn *p = (multiplexConn*)pConn;
   int rc;
-  sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
   if( pSubOpen ){
     return pSubOpen->pMethods->xDeviceCharacteristics(pSubOpen);
   }
@@ -984,7 +937,7 @@ static int multiplexShmMap(
 ){
   multiplexConn *p = (multiplexConn*)pConn;
   int rc;
-  sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
   if( pSubOpen ){
     return pSubOpen->pMethods->xShmMap(pSubOpen, iRegion, szRegion, bExtend,pp);
   }
@@ -1001,7 +954,7 @@ static int multiplexShmLock(
 ){
   multiplexConn *p = (multiplexConn*)pConn;
   int rc;
-  sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
   if( pSubOpen ){
     return pSubOpen->pMethods->xShmLock(pSubOpen, ofst, n, flags);
   }
@@ -1013,7 +966,7 @@ static int multiplexShmLock(
 static void multiplexShmBarrier(sqlite3_file *pConn){
   multiplexConn *p = (multiplexConn*)pConn;
   int rc;
-  sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
   if( pSubOpen ){
     pSubOpen->pMethods->xShmBarrier(pSubOpen);
   }
@@ -1024,7 +977,7 @@ static void multiplexShmBarrier(sqlite3_file *pConn){
 static int multiplexShmUnmap(sqlite3_file *pConn, int deleteFlag){
   multiplexConn *p = (multiplexConn*)pConn;
   int rc;
-  sqlite3_file *pSubOpen = multiplexSubOpen(p, 0, &rc, NULL);
+  sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
   if( pSubOpen ){
     return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag);
   }
@@ -1054,11 +1007,6 @@ int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault){
   if( !gMultiplex.pMutex ){
     return SQLITE_NOMEM;
   }
-  gMultiplex.zName = sqlite3_malloc(pOrigVfs->mxPathname);
-  if( !gMultiplex.zName ){
-    sqlite3_mutex_free(gMultiplex.pMutex);
-    return SQLITE_NOMEM;
-  }
   gMultiplex.pGroups = NULL;
   gMultiplex.isInitialized = 1;
   gMultiplex.pOrigVfs = pOrigVfs;
@@ -1119,7 +1067,6 @@ int sqlite3_multiplex_shutdown(void){
   if( gMultiplex.isInitialized==0 ) return SQLITE_MISUSE;
   if( gMultiplex.pGroups ) return SQLITE_MISUSE;
   gMultiplex.isInitialized = 0;
-  sqlite3_free(gMultiplex.zName);
   sqlite3_mutex_free(gMultiplex.pMutex);
   sqlite3_vfs_unregister(&gMultiplex.sThisVfs);
   memset(&gMultiplex, 0, sizeof(gMultiplex));
@@ -1221,8 +1168,8 @@ static int test_multiplex_dump(
           Tcl_NewIntObj(pGroup->flags));
 
     /* count number of chunks with open handles */
-    for(i=0; i<pGroup->nMaxChunks; i++){
-      if( pGroup->bOpen[i] ) nChunks++;
+    for(i=0; i<pGroup->nReal; i++){
+      if( pGroup->aReal[i].p!=0 ) nChunks++;
     }
     Tcl_ListObjAppendElement(interp, pGroupTerm,
           Tcl_NewIntObj(nChunks));
@@ -1230,7 +1177,7 @@ static int test_multiplex_dump(
     Tcl_ListObjAppendElement(interp, pGroupTerm,
           Tcl_NewIntObj(pGroup->nChunkSize));
     Tcl_ListObjAppendElement(interp, pGroupTerm,
-          Tcl_NewIntObj(pGroup->nMaxChunks));
+          Tcl_NewIntObj(pGroup->nReal));
 
     Tcl_ListObjAppendElement(interp, pResult, pGroupTerm);
   }
index 9278e8427496bb198be62939b93369288c20e3f7..93d4aafc1695dddb4fe5265bb741db4f2d4e9273 100644 (file)
@@ -49,6 +49,7 @@ proc multiplex_set {db name chunk_size max_chunks} {
 # and files with the chunk extension.
 proc multiplex_delete {name} {
   global g_max_chunks
+  forcedelete $name
   for {set i 0} {$i<$g_max_chunks} {incr i} {
     forcedelete [multiplex_name $name $i]
     forcedelete [multiplex_name $name-journal $i]
@@ -78,10 +79,10 @@ do_test multiplex-1.8 { sqlite3_multiplex_shutdown }               {SQLITE_OK}
 do_test multiplex-1.9.1  { sqlite3_multiplex_initialize "" 1 }     {SQLITE_OK}
 do_test multiplex-1.9.2  { sqlite3 db test.db }                    {}
 do_test multiplex-1.9.3  { multiplex_set db main 32768 16 }        {SQLITE_OK}
-do_test multiplex-1.9.4  { multiplex_set db main 32768 -1 }        {SQLITE_MISUSE}
+do_test multiplex-1.9.4  { multiplex_set db main 32768 -1 }        {SQLITE_OK}
 do_test multiplex-1.9.5  { multiplex_set db main -1 16 }           {SQLITE_MISUSE}
 do_test multiplex-1.9.6  { multiplex_set db main 31 16 }           {SQLITE_OK}
-do_test multiplex-1.9.7  { multiplex_set db main 32768 100 }       {SQLITE_MISUSE}
+do_test multiplex-1.9.7  { multiplex_set db main 32768 100 }       {SQLITE_OK}
 do_test multiplex-1.9.8  { multiplex_set db main 1073741824 1 }    {SQLITE_OK}
 do_test multiplex-1.9.9  { db close }                              {}
 do_test multiplex-1.9.10 { sqlite3_multiplex_shutdown }            {SQLITE_OK}
@@ -89,10 +90,10 @@ do_test multiplex-1.9.10 { sqlite3_multiplex_shutdown }            {SQLITE_OK}
 do_test multiplex-1.10.1  { sqlite3_multiplex_initialize "" 1 }                                  {SQLITE_OK}
 do_test multiplex-1.10.2  { sqlite3 db test.db }                                                 {}
 do_test multiplex-1.10.3  { lindex [ catchsql { SELECT multiplex_control(2, 32768); } ] 0 }      {0}
-do_test multiplex-1.10.4  { lindex [ catchsql { SELECT multiplex_control(3, -1); } ] 0 }         {1}
+do_test multiplex-1.10.4  { lindex [ catchsql { SELECT multiplex_control(3, -1); } ] 0 }         {0}
 do_test multiplex-1.10.5  { lindex [ catchsql { SELECT multiplex_control(2, -1); } ] 0 }         {1}
 do_test multiplex-1.10.6  { lindex [ catchsql { SELECT multiplex_control(2, 31); } ] 0 }         {0}
-do_test multiplex-1.10.7  { lindex [ catchsql { SELECT multiplex_control(3, 100); } ] 0 }        {1}
+do_test multiplex-1.10.7  { lindex [ catchsql { SELECT multiplex_control(3, 100); } ] 0 }        {0}
 do_test multiplex-1.10.8  { lindex [ catchsql { SELECT multiplex_control(2, 1073741824); } ] 0 } {0}
 do_test multiplex-1.10.9  { db close }                                                           {}
 do_test multiplex-1.10.10 { sqlite3_multiplex_shutdown }                                         {SQLITE_OK}
@@ -146,8 +147,9 @@ do_test multiplex-1.13.7  { sqlite3_multiplex_shutdown }
 sqlite3_multiplex_initialize "" 1
 multiplex_set db main 32768 16
 
+file delete -force test.x
 do_test multiplex-2.1.2 {
-  sqlite3 db test.db
+  sqlite3 db test.x
   execsql {
     PRAGMA page_size=1024;
     PRAGMA auto_vacuum=OFF;
@@ -159,7 +161,7 @@ do_test multiplex-2.1.2 {
     INSERT INTO t1 VALUES(2, randomblob(1100));
   }
 } {}
-do_test multiplex-2.1.3 { file size [multiplex_name test.db 0] } {4096}
+do_test multiplex-2.1.3 { file size [multiplex_name test.x 0] } {4096}
 do_test multiplex-2.1.4 {
   execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
 } {}
@@ -167,10 +169,10 @@ do_test multiplex-2.1.4 {
 do_test multiplex-2.2.1 {
   execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
 } {}
-do_test multiplex-2.2.3 { file size [multiplex_name test.db 0] } {6144}
+do_test multiplex-2.2.3 { file size [multiplex_name test.x 0] } {6144}
 
 do_test multiplex-2.3.1 {
-  sqlite3 db2 test2.db
+  sqlite3 db2 test2.x
   db2 close
 } {}
 
@@ -181,7 +183,7 @@ do_test multiplex-2.4.1 {
 do_test multiplex-2.4.2 {
   execsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
 } {}
-do_test multiplex-2.4.4 { file size [multiplex_name test.db 0] } {7168}
+do_test multiplex-2.4.4 { file size [multiplex_name test.x 0] } {7168}
 do_test multiplex-2.4.99 {
   db close
   sqlite3_multiplex_shutdown
@@ -189,9 +191,9 @@ do_test multiplex-2.4.99 {
 
 
 do_test multiplex-2.5.1 {
-  multiplex_delete test.db
+  multiplex_delete test.x
   sqlite3_multiplex_initialize "" 1
-  sqlite3 db test.db
+  sqlite3 db test.x
   multiplex_set db main 4096 16
 } {SQLITE_OK}
 
@@ -236,8 +238,8 @@ do_test multiplex-2.5.8 {
   db eval {SELECT a,length(b) FROM t1 WHERE a=4}
 } {4 4000}
 
-do_test multiplex-2.5.9 { file size [multiplex_name test.db 0] } [list $g_chunk_size]
-do_test multiplex-2.5.10 { file size [multiplex_name test.db 1] } [list $g_chunk_size]
+do_test multiplex-2.5.9 { file size [multiplex_name test.x 0] } [list $g_chunk_size]
+do_test multiplex-2.5.10 { file size [multiplex_name test.x 1] } [list $g_chunk_size]
 
 do_test multiplex-2.5.99 {
   db close
@@ -523,50 +525,6 @@ do_faultsim_test multiplex-5.5 -prep {
   multiplex_set db main 32768 16
 }
 
-# test that mismatch filesize is detected
-#
-# Do not run this test if $::G(perm:presql) is set. If it is set, then the
-# expected IO error will occur within the Tcl [sqlite3] wrapper, not within
-# the first SQL statement executed below. This breaks the test case.
-#
-if {0==[info exists ::G(perm:presql)] || $::G(perm:presql) == ""} {
-  set all_journal_modes {delete persist truncate memory off}
-  foreach jmode $all_journal_modes {
-    do_test multiplex-5.6.1.$jmode {
-      sqlite3_multiplex_shutdown
-      multiplex_delete test.db
-      sqlite3 db test.db
-      db eval {
-        PRAGMA page_size = 1024;
-        PRAGMA auto_vacuum = off;
-      }
-      db eval "PRAGMA journal_mode = $jmode;"
-    } $jmode
-    do_test multiplex-5.6.2.$jmode {
-      execsql {
-        CREATE TABLE t1(a, b);
-        INSERT INTO t1 VALUES(1, randomblob(15000));
-        INSERT INTO t1 VALUES(2, randomblob(15000));
-        INSERT INTO t1 VALUES(3, randomblob(15000));
-        INSERT INTO t1 VALUES(4, randomblob(15000));
-        INSERT INTO t1 VALUES(5, randomblob(15000));
-      }
-      db close
-      sqlite3_multiplex_initialize "" 1
-      sqlite3 db test.db
-      multiplex_set db main 4096 16
-    } {SQLITE_OK}
-    do_test multiplex-5.6.3.$jmode {
-      catchsql {
-        INSERT INTO t1 VALUES(6, randomblob(15000));
-      }
-    } {1 {disk I/O error}}
-    do_test multiplex-5.6.4.$jmode {
-      db close
-    } {}
-  }
-}
-
 #-------------------------------------------------------------------------
 # Test that you can vacuum a multiplex'ed DB.  
 
@@ -575,8 +533,9 @@ ifcapable vacuum {
 sqlite3_multiplex_shutdown
 do_test multiplex-6.0.0 {
   multiplex_delete test.db
+  multiplex_delete test.x
   sqlite3_multiplex_initialize "" 1
-  sqlite3 db test.db
+  sqlite3 db test.x
   multiplex_set db main 4096 16
 } {SQLITE_OK}
 
@@ -592,8 +551,8 @@ do_test multiplex-6.1.0 {
     INSERT INTO t1 VALUES(2, randomblob($g_chunk_size));
   }
 } {}
-do_test multiplex-6.2.1 { file size [multiplex_name test.db 0] } [list $g_chunk_size]
-do_test multiplex-6.2.2 { file size [multiplex_name test.db 1] } [list $g_chunk_size]
+do_test multiplex-6.2.1 { file size [multiplex_name test.x 0] } [list $g_chunk_size]
+do_test multiplex-6.2.2 { file size [multiplex_name test.x 1] } [list $g_chunk_size]
 
 do_test multiplex-6.3.0 {
   execsql { VACUUM }
@@ -601,7 +560,7 @@ do_test multiplex-6.3.0 {
 
 do_test multiplex-6.99 {
   db close
-  multiplex_delete test.db
+  multiplex_delete test.x
   sqlite3_multiplex_shutdown
 } {SQLITE_OK}