/ Check-in [cdbfb553]
Login

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

Overview
Comment:Add a file-control that will discover the name of the bottom-level VFS and all the shims in between.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | vfsname-filectrl
Files: files | file ages | folders
SHA1:cdbfb553af02d10767a905489d9dfc57fc6be54e
User & Date: drh 2011-12-14 17:53:36
Context
2011-12-14
18:28
Merge the VFSNAME file-control addition into the nx-devkit branch. check-in: 08c1dc51 user: drh tags: nx-devkit
17:53
Add a file-control that will discover the name of the bottom-level VFS and all the shims in between. Closed-Leaf check-in: cdbfb553 user: drh tags: vfsname-filectrl
01:38
Improvements to comments. No code changes. check-in: 08bbbd8e user: drh tags: nx-devkit
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

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.

  2140   2140         int bPersist = *(int*)pArg;
  2141   2141         if( bPersist<0 ){
  2142   2142           *(int*)pArg = pFile->bPersistWal;
  2143   2143         }else{
  2144   2144           pFile->bPersistWal = bPersist!=0;
  2145   2145         }
  2146   2146         return SQLITE_OK;
         2147  +    }
         2148  +    case SQLITE_FCNTL_VFSNAME: {
         2149  +      *(char**)pArg = sqlite3_mprintf("win32");
         2150  +      return SQLITE_OK;
  2147   2151       }
  2148   2152       case SQLITE_FCNTL_SYNC_OMITTED: {
  2149   2153         return SQLITE_OK;
  2150   2154       }
  2151   2155       case SQLITE_FCNTL_WIN32_AV_RETRY: {
  2152   2156         int *a = (int*)pArg;
  2153   2157         if( a[0]>0 ){

Changes to src/shell.c.

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

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.

  5204   5204     if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
  5205   5205     rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
  5206   5206     sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
  5207   5207     Tcl_AppendResult(interp, z, (char*)0);
  5208   5208     return TCL_OK;  
  5209   5209   }
  5210   5210   
         5211  +
         5212  +/*
         5213  +** tclcmd:   file_control_vfsname DB ?AUXDB?
         5214  +**
         5215  +** Return a string that describes the stack of VFSes.
         5216  +*/
         5217  +static int file_control_vfsname(
         5218  +  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
         5219  +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
         5220  +  int objc,              /* Number of arguments */
         5221  +  Tcl_Obj *CONST objv[]  /* Command arguments */
         5222  +){
         5223  +  sqlite3 *db;
         5224  +  const char *zDbName = "main";
         5225  +  char *zVfsName = 0;
         5226  +
         5227  +  if( objc!=2 && objc!=3 ){
         5228  +    Tcl_AppendResult(interp, "wrong # args: should be \"",
         5229  +        Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
         5230  +    return TCL_ERROR;
         5231  +  }
         5232  +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
         5233  +    return TCL_ERROR;
         5234  +  }
         5235  +  if( objc==3 ){
         5236  +    zDbName = Tcl_GetString(objv[2]);
         5237  +  }
         5238  +  sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName);
         5239  +  Tcl_AppendResult(interp, zVfsName, (char*)0);
         5240  +  sqlite3_free(zVfsName);
         5241  +  return TCL_OK;  
         5242  +}
         5243  +
  5211   5244   
  5212   5245   /*
  5213   5246   ** tclcmd:   sqlite3_vfs_list
  5214   5247   **
  5215   5248   **   Return a tcl list containing the names of all registered vfs's.
  5216   5249   */
  5217   5250   static int vfs_list(
................................................................................
  6028   6061        { "file_control_test",          file_control_test,   0   },
  6029   6062        { "file_control_lasterrno_test", file_control_lasterrno_test,  0   },
  6030   6063        { "file_control_lockproxy_test", file_control_lockproxy_test,  0   },
  6031   6064        { "file_control_chunksize_test", file_control_chunksize_test,  0   },
  6032   6065        { "file_control_sizehint_test",  file_control_sizehint_test,   0   },
  6033   6066        { "file_control_win32_av_retry", file_control_win32_av_retry,  0   },
  6034   6067        { "file_control_persist_wal",    file_control_persist_wal,     0   },
         6068  +     { "file_control_vfsname",        file_control_vfsname,         0   },
  6035   6069        { "sqlite3_vfs_list",           vfs_list,     0   },
  6036   6070        { "sqlite3_create_function_v2", test_create_function_v2, 0 },
  6037   6071   
  6038   6072        /* Functions from os.h */
  6039   6073   #ifndef SQLITE_OMIT_UTF16
  6040   6074        { "add_test_collate",        test_collate, 0            },
  6041   6075        { "add_test_collate_needed", test_collate_needed, 0     },

Changes to src/test_multiplex.c.

   852    852         /* no-op these */
   853    853         rc = SQLITE_OK;
   854    854         break;
   855    855       default:
   856    856         pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL);
   857    857         if( pSubOpen ){
   858    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  +        }
   859    862         }
   860    863         break;
   861    864     }
   862    865     return rc;
   863    866   }
   864    867   
   865    868   /* Pass xSectorSize requests through to the original VFS unchanged.

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/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