/ Check-in [43b5b07f]
Login

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

Overview
Comment:Change the VFS definition so that all methods take a VFS object pointer as their first parameter.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 43b5b07f0d996d7ef7426346b1792e9ca898f487
User & Date: drh 2010-05-03 16:30:27
Context
2010-05-03
16:36
Update the crash-test VFS in test6.c to pass-through the shared-memory methods to the real underlying VFS. This fixes the walcrash.test script. check-in: ea09ff37 user: drh tags: trunk
16:30
Change the VFS definition so that all methods take a VFS object pointer as their first parameter. check-in: 43b5b07f user: drh tags: trunk
15:58
Have sqlite3_wal_checkpoint() handle a zero-length string in the same way as a NULL pointer. Fix "PRAGMA wal_checkpoint" so that it checkpoints all attached databases. check-in: 7fecd21f user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

5068
5069
5070
5071
5072
5073
5074
5075




5076
5077
5078
5079

5080
5081
5082
5083
5084
5085
5086
....
5119
5120
5121
5122
5123
5124
5125

5126
5127
5128
5129
5130
5131
5132
5133


5134
5135
5136
5137
5138
5139
5140
....
5170
5171
5172
5173
5174
5175
5176

5177
5178
5179
5180
5181
5182
5183
....
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
....
5215
5216
5217
5218
5219
5220
5221
5222
5223

5224
5225
5226
5227
5228
5229
5230
....
5246
5247
5248
5249
5250
5251
5252

5253
5254
5255
5256
5257
5258
5259


5260
5261
5262
5263
5264
5265
5266
  return rc;
}

/*
** Close a connection to shared-memory.  Delete the underlying 
** storage if deleteFlag is true.
*/
static int unixShmClose(sqlite3_shm *pSharedMem, int deleteFlag){




  unixShm *p;            /* The connection to be closed */
  unixShmFile *pFile;    /* The underlying shared-memory file */
  unixShm **pp;          /* For looping over sibling connections */


  if( pSharedMem==0 ) return SQLITE_OK;
  p = (struct unixShm*)pSharedMem;
  pFile = p->pFile;

  /* Verify that the connection being closed holds no locks */
  assert( p->exclMask==0 );
  assert( p->sharedMask==0 );
................................................................................
** of the underlying storage into memory.  Use xShmGet() to change
** the mapping size.
**
** The reqSize parameter is the minimum size requested.  The implementation
** is free to expand the storage to some larger amount if it chooses.
*/
static int unixShmSize(

  sqlite3_shm *pSharedMem,  /* Pointer returned by unixShmOpen() */
  int reqSize,              /* Requested size.  -1 for query only */
  int *pNewSize             /* Write new size here */
){
  unixShm *p = (unixShm*)pSharedMem;
  unixShmFile *pFile = p->pFile;
  int rc = SQLITE_OK;
  struct stat sStat;



  if( reqSize>=0 ){
    reqSize = (reqSize + SQLITE_UNIX_SHM_INCR - 1)/SQLITE_UNIX_SHM_INCR;
    reqSize *= SQLITE_UNIX_SHM_INCR;
    rc = ftruncate(pFile->h, reqSize);
  }
  if( fstat(pFile->h, &sStat)==0 ){
................................................................................
**
** *pNewMapSize is set to the size of the mapping.
**
** *ppBuf and *pNewMapSize might be NULL and zero if no space has
** yet been allocated to the underlying storage.
*/
static int unixShmGet(

  sqlite3_shm *pSharedMem, /* Pointer returned by unixShmOpen() */
  int reqMapSize,          /* Requested size of mapping. -1 means don't care */
  int *pNewMapSize,        /* Write new size of mapping here */
  void **ppBuf             /* Write mapping buffer origin here */
){
  unixShm *p = (unixShm*)pSharedMem;
  unixShmFile *pFile = p->pFile;
................................................................................
    assert( sqlite3_mutex_notheld(pFile->mutex) );
    sqlite3_mutex_enter(pFile->mutexBuf);
    p->hasMutexBuf = 1;
  }
  sqlite3_mutex_enter(pFile->mutex);
  if( pFile->szMap==0 || reqMapSize>pFile->szMap ){
    int actualSize;
    if( unixShmSize(pSharedMem, -1, &actualSize)==SQLITE_OK
     && reqMapSize<actualSize
    ){
      reqMapSize = actualSize;
    }
    if( pFile->pMMapBuf ){
      munmap(pFile->pMMapBuf, pFile->szMap);
    }
................................................................................
**
** If the lock is not currently held, this routine is a harmless no-op.
**
** If the shared-memory object is in lock state RECOVER, then we do not
** really want to release the lock, so in that case too, this routine
** is a no-op.
*/
static int unixShmRelease(sqlite3_shm *pSharedMem){
  unixShm *p = (unixShm*)pSharedMem;

  if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
    unixShmFile *pFile = p->pFile;
    assert( sqlite3_mutex_notheld(pFile->mutex) );
    sqlite3_mutex_leave(pFile->mutexBuf);
    p->hasMutexBuf = 0;
  }
  return SQLITE_OK;
................................................................................
#endif


/*
** Change the lock state for a shared-memory segment.
*/
static int unixShmLock(

  sqlite3_shm *pSharedMem,   /* Pointer from unixShmOpen() */
  int desiredLock,           /* One of SQLITE_SHM_xxxxx locking states */
  int *pGotLock              /* The lock you actually got */
){
  unixShm *p = (unixShm*)pSharedMem;
  unixShmFile *pFile = p->pFile;
  int rc = SQLITE_PROTOCOL;



  /* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never
  ** directly requested; they are side effects from requesting
  ** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively.
  */
  assert( desiredLock==SQLITE_SHM_QUERY
       || desiredLock==SQLITE_SHM_UNLOCK







|
>
>
>
>




>







 







>








>
>







 







>







 







|







 







|

>







 







>







>
>







5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
....
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
....
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
....
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
....
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
....
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
  return rc;
}

/*
** Close a connection to shared-memory.  Delete the underlying 
** storage if deleteFlag is true.
*/
static int unixShmClose(
  sqlite3_vfs *pVfs,         /* The VFS */
  sqlite3_shm *pSharedMem,   /* The shared-memory to be closed */
  int deleteFlag             /* Delete after closing if true */
){
  unixShm *p;            /* The connection to be closed */
  unixShmFile *pFile;    /* The underlying shared-memory file */
  unixShm **pp;          /* For looping over sibling connections */

  UNUSED_PARAMETER(pVfs);
  if( pSharedMem==0 ) return SQLITE_OK;
  p = (struct unixShm*)pSharedMem;
  pFile = p->pFile;

  /* Verify that the connection being closed holds no locks */
  assert( p->exclMask==0 );
  assert( p->sharedMask==0 );
................................................................................
** of the underlying storage into memory.  Use xShmGet() to change
** the mapping size.
**
** The reqSize parameter is the minimum size requested.  The implementation
** is free to expand the storage to some larger amount if it chooses.
*/
static int unixShmSize(
  sqlite3_vfs *pVfs,        /* The VFS */
  sqlite3_shm *pSharedMem,  /* Pointer returned by unixShmOpen() */
  int reqSize,              /* Requested size.  -1 for query only */
  int *pNewSize             /* Write new size here */
){
  unixShm *p = (unixShm*)pSharedMem;
  unixShmFile *pFile = p->pFile;
  int rc = SQLITE_OK;
  struct stat sStat;

  UNUSED_PARAMETER(pVfs);

  if( reqSize>=0 ){
    reqSize = (reqSize + SQLITE_UNIX_SHM_INCR - 1)/SQLITE_UNIX_SHM_INCR;
    reqSize *= SQLITE_UNIX_SHM_INCR;
    rc = ftruncate(pFile->h, reqSize);
  }
  if( fstat(pFile->h, &sStat)==0 ){
................................................................................
**
** *pNewMapSize is set to the size of the mapping.
**
** *ppBuf and *pNewMapSize might be NULL and zero if no space has
** yet been allocated to the underlying storage.
*/
static int unixShmGet(
  sqlite3_vfs *pVfs,       /* The VFS */
  sqlite3_shm *pSharedMem, /* Pointer returned by unixShmOpen() */
  int reqMapSize,          /* Requested size of mapping. -1 means don't care */
  int *pNewMapSize,        /* Write new size of mapping here */
  void **ppBuf             /* Write mapping buffer origin here */
){
  unixShm *p = (unixShm*)pSharedMem;
  unixShmFile *pFile = p->pFile;
................................................................................
    assert( sqlite3_mutex_notheld(pFile->mutex) );
    sqlite3_mutex_enter(pFile->mutexBuf);
    p->hasMutexBuf = 1;
  }
  sqlite3_mutex_enter(pFile->mutex);
  if( pFile->szMap==0 || reqMapSize>pFile->szMap ){
    int actualSize;
    if( unixShmSize(pVfs, pSharedMem, -1, &actualSize)==SQLITE_OK
     && reqMapSize<actualSize
    ){
      reqMapSize = actualSize;
    }
    if( pFile->pMMapBuf ){
      munmap(pFile->pMMapBuf, pFile->szMap);
    }
................................................................................
**
** If the lock is not currently held, this routine is a harmless no-op.
**
** If the shared-memory object is in lock state RECOVER, then we do not
** really want to release the lock, so in that case too, this routine
** is a no-op.
*/
static int unixShmRelease(sqlite3_vfs *pVfs, sqlite3_shm *pSharedMem){
  unixShm *p = (unixShm*)pSharedMem;
  UNUSED_PARAMETER(pVfs);
  if( p->hasMutexBuf && p->lockState!=SQLITE_SHM_RECOVER ){
    unixShmFile *pFile = p->pFile;
    assert( sqlite3_mutex_notheld(pFile->mutex) );
    sqlite3_mutex_leave(pFile->mutexBuf);
    p->hasMutexBuf = 0;
  }
  return SQLITE_OK;
................................................................................
#endif


/*
** Change the lock state for a shared-memory segment.
*/
static int unixShmLock(
  sqlite3_vfs *pVfs,         /* The VFS */
  sqlite3_shm *pSharedMem,   /* Pointer from unixShmOpen() */
  int desiredLock,           /* One of SQLITE_SHM_xxxxx locking states */
  int *pGotLock              /* The lock you actually got */
){
  unixShm *p = (unixShm*)pSharedMem;
  unixShmFile *pFile = p->pFile;
  int rc = SQLITE_PROTOCOL;

  UNUSED_PARAMETER(pVfs);

  /* Note that SQLITE_SHM_READ_FULL and SQLITE_SHM_PENDING are never
  ** directly requested; they are side effects from requesting
  ** SQLITE_SHM_READ and SQLITE_SHM_CHECKPOINT, respectively.
  */
  assert( desiredLock==SQLITE_SHM_QUERY
       || desiredLock==SQLITE_SHM_UNLOCK

Changes to src/sqlite.h.in.

840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
  int (*xCurrentTime)(sqlite3_vfs*, double*);
  int (*xGetLastError)(sqlite3_vfs*, int, char *);
  /*
  ** The methods above are in version 1 of the sqlite_vfs object
  ** definition.  Those that follow are added in version 2 or later
  */
  int (*xShmOpen)(sqlite3_vfs*, const char *zName, sqlite3_shm**);
  int (*xShmSize)(sqlite3_shm*, int reqSize, int *pNewSize);
  int (*xShmGet)(sqlite3_shm*, int reqMapSize, int *pMapSize, void**);
  int (*xShmRelease)(sqlite3_shm*);
  int (*xShmLock)(sqlite3_shm*, int desiredLock, int *gotLock);
  int (*xShmClose)(sqlite3_shm*, int deleteFlag);
  int (*xRename)(sqlite3_vfs*, const char *zOld, const char *zNew, int dirSync);
  int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
  /*
  ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
  ** New fields may be appended in figure versions.  The iVersion
  ** value will increment whenever this happens. 
  */







|
|
|
|
|







840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
  int (*xCurrentTime)(sqlite3_vfs*, double*);
  int (*xGetLastError)(sqlite3_vfs*, int, char *);
  /*
  ** The methods above are in version 1 of the sqlite_vfs object
  ** definition.  Those that follow are added in version 2 or later
  */
  int (*xShmOpen)(sqlite3_vfs*, const char *zName, sqlite3_shm**);
  int (*xShmSize)(sqlite3_vfs*, sqlite3_shm*, int reqSize, int *pNewSize);
  int (*xShmGet)(sqlite3_vfs*, sqlite3_shm*, int reqSize, int *pSize, void**);
  int (*xShmRelease)(sqlite3_vfs*, sqlite3_shm*);
  int (*xShmLock)(sqlite3_vfs*, sqlite3_shm*, int desiredLock, int *gotLock);
  int (*xShmClose)(sqlite3_vfs*, sqlite3_shm*, int deleteFlag);
  int (*xRename)(sqlite3_vfs*, const char *zOld, const char *zNew, int dirSync);
  int (*xCurrentTimeInt64)(sqlite3_vfs*, sqlite3_int64*);
  /*
  ** The methods above are in versions 1 and 2 of the sqlite_vfs object.
  ** New fields may be appended in figure versions.  The iVersion
  ** value will increment whenever this happens. 
  */

Changes to src/test_devsym.c.

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
...
353
354
355
356
357
358
359
360





361
362
363

364
365
366
367
368
369
370
371
372
373
374





375
376
377
378
379
380
381
382
383
384
385
static void devsymDlClose(sqlite3_vfs*, void*);
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
static int devsymRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int devsymSleep(sqlite3_vfs*, int microseconds);
static int devsymCurrentTime(sqlite3_vfs*, double*);

static int devsymShmOpen(sqlite3_vfs *, const char *, sqlite3_shm **);
static int devsymShmSize(sqlite3_shm *, int , int *);
static int devsymShmGet(sqlite3_shm *, int , int *, void **);
static int devsymShmRelease(sqlite3_shm *);
static int devsymShmLock(sqlite3_shm *, int , int *);
static int devsymShmClose(sqlite3_shm *, int);

static sqlite3_vfs devsym_vfs = {
  2,                     /* iVersion */
  sizeof(devsym_file),      /* szOsFile */
  DEVSYM_MAX_PATHNAME,      /* mxPathname */
  0,                     /* pNext */
  DEVSYM_VFS_NAME,          /* zName */
................................................................................
static int devsymShmOpen(
  sqlite3_vfs *pVfs, 
  const char *zName, 
  sqlite3_shm **pp
){
  return g.pVfs->xShmOpen(g.pVfs, zName, pp);
}
static int devsymShmSize(sqlite3_shm *p, int reqSize, int *pNewSize){





  return g.pVfs->xShmSize(p, reqSize, pNewSize);
}
static int devsymShmGet(

  sqlite3_shm *p, 
  int reqMapSize, 
  int *pMapSize, 
  void **pp
){
  return g.pVfs->xShmGet(p, reqMapSize, pMapSize, pp);
}
static int devsymShmRelease(sqlite3_shm *p){
  return g.pVfs->xShmRelease(p);
}
static int devsymShmLock(sqlite3_shm *p, int desiredLock, int *gotLock){





  return g.pVfs->xShmLock(p, desiredLock, gotLock);
}
static int devsymShmClose(sqlite3_shm *p, int deleteFlag){
  return g.pVfs->xShmClose(p, deleteFlag);
}

/*
** This procedure registers the devsym vfs with SQLite. If the argument is
** true, the devsym vfs becomes the new default vfs. It is the only publicly
** available function in this file.
*/







|
|
|
|
|







 







|
>
>
>
>
>
|


>





|

|
|

|
>
>
>
>
>
|

|
|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
...
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
static void devsymDlClose(sqlite3_vfs*, void*);
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
static int devsymRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int devsymSleep(sqlite3_vfs*, int microseconds);
static int devsymCurrentTime(sqlite3_vfs*, double*);

static int devsymShmOpen(sqlite3_vfs *, const char *, sqlite3_shm **);
static int devsymShmSize(sqlite3_vfs*, sqlite3_shm *, int , int *);
static int devsymShmGet(sqlite3_vfs*, sqlite3_shm *, int , int *, void **);
static int devsymShmRelease(sqlite3_vfs*, sqlite3_shm *);
static int devsymShmLock(sqlite3_vfs*, sqlite3_shm *, int , int *);
static int devsymShmClose(sqlite3_vfs*, sqlite3_shm *, int);

static sqlite3_vfs devsym_vfs = {
  2,                     /* iVersion */
  sizeof(devsym_file),      /* szOsFile */
  DEVSYM_MAX_PATHNAME,      /* mxPathname */
  0,                     /* pNext */
  DEVSYM_VFS_NAME,          /* zName */
................................................................................
static int devsymShmOpen(
  sqlite3_vfs *pVfs, 
  const char *zName, 
  sqlite3_shm **pp
){
  return g.pVfs->xShmOpen(g.pVfs, zName, pp);
}
static int devsymShmSize(
  sqlite3_vfs *pVfs,
  sqlite3_shm *p,
  int reqSize,
  int *pNewSize
){
  return g.pVfs->xShmSize(g.pVfs, p, reqSize, pNewSize);
}
static int devsymShmGet(
  sqlite3_vfs *pVfs,
  sqlite3_shm *p, 
  int reqMapSize, 
  int *pMapSize, 
  void **pp
){
  return g.pVfs->xShmGet(g.pVfs, p, reqMapSize, pMapSize, pp);
}
static int devsymShmRelease(sqlite3_vfs *pVfs, sqlite3_shm *p){
  return g.pVfs->xShmRelease(g.pVfs, p);
}
static int devsymShmLock(
  sqlite3_vfs *pVfs,
  sqlite3_shm *p,
  int desiredLock,
  int *gotLock
){
  return g.pVfs->xShmLock(g.pVfs, p, desiredLock, gotLock);
}
static int devsymShmClose(sqlite3_vfs *pVfs, sqlite3_shm *p, int deleteFlag){
  return g.pVfs->xShmClose(g.pVfs, p, deleteFlag);
}

/*
** This procedure registers the devsym vfs with SQLite. If the argument is
** true, the devsym vfs becomes the new default vfs. It is the only publicly
** available function in this file.
*/

Changes to src/wal.c.

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
...
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
...
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
...
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
...
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
...
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
** When changing the lock status to SQLITE_SHM_READ, store the
** type of reader lock (either SQLITE_SHM_READ or SQLITE_SHM_READ_FULL)
** in pWal->readerType.
*/
static int walSetLock(Wal *pWal, int desiredStatus){
  int rc, got;
  if( pWal->lockState==desiredStatus ) return SQLITE_OK;
  rc = pWal->pVfs->xShmLock(pWal->pWIndex, desiredStatus, &got);
  pWal->lockState = got;
  if( got==SQLITE_SHM_READ_FULL || got==SQLITE_SHM_READ ){
    pWal->readerType = got;
    pWal->lockState = SQLITE_SHM_READ;
  }
  return rc;
}
................................................................................

/*
** Release our reference to the wal-index memory map, if we are holding
** it.
*/
static void walIndexUnmap(Wal *pWal){
  if( pWal->pWiData ){
    pWal->pVfs->xShmRelease(pWal->pWIndex);
    pWal->pWiData = 0;
  }
}

/*
** Map the wal-index file into memory if it isn't already. 
**
................................................................................
** The reqSize parameter is the minimum required size of the mapping.
** A value of -1 means "don't care".  The reqSize parameter is ignored
** if the mapping is already held.
*/
static int walIndexMap(Wal *pWal, int reqSize){
  int rc = SQLITE_OK;
  if( pWal->pWiData==0 ){
    rc = pWal->pVfs->xShmGet(pWal->pWIndex, reqSize, &pWal->szWIndex,
                             (void**)(char*)&pWal->pWiData);
    if( rc==SQLITE_OK && pWal->pWiData==0 ){
      /* Make sure pWal->pWiData is not NULL while we are holding the
      ** lock on the mapping. */
      assert( pWal->szWIndex==0 );
      pWal->pWiData = &pWal->iCallback;
    }
  }
................................................................................
**
** If enlargeTo is non-negative, then increase the size of the underlying
** storage to be at least as big as enlargeTo before remapping.
*/
static int walIndexRemap(Wal *pWal, int enlargeTo){
  int rc;
  int sz;
  rc = pWal->pVfs->xShmSize(pWal->pWIndex, enlargeTo, &sz);
  if( rc==SQLITE_OK && sz>pWal->szWIndex ){
    walIndexUnmap(pWal);
    rc = walIndexMap(pWal, sz);
  }
  return rc;
}

................................................................................
  /* Open file handle on the write-ahead log file. */
  flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_JOURNAL);
  rc = sqlite3OsOpen(pVfs, zWal, pRet->pFd, flags, &flags);

wal_open_out:
  if( rc!=SQLITE_OK ){
    if( pRet ){
      pVfs->xShmClose(pRet->pWIndex, 0);
      sqlite3OsClose(pRet->pFd);
      sqlite3_free(pRet);
    }
  }
  *ppWal = pRet;
  return rc;
}
................................................................................
      rc = walCheckpoint(pWal, pFd, sync_flags, zBuf);
      if( rc==SQLITE_OK ){
        isDelete = 1;
      }
      walIndexUnmap(pWal);
    }

    pWal->pVfs->xShmClose(pWal->pWIndex, isDelete);
    sqlite3OsClose(pWal->pFd);
    if( isDelete ){
      sqlite3OsDelete(pWal->pVfs, pWal->zName, 0);
    }
    sqlite3_free(pWal);
  }
  return rc;







|







 







|







 







|
|







 







|







 







|







 







|







215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
...
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
...
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
...
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
...
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
...
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
** When changing the lock status to SQLITE_SHM_READ, store the
** type of reader lock (either SQLITE_SHM_READ or SQLITE_SHM_READ_FULL)
** in pWal->readerType.
*/
static int walSetLock(Wal *pWal, int desiredStatus){
  int rc, got;
  if( pWal->lockState==desiredStatus ) return SQLITE_OK;
  rc = pWal->pVfs->xShmLock(pWal->pVfs, pWal->pWIndex, desiredStatus, &got);
  pWal->lockState = got;
  if( got==SQLITE_SHM_READ_FULL || got==SQLITE_SHM_READ ){
    pWal->readerType = got;
    pWal->lockState = SQLITE_SHM_READ;
  }
  return rc;
}
................................................................................

/*
** Release our reference to the wal-index memory map, if we are holding
** it.
*/
static void walIndexUnmap(Wal *pWal){
  if( pWal->pWiData ){
    pWal->pVfs->xShmRelease(pWal->pVfs, pWal->pWIndex);
    pWal->pWiData = 0;
  }
}

/*
** Map the wal-index file into memory if it isn't already. 
**
................................................................................
** The reqSize parameter is the minimum required size of the mapping.
** A value of -1 means "don't care".  The reqSize parameter is ignored
** if the mapping is already held.
*/
static int walIndexMap(Wal *pWal, int reqSize){
  int rc = SQLITE_OK;
  if( pWal->pWiData==0 ){
    rc = pWal->pVfs->xShmGet(pWal->pVfs, pWal->pWIndex, reqSize,
                             &pWal->szWIndex, (void**)(char*)&pWal->pWiData);
    if( rc==SQLITE_OK && pWal->pWiData==0 ){
      /* Make sure pWal->pWiData is not NULL while we are holding the
      ** lock on the mapping. */
      assert( pWal->szWIndex==0 );
      pWal->pWiData = &pWal->iCallback;
    }
  }
................................................................................
**
** If enlargeTo is non-negative, then increase the size of the underlying
** storage to be at least as big as enlargeTo before remapping.
*/
static int walIndexRemap(Wal *pWal, int enlargeTo){
  int rc;
  int sz;
  rc = pWal->pVfs->xShmSize(pWal->pVfs, pWal->pWIndex, enlargeTo, &sz);
  if( rc==SQLITE_OK && sz>pWal->szWIndex ){
    walIndexUnmap(pWal);
    rc = walIndexMap(pWal, sz);
  }
  return rc;
}

................................................................................
  /* Open file handle on the write-ahead log file. */
  flags = (SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MAIN_JOURNAL);
  rc = sqlite3OsOpen(pVfs, zWal, pRet->pFd, flags, &flags);

wal_open_out:
  if( rc!=SQLITE_OK ){
    if( pRet ){
      pVfs->xShmClose(pVfs, pRet->pWIndex, 0);
      sqlite3OsClose(pRet->pFd);
      sqlite3_free(pRet);
    }
  }
  *ppWal = pRet;
  return rc;
}
................................................................................
      rc = walCheckpoint(pWal, pFd, sync_flags, zBuf);
      if( rc==SQLITE_OK ){
        isDelete = 1;
      }
      walIndexUnmap(pWal);
    }

    pWal->pVfs->xShmClose(pWal->pVfs, pWal->pWIndex, isDelete);
    sqlite3OsClose(pWal->pFd);
    if( isDelete ){
      sqlite3OsDelete(pWal->pVfs, pWal->zName, 0);
    }
    sqlite3_free(pWal);
  }
  return rc;