aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pcache1.c29
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;
}