mirror of
https://github.com/postgres/postgres.git
synced 2025-11-07 19:06:32 +03:00
Cache smgrnblocks() results in recovery.
Avoid repeatedly calling lseek(SEEK_END) during recovery by caching the size of each fork. For now, we can't use the same technique in other processes, because we lack a shared invalidation mechanism. Do this by generalizing the pre-existing caching used by FSM and VM to support all forks. Discussion: https://postgr.es/m/CAEepm%3D3SSw-Ty1DFcK%3D1rU-K6GSzYzfdD4d%2BZwapdN7dTa6%3DnQ%40mail.gmail.com
This commit is contained in:
@@ -541,18 +541,19 @@ fsm_readbuf(Relation rel, FSMAddress addr, bool extend)
|
||||
* value might be stale. (We send smgr inval messages on truncation, but
|
||||
* not on extension.)
|
||||
*/
|
||||
if (rel->rd_smgr->smgr_fsm_nblocks == InvalidBlockNumber ||
|
||||
blkno >= rel->rd_smgr->smgr_fsm_nblocks)
|
||||
if (rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] == InvalidBlockNumber ||
|
||||
blkno >= rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM])
|
||||
{
|
||||
/* Invalidate the cache so smgrnblocks asks the kernel. */
|
||||
rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] = InvalidBlockNumber;
|
||||
if (smgrexists(rel->rd_smgr, FSM_FORKNUM))
|
||||
rel->rd_smgr->smgr_fsm_nblocks = smgrnblocks(rel->rd_smgr,
|
||||
FSM_FORKNUM);
|
||||
smgrnblocks(rel->rd_smgr, FSM_FORKNUM);
|
||||
else
|
||||
rel->rd_smgr->smgr_fsm_nblocks = 0;
|
||||
rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] = 0;
|
||||
}
|
||||
|
||||
/* Handle requests beyond EOF */
|
||||
if (blkno >= rel->rd_smgr->smgr_fsm_nblocks)
|
||||
if (blkno >= rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM])
|
||||
{
|
||||
if (extend)
|
||||
fsm_extend(rel, blkno + 1);
|
||||
@@ -621,14 +622,17 @@ fsm_extend(Relation rel, BlockNumber fsm_nblocks)
|
||||
RelationOpenSmgr(rel);
|
||||
|
||||
/*
|
||||
* Create the FSM file first if it doesn't exist. If smgr_fsm_nblocks is
|
||||
* positive then it must exist, no need for an smgrexists call.
|
||||
* Create the FSM file first if it doesn't exist. If
|
||||
* smgr_cached_nblocks[FSM_FORKNUM] is positive then it must exist, no
|
||||
* need for an smgrexists call.
|
||||
*/
|
||||
if ((rel->rd_smgr->smgr_fsm_nblocks == 0 ||
|
||||
rel->rd_smgr->smgr_fsm_nblocks == InvalidBlockNumber) &&
|
||||
if ((rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] == 0 ||
|
||||
rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] == InvalidBlockNumber) &&
|
||||
!smgrexists(rel->rd_smgr, FSM_FORKNUM))
|
||||
smgrcreate(rel->rd_smgr, FSM_FORKNUM, false);
|
||||
|
||||
/* Invalidate cache so that smgrnblocks() asks the kernel. */
|
||||
rel->rd_smgr->smgr_cached_nblocks[FSM_FORKNUM] = InvalidBlockNumber;
|
||||
fsm_nblocks_now = smgrnblocks(rel->rd_smgr, FSM_FORKNUM);
|
||||
|
||||
while (fsm_nblocks_now < fsm_nblocks)
|
||||
@@ -640,9 +644,6 @@ fsm_extend(Relation rel, BlockNumber fsm_nblocks)
|
||||
fsm_nblocks_now++;
|
||||
}
|
||||
|
||||
/* Update local cache with the up-to-date size */
|
||||
rel->rd_smgr->smgr_fsm_nblocks = fsm_nblocks_now;
|
||||
|
||||
UnlockRelationForExtension(rel, ExclusiveLock);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user