diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/pcache1.c | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/src/pcache1.c b/src/pcache1.c index 3e406a7a8..a47087fa1 100644 --- a/src/pcache1.c +++ b/src/pcache1.c @@ -1119,7 +1119,7 @@ static void pcache1Rekey( PCache1 *pCache = (PCache1 *)p; PgHdr1 *pPage = (PgHdr1 *)pPg; PgHdr1 **pp; - unsigned int h; + unsigned int hOld, hNew; assert( pPage->iKey==iOld ); assert( pPage->pCache==pCache ); assert( iOld!=iNew ); /* The page number really is changing */ @@ -1127,18 +1127,33 @@ static void pcache1Rekey( pcache1EnterMutex(pCache->pGroup); assert( pcache1FetchNoMutex(p, iOld, 0)==pPage ); /* pPg really is iOld */ - h = iOld%pCache->nHash; - pp = &pCache->apHash[h]; + hOld = iOld%pCache->nHash; + pp = &pCache->apHash[hOld]; while( (*pp)!=pPage ){ pp = &(*pp)->pNext; } *pp = pPage->pNext; - assert( pcache1FetchNoMutex(p, iNew, 0)==0 ); /* iNew not previously used */ - h = iNew%pCache->nHash; + hNew = iNew%pCache->nHash; + pp = &pCache->apHash[hNew]; + while( *pp ){ + if( (*pp)->iKey==iNew ){ + /* If there is already another pcache entry at iNew, change it to iOld, + ** thus swapping the positions of iNew and iOld */ + PgHdr1 *pOld = *pp; + *pp = pOld->pNext; + pOld->pNext = pCache->apHash[hOld]; + pCache->apHash[hOld] = pOld; + pOld->iKey = iOld; + break; + }else{ + pp = &(*pp)->pNext; + } + } + pPage->iKey = iNew; - pPage->pNext = pCache->apHash[h]; - pCache->apHash[h] = pPage; + pPage->pNext = pCache->apHash[hNew]; + pCache->apHash[hNew] = pPage; if( iNew>pCache->iMaxKey ){ pCache->iMaxKey = iNew; } |