]> granicus.if.org Git - postgresql/commitdiff
Rely on relcache invalidation to update the cached size of the FSM.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 26 Nov 2008 17:08:58 +0000 (17:08 +0000)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
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 */