Commit 9858a8c8 authored by Heikki Linnakangas's avatar Heikki Linnakangas

Rely on relcache invalidation to update the cached size of the FSM.

parent df559de9
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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) ...@@ -376,7 +376,7 @@ CreateFakeRelcacheEntry(RelFileNode rnode)
rel->rd_lockInfo.lockRelId.relId = rnode.relNode; rel->rd_lockInfo.lockRelId.relId = rnode.relNode;
rel->rd_targblock = InvalidBlockNumber; rel->rd_targblock = InvalidBlockNumber;
rel->rd_fsm_nblocks_cache = InvalidBlockNumber; rel->rd_fsm_nblocks = InvalidBlockNumber;
rel->rd_smgr = NULL; rel->rd_smgr = NULL;
return rel; return rel;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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: * NOTES:
...@@ -101,7 +101,7 @@ static BlockNumber fsm_get_heap_blk(FSMAddress addr, uint16 slot); ...@@ -101,7 +101,7 @@ static BlockNumber fsm_get_heap_blk(FSMAddress addr, uint16 slot);
static BlockNumber fsm_logical_to_physical(FSMAddress addr); static BlockNumber fsm_logical_to_physical(FSMAddress addr);
static Buffer fsm_readbuf(Relation rel, FSMAddress addr, bool extend); 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 */ /* functions to convert amount of free space to a FSM category */
static uint8 fsm_space_avail_to_cat(Size avail); static uint8 fsm_space_avail_to_cat(Size avail);
...@@ -303,13 +303,13 @@ FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks) ...@@ -303,13 +303,13 @@ FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
smgrtruncate(rel->rd_smgr, FSM_FORKNUM, new_nfsmblocks, rel->rd_istemp); 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. * seen by other backends is no longer valid.
*/ */
if (!InRecovery) if (!InRecovery)
CacheInvalidateRelcache(rel); 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) ...@@ -503,19 +503,20 @@ fsm_readbuf(Relation rel, FSMAddress addr, bool extend)
RelationOpenSmgr(rel); RelationOpenSmgr(rel);
if (rel->rd_fsm_nblocks_cache == InvalidBlockNumber || /* If we haven't cached the size of the FSM yet, check it first */
rel->rd_fsm_nblocks_cache <= blkno) if (rel->rd_fsm_nblocks == InvalidBlockNumber)
{ {
if (!smgrexists(rel->rd_smgr, FSM_FORKNUM)) if (smgrexists(rel->rd_smgr, FSM_FORKNUM))
fsm_extend(rel, blkno + 1, true); rel->rd_fsm_nblocks = smgrnblocks(rel->rd_smgr, FSM_FORKNUM);
else 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) if (extend)
fsm_extend(rel, blkno + 1, false); fsm_extend(rel, blkno + 1);
else else
return InvalidBuffer; return InvalidBuffer;
} }
...@@ -536,13 +537,12 @@ fsm_readbuf(Relation rel, FSMAddress addr, bool extend) ...@@ -536,13 +537,12 @@ fsm_readbuf(Relation rel, FSMAddress addr, bool extend)
/* /*
* Ensure that the FSM fork is at least n_fsmblocks long, extending * 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 * 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, * with zeros, meaning there's no free space.
* the FSM file might need to be created first.
*/ */
static void 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; Page pg;
pg = (Page) palloc(BLCKSZ); pg = (Page) palloc(BLCKSZ);
...@@ -561,27 +561,30 @@ fsm_extend(Relation rel, BlockNumber n_fsmblocks, bool createstorage) ...@@ -561,27 +561,30 @@ fsm_extend(Relation rel, BlockNumber n_fsmblocks, bool createstorage)
LockRelationForExtension(rel, ExclusiveLock); LockRelationForExtension(rel, ExclusiveLock);
/* Create the FSM file first if it doesn't exist */ /* 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); smgrcreate(rel->rd_smgr, FSM_FORKNUM, false);
n_fsmblocks_now = 0; fsm_nblocks_now = 0;
} }
else 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); (char *) pg, rel->rd_istemp);
n_fsmblocks_now++; fsm_nblocks_now++;
} }
UnlockRelationForExtension(rel, ExclusiveLock); UnlockRelationForExtension(rel, ExclusiveLock);
pfree(pg); pfree(pg);
/* update the cache with the up-to-date size */ /* Update the relcache with the up-to-date size */
rel->rd_fsm_nblocks_cache = n_fsmblocks_now; if (!InRecovery)
CacheInvalidateRelcache(rel);
rel->rd_fsm_nblocks = fsm_nblocks_now;
} }
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -304,7 +304,7 @@ AllocateRelationDesc(Relation relation, Form_pg_class relp)
*/ */
MemSet(relation, 0, sizeof(RelationData)); MemSet(relation, 0, sizeof(RelationData));
relation->rd_targblock = InvalidBlockNumber; 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 */ /* make sure relation is marked as having no open file yet */
relation->rd_smgr = NULL; relation->rd_smgr = NULL;
...@@ -1376,7 +1376,7 @@ formrdesc(const char *relationName, Oid relationReltype, ...@@ -1376,7 +1376,7 @@ formrdesc(const char *relationName, Oid relationReltype,
*/ */
relation = (Relation) palloc0(sizeof(RelationData)); relation = (Relation) palloc0(sizeof(RelationData));
relation->rd_targblock = InvalidBlockNumber; 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 */ /* make sure relation is marked as having no open file yet */
relation->rd_smgr = NULL; relation->rd_smgr = NULL;
...@@ -1665,9 +1665,9 @@ RelationReloadIndexInfo(Relation relation) ...@@ -1665,9 +1665,9 @@ RelationReloadIndexInfo(Relation relation)
heap_freetuple(pg_class_tuple); heap_freetuple(pg_class_tuple);
/* We must recalculate physical address in case it changed */ /* We must recalculate physical address in case it changed */
RelationInitPhysicalAddr(relation); 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_targblock = InvalidBlockNumber;
relation->rd_fsm_nblocks_cache = InvalidBlockNumber; relation->rd_fsm_nblocks = InvalidBlockNumber;
/* Must free any AM cached data, too */ /* Must free any AM cached data, too */
if (relation->rd_amcache) if (relation->rd_amcache)
pfree(relation->rd_amcache); pfree(relation->rd_amcache);
...@@ -1750,7 +1750,7 @@ RelationClearRelation(Relation relation, bool rebuild) ...@@ -1750,7 +1750,7 @@ RelationClearRelation(Relation relation, bool rebuild)
if (relation->rd_isnailed) if (relation->rd_isnailed)
{ {
relation->rd_targblock = InvalidBlockNumber; relation->rd_targblock = InvalidBlockNumber;
relation->rd_fsm_nblocks_cache = InvalidBlockNumber; relation->rd_fsm_nblocks = InvalidBlockNumber;
if (relation->rd_rel->relkind == RELKIND_INDEX) if (relation->rd_rel->relkind == RELKIND_INDEX)
{ {
relation->rd_isvalid = false; /* needs to be revalidated */ relation->rd_isvalid = false; /* needs to be revalidated */
...@@ -2345,7 +2345,7 @@ RelationBuildLocalRelation(const char *relname, ...@@ -2345,7 +2345,7 @@ RelationBuildLocalRelation(const char *relname,
rel = (Relation) palloc0(sizeof(RelationData)); rel = (Relation) palloc0(sizeof(RelationData));
rel->rd_targblock = InvalidBlockNumber; 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 */ /* make sure relation is marked as having no open file yet */
rel->rd_smgr = NULL; rel->rd_smgr = NULL;
...@@ -3602,7 +3602,7 @@ load_relcache_init_file(void) ...@@ -3602,7 +3602,7 @@ load_relcache_init_file(void)
*/ */
rel->rd_smgr = NULL; rel->rd_smgr = NULL;
rel->rd_targblock = InvalidBlockNumber; rel->rd_targblock = InvalidBlockNumber;
rel->rd_fsm_nblocks_cache = InvalidBlockNumber; rel->rd_fsm_nblocks = InvalidBlockNumber;
if (rel->rd_isnailed) if (rel->rd_isnailed)
rel->rd_refcnt = 1; rel->rd_refcnt = 1;
else else
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 ...@@ -195,8 +195,8 @@ typedef struct RelationData
List *rd_indpred; /* index predicate tree, if any */ List *rd_indpred; /* index predicate tree, if any */
void *rd_amcache; /* available for use by index AM */ void *rd_amcache; /* available for use by index AM */
/* Cached last-seen size of the FSM */ /* size of the FSM, or InvalidBlockNumber if not known yet */
BlockNumber rd_fsm_nblocks_cache; BlockNumber rd_fsm_nblocks;
/* use "struct" here to avoid needing to include pgstat.h: */ /* use "struct" here to avoid needing to include pgstat.h: */
struct PgStat_TableStatus *pgstat_info; /* statistics collection area */ struct PgStat_TableStatus *pgstat_info; /* statistics collection area */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment