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: |
0a6787908e989bd5e6af25acbdc59ebc |
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
Changes to src/os.c.
︙ | ︙ | |||
100 101 102 103 104 105 106 | } 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); } | | | 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 | 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*); | | | 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 | ** *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 */ | | | 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 | 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); | | | 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 | */ 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); } | | > > > > > | 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 | 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*); | | | 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 | 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); } | | > > > > > | 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 | 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); | | | 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 | 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; } | | > > > > > | 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 | 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 | #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 *); | | | 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 | return rc; } static int tvfsShmGet( sqlite3_file *pFile, int reqMapSize, int *pMapSize, | | | 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 | */ 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 */ | | | 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 | return rc; } /* ** Update the header of the wal-index file. */ static void walIndexWriteHdr(Wal *pWal, WalIndexHdr *pHdr){ | | | | | | 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 | ** 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, | | | 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 | ** 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 */ | | | | | | 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 | ** 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] */ | | | | | | 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 | 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; } | | | 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 | } /* 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. */ | | | 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 | ** 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){ | | | | 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 | /* 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 | | | 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); } |
︙ | ︙ |