Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Auto-vacuum bug: Correctly manipulate page cache hash-table entries in sqlite3pager_movepage(). (CVS 2046) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
719c1b79671c8cd7c5a6b5967ad4265b |
User & Date: | danielk1977 2004-11-03 08:44:06.000 |
Context
2004-11-03
| ||
09:30 | Comment the autovacuum.test script. No code or test-case changes. (CVS 2047) (check-in: 2eacd38620 user: danielk1977 tags: trunk) | |
08:44 | Auto-vacuum bug: Correctly manipulate page cache hash-table entries in sqlite3pager_movepage(). (CVS 2046) (check-in: 719c1b7967 user: danielk1977 tags: trunk) | |
03:59 | The makefile now runs mkkeywordhash.c. Keywords that are unused are omitted from the keyword hash table. (CVS 2045) (check-in: 007aec1133 user: drh tags: trunk) | |
Changes
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | ** The pager is used to access a database disk file. It implements ** atomic commit and rollback through the use of a journal file that ** is separate from the database file. The pager also implements file ** locking to prevent two processes from writing the same database ** file simultaneously, or one process from reading the database while ** another is writing. ** ** @(#) $Id: pager.c,v 1.171 2004/11/03 08:44:06 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include "pager.h" #include <assert.h> #include <string.h> |
︙ | ︙ | |||
1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 | } /* ** Forward declaration */ static int syncJournal(Pager*); /* ** Unlink a page from the free list (the list of all pages where nRef==0) ** and from its hash collision chain. */ static void unlinkPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 | } /* ** Forward declaration */ static int syncJournal(Pager*); /* ** Unlink pPg from it's hash chain. Also set the page number to 0 to indicate ** that the page is not part of any hash chain. This is required because the ** sqlite3pager_movepage() routine can leave a page in the ** pNextFree/pPrevFree list that is not a part of any hash-chain. */ static void unlinkHashChain(Pager *pPager, PgHdr *pPg){ if( pPg->pgno==0 ){ /* If the page number is zero, then this page is not in any hash chain. */ return; } if( pPg->pNextHash ){ pPg->pNextHash->pPrevHash = pPg->pPrevHash; } if( pPg->pPrevHash ){ assert( pPager->aHash[pager_hash(pPg->pgno)]!=pPg ); pPg->pPrevHash->pNextHash = pPg->pNextHash; }else{ int h = pager_hash(pPg->pgno); assert( pPager->aHash[h]==pPg ); pPager->aHash[h] = pPg->pNextHash; } pPg->pgno = 0; pPg->pNextHash = pPg->pPrevHash = 0; } /* ** Unlink a page from the free list (the list of all pages where nRef==0) ** and from its hash collision chain. */ static void unlinkPage(PgHdr *pPg){ Pager *pPager = pPg->pPager; |
︙ | ︙ | |||
1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 | }else{ assert( pPager->pLast==pPg ); pPager->pLast = pPg->pPrevFree; } pPg->pNextFree = pPg->pPrevFree = 0; /* Unlink from the pgno hash table */ if( pPg->pNextHash ){ pPg->pNextHash->pPrevHash = pPg->pPrevHash; } if( pPg->pPrevHash ){ pPg->pPrevHash->pNextHash = pPg->pNextHash; }else{ int h = pager_hash(pPg->pgno); assert( pPager->aHash[h]==pPg ); pPager->aHash[h] = pPg->pNextHash; } pPg->pNextHash = pPg->pPrevHash = 0; } /* ** This routine is used to truncate an in-memory database. Delete ** all pages whose pgno is larger than pPager->dbSize and is unreferenced. ** Referenced pages larger than pPager->dbSize are zeroed. */ | > > > | 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 | }else{ assert( pPager->pLast==pPg ); pPager->pLast = pPg->pPrevFree; } pPg->pNextFree = pPg->pPrevFree = 0; /* Unlink from the pgno hash table */ unlinkHashChain(pPager, pPg); /* if( pPg->pNextHash ){ pPg->pNextHash->pPrevHash = pPg->pPrevHash; } if( pPg->pPrevHash ){ pPg->pPrevHash->pNextHash = pPg->pNextHash; }else{ int h = pager_hash(pPg->pgno); assert( pPager->aHash[h]==pPg ); pPager->aHash[h] = pPg->pNextHash; } pPg->pNextHash = pPg->pPrevHash = 0; */ } /* ** This routine is used to truncate an in-memory database. Delete ** all pages whose pgno is larger than pPager->dbSize and is unreferenced. ** Referenced pages larger than pPager->dbSize are zeroed. */ |
︙ | ︙ | |||
3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 | } sync_exit: return rc; } #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Move the page identified by pData to location pgno in the file. ** ** There must be no references to the current page pgno. If current page ** pgno is not already in the rollback journal, it is not written there by ** by this routine. The same applies to the page pData refers to on entry to ** this routine. ** ** References to the page refered to by pData remain valid. Updating any ** meta-data associated with page pData (i.e. data stored in the nExtra bytes ** allocated along with the page) is the responsibility of the caller. ** ** A transaction must be active when this routine is called, however it is ** illegal to call this routine if a statment transaction is active. */ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ PgHdr *pPg = DATA_TO_PGHDR(pData); PgHdr *pPgOld; assert( !pPager->stmtInUse ); | > > < < < < < < < < | < | | < < | > < | | | | < < < < < < | < < | > | | > | | | > | | < < < < < | 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 | } sync_exit: return rc; } #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Move the page identified by pData to location pgno in the file. ** ** There must be no references to the current page pgno. If current page ** pgno is not already in the rollback journal, it is not written there by ** by this routine. The same applies to the page pData refers to on entry to ** this routine. ** ** References to the page refered to by pData remain valid. Updating any ** meta-data associated with page pData (i.e. data stored in the nExtra bytes ** allocated along with the page) is the responsibility of the caller. ** ** A transaction must be active when this routine is called, however it is ** illegal to call this routine if a statment transaction is active. */ int sqlite3pager_movepage(Pager *pPager, void *pData, Pgno pgno){ PgHdr *pPg = DATA_TO_PGHDR(pData); PgHdr *pPgOld; int h; assert( !pPager->stmtInUse ); assert( pPg->nRef>0 ); /* Unlink pPg from it's hash-chain */ unlinkHashChain(pPager, pPg); /* If the cache contains a page with page-number pgno exists, remove it ** from it's hash chain. */ pPgOld = pager_lookup(pPager, pgno); if( pPgOld ){ assert( pPgOld->nRef==0 ); unlinkHashChain(pPager, pPgOld); pPgOld->dirty = 0; } /* Change the page number for pPg and insert it into the new hash-chain. */ pPg->pgno = pgno; h = pager_hash(pgno); if( pPager->aHash[h] ){ assert( pPager->aHash[h]->pPrevHash==0 ); pPager->aHash[h]->pPrevHash = pPg; } pPg->pNextHash = pPager->aHash[h]; pPager->aHash[h] = pPg; pPg->pPrevHash = 0; pPg->dirty = 1; pPager->dirtyCache = 1; return SQLITE_OK; } #endif |
︙ | ︙ |