/ Changes On Branch wal-refactor
Login

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

Changes In Branch wal-refactor Excluding Merge-Ins

This is equivalent to a diff from 7838163d08 to 149d2ae4a6

2010-05-13
08:53
The refactored of VFS SHM primitives are now working so merge the wal-refactor branch back into the trunk. (check-in: bce21c1838 user: drh tags: trunk)
08:33
Change the xShmSize() implementation in os_unix.c so that it will only increase and never decrease the size of a shared-memory segment. (Closed-Leaf check-in: 149d2ae4a6 user: drh tags: wal-refactor)
07:08
Fix for a segfault that can follow a malloc failure. (check-in: 3cab902245 user: dan tags: wal-refactor)
2010-05-12
19:02
(Moved to the mistake branch due to compile errors in test_osinst.c.) Change the vfs instrumentation code in test_osinst.c to make it easier to deploy. Add a vtab implementation for reading the binary log file format. (check-in: ee13c8849d user: dan tags: mistake)
18:01
Refactoring the VFS-SHM methods used by WAL. This version compiles and runs non-WAL test cases but crashes and burns on wal.test. (check-in: 2b00152c1a user: drh tags: wal-refactor)
13:50
Remove the OP_Variable optimization of check-in [48b77b04935d894] since it can lead to malfunctions as described in ticket [26ff0c82d1e90]. (check-in: 7838163d08 user: drh tags: trunk)
06:54
Remove a branch made redundant by the earlier exclusive-mode changes. (check-in: c501b2ede6 user: dan tags: trunk)

Changes to doc/vfs-shm.txt.

    74     74   
    75     75   The SQLite core will obey the next set of rules.  These rules are
    76     76   assertions on the behavior of the SQLite core which might be verified
    77     77   during testing using an instrumented lock manager.
    78     78   
    79     79   (5)  No part of the wal-index will be read without holding either some
    80     80        kind of SHM lock or an EXCLUSIVE lock on the original database.
           81  +     The original database is the file named in the 2nd parameter to
           82  +     the xShmOpen method.
           83  +
    81     84   (6)  A holder of a READ_FULL will never read any page of the database
    82     85        file that is contained anywhere in the wal-index.
           86  +
    83     87   (7)  No part of the wal-index other than the header will be written nor
    84         -     will the size of the wal-index grow without holding a WRITE.
           88  +     will the size of the wal-index grow without holding a WRITE or
           89  +     an EXCLUSIVE on the original database file.
           90  +
    85     91   (8)  The wal-index header will not be written without holding one of
    86         -     WRITE, CHECKPOINT, or RECOVER.
    87         -(9)  A CHECKPOINT or RECOVER must be held in order to reset the last valid
    88         -     frame counter in the header of the wal-index back to zero.
           92  +     WRITE, CHECKPOINT, or RECOVER on the wal-index or an EXCLUSIVE on
           93  +     the original database files.
           94  +
           95  +(9)  A CHECKPOINT or RECOVER must be held on the wal-index, or an
           96  +     EXCLUSIVE on the original database file, in order to reset the 
           97  +     last valid frame counter in the header of the wal-index back to zero.
           98  +
    89     99   (10) A WRITE can only increase the last valid frame pointer in the header.
    90    100   
    91    101   The SQLite core will only ever send requests for UNLOCK, READ, WRITE,
    92    102   CHECKPOINT, or RECOVER to the lock manager.   The SQLite core will never
    93    103   request a READ_FULL or PENDING lock though the lock manager may deliver
    94    104   those locking states in response to READ and CHECKPOINT requests,
    95    105   respectively, if and only if the requested READ or CHECKPOINT cannot

Changes to src/os.c.

    94     94   int sqlite3OsSectorSize(sqlite3_file *id){
    95     95     int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
    96     96     return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
    97     97   }
    98     98   int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
    99     99     return id->pMethods->xDeviceCharacteristics(id);
   100    100   }
          101  +int sqlite3OsShmOpen(sqlite3_file *id){
          102  +  return id->pMethods->xShmOpen(id);
          103  +}
          104  +int sqlite3OsShmSize(sqlite3_file *id, int reqSize, int *pNewSize){
          105  +  return id->pMethods->xShmSize(id, reqSize, pNewSize);
          106  +}
          107  +int sqlite3OsShmGet(sqlite3_file *id, int reqSize, int *pSize, void **pp){
          108  +  return id->pMethods->xShmGet(id, reqSize, pSize, pp);
          109  +}
          110  +int sqlite3OsShmRelease(sqlite3_file *id){
          111  +  return id->pMethods->xShmRelease(id);
          112  +}
          113  +int sqlite3OsShmLock(sqlite3_file *id, int desiredLock, int *pGotLock){
          114  +  return id->pMethods->xShmLock(id, desiredLock, pGotLock);
          115  +}
          116  +int sqlite3OsShmClose(sqlite3_file *id, int deleteFlag){
          117  +  return id->pMethods->xShmClose(id, deleteFlag);
          118  +}
   101    119   
   102    120   /*
   103    121   ** The next group of routines are convenience wrappers around the
   104    122   ** VFS methods.
   105    123   */
   106    124   int sqlite3OsOpen(
   107    125     sqlite3_vfs *pVfs, 

Changes to src/os.h.

   239    239   int sqlite3OsLock(sqlite3_file*, int);
   240    240   int sqlite3OsUnlock(sqlite3_file*, int);
   241    241   int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
   242    242   int sqlite3OsFileControl(sqlite3_file*,int,void*);
   243    243   #define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
   244    244   int sqlite3OsSectorSize(sqlite3_file *id);
   245    245   int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
          246  +int sqlite3OsShmOpen(sqlite3_file *id);
          247  +int sqlite3OsShmSize(sqlite3_file *id, int, int*);
          248  +int sqlite3OsShmGet(sqlite3_file *id, int, int*, void**);
          249  +int sqlite3OsShmRelease(sqlite3_file *id);
          250  +int sqlite3OsShmLock(sqlite3_file *id, int, int*);
          251  +int sqlite3OsShmClose(sqlite3_file *id, int);
   246    252   
   247    253   /* 
   248    254   ** Functions for accessing sqlite3_vfs methods 
   249    255   */
   250    256   int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
   251    257   int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
   252    258   int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);

Changes to src/os_unix.c.

   171    171   
   172    172   /*
   173    173   ** Only set the lastErrno if the error code is a real error and not 
   174    174   ** a normal expected return code of SQLITE_BUSY or SQLITE_OK
   175    175   */
   176    176   #define IS_LOCK_ERROR(x)  ((x != SQLITE_OK) && (x != SQLITE_BUSY))
   177    177   
          178  +/* Forward reference */
          179  +typedef struct unixShm unixShm;
          180  +typedef struct unixShmFile unixShmFile;
   178    181   
   179    182   /*
   180    183   ** Sometimes, after a file handle is closed by SQLite, the file descriptor
   181    184   ** cannot be closed immediately. In these cases, instances of the following
   182    185   ** structure are used to store the file descriptor while waiting for an
   183    186   ** opportunity to either close or reuse it.
   184    187   */
................................................................................
   201    204     int h;                           /* The file descriptor */
   202    205     int dirfd;                       /* File descriptor for the directory */
   203    206     unsigned char locktype;          /* The type of lock held on this fd */
   204    207     int lastErrno;                   /* The unix errno from the last I/O error */
   205    208     void *lockingContext;            /* Locking style specific state */
   206    209     UnixUnusedFd *pUnused;           /* Pre-allocated UnixUnusedFd */
   207    210     int fileFlags;                   /* Miscellanous flags */
          211  +  const char *zPath;               /* Name of the file */
          212  +  unixShm *pShm;                   /* Shared memory segment information */
   208    213   #if SQLITE_ENABLE_LOCKING_STYLE
   209    214     int openFlags;                   /* The flags specified at open() */
   210    215   #endif
   211    216   #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__)
   212    217     unsigned fsFlags;                 /* cached details from statfs() */
   213    218   #endif
   214    219   #if SQLITE_THREADSAFE && defined(__linux__)
................................................................................
  3396   3401   ** Return the device characteristics for the file. This is always 0 for unix.
  3397   3402   */
  3398   3403   static int unixDeviceCharacteristics(sqlite3_file *NotUsed){
  3399   3404     UNUSED_PARAMETER(NotUsed);
  3400   3405     return 0;
  3401   3406   }
  3402   3407   
         3408  +#ifndef SQLITE_OMIT_WAL
         3409  +
         3410  +
         3411  +/*
         3412  +** Object used to represent a single file opened and mmapped to provide
         3413  +** shared memory.  When multiple threads all reference the same
         3414  +** log-summary, each thread has its own unixFile object, but they all
         3415  +** point to a single instance of this object.  In other words, each
         3416  +** log-summary is opened only once per process.
         3417  +**
         3418  +** unixMutexHeld() must be true when creating or destroying
         3419  +** this object or while reading or writing the following fields:
         3420  +**
         3421  +**      nRef
         3422  +**      pNext 
         3423  +**
         3424  +** The following fields are read-only after the object is created:
         3425  +** 
         3426  +**      fid
         3427  +**      zFilename
         3428  +**
         3429  +** Either unixShmFile.mutex must be held or unixShmFile.nRef==0 and
         3430  +** unixMutexHeld() is true when reading or writing any other field
         3431  +** in this structure.
         3432  +**
         3433  +** To avoid deadlocks, mutex and mutexBuf are always released in the
         3434  +** reverse order that they are acquired.  mutexBuf is always acquired
         3435  +** first and released last.  This invariant is check by asserting
         3436  +** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or
         3437  +** released.
         3438  +*/
         3439  +struct unixShmFile {
         3440  +  struct unixFileId fid;     /* Unique file identifier */
         3441  +  sqlite3_mutex *mutex;      /* Mutex to access this object */
         3442  +  sqlite3_mutex *mutexBuf;   /* Mutex to access zBuf[] */
         3443  +  char *zFilename;           /* Name of the mmapped file */
         3444  +  int h;                     /* Open file descriptor */
         3445  +  int szMap;                 /* Size of the mapping of file into memory */
         3446  +  char *pMMapBuf;            /* Where currently mmapped().  NULL if unmapped */
         3447  +  int nRef;                  /* Number of unixShm objects pointing to this */
         3448  +  unixShm *pFirst;           /* All unixShm objects pointing to this */
         3449  +  unixShmFile *pNext;        /* Next in list of all unixShmFile objects */
         3450  +#ifdef SQLITE_DEBUG
         3451  +  u8 exclMask;               /* Mask of exclusive locks held */
         3452  +  u8 sharedMask;             /* Mask of shared locks held */
         3453  +  u8 nextShmId;              /* Next available unixShm.id value */
         3454  +#endif
         3455  +};
         3456  +
         3457  +/*
         3458  +** A global array of all unixShmFile objects.
         3459  +**
         3460  +** The unixMutexHeld() must be true while reading or writing this list.
         3461  +*/
         3462  +static unixShmFile *unixShmFileList = 0;
         3463  +
         3464  +/*
         3465  +** Structure used internally by this VFS to record the state of an
         3466  +** open shared memory connection.
         3467  +**
         3468  +** unixShm.pFile->mutex must be held while reading or writing the
         3469  +** unixShm.pNext and unixShm.locks[] elements.
         3470  +**
         3471  +** The unixShm.pFile element is initialized when the object is created
         3472  +** and is read-only thereafter.
         3473  +*/
         3474  +struct unixShm {
         3475  +  unixShmFile *pFile;        /* The underlying unixShmFile object */
         3476  +  unixShm *pNext;            /* Next unixShm with the same unixShmFile */
         3477  +  u8 lockState;              /* Current lock state */
         3478  +  u8 hasMutex;               /* True if holding the unixShmFile mutex */
         3479  +  u8 hasMutexBuf;            /* True if holding pFile->mutexBuf */
         3480  +  u8 sharedMask;             /* Mask of shared locks held */
         3481  +  u8 exclMask;               /* Mask of exclusive locks held */
         3482  +#ifdef SQLITE_DEBUG
         3483  +  u8 id;                     /* Id of this connection with its unixShmFile */
         3484  +#endif
         3485  +};
         3486  +
         3487  +/*
         3488  +** Size increment by which shared memory grows
         3489  +*/
         3490  +#define SQLITE_UNIX_SHM_INCR  4096
         3491  +
         3492  +/*
         3493  +** Constants used for locking
         3494  +*/
         3495  +#define UNIX_SHM_BASE      32        /* Byte offset of the first lock byte */
         3496  +#define UNIX_SHM_DMS       0x01      /* Mask for Dead-Man-Switch lock */
         3497  +#define UNIX_SHM_A         0x10      /* Mask for region locks... */
         3498  +#define UNIX_SHM_B         0x20
         3499  +#define UNIX_SHM_C         0x40
         3500  +#define UNIX_SHM_D         0x80
         3501  +
         3502  +#ifdef SQLITE_DEBUG
         3503  +/*
         3504  +** Return a pointer to a nul-terminated string in static memory that
         3505  +** describes a locking mask.  The string is of the form "MSABCD" with
         3506  +** each character representing a lock.  "M" for MUTEX, "S" for DMS, 
         3507  +** and "A" through "D" for the region locks.  If a lock is held, the
         3508  +** letter is shown.  If the lock is not held, the letter is converted
         3509  +** to ".".
         3510  +**
         3511  +** This routine is for debugging purposes only and does not appear
         3512  +** in a production build.
         3513  +*/
         3514  +static const char *unixShmLockString(u8 mask){
         3515  +  static char zBuf[48];
         3516  +  static int iBuf = 0;
         3517  +  char *z;
         3518  +
         3519  +  z = &zBuf[iBuf];
         3520  +  iBuf += 8;
         3521  +  if( iBuf>=sizeof(zBuf) ) iBuf = 0;
         3522  +
         3523  +  z[0] = (mask & UNIX_SHM_DMS)   ? 'S' : '.';
         3524  +  z[1] = (mask & UNIX_SHM_A)     ? 'A' : '.';
         3525  +  z[2] = (mask & UNIX_SHM_B)     ? 'B' : '.';
         3526  +  z[3] = (mask & UNIX_SHM_C)     ? 'C' : '.';
         3527  +  z[4] = (mask & UNIX_SHM_D)     ? 'D' : '.';
         3528  +  z[5] = 0;
         3529  +  return z;
         3530  +}
         3531  +#endif /* SQLITE_DEBUG */
         3532  +
         3533  +/*
         3534  +** Apply posix advisory locks for all bytes identified in lockMask.
         3535  +**
         3536  +** lockMask might contain multiple bits but all bits are guaranteed
         3537  +** to be contiguous.
         3538  +**
         3539  +** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
         3540  +** otherwise.
         3541  +*/
         3542  +static int unixShmSystemLock(
         3543  +  unixShmFile *pFile,   /* Apply locks to this open shared-memory segment */
         3544  +  int lockType,         /* F_UNLCK, F_RDLCK, or F_WRLCK */
         3545  +  u8 lockMask           /* Which bytes to lock or unlock */
         3546  +){
         3547  +  struct flock f;       /* The posix advisory locking structure */
         3548  +  int lockOp;           /* The opcode for fcntl() */
         3549  +  int i;                /* Offset into the locking byte range */
         3550  +  int rc;               /* Result code form fcntl() */
         3551  +  u8 mask;              /* Mask of bits in lockMask */
         3552  +
         3553  +  /* Access to the unixShmFile object is serialized by the caller */
         3554  +  assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
         3555  +
         3556  +  /* Initialize the locking parameters */
         3557  +  memset(&f, 0, sizeof(f));
         3558  +  f.l_type = lockType;
         3559  +  f.l_whence = SEEK_SET;
         3560  +  if( lockMask==UNIX_SHM_C && lockType!=F_UNLCK ){
         3561  +    lockOp = F_SETLKW;
         3562  +    OSTRACE(("SHM-LOCK requesting blocking lock\n"));
         3563  +  }else{
         3564  +    lockOp = F_SETLK;
         3565  +  }
         3566  +
         3567  +  /* Find the first bit in lockMask that is set */
         3568  +  for(i=0, mask=0x01; mask!=0 && (lockMask&mask)==0; mask <<= 1, i++){}
         3569  +  assert( mask!=0 );
         3570  +  f.l_start = i+UNIX_SHM_BASE;
         3571  +  f.l_len = 1;
         3572  +
         3573  +  /* Extend the locking range for each additional bit that is set */
         3574  +  mask <<= 1;
         3575  +  while( mask!=0 && (lockMask & mask)!=0 ){
         3576  +    f.l_len++;
         3577  +    mask <<= 1;
         3578  +  }
         3579  +
         3580  +  /* Verify that all bits set in lockMask are contiguous */
         3581  +  assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );
         3582  +
         3583  +  /* Acquire the system-level lock */
         3584  +  rc = fcntl(pFile->h, lockOp, &f);
         3585  +  rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
         3586  +
         3587  +  /* Update the global lock state and do debug tracing */
         3588  +#ifdef SQLITE_DEBUG
         3589  +  OSTRACE(("SHM-LOCK "));
         3590  +  if( rc==SQLITE_OK ){
         3591  +    if( lockType==F_UNLCK ){
         3592  +      OSTRACE(("unlock ok"));
         3593  +      pFile->exclMask &= ~lockMask;
         3594  +      pFile->sharedMask &= ~lockMask;
         3595  +    }else if( lockType==F_RDLCK ){
         3596  +      OSTRACE(("read-lock ok"));
         3597  +      pFile->exclMask &= ~lockMask;
         3598  +      pFile->sharedMask |= lockMask;
         3599  +    }else{
         3600  +      assert( lockType==F_WRLCK );
         3601  +      OSTRACE(("write-lock ok"));
         3602  +      pFile->exclMask |= lockMask;
         3603  +      pFile->sharedMask &= ~lockMask;
         3604  +    }
         3605  +  }else{
         3606  +    if( lockType==F_UNLCK ){
         3607  +      OSTRACE(("unlock failed"));
         3608  +    }else if( lockType==F_RDLCK ){
         3609  +      OSTRACE(("read-lock failed"));
         3610  +    }else{
         3611  +      assert( lockType==F_WRLCK );
         3612  +      OSTRACE(("write-lock failed"));
         3613  +    }
         3614  +  }
         3615  +  OSTRACE((" - change requested %s - afterwards %s:%s\n",
         3616  +           unixShmLockString(lockMask),
         3617  +           unixShmLockString(pFile->sharedMask),
         3618  +           unixShmLockString(pFile->exclMask)));
         3619  +#endif
         3620  +
         3621  +  return rc;        
         3622  +}
         3623  +
         3624  +/*
         3625  +** For connection p, unlock all of the locks identified by the unlockMask
         3626  +** parameter.
         3627  +*/
         3628  +static int unixShmUnlock(
         3629  +  unixShmFile *pFile,   /* The underlying shared-memory file */
         3630  +  unixShm *p,           /* The connection to be unlocked */
         3631  +  u8 unlockMask         /* Mask of locks to be unlocked */
         3632  +){
         3633  +  int rc;      /* Result code */
         3634  +  unixShm *pX; /* For looping over all sibling connections */
         3635  +  u8 allMask;  /* Union of locks held by connections other than "p" */
         3636  +
         3637  +  /* Access to the unixShmFile object is serialized by the caller */
         3638  +  assert( sqlite3_mutex_held(pFile->mutex) );
         3639  +
         3640  +  /* Compute locks held by sibling connections */
         3641  +  allMask = 0;
         3642  +  for(pX=pFile->pFirst; pX; pX=pX->pNext){
         3643  +    if( pX==p ) continue;
         3644  +    assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
         3645  +    allMask |= pX->sharedMask;
         3646  +  }
         3647  +
         3648  +  /* Unlock the system-level locks */
         3649  +  if( (unlockMask & allMask)!=unlockMask ){
         3650  +    rc = unixShmSystemLock(pFile, F_UNLCK, unlockMask & ~allMask);
         3651  +  }else{
         3652  +    rc = SQLITE_OK;
         3653  +  }
         3654  +
         3655  +  /* Undo the local locks */
         3656  +  if( rc==SQLITE_OK ){
         3657  +    p->exclMask &= ~unlockMask;
         3658  +    p->sharedMask &= ~unlockMask;
         3659  +  } 
         3660  +  return rc;
         3661  +}
         3662  +
         3663  +/*
         3664  +** Get reader locks for connection p on all locks in the readMask parameter.
         3665  +*/
         3666  +static int unixShmSharedLock(
         3667  +  unixShmFile *pFile,   /* The underlying shared-memory file */
         3668  +  unixShm *p,           /* The connection to get the shared locks */
         3669  +  u8 readMask           /* Mask of shared locks to be acquired */
         3670  +){
         3671  +  int rc;        /* Result code */
         3672  +  unixShm *pX;   /* For looping over all sibling connections */
         3673  +  u8 allShared;  /* Union of locks held by connections other than "p" */
         3674  +
         3675  +  /* Access to the unixShmFile object is serialized by the caller */
         3676  +  assert( sqlite3_mutex_held(pFile->mutex) );
         3677  +
         3678  +  /* Find out which shared locks are already held by sibling connections.
         3679  +  ** If any sibling already holds an exclusive lock, go ahead and return
         3680  +  ** SQLITE_BUSY.
         3681  +  */
         3682  +  allShared = 0;
         3683  +  for(pX=pFile->pFirst; pX; pX=pX->pNext){
         3684  +    if( pX==p ) continue;
         3685  +    if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY;
         3686  +    allShared |= pX->sharedMask;
         3687  +  }
         3688  +
         3689  +  /* Get shared locks at the system level, if necessary */
         3690  +  if( (~allShared) & readMask ){
         3691  +    rc = unixShmSystemLock(pFile, F_RDLCK, readMask);
         3692  +  }else{
         3693  +    rc = SQLITE_OK;
         3694  +  }
         3695  +
         3696  +  /* Get the local shared locks */
         3697  +  if( rc==SQLITE_OK ){
         3698  +    p->sharedMask |= readMask;
         3699  +  }
         3700  +  return rc;
         3701  +}
         3702  +
         3703  +/*
         3704  +** For connection p, get an exclusive lock on all locks identified in
         3705  +** the writeMask parameter.
         3706  +*/
         3707  +static int unixShmExclusiveLock(
         3708  +  unixShmFile *pFile,    /* The underlying shared-memory file */
         3709  +  unixShm *p,            /* The connection to get the exclusive locks */
         3710  +  u8 writeMask           /* Mask of exclusive locks to be acquired */
         3711  +){
         3712  +  int rc;        /* Result code */
         3713  +  unixShm *pX;   /* For looping over all sibling connections */
         3714  +
         3715  +  /* Access to the unixShmFile object is serialized by the caller */
         3716  +  assert( sqlite3_mutex_held(pFile->mutex) );
         3717  +
         3718  +  /* Make sure no sibling connections hold locks that will block this
         3719  +  ** lock.  If any do, return SQLITE_BUSY right away.
         3720  +  */
         3721  +  for(pX=pFile->pFirst; pX; pX=pX->pNext){
         3722  +    if( pX==p ) continue;
         3723  +    if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY;
         3724  +    if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY;
         3725  +  }
         3726  +
         3727  +  /* Get the exclusive locks at the system level.  Then if successful
         3728  +  ** also mark the local connection as being locked.
         3729  +  */
         3730  +  rc = unixShmSystemLock(pFile, F_WRLCK, writeMask);
         3731  +  if( rc==SQLITE_OK ){
         3732  +    p->sharedMask &= ~writeMask;
         3733  +    p->exclMask |= writeMask;
         3734  +  }
         3735  +  return rc;
         3736  +}
         3737  +
         3738  +/*
         3739  +** Purge the unixShmFileList list of all entries with unixShmFile.nRef==0.
         3740  +**
         3741  +** This is not a VFS shared-memory method; it is a utility function called
         3742  +** by VFS shared-memory methods.
         3743  +*/
         3744  +static void unixShmPurge(void){
         3745  +  unixShmFile **pp;
         3746  +  unixShmFile *p;
         3747  +  assert( unixMutexHeld() );
         3748  +  pp = &unixShmFileList;
         3749  +  while( (p = *pp)!=0 ){
         3750  +    if( p->nRef==0 ){
         3751  +      if( p->mutex ) sqlite3_mutex_free(p->mutex);
         3752  +      if( p->mutexBuf ) sqlite3_mutex_free(p->mutexBuf);
         3753  +      if( p->h>=0 ) close(p->h);
         3754  +      *pp = p->pNext;
         3755  +      sqlite3_free(p);
         3756  +    }else{
         3757  +      pp = &p->pNext;
         3758  +    }
         3759  +  }
         3760  +}
         3761  +
         3762  +/*
         3763  +** Open a shared-memory area.  This particular implementation uses
         3764  +** mmapped files.
         3765  +**
         3766  +** zName is a filename used to identify the shared-memory area.  The
         3767  +** implementation does not (and perhaps should not) use this name
         3768  +** directly, but rather use it as a template for finding an appropriate
         3769  +** name for the shared-memory storage.  In this implementation, the
         3770  +** string "-index" is appended to zName and used as the name of the
         3771  +** mmapped file.
         3772  +**
         3773  +** When opening a new shared-memory file, if no other instances of that
         3774  +** file are currently open, in this process or in other processes, then
         3775  +** the file must be truncated to zero length or have its header cleared.
         3776  +*/
         3777  +static int unixShmOpen(
         3778  +  sqlite3_file *fd      /* The file descriptor of the associated database */
         3779  +){
         3780  +  struct unixShm *p = 0;             /* The connection to be opened */
         3781  +  struct unixShmFile *pFile = 0;     /* The underlying mmapped file */
         3782  +  int rc;                            /* Result code */
         3783  +  struct unixFileId fid;             /* Unix file identifier */
         3784  +  struct unixShmFile *pNew;          /* Newly allocated pFile */
         3785  +  struct stat sStat;                 /* Result from stat() an fstat() */
         3786  +  struct unixFile *pDbFd;            /* Underlying database file */
         3787  +  int nPath;                         /* Size of pDbFd->zPath in bytes */
         3788  +
         3789  +  /* Allocate space for the new sqlite3_shm object.  Also speculatively
         3790  +  ** allocate space for a new unixShmFile and filename.
         3791  +  */
         3792  +  p = sqlite3_malloc( sizeof(*p) );
         3793  +  if( p==0 ) return SQLITE_NOMEM;
         3794  +  memset(p, 0, sizeof(*p));
         3795  +  pDbFd = (struct unixFile*)fd;
         3796  +  assert( pDbFd->pShm==0 );
         3797  +  nPath = strlen(pDbFd->zPath);
         3798  +  pNew = sqlite3_malloc( sizeof(*pFile) + nPath + 15 );
         3799  +  if( pNew==0 ){
         3800  +    sqlite3_free(p);
         3801  +    return SQLITE_NOMEM;
         3802  +  }
         3803  +  memset(pNew, 0, sizeof(*pNew));
         3804  +  pNew->zFilename = (char*)&pNew[1];
         3805  +  sqlite3_snprintf(nPath+15, pNew->zFilename, "%s-wal-index", pDbFd->zPath);
         3806  +
         3807  +  /* Look to see if there is an existing unixShmFile that can be used.
         3808  +  ** If no matching unixShmFile currently exists, create a new one.
         3809  +  */
         3810  +  unixEnterMutex();
         3811  +  rc = stat(pNew->zFilename, &sStat);
         3812  +  if( rc==0 ){
         3813  +    memset(&fid, 0, sizeof(fid));
         3814  +    fid.dev = sStat.st_dev;
         3815  +    fid.ino = sStat.st_ino;
         3816  +    for(pFile = unixShmFileList; pFile; pFile=pFile->pNext){
         3817  +      if( memcmp(&pFile->fid, &fid, sizeof(fid))==0 ) break;
         3818  +    }
         3819  +  }
         3820  +  if( pFile ){
         3821  +    sqlite3_free(pNew);
         3822  +  }else{
         3823  +    pFile = pNew;
         3824  +    pNew = 0;
         3825  +    pFile->h = -1;
         3826  +    pFile->pNext = unixShmFileList;
         3827  +    unixShmFileList = pFile;
         3828  +
         3829  +    pFile->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
         3830  +    if( pFile->mutex==0 ){
         3831  +      rc = SQLITE_NOMEM;
         3832  +      goto shm_open_err;
         3833  +    }
         3834  +    pFile->mutexBuf = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
         3835  +    if( pFile->mutexBuf==0 ){
         3836  +      rc = SQLITE_NOMEM;
         3837  +      goto shm_open_err;
         3838  +    }
         3839  +
         3840  +    pFile->h = open(pFile->zFilename, O_RDWR|O_CREAT, 0664);
         3841  +    if( pFile->h<0 ){
         3842  +      rc = SQLITE_CANTOPEN_BKPT;
         3843  +      goto shm_open_err;
         3844  +    }
         3845  +
         3846  +    rc = fstat(pFile->h, &sStat);
         3847  +    if( rc ){
         3848  +      rc = SQLITE_CANTOPEN_BKPT;
         3849  +      goto shm_open_err;
         3850  +    }
         3851  +    pFile->fid.dev = sStat.st_dev;
         3852  +    pFile->fid.ino = sStat.st_ino;
         3853  +
         3854  +    /* Check to see if another process is holding the dead-man switch.
         3855  +    ** If not, truncate the file to zero length. 
         3856  +    */
         3857  +    if( unixShmSystemLock(pFile, F_WRLCK, UNIX_SHM_DMS)==SQLITE_OK ){
         3858  +      if( ftruncate(pFile->h, 0) ){
         3859  +        rc = SQLITE_IOERR;
         3860  +      }
         3861  +    }
         3862  +    if( rc==SQLITE_OK ){
         3863  +      rc = unixShmSystemLock(pFile, F_RDLCK, UNIX_SHM_DMS);
         3864  +    }
         3865  +    if( rc ) goto shm_open_err;
         3866  +  }
         3867  +
         3868  +  /* Make the new connection a child of the unixShmFile */
         3869  +  p->pFile = pFile;
         3870  +  p->pNext = pFile->pFirst;
         3871  +#ifdef SQLITE_DEBUG
         3872  +  p->id = pFile->nextShmId++;
         3873  +#endif
         3874  +  pFile->pFirst = p;
         3875  +  pFile->nRef++;
         3876  +  pDbFd->pShm = p;
         3877  +  unixLeaveMutex();
         3878  +  return SQLITE_OK;
         3879  +
         3880  +  /* Jump here on any error */
         3881  +shm_open_err:
         3882  +  unixShmPurge();                 /* This call frees pFile if required */
         3883  +  sqlite3_free(p);
         3884  +  sqlite3_free(pNew);
         3885  +  unixLeaveMutex();
         3886  +  return rc;
         3887  +}
         3888  +
         3889  +/*
         3890  +** Close a connection to shared-memory.  Delete the underlying 
         3891  +** storage if deleteFlag is true.
         3892  +*/
         3893  +static int unixShmClose(
         3894  +  sqlite3_file *fd,          /* The underlying database file */
         3895  +  int deleteFlag             /* Delete shared-memory if true */
         3896  +){
         3897  +  unixShm *p;            /* The connection to be closed */
         3898  +  unixShmFile *pFile;    /* The underlying shared-memory file */
         3899  +  unixShm **pp;          /* For looping over sibling connections */
         3900  +  unixFile *pDbFd;       /* The underlying database file */
         3901  +
         3902  +  pDbFd = (unixFile*)fd;
         3903  +  p = pDbFd->pShm;
         3904  +  if( p==0 ) return SQLITE_OK;
         3905  +  pFile = p->pFile;
         3906  +
         3907  +  /* Verify that the connection being closed holds no locks */
         3908  +  assert( p->exclMask==0 );
         3909  +  assert( p->sharedMask==0 );
         3910  +
         3911  +  /* Remove connection p from the set of connections associated with pFile */
         3912  +  sqlite3_mutex_enter(pFile->mutex);
         3913  +  for(pp=&pFile->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
         3914  +  *pp = p->pNext;
         3915  +
         3916  +  /* Free the connection p */
         3917  +  sqlite3_free(p);
         3918  +  pDbFd->pShm = 0;
         3919  +  sqlite3_mutex_leave(pFile->mutex);
         3920  +
         3921  +  /* If pFile->nRef has reached 0, then close the underlying
         3922  +  ** shared-memory file, too */
         3923  +  unixEnterMutex();
         3924  +  assert( pFile->nRef>0 );
         3925  +  pFile->nRef--;
         3926  +  if( pFile->nRef==0 ){
         3927  +    if( deleteFlag ) unlink(pFile->zFilename);
         3928  +    unixShmPurge();
         3929  +  }
         3930  +  unixLeaveMutex();
         3931  +
         3932  +  return SQLITE_OK;
         3933  +}
         3934  +
         3935  +/*
         3936  +** Query and/or changes the size of the underlying storage for
         3937  +** a shared-memory segment.  The reqSize parameter is the new size
         3938  +** of the underlying storage, or -1 to do just a query.  The size
         3939  +** of the underlying storage (after resizing if resizing occurs) is
         3940  +** written into pNewSize.
         3941  +**
         3942  +** This routine does not (necessarily) change the size of the mapping 
         3943  +** of the underlying storage into memory.  Use xShmGet() to change
         3944  +** the mapping size.
         3945  +**
         3946  +** The reqSize parameter is the minimum size requested.  The implementation
         3947  +** is free to expand the storage to some larger amount if it chooses.
         3948  +*/
         3949  +static int unixShmSize(
         3950  +  sqlite3_file *fd,         /* The open database file holding SHM */
         3951  +  int reqSize,              /* Requested size.  -1 for query only */
         3952  +  int *pNewSize             /* Write new size here */
         3953  +){
         3954  +  unixFile *pDbFd = (unixFile*)fd;
         3955  +  unixShm *p = pDbFd->pShm;
         3956  +  unixShmFile *pFile = p->pFile;
         3957  +  int rc = SQLITE_OK;
         3958  +  struct stat sStat;
         3959  +
         3960  +  /* On a query, this loop runs once.  When reqSize>=0, the loop potentially
         3961  +  ** runs twice, except if the actual size is already greater than or equal
         3962  +  ** to the requested size, reqSize is set to -1 on the first iteration and
         3963  +  ** the loop only runs once.
         3964  +  */
         3965  +  while( 1 ){
         3966  +    if( fstat(pFile->h, &sStat)==0 ){
         3967  +      *pNewSize = (int)sStat.st_size;
         3968  +      if( reqSize>=0 && reqSize<=(int)sStat.st_size ) break;
         3969  +    }else{
         3970  +      *pNewSize = 0;
         3971  +      rc = SQLITE_IOERR;
         3972  +      break;
         3973  +    }
         3974  +    if( reqSize<0 ) break;
         3975  +    reqSize = (reqSize + SQLITE_UNIX_SHM_INCR - 1)/SQLITE_UNIX_SHM_INCR;
         3976  +    reqSize *= SQLITE_UNIX_SHM_INCR;
         3977  +    rc = ftruncate(pFile->h, reqSize);
         3978  +    reqSize = -1;
         3979  +  }
         3980  +  return rc;
         3981  +}
         3982  +
         3983  +
         3984  +/*
         3985  +** Map the shared storage into memory.  The minimum size of the
         3986  +** mapping should be reqMapSize if reqMapSize is positive.  If
         3987  +** reqMapSize is zero or negative, the implementation can choose
         3988  +** whatever mapping size is convenient.
         3989  +**
         3990  +** *ppBuf is made to point to the memory which is a mapping of the
         3991  +** underlying storage.  A mutex is acquired to prevent other threads
         3992  +** from running while *ppBuf is in use in order to prevent other threads
         3993  +** remapping *ppBuf out from under this thread.  The unixShmRelease()
         3994  +** call will release the mutex.  However, if the lock state is CHECKPOINT,
         3995  +** the mutex is not acquired because CHECKPOINT will never remap the
         3996  +** buffer.  RECOVER might remap, though, so CHECKPOINT will acquire
         3997  +** the mutex if and when it promotes to RECOVER.
         3998  +**
         3999  +** RECOVER needs to be atomic.  The same mutex that prevents *ppBuf from
         4000  +** being remapped also prevents more than one thread from being in
         4001  +** RECOVER at a time.  But, RECOVER sometimes wants to remap itself.
         4002  +** To prevent RECOVER from losing its lock while remapping, the
         4003  +** mutex is not released by unixShmRelease() when in RECOVER.
         4004  +**
         4005  +** *pNewMapSize is set to the size of the mapping.
         4006  +**
         4007  +** *ppBuf and *pNewMapSize might be NULL and zero if no space has
         4008  +** yet been allocated to the underlying storage.
         4009  +*/
         4010  +static int unixShmGet(
         4011  +  sqlite3_file *fd,        /* Database file holding shared memory */
         4012  +  int reqMapSize,          /* Requested size of mapping. -1 means don't care */
         4013  +  int *pNewMapSize,        /* Write new size of mapping here */
         4014  +  void **ppBuf             /* Write mapping buffer origin here */
         4015  +){
         4016  +  unixFile *pDbFd = (unixFile*)fd;
         4017  +  unixShm *p = pDbFd->pShm;
         4018  +  unixShmFile *pFile = p->pFile;
         4019  +  int rc = SQLITE_OK;
         4020  +
         4021  +  if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){
         4022  +    assert( sqlite3_mutex_notheld(pFile->mutex) );
         4023  +    sqlite3_mutex_enter(pFile->mutexBuf);
         4024  +    p->hasMutexBuf = 1;
         4025  +  }
         4026  +  sqlite3_mutex_enter(pFile->mutex);
         4027  +  if( pFile->szMap==0 || reqMapSize>pFile->szMap ){
         4028  +    int actualSize;
         4029  +    if( unixShmSize(fd, -1, &actualSize)==SQLITE_OK
         4030  +     && reqMapSize<actualSize
         4031  +    ){
         4032  +      reqMapSize = actualSize;
         4033  +    }
         4034  +    if( pFile->pMMapBuf ){
         4035  +      munmap(pFile->pMMapBuf, pFile->szMap);
         4036  +    }
         4037  +    pFile->pMMapBuf = mmap(0, reqMapSize, PROT_READ|PROT_WRITE, MAP_SHARED,
         4038  +                           pFile->h, 0);
         4039  +    pFile->szMap = pFile->pMMapBuf ? reqMapSize : 0;
         4040  +  }
         4041  +  *pNewMapSize = pFile->szMap;
         4042  +  *ppBuf = pFile->pMMapBuf;
         4043  +  sqlite3_mutex_leave(pFile->mutex);
         4044  +  return rc;
         4045  +}
         4046  +
         4047  +/*
         4048  +** Release the lock held on the shared memory segment to that other
         4049  +** threads are free to resize it if necessary.
         4050  +**
         4051  +** If the lock is not currently held, this routine is a harmless no-op.
         4052  +**
         4053  +** If the shared-memory object is in lock state RECOVER, then we do not
         4054  +** really want to release the lock, so in that case too, this routine
         4055  +** is a no-op.
         4056  +*/
         4057  +static int unixShmRelease(sqlite3_file *fd){
         4058  +  unixFile *pDbFd = (unixFile*)fd;
         4059  +  unixShm *p = pDbFd->pShm;
         4060  +
         4061  +  if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
         4062  +    assert( sqlite3_mutex_notheld(p->pFile->mutex) );
         4063  +    sqlite3_mutex_leave(p->pFile->mutexBuf);
         4064  +    p->hasMutexBuf = 0;
         4065  +  }
         4066  +  return SQLITE_OK;
         4067  +}
         4068  +
         4069  +/*
         4070  +** Symbolic names for LOCK states used for debugging.
         4071  +*/
         4072  +#ifdef SQLITE_DEBUG
         4073  +static const char *azLkName[] = {
         4074  +  "UNLOCK",
         4075  +  "READ",
         4076  +  "READ_FULL",
         4077  +  "WRITE",
         4078  +  "PENDING",
         4079  +  "CHECKPOINT",
         4080  +  "RECOVER"
         4081  +};
         4082  +#endif
         4083  +
         4084  +
         4085  +/*
         4086  +** Change the lock state for a shared-memory segment.
         4087  +*/
         4088  +static int unixShmLock(
         4089  +  sqlite3_file *fd,          /* Database file holding the shared memory */
         4090  +  int desiredLock,           /* One of SQLITE_SHM_xxxxx locking states */
         4091  +  int *pGotLock              /* The lock you actually got */
         4092  +){
         4093  +  unixFile *pDbFd = (unixFile*)fd;
         4094  +  unixShm *p = pDbFd->pShm;
         4095  +  unixShmFile *pFile = p->pFile;
         4096  +  int rc = SQLITE_PROTOCOL;
         4097  +
         4098  +  /* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never
         4099  +  ** directly requested; they are side effects from requesting
         4100  +  ** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively.
         4101  +  */
         4102  +  assert( desiredLock==SQLITE_SHM_UNLOCK
         4103  +       || desiredLock==SQLITE_SHM_READ
         4104  +       || desiredLock==SQLITE_SHM_WRITE
         4105  +       || desiredLock==SQLITE_SHM_CHECKPOINT
         4106  +       || desiredLock==SQLITE_SHM_RECOVER );
         4107  +
         4108  +  /* Return directly if this is just a lock state query, or if
         4109  +  ** the connection is already in the desired locking state.
         4110  +  */
         4111  +  if( desiredLock==p->lockState
         4112  +   || (desiredLock==SQLITE_SHM_READ && p->lockState==SQLITE_SHM_READ_FULL)
         4113  +  ){
         4114  +    OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s and got %s\n",
         4115  +             p->id, getpid(), azLkName[desiredLock], azLkName[p->lockState]));
         4116  +    if( pGotLock ) *pGotLock = p->lockState;
         4117  +    return SQLITE_OK;
         4118  +  }
         4119  +
         4120  +  OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s->%s\n",
         4121  +            p->id, getpid(), azLkName[p->lockState], azLkName[desiredLock]));
         4122  +  
         4123  +  if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
         4124  +    assert( sqlite3_mutex_notheld(pFile->mutex) );
         4125  +    sqlite3_mutex_enter(pFile->mutexBuf);
         4126  +    p->hasMutexBuf = 1;
         4127  +  }
         4128  +  sqlite3_mutex_enter(pFile->mutex);
         4129  +  switch( desiredLock ){
         4130  +    case SQLITE_SHM_UNLOCK: {
         4131  +      assert( p->lockState!=SQLITE_SHM_RECOVER );
         4132  +      unixShmUnlock(pFile, p, UNIX_SHM_A|UNIX_SHM_B|UNIX_SHM_C|UNIX_SHM_D);
         4133  +      rc = SQLITE_OK;
         4134  +      p->lockState = SQLITE_SHM_UNLOCK;
         4135  +      break;
         4136  +    }
         4137  +    case SQLITE_SHM_READ: {
         4138  +      if( p->lockState==SQLITE_SHM_UNLOCK ){
         4139  +        int nAttempt;
         4140  +        rc = SQLITE_BUSY;
         4141  +        assert( p->lockState==SQLITE_SHM_UNLOCK );
         4142  +        for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){
         4143  +          rc = unixShmSharedLock(pFile, p, UNIX_SHM_A|UNIX_SHM_B);
         4144  +          if( rc==SQLITE_BUSY ){
         4145  +            rc = unixShmSharedLock(pFile, p, UNIX_SHM_D);
         4146  +            if( rc==SQLITE_OK ){
         4147  +              p->lockState = SQLITE_SHM_READ_FULL;
         4148  +            }
         4149  +          }else{
         4150  +            unixShmUnlock(pFile, p, UNIX_SHM_B);
         4151  +            p->lockState = SQLITE_SHM_READ;
         4152  +          }
         4153  +        }
         4154  +      }else{
         4155  +       assert( p->lockState==SQLITE_SHM_WRITE
         4156  +               || p->lockState==SQLITE_SHM_RECOVER );
         4157  +        rc = unixShmSharedLock(pFile, p, UNIX_SHM_A);
         4158  +        unixShmUnlock(pFile, p, UNIX_SHM_C|UNIX_SHM_D);
         4159  +        p->lockState = SQLITE_SHM_READ;
         4160  +      }
         4161  +      break;
         4162  +    }
         4163  +    case SQLITE_SHM_WRITE: {
         4164  +      assert( p->lockState==SQLITE_SHM_READ 
         4165  +              || p->lockState==SQLITE_SHM_READ_FULL );
         4166  +      rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_C|UNIX_SHM_D);
         4167  +      if( rc==SQLITE_OK ){
         4168  +        p->lockState = SQLITE_SHM_WRITE;
         4169  +      }
         4170  +      break;
         4171  +    }
         4172  +    case SQLITE_SHM_CHECKPOINT: {
         4173  +      assert( p->lockState==SQLITE_SHM_UNLOCK
         4174  +           || p->lockState==SQLITE_SHM_PENDING
         4175  +      );
         4176  +      if( p->lockState==SQLITE_SHM_UNLOCK ){
         4177  +        rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_B|UNIX_SHM_C);
         4178  +        if( rc==SQLITE_OK ){
         4179  +          p->lockState = SQLITE_SHM_PENDING;
         4180  +        }
         4181  +      }
         4182  +      if( p->lockState==SQLITE_SHM_PENDING ){
         4183  +        rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_A);
         4184  +        if( rc==SQLITE_OK ){
         4185  +          p->lockState = SQLITE_SHM_CHECKPOINT;
         4186  +        }
         4187  +      }
         4188  +      break;
         4189  +    }
         4190  +    default: {
         4191  +      assert( desiredLock==SQLITE_SHM_RECOVER );
         4192  +      assert( p->lockState==SQLITE_SHM_READ
         4193  +           || p->lockState==SQLITE_SHM_READ_FULL
         4194  +      );
         4195  +      assert( sqlite3_mutex_held(pFile->mutexBuf) );
         4196  +      rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_C);
         4197  +      if( rc==SQLITE_OK ){
         4198  +        p->lockState = SQLITE_SHM_RECOVER;
         4199  +      }
         4200  +      break;
         4201  +    }
         4202  +  }
         4203  +  sqlite3_mutex_leave(pFile->mutex);
         4204  +  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %s\n",
         4205  +           p->id, getpid(), azLkName[p->lockState]));
         4206  +  if( pGotLock ) *pGotLock = p->lockState;
         4207  +  return rc;
         4208  +}
         4209  +
         4210  +#else
         4211  +# define unixShmOpen    0
         4212  +# define unixShmSize    0
         4213  +# define unixShmGet     0
         4214  +# define unixShmRelease 0
         4215  +# define unixShmLock    0
         4216  +# define unixShmClose   0
         4217  +#endif /* #ifndef SQLITE_OMIT_WAL */
         4218  +
  3403   4219   /*
  3404   4220   ** Here ends the implementation of all sqlite3_file methods.
  3405   4221   **
  3406   4222   ********************** End sqlite3_file Methods *******************************
  3407   4223   ******************************************************************************/
  3408   4224   
  3409   4225   /*
................................................................................
  3436   4252   **
  3437   4253   **   *  A constant sqlite3_io_methods object call METHOD that has locking
  3438   4254   **      methods CLOSE, LOCK, UNLOCK, CKRESLOCK.
  3439   4255   **
  3440   4256   **   *  An I/O method finder function called FINDER that returns a pointer
  3441   4257   **      to the METHOD object in the previous bullet.
  3442   4258   */
  3443         -#define IOMETHODS(FINDER, METHOD, CLOSE, LOCK, UNLOCK, CKLOCK)               \
         4259  +#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK)      \
  3444   4260   static const sqlite3_io_methods METHOD = {                                   \
  3445         -   1,                          /* iVersion */                                \
         4261  +   VERSION,                    /* iVersion */                                \
  3446   4262      CLOSE,                      /* xClose */                                  \
  3447   4263      unixRead,                   /* xRead */                                   \
  3448   4264      unixWrite,                  /* xWrite */                                  \
  3449   4265      unixTruncate,               /* xTruncate */                               \
  3450   4266      unixSync,                   /* xSync */                                   \
  3451   4267      unixFileSize,               /* xFileSize */                               \
  3452   4268      LOCK,                       /* xLock */                                   \
  3453   4269      UNLOCK,                     /* xUnlock */                                 \
  3454   4270      CKLOCK,                     /* xCheckReservedLock */                      \
  3455   4271      unixFileControl,            /* xFileControl */                            \
  3456   4272      unixSectorSize,             /* xSectorSize */                             \
  3457         -   unixDeviceCharacteristics   /* xDeviceCapabilities */                     \
         4273  +   unixDeviceCharacteristics,  /* xDeviceCapabilities */                     \
         4274  +   unixShmOpen,                /* xShmOpen */                                \
         4275  +   unixShmSize,                /* xShmSize */                                \
         4276  +   unixShmGet,                 /* xShmGet */                                 \
         4277  +   unixShmRelease,             /* xShmRelease */                             \
         4278  +   unixShmLock,                /* xShmLock */                                \
         4279  +   unixShmClose                /* xShmClose */                               \
  3458   4280   };                                                                           \
  3459   4281   static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
  3460   4282     UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
  3461   4283     return &METHOD;                                                            \
  3462   4284   }                                                                            \
  3463   4285   static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
  3464   4286       = FINDER##Impl;
................................................................................
  3467   4289   ** Here are all of the sqlite3_io_methods objects for each of the
  3468   4290   ** locking strategies.  Functions that return pointers to these methods
  3469   4291   ** are also created.
  3470   4292   */
  3471   4293   IOMETHODS(
  3472   4294     posixIoFinder,            /* Finder function name */
  3473   4295     posixIoMethods,           /* sqlite3_io_methods object name */
         4296  +  2,                        /* ShmOpen is enabled */
  3474   4297     unixClose,                /* xClose method */
  3475   4298     unixLock,                 /* xLock method */
  3476   4299     unixUnlock,               /* xUnlock method */
  3477   4300     unixCheckReservedLock     /* xCheckReservedLock method */
  3478   4301   )
  3479   4302   IOMETHODS(
  3480   4303     nolockIoFinder,           /* Finder function name */
  3481   4304     nolockIoMethods,          /* sqlite3_io_methods object name */
         4305  +  1,                        /* ShmOpen is disabled */
  3482   4306     nolockClose,              /* xClose method */
  3483   4307     nolockLock,               /* xLock method */
  3484   4308     nolockUnlock,             /* xUnlock method */
  3485   4309     nolockCheckReservedLock   /* xCheckReservedLock method */
  3486   4310   )
  3487   4311   IOMETHODS(
  3488   4312     dotlockIoFinder,          /* Finder function name */
  3489   4313     dotlockIoMethods,         /* sqlite3_io_methods object name */
         4314  +  1,                        /* ShmOpen is disabled */
  3490   4315     dotlockClose,             /* xClose method */
  3491   4316     dotlockLock,              /* xLock method */
  3492   4317     dotlockUnlock,            /* xUnlock method */
  3493   4318     dotlockCheckReservedLock  /* xCheckReservedLock method */
  3494   4319   )
  3495   4320   
  3496   4321   #if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
  3497   4322   IOMETHODS(
  3498   4323     flockIoFinder,            /* Finder function name */
  3499   4324     flockIoMethods,           /* sqlite3_io_methods object name */
         4325  +  1,                        /* ShmOpen is disabled */
  3500   4326     flockClose,               /* xClose method */
  3501   4327     flockLock,                /* xLock method */
  3502   4328     flockUnlock,              /* xUnlock method */
  3503   4329     flockCheckReservedLock    /* xCheckReservedLock method */
  3504   4330   )
  3505   4331   #endif
  3506   4332   
  3507   4333   #if OS_VXWORKS
  3508   4334   IOMETHODS(
  3509   4335     semIoFinder,              /* Finder function name */
  3510   4336     semIoMethods,             /* sqlite3_io_methods object name */
         4337  +  1,                        /* ShmOpen is disabled */
  3511   4338     semClose,                 /* xClose method */
  3512   4339     semLock,                  /* xLock method */
  3513   4340     semUnlock,                /* xUnlock method */
  3514   4341     semCheckReservedLock      /* xCheckReservedLock method */
  3515   4342   )
  3516   4343   #endif
  3517   4344   
  3518   4345   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  3519   4346   IOMETHODS(
  3520   4347     afpIoFinder,              /* Finder function name */
  3521   4348     afpIoMethods,             /* sqlite3_io_methods object name */
         4349  +  1,                        /* ShmOpen is disabled */
  3522   4350     afpClose,                 /* xClose method */
  3523   4351     afpLock,                  /* xLock method */
  3524   4352     afpUnlock,                /* xUnlock method */
  3525   4353     afpCheckReservedLock      /* xCheckReservedLock method */
  3526   4354   )
  3527   4355   #endif
  3528   4356   
................................................................................
  3539   4367   static int proxyClose(sqlite3_file*);
  3540   4368   static int proxyLock(sqlite3_file*, int);
  3541   4369   static int proxyUnlock(sqlite3_file*, int);
  3542   4370   static int proxyCheckReservedLock(sqlite3_file*, int*);
  3543   4371   IOMETHODS(
  3544   4372     proxyIoFinder,            /* Finder function name */
  3545   4373     proxyIoMethods,           /* sqlite3_io_methods object name */
         4374  +  1,                        /* ShmOpen is disabled */
  3546   4375     proxyClose,               /* xClose method */
  3547   4376     proxyLock,                /* xLock method */
  3548   4377     proxyUnlock,              /* xUnlock method */
  3549   4378     proxyCheckReservedLock    /* xCheckReservedLock method */
  3550   4379   )
  3551   4380   #endif
  3552   4381   
  3553   4382   /* nfs lockd on OSX 10.3+ doesn't clear write locks when a read lock is set */
  3554   4383   #if defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
  3555   4384   IOMETHODS(
  3556   4385     nfsIoFinder,               /* Finder function name */
  3557   4386     nfsIoMethods,              /* sqlite3_io_methods object name */
         4387  +  1,                         /* ShmOpen is disabled */
  3558   4388     unixClose,                 /* xClose method */
  3559   4389     unixLock,                  /* xLock method */
  3560   4390     nfsUnlock,                 /* xUnlock method */
  3561   4391     unixCheckReservedLock      /* xCheckReservedLock method */
  3562   4392   )
  3563   4393   #endif
  3564   4394   
................................................................................
  3704   4534     UNUSED_PARAMETER(isDelete);
  3705   4535   
  3706   4536     OSTRACE3("OPEN    %-3d %s\n", h, zFilename);    
  3707   4537     pNew->h = h;
  3708   4538     pNew->dirfd = dirfd;
  3709   4539     SET_THREADID(pNew);
  3710   4540     pNew->fileFlags = 0;
         4541  +  assert( zFilename==0 || zFilename[0]=='/' );  /* Never a relative pathname */
         4542  +  pNew->zPath = zFilename;
  3711   4543   
  3712   4544   #if OS_VXWORKS
  3713   4545     pNew->pId = vxworksFindFileId(zFilename);
  3714   4546     if( pNew->pId==0 ){
  3715   4547       noLock = 1;
  3716   4548       rc = SQLITE_NOMEM;
  3717   4549     }
................................................................................
  4571   5403   static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
  4572   5404     UNUSED_PARAMETER(NotUsed);
  4573   5405     UNUSED_PARAMETER(NotUsed2);
  4574   5406     UNUSED_PARAMETER(NotUsed3);
  4575   5407     return 0;
  4576   5408   }
  4577   5409   
  4578         -#ifndef SQLITE_OMIT_WAL
  4579         -
  4580         -/* Forward reference */
  4581         -typedef struct unixShm unixShm;
  4582         -typedef struct unixShmFile unixShmFile;
  4583         -
  4584         -/*
  4585         -** Object used to represent a single file opened and mmapped to provide
  4586         -** shared memory.  When multiple threads all reference the same
  4587         -** log-summary, each thread has its own unixFile object, but they all
  4588         -** point to a single instance of this object.  In other words, each
  4589         -** log-summary is opened only once per process.
  4590         -**
  4591         -** unixMutexHeld() must be true when creating or destroying
  4592         -** this object or while reading or writing the following fields:
  4593         -**
  4594         -**      nRef
  4595         -**      pNext 
  4596         -**
  4597         -** The following fields are read-only after the object is created:
  4598         -** 
  4599         -**      fid
  4600         -**      zFilename
  4601         -**
  4602         -** Either unixShmFile.mutex must be held or unixShmFile.nRef==0 and
  4603         -** unixMutexHeld() is true when reading or writing any other field
  4604         -** in this structure.
  4605         -**
  4606         -** To avoid deadlocks, mutex and mutexBuf are always released in the
  4607         -** reverse order that they are acquired.  mutexBuf is always acquired
  4608         -** first and released last.  This invariant is check by asserting
  4609         -** sqlite3_mutex_notheld() on mutex whenever mutexBuf is acquired or
  4610         -** released.
  4611         -*/
  4612         -struct unixShmFile {
  4613         -  struct unixFileId fid;     /* Unique file identifier */
  4614         -  sqlite3_mutex *mutex;      /* Mutex to access this object */
  4615         -  sqlite3_mutex *mutexBuf;   /* Mutex to access zBuf[] */
  4616         -  char *zFilename;           /* Name of the file */
  4617         -  int h;                     /* Open file descriptor */
  4618         -  int szMap;                 /* Size of the mapping of file into memory */
  4619         -  char *pMMapBuf;            /* Where currently mmapped().  NULL if unmapped */
  4620         -  int nRef;                  /* Number of unixShm objects pointing to this */
  4621         -  unixShm *pFirst;           /* All unixShm objects pointing to this */
  4622         -  unixShmFile *pNext;        /* Next in list of all unixShmFile objects */
  4623         -#ifdef SQLITE_DEBUG
  4624         -  u8 exclMask;               /* Mask of exclusive locks held */
  4625         -  u8 sharedMask;             /* Mask of shared locks held */
  4626         -  u8 nextShmId;              /* Next available unixShm.id value */
  4627         -#endif
  4628         -};
  4629         -
  4630         -/*
  4631         -** A global array of all unixShmFile objects.
  4632         -**
  4633         -** The unixMutexHeld() must be true while reading or writing this list.
  4634         -*/
  4635         -static unixShmFile *unixShmFileList = 0;
  4636         -
  4637         -/*
  4638         -** Structure used internally by this VFS to record the state of an
  4639         -** open shared memory connection.
  4640         -**
  4641         -** unixShm.pFile->mutex must be held while reading or writing the
  4642         -** unixShm.pNext and unixShm.locks[] elements.
  4643         -**
  4644         -** The unixShm.pFile element is initialized when the object is created
  4645         -** and is read-only thereafter.
  4646         -*/
  4647         -struct unixShm {
  4648         -  unixShmFile *pFile;        /* The underlying unixShmFile object */
  4649         -  unixShm *pNext;            /* Next unixShm with the same unixShmFile */
  4650         -  u8 lockState;              /* Current lock state */
  4651         -  u8 hasMutex;               /* True if holding the unixShmFile mutex */
  4652         -  u8 hasMutexBuf;            /* True if holding pFile->mutexBuf */
  4653         -  u8 sharedMask;             /* Mask of shared locks held */
  4654         -  u8 exclMask;               /* Mask of exclusive locks held */
  4655         -#ifdef SQLITE_DEBUG
  4656         -  u8 id;                     /* Id of this connection with its unixShmFile */
  4657         -#endif
  4658         -};
  4659         -
  4660         -/*
  4661         -** Size increment by which shared memory grows
  4662         -*/
  4663         -#define SQLITE_UNIX_SHM_INCR  4096
  4664         -
  4665         -/*
  4666         -** Constants used for locking
  4667         -*/
  4668         -#define UNIX_SHM_BASE      32        /* Byte offset of the first lock byte */
  4669         -#define UNIX_SHM_DMS       0x01      /* Mask for Dead-Man-Switch lock */
  4670         -#define UNIX_SHM_A         0x10      /* Mask for region locks... */
  4671         -#define UNIX_SHM_B         0x20
  4672         -#define UNIX_SHM_C         0x40
  4673         -#define UNIX_SHM_D         0x80
  4674         -
  4675         -#ifdef SQLITE_DEBUG
  4676         -/*
  4677         -** Return a pointer to a nul-terminated string in static memory that
  4678         -** describes a locking mask.  The string is of the form "MSABCD" with
  4679         -** each character representing a lock.  "M" for MUTEX, "S" for DMS, 
  4680         -** and "A" through "D" for the region locks.  If a lock is held, the
  4681         -** letter is shown.  If the lock is not held, the letter is converted
  4682         -** to ".".
  4683         -**
  4684         -** This routine is for debugging purposes only and does not appear
  4685         -** in a production build.
  4686         -*/
  4687         -static const char *unixShmLockString(u8 mask){
  4688         -  static char zBuf[48];
  4689         -  static int iBuf = 0;
  4690         -  char *z;
  4691         -
  4692         -  z = &zBuf[iBuf];
  4693         -  iBuf += 8;
  4694         -  if( iBuf>=sizeof(zBuf) ) iBuf = 0;
  4695         -
  4696         -  z[0] = (mask & UNIX_SHM_DMS)   ? 'S' : '.';
  4697         -  z[1] = (mask & UNIX_SHM_A)     ? 'A' : '.';
  4698         -  z[2] = (mask & UNIX_SHM_B)     ? 'B' : '.';
  4699         -  z[3] = (mask & UNIX_SHM_C)     ? 'C' : '.';
  4700         -  z[4] = (mask & UNIX_SHM_D)     ? 'D' : '.';
  4701         -  z[5] = 0;
  4702         -  return z;
  4703         -}
  4704         -#endif /* SQLITE_DEBUG */
  4705         -
  4706         -/*
  4707         -** Apply posix advisory locks for all bytes identified in lockMask.
  4708         -**
  4709         -** lockMask might contain multiple bits but all bits are guaranteed
  4710         -** to be contiguous.
  4711         -**
  4712         -** Locks block if the mask is exactly UNIX_SHM_C and are non-blocking
  4713         -** otherwise.
  4714         -*/
  4715         -static int unixShmSystemLock(
  4716         -  unixShmFile *pFile,   /* Apply locks to this open shared-memory segment */
  4717         -  int lockType,         /* F_UNLCK, F_RDLCK, or F_WRLCK */
  4718         -  u8 lockMask           /* Which bytes to lock or unlock */
  4719         -){
  4720         -  struct flock f;       /* The posix advisory locking structure */
  4721         -  int lockOp;           /* The opcode for fcntl() */
  4722         -  int i;                /* Offset into the locking byte range */
  4723         -  int rc;               /* Result code form fcntl() */
  4724         -  u8 mask;              /* Mask of bits in lockMask */
  4725         -
  4726         -  /* Access to the unixShmFile object is serialized by the caller */
  4727         -  assert( sqlite3_mutex_held(pFile->mutex) || pFile->nRef==0 );
  4728         -
  4729         -  /* Initialize the locking parameters */
  4730         -  memset(&f, 0, sizeof(f));
  4731         -  f.l_type = lockType;
  4732         -  f.l_whence = SEEK_SET;
  4733         -  if( lockMask==UNIX_SHM_C && lockType!=F_UNLCK ){
  4734         -    lockOp = F_SETLKW;
  4735         -    OSTRACE(("SHM-LOCK requesting blocking lock\n"));
  4736         -  }else{
  4737         -    lockOp = F_SETLK;
  4738         -  }
  4739         -
  4740         -  /* Find the first bit in lockMask that is set */
  4741         -  for(i=0, mask=0x01; mask!=0 && (lockMask&mask)==0; mask <<= 1, i++){}
  4742         -  assert( mask!=0 );
  4743         -  f.l_start = i+UNIX_SHM_BASE;
  4744         -  f.l_len = 1;
  4745         -
  4746         -  /* Extend the locking range for each additional bit that is set */
  4747         -  mask <<= 1;
  4748         -  while( mask!=0 && (lockMask & mask)!=0 ){
  4749         -    f.l_len++;
  4750         -    mask <<= 1;
  4751         -  }
  4752         -
  4753         -  /* Verify that all bits set in lockMask are contiguous */
  4754         -  assert( mask==0 || (lockMask & ~(mask | (mask-1)))==0 );
  4755         -
  4756         -  /* Acquire the system-level lock */
  4757         -  rc = fcntl(pFile->h, lockOp, &f);
  4758         -  rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
  4759         -
  4760         -  /* Update the global lock state and do debug tracing */
  4761         -#ifdef SQLITE_DEBUG
  4762         -  OSTRACE(("SHM-LOCK "));
  4763         -  if( rc==SQLITE_OK ){
  4764         -    if( lockType==F_UNLCK ){
  4765         -      OSTRACE(("unlock ok"));
  4766         -      pFile->exclMask &= ~lockMask;
  4767         -      pFile->sharedMask &= ~lockMask;
  4768         -    }else if( lockType==F_RDLCK ){
  4769         -      OSTRACE(("read-lock ok"));
  4770         -      pFile->exclMask &= ~lockMask;
  4771         -      pFile->sharedMask |= lockMask;
  4772         -    }else{
  4773         -      assert( lockType==F_WRLCK );
  4774         -      OSTRACE(("write-lock ok"));
  4775         -      pFile->exclMask |= lockMask;
  4776         -      pFile->sharedMask &= ~lockMask;
  4777         -    }
  4778         -  }else{
  4779         -    if( lockType==F_UNLCK ){
  4780         -      OSTRACE(("unlock failed"));
  4781         -    }else if( lockType==F_RDLCK ){
  4782         -      OSTRACE(("read-lock failed"));
  4783         -    }else{
  4784         -      assert( lockType==F_WRLCK );
  4785         -      OSTRACE(("write-lock failed"));
  4786         -    }
  4787         -  }
  4788         -  OSTRACE((" - change requested %s - afterwards %s:%s\n",
  4789         -           unixShmLockString(lockMask),
  4790         -           unixShmLockString(pFile->sharedMask),
  4791         -           unixShmLockString(pFile->exclMask)));
  4792         -#endif
  4793         -
  4794         -  return rc;        
  4795         -}
  4796         -
  4797         -/*
  4798         -** For connection p, unlock all of the locks identified by the unlockMask
  4799         -** parameter.
  4800         -*/
  4801         -static int unixShmUnlock(
  4802         -  unixShmFile *pFile,   /* The underlying shared-memory file */
  4803         -  unixShm *p,           /* The connection to be unlocked */
  4804         -  u8 unlockMask         /* Mask of locks to be unlocked */
  4805         -){
  4806         -  int rc;      /* Result code */
  4807         -  unixShm *pX; /* For looping over all sibling connections */
  4808         -  u8 allMask;  /* Union of locks held by connections other than "p" */
  4809         -
  4810         -  /* Access to the unixShmFile object is serialized by the caller */
  4811         -  assert( sqlite3_mutex_held(pFile->mutex) );
  4812         -
  4813         -  /* Compute locks held by sibling connections */
  4814         -  allMask = 0;
  4815         -  for(pX=pFile->pFirst; pX; pX=pX->pNext){
  4816         -    if( pX==p ) continue;
  4817         -    assert( (pX->exclMask & (p->exclMask|p->sharedMask))==0 );
  4818         -    allMask |= pX->sharedMask;
  4819         -  }
  4820         -
  4821         -  /* Unlock the system-level locks */
  4822         -  if( (unlockMask & allMask)!=unlockMask ){
  4823         -    rc = unixShmSystemLock(pFile, F_UNLCK, unlockMask & ~allMask);
  4824         -  }else{
  4825         -    rc = SQLITE_OK;
  4826         -  }
  4827         -
  4828         -  /* Undo the local locks */
  4829         -  if( rc==SQLITE_OK ){
  4830         -    p->exclMask &= ~unlockMask;
  4831         -    p->sharedMask &= ~unlockMask;
  4832         -  } 
  4833         -  return rc;
  4834         -}
  4835         -
  4836         -/*
  4837         -** Get reader locks for connection p on all locks in the readMask parameter.
  4838         -*/
  4839         -static int unixShmSharedLock(
  4840         -  unixShmFile *pFile,   /* The underlying shared-memory file */
  4841         -  unixShm *p,           /* The connection to get the shared locks */
  4842         -  u8 readMask           /* Mask of shared locks to be acquired */
  4843         -){
  4844         -  int rc;        /* Result code */
  4845         -  unixShm *pX;   /* For looping over all sibling connections */
  4846         -  u8 allShared;  /* Union of locks held by connections other than "p" */
  4847         -
  4848         -  /* Access to the unixShmFile object is serialized by the caller */
  4849         -  assert( sqlite3_mutex_held(pFile->mutex) );
  4850         -
  4851         -  /* Find out which shared locks are already held by sibling connections.
  4852         -  ** If any sibling already holds an exclusive lock, go ahead and return
  4853         -  ** SQLITE_BUSY.
  4854         -  */
  4855         -  allShared = 0;
  4856         -  for(pX=pFile->pFirst; pX; pX=pX->pNext){
  4857         -    if( pX==p ) continue;
  4858         -    if( (pX->exclMask & readMask)!=0 ) return SQLITE_BUSY;
  4859         -    allShared |= pX->sharedMask;
  4860         -  }
  4861         -
  4862         -  /* Get shared locks at the system level, if necessary */
  4863         -  if( (~allShared) & readMask ){
  4864         -    rc = unixShmSystemLock(pFile, F_RDLCK, readMask);
  4865         -  }else{
  4866         -    rc = SQLITE_OK;
  4867         -  }
  4868         -
  4869         -  /* Get the local shared locks */
  4870         -  if( rc==SQLITE_OK ){
  4871         -    p->sharedMask |= readMask;
  4872         -  }
  4873         -  return rc;
  4874         -}
  4875         -
  4876         -/*
  4877         -** For connection p, get an exclusive lock on all locks identified in
  4878         -** the writeMask parameter.
  4879         -*/
  4880         -static int unixShmExclusiveLock(
  4881         -  unixShmFile *pFile,    /* The underlying shared-memory file */
  4882         -  unixShm *p,            /* The connection to get the exclusive locks */
  4883         -  u8 writeMask           /* Mask of exclusive locks to be acquired */
  4884         -){
  4885         -  int rc;        /* Result code */
  4886         -  unixShm *pX;   /* For looping over all sibling connections */
  4887         -
  4888         -  /* Access to the unixShmFile object is serialized by the caller */
  4889         -  assert( sqlite3_mutex_held(pFile->mutex) );
  4890         -
  4891         -  /* Make sure no sibling connections hold locks that will block this
  4892         -  ** lock.  If any do, return SQLITE_BUSY right away.
  4893         -  */
  4894         -  for(pX=pFile->pFirst; pX; pX=pX->pNext){
  4895         -    if( pX==p ) continue;
  4896         -    if( (pX->exclMask & writeMask)!=0 ) return SQLITE_BUSY;
  4897         -    if( (pX->sharedMask & writeMask)!=0 ) return SQLITE_BUSY;
  4898         -  }
  4899         -
  4900         -  /* Get the exclusive locks at the system level.  Then if successful
  4901         -  ** also mark the local connection as being locked.
  4902         -  */
  4903         -  rc = unixShmSystemLock(pFile, F_WRLCK, writeMask);
  4904         -  if( rc==SQLITE_OK ){
  4905         -    p->sharedMask &= ~writeMask;
  4906         -    p->exclMask |= writeMask;
  4907         -  }
  4908         -  return rc;
  4909         -}
  4910         -
  4911         -/*
  4912         -** Purge the unixShmFileList list of all entries with unixShmFile.nRef==0.
  4913         -**
  4914         -** This is not a VFS shared-memory method; it is a utility function called
  4915         -** by VFS shared-memory methods.
  4916         -*/
  4917         -static void unixShmPurge(void){
  4918         -  unixShmFile **pp;
  4919         -  unixShmFile *p;
  4920         -  assert( unixMutexHeld() );
  4921         -  pp = &unixShmFileList;
  4922         -  while( (p = *pp)!=0 ){
  4923         -    if( p->nRef==0 ){
  4924         -      if( p->mutex ) sqlite3_mutex_free(p->mutex);
  4925         -      if( p->mutexBuf ) sqlite3_mutex_free(p->mutexBuf);
  4926         -      if( p->h>=0 ) close(p->h);
  4927         -      *pp = p->pNext;
  4928         -      sqlite3_free(p);
  4929         -    }else{
  4930         -      pp = &p->pNext;
  4931         -    }
  4932         -  }
  4933         -}
  4934         -
  4935         -/*
  4936         -** Open a shared-memory area.  This particular implementation uses
  4937         -** mmapped files.
  4938         -**
  4939         -** zName is a filename used to identify the shared-memory area.  The
  4940         -** implementation does not (and perhaps should not) use this name
  4941         -** directly, but rather use it as a template for finding an appropriate
  4942         -** name for the shared-memory storage.  In this implementation, the
  4943         -** string "-index" is appended to zName and used as the name of the
  4944         -** mmapped file.
  4945         -**
  4946         -** When opening a new shared-memory file, if no other instances of that
  4947         -** file are currently open, in this process or in other processes, then
  4948         -** the file must be truncated to zero length or have its header cleared.
  4949         -*/
  4950         -static int unixShmOpen(
  4951         -  sqlite3_vfs *pVfs,    /* The VFS */
  4952         -  const char *zName,    /* Name of the corresponding database file */
  4953         -  sqlite3_shm **pShm    /* Write the unixShm object created here */
  4954         -){
  4955         -  struct unixShm *p = 0;             /* The connection to be opened */
  4956         -  struct unixShmFile *pFile = 0;     /* The underlying mmapped file */
  4957         -  int rc;                            /* Result code */
  4958         -  struct unixFileId fid;             /* Unix file identifier */
  4959         -  struct unixShmFile *pNew;          /* Newly allocated pFile */
  4960         -  struct stat sStat;                 /* Result from stat() an fstat() */
  4961         -  int nName;                         /* Size of zName in bytes */
  4962         -
  4963         -  /* Allocate space for the new sqlite3_shm object.  Also speculatively
  4964         -  ** allocate space for a new unixShmFile and filename.
  4965         -  */
  4966         -  p = sqlite3_malloc( sizeof(*p) );
  4967         -  if( p==0 ) return SQLITE_NOMEM;
  4968         -  memset(p, 0, sizeof(*p));
  4969         -  nName = strlen(zName);
  4970         -  pNew = sqlite3_malloc( sizeof(*pFile) + nName + 15 );
  4971         -  if( pNew==0 ){
  4972         -    sqlite3_free(p);
  4973         -    return SQLITE_NOMEM;
  4974         -  }
  4975         -  memset(pNew, 0, sizeof(*pNew));
  4976         -  pNew->zFilename = (char*)&pNew[1];
  4977         -  sqlite3_snprintf(nName+12, pNew->zFilename, "%s-wal-index", zName);
  4978         -
  4979         -  /* Look to see if there is an existing unixShmFile that can be used.
  4980         -  ** If no matching unixShmFile currently exists, create a new one.
  4981         -  */
  4982         -  unixEnterMutex();
  4983         -  rc = stat(pNew->zFilename, &sStat);
  4984         -  if( rc==0 ){
  4985         -    memset(&fid, 0, sizeof(fid));
  4986         -    fid.dev = sStat.st_dev;
  4987         -    fid.ino = sStat.st_ino;
  4988         -    for(pFile = unixShmFileList; pFile; pFile=pFile->pNext){
  4989         -      if( memcmp(&pFile->fid, &fid, sizeof(fid))==0 ) break;
  4990         -    }
  4991         -  }
  4992         -  if( pFile ){
  4993         -    sqlite3_free(pNew);
  4994         -  }else{
  4995         -    pFile = pNew;
  4996         -    pNew = 0;
  4997         -    pFile->h = -1;
  4998         -    pFile->pNext = unixShmFileList;
  4999         -    unixShmFileList = pFile;
  5000         -
  5001         -    pFile->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  5002         -    if( pFile->mutex==0 ){
  5003         -      rc = SQLITE_NOMEM;
  5004         -      goto shm_open_err;
  5005         -    }
  5006         -    pFile->mutexBuf = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
  5007         -    if( pFile->mutexBuf==0 ){
  5008         -      rc = SQLITE_NOMEM;
  5009         -      goto shm_open_err;
  5010         -    }
  5011         -
  5012         -    pFile->h = open(pFile->zFilename, O_RDWR|O_CREAT, 0664);
  5013         -    if( pFile->h<0 ){
  5014         -      rc = SQLITE_CANTOPEN_BKPT;
  5015         -      goto shm_open_err;
  5016         -    }
  5017         -
  5018         -    rc = fstat(pFile->h, &sStat);
  5019         -    if( rc ){
  5020         -      rc = SQLITE_CANTOPEN_BKPT;
  5021         -      goto shm_open_err;
  5022         -    }
  5023         -    pFile->fid.dev = sStat.st_dev;
  5024         -    pFile->fid.ino = sStat.st_ino;
  5025         -
  5026         -    /* Check to see if another process is holding the dead-man switch.
  5027         -    ** If not, truncate the file to zero length. 
  5028         -    */
  5029         -    if( unixShmSystemLock(pFile, F_WRLCK, UNIX_SHM_DMS)==SQLITE_OK ){
  5030         -      if( ftruncate(pFile->h, 0) ){
  5031         -        rc = SQLITE_IOERR;
  5032         -      }
  5033         -    }
  5034         -    if( rc==SQLITE_OK ){
  5035         -      rc = unixShmSystemLock(pFile, F_RDLCK, UNIX_SHM_DMS);
  5036         -    }
  5037         -    if( rc ) goto shm_open_err;
  5038         -  }
  5039         -
  5040         -  /* Make the new connection a child of the unixShmFile */
  5041         -  p->pFile = pFile;
  5042         -  p->pNext = pFile->pFirst;
  5043         -#ifdef SQLITE_DEBUG
  5044         -  p->id = pFile->nextShmId++;
  5045         -#endif
  5046         -  pFile->pFirst = p;
  5047         -  pFile->nRef++;
  5048         -  *pShm = (sqlite3_shm*)p;
  5049         -  unixLeaveMutex();
  5050         -  return SQLITE_OK;
  5051         -
  5052         -  /* Jump here on any error */
  5053         -shm_open_err:
  5054         -  unixShmPurge();                 /* This call frees pFile if required */
  5055         -  sqlite3_free(p);
  5056         -  sqlite3_free(pNew);
  5057         -  *pShm = 0;
  5058         -  unixLeaveMutex();
  5059         -  return rc;
  5060         -}
  5061         -
  5062         -/*
  5063         -** Close a connection to shared-memory.  Delete the underlying 
  5064         -** storage if deleteFlag is true.
  5065         -*/
  5066         -static int unixShmClose(
  5067         -  sqlite3_vfs *pVfs,         /* The VFS */
  5068         -  sqlite3_shm *pSharedMem,   /* The shared-memory to be closed */
  5069         -  int deleteFlag             /* Delete after closing if true */
  5070         -){
  5071         -  unixShm *p;            /* The connection to be closed */
  5072         -  unixShmFile *pFile;    /* The underlying shared-memory file */
  5073         -  unixShm **pp;          /* For looping over sibling connections */
  5074         -
  5075         -  UNUSED_PARAMETER(pVfs);
  5076         -  if( pSharedMem==0 ) return SQLITE_OK;
  5077         -  p = (struct unixShm*)pSharedMem;
  5078         -  pFile = p->pFile;
  5079         -
  5080         -  /* Verify that the connection being closed holds no locks */
  5081         -  assert( p->exclMask==0 );
  5082         -  assert( p->sharedMask==0 );
  5083         -
  5084         -  /* Remove connection p from the set of connections associated with pFile */
  5085         -  sqlite3_mutex_enter(pFile->mutex);
  5086         -  for(pp=&pFile->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
  5087         -  *pp = p->pNext;
  5088         -
  5089         -  /* Free the connection p */
  5090         -  sqlite3_free(p);
  5091         -  sqlite3_mutex_leave(pFile->mutex);
  5092         -
  5093         -  /* If pFile->nRef has reached 0, then close the underlying
  5094         -  ** shared-memory file, too */
  5095         -  unixEnterMutex();
  5096         -  assert( pFile->nRef>0 );
  5097         -  pFile->nRef--;
  5098         -  if( pFile->nRef==0 ){
  5099         -    if( deleteFlag ) unlink(pFile->zFilename);
  5100         -    unixShmPurge();
  5101         -  }
  5102         -  unixLeaveMutex();
  5103         -
  5104         -  return SQLITE_OK;
  5105         -}
  5106         -
  5107         -/*
  5108         -** Query and/or changes the size of the underlying storage for
  5109         -** a shared-memory segment.  The reqSize parameter is the new size
  5110         -** of the underlying storage, or -1 to do just a query.  The size
  5111         -** of the underlying storage (after resizing if resizing occurs) is
  5112         -** written into pNewSize.
  5113         -**
  5114         -** This routine does not (necessarily) change the size of the mapping 
  5115         -** of the underlying storage into memory.  Use xShmGet() to change
  5116         -** the mapping size.
  5117         -**
  5118         -** The reqSize parameter is the minimum size requested.  The implementation
  5119         -** is free to expand the storage to some larger amount if it chooses.
  5120         -*/
  5121         -static int unixShmSize(
  5122         -  sqlite3_vfs *pVfs,        /* The VFS */
  5123         -  sqlite3_shm *pSharedMem,  /* Pointer returned by unixShmOpen() */
  5124         -  int reqSize,              /* Requested size.  -1 for query only */
  5125         -  int *pNewSize             /* Write new size here */
  5126         -){
  5127         -  unixShm *p = (unixShm*)pSharedMem;
  5128         -  unixShmFile *pFile = p->pFile;
  5129         -  int rc = SQLITE_OK;
  5130         -  struct stat sStat;
  5131         -
  5132         -  UNUSED_PARAMETER(pVfs);
  5133         -
  5134         -  if( reqSize>=0 ){
  5135         -    reqSize = (reqSize + SQLITE_UNIX_SHM_INCR - 1)/SQLITE_UNIX_SHM_INCR;
  5136         -    reqSize *= SQLITE_UNIX_SHM_INCR;
  5137         -    rc = ftruncate(pFile->h, reqSize);
  5138         -  }
  5139         -  if( fstat(pFile->h, &sStat)==0 ){
  5140         -    *pNewSize = (int)sStat.st_size;
  5141         -  }else{
  5142         -    *pNewSize = 0;
  5143         -    rc = SQLITE_IOERR;
  5144         -  }
  5145         -  return rc;
  5146         -}
  5147         -
  5148         -
  5149         -/*
  5150         -** Map the shared storage into memory.  The minimum size of the
  5151         -** mapping should be reqMapSize if reqMapSize is positive.  If
  5152         -** reqMapSize is zero or negative, the implementation can choose
  5153         -** whatever mapping size is convenient.
  5154         -**
  5155         -** *ppBuf is made to point to the memory which is a mapping of the
  5156         -** underlying storage.  A mutex is acquired to prevent other threads
  5157         -** from running while *ppBuf is in use in order to prevent other threads
  5158         -** remapping *ppBuf out from under this thread.  The unixShmRelease()
  5159         -** call will release the mutex.  However, if the lock state is CHECKPOINT,
  5160         -** the mutex is not acquired because CHECKPOINT will never remap the
  5161         -** buffer.  RECOVER might remap, though, so CHECKPOINT will acquire
  5162         -** the mutex if and when it promotes to RECOVER.
  5163         -**
  5164         -** RECOVER needs to be atomic.  The same mutex that prevents *ppBuf from
  5165         -** being remapped also prevents more than one thread from being in
  5166         -** RECOVER at a time.  But, RECOVER sometimes wants to remap itself.
  5167         -** To prevent RECOVER from losing its lock while remapping, the
  5168         -** mutex is not released by unixShmRelease() when in RECOVER.
  5169         -**
  5170         -** *pNewMapSize is set to the size of the mapping.
  5171         -**
  5172         -** *ppBuf and *pNewMapSize might be NULL and zero if no space has
  5173         -** yet been allocated to the underlying storage.
  5174         -*/
  5175         -static int unixShmGet(
  5176         -  sqlite3_vfs *pVfs,       /* The VFS */
  5177         -  sqlite3_shm *pSharedMem, /* Pointer returned by unixShmOpen() */
  5178         -  int reqMapSize,          /* Requested size of mapping. -1 means don't care */
  5179         -  int *pNewMapSize,        /* Write new size of mapping here */
  5180         -  void **ppBuf             /* Write mapping buffer origin here */
  5181         -){
  5182         -  unixShm *p = (unixShm*)pSharedMem;
  5183         -  unixShmFile *pFile = p->pFile;
  5184         -  int rc = SQLITE_OK;
  5185         -
  5186         -  if( p->lockState!=SQLITE_SHM_CHECKPOINT && p->hasMutexBuf==0 ){
  5187         -    assert( sqlite3_mutex_notheld(pFile->mutex) );
  5188         -    sqlite3_mutex_enter(pFile->mutexBuf);
  5189         -    p->hasMutexBuf = 1;
  5190         -  }
  5191         -  sqlite3_mutex_enter(pFile->mutex);
  5192         -  if( pFile->szMap==0 || reqMapSize>pFile->szMap ){
  5193         -    int actualSize;
  5194         -    if( unixShmSize(pVfs, pSharedMem, -1, &actualSize)==SQLITE_OK
  5195         -     && reqMapSize<actualSize
  5196         -    ){
  5197         -      reqMapSize = actualSize;
  5198         -    }
  5199         -    if( pFile->pMMapBuf ){
  5200         -      munmap(pFile->pMMapBuf, pFile->szMap);
  5201         -    }
  5202         -    pFile->pMMapBuf = mmap(0, reqMapSize, PROT_READ|PROT_WRITE, MAP_SHARED,
  5203         -                           pFile->h, 0);
  5204         -    pFile->szMap = pFile->pMMapBuf ? reqMapSize : 0;
  5205         -  }
  5206         -  *pNewMapSize = pFile->szMap;
  5207         -  *ppBuf = pFile->pMMapBuf;
  5208         -  sqlite3_mutex_leave(pFile->mutex);
  5209         -  return rc;
  5210         -}
  5211         -
  5212         -/*
  5213         -** Release the lock held on the shared memory segment to that other
  5214         -** threads are free to resize it if necessary.
  5215         -**
  5216         -** If the lock is not currently held, this routine is a harmless no-op.
  5217         -**
  5218         -** If the shared-memory object is in lock state RECOVER, then we do not
  5219         -** really want to release the lock, so in that case too, this routine
  5220         -** is a no-op.
  5221         -*/
  5222         -static int unixShmRelease(sqlite3_vfs *pVfs, sqlite3_shm *pSharedMem){
  5223         -  unixShm *p = (unixShm*)pSharedMem;
  5224         -  UNUSED_PARAMETER(pVfs);
  5225         -  if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
  5226         -    assert( sqlite3_mutex_notheld(p->pFile->mutex) );
  5227         -    sqlite3_mutex_leave(p->pFile->mutexBuf);
  5228         -    p->hasMutexBuf = 0;
  5229         -  }
  5230         -  return SQLITE_OK;
  5231         -}
  5232         -
  5233         -/*
  5234         -** Symbolic names for LOCK states used for debugging.
  5235         -*/
  5236         -#ifdef SQLITE_DEBUG
  5237         -static const char *azLkName[] = {
  5238         -  "UNLOCK",
  5239         -  "READ",
  5240         -  "READ_FULL",
  5241         -  "WRITE",
  5242         -  "PENDING",
  5243         -  "CHECKPOINT",
  5244         -  "RECOVER"
  5245         -};
  5246         -#endif
  5247         -
  5248         -
  5249         -/*
  5250         -** Change the lock state for a shared-memory segment.
  5251         -*/
  5252         -static int unixShmLock(
  5253         -  sqlite3_vfs *pVfs,         /* The VFS */
  5254         -  sqlite3_shm *pSharedMem,   /* Pointer from unixShmOpen() */
  5255         -  int desiredLock,           /* One of SQLITE_SHM_xxxxx locking states */
  5256         -  int *pGotLock              /* The lock you actually got */
  5257         -){
  5258         -  unixShm *p = (unixShm*)pSharedMem;
  5259         -  unixShmFile *pFile = p->pFile;
  5260         -  int rc = SQLITE_PROTOCOL;
  5261         -
  5262         -  UNUSED_PARAMETER(pVfs);
  5263         -
  5264         -  /* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never
  5265         -  ** directly requested; they are side effects from requesting
  5266         -  ** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively.
  5267         -  */
  5268         -  assert( desiredLock==SQLITE_SHM_UNLOCK
  5269         -       || desiredLock==SQLITE_SHM_READ
  5270         -       || desiredLock==SQLITE_SHM_WRITE
  5271         -       || desiredLock==SQLITE_SHM_CHECKPOINT
  5272         -       || desiredLock==SQLITE_SHM_RECOVER );
  5273         -
  5274         -  /* Return directly if this is just a lock state query, or if
  5275         -  ** the connection is already in the desired locking state.
  5276         -  */
  5277         -  if( desiredLock==p->lockState
  5278         -   || (desiredLock==SQLITE_SHM_READ && p->lockState==SQLITE_SHM_READ_FULL)
  5279         -  ){
  5280         -    OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s and got %s\n",
  5281         -             p->id, getpid(), azLkName[desiredLock], azLkName[p->lockState]));
  5282         -    if( pGotLock ) *pGotLock = p->lockState;
  5283         -    return SQLITE_OK;
  5284         -  }
  5285         -
  5286         -  OSTRACE(("SHM-LOCK shmid-%d, pid-%d request %s->%s\n",
  5287         -            p->id, getpid(), azLkName[p->lockState], azLkName[desiredLock]));
  5288         -  
  5289         -  if( desiredLock==SQLITE_SHM_RECOVER && !p->hasMutexBuf ){
  5290         -    assert( sqlite3_mutex_notheld(pFile->mutex) );
  5291         -    sqlite3_mutex_enter(pFile->mutexBuf);
  5292         -    p->hasMutexBuf = 1;
  5293         -  }
  5294         -  sqlite3_mutex_enter(pFile->mutex);
  5295         -  switch( desiredLock ){
  5296         -    case SQLITE_SHM_UNLOCK: {
  5297         -      assert( p->lockState!=SQLITE_SHM_RECOVER );
  5298         -      unixShmUnlock(pFile, p, UNIX_SHM_A|UNIX_SHM_B|UNIX_SHM_C|UNIX_SHM_D);
  5299         -      rc = SQLITE_OK;
  5300         -      p->lockState = SQLITE_SHM_UNLOCK;
  5301         -      break;
  5302         -    }
  5303         -    case SQLITE_SHM_READ: {
  5304         -      if( p->lockState==SQLITE_SHM_UNLOCK ){
  5305         -        int nAttempt;
  5306         -        rc = SQLITE_BUSY;
  5307         -        assert( p->lockState==SQLITE_SHM_UNLOCK );
  5308         -        for(nAttempt=0; nAttempt<5 && rc==SQLITE_BUSY; nAttempt++){
  5309         -          rc = unixShmSharedLock(pFile, p, UNIX_SHM_A|UNIX_SHM_B);
  5310         -          if( rc==SQLITE_BUSY ){
  5311         -            rc = unixShmSharedLock(pFile, p, UNIX_SHM_D);
  5312         -            if( rc==SQLITE_OK ){
  5313         -              p->lockState = SQLITE_SHM_READ_FULL;
  5314         -            }
  5315         -          }else{
  5316         -            unixShmUnlock(pFile, p, UNIX_SHM_B);
  5317         -            p->lockState = SQLITE_SHM_READ;
  5318         -          }
  5319         -        }
  5320         -      }else{
  5321         -       assert( p->lockState==SQLITE_SHM_WRITE
  5322         -               || p->lockState==SQLITE_SHM_RECOVER );
  5323         -        rc = unixShmSharedLock(pFile, p, UNIX_SHM_A);
  5324         -        unixShmUnlock(pFile, p, UNIX_SHM_C|UNIX_SHM_D);
  5325         -        p->lockState = SQLITE_SHM_READ;
  5326         -      }
  5327         -      break;
  5328         -    }
  5329         -    case SQLITE_SHM_WRITE: {
  5330         -      assert( p->lockState==SQLITE_SHM_READ 
  5331         -              || p->lockState==SQLITE_SHM_READ_FULL );
  5332         -      rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_C|UNIX_SHM_D);
  5333         -      if( rc==SQLITE_OK ){
  5334         -        p->lockState = SQLITE_SHM_WRITE;
  5335         -      }
  5336         -      break;
  5337         -    }
  5338         -    case SQLITE_SHM_CHECKPOINT: {
  5339         -      assert( p->lockState==SQLITE_SHM_UNLOCK
  5340         -           || p->lockState==SQLITE_SHM_PENDING
  5341         -      );
  5342         -      if( p->lockState==SQLITE_SHM_UNLOCK ){
  5343         -        rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_B|UNIX_SHM_C);
  5344         -        if( rc==SQLITE_OK ){
  5345         -          p->lockState = SQLITE_SHM_PENDING;
  5346         -        }
  5347         -      }
  5348         -      if( p->lockState==SQLITE_SHM_PENDING ){
  5349         -        rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_A);
  5350         -        if( rc==SQLITE_OK ){
  5351         -          p->lockState = SQLITE_SHM_CHECKPOINT;
  5352         -        }
  5353         -      }
  5354         -      break;
  5355         -    }
  5356         -    default: {
  5357         -      assert( desiredLock==SQLITE_SHM_RECOVER );
  5358         -      assert( p->lockState==SQLITE_SHM_READ
  5359         -           || p->lockState==SQLITE_SHM_READ_FULL
  5360         -      );
  5361         -      assert( sqlite3_mutex_held(pFile->mutexBuf) );
  5362         -      rc = unixShmExclusiveLock(pFile, p, UNIX_SHM_C);
  5363         -      if( rc==SQLITE_OK ){
  5364         -        p->lockState = SQLITE_SHM_RECOVER;
  5365         -      }
  5366         -      break;
  5367         -    }
  5368         -  }
  5369         -  sqlite3_mutex_leave(pFile->mutex);
  5370         -  OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %s\n",
  5371         -           p->id, getpid(), azLkName[p->lockState]));
  5372         -  if( pGotLock ) *pGotLock = p->lockState;
  5373         -  return rc;
  5374         -}
  5375         -
  5376         -#else
  5377         -# define unixShmOpen    0
  5378         -# define unixShmSize    0
  5379         -# define unixShmGet     0
  5380         -# define unixShmRelease 0
  5381         -# define unixShmLock    0
  5382         -# define unixShmClose   0
  5383         -#endif /* #ifndef SQLITE_OMIT_WAL */
  5384   5410   
  5385   5411   /*
  5386   5412   ************************ End of sqlite3_vfs methods ***************************
  5387   5413   ******************************************************************************/
  5388   5414   
  5389   5415   /******************************************************************************
  5390   5416   ************************** Begin Proxy Locking ********************************
................................................................................
  6596   6622       unixDlError,          /* xDlError */                    \
  6597   6623       unixDlSym,            /* xDlSym */                      \
  6598   6624       unixDlClose,          /* xDlClose */                    \
  6599   6625       unixRandomness,       /* xRandomness */                 \
  6600   6626       unixSleep,            /* xSleep */                      \
  6601   6627       unixCurrentTime,      /* xCurrentTime */                \
  6602   6628       unixGetLastError,     /* xGetLastError */               \
  6603         -    unixShmOpen,          /* xShmOpen */                    \
  6604         -    unixShmSize,          /* xShmSize */                    \
  6605         -    unixShmGet,           /* xShmGet */                     \
  6606         -    unixShmRelease,       /* xShmRelease */                 \
  6607         -    unixShmLock,          /* xShmLock */                    \
  6608         -    unixShmClose,         /* xShmClose */                   \
  6609   6629       0,                    /* xRename */                     \
  6610   6630       unixCurrentTimeInt64, /* xCurrentTimeInt64 */           \
  6611   6631     }
  6612   6632   
  6613   6633     /*
  6614   6634     ** All default VFSes for unix are contained in the following array.
  6615   6635     **

Changes to src/pager.c.

  3073   3073     u8 *pTmp = (u8 *)pPager->pTmpSpace;
  3074   3074   
  3075   3075     disable_simulated_io_errors();
  3076   3076     sqlite3BeginBenignMalloc();
  3077   3077     pPager->errCode = 0;
  3078   3078     pPager->exclusiveMode = 0;
  3079   3079   #ifndef SQLITE_OMIT_WAL
  3080         -  sqlite3WalClose(pPager->pWal, pPager->fd, 
         3080  +  sqlite3WalClose(pPager->pWal,
  3081   3081       (pPager->noSync ? 0 : pPager->sync_flags), 
  3082   3082       pPager->pageSize, pTmp
  3083   3083     );
  3084   3084     pPager->pWal = 0;
  3085   3085   #endif
  3086   3086     pager_reset(pPager);
  3087   3087     if( MEMDB ){
................................................................................
  5874   5874   /*
  5875   5875   ** This function is called when the user invokes "PRAGMA checkpoint".
  5876   5876   */
  5877   5877   int sqlite3PagerCheckpoint(Pager *pPager){
  5878   5878     int rc = SQLITE_OK;
  5879   5879     if( pPager->pWal ){
  5880   5880       u8 *zBuf = (u8 *)pPager->pTmpSpace;
  5881         -    rc = sqlite3WalCheckpoint(pPager->pWal, pPager->fd, 
         5881  +    rc = sqlite3WalCheckpoint(pPager->pWal,
  5882   5882           (pPager->noSync ? 0 : pPager->sync_flags),
  5883   5883           pPager->pageSize, zBuf, 
  5884   5884           pPager->xBusyHandler, pPager->pBusyHandlerArg
  5885   5885       );
  5886   5886     }
  5887   5887     return rc;
  5888   5888   }
  5889   5889   
  5890   5890   int sqlite3PagerWalCallback(Pager *pPager){
  5891   5891     return sqlite3WalCallback(pPager->pWal);
  5892   5892   }
         5893  +
         5894  +/*
         5895  +** Return true if the underlying VFS for the given pager supports the
         5896  +** primitives necessary for write-ahead logging.
         5897  +*/
         5898  +int sqlite3PagerWalSupported(Pager *pPager){
         5899  +  const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
         5900  +  return pMethods->iVersion>=2 && pMethods->xShmOpen!=0;
         5901  +}
  5893   5902   
  5894   5903   /*
  5895   5904   ** Open a connection to the write-ahead log file for pager pPager. If
  5896   5905   ** the log connection is already open, this function is a no-op.
  5897   5906   **
  5898   5907   ** The caller must be holding a SHARED lock on the database file to call
  5899   5908   ** this function.
  5900   5909   */
  5901   5910   int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen){
  5902   5911     int rc = SQLITE_OK;             /* Return code */
  5903   5912   
  5904   5913     assert( pPager->state>=PAGER_SHARED );
  5905   5914     if( !pPager->pWal ){
         5915  +    if( !sqlite3PagerWalSupported(pPager) ) return SQLITE_CANTOPEN;
  5906   5916   
  5907   5917       /* Open the connection to the log file. If this operation fails, 
  5908   5918       ** (e.g. due to malloc() failure), unlock the database file and 
  5909   5919       ** return an error code.
  5910   5920       */
  5911         -    rc = sqlite3WalOpen(pPager->pVfs, pPager->zFilename, &pPager->pWal);
         5921  +    rc = sqlite3WalOpen(pPager->pVfs, pPager->fd,
         5922  +                        pPager->zFilename, &pPager->pWal);
  5912   5923       if( rc==SQLITE_OK ){
  5913   5924         pPager->journalMode = PAGER_JOURNALMODE_WAL;
  5914   5925       }
  5915   5926     }else{
  5916   5927       *pisOpen = 1;
  5917   5928     }
  5918   5929   
................................................................................
  5940   5951     if( !pPager->pWal ){
  5941   5952       int logexists = 0;
  5942   5953       rc = sqlite3OsLock(pPager->fd, SQLITE_LOCK_SHARED);
  5943   5954       if( rc==SQLITE_OK ){
  5944   5955         rc = pagerHasWAL(pPager, &logexists);
  5945   5956       }
  5946   5957       if( rc==SQLITE_OK && logexists ){
  5947         -      rc = sqlite3WalOpen(pPager->pVfs, pPager->zFilename, &pPager->pWal);
         5958  +      rc = sqlite3WalOpen(pPager->pVfs, pPager->fd,
         5959  +                          pPager->zFilename, &pPager->pWal);
  5948   5960       }
  5949   5961     }
  5950   5962       
  5951   5963     /* Checkpoint and close the log. Because an EXCLUSIVE lock is held on
  5952   5964     ** the database file, the log and log-summary files will be deleted.
  5953   5965     */
  5954   5966     if( rc==SQLITE_OK && pPager->pWal ){
  5955   5967       rc = sqlite3OsLock(pPager->fd, SQLITE_LOCK_EXCLUSIVE);
  5956   5968       if( rc==SQLITE_OK ){
  5957         -      rc = sqlite3WalClose(pPager->pWal, pPager->fd,
  5958         -        (pPager->noSync ? 0 : pPager->sync_flags), 
         5969  +      rc = sqlite3WalClose(pPager->pWal,
         5970  +                           (pPager->noSync ? 0 : pPager->sync_flags), 
  5959   5971           pPager->pageSize, (u8*)pPager->pTmpSpace
  5960   5972         );
  5961   5973         pPager->pWal = 0;
  5962   5974       }else{
  5963   5975         /* If we cannot get an EXCLUSIVE lock, downgrade the PENDING lock
  5964   5976         ** that we did get back to SHARED. */
  5965   5977         sqlite3OsUnlock(pPager->fd, SQLITE_LOCK_SHARED);

Changes to src/pager.h.

   131    131   int sqlite3PagerCommitPhaseTwo(Pager*);
   132    132   int sqlite3PagerRollback(Pager*);
   133    133   int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
   134    134   int sqlite3PagerSavepoint(Pager *pPager, int op, int iSavepoint);
   135    135   int sqlite3PagerSharedLock(Pager *pPager);
   136    136   
   137    137   int sqlite3PagerCheckpoint(Pager *pPager);
          138  +int sqlite3PagerWalSupported(Pager *pPager);
   138    139   int sqlite3PagerWalCallback(Pager *pPager);
   139    140   int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
   140    141   int sqlite3PagerCloseWal(Pager *pPager);
   141    142   
   142    143   /* Functions used to query pager state and configuration. */
   143    144   u8 sqlite3PagerIsreadonly(Pager*);
   144    145   int sqlite3PagerRefcount(Pager*);

Changes to src/sqlite.h.in.

   649    649     int (*xFileSize)(sqlite3_file*, sqlite3_int64 *pSize);
   650    650     int (*xLock)(sqlite3_file*, int);
   651    651     int (*xUnlock)(sqlite3_file*, int);
   652    652     int (*xCheckReservedLock)(sqlite3_file*, int *pResOut);
   653    653     int (*xFileControl)(sqlite3_file*, int op, void *pArg);
   654    654     int (*xSectorSize)(sqlite3_file*);
   655    655     int (*xDeviceCharacteristics)(sqlite3_file*);
          656  +  /* Methods above are valid for version 1 */
          657  +  int (*xShmOpen)(sqlite3_file*);
          658  +  int (*xShmSize)(sqlite3_file*, int reqSize, int *pNewSize);
          659  +  int (*xShmGet)(sqlite3_file*, int reqSize, int *pSize, void**);
          660  +  int (*xShmRelease)(sqlite3_file*);
          661  +  int (*xShmLock)(sqlite3_file*, int desiredLock, int *gotLock);
          662  +  int (*xShmClose)(sqlite3_file*, int deleteFlag);
          663  +  /* Methods above are valid for version 2 */
   656    664     /* Additional methods may be added in future releases */
   657    665   };
   658    666   
   659    667   /*
   660    668   ** CAPI3REF: Standard File Control Opcodes
   661    669   **
   662    670   ** These integer constants are opcodes for the xFileControl method
................................................................................
   814    822   ** the actual number of bytes of randomness obtained.
   815    823   ** The xSleep() method causes the calling thread to sleep for at
   816    824   ** least the number of microseconds given.  The xCurrentTime()
   817    825   ** method returns a Julian Day Number for the current date and time.
   818    826   **
   819    827   */
   820    828   typedef struct sqlite3_vfs sqlite3_vfs;
   821         -typedef struct sqlite3_shm sqlite3_shm;
   822    829   struct sqlite3_vfs {
   823    830     int iVersion;            /* Structure version number (currently 2) */
   824    831     int szOsFile;            /* Size of subclassed sqlite3_file */
   825    832     int mxPathname;          /* Maximum file pathname length */
   826    833     sqlite3_vfs *pNext;      /* Next registered VFS */
   827    834     const char *zName;       /* Name of this virtual file system */
   828    835     void *pAppData;          /* Pointer to application-specific data */
................................................................................
   839    846     int (*xSleep)(sqlite3_vfs*, int microseconds);
   840    847     int (*xCurrentTime)(sqlite3_vfs*, double*);
   841    848     int (*xGetLastError)(sqlite3_vfs*, int, char *);
   842    849     /*
   843    850     ** The methods above are in version 1 of the sqlite_vfs object
   844    851     ** definition.  Those that follow are added in version 2 or later
   845    852     */
   846         -  int (*xShmOpen)(sqlite3_vfs*, const char *zName, sqlite3_shm**);
   847         -  int (*xShmSize)(sqlite3_vfs*, sqlite3_shm*, int reqSize, int *pNewSize);
   848         -  int (*xShmGet)(sqlite3_vfs*, sqlite3_shm*, int reqSize, int *pSize, void**);
   849         -  int (*xShmRelease)(sqlite3_vfs*, sqlite3_shm*);
   850         -  int (*xShmLock)(sqlite3_vfs*, sqlite3_shm*, int desiredLock, int *gotLock);
   851         -  int (*xShmClose)(sqlite3_vfs*, sqlite3_shm*, int deleteFlag);
   852    853     int (*xRename)(sqlite3_vfs*, const char *zOld, const char *zNew, int dirSync);
   853    854     int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
   854    855     /*
   855    856     ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
   856    857     ** New fields may be appended in figure versions.  The iVersion
   857    858     ** value will increment whenever this happens. 
   858    859     */

Changes to src/test6.c.

   515    515   */
   516    516   static int cfSectorSize(sqlite3_file *pFile){
   517    517     return g.iSectorSize;
   518    518   }
   519    519   static int cfDeviceCharacteristics(sqlite3_file *pFile){
   520    520     return g.iDeviceCharacteristics;
   521    521   }
          522  +
          523  +/*
          524  +** Pass-throughs for WAL support.
          525  +*/
          526  +static int cfShmOpen(sqlite3_file *pFile){
          527  +  return sqlite3OsShmOpen(((CrashFile*)pFile)->pRealFile);
          528  +}
          529  +static int cfShmSize(sqlite3_file *pFile, int reqSize, int *pNew){
          530  +  return sqlite3OsShmSize(((CrashFile*)pFile)->pRealFile, reqSize, pNew);
          531  +}
          532  +static int cfShmGet(sqlite3_file *pFile, int reqSize, int *pSize, void **pp){
          533  +  return sqlite3OsShmGet(((CrashFile*)pFile)->pRealFile, reqSize, pSize, pp);
          534  +}
          535  +static int cfShmRelease(sqlite3_file *pFile){
          536  +  return sqlite3OsShmRelease(((CrashFile*)pFile)->pRealFile);
          537  +}
          538  +static int cfShmLock(sqlite3_file *pFile, int desired, int *pGot){
          539  +  return sqlite3OsShmLock(((CrashFile*)pFile)->pRealFile, desired, pGot);
          540  +}
          541  +static int cfShmClose(sqlite3_file *pFile, int delFlag){
          542  +  return sqlite3OsShmClose(((CrashFile*)pFile)->pRealFile, delFlag);
          543  +}
          544  +
   522    545   
   523    546   static const sqlite3_io_methods CrashFileVtab = {
   524         -  1,                            /* iVersion */
          547  +  2,                            /* iVersion */
   525    548     cfClose,                      /* xClose */
   526    549     cfRead,                       /* xRead */
   527    550     cfWrite,                      /* xWrite */
   528    551     cfTruncate,                   /* xTruncate */
   529    552     cfSync,                       /* xSync */
   530    553     cfFileSize,                   /* xFileSize */
   531    554     cfLock,                       /* xLock */
   532    555     cfUnlock,                     /* xUnlock */
   533    556     cfCheckReservedLock,          /* xCheckReservedLock */
   534    557     cfFileControl,                /* xFileControl */
   535    558     cfSectorSize,                 /* xSectorSize */
   536         -  cfDeviceCharacteristics       /* xDeviceCharacteristics */
          559  +  cfDeviceCharacteristics,      /* xDeviceCharacteristics */
          560  +  cfShmOpen,                    /* xShmOpen */
          561  +  cfShmSize,                    /* xShmSize */
          562  +  cfShmGet,                     /* xShmGet */
          563  +  cfShmRelease,                 /* xShmRelease */
          564  +  cfShmLock,                    /* xShmLock */
          565  +  cfShmClose                    /* xShmClose */
   537    566   };
   538    567   
   539    568   /*
   540    569   ** Application data for the crash VFS
   541    570   */
   542    571   struct crashAppData {
   543    572     sqlite3_vfs *pOrig;                   /* Wrapped vfs structure */
................................................................................
   653    682     sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   654    683     return pVfs->xSleep(pVfs, nMicro);
   655    684   }
   656    685   static int cfCurrentTime(sqlite3_vfs *pCfVfs, double *pTimeOut){
   657    686     sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   658    687     return pVfs->xCurrentTime(pVfs, pTimeOut);
   659    688   }
   660         -static int cfShmOpen(sqlite3_vfs *pCfVfs, const char *zName, sqlite3_shm **pp){
   661         -  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   662         -  return pVfs->xShmOpen(pVfs, zName, pp);
   663         -}
   664         -static int cfShmSize(sqlite3_vfs *pCfVfs, sqlite3_shm *p,
   665         -                     int reqSize, int *pNew){
   666         -  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   667         -  return pVfs->xShmSize(pVfs, p, reqSize, pNew);
   668         -}
   669         -static int cfShmGet(sqlite3_vfs *pCfVfs, sqlite3_shm *p,
   670         -                    int reqSize, int *pSize, void **pp){
   671         -  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   672         -  return pVfs->xShmGet(pVfs, p, reqSize, pSize, pp);
   673         -}
   674         -static int cfShmRelease(sqlite3_vfs *pCfVfs, sqlite3_shm *p){
   675         -  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   676         -  return pVfs->xShmRelease(pVfs, p);
   677         -}
   678         -static int cfShmLock(sqlite3_vfs *pCfVfs, sqlite3_shm *p,
   679         -                     int desiredLock, int *gotLock){
   680         -  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   681         -  return pVfs->xShmLock(pVfs, p, desiredLock, gotLock);
   682         -}
   683         -static int cfShmClose(sqlite3_vfs *pCfVfs, sqlite3_shm *p, int delFlag){
   684         -  sqlite3_vfs *pVfs = (sqlite3_vfs *)pCfVfs->pAppData;
   685         -  return pVfs->xShmClose(pVfs, p, delFlag);
   686         -}
   687    689   
   688    690   static int processDevSymArgs(
   689    691     Tcl_Interp *interp,
   690    692     int objc,
   691    693     Tcl_Obj *CONST objv[],
   692    694     int *piDeviceChar,
   693    695     int *piSectorSize
................................................................................
   806    808       cfDlError,            /* xDlError */
   807    809       cfDlSym,              /* xDlSym */
   808    810       cfDlClose,            /* xDlClose */
   809    811       cfRandomness,         /* xRandomness */
   810    812       cfSleep,              /* xSleep */
   811    813       cfCurrentTime,        /* xCurrentTime */
   812    814       0,                    /* xGetlastError */
   813         -    cfShmOpen,            /* xShmOpen */
   814         -    cfShmSize,            /* xShmSize */
   815         -    cfShmGet,             /* xShmGet */
   816         -    cfShmRelease,         /* xShmRelease */
   817         -    cfShmLock,            /* xShmLock */
   818         -    cfShmClose,           /* xShmClose */
   819    815       0,                    /* xRename */
   820    816       0,                    /* xCurrentTimeInt64 */
   821    817     };
   822    818   
   823    819     if( objc!=2 ){
   824    820       Tcl_WrongNumArgs(interp, 1, objv, "ENABLE");
   825    821       return TCL_ERROR;
................................................................................
   834    830     }
   835    831   
   836    832     if( crashVfs.pAppData==0 ){
   837    833       sqlite3_vfs *pOriginalVfs = sqlite3_vfs_find(0);
   838    834       crashVfs.mxPathname = pOriginalVfs->mxPathname;
   839    835       crashVfs.pAppData = (void *)pOriginalVfs;
   840    836       crashVfs.szOsFile = sizeof(CrashFile) + pOriginalVfs->szOsFile;
   841         -    if( pOriginalVfs->iVersion<2 || pOriginalVfs->xShmOpen==0 ){
   842         -      crashVfs.xShmOpen = 0;
   843         -    }else{
   844         -      crashVfs.xShmOpen = cfShmOpen;
   845         -    }
   846    837       sqlite3_vfs_register(&crashVfs, 0);
   847    838     }else{
   848    839       crashVfs.pAppData = 0;
   849    840       sqlite3_vfs_unregister(&crashVfs);
   850    841     }
   851    842   
   852    843     return TCL_OK;

Changes to src/test_devsym.c.

    46     46   static int devsymFileSize(sqlite3_file*, sqlite3_int64 *pSize);
    47     47   static int devsymLock(sqlite3_file*, int);
    48     48   static int devsymUnlock(sqlite3_file*, int);
    49     49   static int devsymCheckReservedLock(sqlite3_file*, int *);
    50     50   static int devsymFileControl(sqlite3_file*, int op, void *pArg);
    51     51   static int devsymSectorSize(sqlite3_file*);
    52     52   static int devsymDeviceCharacteristics(sqlite3_file*);
           53  +static int devsymShmOpen(sqlite3_file*);
           54  +static int devsymShmSize(sqlite3_file*,int,int*);
           55  +static int devsymShmGet(sqlite3_file*,int,int*,void**);
           56  +static int devsymShmRelease(sqlite3_file*);
           57  +static int devsymShmLock(sqlite3_file*,int,int*);
           58  +static int devsymShmClose(sqlite3_file*,int);
    53     59   
    54     60   /*
    55     61   ** Method declarations for devsym_vfs.
    56     62   */
    57     63   static int devsymOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
    58     64   static int devsymDelete(sqlite3_vfs*, const char *zName, int syncDir);
    59     65   static int devsymAccess(sqlite3_vfs*, const char *zName, int flags, int *);
................................................................................
    64     70   static void (*devsymDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
    65     71   static void devsymDlClose(sqlite3_vfs*, void*);
    66     72   #endif /* SQLITE_OMIT_LOAD_EXTENSION */
    67     73   static int devsymRandomness(sqlite3_vfs*, int nByte, char *zOut);
    68     74   static int devsymSleep(sqlite3_vfs*, int microseconds);
    69     75   static int devsymCurrentTime(sqlite3_vfs*, double*);
    70     76   
    71         -static int devsymShmOpen(sqlite3_vfs *, const char *, sqlite3_shm **);
    72         -static int devsymShmSize(sqlite3_vfs*, sqlite3_shm *, int , int *);
    73         -static int devsymShmGet(sqlite3_vfs*, sqlite3_shm *, int , int *, void **);
    74         -static int devsymShmRelease(sqlite3_vfs*, sqlite3_shm *);
    75         -static int devsymShmLock(sqlite3_vfs*, sqlite3_shm *, int , int *);
    76         -static int devsymShmClose(sqlite3_vfs*, sqlite3_shm *, int);
    77         -
    78     77   static sqlite3_vfs devsym_vfs = {
    79     78     2,                     /* iVersion */
    80     79     sizeof(devsym_file),      /* szOsFile */
    81     80     DEVSYM_MAX_PATHNAME,      /* mxPathname */
    82     81     0,                     /* pNext */
    83     82     DEVSYM_VFS_NAME,          /* zName */
    84     83     0,                     /* pAppData */
................................................................................
    97     96     0,                        /* xDlSym */
    98     97     0,                        /* xDlClose */
    99     98   #endif /* SQLITE_OMIT_LOAD_EXTENSION */
   100     99     devsymRandomness,         /* xRandomness */
   101    100     devsymSleep,              /* xSleep */
   102    101     devsymCurrentTime,        /* xCurrentTime */
   103    102     0,                        /* xGetLastError */
   104         -  devsymShmOpen,
   105         -  devsymShmSize,
   106         -  devsymShmGet,
   107         -  devsymShmRelease,
   108         -  devsymShmLock,
   109         -  devsymShmClose,
   110         -  0,
   111         -  0,
          103  +  0,                        /* xRename */
          104  +  0                         /* xCurrentTimeInt64 */
   112    105   };
   113    106   
   114    107   static sqlite3_io_methods devsym_io_methods = {
   115         -  1,                            /* iVersion */
          108  +  2,                                /* iVersion */
   116    109     devsymClose,                      /* xClose */
   117    110     devsymRead,                       /* xRead */
   118    111     devsymWrite,                      /* xWrite */
   119    112     devsymTruncate,                   /* xTruncate */
   120    113     devsymSync,                       /* xSync */
   121    114     devsymFileSize,                   /* xFileSize */
   122    115     devsymLock,                       /* xLock */
   123    116     devsymUnlock,                     /* xUnlock */
   124    117     devsymCheckReservedLock,          /* xCheckReservedLock */
   125    118     devsymFileControl,                /* xFileControl */
   126    119     devsymSectorSize,                 /* xSectorSize */
   127         -  devsymDeviceCharacteristics       /* xDeviceCharacteristics */
          120  +  devsymDeviceCharacteristics,      /* xDeviceCharacteristics */
          121  +  devsymShmOpen,                    /* xShmOpen */
          122  +  devsymShmSize,                    /* xShmSize */
          123  +  devsymShmGet,                     /* xShmGet */
          124  +  devsymShmRelease,                 /* xShmRelease */
          125  +  devsymShmLock,                    /* xShmLock */
          126  +  devsymShmClose                    /* xShmClose */
   128    127   };
   129    128   
   130    129   struct DevsymGlobal {
   131    130     sqlite3_vfs *pVfs;
   132    131     int iDeviceChar;
   133    132     int iSectorSize;
   134    133   };
................................................................................
   233    232   
   234    233   /*
   235    234   ** Return the device characteristic flags supported by an devsym-file.
   236    235   */
   237    236   static int devsymDeviceCharacteristics(sqlite3_file *pFile){
   238    237     return g.iDeviceChar;
   239    238   }
          239  +
          240  +/*
          241  +** Shared-memory methods are all pass-thrus.
          242  +*/
          243  +static int devsymShmOpen(sqlite3_file *pFile){
          244  +  devsym_file *p = (devsym_file *)pFile;
          245  +  return sqlite3OsShmOpen(p->pReal);
          246  +}
          247  +static int devsymShmSize(sqlite3_file *pFile, int reqSize, int *pSize){
          248  +  devsym_file *p = (devsym_file *)pFile;
          249  +  return sqlite3OsShmSize(p->pReal, reqSize, pSize);
          250  +}
          251  +static int devsymShmGet(sqlite3_file *pFile, int reqSz, int *pSize, void **pp){
          252  +  devsym_file *p = (devsym_file *)pFile;
          253  +  return sqlite3OsShmGet(p->pReal, reqSz, pSize, pp);
          254  +}
          255  +static int devsymShmRelease(sqlite3_file *pFile){
          256  +  devsym_file *p = (devsym_file *)pFile;
          257  +  return sqlite3OsShmRelease(p->pReal);
          258  +}
          259  +static int devsymShmLock(sqlite3_file *pFile, int desired, int *pGot){
          260  +  devsym_file *p = (devsym_file *)pFile;
          261  +  return sqlite3OsShmLock(p->pReal, desired, pGot);
          262  +}
          263  +static int devsymShmClose(sqlite3_file *pFile, int delFlag){
          264  +  devsym_file *p = (devsym_file *)pFile;
          265  +  return sqlite3OsShmClose(p->pReal, delFlag);
          266  +}
          267  +
          268  +
   240    269   
   241    270   /*
   242    271   ** Open an devsym file handle.
   243    272   */
   244    273   static int devsymOpen(
   245    274     sqlite3_vfs *pVfs,
   246    275     const char *zName,
................................................................................
   346    375   ** Return the current time as a Julian Day number in *pTimeOut.
   347    376   */
   348    377   static int devsymCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
   349    378     return g.pVfs->xCurrentTime(g.pVfs, pTimeOut);
   350    379   }
   351    380   
   352    381   
   353         -static int devsymShmOpen(
   354         -  sqlite3_vfs *pVfs, 
   355         -  const char *zName, 
   356         -  sqlite3_shm **pp
   357         -){
   358         -  return g.pVfs->xShmOpen(g.pVfs, zName, pp);
   359         -}
   360         -static int devsymShmSize(
   361         -  sqlite3_vfs *pVfs,
   362         -  sqlite3_shm *p,
   363         -  int reqSize,
   364         -  int *pNewSize
   365         -){
   366         -  return g.pVfs->xShmSize(g.pVfs, p, reqSize, pNewSize);
   367         -}
   368         -static int devsymShmGet(
   369         -  sqlite3_vfs *pVfs,
   370         -  sqlite3_shm *p, 
   371         -  int reqMapSize, 
   372         -  int *pMapSize, 
   373         -  void **pp
   374         -){
   375         -  return g.pVfs->xShmGet(g.pVfs, p, reqMapSize, pMapSize, pp);
   376         -}
   377         -static int devsymShmRelease(sqlite3_vfs *pVfs, sqlite3_shm *p){
   378         -  return g.pVfs->xShmRelease(g.pVfs, p);
   379         -}
   380         -static int devsymShmLock(
   381         -  sqlite3_vfs *pVfs,
   382         -  sqlite3_shm *p,
   383         -  int desiredLock,
   384         -  int *gotLock
   385         -){
   386         -  return g.pVfs->xShmLock(g.pVfs, p, desiredLock, gotLock);
   387         -}
   388         -static int devsymShmClose(sqlite3_vfs *pVfs, sqlite3_shm *p, int deleteFlag){
   389         -  return g.pVfs->xShmClose(g.pVfs, p, deleteFlag);
   390         -}
   391         -
   392    382   /*
   393    383   ** This procedure registers the devsym vfs with SQLite. If the argument is
   394    384   ** true, the devsym vfs becomes the new default vfs. It is the only publicly
   395    385   ** available function in this file.
   396    386   */
   397    387   void devsym_register(int iDeviceChar, int iSectorSize){
   398    388     if( g.pVfs==0 ){
   399    389       g.pVfs = sqlite3_vfs_find(0);
   400    390       devsym_vfs.szOsFile += g.pVfs->szOsFile;
   401         -    devsym_vfs.xShmOpen = (g.pVfs->xShmOpen ? devsymShmOpen : 0);
   402         -    devsym_vfs.xShmSize = (g.pVfs->xShmSize ? devsymShmSize : 0);
   403         -    devsym_vfs.xShmGet = (g.pVfs->xShmGet ? devsymShmGet : 0);
   404         -    devsym_vfs.xShmRelease = (g.pVfs->xShmRelease ? devsymShmRelease : 0);
   405         -    devsym_vfs.xShmLock = (g.pVfs->xShmLock ? devsymShmLock : 0);
   406         -    devsym_vfs.xShmClose = (g.pVfs->xShmClose ? devsymShmClose : 0);
   407    391       sqlite3_vfs_register(&devsym_vfs, 0);
   408    392     }
   409    393     if( iDeviceChar>=0 ){
   410    394       g.iDeviceChar = iDeviceChar;
   411    395     }else{
   412    396       g.iDeviceChar = 0;
   413    397     }

Changes to src/test_onefile.c.

   195    195       fsDlOpen,                                   /* xDlOpen */
   196    196       fsDlError,                                  /* xDlError */
   197    197       fsDlSym,                                    /* xDlSym */
   198    198       fsDlClose,                                  /* xDlClose */
   199    199       fsRandomness,                               /* xRandomness */
   200    200       fsSleep,                                    /* xSleep */
   201    201       fsCurrentTime,                              /* xCurrentTime */
   202         -    0,                                          /* xShmOpen */
   203         -    0,                                          /* xShmSize */
   204         -    0,                                          /* xShmLock */
   205         -    0,                                          /* xShmClose */
   206         -    0,                                          /* xShmDelete */
   207    202       0,                                          /* xRename */
   208    203       0                                           /* xCurrentTimeInt64 */
   209    204     }, 
   210    205     0,                                            /* pFileList */
   211    206     0                                             /* pParent */
   212    207   };
   213    208   
................................................................................
   220    215     fsSync,                       /* xSync */
   221    216     fsFileSize,                   /* xFileSize */
   222    217     fsLock,                       /* xLock */
   223    218     fsUnlock,                     /* xUnlock */
   224    219     fsCheckReservedLock,          /* xCheckReservedLock */
   225    220     fsFileControl,                /* xFileControl */
   226    221     fsSectorSize,                 /* xSectorSize */
   227         -  fsDeviceCharacteristics       /* xDeviceCharacteristics */
          222  +  fsDeviceCharacteristics,      /* xDeviceCharacteristics */
          223  +  0,                            /* xShmOpen */
          224  +  0,                            /* xShmSize */
          225  +  0,                            /* xShmLock */
          226  +  0,                            /* xShmClose */
          227  +  0,                            /* xShmDelete */
   228    228   };
   229    229   
   230    230   
   231    231   static sqlite3_io_methods tmp_io_methods = {
   232    232     1,                            /* iVersion */
   233    233     tmpClose,                     /* xClose */
   234    234     tmpRead,                      /* xRead */
................................................................................
   237    237     tmpSync,                      /* xSync */
   238    238     tmpFileSize,                  /* xFileSize */
   239    239     tmpLock,                      /* xLock */
   240    240     tmpUnlock,                    /* xUnlock */
   241    241     tmpCheckReservedLock,         /* xCheckReservedLock */
   242    242     tmpFileControl,               /* xFileControl */
   243    243     tmpSectorSize,                /* xSectorSize */
   244         -  tmpDeviceCharacteristics      /* xDeviceCharacteristics */
          244  +  tmpDeviceCharacteristics,     /* xDeviceCharacteristics */
          245  +  0,                            /* xShmOpen */
          246  +  0,                            /* xShmSize */
          247  +  0,                            /* xShmLock */
          248  +  0,                            /* xShmClose */
          249  +  0,                            /* xShmDelete */
   245    250   };
   246    251   
   247    252   /* Useful macros used in several places */
   248    253   #define MIN(x,y) ((x)<(y)?(x):(y))
   249    254   #define MAX(x,y) ((x)>(y)?(x):(y))
   250    255   
   251    256   

Changes to src/test_vfs.c.

    12     12   **
    13     13   */
    14     14   #if SQLITE_TEST          /* This file is used for testing only */
    15     15   
    16     16   #include "sqlite3.h"
    17     17   #include "sqliteInt.h"
    18     18   
    19         -typedef struct tvfs_file tvfs_file;
    20         -struct tvfs_file {
    21         -  sqlite3_file base;
    22         -  sqlite3_file *pReal;
    23         -};
    24         -
    25     19   typedef struct Testvfs Testvfs;
    26     20   typedef struct TestvfsShm TestvfsShm;
    27     21   typedef struct TestvfsBuffer TestvfsBuffer;
           22  +typedef struct TestvfsFile TestvfsFile;
           23  +
           24  +/*
           25  +** An open file handle.
           26  +*/
           27  +struct TestvfsFile {
           28  +  sqlite3_file base;              /* Base class.  Must be first */
           29  +  sqlite3_vfs *pVfs;              /* The VFS */
           30  +  const char *zFilename;          /* Filename as passed to xOpen() */
           31  +  sqlite3_file *pReal;            /* The real, underlying file descriptor */
           32  +  Tcl_Obj *pShmId;                /* Shared memory id for Tcl callbacks */
           33  +  TestvfsBuffer *pShm;            /* Shared memory buffer */
           34  +};
           35  +
    28     36   
    29     37   /*
    30     38   ** An instance of this structure is allocated for each VFS created. The
    31     39   ** sqlite3_vfs.pAppData field of the VFS structure registered with SQLite
    32     40   ** is set to point to it.
    33     41   */
    34     42   struct Testvfs {
................................................................................
    35     43     char *zName;                    /* Name of this VFS */
    36     44     sqlite3_vfs *pParent;           /* The VFS to use for file IO */
    37     45     sqlite3_vfs *pVfs;              /* The testvfs registered with SQLite */
    38     46     Tcl_Interp *interp;             /* Interpreter to run script in */
    39     47     int nScript;                    /* Number of elements in array apScript */
    40     48     Tcl_Obj **apScript;             /* Script to execute */
    41     49     TestvfsBuffer *pBuffer;         /* List of shared buffers */
           50  +  int isNoshm;
    42     51   };
    43     52   
    44     53   /*
    45     54   ** A shared-memory buffer.
    46     55   */
    47     56   struct TestvfsBuffer {
    48     57     char *zFile;                    /* Associated file name */
    49     58     int n;                          /* Size of allocated buffer in bytes */
    50     59     u8 *a;                          /* Buffer allocated using ckalloc() */
    51     60     int nRef;                       /* Number of references to this object */
    52     61     TestvfsBuffer *pNext;           /* Next in linked list of all buffers */
    53     62   };
    54     63   
    55         -/*
    56         -** A shared-memory handle returned by tvfsShmOpen().
    57         -*/
    58         -struct TestvfsShm {
    59         -  Tcl_Obj *id;                    /* Name of this handle */
    60         -  TestvfsBuffer *pBuffer;         /* Underlying buffer */
    61         -};
    62         -
    63     64   
    64     65   #define PARENTVFS(x) (((Testvfs *)((x)->pAppData))->pParent)
    65     66   
    66     67   
    67     68   /*
    68         -** Method declarations for tvfs_file.
           69  +** Method declarations for TestvfsFile.
    69     70   */
    70     71   static int tvfsClose(sqlite3_file*);
    71     72   static int tvfsRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
    72     73   static int tvfsWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
    73     74   static int tvfsTruncate(sqlite3_file*, sqlite3_int64 size);
    74     75   static int tvfsSync(sqlite3_file*, int flags);
    75     76   static int tvfsFileSize(sqlite3_file*, sqlite3_int64 *pSize);
................................................................................
    93     94   static void (*tvfsDlSym(sqlite3_vfs*,void*, const char *zSymbol))(void);
    94     95   static void tvfsDlClose(sqlite3_vfs*, void*);
    95     96   #endif /* SQLITE_OMIT_LOAD_EXTENSION */
    96     97   static int tvfsRandomness(sqlite3_vfs*, int nByte, char *zOut);
    97     98   static int tvfsSleep(sqlite3_vfs*, int microseconds);
    98     99   static int tvfsCurrentTime(sqlite3_vfs*, double*);
    99    100   
   100         -static int tvfsShmOpen(sqlite3_vfs *, const char *, sqlite3_shm **);
   101         -static int tvfsShmSize(sqlite3_vfs*, sqlite3_shm *, int , int *);
   102         -static int tvfsShmGet(sqlite3_vfs*, sqlite3_shm *, int , int *, void **);
   103         -static int tvfsShmRelease(sqlite3_vfs*, sqlite3_shm *);
   104         -static int tvfsShmLock(sqlite3_vfs*, sqlite3_shm *, int , int *);
   105         -static int tvfsShmClose(sqlite3_vfs*, sqlite3_shm *, int);
          101  +static int tvfsShmOpen(sqlite3_file*);
          102  +static int tvfsShmSize(sqlite3_file*, int , int *);
          103  +static int tvfsShmGet(sqlite3_file*, int , int *, void **);
          104  +static int tvfsShmRelease(sqlite3_file*);
          105  +static int tvfsShmLock(sqlite3_file*, int , int *);
          106  +static int tvfsShmClose(sqlite3_file*, int);
   106    107   
   107    108   static sqlite3_io_methods tvfs_io_methods = {
   108         -  1,                            /* iVersion */
          109  +  2,                            /* iVersion */
   109    110     tvfsClose,                      /* xClose */
   110    111     tvfsRead,                       /* xRead */
   111    112     tvfsWrite,                      /* xWrite */
   112    113     tvfsTruncate,                   /* xTruncate */
   113    114     tvfsSync,                       /* xSync */
   114    115     tvfsFileSize,                   /* xFileSize */
   115    116     tvfsLock,                       /* xLock */
   116    117     tvfsUnlock,                     /* xUnlock */
   117    118     tvfsCheckReservedLock,          /* xCheckReservedLock */
   118    119     tvfsFileControl,                /* xFileControl */
   119    120     tvfsSectorSize,                 /* xSectorSize */
   120         -  tvfsDeviceCharacteristics       /* xDeviceCharacteristics */
          121  +  tvfsDeviceCharacteristics,      /* xDeviceCharacteristics */
          122  +  tvfsShmOpen,                    /* xShmOpen */
          123  +  tvfsShmSize,                    /* xShmSize */
          124  +  tvfsShmGet,                     /* xShmGet */
          125  +  tvfsShmRelease,                 /* xShmRelease */
          126  +  tvfsShmLock,                    /* xShmLock */
          127  +  tvfsShmClose                    /* xShmClose */
   121    128   };
   122    129   
   123    130   /*
   124    131   ** Close an tvfs-file.
   125    132   */
   126    133   static int tvfsClose(sqlite3_file *pFile){
   127         -  tvfs_file *p = (tvfs_file *)pFile;
          134  +  TestvfsFile *p = (TestvfsFile *)pFile;
          135  +  if( p->pShmId ){
          136  +    Tcl_DecrRefCount(p->pShmId);
          137  +    p->pShmId = 0;
          138  +  }
          139  +  if( pFile->pMethods ){
          140  +    ckfree((char *)pFile->pMethods);
          141  +  }
   128    142     return sqlite3OsClose(p->pReal);
   129    143   }
   130    144   
   131    145   /*
   132    146   ** Read data from an tvfs-file.
   133    147   */
   134    148   static int tvfsRead(
   135    149     sqlite3_file *pFile, 
   136    150     void *zBuf, 
   137    151     int iAmt, 
   138    152     sqlite_int64 iOfst
   139    153   ){
   140         -  tvfs_file *p = (tvfs_file *)pFile;
          154  +  TestvfsFile *p = (TestvfsFile *)pFile;
   141    155     return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);
   142    156   }
   143    157   
   144    158   /*
   145    159   ** Write data to an tvfs-file.
   146    160   */
   147    161   static int tvfsWrite(
   148    162     sqlite3_file *pFile, 
   149    163     const void *zBuf, 
   150    164     int iAmt, 
   151    165     sqlite_int64 iOfst
   152    166   ){
   153         -  tvfs_file *p = (tvfs_file *)pFile;
          167  +  TestvfsFile *p = (TestvfsFile *)pFile;
   154    168     return sqlite3OsWrite(p->pReal, zBuf, iAmt, iOfst);
   155    169   }
   156    170   
   157    171   /*
   158    172   ** Truncate an tvfs-file.
   159    173   */
   160    174   static int tvfsTruncate(sqlite3_file *pFile, sqlite_int64 size){
   161         -  tvfs_file *p = (tvfs_file *)pFile;
          175  +  TestvfsFile *p = (TestvfsFile *)pFile;
   162    176     return sqlite3OsTruncate(p->pReal, size);
   163    177   }
   164    178   
   165    179   /*
   166    180   ** Sync an tvfs-file.
   167    181   */
   168    182   static int tvfsSync(sqlite3_file *pFile, int flags){
   169         -  tvfs_file *p = (tvfs_file *)pFile;
          183  +  TestvfsFile *p = (TestvfsFile *)pFile;
   170    184     return sqlite3OsSync(p->pReal, flags);
   171    185   }
   172    186   
   173    187   /*
   174    188   ** Return the current file-size of an tvfs-file.
   175    189   */
   176    190   static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
   177         -  tvfs_file *p = (tvfs_file *)pFile;
          191  +  TestvfsFile *p = (TestvfsFile *)pFile;
   178    192     return sqlite3OsFileSize(p->pReal, pSize);
   179    193   }
   180    194   
   181    195   /*
   182    196   ** Lock an tvfs-file.
   183    197   */
   184    198   static int tvfsLock(sqlite3_file *pFile, int eLock){
   185         -  tvfs_file *p = (tvfs_file *)pFile;
          199  +  TestvfsFile *p = (TestvfsFile *)pFile;
   186    200     return sqlite3OsLock(p->pReal, eLock);
   187    201   }
   188    202   
   189    203   /*
   190    204   ** Unlock an tvfs-file.
   191    205   */
   192    206   static int tvfsUnlock(sqlite3_file *pFile, int eLock){
   193         -  tvfs_file *p = (tvfs_file *)pFile;
          207  +  TestvfsFile *p = (TestvfsFile *)pFile;
   194    208     return sqlite3OsUnlock(p->pReal, eLock);
   195    209   }
   196    210   
   197    211   /*
   198    212   ** Check if another file-handle holds a RESERVED lock on an tvfs-file.
   199    213   */
   200    214   static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
   201         -  tvfs_file *p = (tvfs_file *)pFile;
          215  +  TestvfsFile *p = (TestvfsFile *)pFile;
   202    216     return sqlite3OsCheckReservedLock(p->pReal, pResOut);
   203    217   }
   204    218   
   205    219   /*
   206    220   ** File control method. For custom operations on an tvfs-file.
   207    221   */
   208    222   static int tvfsFileControl(sqlite3_file *pFile, int op, void *pArg){
   209         -  tvfs_file *p = (tvfs_file *)pFile;
          223  +  TestvfsFile *p = (TestvfsFile *)pFile;
   210    224     return sqlite3OsFileControl(p->pReal, op, pArg);
   211    225   }
   212    226   
   213    227   /*
   214    228   ** Return the sector-size in bytes for an tvfs-file.
   215    229   */
   216    230   static int tvfsSectorSize(sqlite3_file *pFile){
   217         -  tvfs_file *p = (tvfs_file *)pFile;
          231  +  TestvfsFile *p = (TestvfsFile *)pFile;
   218    232     return sqlite3OsSectorSize(p->pReal);
   219    233   }
   220    234   
   221    235   /*
   222    236   ** Return the device characteristic flags supported by an tvfs-file.
   223    237   */
   224    238   static int tvfsDeviceCharacteristics(sqlite3_file *pFile){
   225         -  tvfs_file *p = (tvfs_file *)pFile;
          239  +  TestvfsFile *p = (TestvfsFile *)pFile;
   226    240     return sqlite3OsDeviceCharacteristics(p->pReal);
   227    241   }
   228    242   
   229    243   /*
   230    244   ** Open an tvfs file handle.
   231    245   */
   232    246   static int tvfsOpen(
................................................................................
   233    247     sqlite3_vfs *pVfs,
   234    248     const char *zName,
   235    249     sqlite3_file *pFile,
   236    250     int flags,
   237    251     int *pOutFlags
   238    252   ){
   239    253     int rc;
   240         -  tvfs_file *p = (tvfs_file *)pFile;
          254  +  TestvfsFile *p = (TestvfsFile *)pFile;
          255  +  p->pShm = 0;
          256  +  p->pShmId = 0;
          257  +  p->zFilename = zName;
          258  +  p->pVfs = pVfs;
   241    259     p->pReal = (sqlite3_file *)&p[1];
   242    260     rc = sqlite3OsOpen(PARENTVFS(pVfs), zName, p->pReal, flags, pOutFlags);
   243    261     if( p->pReal->pMethods ){
   244         -    pFile->pMethods = &tvfs_io_methods;
          262  +    sqlite3_io_methods *pMethods;
          263  +    pMethods = (sqlite3_io_methods *)ckalloc(sizeof(sqlite3_io_methods));
          264  +    memcpy(pMethods, &tvfs_io_methods, sizeof(sqlite3_io_methods));
          265  +    if( ((Testvfs *)pVfs->pAppData)->isNoshm ){
          266  +      pMethods->xShmOpen = 0;
          267  +      pMethods->xShmGet = 0;
          268  +      pMethods->xShmSize = 0;
          269  +      pMethods->xShmRelease = 0;
          270  +      pMethods->xShmClose = 0;
          271  +      pMethods->xShmLock = 0;
          272  +    }
          273  +    pFile->pMethods = pMethods;
   245    274     }
          275  +
   246    276     return rc;
   247    277   }
   248    278   
   249    279   /*
   250    280   ** Delete the file located at zPath. If the dirSync argument is true,
   251    281   ** ensure the file-system modifications are synced to disk before
   252    282   ** returning.
................................................................................
   333    363   /*
   334    364   ** Return the current time as a Julian Day number in *pTimeOut.
   335    365   */
   336    366   static int tvfsCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
   337    367     return PARENTVFS(pVfs)->xCurrentTime(PARENTVFS(pVfs), pTimeOut);
   338    368   }
   339    369   
   340         -static void tvfsGrowBuffer(TestvfsShm *pShm, int reqSize, int *pNewSize){
   341         -  TestvfsBuffer *pBuffer = pShm->pBuffer;
          370  +static void tvfsGrowBuffer(TestvfsFile *pFd, int reqSize, int *pNewSize){
          371  +  TestvfsBuffer *pBuffer = pFd->pShm;
   342    372     if( reqSize>pBuffer->n ){
   343    373       pBuffer->a = (u8 *)ckrealloc((char *)pBuffer->a, reqSize);
   344    374       memset(&pBuffer->a[pBuffer->n], 0x55, reqSize-pBuffer->n);
   345    375       pBuffer->n = reqSize;
   346    376     }
   347    377     *pNewSize = pBuffer->n;
   348    378   }
................................................................................
   401    431       }
   402    432     }
   403    433   
   404    434     return 0;
   405    435   }
   406    436   
   407    437   static int tvfsShmOpen(
   408         -  sqlite3_vfs *pVfs, 
   409         -  const char *zName, 
   410         -  sqlite3_shm **pp
          438  +  sqlite3_file *pFileDes
   411    439   ){
   412         -  Testvfs *p = (Testvfs *)(pVfs->pAppData);
          440  +  Testvfs *p;
   413    441     int rc = SQLITE_OK;             /* Return code */
   414    442     Tcl_Obj *pId = 0;               /* Id for this connection */
   415    443     TestvfsBuffer *pBuffer;         /* Buffer to open connection to */
   416         -  TestvfsShm *pShm;               /* New shm handle */
          444  +  TestvfsFile *pFd;               /* The testvfs file structure */
          445  +
          446  +  pFd = (TestvfsFile*)pFileDes;
          447  +  p = (Testvfs *)pFd->pVfs->pAppData;
          448  +  assert( pFd->pShmId==0 && pFd->pShm==0 );
   417    449   
   418    450     /* Evaluate the Tcl script: 
   419    451     **
   420    452     **   SCRIPT xShmOpen FILENAME
   421    453     **
   422    454     ** If the script returns an SQLite error code other than SQLITE_OK, an
   423    455     ** error is returned to the caller. If it returns SQLITE_OK, the new
   424    456     ** connection is named "anon". Otherwise, the value returned by the
   425    457     ** script is used as the connection name.
   426    458     */
   427         -  tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(zName, -1), 0, 0);
          459  +  tvfsExecTcl(p, "xShmOpen", Tcl_NewStringObj(pFd->zFilename, -1), 0, 0);
   428    460     if( tvfsResultCode(p, &rc) ){
   429    461       if( rc!=SQLITE_OK ) return rc;
   430    462       pId = Tcl_NewStringObj("anon", -1);
   431    463     }else{
   432    464       pId = Tcl_GetObjResult(p->interp);
   433    465     }
   434    466     Tcl_IncrRefCount(pId);
   435         -
   436         -  /* Allocate the TestvfsShm handle. */
   437         -  pShm = (TestvfsShm *)ckalloc(sizeof(TestvfsShm));
   438         -  memset(pShm, 0, sizeof(TestvfsShm));
   439         -  pShm->id = pId;
          467  +  pFd->pShmId = pId;
   440    468   
   441    469     /* Search for a TestvfsBuffer. Create a new one if required. */
   442    470     for(pBuffer=p->pBuffer; pBuffer; pBuffer=pBuffer->pNext){
   443         -    if( 0==strcmp(zName, pBuffer->zFile) ) break;
          471  +    if( 0==strcmp(pFd->zFilename, pBuffer->zFile) ) break;
   444    472     }
   445    473     if( !pBuffer ){
   446         -    int nByte = sizeof(TestvfsBuffer) + strlen(zName) + 1;
          474  +    int nByte = sizeof(TestvfsBuffer) + strlen(pFd->zFilename) + 1;
   447    475       pBuffer = (TestvfsBuffer *)ckalloc(nByte);
   448    476       memset(pBuffer, 0, nByte);
   449    477       pBuffer->zFile = (char *)&pBuffer[1];
   450         -    strcpy(pBuffer->zFile, zName);
          478  +    strcpy(pBuffer->zFile, pFd->zFilename);
   451    479       pBuffer->pNext = p->pBuffer;
   452    480       p->pBuffer = pBuffer;
   453    481     }
   454    482   
   455    483     /* Connect the TestvfsBuffer to the new TestvfsShm handle and return. */
   456    484     pBuffer->nRef++;
   457         -  pShm->pBuffer = pBuffer;
   458         -  *pp = (sqlite3_shm *)pShm;
          485  +  pFd->pShm = pBuffer;
   459    486     return SQLITE_OK;
   460    487   }
   461    488   
   462    489   static int tvfsShmSize(
   463         -  sqlite3_vfs *pVfs,
   464         -  sqlite3_shm *pShmHandle,
          490  +  sqlite3_file *pFile,
   465    491     int reqSize,
   466    492     int *pNewSize
   467    493   ){
   468    494     int rc = SQLITE_OK;
   469         -  Testvfs *p = (Testvfs *)(pVfs->pAppData);
   470         -  TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
          495  +  TestvfsFile *pFd = (TestvfsFile *)pFile;
          496  +  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
   471    497   
   472    498     tvfsExecTcl(p, "xShmSize", 
   473         -      Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0
          499  +      Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
   474    500     );
   475    501     tvfsResultCode(p, &rc);
   476    502     if( rc==SQLITE_OK ){
   477         -    tvfsGrowBuffer(pShm, reqSize, pNewSize);
          503  +    tvfsGrowBuffer(pFd, reqSize, pNewSize);
   478    504     }
   479    505     return rc;
   480    506   }
   481    507   
   482    508   static int tvfsShmGet(
   483         -  sqlite3_vfs *pVfs,
   484         -  sqlite3_shm *pShmHandle, 
          509  +  sqlite3_file *pFile, 
   485    510     int reqMapSize, 
   486    511     int *pMapSize, 
   487    512     void **pp
   488    513   ){
   489    514     int rc = SQLITE_OK;
   490         -  Testvfs *p = (Testvfs *)(pVfs->pAppData);
   491         -  TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
          515  +  TestvfsFile *pFd = (TestvfsFile *)pFile;
          516  +  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
   492    517   
   493    518     tvfsExecTcl(p, "xShmGet", 
   494         -      Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0
          519  +      Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
   495    520     );
   496    521     tvfsResultCode(p, &rc);
   497    522     if( rc==SQLITE_OK ){
   498         -    tvfsGrowBuffer(pShm, reqMapSize, pMapSize);
   499         -    *pp = pShm->pBuffer->a;
          523  +    tvfsGrowBuffer(pFd, reqMapSize, pMapSize);
          524  +    *pp = pFd->pShm->a;
   500    525     }
   501    526     return rc;
   502    527   }
   503    528   
   504         -static int tvfsShmRelease(sqlite3_vfs *pVfs, sqlite3_shm *pShmHandle){
          529  +static int tvfsShmRelease(sqlite3_file *pFile){
   505    530     int rc = SQLITE_OK;
   506         -  Testvfs *p = (Testvfs *)(pVfs->pAppData);
   507         -  TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
          531  +  TestvfsFile *pFd = (TestvfsFile *)pFile;
          532  +  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
   508    533   
   509    534     tvfsExecTcl(p, "xShmRelease", 
   510         -      Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0
          535  +      Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
   511    536     );
   512    537     tvfsResultCode(p, &rc);
   513    538   
   514    539     return rc;
   515    540   }
   516    541   
   517    542   static int tvfsShmLock(
   518         -  sqlite3_vfs *pVfs,
   519         -  sqlite3_shm *pShmHandle,
          543  +  sqlite3_file *pFile,
   520    544     int desiredLock,
   521    545     int *gotLock
   522    546   ){
   523    547     int rc = SQLITE_OK;
   524         -  Testvfs *p = (Testvfs *)(pVfs->pAppData);
   525         -  TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
          548  +  TestvfsFile *pFd = (TestvfsFile *)pFile;
          549  +  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
   526    550     char *zLock = "";
   527    551   
   528    552     switch( desiredLock ){
   529    553       case SQLITE_SHM_READ:         zLock = "READ";       break;
   530    554       case SQLITE_SHM_WRITE:        zLock = "WRITE";      break;
   531    555       case SQLITE_SHM_CHECKPOINT:   zLock = "CHECKPOINT"; break;
   532    556       case SQLITE_SHM_RECOVER:      zLock = "RECOVER";    break;
   533    557       case SQLITE_SHM_PENDING:      zLock = "PENDING";    break;
   534    558       case SQLITE_SHM_UNLOCK:       zLock = "UNLOCK";     break;
   535    559     }
   536    560     tvfsExecTcl(p, "xShmLock", 
   537         -      Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id,
          561  +      Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId,
   538    562         Tcl_NewStringObj(zLock, -1)
   539    563     );
   540    564     tvfsResultCode(p, &rc);
   541    565     if( rc==SQLITE_OK ){
   542    566       *gotLock = desiredLock;
   543    567     }
   544    568   
   545    569     return rc;
   546    570   }
   547    571   
   548    572   static int tvfsShmClose(
   549         -  sqlite3_vfs *pVfs, 
   550         -  sqlite3_shm *pShmHandle, 
          573  +  sqlite3_file *pFile,
   551    574     int deleteFlag
   552    575   ){
   553    576     int rc = SQLITE_OK;
   554         -  Testvfs *p = (Testvfs *)(pVfs->pAppData);
   555         -  TestvfsShm *pShm = (TestvfsShm *)pShmHandle;
   556         -  TestvfsBuffer *pBuffer = pShm->pBuffer;
          577  +  TestvfsFile *pFd = (TestvfsFile *)pFile;
          578  +  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
          579  +  TestvfsBuffer *pBuffer = pFd->pShm;
   557    580   
          581  +  assert( pFd->pShmId && pFd->pShm );
   558    582   #if 0
   559    583     assert( (deleteFlag!=0)==(pBuffer->nRef==1) );
   560    584   #endif
   561    585   
   562    586     tvfsExecTcl(p, "xShmClose", 
   563         -      Tcl_NewStringObj(pShm->pBuffer->zFile, -1), pShm->id, 0
          587  +      Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
   564    588     );
   565    589     tvfsResultCode(p, &rc);
   566    590   
   567    591     pBuffer->nRef--;
   568    592     if( pBuffer->nRef==0 ){
   569    593       TestvfsBuffer **pp;
   570    594       for(pp=&p->pBuffer; *pp!=pBuffer; pp=&((*pp)->pNext));
   571    595       *pp = (*pp)->pNext;
   572    596       ckfree((char *)pBuffer->a);
   573    597       ckfree((char *)pBuffer);
   574    598     }
   575         -  Tcl_DecrRefCount(pShm->id);
   576         -  ckfree((char *)pShm);
          599  +  Tcl_DecrRefCount(pFd->pShmId);
          600  +  pFd->pShmId = 0;
          601  +  pFd->pShm = 0;
   577    602   
   578    603     return rc;
   579    604   }
   580    605   
   581    606   static int testvfs_obj_cmd(
   582    607     ClientData cd,
   583    608     Tcl_Interp *interp,
................................................................................
   683    708   */
   684    709   static int testvfs_cmd(
   685    710     ClientData cd,
   686    711     Tcl_Interp *interp,
   687    712     int objc,
   688    713     Tcl_Obj *CONST objv[]
   689    714   ){
   690         -
   691    715     static sqlite3_vfs tvfs_vfs = {
   692    716       2,                            /* iVersion */
   693         -    sizeof(tvfs_file),            /* szOsFile */
          717  +    sizeof(TestvfsFile),            /* szOsFile */
   694    718       0,                            /* mxPathname */
   695    719       0,                            /* pNext */
   696    720       0,                            /* zName */
   697    721       0,                            /* pAppData */
   698    722       tvfsOpen,                     /* xOpen */
   699    723       tvfsDelete,                   /* xDelete */
   700    724       tvfsAccess,                   /* xAccess */
................................................................................
   710    734       0,                            /* xDlSym */
   711    735       0,                            /* xDlClose */
   712    736   #endif /* SQLITE_OMIT_LOAD_EXTENSION */
   713    737       tvfsRandomness,               /* xRandomness */
   714    738       tvfsSleep,                    /* xSleep */
   715    739       tvfsCurrentTime,              /* xCurrentTime */
   716    740       0,                            /* xGetLastError */
   717         -    tvfsShmOpen,
   718         -    tvfsShmSize,
   719         -    tvfsShmGet,
   720         -    tvfsShmRelease,
   721         -    tvfsShmLock,
   722         -    tvfsShmClose,
   723    741       0,
   724    742       0,
   725    743     };
   726    744   
   727    745     Testvfs *p;                     /* New object */
   728    746     sqlite3_vfs *pVfs;              /* New VFS */
   729    747     char *zVfs;
................................................................................
   766    784     pVfs = (sqlite3_vfs *)ckalloc(sizeof(sqlite3_vfs));
   767    785     memcpy(pVfs, &tvfs_vfs, sizeof(sqlite3_vfs));
   768    786     pVfs->pAppData = (void *)p;
   769    787     pVfs->zName = p->zName;
   770    788     pVfs->mxPathname = p->pParent->mxPathname;
   771    789     pVfs->szOsFile += p->pParent->szOsFile;
   772    790     p->pVfs = pVfs;
   773         -  if( isNoshm ){
   774         -    pVfs->xShmOpen = 0;
   775         -    pVfs->xShmGet = 0;
   776         -    pVfs->xShmSize = 0;
   777         -    pVfs->xShmRelease = 0;
   778         -    pVfs->xShmClose = 0;
   779         -    pVfs->xShmLock = 0;
   780         -  }
          791  +  p->isNoshm = isNoshm;
   781    792   
   782    793     Tcl_CreateObjCommand(interp, zVfs, testvfs_obj_cmd, p, testvfs_obj_del);
   783    794     sqlite3_vfs_register(pVfs, 0);
   784    795   
   785    796     return TCL_OK;
   786    797   
   787    798    bad_args:

Changes to src/vdbe.c.

  5244   5244     zFilename = sqlite3PagerFilename(pPager);
  5245   5245     pVfs = sqlite3PagerVfs(pPager);
  5246   5246   
  5247   5247     /* Do not allow a transition to journal_mode=WAL for a database
  5248   5248     ** in temporary storage or if the VFS does not support xShmOpen.
  5249   5249     */
  5250   5250     if( eNew==PAGER_JOURNALMODE_WAL
  5251         -   && (zFilename[0]==0                               /* Temp file */
  5252         -         || pVfs->iVersion<2 || pVfs->xShmOpen==0)   /* No xShmOpen support */
         5251  +   && (zFilename[0]==0                         /* Temp file */
         5252  +       || !sqlite3PagerWalSupported(pPager))   /* No xShmOpen support */
  5253   5253     ){
  5254   5254       eNew = PAGER_JOURNALMODE_QUERY;
  5255   5255     }
  5256   5256   
  5257   5257     if( eNew!=PAGER_JOURNALMODE_QUERY ){
  5258   5258       eOld = sqlite3PagerJournalMode(pPager, PAGER_JOURNALMODE_QUERY);
  5259   5259       if( (eNew!=eOld)

Changes to src/wal.c.

   121    121   
   122    122   /*
   123    123   ** An open write-ahead log file is represented by an instance of the
   124    124   ** following object.
   125    125   */
   126    126   struct Wal {
   127    127     sqlite3_vfs *pVfs;         /* The VFS used to create pFd */
   128         -  sqlite3_file *pFd;         /* File handle for WAL file */
          128  +  sqlite3_file *pDbFd;       /* File handle for the database file */
          129  +  sqlite3_file *pWalFd;      /* File handle for WAL file */
   129    130     u32 iCallback;             /* Value to pass to log callback (or 0) */
   130         -  sqlite3_shm *pWIndex;      /* The open wal-index file */
   131    131     int szWIndex;              /* Size of the wal-index that is mapped in mem */
   132    132     u32 *pWiData;              /* Pointer to wal-index content in memory */
   133    133     u8 lockState;              /* SQLITE_SHM_xxxx constant showing lock state */
   134    134     u8 readerType;             /* SQLITE_SHM_READ or SQLITE_SHM_READ_FULL */
   135    135     u8 exclusiveMode;          /* Non-zero if connection is in exclusive mode */
          136  +  u8 isWindexOpen;           /* True if ShmOpen() called on pDbFd */
   136    137     WalIndexHdr hdr;           /* Wal-index for current snapshot */
   137         -  char *zName;               /* Name of underlying storage */
          138  +  char *zWalName;            /* Name of WAL file */
   138    139   };
   139    140   
   140    141   
   141    142   /*
   142    143   ** This structure is used to implement an iterator that iterates through
   143    144   ** all frames in the log in database page order. Where two or more frames
   144    145   ** correspond to the same database page, the iterator visits only the 
................................................................................
   219    220   */
   220    221   static int walSetLock(Wal *pWal, int desiredStatus){
   221    222     int rc = SQLITE_OK;             /* Return code */
   222    223     if( pWal->exclusiveMode || pWal->lockState==desiredStatus ){
   223    224       pWal->lockState = desiredStatus;
   224    225     }else{
   225    226       int got = pWal->lockState;
   226         -    rc = pWal->pVfs->xShmLock(pWal->pVfs, pWal->pWIndex, desiredStatus, &got);
          227  +    rc = sqlite3OsShmLock(pWal->pDbFd, desiredStatus, &got);
   227    228       pWal->lockState = got;
   228    229       if( got==SQLITE_SHM_READ_FULL || got==SQLITE_SHM_READ ){
   229    230         pWal->readerType = got;
   230    231         pWal->lockState = SQLITE_SHM_READ;
   231    232       }
   232    233     }
   233    234     return rc;
................................................................................
   400    401   
   401    402   /*
   402    403   ** Release our reference to the wal-index memory map, if we are holding
   403    404   ** it.
   404    405   */
   405    406   static void walIndexUnmap(Wal *pWal){
   406    407     if( pWal->pWiData ){
   407         -    pWal->pVfs->xShmRelease(pWal->pVfs, pWal->pWIndex);
          408  +    sqlite3OsShmRelease(pWal->pDbFd);
   408    409       pWal->pWiData = 0;
   409    410     }
   410    411   }
   411    412   
   412    413   /*
   413    414   ** Map the wal-index file into memory if it isn't already. 
   414    415   **
   415    416   ** The reqSize parameter is the minimum required size of the mapping.
   416    417   ** A value of -1 means "don't care".
   417    418   */
   418    419   static int walIndexMap(Wal *pWal, int reqSize){
   419    420     int rc = SQLITE_OK;
   420    421     if( pWal->pWiData==0 || reqSize>pWal->szWIndex ){
   421         -    rc = pWal->pVfs->xShmGet(pWal->pVfs, pWal->pWIndex, reqSize,
   422         -                             &pWal->szWIndex, (void**)(char*)&pWal->pWiData);
          422  +    rc = sqlite3OsShmGet(pWal->pDbFd, reqSize, &pWal->szWIndex,
          423  +                             (void**)(char*)&pWal->pWiData);
   423    424       if( rc==SQLITE_OK && pWal->pWiData==0 ){
   424    425         /* Make sure pWal->pWiData is not NULL while we are holding the
   425    426         ** lock on the mapping. */
   426    427         assert( pWal->szWIndex==0 );
   427    428         pWal->pWiData = &pWal->iCallback;
   428    429       }
   429    430       if( rc!=SQLITE_OK ){
................................................................................
   439    440   **
   440    441   ** If enlargeTo is non-negative, then increase the size of the underlying
   441    442   ** storage to be at least as big as enlargeTo before remapping.
   442    443   */
   443    444   static int walIndexRemap(Wal *pWal, int enlargeTo){
   444    445     int rc;
   445    446     int sz;
   446         -  rc = pWal->pVfs->xShmSize(pWal->pVfs, pWal->pWIndex, enlargeTo, &sz);
          447  +  rc = sqlite3OsShmSize(pWal->pDbFd, enlargeTo, &sz);
   447    448     if( rc==SQLITE_OK && sz>pWal->szWIndex ){
   448    449       walIndexUnmap(pWal);
   449    450       rc = walIndexMap(pWal, sz);
   450    451     }
   451    452     return rc;
   452    453   }
   453    454   
................................................................................
   557    558     int rc;                         /* Return Code */
   558    559     i64 nSize;                      /* Size of log file */
   559    560     WalIndexHdr hdr;              /* Recovered wal-index header */
   560    561   
   561    562     assert( pWal->lockState>SQLITE_SHM_READ );
   562    563     memset(&hdr, 0, sizeof(hdr));
   563    564   
   564         -  rc = sqlite3OsFileSize(pWal->pFd, &nSize);
          565  +  rc = sqlite3OsFileSize(pWal->pWalFd, &nSize);
   565    566     if( rc!=SQLITE_OK ){
   566    567       return rc;
   567    568     }
   568    569   
   569    570     if( nSize>WAL_FRAME_HDRSIZE ){
   570    571       u8 aBuf[WAL_FRAME_HDRSIZE];   /* Buffer to load first frame header into */
   571    572       u8 *aFrame = 0;               /* Malloc'd buffer to load entire frame */
................................................................................
   575    576       i64 iOffset;                  /* Next offset to read from log file */
   576    577       int nPgsz;                    /* Page size according to the log */
   577    578       u32 aCksum[2];                /* Running checksum */
   578    579   
   579    580       /* Read in the first frame header in the file (to determine the 
   580    581       ** database page size).
   581    582       */
   582         -    rc = sqlite3OsRead(pWal->pFd, aBuf, WAL_HDRSIZE, 0);
          583  +    rc = sqlite3OsRead(pWal->pWalFd, aBuf, WAL_HDRSIZE, 0);
   583    584       if( rc!=SQLITE_OK ){
   584    585         return rc;
   585    586       }
   586    587   
   587    588       /* If the database page size is not a power of two, or is greater than
   588    589       ** SQLITE_MAX_PAGE_SIZE, conclude that the log file contains no valid data.
   589    590       */
................................................................................
   606    607       iFrame = 0;
   607    608       for(iOffset=WAL_HDRSIZE; (iOffset+nFrame)<=nSize; iOffset+=nFrame){
   608    609         u32 pgno;                   /* Database page number for frame */
   609    610         u32 nTruncate;              /* dbsize field from frame header */
   610    611         int isValid;                /* True if this frame is valid */
   611    612   
   612    613         /* Read and decode the next log frame. */
   613         -      rc = sqlite3OsRead(pWal->pFd, aFrame, nFrame, iOffset);
          614  +      rc = sqlite3OsRead(pWal->pWalFd, aFrame, nFrame, iOffset);
   614    615         if( rc!=SQLITE_OK ) break;
   615    616         isValid = walDecodeFrame(aCksum, &pgno, &nTruncate, nPgsz, aData, aFrame);
   616    617         if( !isValid ) break;
   617    618         rc = walIndexAppend(pWal, ++iFrame, pgno);
   618    619         if( rc!=SQLITE_OK ) break;
   619    620   
   620    621         /* If nTruncate is non-zero, this is a commit record. */
................................................................................
   644    645     return rc;
   645    646   }
   646    647   
   647    648   /*
   648    649   ** Close an open wal-index.
   649    650   */
   650    651   static void walIndexClose(Wal *pWal, int isDelete){
   651         -  sqlite3_shm *pWIndex = pWal->pWIndex;
   652         -  if( pWIndex ){
   653         -    sqlite3_vfs *pVfs = pWal->pVfs;
          652  +  if( pWal->isWindexOpen ){
   654    653       int notUsed;
   655         -    pVfs->xShmLock(pVfs, pWIndex, SQLITE_SHM_UNLOCK, &notUsed);
   656         -    pVfs->xShmClose(pVfs, pWIndex, isDelete);
          654  +    sqlite3OsShmLock(pWal->pDbFd, SQLITE_SHM_UNLOCK, &notUsed);
          655  +    sqlite3OsShmClose(pWal->pDbFd, isDelete);
          656  +    pWal->isWindexOpen = 0;
   657    657     }
   658    658   }
   659    659   
   660    660   /* 
   661    661   ** Open a connection to the log file associated with database zDb. The
   662    662   ** database file does not actually have to exist. zDb is used only to
   663    663   ** figure out the name of the log file to open. If the log file does not 
................................................................................
   671    671   **
   672    672   ** If the log file is successfully opened, SQLITE_OK is returned and 
   673    673   ** *ppWal is set to point to a new WAL handle. If an error occurs,
   674    674   ** an SQLite error code is returned and *ppWal is left unmodified.
   675    675   */
   676    676   int sqlite3WalOpen(
   677    677     sqlite3_vfs *pVfs,              /* vfs module to open wal and wal-index */
   678         -  const char *zDb,                /* Name of database file */
          678  +  sqlite3_file *pDbFd,            /* The open database file */
          679  +  const char *zDbName,            /* Name of the database file */
   679    680     Wal **ppWal                     /* OUT: Allocated Wal handle */
   680    681   ){
   681    682     int rc;                         /* Return Code */
   682    683     Wal *pRet;                      /* Object to allocate and return */
   683    684     int flags;                      /* Flags passed to OsOpen() */
   684         -  char *zWal;                     /* Path to WAL file */
          685  +  char *zWal;                     /* Name of write-ahead log file */
   685    686     int nWal;                       /* Length of zWal in bytes */
   686    687   
   687         -  assert( zDb );
   688         -  if( pVfs->xShmOpen==0 ) return SQLITE_CANTOPEN_BKPT;
          688  +  assert( zDbName && zDbName[0] );
          689  +  assert( pDbFd );
   689    690   
   690    691     /* Allocate an instance of struct Wal to return. */
   691    692     *ppWal = 0;
   692         -  nWal = strlen(zDb);
   693         -  pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile + nWal+5);
          693  +  nWal = sqlite3Strlen30(zDbName) + 5;
          694  +  pRet = (Wal*)sqlite3MallocZero(sizeof(Wal) + pVfs->szOsFile + nWal);
   694    695     if( !pRet ){
   695    696       return SQLITE_NOMEM;
   696    697     }
   697    698   
   698    699     pRet->pVfs = pVfs;
   699         -  pRet->pFd = (sqlite3_file *)&pRet[1];
   700         -  pRet->zName = zWal = pVfs->szOsFile + (char*)pRet->pFd;
   701         -  sqlite3_snprintf(nWal+5, zWal, "%s-wal", zDb);
   702         -  rc = pVfs->xShmOpen(pVfs, zDb, &pRet->pWIndex);
          700  +  pRet->pWalFd = (sqlite3_file *)&pRet[1];
          701  +  pRet->pDbFd = pDbFd;
          702  +  pRet->zWalName = zWal = pVfs->szOsFile + (char*)pRet->pWalFd;
          703  +  sqlite3_snprintf(nWal, zWal, "%s-wal", zDbName);
          704  +  rc = sqlite3OsShmOpen(pDbFd);
   703    705   
   704    706     /* Open file handle on the write-ahead log file. */
   705    707     if( rc==SQLITE_OK ){
          708  +    pRet->isWindexOpen = 1;
   706    709       flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_JOURNAL);
   707         -    rc = sqlite3OsOpen(pVfs, zWal, pRet->pFd, flags, &flags);
          710  +    rc = sqlite3OsOpen(pVfs, zWal, pRet->pWalFd, flags, &flags);
   708    711     }
   709    712   
   710    713     if( rc!=SQLITE_OK ){
   711    714       walIndexClose(pRet, 0);
   712         -    sqlite3OsClose(pRet->pFd);
          715  +    sqlite3OsClose(pRet->pWalFd);
   713    716       sqlite3_free(pRet);
   714    717     }else{
   715    718       *ppWal = pRet;
   716    719     }
   717    720     return rc;
   718    721   }
   719    722   
................................................................................
   805    808   }
   806    809   
   807    810   /*
   808    811   ** Checkpoint the contents of the log file.
   809    812   */
   810    813   static int walCheckpoint(
   811    814     Wal *pWal,                      /* Wal connection */
   812         -  sqlite3_file *pFd,              /* File descriptor open on db file */
   813    815     int sync_flags,                 /* Flags for OsSync() (or 0) */
   814    816     int nBuf,                       /* Size of zBuf in bytes */
   815    817     u8 *zBuf                        /* Temporary buffer to use */
   816    818   ){
   817    819     int rc;                         /* Return code */
   818    820     int pgsz = pWal->hdr.pgsz;      /* Database page-size */
   819    821     WalIterator *pIter = 0;         /* Wal iterator context */
................................................................................
   829    831     if( pWal->hdr.pgsz!=nBuf ){
   830    832       rc = SQLITE_CORRUPT_BKPT;
   831    833       goto out;
   832    834     }
   833    835   
   834    836     /* Sync the log file to disk */
   835    837     if( sync_flags ){
   836         -    rc = sqlite3OsSync(pWal->pFd, sync_flags);
          838  +    rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
   837    839       if( rc!=SQLITE_OK ) goto out;
   838    840     }
   839    841   
   840    842     /* Iterate through the contents of the log, copying data to the db file. */
   841    843     while( 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
   842         -    rc = sqlite3OsRead(pWal->pFd, zBuf, pgsz, 
          844  +    rc = sqlite3OsRead(pWal->pWalFd, zBuf, pgsz, 
   843    845           walFrameOffset(iFrame, pgsz) + WAL_FRAME_HDRSIZE
   844    846       );
   845    847       if( rc!=SQLITE_OK ) goto out;
   846         -    rc = sqlite3OsWrite(pFd, zBuf, pgsz, (iDbpage-1)*pgsz);
          848  +    rc = sqlite3OsWrite(pWal->pDbFd, zBuf, pgsz, (iDbpage-1)*pgsz);
   847    849       if( rc!=SQLITE_OK ) goto out;
   848    850     }
   849    851   
   850    852     /* Truncate the database file */
   851         -  rc = sqlite3OsTruncate(pFd, ((i64)pWal->hdr.nPage*(i64)pgsz));
          853  +  rc = sqlite3OsTruncate(pWal->pDbFd, ((i64)pWal->hdr.nPage*(i64)pgsz));
   852    854     if( rc!=SQLITE_OK ) goto out;
   853    855   
   854    856     /* Sync the database file. If successful, update the wal-index. */
   855    857     if( sync_flags ){
   856         -    rc = sqlite3OsSync(pFd, sync_flags);
          858  +    rc = sqlite3OsSync(pWal->pDbFd, sync_flags);
   857    859       if( rc!=SQLITE_OK ) goto out;
   858    860     }
   859    861     pWal->hdr.iLastPg = 0;
   860    862     pWal->hdr.iCheck1 = 2;
   861    863     pWal->hdr.iCheck2 = 3;
   862    864     walIndexWriteHdr(pWal, &pWal->hdr);
   863    865   
................................................................................
   872    874     **
   873    875     ** The easiest thing to do would be to write and sync a dummy header
   874    876     ** into the log at this point. Unfortunately, that turns out to be
   875    877     ** an unwelcome performance hit. Alternatives are...
   876    878     */
   877    879   #if 0 
   878    880     memset(zBuf, 0, WAL_FRAME_HDRSIZE);
   879         -  rc = sqlite3OsWrite(pWal->pFd, zBuf, WAL_FRAME_HDRSIZE, 0);
          881  +  rc = sqlite3OsWrite(pWal->pWalFd, zBuf, WAL_FRAME_HDRSIZE, 0);
   880    882     if( rc!=SQLITE_OK ) goto out;
   881         -  rc = sqlite3OsSync(pWal->pFd, pWal->sync_flags);
          883  +  rc = sqlite3OsSync(pWal->pWalFd, pWal->sync_flags);
   882    884   #endif
   883    885   
   884    886    out:
   885    887     walIteratorFree(pIter);
   886    888     return rc;
   887    889   }
   888    890   
   889    891   /*
   890    892   ** Close a connection to a log file.
   891    893   */
   892    894   int sqlite3WalClose(
   893    895     Wal *pWal,                      /* Wal to close */
   894         -  sqlite3_file *pFd,              /* Database file */
   895    896     int sync_flags,                 /* Flags to pass to OsSync() (or 0) */
   896    897     int nBuf,
   897    898     u8 *zBuf                        /* Buffer of at least nBuf bytes */
   898    899   ){
   899    900     int rc = SQLITE_OK;
   900    901     if( pWal ){
   901    902       int isDelete = 0;             /* True to unlink wal and wal-index files */
................................................................................
   904    905       ** ordinary, rollback-mode locking methods, this guarantees that the
   905    906       ** connection associated with this log file is the only connection to
   906    907       ** the database. In this case checkpoint the database and unlink both
   907    908       ** the wal and wal-index files.
   908    909       **
   909    910       ** The EXCLUSIVE lock is not released before returning.
   910    911       */
   911         -    rc = sqlite3OsLock(pFd, SQLITE_LOCK_EXCLUSIVE);
          912  +    rc = sqlite3OsLock(pWal->pDbFd, SQLITE_LOCK_EXCLUSIVE);
   912    913       if( rc==SQLITE_OK ){
   913         -      rc = sqlite3WalCheckpoint(pWal, pFd, sync_flags, nBuf, zBuf, 0, 0);
          914  +      rc = sqlite3WalCheckpoint(pWal, sync_flags, nBuf, zBuf, 0, 0);
   914    915         if( rc==SQLITE_OK ){
   915    916           isDelete = 1;
   916    917         }
   917    918         walIndexUnmap(pWal);
   918    919       }
   919    920   
   920    921       walIndexClose(pWal, isDelete);
   921         -    sqlite3OsClose(pWal->pFd);
          922  +    sqlite3OsClose(pWal->pWalFd);
   922    923       if( isDelete ){
   923         -      sqlite3OsDelete(pWal->pVfs, pWal->zName, 0);
          924  +      sqlite3OsDelete(pWal->pVfs, pWal->zWalName, 0);
   924    925       }
   925    926       sqlite3_free(pWal);
   926    927     }
   927    928     return rc;
   928    929   }
   929    930   
   930    931   /*
................................................................................
  1187   1188     /* If iRead is non-zero, then it is the log frame number that contains the
  1188   1189     ** required page. Read and return data from the log file.
  1189   1190     */
  1190   1191     walIndexUnmap(pWal);
  1191   1192     if( iRead ){
  1192   1193       i64 iOffset = walFrameOffset(iRead, pWal->hdr.pgsz) + WAL_FRAME_HDRSIZE;
  1193   1194       *pInWal = 1;
  1194         -    return sqlite3OsRead(pWal->pFd, pOut, nOut, iOffset);
         1195  +    return sqlite3OsRead(pWal->pWalFd, pOut, nOut, iOffset);
  1195   1196     }
  1196   1197   
  1197   1198     *pInWal = 0;
  1198   1199     return SQLITE_OK;
  1199   1200   }
  1200   1201   
  1201   1202   
................................................................................
  1286   1287     int rc = SQLITE_OK;
  1287   1288     u8 aCksum[8];
  1288   1289     assert( pWal->lockState==SQLITE_SHM_WRITE );
  1289   1290   
  1290   1291     pWal->hdr.iLastPg = iFrame;
  1291   1292     if( iFrame>0 ){
  1292   1293       i64 iOffset = walFrameOffset(iFrame, pWal->hdr.pgsz) + sizeof(u32)*2;
  1293         -    rc = sqlite3OsRead(pWal->pFd, aCksum, sizeof(aCksum), iOffset);
         1294  +    rc = sqlite3OsRead(pWal->pWalFd, aCksum, sizeof(aCksum), iOffset);
  1294   1295       pWal->hdr.iCheck1 = sqlite3Get4byte(&aCksum[0]);
  1295   1296       pWal->hdr.iCheck2 = sqlite3Get4byte(&aCksum[4]);
  1296   1297     }
  1297   1298   
  1298   1299     return rc;
  1299   1300   }
  1300   1301   
................................................................................
  1330   1331     assert( WAL_FRAME_HDRSIZE>=WAL_HDRSIZE );
  1331   1332     iFrame = pWal->hdr.iLastPg;
  1332   1333     if( iFrame==0 ){
  1333   1334       sqlite3Put4byte(aFrame, nPgsz);
  1334   1335       sqlite3_randomness(8, &aFrame[4]);
  1335   1336       pWal->hdr.iCheck1 = sqlite3Get4byte(&aFrame[4]);
  1336   1337       pWal->hdr.iCheck2 = sqlite3Get4byte(&aFrame[8]);
  1337         -    rc = sqlite3OsWrite(pWal->pFd, aFrame, WAL_HDRSIZE, 0);
         1338  +    rc = sqlite3OsWrite(pWal->pWalFd, aFrame, WAL_HDRSIZE, 0);
  1338   1339       if( rc!=SQLITE_OK ){
  1339   1340         return rc;
  1340   1341       }
  1341   1342     }
  1342   1343   
  1343   1344     aCksum[0] = pWal->hdr.iCheck1;
  1344   1345     aCksum[1] = pWal->hdr.iCheck2;
................................................................................
  1349   1350       i64 iOffset;                  /* Write offset in log file */
  1350   1351   
  1351   1352       iOffset = walFrameOffset(++iFrame, nPgsz);
  1352   1353       
  1353   1354       /* Populate and write the frame header */
  1354   1355       nDbsize = (isCommit && p->pDirty==0) ? nTruncate : 0;
  1355   1356       walEncodeFrame(aCksum, p->pgno, nDbsize, nPgsz, p->pData, aFrame);
  1356         -    rc = sqlite3OsWrite(pWal->pFd, aFrame, sizeof(aFrame), iOffset);
         1357  +    rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOffset);
  1357   1358       if( rc!=SQLITE_OK ){
  1358   1359         return rc;
  1359   1360       }
  1360   1361   
  1361   1362       /* Write the page data */
  1362         -    rc = sqlite3OsWrite(pWal->pFd, p->pData, nPgsz, iOffset + sizeof(aFrame));
         1363  +    rc = sqlite3OsWrite(pWal->pWalFd, p->pData, nPgsz, iOffset + sizeof(aFrame));
  1363   1364       if( rc!=SQLITE_OK ){
  1364   1365         return rc;
  1365   1366       }
  1366   1367       pLast = p;
  1367   1368     }
  1368   1369   
  1369   1370     /* Sync the log file if the 'isSync' flag was specified. */
  1370   1371     if( sync_flags ){
  1371         -    i64 iSegment = sqlite3OsSectorSize(pWal->pFd);
         1372  +    i64 iSegment = sqlite3OsSectorSize(pWal->pWalFd);
  1372   1373       i64 iOffset = walFrameOffset(iFrame+1, nPgsz);
  1373   1374   
  1374   1375       assert( isCommit );
  1375   1376   
  1376   1377       if( iSegment<SQLITE_DEFAULT_SECTOR_SIZE ){
  1377   1378         iSegment = SQLITE_DEFAULT_SECTOR_SIZE;
  1378   1379       }
  1379   1380       iSegment = (((iOffset+iSegment-1)/iSegment) * iSegment);
  1380   1381       while( iOffset<iSegment ){
  1381   1382         walEncodeFrame(aCksum,pLast->pgno,nTruncate,nPgsz,pLast->pData,aFrame);
  1382         -      rc = sqlite3OsWrite(pWal->pFd, aFrame, sizeof(aFrame), iOffset);
         1383  +      rc = sqlite3OsWrite(pWal->pWalFd, aFrame, sizeof(aFrame), iOffset);
  1383   1384         if( rc!=SQLITE_OK ){
  1384   1385           return rc;
  1385   1386         }
  1386   1387   
  1387   1388         iOffset += WAL_FRAME_HDRSIZE;
  1388         -      rc = sqlite3OsWrite(pWal->pFd, pLast->pData, nPgsz, iOffset); 
         1389  +      rc = sqlite3OsWrite(pWal->pWalFd, pLast->pData, nPgsz, iOffset); 
  1389   1390         if( rc!=SQLITE_OK ){
  1390   1391           return rc;
  1391   1392         }
  1392   1393         nLast++;
  1393   1394         iOffset += nPgsz;
  1394   1395       }
  1395   1396   
  1396         -    rc = sqlite3OsSync(pWal->pFd, sync_flags);
         1397  +    rc = sqlite3OsSync(pWal->pWalFd, sync_flags);
  1397   1398     }
  1398   1399     assert( pWal->pWiData==0 );
  1399   1400   
  1400   1401     /* Append data to the log summary. It is not necessary to lock the 
  1401   1402     ** wal-index to do this as the RESERVED lock held on the db file
  1402   1403     ** guarantees that there are no other writers, and no data that may
  1403   1404     ** be in use by existing readers is being overwritten.
................................................................................
  1441   1442   **   1. Acquire a CHECKPOINT lock
  1442   1443   **   2. Copy the contents of the log into the database file.
  1443   1444   **   3. Zero the wal-index header (so new readers will ignore the log).
  1444   1445   **   4. Drop the CHECKPOINT lock.
  1445   1446   */
  1446   1447   int sqlite3WalCheckpoint(
  1447   1448     Wal *pWal,                      /* Wal connection */
  1448         -  sqlite3_file *pFd,              /* File descriptor open on db file */
  1449   1449     int sync_flags,                 /* Flags to sync db file with (or 0) */
  1450   1450     int nBuf,                       /* Size of temporary buffer */
  1451   1451     u8 *zBuf,                       /* Temporary buffer to use */
  1452   1452     int (*xBusyHandler)(void *),    /* Pointer to busy-handler function */
  1453   1453     void *pBusyHandlerArg           /* Argument to pass to xBusyHandler */
  1454   1454   ){
  1455   1455     int rc;                         /* Return code */
................................................................................
  1475   1475       walSetLock(pWal, SQLITE_SHM_UNLOCK);
  1476   1476       return rc;
  1477   1477     }
  1478   1478   
  1479   1479     /* Copy data from the log to the database file. */
  1480   1480     rc = walIndexReadHdr(pWal, &isChanged);
  1481   1481     if( rc==SQLITE_OK ){
  1482         -    rc = walCheckpoint(pWal, pFd, sync_flags, nBuf, zBuf);
         1482  +    rc = walCheckpoint(pWal, sync_flags, nBuf, zBuf);
  1483   1483     }
  1484   1484     if( isChanged ){
  1485   1485       /* If a new wal-index header was loaded before the checkpoint was 
  1486   1486       ** performed, then the pager-cache associated with log pWal is now
  1487   1487       ** out of date. So zero the cached wal-index header to ensure that
  1488   1488       ** next time the pager opens a snapshot on this database it knows that
  1489   1489       ** the cache needs to be reset.

Changes to src/wal.h.

    37     37   
    38     38   /* Connection to a write-ahead log (WAL) file. 
    39     39   ** There is one object of this type for each pager. 
    40     40   */
    41     41   typedef struct Wal Wal;
    42     42   
    43     43   /* Open and close a connection to a write-ahead log. */
    44         -int sqlite3WalOpen(sqlite3_vfs*, const char *zDb, Wal **ppWal);
    45         -int sqlite3WalClose(Wal *pWal, sqlite3_file *pFd, int sync_flags, int, u8 *);
           44  +int sqlite3WalOpen(sqlite3_vfs*, sqlite3_file*, const char *zName, Wal**);
           45  +int sqlite3WalClose(Wal *pWal, int sync_flags, int, u8 *);
    46     46   
    47     47   /* Used by readers to open (lock) and close (unlock) a snapshot.  A 
    48     48   ** snapshot is like a read-transaction.  It is the state of the database
    49     49   ** at an instant in time.  sqlite3WalOpenSnapshot gets a read lock and
    50     50   ** preserves the current state even if the other threads or processes
    51     51   ** write to or checkpoint the WAL.  sqlite3WalCloseSnapshot() closes the
    52     52   ** transaction and releases the lock.
................................................................................
    77     77   
    78     78   /* Write a frame or frames to the log. */
    79     79   int sqlite3WalFrames(Wal *pWal, int, PgHdr *, Pgno, int, int);
    80     80   
    81     81   /* Copy pages from the log to the database file */ 
    82     82   int sqlite3WalCheckpoint(
    83     83     Wal *pWal,                      /* Write-ahead log connection */
    84         -  sqlite3_file *pFd,              /* File descriptor open on db file */
    85     84     int sync_flags,                 /* Flags to sync db file with (or 0) */
    86     85     int nBuf,                       /* Size of buffer nBuf */
    87     86     u8 *zBuf,                       /* Temporary buffer to use */
    88     87     int (*xBusyHandler)(void *),    /* Pointer to busy-handler function */
    89     88     void *pBusyHandlerArg           /* Argument to pass to xBusyHandler */
    90     89   );
    91     90