SQLite

Check-in [0a6787908e]
Login

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

Overview
Comment:Mark the shared-memory in the WAL implementation as volatile.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0a6787908e989bd5e6af25acbdc59ebc8fa61d6d
User & Date: drh 2010-05-18 13:27:13.000
Context
2010-05-18
18:01
Refactoring of the WalIterator implementation. (check-in: b5b60fdcc5 user: drh tags: trunk)
13:27
Mark the shared-memory in the WAL implementation as volatile. (check-in: 0a6787908e user: drh tags: trunk)
12:56
Comment clarifications in wal.c. (check-in: a029be1017 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/os.c.
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
}
int sqlite3OsShmOpen(sqlite3_file *id){
  return id->pMethods->xShmOpen(id);
}
int sqlite3OsShmSize(sqlite3_file *id, int reqSize, int *pNewSize){
  return id->pMethods->xShmSize(id, reqSize, pNewSize);
}
int sqlite3OsShmGet(sqlite3_file *id, int reqSize, int *pSize, void **pp){
  return id->pMethods->xShmGet(id, reqSize, pSize, pp);
}
int sqlite3OsShmRelease(sqlite3_file *id){
  return id->pMethods->xShmRelease(id);
}
int sqlite3OsShmLock(sqlite3_file *id, int desiredLock, int *pGotLock){
  return id->pMethods->xShmLock(id, desiredLock, pGotLock);







|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
}
int sqlite3OsShmOpen(sqlite3_file *id){
  return id->pMethods->xShmOpen(id);
}
int sqlite3OsShmSize(sqlite3_file *id, int reqSize, int *pNewSize){
  return id->pMethods->xShmSize(id, reqSize, pNewSize);
}
int sqlite3OsShmGet(sqlite3_file *id,int reqSize,int *pSize,void volatile **pp){
  return id->pMethods->xShmGet(id, reqSize, pSize, pp);
}
int sqlite3OsShmRelease(sqlite3_file *id){
  return id->pMethods->xShmRelease(id);
}
int sqlite3OsShmLock(sqlite3_file *id, int desiredLock, int *pGotLock){
  return id->pMethods->xShmLock(id, desiredLock, pGotLock);
Changes to src/os.h.
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
int sqlite3OsFileControl(sqlite3_file*,int,void*);
#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
int sqlite3OsSectorSize(sqlite3_file *id);
int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
int sqlite3OsShmOpen(sqlite3_file *id);
int sqlite3OsShmSize(sqlite3_file *id, int, int*);
int sqlite3OsShmGet(sqlite3_file *id, int, int*, void**);
int sqlite3OsShmRelease(sqlite3_file *id);
int sqlite3OsShmLock(sqlite3_file *id, int, int*);
int sqlite3OsShmClose(sqlite3_file *id, int);

/* 
** Functions for accessing sqlite3_vfs methods 
*/







|







241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
int sqlite3OsCheckReservedLock(sqlite3_file *id, int *pResOut);
int sqlite3OsFileControl(sqlite3_file*,int,void*);
#define SQLITE_FCNTL_DB_UNCHANGED 0xca093fa0
int sqlite3OsSectorSize(sqlite3_file *id);
int sqlite3OsDeviceCharacteristics(sqlite3_file *id);
int sqlite3OsShmOpen(sqlite3_file *id);
int sqlite3OsShmSize(sqlite3_file *id, int, int*);
int sqlite3OsShmGet(sqlite3_file *id, int, int*, void volatile**);
int sqlite3OsShmRelease(sqlite3_file *id);
int sqlite3OsShmLock(sqlite3_file *id, int, int*);
int sqlite3OsShmClose(sqlite3_file *id, int);

/* 
** Functions for accessing sqlite3_vfs methods 
*/
Changes to src/os_unix.c.
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
** *ppBuf and *pNewMapSize might be NULL and zero if no space has
** yet been allocated to the underlying storage.
*/
static int unixShmGet(
  sqlite3_file *fd,        /* Database file holding shared memory */
  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 */
){
  unixFile *pDbFd = (unixFile*)fd;
  unixShm *p = pDbFd->pShm;
  unixShmNode *pShmNode = p->pShmNode;
  int rc = SQLITE_OK;

  assert( pShmNode==pDbFd->pInode->pShmNode );







|







3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
** *ppBuf and *pNewMapSize might be NULL and zero if no space has
** yet been allocated to the underlying storage.
*/
static int unixShmGet(
  sqlite3_file *fd,        /* Database file holding shared memory */
  int reqMapSize,          /* Requested size of mapping. -1 means don't care */
  int *pNewMapSize,        /* Write new size of mapping here */
  void volatile **ppBuf    /* Write mapping buffer origin here */
){
  unixFile *pDbFd = (unixFile*)fd;
  unixShm *p = pDbFd->pShm;
  unixShmNode *pShmNode = p->pShmNode;
  int rc = SQLITE_OK;

  assert( pShmNode==pDbFd->pInode->pShmNode );
Changes to src/sqlite.h.in.
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
  int (*xCheckReservedLock)(sqlite3_file*, int *pResOut);
  int (*xFileControl)(sqlite3_file*, int op, void *pArg);
  int (*xSectorSize)(sqlite3_file*);
  int (*xDeviceCharacteristics)(sqlite3_file*);
  /* Methods above are valid for version 1 */
  int (*xShmOpen)(sqlite3_file*);
  int (*xShmSize)(sqlite3_file*, int reqSize, int *pNewSize);
  int (*xShmGet)(sqlite3_file*, int reqSize, int *pSize, void**);
  int (*xShmRelease)(sqlite3_file*);
  int (*xShmLock)(sqlite3_file*, int desiredLock, int *gotLock);
  int (*xShmClose)(sqlite3_file*, int deleteFlag);
  /* Methods above are valid for version 2 */
  /* Additional methods may be added in future releases */
};








|







652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
  int (*xCheckReservedLock)(sqlite3_file*, int *pResOut);
  int (*xFileControl)(sqlite3_file*, int op, void *pArg);
  int (*xSectorSize)(sqlite3_file*);
  int (*xDeviceCharacteristics)(sqlite3_file*);
  /* Methods above are valid for version 1 */
  int (*xShmOpen)(sqlite3_file*);
  int (*xShmSize)(sqlite3_file*, int reqSize, int *pNewSize);
  int (*xShmGet)(sqlite3_file*, int reqSize, int *pSize, void volatile**);
  int (*xShmRelease)(sqlite3_file*);
  int (*xShmLock)(sqlite3_file*, int desiredLock, int *gotLock);
  int (*xShmClose)(sqlite3_file*, int deleteFlag);
  /* Methods above are valid for version 2 */
  /* Additional methods may be added in future releases */
};

Changes to src/test6.c.
525
526
527
528
529
530
531
532





533
534
535
536
537
538
539
*/
static int cfShmOpen(sqlite3_file *pFile){
  return sqlite3OsShmOpen(((CrashFile*)pFile)->pRealFile);
}
static int cfShmSize(sqlite3_file *pFile, int reqSize, int *pNew){
  return sqlite3OsShmSize(((CrashFile*)pFile)->pRealFile, reqSize, pNew);
}
static int cfShmGet(sqlite3_file *pFile, int reqSize, int *pSize, void **pp){





  return sqlite3OsShmGet(((CrashFile*)pFile)->pRealFile, reqSize, pSize, pp);
}
static int cfShmRelease(sqlite3_file *pFile){
  return sqlite3OsShmRelease(((CrashFile*)pFile)->pRealFile);
}
static int cfShmLock(sqlite3_file *pFile, int desired, int *pGot){
  return sqlite3OsShmLock(((CrashFile*)pFile)->pRealFile, desired, pGot);







|
>
>
>
>
>







525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
*/
static int cfShmOpen(sqlite3_file *pFile){
  return sqlite3OsShmOpen(((CrashFile*)pFile)->pRealFile);
}
static int cfShmSize(sqlite3_file *pFile, int reqSize, int *pNew){
  return sqlite3OsShmSize(((CrashFile*)pFile)->pRealFile, reqSize, pNew);
}
static int cfShmGet(
  sqlite3_file *pFile,
  int reqSize,
  int *pSize,
  void volatile **pp
){
  return sqlite3OsShmGet(((CrashFile*)pFile)->pRealFile, reqSize, pSize, pp);
}
static int cfShmRelease(sqlite3_file *pFile){
  return sqlite3OsShmRelease(((CrashFile*)pFile)->pRealFile);
}
static int cfShmLock(sqlite3_file *pFile, int desired, int *pGot){
  return sqlite3OsShmLock(((CrashFile*)pFile)->pRealFile, desired, pGot);
Changes to src/test_devsym.c.
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
static int devsymUnlock(sqlite3_file*, int);
static int devsymCheckReservedLock(sqlite3_file*, int *);
static int devsymFileControl(sqlite3_file*, int op, void *pArg);
static int devsymSectorSize(sqlite3_file*);
static int devsymDeviceCharacteristics(sqlite3_file*);
static int devsymShmOpen(sqlite3_file*);
static int devsymShmSize(sqlite3_file*,int,int*);
static int devsymShmGet(sqlite3_file*,int,int*,void**);
static int devsymShmRelease(sqlite3_file*);
static int devsymShmLock(sqlite3_file*,int,int*);
static int devsymShmClose(sqlite3_file*,int);

/*
** Method declarations for devsym_vfs.
*/







|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
static int devsymUnlock(sqlite3_file*, int);
static int devsymCheckReservedLock(sqlite3_file*, int *);
static int devsymFileControl(sqlite3_file*, int op, void *pArg);
static int devsymSectorSize(sqlite3_file*);
static int devsymDeviceCharacteristics(sqlite3_file*);
static int devsymShmOpen(sqlite3_file*);
static int devsymShmSize(sqlite3_file*,int,int*);
static int devsymShmGet(sqlite3_file*,int,int*,volatile void**);
static int devsymShmRelease(sqlite3_file*);
static int devsymShmLock(sqlite3_file*,int,int*);
static int devsymShmClose(sqlite3_file*,int);

/*
** Method declarations for devsym_vfs.
*/
244
245
246
247
248
249
250
251





252
253
254
255
256
257
258
  devsym_file *p = (devsym_file *)pFile;
  return sqlite3OsShmOpen(p->pReal);
}
static int devsymShmSize(sqlite3_file *pFile, int reqSize, int *pSize){
  devsym_file *p = (devsym_file *)pFile;
  return sqlite3OsShmSize(p->pReal, reqSize, pSize);
}
static int devsymShmGet(sqlite3_file *pFile, int reqSz, int *pSize, void **pp){





  devsym_file *p = (devsym_file *)pFile;
  return sqlite3OsShmGet(p->pReal, reqSz, pSize, pp);
}
static int devsymShmRelease(sqlite3_file *pFile){
  devsym_file *p = (devsym_file *)pFile;
  return sqlite3OsShmRelease(p->pReal);
}







|
>
>
>
>
>







244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
  devsym_file *p = (devsym_file *)pFile;
  return sqlite3OsShmOpen(p->pReal);
}
static int devsymShmSize(sqlite3_file *pFile, int reqSize, int *pSize){
  devsym_file *p = (devsym_file *)pFile;
  return sqlite3OsShmSize(p->pReal, reqSize, pSize);
}
static int devsymShmGet(
  sqlite3_file *pFile,
  int reqSz,
  int *pSize,
  void volatile **pp
){
  devsym_file *p = (devsym_file *)pFile;
  return sqlite3OsShmGet(p->pReal, reqSz, pSize, pp);
}
static int devsymShmRelease(sqlite3_file *pFile){
  devsym_file *p = (devsym_file *)pFile;
  return sqlite3OsShmRelease(p->pReal);
}
Changes to src/test_osinst.c.
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
static int vfslogCheckReservedLock(sqlite3_file*, int *pResOut);
static int vfslogFileControl(sqlite3_file*, int op, void *pArg);
static int vfslogSectorSize(sqlite3_file*);
static int vfslogDeviceCharacteristics(sqlite3_file*);

static int vfslogShmOpen(sqlite3_file *pFile);
static int vfslogShmSize(sqlite3_file *pFile, int reqSize, int *pNewSize);
static int vfslogShmGet(sqlite3_file *pFile, int req, int *pSize, void **pp);
static int vfslogShmRelease(sqlite3_file *pFile);
static int vfslogShmLock(sqlite3_file *pFile, int desiredLock, int *gotLock);
static int vfslogShmClose(sqlite3_file *pFile, int deleteFlag);

/*
** Method declarations for vfslog_vfs.
*/







|







143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
static int vfslogCheckReservedLock(sqlite3_file*, int *pResOut);
static int vfslogFileControl(sqlite3_file*, int op, void *pArg);
static int vfslogSectorSize(sqlite3_file*);
static int vfslogDeviceCharacteristics(sqlite3_file*);

static int vfslogShmOpen(sqlite3_file *pFile);
static int vfslogShmSize(sqlite3_file *pFile, int reqSize, int *pNewSize);
static int vfslogShmGet(sqlite3_file *pFile, int,int*,volatile void **);
static int vfslogShmRelease(sqlite3_file *pFile);
static int vfslogShmLock(sqlite3_file *pFile, int desiredLock, int *gotLock);
static int vfslogShmClose(sqlite3_file *pFile, int deleteFlag);

/*
** Method declarations for vfslog_vfs.
*/
416
417
418
419
420
421
422
423





424
425
426
427
428
429
430
  VfslogFile *p = (VfslogFile *)pFile;
  t = vfslog_time();
  rc = p->pReal->pMethods->xShmSize(p->pReal, reqSize, pNewSize);
  t = vfslog_time() - t;
  vfslog_call(p->pVfslog, OS_SHMSIZE, p->iFileId, t, rc, 0, 0);
  return rc;
}
static int vfslogShmGet(sqlite3_file *pFile, int req, int *pSize, void **pp){





  int rc;
  sqlite3_uint64 t;
  VfslogFile *p = (VfslogFile *)pFile;
  t = vfslog_time();
  rc = p->pReal->pMethods->xShmGet(p->pReal, req, pSize, pp);
  t = vfslog_time() - t;
  vfslog_call(p->pVfslog, OS_SHMGET, p->iFileId, t, rc, 0, 0);







|
>
>
>
>
>







416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
  VfslogFile *p = (VfslogFile *)pFile;
  t = vfslog_time();
  rc = p->pReal->pMethods->xShmSize(p->pReal, reqSize, pNewSize);
  t = vfslog_time() - t;
  vfslog_call(p->pVfslog, OS_SHMSIZE, p->iFileId, t, rc, 0, 0);
  return rc;
}
static int vfslogShmGet(
  sqlite3_file *pFile,
  int req,
  int *pSize,
  volatile void **pp
){
  int rc;
  sqlite3_uint64 t;
  VfslogFile *p = (VfslogFile *)pFile;
  t = vfslog_time();
  rc = p->pReal->pMethods->xShmGet(p->pReal, req, pSize, pp);
  t = vfslog_time() - t;
  vfslog_call(p->pVfslog, OS_SHMGET, p->iFileId, t, rc, 0, 0);
1189
1190
1191
1192
1193
1194
1195
1196

int SqlitetestOsinst_Init(Tcl_Interp *interp){
  Tcl_CreateObjCommand(interp, "vfslog", test_vfslog, 0, 0);
  return TCL_OK;
}

#endif /* SQLITE_TEST */








<
1194
1195
1196
1197
1198
1199
1200


int SqlitetestOsinst_Init(Tcl_Interp *interp){
  Tcl_CreateObjCommand(interp, "vfslog", test_vfslog, 0, 0);
  return TCL_OK;
}

#endif /* SQLITE_TEST */

Changes to src/test_vfs.c.
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
static int tvfsRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int tvfsSleep(sqlite3_vfs*, int microseconds);
static int tvfsCurrentTime(sqlite3_vfs*, double*);

static int tvfsShmOpen(sqlite3_file*);
static int tvfsShmSize(sqlite3_file*, int , int *);
static int tvfsShmGet(sqlite3_file*, int , int *, void **);
static int tvfsShmRelease(sqlite3_file*);
static int tvfsShmLock(sqlite3_file*, int , int *);
static int tvfsShmClose(sqlite3_file*, int);

static sqlite3_io_methods tvfs_io_methods = {
  2,                            /* iVersion */
  tvfsClose,                      /* xClose */







|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
static int tvfsRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int tvfsSleep(sqlite3_vfs*, int microseconds);
static int tvfsCurrentTime(sqlite3_vfs*, double*);

static int tvfsShmOpen(sqlite3_file*);
static int tvfsShmSize(sqlite3_file*, int , int *);
static int tvfsShmGet(sqlite3_file*, int , int *, volatile void **);
static int tvfsShmRelease(sqlite3_file*);
static int tvfsShmLock(sqlite3_file*, int , int *);
static int tvfsShmClose(sqlite3_file*, int);

static sqlite3_io_methods tvfs_io_methods = {
  2,                            /* iVersion */
  tvfsClose,                      /* xClose */
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
  return rc;
}

static int tvfsShmGet(
  sqlite3_file *pFile, 
  int reqMapSize, 
  int *pMapSize, 
  void **pp
){
  int rc = SQLITE_OK;
  TestvfsFile *pFd = (TestvfsFile *)pFile;
  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);

  tvfsExecTcl(p, "xShmGet", 
      Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0







|







505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
  return rc;
}

static int tvfsShmGet(
  sqlite3_file *pFile, 
  int reqMapSize, 
  int *pMapSize, 
  volatile void **pp
){
  int rc = SQLITE_OK;
  TestvfsFile *pFd = (TestvfsFile *)pFile;
  Testvfs *p = (Testvfs *)(pFd->pVfs->pAppData);

  tvfsExecTcl(p, "xShmGet", 
      Tcl_NewStringObj(pFd->pShm->zFile, -1), pFd->pShmId, 0
Changes to src/wal.c.
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
*/
struct Wal {
  sqlite3_vfs *pVfs;         /* The VFS used to create pFd */
  sqlite3_file *pDbFd;       /* File handle for the database file */
  sqlite3_file *pWalFd;      /* File handle for WAL file */
  u32 iCallback;             /* Value to pass to log callback (or 0) */
  int szWIndex;              /* Size of the wal-index that is mapped in mem */
  u32 *pWiData;              /* Pointer to wal-index content in memory */
  u8 lockState;              /* SQLITE_SHM_xxxx constant showing lock state */
  u8 readerType;             /* SQLITE_SHM_READ or SQLITE_SHM_READ_FULL */
  u8 exclusiveMode;          /* Non-zero if connection is in exclusive mode */
  u8 isWindexOpen;           /* True if ShmOpen() called on pDbFd */
  WalIndexHdr hdr;           /* Wal-index for current snapshot */
  char *zWalName;            /* Name of WAL file */
};







|







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
*/
struct Wal {
  sqlite3_vfs *pVfs;         /* The VFS used to create pFd */
  sqlite3_file *pDbFd;       /* File handle for the database file */
  sqlite3_file *pWalFd;      /* File handle for WAL file */
  u32 iCallback;             /* Value to pass to log callback (or 0) */
  int szWIndex;              /* Size of the wal-index that is mapped in mem */
  volatile u32 *pWiData;     /* Pointer to wal-index content in memory */
  u8 lockState;              /* SQLITE_SHM_xxxx constant showing lock state */
  u8 readerType;             /* SQLITE_SHM_READ or SQLITE_SHM_READ_FULL */
  u8 exclusiveMode;          /* Non-zero if connection is in exclusive mode */
  u8 isWindexOpen;           /* True if ShmOpen() called on pDbFd */
  WalIndexHdr hdr;           /* Wal-index for current snapshot */
  char *zWalName;            /* Name of WAL file */
};
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
  return rc;
}

/*
** Update the header of the wal-index file.
*/
static void walIndexWriteHdr(Wal *pWal, WalIndexHdr *pHdr){
  u32 *aHdr = pWal->pWiData;                   /* Write header here */
  u32 *aCksum = &aHdr[WALINDEX_HDR_NFIELD];    /* Write header cksum here */

  assert( WALINDEX_HDR_NFIELD==sizeof(WalIndexHdr)/4 );
  assert( aHdr!=0 );
  memcpy(aHdr, pHdr, sizeof(WalIndexHdr));
  aCksum[0] = aCksum[1] = 1;
  walChecksumBytes((u8 *)aHdr, sizeof(WalIndexHdr), aCksum);
}

/*
** This function encodes a single frame header and writes it to a buffer
** supplied by the caller. A frame-header is made up of a series of 
** 4-byte big-endian integers, as follows:
**







|
|



|

|







228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
  return rc;
}

/*
** Update the header of the wal-index file.
*/
static void walIndexWriteHdr(Wal *pWal, WalIndexHdr *pHdr){
  volatile u32 *aHdr = pWal->pWiData;                 /* Write header here */
  volatile u32 *aCksum = &aHdr[WALINDEX_HDR_NFIELD];  /* Write cksum here */

  assert( WALINDEX_HDR_NFIELD==sizeof(WalIndexHdr)/4 );
  assert( aHdr!=0 );
  memcpy((void*)aHdr, pHdr, sizeof(WalIndexHdr));
  aCksum[0] = aCksum[1] = 1;
  walChecksumBytes((u8*)aHdr, sizeof(WalIndexHdr), (u32*)aCksum);
}

/*
** This function encodes a single frame header and writes it to a buffer
** supplied by the caller. A frame-header is made up of a series of 
** 4-byte big-endian integers, as follows:
**
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
** A value of -1 means "don't care".
*/
static int walIndexMap(Wal *pWal, int reqSize){
  int rc = SQLITE_OK;
  if( pWal->pWiData==0 || reqSize>pWal->szWIndex ){
    walIndexUnmap(pWal);
    rc = sqlite3OsShmGet(pWal->pDbFd, 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( rc!=SQLITE_OK ){







|







411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
** A value of -1 means "don't care".
*/
static int walIndexMap(Wal *pWal, int reqSize){
  int rc = SQLITE_OK;
  if( pWal->pWiData==0 || reqSize>pWal->szWIndex ){
    walIndexUnmap(pWal);
    rc = sqlite3OsShmGet(pWal->pDbFd, reqSize, &pWal->szWIndex,
                             (void volatile**)(char volatile*)&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( rc!=SQLITE_OK ){
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
** Finally, set *paPgno such that for all frames F between (*piZero+1) and 
** (*piZero+HASHTABLE_NPAGE), (*paPgno)[F] is the database page number 
** associated with frame F.
*/
static void walHashFind(
  Wal *pWal,                      /* WAL handle */
  u32 iFrame,                     /* Find the hash table indexing this frame */
  HASHTABLE_DATATYPE **paHash,    /* OUT: Pointer to hash index */
  u32 **paPgno,                   /* OUT: Pointer to page number array */
  u32 *piZero                     /* OUT: Frame associated with *paPgno[0] */
){
  u32 iZero;
  u32 *aPgno;
  HASHTABLE_DATATYPE *aHash;

  iZero = ((iFrame-1)/HASHTABLE_NPAGE) * HASHTABLE_NPAGE;
  aPgno = &pWal->pWiData[walIndexEntry(iZero+1)-iZero-1];
  aHash = (HASHTABLE_DATATYPE *)&aPgno[iZero+HASHTABLE_NPAGE+1];

  /* Assert that:
  **







|
|



|
|







470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
** Finally, set *paPgno such that for all frames F between (*piZero+1) and 
** (*piZero+HASHTABLE_NPAGE), (*paPgno)[F] is the database page number 
** associated with frame F.
*/
static void walHashFind(
  Wal *pWal,                      /* WAL handle */
  u32 iFrame,                     /* Find the hash table indexing this frame */
  volatile HASHTABLE_DATATYPE **paHash,    /* OUT: Pointer to hash index */
  volatile u32 **paPgno,          /* OUT: Pointer to page number array */
  u32 *piZero                     /* OUT: Frame associated with *paPgno[0] */
){
  u32 iZero;
  volatile u32 *aPgno;
  volatile HASHTABLE_DATATYPE *aHash;

  iZero = ((iFrame-1)/HASHTABLE_NPAGE) * HASHTABLE_NPAGE;
  aPgno = &pWal->pWiData[walIndexEntry(iZero+1)-iZero-1];
  aHash = (HASHTABLE_DATATYPE *)&aPgno[iZero+HASHTABLE_NPAGE+1];

  /* Assert that:
  **
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
  ** table and section of of the page number array that pertain to frame 
  ** iFrame of the WAL. Then populate the page number array and the hash 
  ** table entry.
  */
  if( rc==SQLITE_OK ){
    int iKey;                     /* Hash table key */
    u32 iZero;                    /* One less than frame number of aPgno[1] */
    u32 *aPgno;                   /* Page number array */
    HASHTABLE_DATATYPE *aHash;    /* Hash table */
    int idx;                      /* Value to write to hash-table slot */

    walHashFind(pWal, iFrame, &aHash, &aPgno, &iZero);
    idx = iFrame - iZero;
    if( idx==1 ) memset(aHash, 0, HASHTABLE_NBYTE);
    aPgno[iFrame] = iPage;
    for(iKey=walHashKey(iPage); aHash[iKey]; iKey=(iKey+1)%HASHTABLE_NSLOT);
    aHash[iKey] = idx;
  }

  return rc;
}







|
|
|



|







525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
  ** table and section of of the page number array that pertain to frame 
  ** iFrame of the WAL. Then populate the page number array and the hash 
  ** table entry.
  */
  if( rc==SQLITE_OK ){
    int iKey;                     /* Hash table key */
    u32 iZero;                    /* One less than frame number of aPgno[1] */
    volatile u32 *aPgno;                 /* Page number array */
    volatile HASHTABLE_DATATYPE *aHash;  /* Hash table */
    int idx;                             /* Value to write to hash-table slot */

    walHashFind(pWal, iFrame, &aHash, &aPgno, &iZero);
    idx = iFrame - iZero;
    if( idx==1 ) memset((void*)aHash, 0, HASHTABLE_NBYTE);
    aPgno[iFrame] = iPage;
    for(iKey=walHashKey(iPage); aHash[iKey]; iKey=(iKey+1)%HASHTABLE_NSLOT);
    aHash[iKey] = idx;
  }

  return rc;
}
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
  u8 *aTmp;                       /* Temp space used by merge-sort */
  int rc;                         /* Return code of walIndexMap() */

  rc = walIndexMap(pWal, walMappingSize(pWal->hdr.iLastPg));
  if( rc!=SQLITE_OK ){
    return rc;
  }
  aData = pWal->pWiData;
  iLast = pWal->hdr.iLastPg;
  nSegment = (iLast >> 8) + 1;
  nFinal = (iLast & 0x000000FF);

  nByte = sizeof(WalIterator) + (nSegment+1)*(sizeof(struct WalSegment)+256);
  p = (WalIterator *)sqlite3_malloc(nByte);
  if( !p ){







|







756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
  u8 *aTmp;                       /* Temp space used by merge-sort */
  int rc;                         /* Return code of walIndexMap() */

  rc = walIndexMap(pWal, walMappingSize(pWal->hdr.iLastPg));
  if( rc!=SQLITE_OK ){
    return rc;
  }
  aData = (u32*)pWal->pWiData;
  iLast = pWal->hdr.iLastPg;
  nSegment = (iLast >> 8) + 1;
  nFinal = (iLast & 0x000000FF);

  nByte = sizeof(WalIterator) + (nSegment+1)*(sizeof(struct WalSegment)+256);
  p = (WalIterator *)sqlite3_malloc(nByte);
  if( !p ){
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
  }

  /* Read the header. The caller may or may not have an exclusive 
  ** (WRITE, PENDING, CHECKPOINT or RECOVER) lock on the wal-index
  ** file, meaning it is possible that an inconsistent snapshot is read
  ** from the file. If this happens, return non-zero.
  */
  memcpy(aHdr, pWal->pWiData, sizeof(aHdr));
  walChecksumBytes((u8*)aHdr, sizeof(u32)*WALINDEX_HDR_NFIELD, aCksum);
  if( aCksum[0]!=aHdr[WALINDEX_HDR_NFIELD]
   || aCksum[1]!=aHdr[WALINDEX_HDR_NFIELD+1]
  ){
    return 1;
  }








|







947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
  }

  /* Read the header. The caller may or may not have an exclusive 
  ** (WRITE, PENDING, CHECKPOINT or RECOVER) lock on the wal-index
  ** file, meaning it is possible that an inconsistent snapshot is read
  ** from the file. If this happens, return non-zero.
  */
  memcpy(aHdr, (void*)pWal->pWiData, sizeof(aHdr));
  walChecksumBytes((u8*)aHdr, sizeof(u32)*WALINDEX_HDR_NFIELD, aCksum);
  if( aCksum[0]!=aHdr[WALINDEX_HDR_NFIELD]
   || aCksum[1]!=aHdr[WALINDEX_HDR_NFIELD+1]
  ){
    return 1;
  }

1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
  **     incorrectly read data from frame 3 instead of 4. This would be
  **     an error.
  **
  ** It is not actually clear to the developers that such a dirty-read
  ** can occur. But if it does, it should not cause any problems.
  */
  for(iHash=iLast; iHash>0 && iRead==0; iHash-=HASHTABLE_NPAGE){
    HASHTABLE_DATATYPE *aHash;    /* Pointer to hash table */
    u32 *aPgno;                   /* Pointer to array of page numbers */
    u32 iZero;                    /* Frame number corresponding to aPgno[0] */
    int iKey;                     /* Hash slot index */

    walHashFind(pWal, iHash, &aHash, &aPgno, &iZero);
    for(iKey=walHashKey(pgno); aHash[iKey]; iKey=(iKey+1)%HASHTABLE_NSLOT){
      u32 iFrame = aHash[iKey] + iZero;
      if( iFrame<=iLast && aPgno[iFrame]==pgno && iFrame>iRead ){







|
|







1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
  **     incorrectly read data from frame 3 instead of 4. This would be
  **     an error.
  **
  ** It is not actually clear to the developers that such a dirty-read
  ** can occur. But if it does, it should not cause any problems.
  */
  for(iHash=iLast; iHash>0 && iRead==0; iHash-=HASHTABLE_NPAGE){
    volatile HASHTABLE_DATATYPE *aHash;  /* Pointer to hash table */
    volatile u32 *aPgno;                 /* Pointer to array of page numbers */
    u32 iZero;                    /* Frame number corresponding to aPgno[0] */
    int iKey;                     /* Hash slot index */

    walHashFind(pWal, iHash, &aHash, &aPgno, &iZero);
    for(iKey=walHashKey(pgno); aHash[iKey]; iKey=(iKey+1)%HASHTABLE_NSLOT){
      u32 iFrame = aHash[iKey] + iZero;
      if( iFrame<=iLast && aPgno[iFrame]==pgno && iFrame>iRead ){
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
    /* If this connection is not reading the most recent database snapshot,
    ** it is not possible to write to the database. In this case release
    ** the write locks and return SQLITE_BUSY.
    */
    if( rc==SQLITE_OK ){
      rc = walIndexMap(pWal, sizeof(WalIndexHdr));
      if( rc==SQLITE_OK
       && memcmp(&pWal->hdr, pWal->pWiData, sizeof(WalIndexHdr))
      ){
        rc = SQLITE_BUSY;
      }
      walIndexUnmap(pWal);
      if( rc!=SQLITE_OK ){
        walSetLock(pWal, SQLITE_SHM_READ);
      }







|







1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
    /* If this connection is not reading the most recent database snapshot,
    ** it is not possible to write to the database. In this case release
    ** the write locks and return SQLITE_BUSY.
    */
    if( rc==SQLITE_OK ){
      rc = walIndexMap(pWal, sizeof(WalIndexHdr));
      if( rc==SQLITE_OK
       && memcmp(&pWal->hdr, (void*)pWal->pWiData, sizeof(WalIndexHdr))
      ){
        rc = SQLITE_BUSY;
      }
      walIndexUnmap(pWal);
      if( rc!=SQLITE_OK ){
        walSetLock(pWal, SQLITE_SHM_READ);
      }