-C Fix\sa\stypo\son\sa\swebpage.\s\sTicket\s#1792.\s(CVS\s3179)
-D 2006-05-03T23:39:37
+C Automatically\sincrease\sthe\ssize\sof\sthe\spager\shash\stable\sas\sthe\snumber\nof\sin-memory\spages\sincreases.\s\sTickets\s#1790\sand\s#1799.\s(CVS\s3180)
+D 2006-05-07T17:49:39
F Makefile.in 5d8dff443383918b700e495de42ec65bc1c8865b
F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
F src/os_win.c 8ced9ac82670bbf77492961a2f7ff80a87f1404f
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
-F src/pager.c 57348b21910450b47cdb7ab7a9a4e6bac68f6a5f
+F src/pager.c ddd05666bb89808a516baef2c186d6a75887ae90
F src/pager.h 43f32f3847421f7502cfbb66f4eb2302b8033818
F src/parse.y ee1887ce0e6eea15cc728913ad3462898f88e9b0
F src/pragma.c 27d5e395c5d950931c7ac4fe610e7c2993e2fa55
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 8f820e435272c0a4861421508c7e6f2979c2750f
-R 04653401c505e2c6061ff2b69b857755
+P 2702205277f45aadd2f07d51f71af4efd266228f
+R 682ba0f4fded90e799844395c2609fd0
U drh
-Z 8508385ee7359f0e5208e0edf1f45b07
+Z 5c4f907a07f2808d253fc1ec4dae9689
** file simultaneously, or one process from reading the database while
** another is writing.
**
-** @(#) $Id: pager.c,v 1.267 2006/05/03 23:34:06 drh Exp $
+** @(#) $Id: pager.c,v 1.268 2006/05/07 17:49:39 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#define PGHDR_TO_HIST(P,PGR) \
((PgHistory*)&((char*)(&(P)[1]))[(PGR)->pageSize+(PGR)->nExtra])
-/*
-** How big to make the hash table used for locating in-memory pages
-** by page number. This macro looks a little silly, but is evaluated
-** at compile-time, not run-time (at least for gcc this is true).
-*/
-#define N_PG_HASH (\
- (MAX_PAGES>1024)?2048: \
- (MAX_PAGES>512)?1024: \
- (MAX_PAGES>256)?512: \
- (MAX_PAGES>128)?256: \
- (MAX_PAGES>64)?128:64 \
-)
-
-/*
-** Hash a page number
-*/
-#define pager_hash(PN) ((PN)&(N_PG_HASH-1))
-
/*
** A open page cache is an instance of the following structure.
**
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() */
- PgHdr *aHash[N_PG_HASH]; /* Hash table to map page number to PgHdr */
+ 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
# 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
** a pointer to the page or NULL if not found.
*/
static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
- PgHdr *p = pPager->aHash[pager_hash(pgno)];
+ PgHdr *p;
+ if( pPager->aHash==0 ) return 0;
+ p = pPager->aHash[pgno & (pPager->nHash-1)];
while( p && p->pgno!=pgno ){
p = p->pNextHash;
}
pPager->pFirstSynced = 0;
pPager->pLast = 0;
pPager->pAll = 0;
- memset(pPager->aHash, 0, sizeof(pPager->aHash));
+ pPager->nHash = 0;
+ sqliteFree(pPager->aHash);
pPager->nPage = 0;
+ pPager->aHash = 0;
if( pPager->state>=PAGER_RESERVED ){
sqlite3pager_rollback(pPager);
}
pPg->pNextHash->pPrevHash = pPg->pPrevHash;
}
if( pPg->pPrevHash ){
- assert( pPager->aHash[pager_hash(pPg->pgno)]!=pPg );
+ assert( pPager->aHash[pPg->pgno & (pPager->nHash-1)]!=pPg );
pPg->pPrevHash->pNextHash = pPg->pNextHash;
}else{
- int h = pager_hash(pPg->pgno);
+ int h = pPg->pgno & (pPager->nHash-1);
assert( pPager->aHash[h]==pPg );
pPager->aHash[h] = pPg->pNextHash;
}
pTmp->pNext = pPager->pNext;
}
#endif
-
+ sqliteFree(pPager->aHash);
sqliteFree(pPager);
return SQLITE_OK;
}
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) );
}
/* Link the page into the page hash table */
- h = pager_hash(pgno);
+ h = pgno & (pPager->nHash-1);
pPg->pNextHash = pPager->aHash[h];
pPager->aHash[h] = pPg;
if( pPg->pNextHash ){
/* Change the page number for pPg and insert it into the new hash-chain. */
pPg->pgno = pgno;
- h = pager_hash(pgno);
+ h = pgno & (pPager->nHash-1);
if( pPager->aHash[h] ){
assert( pPager->aHash[h]->pPrevHash==0 );
pPager->aHash[h]->pPrevHash = pPg;