diff options
author | drh <> | 2022-09-02 14:29:54 +0000 |
---|---|---|
committer | drh <> | 2022-09-02 14:29:54 +0000 |
commit | 4e9bf5ace34a29d04386bfa9bcdda1861750b744 (patch) | |
tree | 64ea7cf89d49069128e37b78bb09061fac2e2a64 /src | |
parent | e04c9f4b33521a99388ce27eb46a0947fda44a26 (diff) | |
download | sqlite-4e9bf5ace34a29d04386bfa9bcdda1861750b744.tar.gz sqlite-4e9bf5ace34a29d04386bfa9bcdda1861750b744.zip |
Enhance the pcache1 implementation so that during an xRekey operation if
another page already exists at the destination, that other page gets moved
to the source key.
FossilOrigin-Name: aadd38f99a3e5abcf9bef49f4367752f163cc79500a28f812bb71969d7de419c
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; } |