/ Check-in [da118e02]
Login

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

Overview
Comment:Merge the nx-devkit changes into trunk. This includes the new SQLITE_FCNTL_VFSNAME file-control.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:da118e02c0576ce16f7a26663f59413316223d55
User & Date: drh 2011-12-14 18:33:13
Context
2011-12-15
17:44
Add stdio support to the quota VFS. check-in: 322bd15f user: drh tags: trunk
2011-12-14
18:33
Merge the nx-devkit changes into trunk. This includes the new SQLITE_FCNTL_VFSNAME file-control. check-in: da118e02 user: drh tags: trunk
18:28
Merge the VFSNAME file-control addition into the nx-devkit branch. check-in: 08c1dc51 user: drh tags: nx-devkit
00:37
Treat a zero return value from the Win32 APIs MultiByteToWideChar and WideCharToMultiByte as an error condition. check-in: c65e5a36 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/main.c.

   235    235   #endif
   236    236   
   237    237     /* Do extra initialization steps requested by the SQLITE_EXTRA_INIT
   238    238     ** compile-time option.
   239    239     */
   240    240   #ifdef SQLITE_EXTRA_INIT
   241    241     if( rc==SQLITE_OK && sqlite3GlobalConfig.isInit ){
   242         -    int SQLITE_EXTRA_INIT(void);
   243         -    rc = SQLITE_EXTRA_INIT();
          242  +    int SQLITE_EXTRA_INIT(const char*);
          243  +    rc = SQLITE_EXTRA_INIT(0);
   244    244     }
   245    245   #endif
   246    246   
   247    247     return rc;
   248    248   }
   249    249   
   250    250   /*

Changes to src/os_unix.c.

   202    202   /*
   203    203   ** The unixFile structure is subclass of sqlite3_file specific to the unix
   204    204   ** VFS implementations.
   205    205   */
   206    206   typedef struct unixFile unixFile;
   207    207   struct unixFile {
   208    208     sqlite3_io_methods const *pMethod;  /* Always the first entry */
          209  +  sqlite3_vfs *pVfs;                  /* The VFS that created this unixFile */
   209    210     unixInodeInfo *pInode;              /* Info about locks on this inode */
   210    211     int h;                              /* The file descriptor */
   211    212     unsigned char eFileLock;            /* The type of lock held on this fd */
   212    213     unsigned char ctrlFlags;            /* Behavioral bits.  UNIXFILE_* flags */
   213    214     int lastErrno;                      /* The unix errno from last I/O error */
   214    215     void *lockingContext;               /* Locking style specific state */
   215    216     UnixUnusedFd *pUnused;              /* Pre-allocated UnixUnusedFd */
................................................................................
  3529   3530         }else if( bPersist==0 ){
  3530   3531           pFile->ctrlFlags &= ~UNIXFILE_PERSIST_WAL;
  3531   3532         }else{
  3532   3533           pFile->ctrlFlags |= UNIXFILE_PERSIST_WAL;
  3533   3534         }
  3534   3535         return SQLITE_OK;
  3535   3536       }
         3537  +    case SQLITE_FCNTL_VFSNAME: {
         3538  +      *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName);
         3539  +      return SQLITE_OK;
         3540  +    }
  3536   3541   #ifndef NDEBUG
  3537   3542       /* The pager calls this method to signal that it has done
  3538   3543       ** a rollback and that the database is therefore unchanged and
  3539   3544       ** it hence it is OK for the transaction change counter to be
  3540   3545       ** unchanged.
  3541   3546       */
  3542   3547       case SQLITE_FCNTL_DB_UNCHANGED: {
................................................................................
  4556   4561   #endif
  4557   4562   
  4558   4563     /* No locking occurs in temporary files */
  4559   4564     assert( zFilename!=0 || noLock );
  4560   4565   
  4561   4566     OSTRACE(("OPEN    %-3d %s\n", h, zFilename));
  4562   4567     pNew->h = h;
         4568  +  pNew->pVfs = pVfs;
  4563   4569     pNew->zPath = zFilename;
  4564   4570     if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
  4565   4571       pNew->ctrlFlags = UNIXFILE_EXCL;
  4566   4572     }else{
  4567   4573       pNew->ctrlFlags = 0;
  4568   4574     }
  4569   4575     if( isReadOnly ){

Changes to src/os_win.c.

  2163   2163         int bPersist = *(int*)pArg;
  2164   2164         if( bPersist<0 ){
  2165   2165           *(int*)pArg = pFile->bPersistWal;
  2166   2166         }else{
  2167   2167           pFile->bPersistWal = bPersist!=0;
  2168   2168         }
  2169   2169         return SQLITE_OK;
         2170  +    }
         2171  +    case SQLITE_FCNTL_VFSNAME: {
         2172  +      *(char**)pArg = sqlite3_mprintf("win32");
         2173  +      return SQLITE_OK;
  2170   2174       }
  2171   2175       case SQLITE_FCNTL_SYNC_OMITTED: {
  2172   2176         return SQLITE_OK;
  2173   2177       }
  2174   2178       case SQLITE_FCNTL_WIN32_AV_RETRY: {
  2175   2179         int *a = (int*)pArg;
  2176   2180         if( a[0]>0 ){

Changes to src/shell.c.

  1401   1401     ".separator STRING      Change separator used by output mode and .import\n"
  1402   1402     ".show                  Show the current values for various settings\n"
  1403   1403     ".stats ON|OFF          Turn stats on or off\n"
  1404   1404     ".tables ?TABLE?        List names of tables\n"
  1405   1405     "                         If TABLE specified, only list tables matching\n"
  1406   1406     "                         LIKE pattern TABLE.\n"
  1407   1407     ".timeout MS            Try opening locked tables for MS milliseconds\n"
         1408  +  ".vfsname ?AUX?         Print the name of the VFS stack\n"
  1408   1409     ".width NUM1 NUM2 ...   Set column widths for \"column\" mode\n"
  1409   1410   ;
  1410   1411   
  1411   1412   static char zTimerHelp[] =
  1412   1413     ".timer ON|OFF          Turn the CPU timer measurement on or off\n"
  1413   1414   ;
  1414   1415   
................................................................................
  2343   2344       enableTimer = booleanValue(azArg[1]);
  2344   2345     }else
  2345   2346     
  2346   2347     if( c=='v' && strncmp(azArg[0], "version", n)==0 ){
  2347   2348       printf("SQLite %s %s\n" /*extra-version-info*/,
  2348   2349           sqlite3_libversion(), sqlite3_sourceid());
  2349   2350     }else
         2351  +
         2352  +  if( c=='v' && strncmp(azArg[0], "vfsname", n)==0 ){
         2353  +    const char *zDbName = nArg==2 ? azArg[1] : "main";
         2354  +    char *zVfsName = 0;
         2355  +    if( p->db ){
         2356  +      sqlite3_file_control(p->db, zDbName, SQLITE_FCNTL_VFSNAME, &zVfsName);
         2357  +      if( zVfsName ){
         2358  +        printf("%s\n", zVfsName);
         2359  +        sqlite3_free(zVfsName);
         2360  +      }
         2361  +    }
         2362  +  }else
  2350   2363   
  2351   2364     if( c=='w' && strncmp(azArg[0], "width", n)==0 && nArg>1 ){
  2352   2365       int j;
  2353   2366       assert( nArg<=ArraySize(azArg) );
  2354   2367       for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){
  2355   2368         p->colWidth[j-1] = atoi(azArg[j]);
  2356   2369       }

Changes to src/sqlite.h.in.

   767    767   ** WAL mode.  If the integer is -1, then it is overwritten with the current
   768    768   ** WAL persistence setting.
   769    769   **
   770    770   ** ^The [SQLITE_FCNTL_OVERWRITE] opcode is invoked by SQLite after opening
   771    771   ** a write transaction to indicate that, unless it is rolled back for some
   772    772   ** reason, the entire database file will be overwritten by the current 
   773    773   ** transaction. This is used by VACUUM operations.
          774  +**
          775  +** ^The [SQLITE_FCNTL_VFSNAME] opcode can be used to obtain the names of
          776  +** all [VFSes] in the VFS stack.  The names are of all VFS shims and the
          777  +** final bottom-level VFS are written into memory obtained from 
          778  +** [sqlite3_malloc()] and the result is stored in the char* variable
          779  +** that the fourth parameter of [sqlite3_file_control()] points to.
          780  +** The caller is responsible for freeing the memory when done.  As with
          781  +** all file-control actions, there is no guarantee that this will actually
          782  +** do anything.  Callers should initialize the char* variable to a NULL
          783  +** pointer in case this file-control is not implemented.  This file-control
          784  +** is intended for diagnostic use only.
   774    785   */
   775    786   #define SQLITE_FCNTL_LOCKSTATE        1
   776    787   #define SQLITE_GET_LOCKPROXYFILE      2
   777    788   #define SQLITE_SET_LOCKPROXYFILE      3
   778    789   #define SQLITE_LAST_ERRNO             4
   779    790   #define SQLITE_FCNTL_SIZE_HINT        5
   780    791   #define SQLITE_FCNTL_CHUNK_SIZE       6
   781    792   #define SQLITE_FCNTL_FILE_POINTER     7
   782    793   #define SQLITE_FCNTL_SYNC_OMITTED     8
   783    794   #define SQLITE_FCNTL_WIN32_AV_RETRY   9
   784    795   #define SQLITE_FCNTL_PERSIST_WAL     10
   785    796   #define SQLITE_FCNTL_OVERWRITE       11
          797  +#define SQLITE_FCNTL_VFSNAME         12
   786    798   
   787    799   /*
   788    800   ** CAPI3REF: Mutex Handle
   789    801   **
   790    802   ** The mutex module within SQLite defines [sqlite3_mutex] to be an
   791    803   ** abstract type for a mutex object.  The SQLite core never looks
   792    804   ** at the internal representation of an [sqlite3_mutex].  It only

Changes to src/test1.c.

  5231   5231     if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
  5232   5232     rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
  5233   5233     sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
  5234   5234     Tcl_AppendResult(interp, z, (char*)0);
  5235   5235     return TCL_OK;  
  5236   5236   }
  5237   5237   
         5238  +
         5239  +/*
         5240  +** tclcmd:   file_control_vfsname DB ?AUXDB?
         5241  +**
         5242  +** Return a string that describes the stack of VFSes.
         5243  +*/
         5244  +static int file_control_vfsname(
         5245  +  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
         5246  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
         5247  +  int objc,              /* Number of arguments */
         5248  +  Tcl_Obj *CONST objv[]  /* Command arguments */
         5249  +){
         5250  +  sqlite3 *db;
         5251  +  const char *zDbName = "main";
         5252  +  char *zVfsName = 0;
         5253  +
         5254  +  if( objc!=2 && objc!=3 ){
         5255  +    Tcl_AppendResult(interp, "wrong # args: should be \"",
         5256  +        Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
         5257  +    return TCL_ERROR;
         5258  +  }
         5259  +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
         5260  +    return TCL_ERROR;
         5261  +  }
         5262  +  if( objc==3 ){
         5263  +    zDbName = Tcl_GetString(objv[2]);
         5264  +  }
         5265  +  sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName);
         5266  +  Tcl_AppendResult(interp, zVfsName, (char*)0);
         5267  +  sqlite3_free(zVfsName);
         5268  +  return TCL_OK;  
         5269  +}
         5270  +
  5238   5271   
  5239   5272   /*
  5240   5273   ** tclcmd:   sqlite3_vfs_list
  5241   5274   **
  5242   5275   **   Return a tcl list containing the names of all registered vfs's.
  5243   5276   */
  5244   5277   static int vfs_list(
................................................................................
  6056   6089        { "file_control_test",          file_control_test,   0   },
  6057   6090        { "file_control_lasterrno_test", file_control_lasterrno_test,  0   },
  6058   6091        { "file_control_lockproxy_test", file_control_lockproxy_test,  0   },
  6059   6092        { "file_control_chunksize_test", file_control_chunksize_test,  0   },
  6060   6093        { "file_control_sizehint_test",  file_control_sizehint_test,   0   },
  6061   6094        { "file_control_win32_av_retry", file_control_win32_av_retry,  0   },
  6062   6095        { "file_control_persist_wal",    file_control_persist_wal,     0   },
         6096  +     { "file_control_vfsname",        file_control_vfsname,         0   },
  6063   6097        { "sqlite3_vfs_list",           vfs_list,     0   },
  6064   6098        { "sqlite3_create_function_v2", test_create_function_v2, 0 },
  6065   6099   
  6066   6100        /* Functions from os.h */
  6067   6101   #ifndef SQLITE_OMIT_UTF16
  6068   6102        { "add_test_collate",        test_collate, 0            },
  6069   6103        { "add_test_collate_needed", test_collate_needed, 0     },

Changes to src/test_multiplex.c.

    77     77   #define sqlite3_mutex_enter(X)
    78     78   #define sqlite3_mutex_try(X)      SQLITE_OK
    79     79   #define sqlite3_mutex_leave(X)
    80     80   #define sqlite3_mutex_held(X)     ((void)(X),1)
    81     81   #define sqlite3_mutex_notheld(X)  ((void)(X),1)
    82     82   #endif /* SQLITE_THREADSAFE==0 */
    83     83   
           84  +/* First chunk for rollback journal files */
           85  +#define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400
           86  +
    84     87   
    85     88   /************************ Shim Definitions ******************************/
    86     89   
    87     90   #ifndef SQLITE_MULTIPLEX_VFS_NAME
    88     91   # define SQLITE_MULTIPLEX_VFS_NAME "multiplex"
    89     92   #endif
    90     93   
................................................................................
    93     96   ** multiple of MAX_PAGE_SIZE.  We default it here to 2GiB less 64KiB.
    94     97   */
    95     98   #ifndef SQLITE_MULTIPLEX_CHUNK_SIZE
    96     99   # define SQLITE_MULTIPLEX_CHUNK_SIZE 2147418112
    97    100   #endif
    98    101   
    99    102   /* This used to be the default limit on number of chunks, but
   100         -** it is no longer enforced.  There is currently no limit to the
          103  +** it is no longer enforced. There is currently no limit to the
   101    104   ** number of chunks.
   102    105   **
   103    106   ** May be changed by calling the xFileControl() interface.
   104    107   */
   105    108   #ifndef SQLITE_MULTIPLEX_MAX_CHUNKS
   106    109   # define SQLITE_MULTIPLEX_MAX_CHUNKS 12
   107    110   #endif
................................................................................
   237    240       if( iChunk>0 ){
   238    241   #ifdef SQLITE_ENABLE_8_3_NAMES
   239    242         int i;
   240    243         for(i=n-1; i>0 && i>=n-4 && z[i]!='.'; i--){}
   241    244         if( i>=n-4 ) n = i+1;
   242    245         if( pGroup->flags & (SQLITE_OPEN_MAIN_JOURNAL|SQLITE_OPEN_TEMP_JOURNAL) ){
   243    246           /* The extensions on overflow files for main databases are 001, 002,
   244         -        ** 003 and so forth.  To avoid name collisions, add 100 to the 
   245         -        ** extensions of journal files so that they are 101, 102, 103, ....
          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, ....
   246    249           */
   247         -        iChunk += 100;
          250  +        iChunk += SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET;
   248    251         }
   249    252   #endif
   250    253         sqlite3_snprintf(4,&z[n],"%03d",iChunk);
   251    254       }
   252    255     }
   253    256     return SQLITE_OK;
   254    257   }
................................................................................
   260    263     multiplexGroup *pGroup,
   261    264     int iChunk,
   262    265     int *rc,
   263    266     int *pOutFlags
   264    267   ){
   265    268     sqlite3_file *pSubOpen = 0;
   266    269     sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;        /* Real VFS */
          270  +
          271  +#ifdef SQLITE_ENABLE_8_3_NAMES
          272  +  /* If JOURNAL_8_3_OFFSET is set to (say) 400, then any overflow files are 
          273  +  ** part of a database journal are named db.401, db.402, and so on. A 
          274  +  ** database may therefore not grow to larger than 400 chunks. Attempting
          275  +  ** to open chunk 401 indicates the database is full. */
          276  +  if( iChunk>=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){
          277  +    *rc = SQLITE_FULL;
          278  +    return 0;
          279  +  }
          280  +#endif
          281  +
   267    282     *rc = multiplexSubFilename(pGroup, iChunk);
   268    283     if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){
   269    284       pSubOpen = sqlite3_malloc( pOrigVfs->szOsFile );
   270    285       if( pSubOpen==0 ){
   271    286         *rc = SQLITE_NOMEM;
   272    287         return 0;
   273    288       }
................................................................................
   451    466         pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags);
   452    467       }
   453    468       if( pSubOpen ){
   454    469         int exists, rc2, rc3;
   455    470         sqlite3_int64 sz;
   456    471   
   457    472         rc2 = pSubOpen->pMethods->xFileSize(pSubOpen, &sz);
   458         -      if( rc2==SQLITE_OK ){
          473  +      if( rc2==SQLITE_OK && zName ){
   459    474           /* If the first overflow file exists and if the size of the main file
   460    475           ** is different from the chunk size, that means the chunk size is set
   461    476           ** set incorrectly.  So fix it.
   462    477           **
   463    478           ** Or, if the first overflow file does not exist and the main file is
   464    479           ** larger than the chunk size, that means the chunk size is too small.
   465    480           ** But we have no way of determining the intended chunk size, so 
................................................................................
   629    644       sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
   630    645       if( pSubOpen==0 ){
   631    646         rc = SQLITE_IOERR_WRITE;
   632    647       }else{
   633    648         rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst);
   634    649       }
   635    650     }else{
   636         -    while( iAmt > 0 ){
          651  +    while( rc==SQLITE_OK && iAmt>0 ){
   637    652         int i = (int)(iOfst / pGroup->szChunk);
   638    653         sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL);
   639    654         if( pSubOpen ){
   640    655           int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) -
   641    656                       pGroup->szChunk;
   642    657           if( extra<0 ) extra = 0;
   643    658           iAmt -= extra;
   644    659           rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt,
   645    660                                           iOfst % pGroup->szChunk);
   646         -        if( rc!=SQLITE_OK ) break;
   647    661           pBuf = (char *)pBuf + iAmt;
   648    662           iOfst += iAmt;
   649    663           iAmt = extra;
   650         -      }else{
   651         -        rc = SQLITE_IOERR_WRITE;
   652         -        break;
   653    664         }
   654    665       }
   655    666     }
   656    667     multiplexLeave();
   657    668     return rc;
   658    669   }
   659    670   
................................................................................
   841    852         /* no-op these */
   842    853         rc = SQLITE_OK;
   843    854         break;
   844    855       default:
   845    856         pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
   846    857         if( pSubOpen ){
   847    858           rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
          859  +        if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
          860  +         *(char**)pArg = sqlite3_mprintf("multiplex/%z", *(char**)pArg);
          861  +        }
   848    862         }
   849    863         break;
   850    864     }
   851    865     return rc;
   852    866   }
   853    867   
   854    868   /* Pass xSectorSize requests through to the original VFS unchanged.
   855    869   */
   856    870   static int multiplexSectorSize(sqlite3_file *pConn){
   857    871     multiplexConn *p = (multiplexConn*)pConn;
   858    872     int rc;
   859    873     sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL);
   860         -  if( pSubOpen ){
          874  +  if( pSubOpen && pSubOpen->pMethods->xSectorSize ){
   861    875       return pSubOpen->pMethods->xSectorSize(pSubOpen);
   862    876     }
   863    877     return DEFAULT_SECTOR_SIZE;
   864    878   }
   865    879   
   866    880   /* Pass xDeviceCharacteristics requests through to the original VFS unchanged.
   867    881   */

Changes to src/test_osinst.c.

   385    385   }
   386    386   
   387    387   /*
   388    388   ** File control method. For custom operations on an vfslog-file.
   389    389   */
   390    390   static int vfslogFileControl(sqlite3_file *pFile, int op, void *pArg){
   391    391     VfslogFile *p = (VfslogFile *)pFile;
   392         -  return p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
          392  +  int rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
          393  +  if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
          394  +    *(char**)pArg = sqlite3_mprintf("vfslog/%z", *(char**)pArg);
          395  +  }
          396  +  return rc;
   393    397   }
   394    398   
   395    399   /*
   396    400   ** Return the sector-size in bytes for an vfslog-file.
   397    401   */
   398    402   static int vfslogSectorSize(sqlite3_file *pFile){
   399    403     int rc;

Changes to src/test_quota.c.

   585    585     return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut);
   586    586   }
   587    587   
   588    588   /* Pass xFileControl requests through to the original VFS unchanged.
   589    589   */
   590    590   static int quotaFileControl(sqlite3_file *pConn, int op, void *pArg){
   591    591     sqlite3_file *pSubOpen = quotaSubOpen(pConn);
   592         -  return pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
          592  +  int rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
          593  +  if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
          594  +    *(char**)pArg = sqlite3_mprintf("quota/%z", *(char**)pArg);
          595  +  }
          596  +  return rc;
   593    597   }
   594    598   
   595    599   /* Pass xSectorSize requests through to the original VFS unchanged.
   596    600   */
   597    601   static int quotaSectorSize(sqlite3_file *pConn){
   598    602     sqlite3_file *pSubOpen = quotaSubOpen(pConn);
   599    603     return pSubOpen->pMethods->xSectorSize(pSubOpen);

Changes to src/test_vfstrace.c.

   467    467       case SQLITE_FCNTL_CHUNK_SIZE: {
   468    468         sqlite3_snprintf(sizeof(zBuf), zBuf, "CHUNK_SIZE,%d", *(int*)pArg);
   469    469         zOp = zBuf;
   470    470         break;
   471    471       }
   472    472       case SQLITE_FCNTL_FILE_POINTER: zOp = "FILE_POINTER";       break;
   473    473       case SQLITE_FCNTL_SYNC_OMITTED: zOp = "SYNC_OMITTED";       break;
          474  +    case SQLITE_FCNTL_WIN32_AV_RETRY: zOp = "WIN32_AV_RETRY";   break;
          475  +    case SQLITE_FCNTL_PERSIST_WAL:  zOp = "PERSIST_WAL";        break;
          476  +    case SQLITE_FCNTL_OVERWRITE:    zOp = "OVERWRITE";          break;
          477  +    case SQLITE_FCNTL_VFSNAME:      zOp = "VFSNAME";            break;
   474    478       case 0xca093fa0:                zOp = "DB_UNCHANGED";       break;
   475    479       default: {
   476    480         sqlite3_snprintf(sizeof zBuf, zBuf, "%d", op);
   477    481         zOp = zBuf;
   478    482         break;
   479    483       }
   480    484     }
   481    485     vfstrace_printf(pInfo, "%s.xFileControl(%s,%s)",
   482    486                     pInfo->zVfsName, p->zFName, zOp);
   483    487     rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
   484    488     vfstrace_print_errcode(pInfo, " -> %s\n", rc);
          489  +  if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
          490  +    *(char**)pArg = sqlite3_mprintf("vfstrace.%s/%z",
          491  +                                    pInfo->zVfsName, *(char**)pArg);
          492  +  }
   485    493     return rc;
   486    494   }
   487    495   
   488    496   /*
   489    497   ** Return the sector-size in bytes for an vfstrace-file.
   490    498   */
   491    499   static int vfstraceSectorSize(sqlite3_file *pFile){

Changes to test/multiplex3.test.

    51     51     foreach f [glob -nocomplain sv_test.*] { forcedelete $f }
    52     52     foreach f [glob -nocomplain test.*]    { forcecopy $f "sv_$f" }
    53     53   }
    54     54   proc multiplex_restore_db {} {
    55     55     foreach f [glob -nocomplain test.*]    {forcedelete $f}
    56     56     foreach f [glob -nocomplain sv_test.*] {forcecopy $f [string range $f 3 end]} }
    57     57   
    58         -
    59         -do_test 1.0 {
           58  +proc setup_and_save_db {} {
    60     59     multiplex_delete_db
    61     60     sqlite3 db file:test.db?8_3_names=1
    62     61     sqlite3_multiplex_control db main chunk_size [expr 256*1024]
    63     62     execsql {
    64     63       CREATE TABLE t1(a PRIMARY KEY, b);
    65     64       INSERT INTO t1 VALUES(randomblob(15), randomblob(2000));
    66     65       INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1;    --   2
................................................................................
    72     71       INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1;    -- 128
    73     72       INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1;    -- 256
    74     73       INSERT INTO t1 SELECT randomblob(15), randomblob(2000) FROM t1;    -- 512
    75     74     }
    76     75     set ::cksum1 [execsql {SELECT md5sum(a, b) FROM t1 ORDER BY a}]
    77     76     db close
    78     77     multiplex_save_db
    79         -} {}
           78  +}
    80     79   
           80  +do_test 1.0 { setup_and_save_db } {}
    81     81   do_faultsim_test 1 -prep {
    82     82     multiplex_restore_db
    83     83     sqlite3 db file:test.db?8_3_names=1
    84     84     sqlite3_multiplex_control db main chunk_size [expr 256*1024]
    85     85   } -body {
    86         -  execsql "UPDATE t1 SET a=randomblob(12), b=randomblob(1500) WHERE (rowid%32)=0"
           86  +  execsql {
           87  +    UPDATE t1 SET a=randomblob(12), b=randomblob(1500) WHERE (rowid%32)=0
           88  +  }
    87     89   } -test {
    88     90     faultsim_test_result {0 {}}
    89     91     if {$testrc!=0} {
    90     92       set cksum2 [execsql {SELECT md5sum(a, b) FROM t1 ORDER BY a}]
    91     93       if {$cksum2 != $::cksum1} { error "data mismatch" }
    92     94     }
    93     95   }
    94     96   
    95         -catch { db close }
           97  +#-------------------------------------------------------------------------
           98  +# The following tests verify that hot-journal rollback works. As follows:
           99  +#
          100  +#   1. Create a large database.
          101  +#   2. Set the pager cache to be very small.
          102  +#   3. Open a transaction. 
          103  +#   4. Run the following 100 times:
          104  +#      a. Update a row.
          105  +#      b. Copy all files on disk to a new db location, including the journal.
          106  +#      c. Verify that the new db can be opened and that the content matches
          107  +#         the database created in step 1 (proving the journal was rolled
          108  +#         back).
          109  +
          110  +do_test 2.0 { 
          111  +  setup_and_save_db
          112  +  multiplex_restore_db
          113  +  sqlite3 db file:test.db?8_3_names=1
          114  +  execsql { PRAGMA cache_size = 10 }
          115  +  execsql { BEGIN }
          116  +} {}
          117  +
          118  +for {set iTest 1} {$iTest<=100} {incr iTest} {
          119  +  do_test 2.$iTest {
          120  +    execsql { 
          121  +      UPDATE t1 SET a=randomblob(12), b=randomblob(1400) WHERE rowid=5*$iTest
          122  +    }
          123  +    foreach f [glob -nocomplain test.*] {forcecopy $f "xx_$f"}
          124  +    sqlite3 db2 file:xx_test.db?8_3_names=1
          125  +    execsql {SELECT md5sum(a, b) FROM t1 ORDER BY a} db2
          126  +  } $::cksum1
          127  +
          128  +  db2 close
          129  +}
    96    130   
          131  +catch { db close }
    97    132   sqlite3_multiplex_shutdown
    98    133   finish_test

Changes to test/quota.test.

    10     10   #***********************************************************************
    11     11   #
    12     12   
    13     13   set testdir [file dirname $argv0]
    14     14   source $testdir/tester.tcl
    15     15   source $testdir/malloc_common.tcl
    16     16   
           17  +unset -nocomplain defaultVfs
           18  +set defaultVfs [file_control_vfsname db]
    17     19   db close
    18     20   
    19     21   do_test quota-1.1 { sqlite3_quota_initialize nosuchvfs 1 } {SQLITE_ERROR}
    20     22   do_test quota-1.2 { sqlite3_quota_initialize "" 1 }        {SQLITE_OK}
    21     23   do_test quota-1.3 { sqlite3_quota_initialize "" 1 }        {SQLITE_MISUSE}
    22     24   do_test quota-1.4 { sqlite3_quota_shutdown }               {SQLITE_OK}
    23     25   
................................................................................
    69     71     execsql {
    70     72       CREATE TABLE t1(a, b);
    71     73       INSERT INTO t1 VALUES(1, randomblob(1100));
    72     74       INSERT INTO t1 VALUES(2, randomblob(1100));
    73     75     }
    74     76     set ::quota
    75     77   } {}
           78  +do_test quota-2.1.2.1 {
           79  +  file_control_vfsname db
           80  +} quota/$defaultVfs
    76     81   do_test quota-2.1.3 { file size test.db } {4096}
    77     82   do_test quota-2.1.4 {
    78     83     catchsql { INSERT INTO t1 VALUES(3, randomblob(1100)) }
    79     84   } {1 {database or disk is full}}
    80     85   do_test quota-2.1.5 { set ::quota } {4096 5120}
    81     86   
    82     87   set ::quota_request_ok 1