Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Automatically increase the size of the pager hash table as the number of in-memory pages increases. Tickets #1790 and #1799. (CVS 3180) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
ef8e9886f40c8528604264308f5e4734 |
User & Date: | drh 2006-05-07 17:49:39.000 |
Context
2006-05-08
| ||
15:14 | Fix error processing in Lemon. SQLite does not use this feature of lemon so it is uneffected. (CVS 3181) (check-in: 864cac9603 user: drh tags: trunk) | |
2006-05-07
| ||
17:49 | Automatically increase the size of the pager hash table as the number of in-memory pages increases. Tickets #1790 and #1799. (CVS 3180) (check-in: ef8e9886f4 user: drh tags: trunk) | |
2006-05-03
| ||
23:39 | Fix a typo on a webpage. Ticket #1792. (CVS 3179) (check-in: 2702205277 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.268 2006/05/07 17:49:39 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" #include "os.h" #include "pager.h" #include <assert.h> #include <string.h> |
︙ | ︙ | |||
204 205 206 207 208 209 210 | */ #define PGHDR_TO_DATA(P) ((void*)(&(P)[1])) #define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1]) #define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->pageSize]) #define PGHDR_TO_HIST(P,PGR) \ ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra]) | < < < < < < < < < < < < < < < < < < | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | */ #define PGHDR_TO_DATA(P) ((void*)(&(P)[1])) #define DATA_TO_PGHDR(D) (&((PgHdr*)(D))[-1]) #define PGHDR_TO_EXTRA(G,P) ((void*)&((char*)(&(G)[1]))[(P)->pageSize]) #define PGHDR_TO_HIST(P,PGR) \ ((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra]) /* ** A open page cache is an instance of the following structure. ** ** Pager.errCode may be set to SQLITE_IOERR, SQLITE_CORRUPT, SQLITE_PROTOCOL ** or SQLITE_FULL. Once one of the first three errors occurs, it persists ** and is returned as the result of every major pager API call. The ** SQLITE_FULL return code is slightly different. It persists only until the |
︙ | ︙ | |||
292 293 294 295 296 297 298 | int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */ int nRead,nWrite; /* Database pages read/written */ #endif void (*xDestructor)(void*,int); /* Call this routine when freeing pages */ void (*xReiniter)(void*,int); /* Call this routine when reloading pages */ void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ void *pCodecArg; /* First argument to xCodec() */ | > | | 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 | int nHit, nMiss, nOvfl; /* Cache hits, missing, and LRU overflows */ int nRead,nWrite; /* Database pages read/written */ #endif void (*xDestructor)(void*,int); /* Call this routine when freeing pages */ void (*xReiniter)(void*,int); /* Call this routine when reloading pages */ void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */ void *pCodecArg; /* First argument to xCodec() */ int nHash; /* Size of the pager hash table */ PgHdr **aHash; /* Hash table to map page number to PgHdr */ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT Pager *pNext; /* Linked list of pagers in this thread */ #endif }; /* ** If SQLITE_TEST is defined then increment the variable given in |
︙ | ︙ | |||
399 400 401 402 403 404 405 406 407 408 409 410 411 412 | cnt++; /* Something to set a breakpoint on */ } # define REFINFO(X) pager_refinfo(X) #else # define REFINFO(X) #endif /* ** Read a 32-bit integer from the given file descriptor. Store the integer ** that is read in *pRes. Return SQLITE_OK if everything worked, or an ** error code is something goes wrong. ** ** All values are stored on disk as big-endian. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 | cnt++; /* Something to set a breakpoint on */ } # define REFINFO(X) pager_refinfo(X) #else # define REFINFO(X) #endif /* ** Change the size of the pager hash table to N. N must be a power ** of two. */ static void pager_resize_hash_table(Pager *pPager, int N){ PgHdr **aHash, *pPg; assert( N>0 && (N&(N-1))==0 ); aHash = sqliteMalloc( sizeof(aHash[0])*N ); if( aHash==0 ){ /* Failure to rehash is not an error. It is only a performance hit. */ return; } sqliteFree(pPager->aHash); pPager->nHash = N; pPager->aHash = aHash; for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){ int h = pPg->pgno & (N-1); pPg->pNextHash = aHash[h]; if( aHash[h] ){ aHash[h]->pPrevHash = pPg; } aHash[h] = pPg; pPg->pPrevHash = 0; } } /* ** Read a 32-bit integer from the given file descriptor. Store the integer ** that is read in *pRes. Return SQLITE_OK if everything worked, or an ** error code is something goes wrong. ** ** All values are stored on disk as big-endian. */ |
︙ | ︙ | |||
818 819 820 821 822 823 824 | } /* ** Find a page in the hash table given its page number. Return ** a pointer to the page or NULL if not found. */ static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ | | > > | 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 | } /* ** Find a page in the hash table given its page number. Return ** a pointer to the page or NULL if not found. */ static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){ PgHdr *p; if( pPager->aHash==0 ) return 0; p = pPager->aHash[pgno & (pPager->nHash-1)]; while( p && p->pgno!=pgno ){ p = p->pNextHash; } return p; } /* |
︙ | ︙ | |||
842 843 844 845 846 847 848 | pNext = pPg->pNextAll; sqliteFree(pPg); } pPager->pFirst = 0; pPager->pFirstSynced = 0; pPager->pLast = 0; pPager->pAll = 0; | > | > | 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 | pNext = pPg->pNextAll; sqliteFree(pPg); } pPager->pFirst = 0; pPager->pFirstSynced = 0; pPager->pLast = 0; pPager->pAll = 0; pPager->nHash = 0; sqliteFree(pPager->aHash); pPager->nPage = 0; pPager->aHash = 0; if( pPager->state>=PAGER_RESERVED ){ sqlite3pager_rollback(pPager); } sqlite3OsUnlock(pPager->fd, NO_LOCK); pPager->state = PAGER_UNLOCK; pPager->dbSize = -1; pPager->nRef = 0; |
︙ | ︙ | |||
1845 1846 1847 1848 1849 1850 1851 | /* 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 ){ | | | | 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 | /* 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[pPg->pgno & (pPager->nHash-1)]!=pPg ); pPg->pPrevHash->pNextHash = pPg->pNextHash; }else{ int h = pPg->pgno & (pPager->nHash-1); assert( pPager->aHash[h]==pPg ); pPager->aHash[h] = pPg->pNextHash; } if( MEMDB ){ clearHistory(PGHDR_TO_HIST(pPg, pPager)); } pPg->pgno = 0; |
︙ | ︙ | |||
2080 2081 2082 2083 2084 2085 2086 | pTsd->pPager = pPager->pNext; }else{ Pager *pTmp; for(pTmp = pTsd->pPager; pTmp->pNext!=pPager; pTmp=pTmp->pNext){} pTmp->pNext = pPager->pNext; } #endif | | | 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 | pTsd->pPager = pPager->pNext; }else{ Pager *pTmp; for(pTmp = pTsd->pPager; pTmp->pNext!=pPager; pTmp=pTmp->pNext){} pTmp->pNext = pPager->pNext; } #endif sqliteFree(pPager->aHash); sqliteFree(pPager); return SQLITE_OK; } /* ** Return the page number for the given page data. */ |
︙ | ︙ | |||
2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 | } if( pPg==0 ){ /* The requested page is not in the page cache. */ int h; TEST_INCR(pPager->nMiss); if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || MEMDB ){ /* Create a new page */ pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize + sizeof(u32) + pPager->nExtra + MEMDB*sizeof(PgHistory) ); if( pPg==0 ){ return SQLITE_NOMEM; } memset(pPg, 0, sizeof(*pPg)); | > > > > > > > | 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 | } if( pPg==0 ){ /* The requested page is not in the page cache. */ int h; TEST_INCR(pPager->nMiss); if( pPager->nPage<pPager->mxPage || pPager->pFirst==0 || MEMDB ){ /* Create a new page */ if( pPager->nPage>=pPager->nHash ){ pager_resize_hash_table(pPager, pPager->nHash<256 ? 256 : pPager->nHash*2); if( pPager->nHash==0 ){ return SQLITE_NOMEM; } } pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->pageSize + sizeof(u32) + pPager->nExtra + MEMDB*sizeof(PgHistory) ); if( pPg==0 ){ return SQLITE_NOMEM; } memset(pPg, 0, sizeof(*pPg)); |
︙ | ︙ | |||
2706 2707 2708 2709 2710 2711 2712 | } }else{ TEST_INCR(pPager->nRead); } } /* Link the page into the page hash table */ | | | 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 | } }else{ TEST_INCR(pPager->nRead); } } /* Link the page into the page hash table */ h = pgno & (pPager->nHash-1); pPg->pNextHash = pPager->aHash[h]; pPager->aHash[h] = pPg; if( pPg->pNextHash ){ assert( pPg->pNextHash->pPrevHash==0 ); pPg->pNextHash->pPrevHash = pPg; } |
︙ | ︙ | |||
3762 3763 3764 3765 3766 3767 3768 | pPg->needSync = 1; assert( pPager->needSync ); } } /* Change the page number for pPg and insert it into the new hash-chain. */ pPg->pgno = pgno; | | | 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 | pPg->needSync = 1; assert( pPager->needSync ); } } /* Change the page number for pPg and insert it into the new hash-chain. */ pPg->pgno = pgno; h = pgno & (pPager->nHash-1); 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; |
︙ | ︙ |