Rely on relcache invalidation to update the cached size of the FSM.
authorHeikki Linnakangas
Wed, 26 Nov 2008 17:08:58 +0000 (17:08 +0000)
committerHeikki Linnakangas
Wed, 26 Nov 2008 17:08:58 +0000 (17:08 +0000)
src/backend/access/transam/xlogutils.c
src/backend/storage/freespace/freespace.c
src/backend/utils/cache/relcache.c
src/include/utils/rel.h

index b481a5ef1d43b25d7107618acff6c695d74512ad..466cc648581085d442701c4653eaca80bfb5d17a 100644 (file)
@@ -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;
index 013b4ce221153b9e2bd56e90258a2f2dbd12a68f..7466ba85cbbe374002eefa2ccb8ef7b6dd0bbb9d 100644 (file)
@@ -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;
 }
 
 /*
index 657ebf8c71f74f3c5e7890ace016658fc0f706b6..b6a87ed7a8a179eff7947d449699e17d2a7aecd9 100644 (file)
@@ -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
index 71ad936d2747719516dd602ea5ca86bf6b82b252..44540dd64990cb9225942ca81932cc69b2952c02 100644 (file)
@@ -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 */