/ Check-in [f4780bde]
Login

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

Overview
Comment:Changes so that the xShmOpen VFS method is no longer required. Its job can be done by the first call to xShmMap. Rename xShmClose to xShmUnmap.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1:f4780bde62c6c19146d2723c101540b8db898d38
User & Date: dan 2010-07-13 18:44:04
Context
2010-07-13
18:45
Fix a typo in a comment in sqlite.h.in. check-in: 4a6c4b66 user: dan tags: experimental
18:44
Changes so that the xShmOpen VFS method is no longer required. Its job can be done by the first call to xShmMap. Rename xShmClose to xShmUnmap. check-in: f4780bde user: dan tags: experimental
14:48
Improved documentation for the SQLITE_ACCESS_* constants that are used with the xAccess() method of the VFS. check-in: 3d4bb65f user: drh tags: experimental
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os.c.

    96     96   int sqlite3OsSectorSize(sqlite3_file *id){
    97     97     int (*xSectorSize)(sqlite3_file*) = id->pMethods->xSectorSize;
    98     98     return (xSectorSize ? xSectorSize(id) : SQLITE_DEFAULT_SECTOR_SIZE);
    99     99   }
   100    100   int sqlite3OsDeviceCharacteristics(sqlite3_file *id){
   101    101     return id->pMethods->xDeviceCharacteristics(id);
   102    102   }
   103         -int sqlite3OsShmOpen(sqlite3_file *id){
   104         -  return id->pMethods->xShmOpen(id);
   105         -}
   106    103   int sqlite3OsShmLock(sqlite3_file *id, int offset, int n, int flags){
   107    104     return id->pMethods->xShmLock(id, offset, n, flags);
   108    105   }
   109    106   void sqlite3OsShmBarrier(sqlite3_file *id){
   110    107     id->pMethods->xShmBarrier(id);
   111    108   }
   112    109   int sqlite3OsShmClose(sqlite3_file *id, int deleteFlag){
   113         -  return id->pMethods->xShmClose(id, deleteFlag);
          110  +  return id->pMethods->xShmUnmap(id, deleteFlag);
   114    111   }
   115    112   int sqlite3OsShmMap(
   116         -  sqlite3_file *id, 
   117         -  int iPage, 
   118         -  int pgsz, 
   119         -  int isWrite, 
   120         -  void volatile **pp
          113  +  sqlite3_file *id,               /* Database file handle */
          114  +  int iPage,
          115  +  int pgsz,
          116  +  int bExtend,                    /* True to extend file if necessary */
          117  +  void volatile **pp              /* OUT: Pointer to mapping */
   121    118   ){
   122         -  return id->pMethods->xShmMap(id, iPage, pgsz, isWrite, pp);
          119  +  return id->pMethods->xShmMap(id, iPage, pgsz, bExtend, pp);
   123    120   }
   124    121   
   125    122   /*
   126    123   ** The next group of routines are convenience wrappers around the
   127    124   ** VFS methods.
   128    125   */
   129    126   int sqlite3OsOpen(

Changes to src/os.h.

   243    243   int sqlite3OsLock(sqlite3_file*, int);
   244    244   int sqlite3OsUnlock(sqlite3_file*, int);
   245    245   int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
   246    246   int sqlite3OsFileControl(sqlite3_file*,int,void*);
   247    247   #define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
   248    248   int sqlite3OsSectorSize(sqlite3_file *id);
   249    249   int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
   250         -int sqlite3OsShmOpen(sqlite3_file *id);
          250  +int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
   251    251   int sqlite3OsShmLock(sqlite3_file *id, int, int, int);
   252    252   void sqlite3OsShmBarrier(sqlite3_file *id);
   253    253   int sqlite3OsShmClose(sqlite3_file *id, int);
   254         -int sqlite3OsShmMap(sqlite3_file *,int,int,int,void volatile **);
   255    254   
   256    255   /* 
   257    256   ** Functions for accessing sqlite3_vfs methods 
   258    257   */
   259    258   int sqlite3OsOpen(sqlite3_vfs *, const char *, sqlite3_file*, int, int *);
   260    259   int sqlite3OsDelete(sqlite3_vfs *, const char *, int);
   261    260   int sqlite3OsAccess(sqlite3_vfs *, const char *, int, int *pResOut);

Changes to src/os_unix.c.

  3271   3271       if( p->h>=0 ) close(p->h);
  3272   3272       p->pInode->pShmNode = 0;
  3273   3273       sqlite3_free(p);
  3274   3274     }
  3275   3275   }
  3276   3276   
  3277   3277   /*
  3278         -** Open a shared-memory area associated with open database file fd.  
         3278  +** Open a shared-memory area associated with open database file pDbFd.  
  3279   3279   ** This particular implementation uses mmapped files.
  3280   3280   **
  3281   3281   ** The file used to implement shared-memory is in the same directory
  3282   3282   ** as the open database file and has the same name as the open database
  3283   3283   ** file with the "-shm" suffix added.  For example, if the database file
  3284   3284   ** is "/home/user1/config.db" then the file that is created and mmapped
  3285   3285   ** for shared memory will be called "/home/user1/config.db-shm".  We
................................................................................
  3290   3290   ** shared memory - meaning that their memory would not really be shared - 
  3291   3291   ** resulting in database corruption.
  3292   3292   **
  3293   3293   ** When opening a new shared-memory file, if no other instances of that
  3294   3294   ** file are currently open, in this process or in other processes, then
  3295   3295   ** the file must be truncated to zero length or have its header cleared.
  3296   3296   */
  3297         -static int unixShmOpen(
  3298         -  sqlite3_file *fd      /* The file descriptor of the associated database */
  3299         -){
  3300         -  struct unixShm *p = 0;             /* The connection to be opened */
  3301         -  struct unixShmNode *pShmNode = 0;  /* The underlying mmapped file */
  3302         -  int rc;                            /* Result code */
  3303         -  struct unixFile *pDbFd;            /* Underlying database file */
  3304         -  unixInodeInfo *pInode;             /* The inode of fd */
  3305         -  char *zShmFilename;                /* Name of the file used for SHM */
  3306         -  int nShmFilename;                  /* Size of the SHM filename in bytes */
         3297  +static int unixOpenSharedMemory(unixFile *pDbFd){
         3298  +  struct unixShm *p = 0;          /* The connection to be opened */
         3299  +  struct unixShmNode *pShmNode;   /* The underlying mmapped file */
         3300  +  int rc;                         /* Result code */
         3301  +  unixInodeInfo *pInode;          /* The inode of fd */
         3302  +  char *zShmFilename;             /* Name of the file used for SHM */
         3303  +  int nShmFilename;               /* Size of the SHM filename in bytes */
  3307   3304   
  3308         -  /* Allocate space for the new sqlite3_shm object.
  3309         -  */
         3305  +  /* Allocate space for the new unixShm object. */
  3310   3306     p = sqlite3_malloc( sizeof(*p) );
  3311   3307     if( p==0 ) return SQLITE_NOMEM;
  3312   3308     memset(p, 0, sizeof(*p));
  3313         -  pDbFd = (struct unixFile*)fd;
  3314   3309     assert( pDbFd->pShm==0 );
  3315   3310   
  3316         -  /* Check to see if a unixShmNode object already exists.  Reuse an existing
  3317         -  ** one if present.  Create a new one if necessary.
         3311  +  /* Check to see if a unixShmNode object already exists. Reuse an existing
         3312  +  ** one if present. Create a new one if necessary.
  3318   3313     */
  3319   3314     unixEnterMutex();
  3320   3315     pInode = pDbFd->pInode;
  3321   3316     pShmNode = pInode->pShmNode;
  3322   3317     if( pShmNode==0 ){
  3323   3318       nShmFilename = 5 + (int)strlen(pDbFd->zPath);
  3324   3319       pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nShmFilename );
................................................................................
  3376   3371     unixShmPurge(pDbFd);       /* This call frees pShmNode if required */
  3377   3372     sqlite3_free(p);
  3378   3373     unixLeaveMutex();
  3379   3374     return rc;
  3380   3375   }
  3381   3376   
  3382   3377   /*
  3383         -** Close a connection to shared-memory.  Delete the underlying 
  3384         -** storage if deleteFlag is true.
  3385         -*/
  3386         -static int unixShmClose(
  3387         -  sqlite3_file *fd,          /* The underlying database file */
  3388         -  int deleteFlag             /* Delete shared-memory if true */
  3389         -){
  3390         -  unixShm *p;            /* The connection to be closed */
  3391         -  unixShmNode *pShmNode; /* The underlying shared-memory file */
  3392         -  unixShm **pp;          /* For looping over sibling connections */
  3393         -  unixFile *pDbFd;       /* The underlying database file */
  3394         -
  3395         -  pDbFd = (unixFile*)fd;
         3378  +** This function is called to obtain a pointer to region iRegion of the 
         3379  +** shared-memory associated with the database file fd. Shared-memory regions 
         3380  +** are numbered starting from zero. Each shared-memory region is szRegion 
         3381  +** bytes in size.
         3382  +**
         3383  +** If an error occurs, an error code is returned and *pp is set to NULL.
         3384  +**
         3385  +** Otherwise, if the bExtend parameter is 0 and the requested shared-memory
         3386  +** region has not been allocated (by any client, including one running in a
         3387  +** separate process), then *pp is set to NULL and SQLITE_OK returned. If 
         3388  +** bExtend is non-zero and the requested shared-memory region has not yet 
         3389  +** been allocated, it is allocated by this function.
         3390  +**
         3391  +** If the shared-memory region has already been allocated or is allocated by
         3392  +** this call as described above, then it is mapped into this processes 
         3393  +** address space (if it is not already), *pp is set to point to the mapped 
         3394  +** memory and SQLITE_OK returned.
         3395  +*/
         3396  +static int unixShmMap(
         3397  +  sqlite3_file *fd,               /* Handle open on database file */
         3398  +  int iRegion,                    /* Region to retrieve */
         3399  +  int szRegion,                   /* Size of regions */
         3400  +  int bExtend,                    /* True to extend file if necessary */
         3401  +  void volatile **pp              /* OUT: Mapped memory */
         3402  +){
         3403  +  unixFile *pDbFd = (unixFile*)fd;
         3404  +  unixShm *p;
         3405  +  unixShmNode *pShmNode;
         3406  +  int rc = SQLITE_OK;
         3407  +
         3408  +  /* If the shared-memory file has not yet been opened, open it now. */
         3409  +  if( pDbFd->pShm==0 ){
         3410  +    rc = unixOpenSharedMemory(pDbFd);
         3411  +    if( rc!=SQLITE_OK ) return rc;
         3412  +  }
         3413  +
  3396   3414     p = pDbFd->pShm;
  3397         -  if( p==0 ) return SQLITE_OK;
  3398   3415     pShmNode = p->pShmNode;
  3399         -
  3400         -  assert( pShmNode==pDbFd->pInode->pShmNode );
  3401         -  assert( pShmNode->pInode==pDbFd->pInode );
  3402         -
  3403         -  /* Remove connection p from the set of connections associated
  3404         -  ** with pShmNode */
  3405   3416     sqlite3_mutex_enter(pShmNode->mutex);
  3406         -  for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
  3407         -  *pp = p->pNext;
         3417  +  assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
  3408   3418   
  3409         -  /* Free the connection p */
  3410         -  sqlite3_free(p);
  3411         -  pDbFd->pShm = 0;
         3419  +  if( pShmNode->nRegion<=iRegion ){
         3420  +    char **apNew;                      /* New apRegion[] array */
         3421  +    int nByte = (iRegion+1)*szRegion;  /* Minimum required file size */
         3422  +    struct stat sStat;                 /* Used by fstat() */
         3423  +
         3424  +    pShmNode->szRegion = szRegion;
         3425  +
         3426  +    /* The requested region is not mapped into this processes address space.
         3427  +    ** Check to see if it has been allocated (i.e. if the wal-index file is
         3428  +    ** large enough to contain the requested region).
         3429  +    */
         3430  +    if( fstat(pShmNode->h, &sStat) ){
         3431  +      rc = SQLITE_IOERR_SHMSIZE;
         3432  +      goto shmpage_out;
         3433  +    }
         3434  +
         3435  +    if( sStat.st_size<nByte ){
         3436  +      /* The requested memory region does not exist. If bExtend is set to
         3437  +      ** false, exit early. *pp will be set to NULL and SQLITE_OK returned.
         3438  +      **
         3439  +      ** Alternatively, if bExtend is true, use ftruncate() to allocate
         3440  +      ** the requested memory region.
         3441  +      */
         3442  +      if( !bExtend ) goto shmpage_out;
         3443  +      if( ftruncate(pShmNode->h, nByte) ){
         3444  +        rc = SQLITE_IOERR_SHMSIZE;
         3445  +        goto shmpage_out;
         3446  +      }
         3447  +    }
         3448  +
         3449  +    /* Map the requested memory region into this processes address space. */
         3450  +    apNew = (char **)sqlite3_realloc(
         3451  +        pShmNode->apRegion, (iRegion+1)*sizeof(char *)
         3452  +    );
         3453  +    if( !apNew ){
         3454  +      rc = SQLITE_IOERR_NOMEM;
         3455  +      goto shmpage_out;
         3456  +    }
         3457  +    pShmNode->apRegion = apNew;
         3458  +    while(pShmNode->nRegion<=iRegion){
         3459  +      void *pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE, 
         3460  +          MAP_SHARED, pShmNode->h, iRegion*szRegion
         3461  +      );
         3462  +      if( pMem==MAP_FAILED ){
         3463  +        rc = SQLITE_IOERR;
         3464  +        goto shmpage_out;
         3465  +      }
         3466  +      pShmNode->apRegion[pShmNode->nRegion] = pMem;
         3467  +      pShmNode->nRegion++;
         3468  +    }
         3469  +  }
         3470  +
         3471  +shmpage_out:
         3472  +  if( pShmNode->nRegion>iRegion ){
         3473  +    *pp = pShmNode->apRegion[iRegion];
         3474  +  }else{
         3475  +    *pp = 0;
         3476  +  }
  3412   3477     sqlite3_mutex_leave(pShmNode->mutex);
  3413         -
  3414         -  /* If pShmNode->nRef has reached 0, then close the underlying
  3415         -  ** shared-memory file, too */
  3416         -  unixEnterMutex();
  3417         -  assert( pShmNode->nRef>0 );
  3418         -  pShmNode->nRef--;
  3419         -  if( pShmNode->nRef==0 ){
  3420         -    if( deleteFlag ) unlink(pShmNode->zFilename);
  3421         -    unixShmPurge(pDbFd);
  3422         -  }
  3423         -  unixLeaveMutex();
  3424         -
  3425         -  return SQLITE_OK;
         3478  +  return rc;
  3426   3479   }
  3427   3480   
  3428   3481   /*
  3429   3482   ** Change the lock state for a shared-memory segment.
  3430   3483   **
  3431   3484   ** Note that the relationship between SHAREd and EXCLUSIVE locks is a little
  3432   3485   ** different here than in posix.  In xShmLock(), one can go from unlocked
................................................................................
  3548   3601   ){
  3549   3602     UNUSED_PARAMETER(fd);
  3550   3603     unixEnterMutex();
  3551   3604     unixLeaveMutex();
  3552   3605   }
  3553   3606   
  3554   3607   /*
  3555         -** This function is called to obtain a pointer to region iRegion of the 
  3556         -** shared-memory associated with the database file fd. Shared-memory regions 
  3557         -** are numbered starting from zero. Each shared-memory region is szRegion 
  3558         -** bytes in size.
  3559         -**
  3560         -** If an error occurs, an error code is returned and *pp is set to NULL.
  3561         -**
  3562         -** Otherwise, if the isWrite parameter is 0 and the requested shared-memory
  3563         -** region has not been allocated (by any client, including one running in a
  3564         -** separate process), then *pp is set to NULL and SQLITE_OK returned. If 
  3565         -** isWrite is non-zero and the requested shared-memory region has not yet 
  3566         -** been allocated, it is allocated by this function.
  3567         -**
  3568         -** If the shared-memory region has already been allocated or is allocated by
  3569         -** this call as described above, then it is mapped into this processes 
  3570         -** address space (if it is not already), *pp is set to point to the mapped 
  3571         -** memory and SQLITE_OK returned.
         3608  +** Close a connection to shared-memory.  Delete the underlying 
         3609  +** storage if deleteFlag is true.
  3572   3610   */
  3573         -static int unixShmMap(
  3574         -  sqlite3_file *fd,               /* Handle open on database file */
  3575         -  int iRegion,                    /* Region to retrieve */
  3576         -  int szRegion,                   /* Size of regions */
  3577         -  int isWrite,                    /* True to extend file if necessary */
  3578         -  void volatile **pp              /* OUT: Mapped memory */
         3611  +static int unixShmUnmap(
         3612  +  sqlite3_file *fd,               /* The underlying database file */
         3613  +  int deleteFlag                  /* Delete shared-memory if true */
  3579   3614   ){
  3580         -  unixFile *pDbFd = (unixFile*)fd;
  3581         -  unixShm *p = pDbFd->pShm;
  3582         -  unixShmNode *pShmNode = p->pShmNode;
  3583         -  int rc = SQLITE_OK;
         3615  +  unixShm *p;                     /* The connection to be closed */
         3616  +  unixShmNode *pShmNode;          /* The underlying shared-memory file */
         3617  +  unixShm **pp;                   /* For looping over sibling connections */
         3618  +  unixFile *pDbFd;                /* The underlying database file */
  3584   3619   
         3620  +  pDbFd = (unixFile*)fd;
         3621  +  p = pDbFd->pShm;
         3622  +  if( p==0 ) return SQLITE_OK;
         3623  +  pShmNode = p->pShmNode;
         3624  +
         3625  +  assert( pShmNode==pDbFd->pInode->pShmNode );
         3626  +  assert( pShmNode->pInode==pDbFd->pInode );
         3627  +
         3628  +  /* Remove connection p from the set of connections associated
         3629  +  ** with pShmNode */
  3585   3630     sqlite3_mutex_enter(pShmNode->mutex);
  3586         -  assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
         3631  +  for(pp=&pShmNode->pFirst; (*pp)!=p; pp = &(*pp)->pNext){}
         3632  +  *pp = p->pNext;
  3587   3633   
  3588         -  if( pShmNode->nRegion<=iRegion ){
  3589         -    char **apNew;                      /* New apRegion[] array */
  3590         -    int nByte = (iRegion+1)*szRegion;  /* Minimum required file size */
  3591         -    struct stat sStat;                 /* Used by fstat() */
  3592         -
  3593         -    pShmNode->szRegion = szRegion;
  3594         -
  3595         -    /* The requested region is not mapped into this processes address space.
  3596         -    ** Check to see if it has been allocated (i.e. if the wal-index file is
  3597         -    ** large enough to contain the requested region).
  3598         -    */
  3599         -    if( fstat(pShmNode->h, &sStat) ){
  3600         -      rc = SQLITE_IOERR_SHMSIZE;
  3601         -      goto shmpage_out;
  3602         -    }
  3603         -
  3604         -    if( sStat.st_size<nByte ){
  3605         -      /* The requested memory region does not exist. If isWrite is set to
  3606         -      ** zero, exit early. *pp will be set to NULL and SQLITE_OK returned.
  3607         -      **
  3608         -      ** Alternatively, if isWrite is non-zero, use ftruncate() to allocate
  3609         -      ** the requested memory region.
  3610         -      */
  3611         -      if( !isWrite ) goto shmpage_out;
  3612         -      if( ftruncate(pShmNode->h, nByte) ){
  3613         -        rc = SQLITE_IOERR_SHMSIZE;
  3614         -        goto shmpage_out;
  3615         -      }  
  3616         -    }
  3617         -
  3618         -    /* Map the requested memory region into this processes address space. */
  3619         -    apNew = (char **)sqlite3_realloc(
  3620         -        pShmNode->apRegion, (iRegion+1)*sizeof(char *)
  3621         -    );
  3622         -    if( !apNew ){
  3623         -      rc = SQLITE_IOERR_NOMEM;
  3624         -      goto shmpage_out;
  3625         -    }
  3626         -    pShmNode->apRegion = apNew;
  3627         -    while(pShmNode->nRegion<=iRegion){
  3628         -      void *pMem = mmap(0, szRegion, PROT_READ|PROT_WRITE, 
  3629         -          MAP_SHARED, pShmNode->h, iRegion*szRegion
  3630         -      );
  3631         -      if( pMem==MAP_FAILED ){
  3632         -        rc = SQLITE_IOERR;
  3633         -        goto shmpage_out;
  3634         -      }
  3635         -      pShmNode->apRegion[pShmNode->nRegion] = pMem;
  3636         -      pShmNode->nRegion++;
  3637         -    }
  3638         -  }
  3639         -
  3640         -shmpage_out:
  3641         -  if( pShmNode->nRegion>iRegion ){
  3642         -    *pp = pShmNode->apRegion[iRegion];
  3643         -  }else{
  3644         -    *pp = 0;
  3645         -  }
         3634  +  /* Free the connection p */
         3635  +  sqlite3_free(p);
         3636  +  pDbFd->pShm = 0;
  3646   3637     sqlite3_mutex_leave(pShmNode->mutex);
  3647         -  return rc;
         3638  +
         3639  +  /* If pShmNode->nRef has reached 0, then close the underlying
         3640  +  ** shared-memory file, too */
         3641  +  unixEnterMutex();
         3642  +  assert( pShmNode->nRef>0 );
         3643  +  pShmNode->nRef--;
         3644  +  if( pShmNode->nRef==0 ){
         3645  +    if( deleteFlag ) unlink(pShmNode->zFilename);
         3646  +    unixShmPurge(pDbFd);
         3647  +  }
         3648  +  unixLeaveMutex();
         3649  +
         3650  +  return SQLITE_OK;
  3648   3651   }
         3652  +
  3649   3653   
  3650   3654   #else
  3651         -# define unixShmOpen    0
         3655  +# define unixShmMap     0
  3652   3656   # define unixShmLock    0
  3653         -# define unixShmMap     0
  3654   3657   # define unixShmBarrier 0
  3655         -# define unixShmClose   0
         3658  +# define unixShmUnmap   0
  3656   3659   #endif /* #ifndef SQLITE_OMIT_WAL */
  3657   3660   
  3658   3661   /*
  3659   3662   ** Here ends the implementation of all sqlite3_file methods.
  3660   3663   **
  3661   3664   ********************** End sqlite3_file Methods *******************************
  3662   3665   ******************************************************************************/
................................................................................
  3706   3709      unixFileSize,               /* xFileSize */                               \
  3707   3710      LOCK,                       /* xLock */                                   \
  3708   3711      UNLOCK,                     /* xUnlock */                                 \
  3709   3712      CKLOCK,                     /* xCheckReservedLock */                      \
  3710   3713      unixFileControl,            /* xFileControl */                            \
  3711   3714      unixSectorSize,             /* xSectorSize */                             \
  3712   3715      unixDeviceCharacteristics,  /* xDeviceCapabilities */                     \
  3713         -   unixShmOpen,                /* xShmOpen */                                \
         3716  +   unixShmMap,                 /* xShmMap */                                 \
  3714   3717      unixShmLock,                /* xShmLock */                                \
  3715         -   unixShmMap,                 /* xShmMap */                                 \
  3716   3718      unixShmBarrier,             /* xShmBarrier */                             \
  3717         -   unixShmClose                /* xShmClose */                               \
         3719  +   unixShmUnmap                /* xShmUnmap */                               \
  3718   3720   };                                                                           \
  3719   3721   static const sqlite3_io_methods *FINDER##Impl(const char *z, unixFile *p){   \
  3720   3722     UNUSED_PARAMETER(z); UNUSED_PARAMETER(p);                                  \
  3721   3723     return &METHOD;                                                            \
  3722   3724   }                                                                            \
  3723   3725   static const sqlite3_io_methods *(*const FINDER)(const char*,unixFile *p)    \
  3724   3726       = FINDER##Impl;

Changes to src/os_win.c.

  1370   1370       }else{
  1371   1371         pp = &p->pNext;
  1372   1372       }
  1373   1373     }
  1374   1374   }
  1375   1375   
  1376   1376   /*
  1377         -** Open a shared-memory area.  This particular implementation uses
  1378         -** mmapped files.
  1379         -**
  1380         -** zName is a filename used to identify the shared-memory area.  The
  1381         -** implementation does not (and perhaps should not) use this name
  1382         -** directly, but rather use it as a template for finding an appropriate
  1383         -** name for the shared-memory storage.  In this implementation, the
  1384         -** string "-index" is appended to zName and used as the name of the
  1385         -** mmapped file.
         1377  +** Open the shared-memory area associated with database file pDbFd.
  1386   1378   **
  1387   1379   ** When opening a new shared-memory file, if no other instances of that
  1388   1380   ** file are currently open, in this process or in other processes, then
  1389   1381   ** the file must be truncated to zero length or have its header cleared.
  1390   1382   */
  1391         -static int winShmOpen(
  1392         -  sqlite3_file *fd      /* The file to which to attach shared memory */
  1393         -){
  1394         -  struct winFile *pDbFd;             /* Database to which to attach SHM */
         1383  +static int winOpenSharedMemory(winFile *pDbFd){
  1395   1384     struct winShm *p;                  /* The connection to be opened */
  1396   1385     struct winShmNode *pShmNode = 0;   /* The underlying mmapped file */
  1397   1386     int rc;                            /* Result code */
  1398   1387     struct winShmNode *pNew;           /* Newly allocated winShmNode */
  1399   1388     int nName;                         /* Size of zName in bytes */
  1400   1389   
  1401         -  pDbFd = (winFile*)fd;
  1402   1390     assert( pDbFd->pShm==0 );    /* Not previously opened */
  1403   1391   
  1404   1392     /* Allocate space for the new sqlite3_shm object.  Also speculatively
  1405   1393     ** allocate space for a new winShmNode and filename.
  1406   1394     */
  1407   1395     p = sqlite3_malloc( sizeof(*p) );
  1408   1396     if( p==0 ) return SQLITE_NOMEM;
................................................................................
  1676   1664     int iRegion,                    /* Region to retrieve */
  1677   1665     int szRegion,                   /* Size of regions */
  1678   1666     int isWrite,                    /* True to extend file if necessary */
  1679   1667     void volatile **pp              /* OUT: Mapped memory */
  1680   1668   ){
  1681   1669     winFile *pDbFd = (winFile*)fd;
  1682   1670     winShm *p = pDbFd->pShm;
  1683         -  winShmNode *pShmNode = p->pShmNode;
         1671  +  winShmNode *pShmNode;
  1684   1672     int rc = SQLITE_OK;
  1685   1673   
         1674  +  if( !p ){
         1675  +    rc = winOpenSharedMemory(pDbFd);
         1676  +    if( rc!=SQLITE_OK ) return rc;
         1677  +    p = pDbFd->pShm;
         1678  +  }
         1679  +  pShmNode = p->pShmNode;
         1680  +
  1686   1681     sqlite3_mutex_enter(pShmNode->mutex);
  1687   1682     assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
  1688   1683   
  1689   1684     if( pShmNode->nRegion<=iRegion ){
  1690   1685       struct ShmRegion *apNew;           /* New aRegion[] array */
  1691   1686       int nByte = (iRegion+1)*szRegion;  /* Minimum required file size */
  1692   1687       sqlite3_int64 sz;                  /* Current size of wal-index file */
................................................................................
  1761   1756       *pp = 0;
  1762   1757     }
  1763   1758     sqlite3_mutex_leave(pShmNode->mutex);
  1764   1759     return rc;
  1765   1760   }
  1766   1761   
  1767   1762   #else
  1768         -# define winShmOpen    0
  1769         -# define winShmLock    0
  1770   1763   # define winShmMap     0
         1764  +# define winShmLock    0
  1771   1765   # define winShmBarrier 0
  1772   1766   # define winShmClose   0
  1773   1767   #endif /* #ifndef SQLITE_OMIT_WAL */
  1774   1768   
  1775   1769   /*
  1776   1770   ** Here ends the implementation of all sqlite3_file methods.
  1777   1771   **
................................................................................
  1779   1773   ******************************************************************************/
  1780   1774   
  1781   1775   /*
  1782   1776   ** This vector defines all the methods that can operate on an
  1783   1777   ** sqlite3_file for win32.
  1784   1778   */
  1785   1779   static const sqlite3_io_methods winIoMethod = {
  1786         -  2,                        /* iVersion */
  1787         -  winClose,
  1788         -  winRead,
  1789         -  winWrite,
  1790         -  winTruncate,
  1791         -  winSync,
  1792         -  winFileSize,
  1793         -  winLock,
  1794         -  winUnlock,
  1795         -  winCheckReservedLock,
  1796         -  winFileControl,
  1797         -  winSectorSize,
  1798         -  winDeviceCharacteristics,
  1799         -  winShmOpen,              /* xShmOpen */
  1800         -  winShmLock,              /* xShmLock */
  1801         -  winShmMap,               /* xShmMap */
  1802         -  winShmBarrier,           /* xShmBarrier */
  1803         -  winShmClose              /* xShmClose */
         1780  +  2,                              /* iVersion */
         1781  +  winClose,                       /* xClose */
         1782  +  winRead,                        /* xRead */
         1783  +  winWrite,                       /* xWrite */
         1784  +  winTruncate,                    /* xTruncate */
         1785  +  winSync,                        /* xSync */
         1786  +  winFileSize,                    /* xFileSize */
         1787  +  winLock,                        /* xLock */
         1788  +  winUnlock,                      /* xUnlock */
         1789  +  winCheckReservedLock,           /* xCheckReservedLock */
         1790  +  winFileControl,                 /* xFileControl */
         1791  +  winSectorSize,                  /* xSectorSize */
         1792  +  winDeviceCharacteristics,       /* xDeviceCharacteristics */
         1793  +  winShmMap,                      /* xShmMap */
         1794  +  winShmLock,                     /* xShmLock */
         1795  +  winShmBarrier,                  /* xShmBarrier */
         1796  +  winShmClose                     /* xShmClose */
  1804   1797   };
  1805   1798   
  1806   1799   /****************************************************************************
  1807   1800   **************************** sqlite3_vfs methods ****************************
  1808   1801   **
  1809   1802   ** This division contains the implementation of methods on the
  1810   1803   ** sqlite3_vfs object.

Changes to src/pager.c.

  6019   6019   
  6020   6020   /*
  6021   6021   ** Return true if the underlying VFS for the given pager supports the
  6022   6022   ** primitives necessary for write-ahead logging.
  6023   6023   */
  6024   6024   int sqlite3PagerWalSupported(Pager *pPager){
  6025   6025     const sqlite3_io_methods *pMethods = pPager->fd->pMethods;
  6026         -  return pMethods->iVersion>=2 && pMethods->xShmOpen!=0;
         6026  +  return pMethods->iVersion>=2 && pMethods->xShmMap!=0;
  6027   6027   }
  6028   6028   
  6029   6029   /*
  6030   6030   ** The caller must be holding a SHARED lock on the database file to call
  6031   6031   ** this function.
  6032   6032   **
  6033   6033   ** If the pager passed as the first argument is open on a real database

Changes to src/sqlite.h.in.

   656    656     int (*xLock)(sqlite3_file*, int);
   657    657     int (*xUnlock)(sqlite3_file*, int);
   658    658     int (*xCheckReservedLock)(sqlite3_file*, int *pResOut);
   659    659     int (*xFileControl)(sqlite3_file*, int op, void *pArg);
   660    660     int (*xSectorSize)(sqlite3_file*);
   661    661     int (*xDeviceCharacteristics)(sqlite3_file*);
   662    662     /* Methods above are valid for version 1 */
   663         -  int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, int*, void volatile**);
          663  +  int (*xShmMap)(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
   664    664     int (*xShmLock)(sqlite3_file*, int offset, int n, int flags);
   665    665     void (*xShmBarrier)(sqlite3_file*);
   666    666     int (*xShmUnmap)(sqlite3_file*, int deleteFlag);
   667    667     /* Methods above are valid for version 2 */
   668    668     /* Additional methods may be added in future releases */
   669    669   };
   670    670   

Changes to src/test6.c.

   519    519   static int cfDeviceCharacteristics(sqlite3_file *pFile){
   520    520     return g.iDeviceCharacteristics;
   521    521   }
   522    522   
   523    523   /*
   524    524   ** Pass-throughs for WAL support.
   525    525   */
   526         -static int cfShmOpen(sqlite3_file *pFile){
   527         -  return sqlite3OsShmOpen(((CrashFile*)pFile)->pRealFile);
   528         -}
   529    526   static int cfShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
   530    527     return sqlite3OsShmLock(((CrashFile*)pFile)->pRealFile, ofst, n, flags);
   531    528   }
   532    529   static void cfShmBarrier(sqlite3_file *pFile){
   533    530     sqlite3OsShmBarrier(((CrashFile*)pFile)->pRealFile);
   534    531   }
   535    532   static int cfShmClose(sqlite3_file *pFile, int delFlag){
................................................................................
   555    552     cfFileSize,                   /* xFileSize */
   556    553     cfLock,                       /* xLock */
   557    554     cfUnlock,                     /* xUnlock */
   558    555     cfCheckReservedLock,          /* xCheckReservedLock */
   559    556     cfFileControl,                /* xFileControl */
   560    557     cfSectorSize,                 /* xSectorSize */
   561    558     cfDeviceCharacteristics,      /* xDeviceCharacteristics */
   562         -  cfShmOpen,                    /* xShmOpen */
   563         -  cfShmLock,                    /* xShmLock */
   564    559     cfShmMap,                     /* xShmMap */
          560  +  cfShmLock,                    /* xShmLock */
   565    561     cfShmBarrier,                 /* xShmBarrier */
   566    562     cfShmClose                    /* xShmClose */
   567    563   };
   568    564   
   569    565   /*
   570    566   ** Application data for the crash VFS
   571    567   */

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     53   static int devsymShmLock(sqlite3_file*,int,int,int);
    55     54   static int devsymShmMap(sqlite3_file*,int,int,int, void volatile **);
    56     55   static void devsymShmBarrier(sqlite3_file*);
    57     56   static int devsymShmClose(sqlite3_file*,int);
    58     57   
    59     58   /*
    60     59   ** Method declarations for devsym_vfs.
................................................................................
   112    111     devsymFileSize,                   /* xFileSize */
   113    112     devsymLock,                       /* xLock */
   114    113     devsymUnlock,                     /* xUnlock */
   115    114     devsymCheckReservedLock,          /* xCheckReservedLock */
   116    115     devsymFileControl,                /* xFileControl */
   117    116     devsymSectorSize,                 /* xSectorSize */
   118    117     devsymDeviceCharacteristics,      /* xDeviceCharacteristics */
   119         -  devsymShmOpen,                    /* xShmOpen */
   120         -  devsymShmLock,                    /* xShmLock */
   121    118     devsymShmMap,                     /* xShmMap */
          119  +  devsymShmLock,                    /* xShmLock */
   122    120     devsymShmBarrier,                 /* xShmBarrier */
   123    121     devsymShmClose                    /* xShmClose */
   124    122   };
   125    123   
   126    124   struct DevsymGlobal {
   127    125     sqlite3_vfs *pVfs;
   128    126     int iDeviceChar;
................................................................................
   233    231   static int devsymDeviceCharacteristics(sqlite3_file *pFile){
   234    232     return g.iDeviceChar;
   235    233   }
   236    234   
   237    235   /*
   238    236   ** Shared-memory methods are all pass-thrus.
   239    237   */
   240         -static int devsymShmOpen(sqlite3_file *pFile){
   241         -  devsym_file *p = (devsym_file *)pFile;
   242         -  return sqlite3OsShmOpen(p->pReal);
   243         -}
   244    238   static int devsymShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
   245    239     devsym_file *p = (devsym_file *)pFile;
   246    240     return sqlite3OsShmLock(p->pReal, ofst, n, flags);
   247    241   }
   248    242   static int devsymShmMap(
   249    243     sqlite3_file *pFile, 
   250    244     int iRegion, 

Changes to src/test_onefile.c.

   215    215     fsFileSize,                   /* xFileSize */
   216    216     fsLock,                       /* xLock */
   217    217     fsUnlock,                     /* xUnlock */
   218    218     fsCheckReservedLock,          /* xCheckReservedLock */
   219    219     fsFileControl,                /* xFileControl */
   220    220     fsSectorSize,                 /* xSectorSize */
   221    221     fsDeviceCharacteristics,      /* xDeviceCharacteristics */
   222         -  0,                            /* xShmOpen */
   223         -  0,                            /* xShmLock */
   224    222     0,                            /* xShmMap */
          223  +  0,                            /* xShmLock */
   225    224     0,                            /* xShmBarrier */
   226    225     0                             /* xShmClose */
   227    226   };
   228    227   
   229    228   
   230    229   static sqlite3_io_methods tmp_io_methods = {
   231    230     1,                            /* iVersion */
................................................................................
   237    236     tmpFileSize,                  /* xFileSize */
   238    237     tmpLock,                      /* xLock */
   239    238     tmpUnlock,                    /* xUnlock */
   240    239     tmpCheckReservedLock,         /* xCheckReservedLock */
   241    240     tmpFileControl,               /* xFileControl */
   242    241     tmpSectorSize,                /* xSectorSize */
   243    242     tmpDeviceCharacteristics,     /* xDeviceCharacteristics */
   244         -  0,                            /* xShmOpen */
   245         -  0,                            /* xShmLock */
   246    243     0,                            /* xShmMap */
          244  +  0,                            /* xShmLock */
   247    245     0,                            /* xShmBarrier */
   248    246     0                             /* xShmClose */
   249    247   };
   250    248   
   251    249   /* Useful macros used in several places */
   252    250   #define MIN(x,y) ((x)<(y)?(x):(y))
   253    251   #define MAX(x,y) ((x)>(y)?(x):(y))

Changes to src/test_osinst.c.

    94     94   #define OS_READ              14 
    95     95   #define OS_SECTORSIZE        15
    96     96   #define OS_SLEEP             16
    97     97   #define OS_SYNC              17
    98     98   #define OS_TRUNCATE          18
    99     99   #define OS_UNLOCK            19
   100    100   #define OS_WRITE             20
   101         -#define OS_SHMOPEN           21
   102         -#define OS_SHMCLOSE          22
          101  +#define OS_SHMUNMAP          22
   103    102   #define OS_SHMMAP            23
   104    103   #define OS_SHMLOCK           25
   105    104   #define OS_SHMBARRIER        26
   106    105   #define OS_ANNOTATE          28
   107    106   
   108    107   #define OS_NUMEVENTS         29
   109    108   
................................................................................
   145    144   static int vfslogLock(sqlite3_file*, int);
   146    145   static int vfslogUnlock(sqlite3_file*, int);
   147    146   static int vfslogCheckReservedLock(sqlite3_file*, int *pResOut);
   148    147   static int vfslogFileControl(sqlite3_file*, int op, void *pArg);
   149    148   static int vfslogSectorSize(sqlite3_file*);
   150    149   static int vfslogDeviceCharacteristics(sqlite3_file*);
   151    150   
   152         -static int vfslogShmOpen(sqlite3_file *pFile);
   153    151   static int vfslogShmLock(sqlite3_file *pFile, int ofst, int n, int flags);
   154    152   static int vfslogShmMap(sqlite3_file *pFile,int,int,int,volatile void **);
   155    153   static void vfslogShmBarrier(sqlite3_file*);
   156         -static int vfslogShmClose(sqlite3_file *pFile, int deleteFlag);
          154  +static int vfslogShmUnmap(sqlite3_file *pFile, int deleteFlag);
   157    155   
   158    156   /*
   159    157   ** Method declarations for vfslog_vfs.
   160    158   */
   161    159   static int vfslogOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
   162    160   static int vfslogDelete(sqlite3_vfs*, const char *zName, int syncDir);
   163    161   static int vfslogAccess(sqlite3_vfs*, const char *zName, int flags, int *);
................................................................................
   205    203     vfslogFileSize,                 /* xFileSize */
   206    204     vfslogLock,                     /* xLock */
   207    205     vfslogUnlock,                   /* xUnlock */
   208    206     vfslogCheckReservedLock,        /* xCheckReservedLock */
   209    207     vfslogFileControl,              /* xFileControl */
   210    208     vfslogSectorSize,               /* xSectorSize */
   211    209     vfslogDeviceCharacteristics,    /* xDeviceCharacteristics */
   212         -  vfslogShmOpen,                  /* xShmOpen */
          210  +  vfslogShmMap,                   /* xShmMap */
   213    211     vfslogShmLock,                  /* xShmLock */
   214         -  vfslogShmMap,                   /* xShmMap */
   215    212     vfslogShmBarrier,               /* xShmBarrier */
   216         -  vfslogShmClose                  /* xShmClose */
          213  +  vfslogShmUnmap                  /* xShmUnmap */
   217    214   };
   218    215   
   219    216   #if defined(SQLITE_OS_UNIX) && !defined(NO_GETTOD)
   220    217   #include <sys/time.h>
   221    218   static sqlite3_uint64 vfslog_time(){
   222    219     struct timeval sTime;
   223    220     gettimeofday(&sTime, 0);
................................................................................
   419    416     t = vfslog_time();
   420    417     rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
   421    418     t = vfslog_time() - t;
   422    419     vfslog_call(p->pVfslog, OS_DEVCHAR, p->iFileId, t, rc, 0, 0);
   423    420     return rc;
   424    421   }
   425    422   
   426         -static int vfslogShmOpen(sqlite3_file *pFile){
   427         -  int rc;
   428         -  sqlite3_uint64 t;
   429         -  VfslogFile *p = (VfslogFile *)pFile;
   430         -  t = vfslog_time();
   431         -  rc = p->pReal->pMethods->xShmOpen(p->pReal);
   432         -  t = vfslog_time() - t;
   433         -  vfslog_call(p->pVfslog, OS_SHMOPEN, p->iFileId, t, rc, 0, 0);
   434         -  return rc;
   435         -}
   436    423   static int vfslogShmLock(sqlite3_file *pFile, int ofst, int n, int flags){
   437    424     int rc;
   438    425     sqlite3_uint64 t;
   439    426     VfslogFile *p = (VfslogFile *)pFile;
   440    427     t = vfslog_time();
   441    428     rc = p->pReal->pMethods->xShmLock(p->pReal, ofst, n, flags);
   442    429     t = vfslog_time() - t;
................................................................................
   463    450     sqlite3_uint64 t;
   464    451     VfslogFile *p = (VfslogFile *)pFile;
   465    452     t = vfslog_time();
   466    453     p->pReal->pMethods->xShmBarrier(p->pReal);
   467    454     t = vfslog_time() - t;
   468    455     vfslog_call(p->pVfslog, OS_SHMBARRIER, p->iFileId, t, SQLITE_OK, 0, 0);
   469    456   }
   470         -static int vfslogShmClose(sqlite3_file *pFile, int deleteFlag){
          457  +static int vfslogShmUnmap(sqlite3_file *pFile, int deleteFlag){
   471    458     int rc;
   472    459     sqlite3_uint64 t;
   473    460     VfslogFile *p = (VfslogFile *)pFile;
   474    461     t = vfslog_time();
   475         -  rc = p->pReal->pMethods->xShmClose(p->pReal, deleteFlag);
          462  +  rc = p->pReal->pMethods->xShmUnmap(p->pReal, deleteFlag);
   476    463     t = vfslog_time() - t;
   477         -  vfslog_call(p->pVfslog, OS_SHMCLOSE, p->iFileId, t, rc, 0, 0);
          464  +  vfslog_call(p->pVfslog, OS_SHMUNMAP, p->iFileId, t, rc, 0, 0);
   478    465     return rc;
   479    466   }
   480    467   
   481    468   
   482    469   /*
   483    470   ** Open an vfslog file handle.
   484    471   */
................................................................................
   790    777       case OS_DELETE:            zEvent = "xDelete"; break;
   791    778       case OS_ACCESS:            zEvent = "xAccess"; break;
   792    779       case OS_FULLPATHNAME:      zEvent = "xFullPathname"; break;
   793    780       case OS_RANDOMNESS:        zEvent = "xRandomness"; break;
   794    781       case OS_SLEEP:             zEvent = "xSleep"; break;
   795    782       case OS_CURRENTTIME:       zEvent = "xCurrentTime"; break;
   796    783   
   797         -    case OS_SHMCLOSE:          zEvent = "xShmClose"; break;
   798         -    case OS_SHMOPEN:           zEvent = "xShmOpen"; break;
          784  +    case OS_SHMUNMAP:          zEvent = "xShmUnmap"; break;
   799    785       case OS_SHMLOCK:           zEvent = "xShmLock"; break;
   800    786       case OS_SHMBARRIER:        zEvent = "xShmBarrier"; break;
   801    787       case OS_SHMMAP:            zEvent = "xShmMap"; break;
   802    788   
   803    789       case OS_ANNOTATE:          zEvent = "annotation"; break;
   804    790     }
   805    791   

Changes to src/test_vfs.c.

   183    183   static int tvfsSleep(sqlite3_vfs*, int microseconds);
   184    184   static int tvfsCurrentTime(sqlite3_vfs*, double*);
   185    185   
   186    186   static int tvfsShmOpen(sqlite3_file*);
   187    187   static int tvfsShmLock(sqlite3_file*, int , int, int);
   188    188   static int tvfsShmMap(sqlite3_file*,int,int,int, void volatile **);
   189    189   static void tvfsShmBarrier(sqlite3_file*);
   190         -static int tvfsShmClose(sqlite3_file*, int);
          190  +static int tvfsShmUnmap(sqlite3_file*, int);
   191    191   
   192    192   static sqlite3_io_methods tvfs_io_methods = {
   193    193     2,                              /* iVersion */
   194    194     tvfsClose,                      /* xClose */
   195    195     tvfsRead,                       /* xRead */
   196    196     tvfsWrite,                      /* xWrite */
   197    197     tvfsTruncate,                   /* xTruncate */
................................................................................
   199    199     tvfsFileSize,                   /* xFileSize */
   200    200     tvfsLock,                       /* xLock */
   201    201     tvfsUnlock,                     /* xUnlock */
   202    202     tvfsCheckReservedLock,          /* xCheckReservedLock */
   203    203     tvfsFileControl,                /* xFileControl */
   204    204     tvfsSectorSize,                 /* xSectorSize */
   205    205     tvfsDeviceCharacteristics,      /* xDeviceCharacteristics */
   206         -  tvfsShmOpen,                    /* xShmOpen */
          206  +  tvfsShmMap,                     /* xShmMap */
   207    207     tvfsShmLock,                    /* xShmLock */
   208         -  tvfsShmMap,                     /* xShmMap */
   209    208     tvfsShmBarrier,                 /* xShmBarrier */
   210         -  tvfsShmClose                    /* xShmClose */
          209  +  tvfsShmUnmap                    /* xShmUnmap */
   211    210   };
   212    211   
   213    212   static int tvfsResultCode(Testvfs *p, int *pRc){
   214    213     struct errcode {
   215    214       int eCode;
   216    215       const char *zCode;
   217    216     } aCode[] = {
................................................................................
   576    575     if( pFd->pReal->pMethods ){
   577    576       sqlite3_io_methods *pMethods;
   578    577       int nByte;
   579    578   
   580    579       if( pVfs->iVersion>1 ){
   581    580         nByte = sizeof(sqlite3_io_methods);
   582    581       }else{
   583         -      nByte = offsetof(sqlite3_io_methods, xShmOpen);
          582  +      nByte = offsetof(sqlite3_io_methods, xShmMap);
   584    583       }
   585    584   
   586    585       pMethods = (sqlite3_io_methods *)ckalloc(nByte);
   587    586       memcpy(pMethods, &tvfs_io_methods, nByte);
   588    587       pMethods->iVersion = pVfs->iVersion;
   589    588       if( pVfs->iVersion>1 && ((Testvfs *)pVfs->pAppData)->isNoshm ){
   590         -      pMethods->xShmOpen = 0;
   591         -      pMethods->xShmClose = 0;
          589  +      pMethods->xShmUnmap = 0;
   592    590         pMethods->xShmLock = 0;
   593    591         pMethods->xShmBarrier = 0;
   594    592         pMethods->xShmMap = 0;
   595    593       }
   596    594       pFile->pMethods = pMethods;
   597    595     }
   598    596   
................................................................................
   784    782     int pgsz,                       /* Size of pages */
   785    783     int isWrite,                    /* True to extend file if necessary */
   786    784     void volatile **pp              /* OUT: Mapped memory */
   787    785   ){
   788    786     int rc = SQLITE_OK;
   789    787     TestvfsFd *pFd = tvfsGetFd(pFile);
   790    788     Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
          789  +
          790  +  if( 0==pFd->pShm ){
          791  +    rc = tvfsShmOpen(pFile);
          792  +    if( rc!=SQLITE_OK ){
          793  +      return rc;
          794  +    }
          795  +  }
   791    796   
   792    797     if( p->pScript && p->mask&TESTVFS_SHMMAP_MASK ){
   793    798       Tcl_Obj *pArg = Tcl_NewObj();
   794    799       Tcl_IncrRefCount(pArg);
   795    800       Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(iPage));
   796    801       Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(pgsz));
   797    802       Tcl_ListObjAppendElement(p->interp, pArg, Tcl_NewIntObj(isWrite));
................................................................................
   884    889     if( p->pScript && p->mask&TESTVFS_SHMBARRIER_MASK ){
   885    890       tvfsExecTcl(p, "xShmBarrier", 
   886    891           Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
   887    892       );
   888    893     }
   889    894   }
   890    895   
   891         -static int tvfsShmClose(
          896  +static int tvfsShmUnmap(
   892    897     sqlite3_file *pFile,
   893    898     int deleteFlag
   894    899   ){
   895    900     int rc = SQLITE_OK;
   896    901     TestvfsFd *pFd = tvfsGetFd(pFile);
   897    902     Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);
   898    903     TestvfsBuffer *pBuffer = pFd->pShm;
   899    904     TestvfsFd **ppFd;
   900    905   
          906  +  if( !pBuffer ) return SQLITE_OK;
   901    907     assert( pFd->pShmId && pFd->pShm );
   902    908   
   903    909     if( p->pScript && p->mask&TESTVFS_SHMCLOSE_MASK ){
   904         -    tvfsExecTcl(p, "xShmClose", 
          910  +    tvfsExecTcl(p, "xShmUnmap", 
   905    911           Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
   906    912       );
   907    913       tvfsResultCode(p, &rc);
   908    914     }
   909    915   
   910    916     for(ppFd=&pBuffer->pFile; *ppFd!=pFd; ppFd=&((*ppFd)->pNext));
   911    917     assert( (*ppFd)==pFd );
................................................................................
  1019   1025         static struct VfsMethod {
  1020   1026           char *zName;
  1021   1027           int mask;
  1022   1028         } vfsmethod [] = {
  1023   1029           { "xShmOpen",    TESTVFS_SHMOPEN_MASK },
  1024   1030           { "xShmLock",    TESTVFS_SHMLOCK_MASK },
  1025   1031           { "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
  1026         -        { "xShmClose",   TESTVFS_SHMCLOSE_MASK },
         1032  +        { "xShmUnmap",   TESTVFS_SHMCLOSE_MASK },
  1027   1033           { "xShmMap",     TESTVFS_SHMMAP_MASK },
  1028   1034           { "xSync",       TESTVFS_SYNC_MASK },
  1029   1035           { "xDelete",     TESTVFS_DELETE_MASK },
  1030   1036           { "xWrite",      TESTVFS_WRITE_MASK },
  1031   1037           { "xTruncate",   TESTVFS_TRUNCATE_MASK },
  1032   1038           { "xOpen",       TESTVFS_OPEN_MASK },
  1033   1039           { "xClose",      TESTVFS_CLOSE_MASK },

Changes to src/wal.c.

   409    409     sqlite3_file *pWalFd;      /* File handle for WAL file */
   410    410     u32 iCallback;             /* Value to pass to log callback (or 0) */
   411    411     int nWiData;               /* Size of array apWiData */
   412    412     volatile u32 **apWiData;   /* Pointer to wal-index content in memory */
   413    413     u16 szPage;                /* Database page size */
   414    414     i16 readLock;              /* Which read lock is being held.  -1 for none */
   415    415     u8 exclusiveMode;          /* Non-zero if connection is in exclusive mode */
   416         -  u8 isWIndexOpen;           /* True if ShmOpen() called on pDbFd */
   417    416     u8 writeLock;              /* True if in a write transaction */
   418    417     u8 ckptLock;               /* True if holding a checkpoint lock */
   419    418     WalIndexHdr hdr;           /* Wal-index header for current transaction */
   420    419     const char *zWalName;      /* Name of WAL file */
   421    420     u32 nCkpt;                 /* Checkpoint sequence counter in the wal-header */
   422    421   #ifdef SQLITE_DEBUG
   423    422     u8 lockError;              /* True if a locking error has occurred */
................................................................................
  1164   1163     return rc;
  1165   1164   }
  1166   1165   
  1167   1166   /*
  1168   1167   ** Close an open wal-index.
  1169   1168   */
  1170   1169   static void walIndexClose(Wal *pWal, int isDelete){
  1171         -  if( pWal->isWIndexOpen ){
  1172         -    sqlite3OsShmClose(pWal->pDbFd, isDelete);
  1173         -    pWal->isWIndexOpen = 0;
  1174         -  }
         1170  +  sqlite3OsShmClose(pWal->pDbFd, isDelete);
  1175   1171   }
  1176   1172   
  1177   1173   /* 
  1178   1174   ** Open a connection to the WAL file zWalName. The database file must 
  1179   1175   ** already be opened on connection pDbFd. The buffer that zWalName points
  1180   1176   ** to must remain valid for the lifetime of the returned Wal* handle.
  1181   1177   **
................................................................................
  1222   1218     }
  1223   1219   
  1224   1220     pRet->pVfs = pVfs;
  1225   1221     pRet->pWalFd = (sqlite3_file *)&pRet[1];
  1226   1222     pRet->pDbFd = pDbFd;
  1227   1223     pRet->readLock = -1;
  1228   1224     pRet->zWalName = zWalName;
  1229         -  rc = sqlite3OsShmOpen(pDbFd);
  1230   1225   
  1231   1226     /* Open file handle on the write-ahead log file. */
  1232         -  if( rc==SQLITE_OK ){
  1233         -    pRet->isWIndexOpen = 1;
  1234         -    flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_JOURNAL);
  1235         -    rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags);
  1236         -  }
         1227  +  flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_JOURNAL);
         1228  +  rc = sqlite3OsOpen(pVfs, zWalName, pRet->pWalFd, flags, &flags);
  1237   1229   
  1238   1230     if( rc!=SQLITE_OK ){
  1239   1231       walIndexClose(pRet, 0);
  1240   1232       sqlite3OsClose(pRet->pWalFd);
  1241   1233       sqlite3_free(pRet);
  1242   1234     }else{
  1243   1235       *ppWal = pRet;
................................................................................
  2200   2192   }
  2201   2193   
  2202   2194   /*
  2203   2195   ** End a write transaction.  The commit has already been done.  This
  2204   2196   ** routine merely releases the lock.
  2205   2197   */
  2206   2198   int sqlite3WalEndWriteTransaction(Wal *pWal){
  2207         -  walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
  2208         -  pWal->writeLock = 0;
         2199  +  if( pWal->writeLock ){
         2200  +    walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
         2201  +    pWal->writeLock = 0;
         2202  +  }
  2209   2203     return SQLITE_OK;
  2210   2204   }
  2211   2205   
  2212   2206   /*
  2213   2207   ** If any data has been written (but not committed) to the log file, this
  2214   2208   ** function moves the write-pointer back to the start of the transaction.
  2215   2209   **