/ Check-in [542b90eb]

 ```266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 ... 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 ... 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 ``` ``` u32 *aPgno; /* 256 page numbers. Pointer to Wal.pWiData */ } aSegment[1]; /* One for every 256 entries in the WAL */ }; /* ** Generate an 8 byte checksum based on the data in array aByte[] and the ** initial values of aCksum[0] and aCksum[1]. The checksum is written into ** aCksum[] before returning. ** ** The range of bytes to checksum is treated as an array of 32-bit ** little-endian unsigned integers. For each integer X in the array, from ** start to finish, do the following: ** ** aCksum[0] += X; ** aCksum[1] += aCksum[0]; ** ** For the calculation above, use 64-bit unsigned accumulators. Before ** returning, truncate the values to 32-bits as follows: ** ** aCksum[0] = (u32)(aCksum[0] + (aCksum[0]>>24)); ** aCksum[1] = (u32)(aCksum[1] + (aCksum[1]>>24)); */ static void walChecksumBytes(u8 *aByte, int nByte, u32 *aCksum){ u64 sum1 = aCksum[0]; u64 sum2 = aCksum[1]; u32 *a32 = (u32 *)aByte; u32 *aEnd = (u32 *)&aByte[nByte]; assert( (nByte&0x00000003)==0 ); if( SQLITE_LITTLEENDIAN ){ #ifdef SQLITE_DEBUG u8 *a = (u8 *)a32; assert( *a32==(a[0] + (a[1]<<8) + (a[2]<<16) + (a[3]<<24)) ); #endif do { sum1 += *a32; sum2 += sum1; } while( ++a32>24); aCksum[1] = sum2 + (sum2>>24); } /* ** Attempt to change the lock status. ** ** When changing the lock status to SQLITE_SHM_READ, store the ** type of reader lock (either SQLITE_SHM_READ or SQLITE_SHM_READ_FULL) ................................................................................ if( rc!=SQLITE_OK ){ return rc; } if( nSize>WAL_FRAME_HDRSIZE ){ u8 aBuf[WAL_FRAME_HDRSIZE]; /* Buffer to load first frame header into */ u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */ int nFrame; /* Number of bytes at aFrame */ u8 *aData; /* Pointer to data part of aFrame buffer */ int iFrame; /* Index of last frame read */ i64 iOffset; /* Next offset to read from log file */ int szPage; /* Page size according to the log */ u32 aCksum[2]; /* Running checksum */ /* Read in the first frame header in the file (to determine the ................................................................................ if( szPage&(szPage-1) || szPage>SQLITE_MAX_PAGE_SIZE || szPage<512 ){ goto finished; } aCksum[0] = sqlite3Get4byte(&aBuf[4]); aCksum[1] = sqlite3Get4byte(&aBuf[8]); /* Malloc a buffer to read frames into. */ nFrame = szPage + WAL_FRAME_HDRSIZE; aFrame = (u8 *)sqlite3_malloc(nFrame); if( !aFrame ){ return SQLITE_NOMEM; } aData = &aFrame[WAL_FRAME_HDRSIZE]; /* Read all frames from the log file. */ iFrame = 0; for(iOffset=WAL_HDRSIZE; (iOffset+nFrame)<=nSize; iOffset+=nFrame){ u32 pgno; /* Database page number for frame */ u32 nTruncate; /* dbsize field from frame header */ int isValid; /* True if this frame is valid */ /* Read and decode the next log frame. */ rc = sqlite3OsRead(pWal->pWalFd, aFrame, nFrame, iOffset); if( rc!=SQLITE_OK ) break; isValid = walDecodeFrame(aCksum, &pgno, &nTruncate, szPage, aData, aFrame); if( !isValid ) break; rc = walIndexAppend(pWal, ++iFrame, pgno); if( rc!=SQLITE_OK ) break; /* If nTruncate is non-zero, this is a commit record. */ ``` ``` | | < < < < < < < < < < < < < | | | < | > < < < < < | < < < < < < | > | | < < | | | | | | | ``` ```266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 ... 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 ... 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 ``` ``` u32 *aPgno; /* 256 page numbers. Pointer to Wal.pWiData */ } aSegment[1]; /* One for every 256 entries in the WAL */ }; /* ** Generate an 8 byte checksum based on the data in array aByte[] and the ** initial values of aCksum[0] and aCksum[1]. The checksum is written ** back into aCksum[] before returning. */ static void walChecksumBytes(u8 *a, int nByte, u32 *aCksum){ u32 s1 = aCksum[0]; u32 s2 = aCksum[1]; u8 *aEnd = (u8*)&a[nByte]; assert( nByte>=8 ); assert( (nByte&0x00000003)==0 ); do { s1 += (a[0]<<24) + (a[2]<<16) + (a[2]<<8) + a[3] + s2; s2 += (a[3]<<24) + (a[5]<<16) + (a[6]<<8) + a[7] + s1; a += 8; }while( aWAL_FRAME_HDRSIZE ){ u8 aBuf[WAL_FRAME_HDRSIZE]; /* Buffer to load first frame header into */ u8 *aFrame = 0; /* Malloc'd buffer to load entire frame */ int szFrame; /* Number of bytes in buffer aFrame[] */ u8 *aData; /* Pointer to data part of aFrame buffer */ int iFrame; /* Index of last frame read */ i64 iOffset; /* Next offset to read from log file */ int szPage; /* Page size according to the log */ u32 aCksum[2]; /* Running checksum */ /* Read in the first frame header in the file (to determine the ................................................................................ if( szPage&(szPage-1) || szPage>SQLITE_MAX_PAGE_SIZE || szPage<512 ){ goto finished; } aCksum[0] = sqlite3Get4byte(&aBuf[4]); aCksum[1] = sqlite3Get4byte(&aBuf[8]); /* Malloc a buffer to read frames into. */ szFrame = szPage + WAL_FRAME_HDRSIZE; aFrame = (u8 *)sqlite3_malloc(szFrame); if( !aFrame ){ return SQLITE_NOMEM; } aData = &aFrame[WAL_FRAME_HDRSIZE]; /* Read all frames from the log file. */ iFrame = 0; for(iOffset=WAL_HDRSIZE; (iOffset+szFrame)<=nSize; iOffset+=szFrame){ u32 pgno; /* Database page number for frame */ u32 nTruncate; /* dbsize field from frame header */ int isValid; /* True if this frame is valid */ /* Read and decode the next log frame. */ rc = sqlite3OsRead(pWal->pWalFd, aFrame, szFrame, iOffset); if( rc!=SQLITE_OK ) break; isValid = walDecodeFrame(aCksum, &pgno, &nTruncate, szPage, aData, aFrame); if( !isValid ) break; rc = walIndexAppend(pWal, ++iFrame, pgno); if( rc!=SQLITE_OK ) break; /* If nTruncate is non-zero, this is a commit record. */ ```