/ Check-in [eb95d2f7]
Login

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

Overview
Comment:Move the multiplexor changes in the experimental branch (check-ins [255d21499b] and [199f52bced]) into the nx-devkit branch.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | nx-devkit
Files: files | file ages | folders
SHA1: eb95d2f72c625bcfd0f8e9db1db2cb8799854b57
User & Date: drh 2011-12-13 15:02:54
Context
2011-12-13
15:25
Update the multiplex.test script to conform to that found in the "experimental" branch off of trunk. check-in: 2eb79efb user: drh tags: nx-devkit
15:02
Move the multiplexor changes in the experimental branch (check-ins [255d21499b] and [199f52bced]) into the nx-devkit branch. check-in: eb95d2f7 user: drh tags: nx-devkit
04:08
When an sqlite3_auto_extension() function fails, report back its actual error code, not the generic SQLITE_ERROR. check-in: ce55f250 user: drh tags: nx-devkit
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/test_multiplex.c.

   209    209   static int multiplexStrlen30(const char *z){
   210    210     const char *z2 = z;
   211    211     if( z==0 ) return 0;
   212    212     while( *z2 ){ z2++; }
   213    213     return 0x3fffffff & (int)(z2 - z);
   214    214   }
   215    215   
   216         -/*
   217         -** Create a temporary file name in zBuf.  zBuf must be big enough to
   218         -** hold at pOrigVfs->mxPathname characters.  This function departs
   219         -** from the traditional temporary name generation in the os_win
   220         -** and os_unix VFS in several ways, but is necessary so that 
   221         -** the file name is known for temporary files (like those used 
   222         -** during vacuum.)
   223         -**
   224         -** N.B. This routine assumes your underlying VFS is ok with using
   225         -** "/" as a directory seperator.  This is the default for UNIXs
   226         -** and is allowed (even mixed) for most versions of Windows.
   227         -*/
   228         -static int multiplexGetTempname(sqlite3_vfs *pOrigVfs, int nBuf, char *zBuf){
   229         -  static char zChars[] =
   230         -    "abcdefghijklmnopqrstuvwxyz"
   231         -    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   232         -    "0123456789";
   233         -  int i,j;
   234         -  int attempts = 0;
   235         -  int exists = 0;
   236         -  int rc = SQLITE_ERROR;
   237         -
   238         -  /* Check that the output buffer is large enough for 
   239         -  ** pVfs->mxPathname characters.
   240         -  */
   241         -  if( pOrigVfs->mxPathname <= nBuf ){
   242         -    char *zTmp = sqlite3_malloc(pOrigVfs->mxPathname);
   243         -    if( zTmp==0 ) return SQLITE_NOMEM;
   244         -
   245         -    /* sqlite3_temp_directory should always be less than
   246         -    ** pVfs->mxPathname characters.
   247         -    */
   248         -    sqlite3_snprintf(pOrigVfs->mxPathname,
   249         -                     zTmp,
   250         -                     "%s/",
   251         -                     sqlite3_temp_directory ? sqlite3_temp_directory : ".");
   252         -    rc = pOrigVfs->xFullPathname(pOrigVfs, zTmp, nBuf, zBuf);
   253         -    sqlite3_free(zTmp);
   254         -    if( rc ) return rc;
   255         -
   256         -    /* Check that the output buffer is large enough for the temporary file 
   257         -    ** name.
   258         -    */
   259         -    j = multiplexStrlen30(zBuf);
   260         -    if( (j + 8 + 1 + 3 + 1) <= nBuf ){
   261         -      /* Make 3 attempts to generate a unique name. */
   262         -      do {
   263         -        attempts++;
   264         -        sqlite3_randomness(8, &zBuf[j]);
   265         -        for(i=0; i<8; i++){
   266         -          unsigned char uc = (unsigned char)zBuf[j+i];
   267         -          zBuf[j+i] = (char)zChars[uc%(sizeof(zChars)-1)];
   268         -        }
   269         -        memcpy(&zBuf[j+i], ".tmp", 5);
   270         -        rc = pOrigVfs->xAccess(pOrigVfs, zBuf, SQLITE_ACCESS_EXISTS, &exists);
   271         -      } while ( (rc==SQLITE_OK) && exists && (attempts<3) );
   272         -      if( rc==SQLITE_OK && exists ){
   273         -        rc = SQLITE_ERROR;
   274         -      }
   275         -    }
   276         -  }
   277         -
   278         -  return rc;
   279         -}
   280         -
   281    216   /* Compute the filename for the iChunk-th chunk
   282    217   */
   283    218   static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
   284    219     if( iChunk>=pGroup->nReal ){
   285    220       struct multiplexReal *p;
   286    221       p = sqlite3_realloc(pGroup->aReal, (iChunk+1)*sizeof(*p));
   287    222       if( p==0 ){
   288    223         return SQLITE_NOMEM;
   289    224       }
   290    225       memset(&p[pGroup->nReal], 0, sizeof(p[0])*(iChunk+1-pGroup->nReal));
   291    226       pGroup->aReal = p;
   292    227       pGroup->nReal = iChunk+1;
   293    228     }
   294         -  if( pGroup->aReal[iChunk].z==0 ){
          229  +  if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){
   295    230       char *z;
   296    231       int n = pGroup->nName;
   297    232       pGroup->aReal[iChunk].z = z = sqlite3_malloc( n+4 );
   298    233       if( z==0 ){
   299    234         return SQLITE_NOMEM;
   300    235       }
   301    236       memcpy(z, pGroup->zName, n+1);
................................................................................
   457    392     sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
   458    393     int nName;
   459    394     int sz;
   460    395     char *zToFree = 0;
   461    396   
   462    397     UNUSED_PARAMETER(pVfs);
   463    398     memset(pConn, 0, pVfs->szOsFile);
          399  +  assert( zName || (flags & SQLITE_OPEN_DELETEONCLOSE) );
   464    400   
   465    401     /* We need to create a group structure and manage
   466    402     ** access to this group of files.
   467    403     */
   468    404     multiplexEnter();
   469    405     pMultiplexOpen = (multiplexConn*)pConn;
   470    406   
   471         -  /* If the second argument to this function is NULL, generate a 
   472         -  ** temporary file name to use.  This will be handled by the
   473         -  ** original xOpen method.  We just need to allocate space for
   474         -  ** it.
   475         -  */
   476         -  if( !zName ){
   477         -    zName = zToFree = sqlite3_malloc( pOrigVfs->mxPathname + 10 );
   478         -    if( zName==0 ){
   479         -      rc = SQLITE_NOMEM;
   480         -    }else{
   481         -      rc = multiplexGetTempname(pOrigVfs, pOrigVfs->mxPathname, zToFree);
   482         -    }
   483         -  }
   484         -
   485    407     if( rc==SQLITE_OK ){
   486    408       /* allocate space for group */
   487         -    nName = multiplexStrlen30(zName);
          409  +    nName = zName ? multiplexStrlen30(zName) : 0;
   488    410       sz = sizeof(multiplexGroup)                             /* multiplexGroup */
   489    411          + nName + 1;                                         /* zName */
   490    412       pGroup = sqlite3_malloc( sz );
   491    413       if( pGroup==0 ){
   492    414         rc = SQLITE_NOMEM;
   493    415       }
   494    416     }
   495    417   
   496    418     if( rc==SQLITE_OK ){
   497    419       /* assign pointers to extra space allocated */
   498         -    char *p = (char *)&pGroup[1];
   499         -    pMultiplexOpen->pGroup = pGroup;
   500    420       memset(pGroup, 0, sz);
          421  +    pMultiplexOpen->pGroup = pGroup;
   501    422       pGroup->bEnabled = -1;
   502    423       pGroup->szChunk = SQLITE_MULTIPLEX_CHUNK_SIZE;
   503         -    if( flags & SQLITE_OPEN_URI ){
   504         -      const char *zChunkSize;
   505         -      zChunkSize = sqlite3_uri_parameter(zName, "chunksize");
   506         -      if( zChunkSize ){
   507         -        unsigned int n = 0;
   508         -        int i;
   509         -        for(i=0; zChunkSize[i]>='0' && zChunkSize[i]<='9'; i++){
   510         -          n = n*10 + zChunkSize[i] - '0';
   511         -        }
   512         -        if( n>0 ){
   513         -          pGroup->szChunk = (n+0xffff)&~0xffff;
   514         -        }else{
   515         -          /* A zero or negative chunksize disabled the multiplexor */
   516         -          pGroup->bEnabled = 0;
          424  +
          425  +    if( zName ){
          426  +      char *p = (char *)&pGroup[1];
          427  +      if( flags & SQLITE_OPEN_URI ){
          428  +        const char *zChunkSize;
          429  +        zChunkSize = sqlite3_uri_parameter(zName, "chunksize");
          430  +        if( zChunkSize ){
          431  +          unsigned int n = 0;
          432  +          int i;
          433  +          for(i=0; zChunkSize[i]>='0' && zChunkSize[i]<='9'; i++){
          434  +            n = n*10 + zChunkSize[i] - '0';
          435  +          }
          436  +          if( n>0 ){
          437  +            pGroup->szChunk = (n+0xffff)&~0xffff;
          438  +          }else{
          439  +            /* A zero or negative chunksize disabled the multiplexor */
          440  +            pGroup->bEnabled = 0;
          441  +          }
   517    442           }
   518    443         }
          444  +      pGroup->zName = p;
          445  +      memcpy(pGroup->zName, zName, nName+1);
          446  +      pGroup->nName = nName;
   519    447       }
   520         -    pGroup->zName = p;
   521         -    /* save off base filename, name length, and original open flags  */
   522         -    memcpy(pGroup->zName, zName, nName+1);
   523         -    pGroup->nName = nName;
   524    448       pGroup->flags = flags;
   525    449       rc = multiplexSubFilename(pGroup, 1);
   526    450       if( rc==SQLITE_OK ){
   527    451         pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags);
   528    452       }
   529    453       if( pSubOpen ){
   530    454         int exists, rc2, rc3;
................................................................................
   792    716   /* Pass xFileSize requests through to the original VFS.
   793    717   ** Aggregate the size of all the chunks before returning.
   794    718   */
   795    719   static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
   796    720     multiplexConn *p = (multiplexConn*)pConn;
   797    721     multiplexGroup *pGroup = p->pGroup;
   798    722     int rc = SQLITE_OK;
   799         -  int rc2;
   800    723     int i;
   801         -  *pSize = 0;
   802    724     multiplexEnter();
   803    725     if( !pGroup->bEnabled ){
   804    726       sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
   805    727       if( pSubOpen==0 ){
   806         -      rc = SQLITE_OK;  /* If SubOpen failed, assume a size of zero */
          728  +      rc = SQLITE_IOERR_FSTAT;
   807    729       }else{
   808    730         rc = pSubOpen->pMethods->xFileSize(pSubOpen, pSize);
   809    731       }
   810    732     }else{
   811    733       sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;
   812    734       *pSize = 0;
   813         -    for(i=0; 1; i++){
          735  +    for(i=0; rc==SQLITE_OK; i++){
   814    736         sqlite3_file *pSubOpen = 0;
   815    737         int exists = 0;
   816    738         rc = multiplexSubFilename(pGroup, i);
   817         -      if( rc ){ rc = SQLITE_OK; /* Assume size of zero */ break; }
   818         -      if( pGroup->flags & SQLITE_OPEN_DELETEONCLOSE ){
   819         -        exists = pGroup->nReal>=i && pGroup->aReal[i].p!=0;
   820         -        rc2 = SQLITE_OK;
   821         -      }else{
   822         -        rc2 = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[i].z,
   823         -            SQLITE_ACCESS_EXISTS, &exists);
          739  +      if( rc!=SQLITE_OK ) break;
          740  +      if( pGroup->nReal>i && pGroup->aReal[i].p!=0 ){
          741  +        exists = 1;
          742  +      }else if( (pGroup->flags & SQLITE_OPEN_DELETEONCLOSE)==0 ){
          743  +        const char *zReal = pGroup->aReal[i].z;
          744  +        rc = pOrigVfs->xAccess(pOrigVfs, zReal, SQLITE_ACCESS_EXISTS, &exists);
   824    745         }
   825         -      if( rc2==SQLITE_OK && exists){
   826         -        /* if it exists, open it */
   827         -        pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
   828         -      }else{
   829         -        /* stop at first "gap" */
          746  +      if( exists==0 ){
          747  +        /* stop at first "gap" or IO error. */
   830    748           break;
   831    749         }
   832         -      if( pSubOpen ){
   833         -        sqlite3_int64 sz;
   834         -        rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
   835         -        if( rc2!=SQLITE_OK ){
   836         -          rc = rc2;
   837         -        }else{
   838         -          if( sz>pGroup->szChunk ){
   839         -            rc = SQLITE_IOERR_FSTAT;
   840         -          }
   841         -          *pSize += sz;
          750  +      if( rc==SQLITE_OK ){
          751  +        pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
          752  +      }
          753  +      assert( pSubOpen || rc!=SQLITE_OK );
          754  +      if( rc==SQLITE_OK ){
          755  +        sqlite3_int64 sz = 0;
          756  +        rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
          757  +        if( rc==SQLITE_OK && sz>pGroup->szChunk ){
          758  +          rc = SQLITE_IOERR_FSTAT;
   842    759           }
   843         -      }else{
   844         -        break;
          760  +        *pSize += sz;
   845    761         }
   846    762       }
   847    763     }
   848    764     multiplexLeave();
   849    765     return rc;
   850    766   }
   851    767   
................................................................................
  1188   1104     UNUSED_PARAMETER(objv);
  1189   1105   
  1190   1106     pResult = Tcl_NewObj();
  1191   1107     multiplexEnter();
  1192   1108     for(pGroup=gMultiplex.pGroups; pGroup; pGroup=pGroup->pNext){
  1193   1109       pGroupTerm = Tcl_NewObj();
  1194   1110   
  1195         -    pGroup->zName[pGroup->nName] = '\0';
  1196         -    Tcl_ListObjAppendElement(interp, pGroupTerm,
         1111  +    if( pGroup->zName ){
         1112  +      pGroup->zName[pGroup->nName] = '\0';
         1113  +      Tcl_ListObjAppendElement(interp, pGroupTerm,
  1197   1114             Tcl_NewStringObj(pGroup->zName, -1));
         1115  +    }else{
         1116  +      Tcl_ListObjAppendElement(interp, pGroupTerm, Tcl_NewObj());
         1117  +    }
  1198   1118       Tcl_ListObjAppendElement(interp, pGroupTerm,
  1199   1119             Tcl_NewIntObj(pGroup->nName));
  1200   1120       Tcl_ListObjAppendElement(interp, pGroupTerm,
  1201   1121             Tcl_NewIntObj(pGroup->flags));
  1202   1122   
  1203   1123       /* count number of chunks with open handles */
  1204   1124       for(i=0; i<pGroup->nReal; i++){