1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Add a new xShmBarrier method to the VFS - a shared-memory fence operation.

Implement the same in both unix and win32.  Use it to make the WAL subsystem
more robust.

FossilOrigin-Name: 1bd011c9fed5ef29fb616b4d0a52df3b82221b1f
This commit is contained in:
drh
2010-05-20 23:51:06 +00:00
parent 7e263728f2
commit 286a288493
14 changed files with 135 additions and 41 deletions

View File

@@ -207,7 +207,10 @@ typedef struct WalIterator WalIterator;
/*
** The following object holds an exact copy of the wal-index header.
** The following object holds a copy of the wal-index header content.
**
** The actual header in the wal-index consists of two copies of this
** object.
*/
struct WalIndexHdr {
u32 iChange; /* Counter incremented each transaction */
@@ -223,7 +226,7 @@ struct WalIndexHdr {
** only support mandatory file-locks, we do not read or write data
** from the region of the file on which locks are applied.
*/
#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr))
#define WALINDEX_LOCK_OFFSET (sizeof(WalIndexHdr)*2)
#define WALINDEX_LOCK_RESERVED 8
/* Size of header before each frame in wal */
@@ -306,13 +309,13 @@ static void walChecksumBytes(
u32 *aOut /* OUT: Final checksum value output */
){
u32 s1, s2;
u8 *aEnd = (u8*)&a[nByte];
if( aIn ){
s1 = aIn[0];
s2 = aIn[1];
}else{
s1 = s2 = 0;
}
u8 *aEnd = (u8*)&a[nByte];
assert( nByte>=8 );
assert( (nByte&0x00000003)==0 );
@@ -355,10 +358,14 @@ static int walSetLock(Wal *pWal, int desiredStatus){
** The checksum on pWal->hdr is updated before it is written.
*/
static void walIndexWriteHdr(Wal *pWal){
WalIndexHdr *aHdr;
walChecksumBytes((u8*)&pWal->hdr,
sizeof(pWal->hdr) - sizeof(pWal->hdr.aCksum),
0, pWal->hdr.aCksum);
memcpy((void*)pWal->pWiData, &pWal->hdr, sizeof(pWal->hdr));
aHdr = (WalIndexHdr*)pWal->pWiData;
memcpy(&aHdr[1], &pWal->hdr, sizeof(pWal->hdr));
sqlite3OsShmBarrier(pWal->pDbFd);
memcpy(&aHdr[0], &pWal->hdr, sizeof(pWal->hdr));
}
/*
@@ -1118,8 +1125,9 @@ int sqlite3WalClose(
** is read successfully and the checksum verified, return zero.
*/
int walIndexTryHdr(Wal *pWal, int *pChanged){
u32 aCksum[2];
WalIndexHdr hdr;
u32 aCksum[2]; /* Checksum on the header content */
WalIndexHdr hdr1, hdr2; /* Two copies of the header content */
WalIndexHdr *aHdr; /* Header in shared memory */
assert( pWal->pWiData );
if( pWal->szWIndex==0 ){
@@ -1135,15 +1143,24 @@ int walIndexTryHdr(Wal *pWal, int *pChanged){
** file, meaning it is possible that an inconsistent snapshot is read
** from the file. If this happens, return non-zero.
*/
memcpy(&hdr, (void*)pWal->pWiData, sizeof(hdr));
walChecksumBytes((u8*)&hdr, sizeof(hdr)-sizeof(hdr.aCksum), 0, aCksum);
if( aCksum[0]!=hdr.aCksum[0] || aCksum[1]!=hdr.aCksum[1] ){
aHdr = (WalIndexHdr*)pWal->pWiData;
memcpy(&hdr1, &aHdr[0], sizeof(hdr1));
sqlite3OsShmBarrier(pWal->pDbFd);
memcpy(&hdr2, &aHdr[1], sizeof(hdr2));
if( memcmp(&hdr1, &hdr2, sizeof(hdr1))!=0 ){
/* Dirty read */
return 1;
}
walChecksumBytes((u8*)&hdr1, sizeof(hdr1)-sizeof(hdr1.aCksum), 0, aCksum);
if( aCksum[0]!=hdr1.aCksum[0] || aCksum[1]!=hdr1.aCksum[1] ){
/* Malformed header */
return 1;
}
if( memcmp(&pWal->hdr, &hdr, sizeof(WalIndexHdr)) ){
if( memcmp(&pWal->hdr, &hdr1, sizeof(WalIndexHdr)) ){
*pChanged = 1;
memcpy(&pWal->hdr, &hdr, sizeof(WalIndexHdr));
memcpy(&pWal->hdr, &hdr1, sizeof(WalIndexHdr));
pWal->szPage = pWal->hdr.szPage;
}