Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add several EXPENSIVE_ASSERT code blocks to validate the wal-index hash table. Fix the bugs that these code blocks fine. Rename walClearHash() to walCleanupHash() and simplify its interface. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
7aade899e55f4565f02d301e1e83fb0b |
User & Date: | drh 2010-05-22 00:55:40.000 |
Context
2010-05-22
| ||
08:22 | Add a couple of missing methods to test_osinst.c.. (check-in: 5c9e9c06ae user: dan tags: trunk) | |
00:55 | Add several EXPENSIVE_ASSERT code blocks to validate the wal-index hash table. Fix the bugs that these code blocks fine. Rename walClearHash() to walCleanupHash() and simplify its interface. (check-in: 7aade899e5 user: drh tags: trunk) | |
2010-05-21
| ||
19:15 | Fix another bug in walClearHash(). (check-in: 40f80ffe70 user: dan tags: trunk) | |
Changes
Changes to src/wal.c.
︙ | ︙ | |||
648 649 650 651 652 653 654 | if( idx==1 ) memset((void*)aHash, 0, HASHTABLE_NBYTE); assert( idx <= HASHTABLE_NSLOT/2 + 1 ); aPgno[iFrame] = iPage; for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){ assert( nCollide++ < idx ); } aHash[iKey] = idx; | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 | if( idx==1 ) memset((void*)aHash, 0, HASHTABLE_NBYTE); assert( idx <= HASHTABLE_NSLOT/2 + 1 ); aPgno[iFrame] = iPage; for(iKey=walHash(iPage); aHash[iKey]; iKey=walNextHash(iKey)){ assert( nCollide++ < idx ); } aHash[iKey] = idx; #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT /* Verify that the number of entries in the hash table exactly equals ** the number of entries in the mapping region. */ { int i; /* Loop counter */ int nEntry = 0; /* Number of entries in the hash table */ for(i=0; i<HASHTABLE_NSLOT; i++){ if( aHash[i] ) nEntry++; } assert( nEntry==idx ); } /* Verify that the every entry in the mapping region is reachable ** via the hash table. This turns out to be a really, really expensive ** thing to check, so only do this occasionally - not on every ** iteration. */ if( (idx&0x3ff)==0 ){ int i; /* Loop counter */ for(i=1; i<=idx; i++){ for(iKey=walHash(aPgno[i+iZero]); aHash[iKey]; iKey=walNextHash(iKey)){ if( aHash[iKey]==i ) break; } assert( aHash[iKey]==i ); } } #endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */ } return rc; } /* ** Recover the wal-index by reading the write-ahead log file. |
︙ | ︙ | |||
1463 1464 1465 1466 1467 1468 1469 | }else if( pWal->lockState==SQLITE_SHM_WRITE ){ rc = walSetLock(pWal, SQLITE_SHM_READ); } return rc; } /* | | | | < < | < < < < | > > > | < | | | | > | | | | | | | | | | | > > > > > > > > > > > > > > > | 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 | }else if( pWal->lockState==SQLITE_SHM_WRITE ){ rc = walSetLock(pWal, SQLITE_SHM_READ); } return rc; } /* ** Remove entries from the hash table that point to WAL slots greater ** than pWal->hdr.mxFrame. ** ** This function is called whenever pWal->hdr.mxFrame is decreased due ** to a rollback or savepoint. ** ** At most only the very last hash table needs to be updated. Any ** later hash tables will be automatically cleared when pWal->hdr.mxFrame ** advances to the point where those hash tables are actually needed. */ static void walCleanupHash(Wal *pWal){ volatile HASHTABLE_DATATYPE *aHash; /* Pointer to hash table to clear */ volatile u32 *aPgno; /* Unused return from walHashFind() */ u32 iZero; /* frame == (aHash[x]+iZero) */ int iLimit; /* Zero values greater than this */ assert( pWal->lockState==SQLITE_SHM_WRITE ); walHashFind(pWal, pWal->hdr.mxFrame+1, &aHash, &aPgno, &iZero); iLimit = pWal->hdr.mxFrame - iZero; if( iLimit>0 ){ int i; /* Used to iterate through aHash[] */ for(i=0; i<HASHTABLE_NSLOT; i++){ if( aHash[i]>iLimit ){ aHash[i] = 0; } } } #ifdef SQLITE_ENABLE_EXPENSIVE_ASSERT /* Verify that the every entry in the mapping region is still reachable ** via the hash table even after the cleanup. */ { int i; /* Loop counter */ int iKey; /* Hash key */ for(i=1; i<=iLimit; i++){ for(iKey=walHash(aPgno[i+iZero]); aHash[iKey]; iKey=walNextHash(iKey)){ if( aHash[iKey]==i ) break; } assert( aHash[iKey]==i ); } } #endif /* SQLITE_ENABLE_EXPENSIVE_ASSERT */ } /* ** If any data has been written (but not committed) to the log file, this ** function moves the write-pointer back to the start of the transaction. ** ** Additionally, the callback function is invoked for each frame written |
︙ | ︙ | |||
1517 1518 1519 1520 1521 1522 1523 | if( pWal->lockState==SQLITE_SHM_WRITE ){ int unused; Pgno iMax = pWal->hdr.mxFrame; Pgno iFrame; assert( pWal->pWiData==0 ); rc = walIndexReadHdr(pWal, &unused); | > > | | | | < < | 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 | if( pWal->lockState==SQLITE_SHM_WRITE ){ int unused; Pgno iMax = pWal->hdr.mxFrame; Pgno iFrame; assert( pWal->pWiData==0 ); rc = walIndexReadHdr(pWal, &unused); if( rc==SQLITE_OK ){ walCleanupHash(pWal); for(iFrame=pWal->hdr.mxFrame+1; rc==SQLITE_OK && iFrame<=iMax; iFrame++){ assert( pWal->lockState==SQLITE_SHM_WRITE ); rc = xUndo(pUndoCtx, pWal->pWiData[walIndexEntry(iFrame)]); } } walIndexUnmap(pWal); } return rc; } /* Return an integer that records the current (uncommitted) write |
︙ | ︙ | |||
1544 1545 1546 1547 1548 1549 1550 | /* Move the write position of the WAL back to iFrame. Called in ** response to a ROLLBACK TO command. */ int sqlite3WalSavepointUndo(Wal *pWal, u32 iFrame){ int rc = SQLITE_OK; assert( pWal->lockState==SQLITE_SHM_WRITE ); | > > | > | | | | < > | 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 | /* Move the write position of the WAL back to iFrame. Called in ** response to a ROLLBACK TO command. */ int sqlite3WalSavepointUndo(Wal *pWal, u32 iFrame){ int rc = SQLITE_OK; assert( pWal->lockState==SQLITE_SHM_WRITE ); assert( iFrame<=pWal->hdr.mxFrame ); if( iFrame<pWal->hdr.mxFrame ){ rc = walIndexMap(pWal, walMappingSize(pWal->hdr.mxFrame)); pWal->hdr.mxFrame = iFrame; if( rc==SQLITE_OK ){ walCleanupHash(pWal); walIndexUnmap(pWal); } } return rc; } /* ** Write a set of frames to the log. The caller must hold the write-lock ** on the log file (obtained using sqlite3WalWriteLock()). */ |
︙ | ︙ |