From 9858a8c81cc1c433e273a55a278b757716201179 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Wed, 26 Nov 2008 17:08:58 +0000 Subject: [PATCH] Rely on relcache invalidation to update the cached size of the FSM. --- src/backend/access/transam/xlogutils.c | 4 +- src/backend/storage/freespace/freespace.c | 49 ++++++++++++----------- src/backend/utils/cache/relcache.c | 16 ++++---- src/include/utils/rel.h | 6 +-- 4 files changed, 39 insertions(+), 36 deletions(-) diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c index b481a5ef1d..466cc64858 100644 --- a/src/backend/access/transam/xlogutils.c +++ b/src/backend/access/transam/xlogutils.c @@ -11,7 +11,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.63 2008/11/19 10:34:50 heikki Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.64 2008/11/26 17:08:57 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -376,7 +376,7 @@ CreateFakeRelcacheEntry(RelFileNode rnode) rel->rd_lockInfo.lockRelId.relId = rnode.relNode; rel->rd_targblock = InvalidBlockNumber; - rel->rd_fsm_nblocks_cache = InvalidBlockNumber; + rel->rd_fsm_nblocks = InvalidBlockNumber; rel->rd_smgr = NULL; return rel; diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c index 013b4ce221..7466ba85cb 100644 --- a/src/backend/storage/freespace/freespace.c +++ b/src/backend/storage/freespace/freespace.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.67 2008/11/19 10:34:52 heikki Exp $ + * $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.68 2008/11/26 17:08:57 heikki Exp $ * * * NOTES: @@ -101,7 +101,7 @@ static BlockNumber fsm_get_heap_blk(FSMAddress addr, uint16 slot); static BlockNumber fsm_logical_to_physical(FSMAddress addr); static Buffer fsm_readbuf(Relation rel, FSMAddress addr, bool extend); -static void fsm_extend(Relation rel, BlockNumber nfsmblocks, bool createstorage); +static void fsm_extend(Relation rel, BlockNumber fsm_nblocks); /* functions to convert amount of free space to a FSM category */ static uint8 fsm_space_avail_to_cat(Size avail); @@ -303,13 +303,13 @@ FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks) smgrtruncate(rel->rd_smgr, FSM_FORKNUM, new_nfsmblocks, rel->rd_istemp); /* - * Need to invalidate the relcache entry, because rd_fsm_nblocks_cache + * Need to invalidate the relcache entry, because rd_fsm_nblocks * seen by other backends is no longer valid. */ if (!InRecovery) CacheInvalidateRelcache(rel); - rel->rd_fsm_nblocks_cache = new_nfsmblocks; + rel->rd_fsm_nblocks = new_nfsmblocks; } /* @@ -503,19 +503,20 @@ fsm_readbuf(Relation rel, FSMAddress addr, bool extend) RelationOpenSmgr(rel); - if (rel->rd_fsm_nblocks_cache == InvalidBlockNumber || - rel->rd_fsm_nblocks_cache <= blkno) + /* If we haven't cached the size of the FSM yet, check it first */ + if (rel->rd_fsm_nblocks == InvalidBlockNumber) { - if (!smgrexists(rel->rd_smgr, FSM_FORKNUM)) - fsm_extend(rel, blkno + 1, true); + if (smgrexists(rel->rd_smgr, FSM_FORKNUM)) + rel->rd_fsm_nblocks = smgrnblocks(rel->rd_smgr, FSM_FORKNUM); else - rel->rd_fsm_nblocks_cache = smgrnblocks(rel->rd_smgr, FSM_FORKNUM); + rel->rd_fsm_nblocks = 0; } - if (blkno >= rel->rd_fsm_nblocks_cache) + /* Handle requests beyond EOF */ + if (blkno >= rel->rd_fsm_nblocks) { if (extend) - fsm_extend(rel, blkno + 1, false); + fsm_extend(rel, blkno + 1); else return InvalidBuffer; } @@ -536,13 +537,12 @@ fsm_readbuf(Relation rel, FSMAddress addr, bool extend) /* * Ensure that the FSM fork is at least n_fsmblocks long, extending * it if necessary with empty pages. And by empty, I mean pages filled - * with zeros, meaning there's no free space. If createstorage is true, - * the FSM file might need to be created first. + * with zeros, meaning there's no free space. */ static void -fsm_extend(Relation rel, BlockNumber n_fsmblocks, bool createstorage) +fsm_extend(Relation rel, BlockNumber fsm_nblocks) { - BlockNumber n_fsmblocks_now; + BlockNumber fsm_nblocks_now; Page pg; pg = (Page) palloc(BLCKSZ); @@ -561,27 +561,30 @@ fsm_extend(Relation rel, BlockNumber n_fsmblocks, bool createstorage) LockRelationForExtension(rel, ExclusiveLock); /* Create the FSM file first if it doesn't exist */ - if (createstorage && !smgrexists(rel->rd_smgr, FSM_FORKNUM)) + if ((rel->rd_fsm_nblocks == 0 || rel->rd_fsm_nblocks == InvalidBlockNumber) + && !smgrexists(rel->rd_smgr, FSM_FORKNUM)) { smgrcreate(rel->rd_smgr, FSM_FORKNUM, false); - n_fsmblocks_now = 0; + fsm_nblocks_now = 0; } else - n_fsmblocks_now = smgrnblocks(rel->rd_smgr, FSM_FORKNUM); + fsm_nblocks_now = smgrnblocks(rel->rd_smgr, FSM_FORKNUM); - while (n_fsmblocks_now < n_fsmblocks) + while (fsm_nblocks_now < fsm_nblocks) { - smgrextend(rel->rd_smgr, FSM_FORKNUM, n_fsmblocks_now, + smgrextend(rel->rd_smgr, FSM_FORKNUM, fsm_nblocks_now, (char *) pg, rel->rd_istemp); - n_fsmblocks_now++; + fsm_nblocks_now++; } UnlockRelationForExtension(rel, ExclusiveLock); pfree(pg); - /* update the cache with the up-to-date size */ - rel->rd_fsm_nblocks_cache = n_fsmblocks_now; + /* Update the relcache with the up-to-date size */ + if (!InRecovery) + CacheInvalidateRelcache(rel); + rel->rd_fsm_nblocks = fsm_nblocks_now; } /* diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 657ebf8c71..b6a87ed7a8 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.276 2008/11/10 00:49:37 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.277 2008/11/26 17:08:57 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -304,7 +304,7 @@ AllocateRelationDesc(Relation relation, Form_pg_class relp) */ MemSet(relation, 0, sizeof(RelationData)); relation->rd_targblock = InvalidBlockNumber; - relation->rd_fsm_nblocks_cache = InvalidBlockNumber; + relation->rd_fsm_nblocks = InvalidBlockNumber; /* make sure relation is marked as having no open file yet */ relation->rd_smgr = NULL; @@ -1376,7 +1376,7 @@ formrdesc(const char *relationName, Oid relationReltype, */ relation = (Relation) palloc0(sizeof(RelationData)); relation->rd_targblock = InvalidBlockNumber; - relation->rd_fsm_nblocks_cache = InvalidBlockNumber; + relation->rd_fsm_nblocks = InvalidBlockNumber; /* make sure relation is marked as having no open file yet */ relation->rd_smgr = NULL; @@ -1665,9 +1665,9 @@ RelationReloadIndexInfo(Relation relation) heap_freetuple(pg_class_tuple); /* We must recalculate physical address in case it changed */ RelationInitPhysicalAddr(relation); - /* Must reset targblock and fsm_nblocks_cache in case rel was truncated */ + /* Must reset targblock and fsm_nblocks in case rel was truncated */ relation->rd_targblock = InvalidBlockNumber; - relation->rd_fsm_nblocks_cache = InvalidBlockNumber; + relation->rd_fsm_nblocks = InvalidBlockNumber; /* Must free any AM cached data, too */ if (relation->rd_amcache) pfree(relation->rd_amcache); @@ -1750,7 +1750,7 @@ RelationClearRelation(Relation relation, bool rebuild) if (relation->rd_isnailed) { relation->rd_targblock = InvalidBlockNumber; - relation->rd_fsm_nblocks_cache = InvalidBlockNumber; + relation->rd_fsm_nblocks = InvalidBlockNumber; if (relation->rd_rel->relkind == RELKIND_INDEX) { relation->rd_isvalid = false; /* needs to be revalidated */ @@ -2345,7 +2345,7 @@ RelationBuildLocalRelation(const char *relname, rel = (Relation) palloc0(sizeof(RelationData)); rel->rd_targblock = InvalidBlockNumber; - rel->rd_fsm_nblocks_cache = InvalidBlockNumber; + rel->rd_fsm_nblocks = InvalidBlockNumber; /* make sure relation is marked as having no open file yet */ rel->rd_smgr = NULL; @@ -3602,7 +3602,7 @@ load_relcache_init_file(void) */ rel->rd_smgr = NULL; rel->rd_targblock = InvalidBlockNumber; - rel->rd_fsm_nblocks_cache = InvalidBlockNumber; + rel->rd_fsm_nblocks = InvalidBlockNumber; if (rel->rd_isnailed) rel->rd_refcnt = 1; else diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index 71ad936d27..44540dd649 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.108 2008/09/30 10:52:14 heikki Exp $ + * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.109 2008/11/26 17:08:58 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -195,8 +195,8 @@ typedef struct RelationData List *rd_indpred; /* index predicate tree, if any */ void *rd_amcache; /* available for use by index AM */ - /* Cached last-seen size of the FSM */ - BlockNumber rd_fsm_nblocks_cache; + /* size of the FSM, or InvalidBlockNumber if not known yet */ + BlockNumber rd_fsm_nblocks; /* use "struct" here to avoid needing to include pgstat.h: */ struct PgStat_TableStatus *pgstat_info; /* statistics collection area */ -- 2.40.0