000001  /*
000002  ** 2010 October 28
000003  **
000004  ** The author disclaims copyright to this source code.  In place of
000005  ** a legal notice, here is a blessing:
000006  **
000007  **    May you do good and not evil.
000008  **    May you find forgiveness for yourself and forgive others.
000009  **    May you share freely, never taking more than you give.
000010  **
000011  *************************************************************************
000012  **
000013  ** This file contains a VFS "shim" - a layer that sits in between the
000014  ** pager and the real VFS - that breaks up a very large database file
000015  ** into two or more smaller files on disk.  This is useful, for example,
000016  ** in order to support large, multi-gigabyte databases on older filesystems
000017  ** that limit the maximum file size to 2 GiB.
000018  **
000019  ** USAGE:
000020  **
000021  ** Compile this source file and link it with your application.  Then
000022  ** at start-time, invoke the following procedure:
000023  **
000024  **   int sqlite3_multiplex_initialize(
000025  **      const char *zOrigVfsName,    // The underlying real VFS
000026  **      int makeDefault              // True to make multiplex the default VFS
000027  **   );
000028  **
000029  ** The procedure call above will create and register a new VFS shim named
000030  ** "multiplex".  The multiplex VFS will use the VFS named by zOrigVfsName to
000031  ** do the actual disk I/O.  (The zOrigVfsName parameter may be NULL, in 
000032  ** which case the default VFS at the moment sqlite3_multiplex_initialize()
000033  ** is called will be used as the underlying real VFS.)  
000034  **
000035  ** If the makeDefault parameter is TRUE then multiplex becomes the new
000036  ** default VFS.  Otherwise, you can use the multiplex VFS by specifying
000037  ** "multiplex" as the 4th parameter to sqlite3_open_v2() or by employing
000038  ** URI filenames and adding "vfs=multiplex" as a parameter to the filename
000039  ** URI.
000040  **
000041  ** The multiplex VFS allows databases up to 32 GiB in size.  But it splits
000042  ** the files up into smaller pieces, so that they will work even on 
000043  ** filesystems that do not support large files.  The default chunk size
000044  ** is 2147418112 bytes (which is 64KiB less than 2GiB) but this can be
000045  ** changed at compile-time by defining the SQLITE_MULTIPLEX_CHUNK_SIZE
000046  ** macro.  Use the "chunksize=NNNN" query parameter with a URI filename
000047  ** in order to select an alternative chunk size for individual connections
000048  ** at run-time.
000049  */
000050  #include "sqlite3.h"
000051  #include <string.h>
000052  #include <assert.h>
000053  #include <stdlib.h>
000054  #include "test_multiplex.h"
000055  
000056  #ifndef SQLITE_CORE
000057    #define SQLITE_CORE 1  /* Disable the API redefinition in sqlite3ext.h */
000058  #endif
000059  #include "sqlite3ext.h"
000060  
000061  /* 
000062  ** These should be defined to be the same as the values in 
000063  ** sqliteInt.h.  They are defined separately here so that
000064  ** the multiplex VFS shim can be built as a loadable 
000065  ** module.
000066  */
000067  #define UNUSED_PARAMETER(x) (void)(x)
000068  #define MAX_PAGE_SIZE       0x10000
000069  #define DEFAULT_SECTOR_SIZE 0x1000
000070  
000071  /* Maximum chunk number */
000072  #define MX_CHUNK_NUMBER 299
000073  
000074  /* First chunk for rollback journal files */
000075  #define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400
000076  #define SQLITE_MULTIPLEX_WAL_8_3_OFFSET 700
000077  
000078  
000079  /************************ Shim Definitions ******************************/
000080  
000081  #ifndef SQLITE_MULTIPLEX_VFS_NAME
000082  # define SQLITE_MULTIPLEX_VFS_NAME "multiplex"
000083  #endif
000084  
000085  /* This is the limit on the chunk size.  It may be changed by calling
000086  ** the xFileControl() interface.  It will be rounded up to a 
000087  ** multiple of MAX_PAGE_SIZE.  We default it here to 2GiB less 64KiB.
000088  */
000089  #ifndef SQLITE_MULTIPLEX_CHUNK_SIZE
000090  # define SQLITE_MULTIPLEX_CHUNK_SIZE 2147418112
000091  #endif
000092  
000093  /* This used to be the default limit on number of chunks, but
000094  ** it is no longer enforced. There is currently no limit to the
000095  ** number of chunks.
000096  **
000097  ** May be changed by calling the xFileControl() interface.
000098  */
000099  #ifndef SQLITE_MULTIPLEX_MAX_CHUNKS
000100  # define SQLITE_MULTIPLEX_MAX_CHUNKS 12
000101  #endif
000102  
000103  /************************ Object Definitions ******************************/
000104  
000105  /* Forward declaration of all object types */
000106  typedef struct multiplexGroup multiplexGroup;
000107  typedef struct multiplexConn multiplexConn;
000108  
000109  /*
000110  ** A "multiplex group" is a collection of files that collectively
000111  ** makeup a single SQLite DB file.  This allows the size of the DB
000112  ** to exceed the limits imposed by the file system.
000113  **
000114  ** There is an instance of the following object for each defined multiplex
000115  ** group.
000116  */
000117  struct multiplexGroup {
000118    struct multiplexReal {           /* For each chunk */
000119      sqlite3_file *p;                  /* Handle for the chunk */
000120      char *z;                          /* Name of this chunk */
000121    } *aReal;                        /* list of all chunks */
000122    int nReal;                       /* Number of chunks */
000123    char *zName;                     /* Base filename of this group */
000124    int nName;                       /* Length of base filename */
000125    int flags;                       /* Flags used for original opening */
000126    unsigned int szChunk;            /* Chunk size used for this group */
000127    unsigned char bEnabled;          /* TRUE to use Multiplex VFS for this file */
000128    unsigned char bTruncate;         /* TRUE to enable truncation of databases */
000129  };
000130  
000131  /*
000132  ** An instance of the following object represents each open connection
000133  ** to a file that is multiplex'ed.  This object is a 
000134  ** subclass of sqlite3_file.  The sqlite3_file object for the underlying
000135  ** VFS is appended to this structure.
000136  */
000137  struct multiplexConn {
000138    sqlite3_file base;              /* Base class - must be first */
000139    multiplexGroup *pGroup;         /* The underlying group of files */
000140  };
000141  
000142  /************************* Global Variables **********************************/
000143  /*
000144  ** All global variables used by this file are containing within the following
000145  ** gMultiplex structure.
000146  */
000147  static struct {
000148    /* The pOrigVfs is the real, original underlying VFS implementation.
000149    ** Most operations pass-through to the real VFS.  This value is read-only
000150    ** during operation.  It is only modified at start-time and thus does not
000151    ** require a mutex.
000152    */
000153    sqlite3_vfs *pOrigVfs;
000154  
000155    /* The sThisVfs is the VFS structure used by this shim.  It is initialized
000156    ** at start-time and thus does not require a mutex
000157    */
000158    sqlite3_vfs sThisVfs;
000159  
000160    /* The sIoMethods defines the methods used by sqlite3_file objects 
000161    ** associated with this shim.  It is initialized at start-time and does
000162    ** not require a mutex.
000163    **
000164    ** When the underlying VFS is called to open a file, it might return 
000165    ** either a version 1 or a version 2 sqlite3_file object.  This shim
000166    ** has to create a wrapper sqlite3_file of the same version.  Hence
000167    ** there are two I/O method structures, one for version 1 and the other
000168    ** for version 2.
000169    */
000170    sqlite3_io_methods sIoMethodsV1;
000171    sqlite3_io_methods sIoMethodsV2;
000172  
000173    /* True when this shim has been initialized.
000174    */
000175    int isInitialized;
000176  } gMultiplex;
000177  
000178  /************************* Utility Routines *********************************/
000179  /*
000180  ** Compute a string length that is limited to what can be stored in
000181  ** lower 30 bits of a 32-bit signed integer.
000182  **
000183  ** The value returned will never be negative.  Nor will it ever be greater
000184  ** than the actual length of the string.  For very long strings (greater
000185  ** than 1GiB) the value returned might be less than the true string length.
000186  */
000187  static int multiplexStrlen30(const char *z){
000188    const char *z2 = z;
000189    if( z==0 ) return 0;
000190    while( *z2 ){ z2++; }
000191    return 0x3fffffff & (int)(z2 - z);
000192  }
000193  
000194  /*
000195  ** Generate the file-name for chunk iChunk of the group with base name
000196  ** zBase. The file-name is written to buffer zOut before returning. Buffer
000197  ** zOut must be allocated by the caller so that it is at least (nBase+5)
000198  ** bytes in size, where nBase is the length of zBase, not including the
000199  ** nul-terminator.
000200  **
000201  ** If iChunk is 0 (or 400 - the number for the first journal file chunk),
000202  ** the output is a copy of the input string. Otherwise, if 
000203  ** SQLITE_ENABLE_8_3_NAMES is not defined or the input buffer does not contain
000204  ** a "." character, then the output is a copy of the input string with the 
000205  ** three-digit zero-padded decimal representation if iChunk appended to it. 
000206  ** For example:
000207  **
000208  **   zBase="test.db", iChunk=4  ->  zOut="test.db004"
000209  **
000210  ** Or, if SQLITE_ENABLE_8_3_NAMES is defined and the input buffer contains
000211  ** a "." character, then everything after the "." is replaced by the 
000212  ** three-digit representation of iChunk.
000213  **
000214  **   zBase="test.db", iChunk=4  ->  zOut="test.004"
000215  **
000216  ** The output buffer string is terminated by 2 0x00 bytes. This makes it safe
000217  ** to pass to sqlite3_uri_parameter() and similar.
000218  */
000219  static void multiplexFilename(
000220    const char *zBase,              /* Filename for chunk 0 */
000221    int nBase,                      /* Size of zBase in bytes (without \0) */
000222    int flags,                      /* Flags used to open file */
000223    int iChunk,                     /* Chunk to generate filename for */
000224    char *zOut                      /* Buffer to write generated name to */
000225  ){
000226    int n = nBase;
000227    memcpy(zOut, zBase, n+1);
000228    if( iChunk!=0 && iChunk<=MX_CHUNK_NUMBER ){
000229  #ifdef SQLITE_ENABLE_8_3_NAMES
000230      int i;
000231      for(i=n-1; i>0 && i>=n-4 && zOut[i]!='.'; i--){}
000232      if( i>=n-4 ) n = i+1;
000233      if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
000234        /* The extensions on overflow files for main databases are 001, 002,
000235        ** 003 and so forth.  To avoid name collisions, add 400 to the 
000236        ** extensions of journal files so that they are 401, 402, 403, ....
000237        */
000238        iChunk += SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET;
000239      }else if( flags & SQLITE_OPEN_WAL ){
000240        /* To avoid name collisions, add 700 to the 
000241        ** extensions of WAL files so that they are 701, 702, 703, ....
000242        */
000243        iChunk += SQLITE_MULTIPLEX_WAL_8_3_OFFSET;
000244      }
000245  #endif
000246      sqlite3_snprintf(4,&zOut[n],"%03d",iChunk);
000247      n += 3;
000248    }
000249  
000250    assert( zOut[n]=='\0' );
000251    zOut[n+1] = '\0';
000252  }
000253  
000254  /* Compute the filename for the iChunk-th chunk
000255  */
000256  static int multiplexSubFilename(multiplexGroup *pGroup, int iChunk){
000257    if( iChunk>=pGroup->nReal ){
000258      struct multiplexReal *p;
000259      p = sqlite3_realloc64(pGroup->aReal, (iChunk+1)*sizeof(*p));
000260      if( p==0 ){
000261        return SQLITE_NOMEM;
000262      }
000263      memset(&p[pGroup->nReal], 0, sizeof(p[0])*(iChunk+1-pGroup->nReal));
000264      pGroup->aReal = p;
000265      pGroup->nReal = iChunk+1;
000266    }
000267    if( pGroup->zName && pGroup->aReal[iChunk].z==0 ){
000268      char *z;
000269      int n = pGroup->nName;
000270      pGroup->aReal[iChunk].z = z = sqlite3_malloc64( n+5 );
000271      if( z==0 ){
000272        return SQLITE_NOMEM;
000273      }
000274      multiplexFilename(pGroup->zName, pGroup->nName, pGroup->flags, iChunk, z);
000275    }
000276    return SQLITE_OK;
000277  }
000278  
000279  /* Translate an sqlite3_file* that is really a multiplexGroup* into
000280  ** the sqlite3_file* for the underlying original VFS.
000281  **
000282  ** For chunk 0, the pGroup->flags determines whether or not a new file
000283  ** is created if it does not already exist.  For chunks 1 and higher, the
000284  ** file is created only if createFlag is 1.
000285  */
000286  static sqlite3_file *multiplexSubOpen(
000287    multiplexGroup *pGroup,    /* The multiplexor group */
000288    int iChunk,                /* Which chunk to open.  0==original file */
000289    int *rc,                   /* Result code in and out */
000290    int *pOutFlags,            /* Output flags */
000291    int createFlag             /* True to create if iChunk>0 */
000292  ){
000293    sqlite3_file *pSubOpen = 0;
000294    sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;        /* Real VFS */
000295  
000296  #ifdef SQLITE_ENABLE_8_3_NAMES
000297    /* If JOURNAL_8_3_OFFSET is set to (say) 400, then any overflow files are 
000298    ** part of a database journal are named db.401, db.402, and so on. A 
000299    ** database may therefore not grow to larger than 400 chunks. Attempting
000300    ** to open chunk 401 indicates the database is full. */
000301    if( iChunk>=SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET ){
000302      sqlite3_log(SQLITE_FULL, "multiplexed chunk overflow: %s", pGroup->zName);
000303      *rc = SQLITE_FULL;
000304      return 0;
000305    }
000306  #endif
000307  
000308    *rc = multiplexSubFilename(pGroup, iChunk);
000309    if( (*rc)==SQLITE_OK && (pSubOpen = pGroup->aReal[iChunk].p)==0 ){
000310      int flags, bExists;
000311      flags = pGroup->flags;
000312      if( createFlag ){
000313        flags |= SQLITE_OPEN_CREATE;
000314      }else if( iChunk==0 ){
000315        /* Fall through */
000316      }else if( pGroup->aReal[iChunk].z==0 ){
000317        return 0;
000318      }else{
000319        *rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[iChunk].z,
000320                                SQLITE_ACCESS_EXISTS, &bExists);
000321       if( *rc || !bExists ){
000322          if( *rc ){
000323            sqlite3_log(*rc, "multiplexor.xAccess failure on %s",
000324                        pGroup->aReal[iChunk].z);
000325          }
000326          return 0;
000327        }
000328        flags &= ~SQLITE_OPEN_CREATE;
000329      }
000330      pSubOpen = sqlite3_malloc64( pOrigVfs->szOsFile );
000331      if( pSubOpen==0 ){
000332        *rc = SQLITE_IOERR_NOMEM;
000333        return 0;
000334      }
000335      pGroup->aReal[iChunk].p = pSubOpen;
000336      *rc = pOrigVfs->xOpen(pOrigVfs, pGroup->aReal[iChunk].z, pSubOpen,
000337                            flags, pOutFlags);
000338      if( (*rc)!=SQLITE_OK ){
000339        sqlite3_log(*rc, "multiplexor.xOpen failure on %s",
000340                    pGroup->aReal[iChunk].z);
000341        sqlite3_free(pSubOpen);
000342        pGroup->aReal[iChunk].p = 0;
000343        return 0;
000344      }
000345    }
000346    return pSubOpen;
000347  }
000348  
000349  /*
000350  ** Return the size, in bytes, of chunk number iChunk.  If that chunk
000351  ** does not exist, then return 0.  This function does not distingish between
000352  ** non-existant files and zero-length files.
000353  */
000354  static sqlite3_int64 multiplexSubSize(
000355    multiplexGroup *pGroup,    /* The multiplexor group */
000356    int iChunk,                /* Which chunk to open.  0==original file */
000357    int *rc                    /* Result code in and out */
000358  ){
000359    sqlite3_file *pSub;
000360    sqlite3_int64 sz = 0;
000361  
000362    if( *rc ) return 0;
000363    pSub = multiplexSubOpen(pGroup, iChunk, rc, NULL, 0);
000364    if( pSub==0 ) return 0;
000365    *rc = pSub->pMethods->xFileSize(pSub, &sz);
000366    return sz;
000367  }    
000368  
000369  /*
000370  ** This is the implementation of the multiplex_control() SQL function.
000371  */
000372  static void multiplexControlFunc(
000373    sqlite3_context *context,
000374    int argc,
000375    sqlite3_value **argv
000376  ){
000377    int rc = SQLITE_OK;
000378    sqlite3 *db = sqlite3_context_db_handle(context);
000379    int op = 0;
000380    int iVal;
000381  
000382    if( !db || argc!=2 ){ 
000383      rc = SQLITE_ERROR; 
000384    }else{
000385      /* extract params */
000386      op = sqlite3_value_int(argv[0]);
000387      iVal = sqlite3_value_int(argv[1]);
000388      /* map function op to file_control op */
000389      switch( op ){
000390        case 1: 
000391          op = MULTIPLEX_CTRL_ENABLE; 
000392          break;
000393        case 2: 
000394          op = MULTIPLEX_CTRL_SET_CHUNK_SIZE; 
000395          break;
000396        case 3: 
000397          op = MULTIPLEX_CTRL_SET_MAX_CHUNKS; 
000398          break;
000399        default:
000400          rc = SQLITE_NOTFOUND;
000401          break;
000402      }
000403    }
000404    if( rc==SQLITE_OK ){
000405      rc = sqlite3_file_control(db, 0, op, &iVal);
000406    }
000407    sqlite3_result_error_code(context, rc);
000408  }
000409  
000410  /*
000411  ** This is the entry point to register the auto-extension for the 
000412  ** multiplex_control() function.
000413  */
000414  static int multiplexFuncInit(
000415    sqlite3 *db, 
000416    char **pzErrMsg, 
000417    const sqlite3_api_routines *pApi
000418  ){
000419    int rc;
000420    rc = sqlite3_create_function(db, "multiplex_control", 2, SQLITE_ANY, 
000421        0, multiplexControlFunc, 0, 0);
000422    return rc;
000423  }
000424  
000425  /*
000426  ** Close a single sub-file in the connection group.
000427  */
000428  static void multiplexSubClose(
000429    multiplexGroup *pGroup,
000430    int iChunk,
000431    sqlite3_vfs *pOrigVfs
000432  ){
000433    sqlite3_file *pSubOpen = pGroup->aReal[iChunk].p;
000434    if( pSubOpen ){
000435      pSubOpen->pMethods->xClose(pSubOpen);
000436      if( pOrigVfs && pGroup->aReal[iChunk].z ){
000437        pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
000438      }
000439      sqlite3_free(pGroup->aReal[iChunk].p);
000440    }
000441    sqlite3_free(pGroup->aReal[iChunk].z);
000442    memset(&pGroup->aReal[iChunk], 0, sizeof(pGroup->aReal[iChunk]));
000443  }
000444  
000445  /*
000446  ** Deallocate memory held by a multiplexGroup
000447  */
000448  static void multiplexFreeComponents(multiplexGroup *pGroup){
000449    int i;
000450    for(i=0; i<pGroup->nReal; i++){ multiplexSubClose(pGroup, i, 0); }
000451    sqlite3_free(pGroup->aReal);
000452    pGroup->aReal = 0;
000453    pGroup->nReal = 0;
000454  }
000455  
000456  
000457  /************************* VFS Method Wrappers *****************************/
000458  
000459  /*
000460  ** This is the xOpen method used for the "multiplex" VFS.
000461  **
000462  ** Most of the work is done by the underlying original VFS.  This method
000463  ** simply links the new file into the appropriate multiplex group if it is a
000464  ** file that needs to be tracked.
000465  */
000466  static int multiplexOpen(
000467    sqlite3_vfs *pVfs,         /* The multiplex VFS */
000468    const char *zName,         /* Name of file to be opened */
000469    sqlite3_file *pConn,       /* Fill in this file descriptor */
000470    int flags,                 /* Flags to control the opening */
000471    int *pOutFlags             /* Flags showing results of opening */
000472  ){
000473    int rc = SQLITE_OK;                  /* Result code */
000474    multiplexConn *pMultiplexOpen;       /* The new multiplex file descriptor */
000475    multiplexGroup *pGroup = 0;          /* Corresponding multiplexGroup object */
000476    sqlite3_file *pSubOpen = 0;                    /* Real file descriptor */
000477    sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
000478    int nName = 0;
000479    int sz = 0;
000480    char *zToFree = 0;
000481  
000482    UNUSED_PARAMETER(pVfs);
000483    memset(pConn, 0, pVfs->szOsFile);
000484    assert( zName || (flags & SQLITE_OPEN_DELETEONCLOSE) );
000485  
000486    /* We need to create a group structure and manage
000487    ** access to this group of files.
000488    */
000489    pMultiplexOpen = (multiplexConn*)pConn;
000490  
000491    if( rc==SQLITE_OK ){
000492      /* allocate space for group */
000493      nName = zName ? multiplexStrlen30(zName) : 0;
000494      sz = sizeof(multiplexGroup)                             /* multiplexGroup */
000495         + nName + 1;                                         /* zName */
000496      pGroup = sqlite3_malloc64( sz );
000497      if( pGroup==0 ){
000498        rc = SQLITE_NOMEM;
000499      }
000500    }
000501  
000502    if( rc==SQLITE_OK ){
000503      const char *zUri = (flags & SQLITE_OPEN_URI) ? zName : 0;
000504      /* assign pointers to extra space allocated */
000505      memset(pGroup, 0, sz);
000506      pMultiplexOpen->pGroup = pGroup;
000507      pGroup->bEnabled = (unsigned char)-1;
000508      pGroup->bTruncate = (unsigned char)sqlite3_uri_boolean(zUri, "truncate", 
000509                                     (flags & SQLITE_OPEN_MAIN_DB)==0);
000510      pGroup->szChunk = (int)sqlite3_uri_int64(zUri, "chunksize",
000511                                          SQLITE_MULTIPLEX_CHUNK_SIZE);
000512      pGroup->szChunk = (pGroup->szChunk+0xffff)&~0xffff;
000513      if( zName ){
000514        char *p = (char *)&pGroup[1];
000515        pGroup->zName = p;
000516        memcpy(pGroup->zName, zName, nName+1);
000517        pGroup->nName = nName;
000518      }
000519      if( pGroup->bEnabled ){
000520        /* Make sure that the chunksize is such that the pending byte does not
000521        ** falls at the end of a chunk.  A region of up to 64K following
000522        ** the pending byte is never written, so if the pending byte occurs
000523        ** near the end of a chunk, that chunk will be too small. */
000524  #ifndef SQLITE_OMIT_WSD
000525        extern int sqlite3PendingByte;
000526  #else
000527        int sqlite3PendingByte = 0x40000000;
000528  #endif
000529        while( (sqlite3PendingByte % pGroup->szChunk)>=(pGroup->szChunk-65536) ){
000530          pGroup->szChunk += 65536;
000531        }
000532      }
000533      pGroup->flags = flags;
000534      rc = multiplexSubFilename(pGroup, 1);
000535      if( rc==SQLITE_OK ){
000536        pSubOpen = multiplexSubOpen(pGroup, 0, &rc, pOutFlags, 0);
000537        if( pSubOpen==0 && rc==SQLITE_OK ) rc = SQLITE_CANTOPEN;
000538      }
000539      if( rc==SQLITE_OK ){
000540        sqlite3_int64 sz64;
000541  
000542        rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz64);
000543        if( rc==SQLITE_OK && zName ){
000544          int bExists;
000545          if( flags & SQLITE_OPEN_MASTER_JOURNAL ){
000546            pGroup->bEnabled = 0;
000547          }else
000548          if( sz64==0 ){
000549            if( flags & SQLITE_OPEN_MAIN_JOURNAL ){
000550              /* If opening a main journal file and the first chunk is zero
000551              ** bytes in size, delete any subsequent chunks from the 
000552              ** file-system. */
000553              int iChunk = 1;
000554              do {
000555                rc = pOrigVfs->xAccess(pOrigVfs, 
000556                    pGroup->aReal[iChunk].z, SQLITE_ACCESS_EXISTS, &bExists
000557                );
000558                if( rc==SQLITE_OK && bExists ){
000559                  rc = pOrigVfs->xDelete(pOrigVfs, pGroup->aReal[iChunk].z, 0);
000560                  if( rc==SQLITE_OK ){
000561                    rc = multiplexSubFilename(pGroup, ++iChunk);
000562                  }
000563                }
000564              }while( rc==SQLITE_OK && bExists );
000565            }
000566          }else{
000567            /* If the first overflow file exists and if the size of the main file
000568            ** is different from the chunk size, that means the chunk size is set
000569            ** set incorrectly.  So fix it.
000570            **
000571            ** Or, if the first overflow file does not exist and the main file is
000572            ** larger than the chunk size, that means the chunk size is too small.
000573            ** But we have no way of determining the intended chunk size, so 
000574            ** just disable the multiplexor all togethre.
000575            */
000576            rc = pOrigVfs->xAccess(pOrigVfs, pGroup->aReal[1].z,
000577                SQLITE_ACCESS_EXISTS, &bExists);
000578            bExists = multiplexSubSize(pGroup, 1, &rc)>0;
000579            if( rc==SQLITE_OK && bExists && sz64==(sz64&0xffff0000) && sz64>0
000580                && sz64!=pGroup->szChunk ){
000581              pGroup->szChunk = (int)sz64;
000582            }else if( rc==SQLITE_OK && !bExists && sz64>pGroup->szChunk ){
000583              pGroup->bEnabled = 0;
000584            }
000585          }
000586        }
000587      }
000588  
000589      if( rc==SQLITE_OK ){
000590        if( pSubOpen->pMethods->iVersion==1 ){
000591          pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1;
000592        }else{
000593          pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV2;
000594        }
000595      }else{
000596        multiplexFreeComponents(pGroup);
000597        sqlite3_free(pGroup);
000598      }
000599    }
000600    sqlite3_free(zToFree);
000601    return rc;
000602  }
000603  
000604  /*
000605  ** This is the xDelete method used for the "multiplex" VFS.
000606  ** It attempts to delete the filename specified.
000607  */
000608  static int multiplexDelete(
000609    sqlite3_vfs *pVfs,         /* The multiplex VFS */
000610    const char *zName,         /* Name of file to delete */
000611    int syncDir
000612  ){
000613    int rc;
000614    sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
000615    rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
000616    if( rc==SQLITE_OK ){
000617      /* If the main chunk was deleted successfully, also delete any subsequent
000618      ** chunks - starting with the last (highest numbered). 
000619      */
000620      int nName = (int)strlen(zName);
000621      char *z;
000622      z = sqlite3_malloc64(nName + 5);
000623      if( z==0 ){
000624        rc = SQLITE_IOERR_NOMEM;
000625      }else{
000626        int iChunk = 0;
000627        int bExists;
000628        do{
000629          multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, ++iChunk, z);
000630          rc = pOrigVfs->xAccess(pOrigVfs, z, SQLITE_ACCESS_EXISTS, &bExists);
000631        }while( rc==SQLITE_OK && bExists );
000632        while( rc==SQLITE_OK && iChunk>1 ){
000633          multiplexFilename(zName, nName, SQLITE_OPEN_MAIN_JOURNAL, --iChunk, z);
000634          rc = pOrigVfs->xDelete(pOrigVfs, z, syncDir);
000635        }
000636        if( rc==SQLITE_OK ){
000637          iChunk = 0;
000638          do{
000639            multiplexFilename(zName, nName, SQLITE_OPEN_WAL, ++iChunk, z);
000640            rc = pOrigVfs->xAccess(pOrigVfs, z, SQLITE_ACCESS_EXISTS, &bExists);
000641          }while( rc==SQLITE_OK && bExists );
000642          while( rc==SQLITE_OK && iChunk>1 ){
000643            multiplexFilename(zName, nName, SQLITE_OPEN_WAL, --iChunk, z);
000644            rc = pOrigVfs->xDelete(pOrigVfs, z, syncDir);
000645          }
000646        }
000647      }
000648      sqlite3_free(z);
000649    }
000650    return rc;
000651  }
000652  
000653  static int multiplexAccess(sqlite3_vfs *a, const char *b, int c, int *d){
000654    return gMultiplex.pOrigVfs->xAccess(gMultiplex.pOrigVfs, b, c, d);
000655  }
000656  static int multiplexFullPathname(sqlite3_vfs *a, const char *b, int c, char *d){
000657    return gMultiplex.pOrigVfs->xFullPathname(gMultiplex.pOrigVfs, b, c, d);
000658  }
000659  static void *multiplexDlOpen(sqlite3_vfs *a, const char *b){
000660    return gMultiplex.pOrigVfs->xDlOpen(gMultiplex.pOrigVfs, b);
000661  }
000662  static void multiplexDlError(sqlite3_vfs *a, int b, char *c){
000663    gMultiplex.pOrigVfs->xDlError(gMultiplex.pOrigVfs, b, c);
000664  }
000665  static void (*multiplexDlSym(sqlite3_vfs *a, void *b, const char *c))(void){
000666    return gMultiplex.pOrigVfs->xDlSym(gMultiplex.pOrigVfs, b, c);
000667  }
000668  static void multiplexDlClose(sqlite3_vfs *a, void *b){
000669    gMultiplex.pOrigVfs->xDlClose(gMultiplex.pOrigVfs, b);
000670  }
000671  static int multiplexRandomness(sqlite3_vfs *a, int b, char *c){
000672    return gMultiplex.pOrigVfs->xRandomness(gMultiplex.pOrigVfs, b, c);
000673  }
000674  static int multiplexSleep(sqlite3_vfs *a, int b){
000675    return gMultiplex.pOrigVfs->xSleep(gMultiplex.pOrigVfs, b);
000676  }
000677  static int multiplexCurrentTime(sqlite3_vfs *a, double *b){
000678    return gMultiplex.pOrigVfs->xCurrentTime(gMultiplex.pOrigVfs, b);
000679  }
000680  static int multiplexGetLastError(sqlite3_vfs *a, int b, char *c){
000681    if( gMultiplex.pOrigVfs->xGetLastError ){
000682      return gMultiplex.pOrigVfs->xGetLastError(gMultiplex.pOrigVfs, b, c);
000683    }else{
000684      return 0;
000685    }
000686  }
000687  static int multiplexCurrentTimeInt64(sqlite3_vfs *a, sqlite3_int64 *b){
000688    return gMultiplex.pOrigVfs->xCurrentTimeInt64(gMultiplex.pOrigVfs, b);
000689  }
000690  
000691  /************************ I/O Method Wrappers *******************************/
000692  
000693  /* xClose requests get passed through to the original VFS.
000694  ** We loop over all open chunk handles and close them.
000695  ** The group structure for this file is unlinked from 
000696  ** our list of groups and freed.
000697  */
000698  static int multiplexClose(sqlite3_file *pConn){
000699    multiplexConn *p = (multiplexConn*)pConn;
000700    multiplexGroup *pGroup = p->pGroup;
000701    int rc = SQLITE_OK;
000702    multiplexFreeComponents(pGroup);
000703    sqlite3_free(pGroup);
000704    return rc;
000705  }
000706  
000707  /* Pass xRead requests thru to the original VFS after
000708  ** determining the correct chunk to operate on.
000709  ** Break up reads across chunk boundaries.
000710  */
000711  static int multiplexRead(
000712    sqlite3_file *pConn,
000713    void *pBuf,
000714    int iAmt,
000715    sqlite3_int64 iOfst
000716  ){
000717    multiplexConn *p = (multiplexConn*)pConn;
000718    multiplexGroup *pGroup = p->pGroup;
000719    int rc = SQLITE_OK;
000720    if( !pGroup->bEnabled ){
000721      sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
000722      if( pSubOpen==0 ){
000723        rc = SQLITE_IOERR_READ;
000724      }else{
000725        rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst);
000726      }
000727    }else{
000728      while( iAmt > 0 ){
000729        int i = (int)(iOfst / pGroup->szChunk);
000730        sqlite3_file *pSubOpen;
000731        pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL, 1);
000732        if( pSubOpen ){
000733          int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) - pGroup->szChunk;
000734          if( extra<0 ) extra = 0;
000735          iAmt -= extra;
000736          rc = pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt,
000737                                         iOfst % pGroup->szChunk);
000738          if( rc!=SQLITE_OK ) break;
000739          pBuf = (char *)pBuf + iAmt;
000740          iOfst += iAmt;
000741          iAmt = extra;
000742        }else{
000743          rc = SQLITE_IOERR_READ;
000744          break;
000745        }
000746      }
000747    }
000748  
000749    return rc;
000750  }
000751  
000752  /* Pass xWrite requests thru to the original VFS after
000753  ** determining the correct chunk to operate on.
000754  ** Break up writes across chunk boundaries.
000755  */
000756  static int multiplexWrite(
000757    sqlite3_file *pConn,
000758    const void *pBuf,
000759    int iAmt,
000760    sqlite3_int64 iOfst
000761  ){
000762    multiplexConn *p = (multiplexConn*)pConn;
000763    multiplexGroup *pGroup = p->pGroup;
000764    int rc = SQLITE_OK;
000765    if( !pGroup->bEnabled ){
000766      sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
000767      if( pSubOpen==0 ){
000768        rc = SQLITE_IOERR_WRITE;
000769      }else{
000770        rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt, iOfst);
000771      }
000772    }else{
000773      while( rc==SQLITE_OK && iAmt>0 ){
000774        int i = (int)(iOfst / pGroup->szChunk);
000775        sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, i, &rc, NULL, 1);
000776        if( pSubOpen ){
000777          int extra = ((int)(iOfst % pGroup->szChunk) + iAmt) -
000778                      pGroup->szChunk;
000779          if( extra<0 ) extra = 0;
000780          iAmt -= extra;
000781          rc = pSubOpen->pMethods->xWrite(pSubOpen, pBuf, iAmt,
000782                                          iOfst % pGroup->szChunk);
000783          pBuf = (char *)pBuf + iAmt;
000784          iOfst += iAmt;
000785          iAmt = extra;
000786        }
000787      }
000788    }
000789    return rc;
000790  }
000791  
000792  /* Pass xTruncate requests thru to the original VFS after
000793  ** determining the correct chunk to operate on.  Delete any
000794  ** chunks above the truncate mark.
000795  */
000796  static int multiplexTruncate(sqlite3_file *pConn, sqlite3_int64 size){
000797    multiplexConn *p = (multiplexConn*)pConn;
000798    multiplexGroup *pGroup = p->pGroup;
000799    int rc = SQLITE_OK;
000800    if( !pGroup->bEnabled ){
000801      sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
000802      if( pSubOpen==0 ){
000803        rc = SQLITE_IOERR_TRUNCATE;
000804      }else{
000805        rc = pSubOpen->pMethods->xTruncate(pSubOpen, size);
000806      }
000807    }else{
000808      int i;
000809      int iBaseGroup = (int)(size / pGroup->szChunk);
000810      sqlite3_file *pSubOpen;
000811      sqlite3_vfs *pOrigVfs = gMultiplex.pOrigVfs;   /* Real VFS */
000812      /* delete the chunks above the truncate limit */
000813      for(i = pGroup->nReal-1; i>iBaseGroup && rc==SQLITE_OK; i--){
000814        if( pGroup->bTruncate ){
000815          multiplexSubClose(pGroup, i, pOrigVfs);
000816        }else{
000817          pSubOpen = multiplexSubOpen(pGroup, i, &rc, 0, 0);
000818          if( pSubOpen ){
000819            rc = pSubOpen->pMethods->xTruncate(pSubOpen, 0);
000820          }
000821        }
000822      }
000823      if( rc==SQLITE_OK ){
000824        pSubOpen = multiplexSubOpen(pGroup, iBaseGroup, &rc, 0, 0);
000825        if( pSubOpen ){
000826          rc = pSubOpen->pMethods->xTruncate(pSubOpen, size % pGroup->szChunk);
000827        }
000828      }
000829      if( rc ) rc = SQLITE_IOERR_TRUNCATE;
000830    }
000831    return rc;
000832  }
000833  
000834  /* Pass xSync requests through to the original VFS without change
000835  */
000836  static int multiplexSync(sqlite3_file *pConn, int flags){
000837    multiplexConn *p = (multiplexConn*)pConn;
000838    multiplexGroup *pGroup = p->pGroup;
000839    int rc = SQLITE_OK;
000840    int i;
000841    for(i=0; i<pGroup->nReal; i++){
000842      sqlite3_file *pSubOpen = pGroup->aReal[i].p;
000843      if( pSubOpen ){
000844        int rc2 = pSubOpen->pMethods->xSync(pSubOpen, flags);
000845        if( rc2!=SQLITE_OK ) rc = rc2;
000846      }
000847    }
000848    return rc;
000849  }
000850  
000851  /* Pass xFileSize requests through to the original VFS.
000852  ** Aggregate the size of all the chunks before returning.
000853  */
000854  static int multiplexFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){
000855    multiplexConn *p = (multiplexConn*)pConn;
000856    multiplexGroup *pGroup = p->pGroup;
000857    int rc = SQLITE_OK;
000858    int i;
000859    if( !pGroup->bEnabled ){
000860      sqlite3_file *pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
000861      if( pSubOpen==0 ){
000862        rc = SQLITE_IOERR_FSTAT;
000863      }else{
000864        rc = pSubOpen->pMethods->xFileSize(pSubOpen, pSize);
000865      }
000866    }else{
000867      *pSize = 0;
000868      for(i=0; rc==SQLITE_OK; i++){
000869        sqlite3_int64 sz = multiplexSubSize(pGroup, i, &rc);
000870        if( sz==0 ) break;
000871        *pSize = i*(sqlite3_int64)pGroup->szChunk + sz;
000872      }
000873    }
000874    return rc;
000875  }
000876  
000877  /* Pass xLock requests through to the original VFS unchanged.
000878  */
000879  static int multiplexLock(sqlite3_file *pConn, int lock){
000880    multiplexConn *p = (multiplexConn*)pConn;
000881    int rc;
000882    sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
000883    if( pSubOpen ){
000884      return pSubOpen->pMethods->xLock(pSubOpen, lock);
000885    }
000886    return SQLITE_BUSY;
000887  }
000888  
000889  /* Pass xUnlock requests through to the original VFS unchanged.
000890  */
000891  static int multiplexUnlock(sqlite3_file *pConn, int lock){
000892    multiplexConn *p = (multiplexConn*)pConn;
000893    int rc;
000894    sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
000895    if( pSubOpen ){
000896      return pSubOpen->pMethods->xUnlock(pSubOpen, lock);
000897    }
000898    return SQLITE_IOERR_UNLOCK;
000899  }
000900  
000901  /* Pass xCheckReservedLock requests through to the original VFS unchanged.
000902  */
000903  static int multiplexCheckReservedLock(sqlite3_file *pConn, int *pResOut){
000904    multiplexConn *p = (multiplexConn*)pConn;
000905    int rc;
000906    sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
000907    if( pSubOpen ){
000908      return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut);
000909    }
000910    return SQLITE_IOERR_CHECKRESERVEDLOCK;
000911  }
000912  
000913  /* Pass xFileControl requests through to the original VFS unchanged,
000914  ** except for any MULTIPLEX_CTRL_* requests here.
000915  */
000916  static int multiplexFileControl(sqlite3_file *pConn, int op, void *pArg){
000917    multiplexConn *p = (multiplexConn*)pConn;
000918    multiplexGroup *pGroup = p->pGroup;
000919    int rc = SQLITE_ERROR;
000920    sqlite3_file *pSubOpen;
000921  
000922    if( !gMultiplex.isInitialized ) return SQLITE_MISUSE;
000923    switch( op ){
000924      case MULTIPLEX_CTRL_ENABLE:
000925        if( pArg ) {
000926          int bEnabled = *(int *)pArg;
000927          pGroup->bEnabled = (unsigned char)bEnabled;
000928          rc = SQLITE_OK;
000929        }
000930        break;
000931      case MULTIPLEX_CTRL_SET_CHUNK_SIZE:
000932        if( pArg ) {
000933          unsigned int szChunk = *(unsigned*)pArg;
000934          if( szChunk<1 ){
000935            rc = SQLITE_MISUSE;
000936          }else{
000937            /* Round up to nearest multiple of MAX_PAGE_SIZE. */
000938            szChunk = (szChunk + (MAX_PAGE_SIZE-1));
000939            szChunk &= ~(MAX_PAGE_SIZE-1);
000940            pGroup->szChunk = szChunk;
000941            rc = SQLITE_OK;
000942          }
000943        }
000944        break;
000945      case MULTIPLEX_CTRL_SET_MAX_CHUNKS:
000946        rc = SQLITE_OK;
000947        break;
000948      case SQLITE_FCNTL_SIZE_HINT:
000949      case SQLITE_FCNTL_CHUNK_SIZE:
000950        /* no-op these */
000951        rc = SQLITE_OK;
000952        break;
000953      case SQLITE_FCNTL_PRAGMA: {
000954        char **aFcntl = (char**)pArg;
000955        /*
000956        ** EVIDENCE-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA
000957        ** file control is an array of pointers to strings (char**) in which the
000958        ** second element of the array is the name of the pragma and the third
000959        ** element is the argument to the pragma or NULL if the pragma has no
000960        ** argument.
000961        */
000962        if( aFcntl[1] && sqlite3_stricmp(aFcntl[1],"multiplex_truncate")==0 ){
000963          if( aFcntl[2] && aFcntl[2][0] ){
000964            if( sqlite3_stricmp(aFcntl[2], "on")==0
000965             || sqlite3_stricmp(aFcntl[2], "1")==0 ){
000966              pGroup->bTruncate = 1;
000967            }else
000968            if( sqlite3_stricmp(aFcntl[2], "off")==0
000969             || sqlite3_stricmp(aFcntl[2], "0")==0 ){
000970              pGroup->bTruncate = 0;
000971            }
000972          }
000973          /* EVIDENCE-OF: R-27806-26076 The handler for an SQLITE_FCNTL_PRAGMA
000974          ** file control can optionally make the first element of the char**
000975          ** argument point to a string obtained from sqlite3_mprintf() or the
000976          ** equivalent and that string will become the result of the pragma
000977          ** or the error message if the pragma fails.
000978          */
000979          aFcntl[0] = sqlite3_mprintf(pGroup->bTruncate ? "on" : "off");
000980          rc = SQLITE_OK;
000981          break;
000982        }
000983        /* If the multiplexor does not handle the pragma, pass it through
000984        ** into the default case. */
000985      }
000986      default:
000987        pSubOpen = multiplexSubOpen(pGroup, 0, &rc, NULL, 0);
000988        if( pSubOpen ){
000989          rc = pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg);
000990          if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
000991           *(char**)pArg = sqlite3_mprintf("multiplex/%z", *(char**)pArg);
000992          }
000993        }
000994        break;
000995    }
000996    return rc;
000997  }
000998  
000999  /* Pass xSectorSize requests through to the original VFS unchanged.
001000  */
001001  static int multiplexSectorSize(sqlite3_file *pConn){
001002    multiplexConn *p = (multiplexConn*)pConn;
001003    int rc;
001004    sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
001005    if( pSubOpen && pSubOpen->pMethods->xSectorSize ){
001006      return pSubOpen->pMethods->xSectorSize(pSubOpen);
001007    }
001008    return DEFAULT_SECTOR_SIZE;
001009  }
001010  
001011  /* Pass xDeviceCharacteristics requests through to the original VFS unchanged.
001012  */
001013  static int multiplexDeviceCharacteristics(sqlite3_file *pConn){
001014    multiplexConn *p = (multiplexConn*)pConn;
001015    int rc;
001016    sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
001017    if( pSubOpen ){
001018      return pSubOpen->pMethods->xDeviceCharacteristics(pSubOpen);
001019    }
001020    return 0;
001021  }
001022  
001023  /* Pass xShmMap requests through to the original VFS unchanged.
001024  */
001025  static int multiplexShmMap(
001026    sqlite3_file *pConn,            /* Handle open on database file */
001027    int iRegion,                    /* Region to retrieve */
001028    int szRegion,                   /* Size of regions */
001029    int bExtend,                    /* True to extend file if necessary */
001030    void volatile **pp              /* OUT: Mapped memory */
001031  ){
001032    multiplexConn *p = (multiplexConn*)pConn;
001033    int rc;
001034    sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
001035    if( pSubOpen ){
001036      return pSubOpen->pMethods->xShmMap(pSubOpen, iRegion, szRegion, bExtend,pp);
001037    }
001038    return SQLITE_IOERR;
001039  }
001040  
001041  /* Pass xShmLock requests through to the original VFS unchanged.
001042  */
001043  static int multiplexShmLock(
001044    sqlite3_file *pConn,       /* Database file holding the shared memory */
001045    int ofst,                  /* First lock to acquire or release */
001046    int n,                     /* Number of locks to acquire or release */
001047    int flags                  /* What to do with the lock */
001048  ){
001049    multiplexConn *p = (multiplexConn*)pConn;
001050    int rc;
001051    sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
001052    if( pSubOpen ){
001053      return pSubOpen->pMethods->xShmLock(pSubOpen, ofst, n, flags);
001054    }
001055    return SQLITE_BUSY;
001056  }
001057  
001058  /* Pass xShmBarrier requests through to the original VFS unchanged.
001059  */
001060  static void multiplexShmBarrier(sqlite3_file *pConn){
001061    multiplexConn *p = (multiplexConn*)pConn;
001062    int rc;
001063    sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
001064    if( pSubOpen ){
001065      pSubOpen->pMethods->xShmBarrier(pSubOpen);
001066    }
001067  }
001068  
001069  /* Pass xShmUnmap requests through to the original VFS unchanged.
001070  */
001071  static int multiplexShmUnmap(sqlite3_file *pConn, int deleteFlag){
001072    multiplexConn *p = (multiplexConn*)pConn;
001073    int rc;
001074    sqlite3_file *pSubOpen = multiplexSubOpen(p->pGroup, 0, &rc, NULL, 0);
001075    if( pSubOpen ){
001076      return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag);
001077    }
001078    return SQLITE_OK;
001079  }
001080  
001081  /************************** Public Interfaces *****************************/
001082  /*
001083  ** CAPI: Initialize the multiplex VFS shim - sqlite3_multiplex_initialize()
001084  **
001085  ** Use the VFS named zOrigVfsName as the VFS that does the actual work.  
001086  ** Use the default if zOrigVfsName==NULL.  
001087  **
001088  ** The multiplex VFS shim is named "multiplex".  It will become the default
001089  ** VFS if makeDefault is non-zero.
001090  **
001091  ** THIS ROUTINE IS NOT THREADSAFE.  Call this routine exactly once
001092  ** during start-up.
001093  */
001094  int sqlite3_multiplex_initialize(const char *zOrigVfsName, int makeDefault){
001095    sqlite3_vfs *pOrigVfs;
001096    if( gMultiplex.isInitialized ) return SQLITE_MISUSE;
001097    pOrigVfs = sqlite3_vfs_find(zOrigVfsName);
001098    if( pOrigVfs==0 ) return SQLITE_ERROR;
001099    assert( pOrigVfs!=&gMultiplex.sThisVfs );
001100    gMultiplex.isInitialized = 1;
001101    gMultiplex.pOrigVfs = pOrigVfs;
001102    gMultiplex.sThisVfs = *pOrigVfs;
001103    gMultiplex.sThisVfs.szOsFile += sizeof(multiplexConn);
001104    gMultiplex.sThisVfs.zName = SQLITE_MULTIPLEX_VFS_NAME;
001105    gMultiplex.sThisVfs.xOpen = multiplexOpen;
001106    gMultiplex.sThisVfs.xDelete = multiplexDelete;
001107    gMultiplex.sThisVfs.xAccess = multiplexAccess;
001108    gMultiplex.sThisVfs.xFullPathname = multiplexFullPathname;
001109    gMultiplex.sThisVfs.xDlOpen = multiplexDlOpen;
001110    gMultiplex.sThisVfs.xDlError = multiplexDlError;
001111    gMultiplex.sThisVfs.xDlSym = multiplexDlSym;
001112    gMultiplex.sThisVfs.xDlClose = multiplexDlClose;
001113    gMultiplex.sThisVfs.xRandomness = multiplexRandomness;
001114    gMultiplex.sThisVfs.xSleep = multiplexSleep;
001115    gMultiplex.sThisVfs.xCurrentTime = multiplexCurrentTime;
001116    gMultiplex.sThisVfs.xGetLastError = multiplexGetLastError;
001117    gMultiplex.sThisVfs.xCurrentTimeInt64 = multiplexCurrentTimeInt64;
001118  
001119    gMultiplex.sIoMethodsV1.iVersion = 1;
001120    gMultiplex.sIoMethodsV1.xClose = multiplexClose;
001121    gMultiplex.sIoMethodsV1.xRead = multiplexRead;
001122    gMultiplex.sIoMethodsV1.xWrite = multiplexWrite;
001123    gMultiplex.sIoMethodsV1.xTruncate = multiplexTruncate;
001124    gMultiplex.sIoMethodsV1.xSync = multiplexSync;
001125    gMultiplex.sIoMethodsV1.xFileSize = multiplexFileSize;
001126    gMultiplex.sIoMethodsV1.xLock = multiplexLock;
001127    gMultiplex.sIoMethodsV1.xUnlock = multiplexUnlock;
001128    gMultiplex.sIoMethodsV1.xCheckReservedLock = multiplexCheckReservedLock;
001129    gMultiplex.sIoMethodsV1.xFileControl = multiplexFileControl;
001130    gMultiplex.sIoMethodsV1.xSectorSize = multiplexSectorSize;
001131    gMultiplex.sIoMethodsV1.xDeviceCharacteristics =
001132                                              multiplexDeviceCharacteristics;
001133    gMultiplex.sIoMethodsV2 = gMultiplex.sIoMethodsV1;
001134    gMultiplex.sIoMethodsV2.iVersion = 2;
001135    gMultiplex.sIoMethodsV2.xShmMap = multiplexShmMap;
001136    gMultiplex.sIoMethodsV2.xShmLock = multiplexShmLock;
001137    gMultiplex.sIoMethodsV2.xShmBarrier = multiplexShmBarrier;
001138    gMultiplex.sIoMethodsV2.xShmUnmap = multiplexShmUnmap;
001139    sqlite3_vfs_register(&gMultiplex.sThisVfs, makeDefault);
001140  
001141    sqlite3_auto_extension((void(*)(void))multiplexFuncInit);
001142  
001143    return SQLITE_OK;
001144  }
001145  
001146  /*
001147  ** CAPI: Shutdown the multiplex system - sqlite3_multiplex_shutdown()
001148  **
001149  ** All SQLite database connections must be closed before calling this
001150  ** routine.
001151  **
001152  ** THIS ROUTINE IS NOT THREADSAFE.  Call this routine exactly once while
001153  ** shutting down in order to free all remaining multiplex groups.
001154  */
001155  int sqlite3_multiplex_shutdown(int eForce){
001156    int rc = SQLITE_OK;
001157    if( gMultiplex.isInitialized==0 ) return SQLITE_MISUSE;
001158    gMultiplex.isInitialized = 0;
001159    sqlite3_vfs_unregister(&gMultiplex.sThisVfs);
001160    memset(&gMultiplex, 0, sizeof(gMultiplex));
001161    return rc;
001162  }
001163  
001164  /***************************** Test Code ***********************************/
001165  #ifdef SQLITE_TEST
001166  #if defined(INCLUDE_SQLITE_TCL_H)
001167  #  include "sqlite_tcl.h"
001168  #else
001169  #  include "tcl.h"
001170  #  ifndef SQLITE_TCLAPI
001171  #    define SQLITE_TCLAPI
001172  #  endif
001173  #endif
001174  extern const char *sqlite3ErrName(int);
001175  
001176  
001177  /*
001178  ** tclcmd: sqlite3_multiplex_initialize NAME MAKEDEFAULT
001179  */
001180  static int SQLITE_TCLAPI test_multiplex_initialize(
001181    void * clientData,
001182    Tcl_Interp *interp,
001183    int objc,
001184    Tcl_Obj *CONST objv[]
001185  ){
001186    const char *zName;              /* Name of new multiplex VFS */
001187    int makeDefault;                /* True to make the new VFS the default */
001188    int rc;                         /* Value returned by multiplex_initialize() */
001189  
001190    UNUSED_PARAMETER(clientData);
001191  
001192    /* Process arguments */
001193    if( objc!=3 ){
001194      Tcl_WrongNumArgs(interp, 1, objv, "NAME MAKEDEFAULT");
001195      return TCL_ERROR;
001196    }
001197    zName = Tcl_GetString(objv[1]);
001198    if( Tcl_GetBooleanFromObj(interp, objv[2], &makeDefault) ) return TCL_ERROR;
001199    if( zName[0]=='\0' ) zName = 0;
001200  
001201    /* Call sqlite3_multiplex_initialize() */
001202    rc = sqlite3_multiplex_initialize(zName, makeDefault);
001203    Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
001204  
001205    return TCL_OK;
001206  }
001207  
001208  /*
001209  ** tclcmd: sqlite3_multiplex_shutdown
001210  */
001211  static int SQLITE_TCLAPI test_multiplex_shutdown(
001212    void * clientData,
001213    Tcl_Interp *interp,
001214    int objc,
001215    Tcl_Obj *CONST objv[]
001216  ){
001217    int rc;                         /* Value returned by multiplex_shutdown() */
001218  
001219    UNUSED_PARAMETER(clientData);
001220  
001221    if( objc==2 && strcmp(Tcl_GetString(objv[1]),"-force")!=0 ){
001222      objc = 3;
001223    }
001224    if( (objc!=1 && objc!=2) ){
001225      Tcl_WrongNumArgs(interp, 1, objv, "?-force?");
001226      return TCL_ERROR;
001227    }
001228  
001229    /* Call sqlite3_multiplex_shutdown() */
001230    rc = sqlite3_multiplex_shutdown(objc==2);
001231    Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
001232  
001233    return TCL_OK;
001234  }
001235  
001236  /*
001237  ** Tclcmd: test_multiplex_control HANDLE DBNAME SUB-COMMAND ?INT-VALUE?
001238  */
001239  static int SQLITE_TCLAPI test_multiplex_control(
001240    ClientData cd,
001241    Tcl_Interp *interp,
001242    int objc,
001243    Tcl_Obj *CONST objv[]
001244  ){
001245    int rc;                         /* Return code from file_control() */
001246    int idx;                        /* Index in aSub[] */
001247    Tcl_CmdInfo cmdInfo;            /* Command info structure for HANDLE */
001248    sqlite3 *db;                    /* Underlying db handle for HANDLE */
001249    int iValue = 0;
001250    void *pArg = 0;
001251  
001252    struct SubCommand {
001253      const char *zName;
001254      int op;
001255      int argtype;
001256    } aSub[] = {
001257      { "enable",       MULTIPLEX_CTRL_ENABLE,           1 },
001258      { "chunk_size",   MULTIPLEX_CTRL_SET_CHUNK_SIZE,   1 },
001259      { "max_chunks",   MULTIPLEX_CTRL_SET_MAX_CHUNKS,   1 },
001260      { 0, 0, 0 }
001261    };
001262  
001263    if( objc!=5 ){
001264      Tcl_WrongNumArgs(interp, 1, objv, "HANDLE DBNAME SUB-COMMAND INT-VALUE");
001265      return TCL_ERROR;
001266    }
001267  
001268    if( 0==Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
001269      Tcl_AppendResult(interp, "expected database handle, got \"", 0);
001270      Tcl_AppendResult(interp, Tcl_GetString(objv[1]), "\"", 0);
001271      return TCL_ERROR;
001272    }else{
001273      db = *(sqlite3 **)cmdInfo.objClientData;
001274    }
001275  
001276    rc = Tcl_GetIndexFromObjStruct(
001277        interp, objv[3], aSub, sizeof(aSub[0]), "sub-command", 0, &idx
001278    );
001279    if( rc!=TCL_OK ) return rc;
001280  
001281    switch( aSub[idx].argtype ){
001282      case 1:
001283        if( Tcl_GetIntFromObj(interp, objv[4], &iValue) ){
001284          return TCL_ERROR;
001285        }
001286        pArg = (void *)&iValue;
001287        break;
001288      default:
001289        Tcl_WrongNumArgs(interp, 4, objv, "SUB-COMMAND");
001290        return TCL_ERROR;
001291    }
001292  
001293    rc = sqlite3_file_control(db, Tcl_GetString(objv[2]), aSub[idx].op, pArg);
001294    Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
001295    return (rc==SQLITE_OK) ? TCL_OK : TCL_ERROR;
001296  }
001297  
001298  /*
001299  ** This routine registers the custom TCL commands defined in this
001300  ** module.  This should be the only procedure visible from outside
001301  ** of this module.
001302  */
001303  int Sqlitemultiplex_Init(Tcl_Interp *interp){
001304    static struct {
001305       char *zName;
001306       Tcl_ObjCmdProc *xProc;
001307    } aCmd[] = {
001308      { "sqlite3_multiplex_initialize", test_multiplex_initialize },
001309      { "sqlite3_multiplex_shutdown", test_multiplex_shutdown },
001310      { "sqlite3_multiplex_control", test_multiplex_control },
001311    };
001312    int i;
001313  
001314    for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
001315      Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
001316    }
001317  
001318    return TCL_OK;
001319  }
001320  #endif