]> granicus.if.org Git - postgresql/commitdiff
Restructure smgr API as per recent proposal. smgr no longer depends on
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 10 Feb 2004 01:55:27 +0000 (01:55 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 10 Feb 2004 01:55:27 +0000 (01:55 +0000)
the relcache, and so the notion of 'blind write' is gone.  This should
improve efficiency in bgwriter and background checkpoint processes.
Internal restructuring in md.c to remove the not-very-useful array of
MdfdVec objects --- might as well just use pointers.
Also remove the long-dead 'persistent main memory' storage manager (mm.c),
since it seems quite unlikely to ever get resurrected.

37 files changed:
src/backend/access/nbtree/nbtree.c
src/backend/access/transam/slru.c
src/backend/access/transam/xact.c
src/backend/access/transam/xlog.c
src/backend/access/transam/xlogutils.c
src/backend/bootstrap/bootstrap.c
src/backend/catalog/heap.c
src/backend/catalog/index.c
src/backend/commands/copy.c
src/backend/commands/dbcommands.c
src/backend/commands/tablecmds.c
src/backend/commands/trigger.c
src/backend/commands/user.c
src/backend/commands/vacuum.c
src/backend/commands/vacuumlazy.c
src/backend/libpq/be-fsstubs.c
src/backend/rewrite/rewriteDefine.c
src/backend/rewrite/rewriteSupport.c
src/backend/storage/buffer/bufmgr.c
src/backend/storage/buffer/localbuf.c
src/backend/storage/ipc/ipci.c
src/backend/storage/smgr/Makefile
src/backend/storage/smgr/README
src/backend/storage/smgr/md.c
src/backend/storage/smgr/mm.c [deleted file]
src/backend/storage/smgr/smgr.c
src/backend/storage/smgr/smgrtype.c
src/backend/tcop/utility.c
src/backend/utils/cache/inval.c
src/backend/utils/cache/relcache.c
src/backend/utils/init/miscinit.c
src/include/catalog/pg_database.h
src/include/storage/sinval.h
src/include/storage/smgr.h
src/include/utils/inval.h
src/include/utils/rel.h
src/include/utils/relcache.h

index 87a251915a5e0ae8a747ee24e70530bfea72dc71..fa77318ea3fbf97dd1806d5cbfc0232617552e79 100644 (file)
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.111 2004/02/06 19:36:17 wieck Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.112 2004/02/10 01:55:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -821,7 +821,9 @@ btvacuumcleanup(PG_FUNCTION_ARGS)
                        /*
                         * Do the physical truncation.
                         */
-                       new_pages = smgrtruncate(DEFAULT_SMGR, rel, new_pages);
+                       if (rel->rd_smgr == NULL)
+                               rel->rd_smgr = smgropen(rel->rd_node);
+                       new_pages = smgrtruncate(rel->rd_smgr, new_pages);
                        rel->rd_nblocks = new_pages;            /* update relcache
                                                                                                 * immediately */
                        rel->rd_targblock = InvalidBlockNumber;
index ba3054f14bbbbe52e94c2dd5c5f9541702552beb..c92f90f6ca83c70cce12aac1f335e0418fccbcfa 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.10 2004/01/28 21:02:39 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.11 2004/02/10 01:55:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,6 +19,7 @@
 #include <unistd.h>
 
 #include "access/slru.h"
+#include "storage/fd.h"
 #include "storage/lwlock.h"
 #include "miscadmin.h"
 
index d5f357bc5ffcb7475be6d3c8118fd480031ba7d1..06e152d1bba55263a3385a338b3207deafe02014 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.161 2004/01/26 22:51:55 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.162 2004/02/10 01:55:24 tgl Exp $
  *
  * NOTES
  *             Transaction aborts can now occur two ways:
 #include "executor/spi.h"
 #include "libpq/be-fsstubs.h"
 #include "miscadmin.h"
+#include "storage/fd.h"
 #include "storage/proc.h"
 #include "storage/sinval.h"
 #include "storage/smgr.h"
index fe1ecd453c5f1dd96db6195f4ffd940018382435..9056f0b454943170ed5293bbf05b8af498e9c0d0 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.133 2004/01/26 22:35:31 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.134 2004/02/10 01:55:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,6 +30,7 @@
 #include "catalog/catversion.h"
 #include "catalog/pg_control.h"
 #include "storage/bufpage.h"
+#include "storage/fd.h"
 #include "storage/lwlock.h"
 #include "storage/pmsignal.h"
 #include "storage/proc.h"
@@ -3126,7 +3127,6 @@ ShutdownXLOG(int code, Datum arg)
        MyXactMadeTempRelUpdate = false;
 
        CritSectionCount++;
-       CreateDummyCaches();
        CreateCheckPoint(true, true);
        ShutdownCLOG();
        CritSectionCount--;
index d200b7e17adb5d8afb620b51884627e87f8d9bf4..0271742ce0ae1b16c600a9637bebd5058b67da84 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.28 2003/12/14 00:34:47 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.29 2004/02/10 01:55:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -261,14 +261,12 @@ _xl_remove_hash_entry(XLogRelDesc *rdesc)
        if (hentry == NULL)
                elog(PANIC, "_xl_remove_hash_entry: file was not found in cache");
 
-       if (rdesc->reldata.rd_fd >= 0)
-               smgrclose(DEFAULT_SMGR, &(rdesc->reldata));
+       if (rdesc->reldata.rd_smgr != NULL)
+               smgrclose(rdesc->reldata.rd_smgr);
 
        memset(rdesc, 0, sizeof(XLogRelDesc));
        memset(tpgc, 0, sizeof(FormData_pg_class));
        rdesc->reldata.rd_rel = tpgc;
-
-       return;
 }
 
 static XLogRelDesc *
@@ -296,7 +294,6 @@ _xl_new_reldesc(void)
 void
 XLogInitRelationCache(void)
 {
-       CreateDummyCaches();
        _xl_init_rel_cache();
 }
 
@@ -306,8 +303,6 @@ XLogCloseRelationCache(void)
        HASH_SEQ_STATUS status;
        XLogRelCacheEntry *hentry;
 
-       DestroyDummyCaches();
-
        if (!_xlrelarr)
                return;
 
@@ -347,11 +342,18 @@ XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode)
 
                sprintf(RelationGetRelationName(&(res->reldata)), "%u", rnode.relNode);
 
-               /* unexisting DB id */
-               res->reldata.rd_lockInfo.lockRelId.dbId = RecoveryDb;
-               res->reldata.rd_lockInfo.lockRelId.relId = rnode.relNode;
                res->reldata.rd_node = rnode;
 
+               /*
+                * We set up the lockRelId in case anything tries to lock the dummy
+                * relation.  Note that this is fairly bogus since relNode may be
+                * different from the relation's OID.  It shouldn't really matter
+                * though, since we are presumably running by ourselves and can't
+                * have any lock conflicts ...
+                */
+               res->reldata.rd_lockInfo.lockRelId.dbId = rnode.tblNode;
+               res->reldata.rd_lockInfo.lockRelId.relId = rnode.relNode;
+
                hentry = (XLogRelCacheEntry *)
                        hash_search(_xlrelcache, (void *) &rnode, HASH_ENTER, &found);
 
@@ -364,9 +366,17 @@ XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode)
                hentry->rdesc = res;
 
                res->reldata.rd_targblock = InvalidBlockNumber;
-               res->reldata.rd_fd = -1;
-               res->reldata.rd_fd = smgropen(DEFAULT_SMGR, &(res->reldata),
-                                                                         true /* allow failure */ );
+               res->reldata.rd_smgr = smgropen(res->reldata.rd_node);
+               /*
+                * Create the target file if it doesn't already exist.  This lets
+                * us cope if the replay sequence contains writes to a relation
+                * that is later deleted.  (The original coding of this routine
+                * would instead return NULL, causing the writes to be suppressed.
+                * But that seems like it risks losing valuable data if the filesystem
+                * loses an inode during a crash.  Better to write the data until we
+                * are actually told to delete the file.)
+                */
+               smgrcreate(res->reldata.rd_smgr, res->reldata.rd_istemp, true);
        }
 
        res->moreRecently = &(_xlrelarr[0]);
@@ -374,8 +384,5 @@ XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode)
        _xlrelarr[0].lessRecently = res;
        res->lessRecently->moreRecently = res;
 
-       if (res->reldata.rd_fd < 0) /* file doesn't exist */
-               return (NULL);
-
        return (&(res->reldata));
 }
index 8d29134d39d01cc5209125e927a36a148ef17737..2f67061c48b036d92d520ddbe7885115a6398461 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.175 2004/01/07 18:56:25 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.176 2004/02/10 01:55:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -465,14 +465,12 @@ BootstrapMain(int argc, char *argv[])
                        break;
 
                case BS_XLOG_CHECKPOINT:
-                       CreateDummyCaches();
                        CreateCheckPoint(false, false);
                        SetSavedRedoRecPtr();           /* pass redo ptr back to
                                                                                 * postmaster */
                        proc_exit(0);           /* done */
 
                case BS_XLOG_BGWRITER:
-                       CreateDummyCaches();
                        BufferBackgroundWriter();
                        proc_exit(0);           /* done */
 
index 14c3745e5e91d282bd015f64b723f14c5c4caac7..905aa5b0b222f2efcfdc08204976ce1ebb0d2bce 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.257 2003/12/28 21:57:36 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.258 2004/02/10 01:55:24 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -298,9 +298,9 @@ heap_create(const char *relname,
 void
 heap_storage_create(Relation rel)
 {
-       Assert(rel->rd_fd < 0);
-       rel->rd_fd = smgrcreate(DEFAULT_SMGR, rel);
-       Assert(rel->rd_fd >= 0);
+       Assert(rel->rd_smgr == NULL);
+       rel->rd_smgr = smgropen(rel->rd_node);
+       smgrcreate(rel->rd_smgr, rel->rd_istemp, false);
 }
 
 /* ----------------------------------------------------------------
@@ -1210,7 +1210,12 @@ heap_drop_with_catalog(Oid rid)
         */
        if (rel->rd_rel->relkind != RELKIND_VIEW &&
                rel->rd_rel->relkind != RELKIND_COMPOSITE_TYPE)
-               smgrunlink(DEFAULT_SMGR, rel);
+       {
+               if (rel->rd_smgr == NULL)
+                       rel->rd_smgr = smgropen(rel->rd_node);
+               smgrscheduleunlink(rel->rd_smgr, rel->rd_istemp);
+               rel->rd_smgr = NULL;
+       }
 
        /*
         * Close relcache entry, but *keep* AccessExclusiveLock on the
@@ -1706,7 +1711,7 @@ SetRelationNumChecks(Relation rel, int numchecks)
        else
        {
                /* Skip the disk update, but force relcache inval anyway */
-               CacheInvalidateRelcache(RelationGetRelid(rel));
+               CacheInvalidateRelcache(rel);
        }
 
        heap_freetuple(reltup);
@@ -1943,7 +1948,9 @@ RelationTruncateIndexes(Oid heapId)
                DropRelationBuffers(currentIndex);
 
                /* Now truncate the actual data and set blocks to zero */
-               smgrtruncate(DEFAULT_SMGR, currentIndex, 0);
+               if (currentIndex->rd_smgr == NULL)
+                       currentIndex->rd_smgr = smgropen(currentIndex->rd_node);
+               smgrtruncate(currentIndex->rd_smgr, 0);
                currentIndex->rd_nblocks = 0;
                currentIndex->rd_targblock = InvalidBlockNumber;
 
@@ -1990,7 +1997,9 @@ heap_truncate(Oid rid)
        DropRelationBuffers(rel);
 
        /* Now truncate the actual data and set blocks to zero */
-       smgrtruncate(DEFAULT_SMGR, rel, 0);
+       if (rel->rd_smgr == NULL)
+               rel->rd_smgr = smgropen(rel->rd_node);
+       smgrtruncate(rel->rd_smgr, 0);
        rel->rd_nblocks = 0;
        rel->rd_targblock = InvalidBlockNumber;
 
index 4180526301ac50cd73180e22b62777729afef95e..9c92f21740922fbfed4c6be69f4ce5e5617f35a9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.226 2004/01/28 21:02:39 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.227 2004/02/10 01:55:24 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -808,7 +808,11 @@ index_drop(Oid indexId)
        if (i < 0)
                elog(ERROR, "FlushRelationBuffers returned %d", i);
 
-       smgrunlink(DEFAULT_SMGR, userIndexRelation);
+       if (userIndexRelation->rd_smgr == NULL)
+               userIndexRelation->rd_smgr = smgropen(userIndexRelation->rd_node);
+       smgrscheduleunlink(userIndexRelation->rd_smgr,
+                                          userIndexRelation->rd_istemp);
+       userIndexRelation->rd_smgr = NULL;
 
        /*
         * We are presently too lazy to attempt to compute the new correct
@@ -818,7 +822,7 @@ index_drop(Oid indexId)
         * owning relation to ensure other backends update their relcache
         * lists of indexes.
         */
-       CacheInvalidateRelcache(heapId);
+       CacheInvalidateRelcache(userHeapRelation);
 
        /*
         * Close rels, but keep locks
@@ -1057,7 +1061,7 @@ setRelhasindex(Oid relid, bool hasindex, bool isprimary, Oid reltoastidxid)
        else
        {
                /* no need to change tuple, but force relcache rebuild anyway */
-               CacheInvalidateRelcache(relid);
+               CacheInvalidateRelcacheByTuple(tuple);
        }
 
        if (!pg_class_scan)
@@ -1077,10 +1081,11 @@ void
 setNewRelfilenode(Relation relation)
 {
        Oid                     newrelfilenode;
+       RelFileNode newrnode;
+       SMgrRelation srel;
        Relation        pg_class;
        HeapTuple       tuple;
        Form_pg_class rd_rel;
-       RelationData workrel;
 
        /* Can't change relfilenode for nailed tables (indexes ok though) */
        Assert(!relation->rd_isnailed ||
@@ -1107,14 +1112,18 @@ setNewRelfilenode(Relation relation)
 
        /* create another storage file. Is it a little ugly ? */
        /* NOTE: any conflict in relfilenode value will be caught here */
-       memcpy((char *) &workrel, relation, sizeof(RelationData));
-       workrel.rd_fd = -1;
-       workrel.rd_node.relNode = newrelfilenode;
-       heap_storage_create(&workrel);
-       smgrclose(DEFAULT_SMGR, &workrel);
+       newrnode = relation->rd_node;
+       newrnode.relNode = newrelfilenode;
+
+       srel = smgropen(newrnode);
+       smgrcreate(srel, relation->rd_istemp, false);
+       smgrclose(srel);
 
        /* schedule unlinking old relfilenode */
-       smgrunlink(DEFAULT_SMGR, relation);
+       if (relation->rd_smgr == NULL)
+               relation->rd_smgr = smgropen(relation->rd_node);
+       smgrscheduleunlink(relation->rd_smgr, relation->rd_istemp);
+       relation->rd_smgr = NULL;
 
        /* update the pg_class row */
        rd_rel->relfilenode = newrelfilenode;
@@ -1672,7 +1681,9 @@ reindex_index(Oid indexId)
                DropRelationBuffers(iRel);
 
                /* Now truncate the actual data and set blocks to zero */
-               smgrtruncate(DEFAULT_SMGR, iRel, 0);
+               if (iRel->rd_smgr == NULL)
+                       iRel->rd_smgr = smgropen(iRel->rd_node);
+               smgrtruncate(iRel->rd_smgr, 0);
                iRel->rd_nblocks = 0;
                iRel->rd_targblock = InvalidBlockNumber;
        }
index 66850d32d56229523972129e428d14b6b9b3d96f..7af8200e0637a1591c18df221731c0c190d24780 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.217 2004/01/28 21:02:39 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.218 2004/02/10 01:55:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,6 +40,7 @@
 #include "parser/parse_coerce.h"
 #include "parser/parse_relation.h"
 #include "rewrite/rewriteHandler.h"
+#include "storage/fd.h"
 #include "tcop/pquery.h"
 #include "tcop/tcopprot.h"
 #include "utils/acl.h"
index 2b8fdb9a2d4abd2717c94a6c15ac04a7883674cc..85f49537efce589c7722f5d7491e455b232ce2dd 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.130 2004/01/07 18:56:25 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.131 2004/02/10 01:55:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,6 +30,7 @@
 #include "commands/comment.h"
 #include "commands/dbcommands.h"
 #include "miscadmin.h"
+#include "storage/fd.h"
 #include "storage/freespace.h"
 #include "storage/sinval.h"
 #include "utils/acl.h"
index 809f425bc656a72b71a67ee52e283a6efb598aea..6fadd0d4e15f99ea9e9ffd7bf8a615593ecdf870 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.97 2004/01/28 21:02:39 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.98 2004/02/10 01:55:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1010,7 +1010,7 @@ setRelhassubclassInRelation(Oid relationId, bool relhassubclass)
        else
        {
                /* no need to change tuple, but force relcache rebuild anyway */
-               CacheInvalidateRelcache(relationId);
+               CacheInvalidateRelcacheByTuple(tuple);
        }
 
        heap_freetuple(tuple);
index 34cfc4d10e3d29f6a6555bda26dff9a760aebe2b..bddf3f5ad68b7e97c6de952cc21ce4aca587d74d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.163 2003/11/29 19:51:47 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.164 2004/02/10 01:55:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -691,7 +691,7 @@ renametrig(Oid relid,
                 * relcache entries.  (Ideally this should happen
                 * automatically...)
                 */
-               CacheInvalidateRelcache(relid);
+               CacheInvalidateRelcache(targetrel);
        }
        else
        {
index d2d1a3c7a950a59ac5616ab744b79dca786573ee..9352aeb0ec03784414a0643acfe5c354f3416ab8 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.136 2004/02/02 17:21:07 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/user.c,v 1.137 2004/02/10 01:55:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,7 @@
 #include "commands/user.h"
 #include "libpq/crypt.h"
 #include "miscadmin.h"
+#include "storage/fd.h"
 #include "storage/pmsignal.h"
 #include "utils/acl.h"
 #include "utils/array.h"
index dae8c3f37cddfda321ae03623996c39acbd58f7a..29a2df1ef1d4aee68a01632f9f402d72672d2546 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.271 2004/01/07 18:56:25 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.272 2004/02/10 01:55:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2513,7 +2513,9 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
        /* truncate relation, if needed */
        if (blkno < nblocks)
        {
-               blkno = smgrtruncate(DEFAULT_SMGR, onerel, blkno);
+               if (onerel->rd_smgr == NULL)
+                       onerel->rd_smgr = smgropen(onerel->rd_node);
+               blkno = smgrtruncate(onerel->rd_smgr, blkno);
                onerel->rd_nblocks = blkno;             /* update relcache immediately */
                onerel->rd_targblock = InvalidBlockNumber;
                vacrelstats->rel_pages = blkno; /* set new number of blocks */
@@ -2582,7 +2584,9 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
                                (errmsg("\"%s\": truncated %u to %u pages",
                                                RelationGetRelationName(onerel),
                                                vacrelstats->rel_pages, relblocks)));
-               relblocks = smgrtruncate(DEFAULT_SMGR, onerel, relblocks);
+               if (onerel->rd_smgr == NULL)
+                       onerel->rd_smgr = smgropen(onerel->rd_node);
+               relblocks = smgrtruncate(onerel->rd_smgr, relblocks);
                onerel->rd_nblocks = relblocks; /* update relcache immediately */
                onerel->rd_targblock = InvalidBlockNumber;
                vacrelstats->rel_pages = relblocks;             /* set new number of
index c271152877054a24d2c94033ec0d75fc7b559a8f..17f91efef7065130b6cf8f573505bf695ea579a3 100644 (file)
@@ -31,7 +31,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.35 2004/02/06 19:36:17 wieck Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/vacuumlazy.c,v 1.36 2004/02/10 01:55:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -148,9 +148,8 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
        vac_open_indexes(onerel, &nindexes, &Irel);
        hasindex = (nindexes > 0);
 
-       /* Turn on vacuum cost accounting */
-       if (VacuumCostNaptime > 0)
-               VacuumCostActive = true;
+       /* Turn vacuum cost accounting on or off */
+       VacuumCostActive = (VacuumCostNaptime > 0);
        VacuumCostBalance = 0;
 
        /* Do the vacuuming */
@@ -784,7 +783,9 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats)
        /*
         * Do the physical truncation.
         */
-       new_rel_pages = smgrtruncate(DEFAULT_SMGR, onerel, new_rel_pages);
+       if (onerel->rd_smgr == NULL)
+               onerel->rd_smgr = smgropen(onerel->rd_node);
+       new_rel_pages = smgrtruncate(onerel->rd_smgr, new_rel_pages);
        onerel->rd_nblocks = new_rel_pages; /* update relcache immediately */
        onerel->rd_targblock = InvalidBlockNumber;
        vacrelstats->rel_pages = new_rel_pages;         /* save new number of
index aa8ba2f884abb86a6253de9687046f34db8e43f0..ed19e76db2ccd3d3ea1ce4b4e4461ea41aaf7bc6 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/libpq/be-fsstubs.c,v 1.69 2003/11/29 19:51:49 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/libpq/be-fsstubs.c,v 1.70 2004/02/10 01:55:25 tgl Exp $
  *
  * NOTES
  *       This should be moved to a more appropriate place.  It is here
@@ -41,6 +41,7 @@
 #include "libpq/be-fsstubs.h"
 #include "libpq/libpq-fs.h"
 #include "miscadmin.h"
+#include "storage/fd.h"
 #include "storage/large_object.h"
 #include "utils/memutils.h"
 
index f1cbe96fd2a2c206a3356f992f496b070e7f1f25..995afe5509e850c9de2aa48dd265d96e7d23f440 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.92 2004/01/14 23:01:55 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/rewrite/rewriteDefine.c,v 1.93 2004/02/10 01:55:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -480,7 +480,12 @@ DefineQueryRewrite(RuleStmt *stmt)
         * XXX what about getting rid of its TOAST table?  For now, we don't.
         */
        if (RelisBecomingView)
-               smgrunlink(DEFAULT_SMGR, event_relation);
+       {
+               if (event_relation->rd_smgr == NULL)
+                       event_relation->rd_smgr = smgropen(event_relation->rd_node);
+               smgrscheduleunlink(event_relation->rd_smgr, event_relation->rd_istemp);
+               event_relation->rd_smgr = NULL;
+       }
 
        /* Close rel, but keep lock till commit... */
        heap_close(event_relation, NoLock);
index 54fdcfcddeb1dd646be727defb2a5abb4a906fbb..6e01de4b5cb293f90f943f771f0698bcebc9f594 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/rewrite/rewriteSupport.c,v 1.57 2003/11/29 19:51:55 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/rewrite/rewriteSupport.c,v 1.58 2004/02/10 01:55:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -84,7 +84,7 @@ SetRelationRuleStatus(Oid relationId, bool relHasRules,
        else
        {
                /* no need to change tuple, but force relcache rebuild anyway */
-               CacheInvalidateRelcache(relationId);
+               CacheInvalidateRelcacheByTuple(tuple);
        }
 
        heap_freetuple(tuple);
index b927b5ea5e7ed164e7b626d965e0095be56248a3..203e03ab059b094aca730f3df3fa0d2c569c7952 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.156 2004/02/06 19:36:18 wieck Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.157 2004/02/10 01:55:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -85,7 +85,7 @@ static Buffer ReadBufferInternal(Relation reln, BlockNumber blockNum,
                                   bool bufferLockHeld);
 static BufferDesc *BufferAlloc(Relation reln, BlockNumber blockNum,
                        bool *foundPtr);
-static bool BufferReplace(BufferDesc *bufHdr);
+static void BufferReplace(BufferDesc *bufHdr);
 
 #ifdef NOT_USED
 void           PrintBufferDescs(void);
@@ -127,7 +127,6 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
                                   bool bufferLockHeld)
 {
        BufferDesc *bufHdr;
-       int                     status;
        bool            found;
        bool            isExtend;
        bool            isLocalBuf;
@@ -135,6 +134,10 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
        isExtend = (blockNum == P_NEW);
        isLocalBuf = reln->rd_istemp;
 
+       /* Open it at the smgr level if not already done */
+       if (reln->rd_smgr == NULL)
+               reln->rd_smgr = smgropen(reln->rd_node);
+
        if (isLocalBuf)
        {
                ReadLocalBufferCount++;
@@ -160,7 +163,7 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
                if (isExtend)
                {
                        /* must be sure we have accurate file length! */
-                       blockNum = reln->rd_nblocks = smgrnblocks(DEFAULT_SMGR, reln);
+                       blockNum = reln->rd_nblocks = smgrnblocks(reln->rd_smgr);
                        reln->rd_nblocks++;
                }
 
@@ -207,23 +210,19 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
        }
 
        /*
-        * if we have gotten to this point, the reln pointer must be ok and
-        * the relation file must be open.
+        * if we have gotten to this point, the relation must be open in the smgr.
         */
        if (isExtend)
        {
                /* new buffers are zero-filled */
                MemSet((char *) MAKE_PTR(bufHdr->data), 0, BLCKSZ);
-               status = smgrextend(DEFAULT_SMGR, reln, blockNum,
-                                                       (char *) MAKE_PTR(bufHdr->data));
+               smgrextend(reln->rd_smgr, blockNum, (char *) MAKE_PTR(bufHdr->data));
        }
        else
        {
-               status = smgrread(DEFAULT_SMGR, reln, blockNum,
-                                                 (char *) MAKE_PTR(bufHdr->data));
+               smgrread(reln->rd_smgr, blockNum, (char *) MAKE_PTR(bufHdr->data));
                /* check for garbage data */
-               if (status == SM_SUCCESS &&
-                       !PageHeaderIsValid((PageHeader) MAKE_PTR(bufHdr->data)))
+               if (!PageHeaderIsValid((PageHeader) MAKE_PTR(bufHdr->data)))
                {
                        /*
                         * During WAL recovery, the first access to any data page should
@@ -250,47 +249,20 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
        if (isLocalBuf)
        {
                /* No shared buffer state to update... */
-               if (status == SM_FAIL)
-               {
-                       bufHdr->flags |= BM_IO_ERROR;
-                       return InvalidBuffer;
-               }
                return BufferDescriptorGetBuffer(bufHdr);
        }
 
        /* lock buffer manager again to update IO IN PROGRESS */
        LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
 
-       if (status == SM_FAIL)
-       {
-               /* IO Failed.  cleanup the data structures and go home */
-               StrategyInvalidateBuffer(bufHdr);
-
-               /* remember that BufferAlloc() pinned the buffer */
-               UnpinBuffer(bufHdr);
-
-               /*
-                * Have to reset the flag so that anyone waiting for the buffer
-                * can tell that the contents are invalid.
-                */
-               bufHdr->flags |= BM_IO_ERROR;
-               bufHdr->flags &= ~BM_IO_IN_PROGRESS;
-       }
-       else
-       {
-               /* IO Succeeded.  clear the flags, finish buffer update */
-
-               bufHdr->flags &= ~(BM_IO_ERROR | BM_IO_IN_PROGRESS);
-       }
+       /* IO Succeeded.  clear the flags, finish buffer update */
+       bufHdr->flags &= ~(BM_IO_ERROR | BM_IO_IN_PROGRESS);
 
        /* If anyone was waiting for IO to complete, wake them up now */
        TerminateBufferIO(bufHdr);
 
        LWLockRelease(BufMgrLock);
 
-       if (status == SM_FAIL)
-               return InvalidBuffer;
-
        return BufferDescriptorGetBuffer(bufHdr);
 }
 
@@ -391,8 +363,6 @@ BufferAlloc(Relation reln,
 
                if (buf->flags & BM_DIRTY || buf->cntxDirty)
                {
-                       bool    replace_ok;
-
                        /*
                         * skip write error buffers
                         */
@@ -425,39 +395,21 @@ BufferAlloc(Relation reln,
                         * Write the buffer out, being careful to release BufMgrLock
                         * before starting the I/O.
                         */
-                       replace_ok = BufferReplace(buf);
+                       BufferReplace(buf);
 
-                       if (replace_ok == false)
+                       /*
+                        * BM_JUST_DIRTIED cleared by BufferReplace and shouldn't
+                        * be set by anyone.            - vadim 01/17/97
+                        */
+                       if (buf->flags & BM_JUST_DIRTIED)
                        {
-                               ereport(WARNING,
-                                               (errcode(ERRCODE_IO_ERROR),
-                                                errmsg("could not write block %u of %u/%u",
-                                                               buf->tag.blockNum,
-                                                               buf->tag.rnode.tblNode,
-                                                               buf->tag.rnode.relNode)));
-                               inProgress = FALSE;
-                               buf->flags |= BM_IO_ERROR;
-                               buf->flags &= ~BM_IO_IN_PROGRESS;
-                               TerminateBufferIO(buf);
-                               UnpinBuffer(buf);
-                               buf = NULL;
+                               elog(PANIC, "content of block %u of %u/%u changed while flushing",
+                                        buf->tag.blockNum,
+                                        buf->tag.rnode.tblNode, buf->tag.rnode.relNode);
                        }
-                       else
-                       {
-                               /*
-                                * BM_JUST_DIRTIED cleared by BufferReplace and shouldn't
-                                * be set by anyone.            - vadim 01/17/97
-                                */
-                               if (buf->flags & BM_JUST_DIRTIED)
-                               {
-                                       elog(PANIC, "content of block %u of %u/%u changed while flushing",
-                                                buf->tag.blockNum,
-                                                buf->tag.rnode.tblNode, buf->tag.rnode.relNode);
-                               }
 
-                               buf->flags &= ~BM_DIRTY;
-                               buf->cntxDirty = false;
-                       }
+                       buf->flags &= ~BM_DIRTY;
+                       buf->cntxDirty = false;
 
                        /*
                         * Somebody could have pinned the buffer while we were doing
@@ -721,10 +673,8 @@ BufferSync(int percent, int maxpages)
        for (i = 0; i < num_buffer_dirty; i++)
        {
                Buffer          buffer;
-               int                     status;
-               RelFileNode rnode;
                XLogRecPtr      recptr;
-               Relation        reln;
+               SMgrRelation reln;
 
                LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
 
@@ -775,15 +725,9 @@ BufferSync(int percent, int maxpages)
                StartBufferIO(bufHdr, false);   /* output IO start */
 
                buffer = BufferDescriptorGetBuffer(bufHdr);
-               rnode = bufHdr->tag.rnode;
 
                LWLockRelease(BufMgrLock);
 
-               /*
-                * Try to find relation for buffer
-                */
-               reln = RelationNodeCacheGetRelation(rnode);
-
                /*
                 * Protect buffer content against concurrent update
                 */
@@ -805,27 +749,13 @@ BufferSync(int percent, int maxpages)
                bufHdr->flags &= ~BM_JUST_DIRTIED;
                LWLockRelease(BufMgrLock);
 
-               if (reln == NULL)
-               {
-                       status = smgrblindwrt(DEFAULT_SMGR,
-                                                                 bufHdr->tag.rnode,
-                                                                 bufHdr->tag.blockNum,
-                                                                 (char *) MAKE_PTR(bufHdr->data));
-               }
-               else
-               {
-                       status = smgrwrite(DEFAULT_SMGR, reln,
-                                                          bufHdr->tag.blockNum,
-                                                          (char *) MAKE_PTR(bufHdr->data));
-               }
+               /* Find smgr relation for buffer */
+               reln = smgropen(bufHdr->tag.rnode);
 
-               if (status == SM_FAIL)  /* disk failure ?! */
-                       ereport(PANIC,
-                                       (errcode(ERRCODE_IO_ERROR),
-                                        errmsg("could not write block %u of %u/%u",
-                                                       bufHdr->tag.blockNum,
-                                                       bufHdr->tag.rnode.tblNode,
-                                                       bufHdr->tag.rnode.relNode)));
+               /* And write... */
+               smgrwrite(reln,
+                                 bufHdr->tag.blockNum,
+                                 (char *) MAKE_PTR(bufHdr->data));
 
                /*
                 * Note that it's safe to change cntxDirty here because of we
@@ -853,10 +783,6 @@ BufferSync(int percent, int maxpages)
                        bufHdr->flags &= ~BM_DIRTY;
                UnpinBuffer(bufHdr);
                LWLockRelease(BufMgrLock);
-
-               /* drop refcnt obtained by RelationNodeCacheGetRelation */
-               if (reln != NULL)
-                       RelationDecrementReferenceCount(reln);
        }
 
        pfree(buffer_dirty);
@@ -1026,12 +952,22 @@ BufferBackgroundWriter(void)
                n = BufferSync(BgWriterPercent, BgWriterMaxpages);
 
                /*
-                * Whatever signal is sent to us, let's just die galantly. If
+                * Whatever signal is sent to us, let's just die gallantly. If
                 * it wasn't meant that way, the postmaster will reincarnate us.
                 */
                if (InterruptPending)
                        return;
 
+               /*
+                * Whenever we have nothing to do, close all smgr files.  This
+                * is so we won't hang onto smgr references to deleted files
+                * indefinitely.  XXX this is a bogus, temporary solution.  'Twould
+                * be much better to do this once per checkpoint, but the bgwriter
+                * doesn't yet know anything about checkpoints.
+                */
+               if (n == 0)
+                       smgrcloseall();
+
                /*
                 * Nap for the configured time or sleep for 10 seconds if
                 * there was nothing to do at all.
@@ -1073,17 +1009,15 @@ BufferGetBlockNumber(Buffer buffer)
 /*
  * BufferReplace
  *
- * Write out the buffer corresponding to 'bufHdr'. Returns 'true' if
- * the buffer was successfully written out, 'false' otherwise.
+ * Write out the buffer corresponding to 'bufHdr'.
  *
  * BufMgrLock must be held at entry, and the buffer must be pinned.
  */
-static bool
+static void
 BufferReplace(BufferDesc *bufHdr)
 {
-       Relation        reln;
+       SMgrRelation reln;
        XLogRecPtr      recptr;
-       int                     status;
        ErrorContextCallback errcontext;
 
        /* To check if block content changed while flushing. - vadim 01/17/97 */
@@ -1104,36 +1038,20 @@ BufferReplace(BufferDesc *bufHdr)
        recptr = BufferGetLSN(bufHdr);
        XLogFlush(recptr);
 
-       reln = RelationNodeCacheGetRelation(bufHdr->tag.rnode);
+       /* Find smgr relation for buffer */
+       reln = smgropen(bufHdr->tag.rnode);
 
-       if (reln != NULL)
-       {
-               status = smgrwrite(DEFAULT_SMGR, reln,
-                                                  bufHdr->tag.blockNum,
-                                                  (char *) MAKE_PTR(bufHdr->data));
-       }
-       else
-       {
-               status = smgrblindwrt(DEFAULT_SMGR, bufHdr->tag.rnode,
-                                                         bufHdr->tag.blockNum,
-                                                         (char *) MAKE_PTR(bufHdr->data));
-       }
-
-       /* drop relcache refcnt incremented by RelationNodeCacheGetRelation */
-       if (reln != NULL)
-               RelationDecrementReferenceCount(reln);
+       /* And write... */
+       smgrwrite(reln,
+                         bufHdr->tag.blockNum,
+                         (char *) MAKE_PTR(bufHdr->data));
 
        /* Pop the error context stack */
        error_context_stack = errcontext.previous;
 
        LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
 
-       if (status == SM_FAIL)
-               return false;
-
        BufferFlushCount++;
-
-       return true;
 }
 
 /*
@@ -1151,12 +1069,17 @@ RelationGetNumberOfBlocks(Relation relation)
         *
         * Don't call smgr on a view or a composite type, either.
         */
-       if (relation->rd_rel->relkind == RELKIND_VIEW)
-               relation->rd_nblocks = 0;
-       else if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+       if (relation->rd_rel->relkind == RELKIND_VIEW ||
+               relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
                relation->rd_nblocks = 0;
        else if (!relation->rd_isnew && !relation->rd_istemp)
-               relation->rd_nblocks = smgrnblocks(DEFAULT_SMGR, relation);
+       {
+               /* Open it at the smgr level if not already done */
+               if (relation->rd_smgr == NULL)
+                       relation->rd_smgr = smgropen(relation->rd_node);
+
+               relation->rd_nblocks = smgrnblocks(relation->rd_smgr);
+       }
 
        return relation->rd_nblocks;
 }
@@ -1172,12 +1095,17 @@ RelationGetNumberOfBlocks(Relation relation)
 void
 RelationUpdateNumberOfBlocks(Relation relation)
 {
-       if (relation->rd_rel->relkind == RELKIND_VIEW)
-               relation->rd_nblocks = 0;
-       else if (relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+       if (relation->rd_rel->relkind == RELKIND_VIEW ||
+               relation->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
                relation->rd_nblocks = 0;
        else
-               relation->rd_nblocks = smgrnblocks(DEFAULT_SMGR, relation);
+       {
+               /* Open it at the smgr level if not already done */
+               if (relation->rd_smgr == NULL)
+                       relation->rd_smgr = smgropen(relation->rd_node);
+
+               relation->rd_nblocks = smgrnblocks(relation->rd_smgr);
+       }
 }
 
 /* ---------------------------------------------------------------------
@@ -1465,7 +1393,6 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
        int                     i;
        BufferDesc *bufHdr;
        XLogRecPtr      recptr;
-       int                     status;
        ErrorContextCallback errcontext;
 
        /* Setup error traceback support for ereport() */
@@ -1484,17 +1411,13 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
                        {
                                if (bufHdr->flags & BM_DIRTY || bufHdr->cntxDirty)
                                {
-                                       status = smgrwrite(DEFAULT_SMGR, rel,
-                                                                          bufHdr->tag.blockNum,
-                                                                          (char *) MAKE_PTR(bufHdr->data));
-                                       if (status == SM_FAIL)
-                                       {
-                                               error_context_stack = errcontext.previous;
-                                               elog(WARNING, "FlushRelationBuffers(\"%s\" (local), %u): block %u is dirty, could not flush it",
-                                                        RelationGetRelationName(rel), firstDelBlock,
-                                                        bufHdr->tag.blockNum);
-                                               return (-1);
-                                       }
+                                       /* Open it at the smgr level if not already done */
+                                       if (rel->rd_smgr == NULL)
+                                               rel->rd_smgr = smgropen(rel->rd_node);
+
+                                       smgrwrite(rel->rd_smgr,
+                                                         bufHdr->tag.blockNum,
+                                                         (char *) MAKE_PTR(bufHdr->data));
                                        bufHdr->flags &= ~(BM_DIRTY | BM_JUST_DIRTIED);
                                        bufHdr->cntxDirty = false;
                                }
@@ -1553,17 +1476,13 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
 
                                        LWLockRelease(BufMgrLock);
 
-                                       status = smgrwrite(DEFAULT_SMGR, rel,
-                                                                          bufHdr->tag.blockNum,
-                                                                          (char *) MAKE_PTR(bufHdr->data));
+                                       /* Open it at the smgr level if not already done */
+                                       if (rel->rd_smgr == NULL)
+                                               rel->rd_smgr = smgropen(rel->rd_node);
 
-                                       if (status == SM_FAIL)          /* disk failure ?! */
-                                               ereport(PANIC,
-                                                               (errcode(ERRCODE_IO_ERROR),
-                                                         errmsg("could not write block %u of %u/%u",
-                                                                        bufHdr->tag.blockNum,
-                                                                        bufHdr->tag.rnode.tblNode,
-                                                                        bufHdr->tag.rnode.relNode)));
+                                       smgrwrite(rel->rd_smgr,
+                                                         bufHdr->tag.blockNum,
+                                                         (char *) MAKE_PTR(bufHdr->data));
 
                                        BufferFlushCount++;
 
@@ -2046,7 +1965,11 @@ AbortBufferIO(void)
                LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
                Assert(buf->flags & BM_IO_IN_PROGRESS);
                if (IsForInput)
+               {
                        Assert(!(buf->flags & BM_DIRTY) && !(buf->cntxDirty));
+                       /* Don't think that buffer is valid */
+                       StrategyInvalidateBuffer(buf);
+               }
                else
                {
                        Assert(buf->flags & BM_DIRTY || buf->cntxDirty);
index 01c8303928055e49a61bd38a1b983e701b708998..bcbedc9c6517a762cce4c437d80b32f9dd5e4d8b 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.51 2004/01/07 18:56:27 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.52 2004/02/10 01:55:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -90,24 +90,15 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
         */
        if (bufHdr->flags & BM_DIRTY || bufHdr->cntxDirty)
        {
-               Relation        bufrel = RelationNodeCacheGetRelation(bufHdr->tag.rnode);
+               SMgrRelation reln;
 
-               /* flush this page */
-               if (bufrel == NULL)
-               {
-                       smgrblindwrt(DEFAULT_SMGR,
-                                                bufHdr->tag.rnode,
-                                                bufHdr->tag.blockNum,
-                                                (char *) MAKE_PTR(bufHdr->data));
-               }
-               else
-               {
-                       smgrwrite(DEFAULT_SMGR, bufrel,
-                                         bufHdr->tag.blockNum,
-                                         (char *) MAKE_PTR(bufHdr->data));
-                       /* drop refcount incremented by RelationNodeCacheGetRelation */
-                       RelationDecrementReferenceCount(bufrel);
-               }
+               /* Find smgr relation for buffer */
+               reln = smgropen(bufHdr->tag.rnode);
+
+               /* And write... */
+               smgrwrite(reln,
+                                 bufHdr->tag.blockNum,
+                                 (char *) MAKE_PTR(bufHdr->data));
 
                LocalBufferFlushCount++;
        }
@@ -143,9 +134,6 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
 
        /*
         * it's all ours now.
-        *
-        * We need not in tblNode currently but will in future I think, when
-        * we'll give up rel->rd_fd to fmgr cache.
         */
        bufHdr->tag.rnode = reln->rd_node;
        bufHdr->tag.blockNum = blockNum;
index 7de7d85e74d6e87a345634c1f6a9520eccb4bec9..f95b1b3441057d6d70526f73291061d89b5ec02b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.63 2004/01/26 22:59:53 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.64 2004/02/10 01:55:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -65,9 +65,6 @@ CreateSharedMemoryAndSemaphores(bool makePrivate,
        size += FreeSpaceShmemSize();
 #ifdef EXEC_BACKEND
        size += ShmemBackendArraySize();
-#endif
-#ifdef STABLE_MEMORY_STORAGE
-       size += MMShmemSize();
 #endif
        size += 100000;
        /* might as well round it off to a multiple of a typical page size */
index 7c2a0f62b2af598e12297c87cff591c749d3f6b8..71695f9a749cb924b2c9a4261e629742970f33e0 100644 (file)
@@ -4,7 +4,7 @@
 #    Makefile for storage/smgr
 #
 # IDENTIFICATION
-#    $PostgreSQL: pgsql/src/backend/storage/smgr/Makefile,v 1.14 2003/11/29 19:51:57 pgsql Exp $
+#    $PostgreSQL: pgsql/src/backend/storage/smgr/Makefile,v 1.15 2004/02/10 01:55:26 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -12,7 +12,7 @@ subdir = src/backend/storage/smgr
 top_builddir = ../../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = md.o mm.o smgr.o smgrtype.o
+OBJS = md.o smgr.o smgrtype.o
 
 all: SUBSYS.o
 
index 606431f926fd9e49b17fcd5b0291a4b164e82145..124d5bcdffc2086bd26cb4bcfdfc321d89edd0a3 100644 (file)
@@ -1,40 +1,31 @@
-# $PostgreSQL: pgsql/src/backend/storage/smgr/README,v 1.2 2003/11/29 19:51:57 pgsql Exp $
+# $PostgreSQL: pgsql/src/backend/storage/smgr/README,v 1.3 2004/02/10 01:55:26 tgl Exp $
 
-This directory contains the code that supports the Postgres storage manager
-switch and all of the installed storage managers.  In released systems,
-the only supported storage manager is the magnetic disk manager.  At UC
-Berkeley, the Sony WORM optical disk jukebox and persistent main memory are
-also supported.
+In the original Berkeley Postgres system, there were several storage managers,
+of which only the "magnetic disk" manager remains.  (At Berkeley there were
+also managers for the Sony WORM optical disk jukebox and persistent main
+memory, but these were never supported in any externally released Postgres,
+nor in any version of PostgreSQL.)  However, we retain the notion of a storage
+manager switch in case anyone wants to reintroduce other kinds of storage
+managers.
 
-As of Postgres Release 3.0, every relation in the system is tagged with the
-storage manager on which it resides.  The storage manager switch code turns
-what used to by filesystem operations into operations on the correct store,
-for any given relation.
+In Berkeley Postgres each relation was tagged with the ID of the storage
+manager to use for it.  This is gone.  It would be more reasonable to
+associate storage managers with tablespaces (a feature not present as this
+text is being written, but one likely to emerge soon).
 
 The files in this directory, and their contents, are
 
     smgrtype.c Storage manager type -- maps string names to storage manager
                IDs and provides simple comparison operators.  This is the
                regproc support for type 'smgr' in the system catalogs.
+               (This is vestigial since no columns of type smgr exist
+               in the catalogs anymore.)
 
     smgr.c     The storage manager switch dispatch code.  The routines in
                this file call the appropriate storage manager to do hardware
-               accesses requested by the backend.
+               accesses requested by the backend.  smgr.c also manages the
+               file handle cache (SMgrRelation table).
 
     md.c       The magnetic disk storage manager.
 
-    mm.c       The persistent main memory storage manager (#undef'ed in
-               tmp/c.h for all distributed systems).
-
-    sj.c       The sony jukebox storage manager and cache management code
-               (#undef'ed in tmp/c.h for all distributed systems).  The
-               routines in this file allocate extents, maintain block
-               maps, and guarantee the persistence and coherency of a cache
-               of jukebox blocks on magnetic disk.
-
-    pgjb.c     The postgres jukebox interface routines.  The routines here
-               handle exclusion on the physical device and translate requests
-               from the storage manager code (sj.c) into jbaccess calls.
-
-    jbaccess.c Access code for the physical Sony jukebox device.  This code
-               was swiped from Andy McFadden's jblib.a code at UC Berkeley.
+Note that md.c in turn relies on src/backend/storage/file/fd.c.
index 0405c2849a0b8d201edbec9c4e0cda91e46f2927..58629218a3ceaecb3b2a760d1cd2d03e90615036 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/smgr/md.c,v 1.101 2004/01/07 18:56:27 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/smgr/md.c,v 1.102 2004/02/10 01:55:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "catalog/catalog.h"
 #include "miscadmin.h"
+#include "storage/fd.h"
 #include "storage/smgr.h"
-#include "utils/inval.h"
 #include "utils/memutils.h"
 
+
 /*
  *     The magnetic disk storage manager keeps track of open file
  *     descriptors in its own descriptor pool.  This is done to make it
  *     easier to support relations that are larger than the operating
- *     system's file size limit (often 2GBytes).  In order to do that, we
+ *     system's file size limit (often 2GBytes).  In order to do that,
  *     we break relations up into chunks of < 2GBytes and store one chunk
  *     in each of several files that represent the relation.  See the
  *     BLCKSZ and RELSEG_SIZE configuration constants in
- *     include/pg_config.h.
+ *     include/pg_config.h.  All chunks except the last MUST have size exactly
+ *     equal to RELSEG_SIZE blocks --- see mdnblocks() and mdtruncate().
  *
- *     The file descriptor stored in the relation cache (see RelationGetFile())
- *     is actually an index into the Md_fdvec array.  -1 indicates not open.
+ *     The file descriptor pointer (md_fd field) stored in the SMgrRelation
+ *     cache is, therefore, just the head of a list of MdfdVec objects.
+ *     But note the md_fd pointer can be NULL, indicating relation not open.
  *
- *     When a relation is broken into multiple chunks, only the first chunk
- *     has its own entry in the Md_fdvec array; the remaining chunks have
- *     palloc'd MdfdVec objects that are chained onto the first chunk via the
- *     mdfd_chain links.  All chunks except the last MUST have size exactly
- *     equal to RELSEG_SIZE blocks --- see mdnblocks() and mdtruncate().
+ *     All MdfdVec objects are palloc'd in the MdCxt memory context.
  */
 
 typedef struct _MdfdVec
 {
-       int                     mdfd_vfd;               /* fd number in vfd pool */
-       int                     mdfd_flags;             /* fd status flags */
+       File            mdfd_vfd;                       /* fd number in fd.c's pool */
 
-/* these are the assigned bits in mdfd_flags: */
-#define MDFD_FREE      (1 << 0)        /* unused entry */
-
-       int                     mdfd_nextFree;  /* link to next freelist member, if free */
 #ifndef LET_OS_MANAGE_FILESIZE
        struct _MdfdVec *mdfd_chain;    /* for large relations */
 #endif
 } MdfdVec;
 
-static int     Nfds = 100;                     /* initial/current size of Md_fdvec array */
-static MdfdVec *Md_fdvec = NULL;
-static int     Md_Free = -1;           /* head of freelist of unused fdvec
-                                                                * entries */
-static int     CurFd = 0;                      /* first never-used fdvec index */
 static MemoryContext MdCxt;            /* context for all md.c allocations */
 
-/* routines declared here */
-static void mdclose_fd(int fd);
-static int     _mdfd_getrelnfd(Relation reln);
-static MdfdVec *_mdfd_openseg(Relation reln, BlockNumber segno, int oflags);
-static MdfdVec *_mdfd_getseg(Relation reln, BlockNumber blkno);
-
-static int     _mdfd_blind_getseg(RelFileNode rnode, BlockNumber blkno);
 
-static int     _fdvec_alloc(void);
-static void _fdvec_free(int);
+/* routines declared here */
+static MdfdVec *mdopen(SMgrRelation reln);
+static MdfdVec *_fdvec_alloc(void);
+#ifndef LET_OS_MANAGE_FILESIZE
+static MdfdVec *_mdfd_openseg(SMgrRelation reln, BlockNumber segno,
+                                                         int oflags);
+#endif
+static MdfdVec *_mdfd_getseg(SMgrRelation reln, BlockNumber blkno);
 static BlockNumber _mdnblocks(File file, Size blcksz);
 
+
 /*
  *     mdinit() -- Initialize private state for magnetic disk storage manager.
- *
- *             We keep a private table of all file descriptors.  This routine
- *             allocates and initializes the table.
- *
- *             Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
  */
-int
+bool
 mdinit(void)
 {
-       int                     i;
-
        MdCxt = AllocSetContextCreate(TopMemoryContext,
                                                                  "MdSmgr",
                                                                  ALLOCSET_DEFAULT_MINSIZE,
                                                                  ALLOCSET_DEFAULT_INITSIZE,
                                                                  ALLOCSET_DEFAULT_MAXSIZE);
 
-       Md_fdvec = (MdfdVec *) MemoryContextAlloc(MdCxt, Nfds * sizeof(MdfdVec));
-
-       MemSet(Md_fdvec, 0, Nfds * sizeof(MdfdVec));
-
-       /* Set free list */
-       for (i = 0; i < Nfds; i++)
-       {
-               Md_fdvec[i].mdfd_nextFree = i + 1;
-               Md_fdvec[i].mdfd_flags = MDFD_FREE;
-       }
-       Md_Free = 0;
-       Md_fdvec[Nfds - 1].mdfd_nextFree = -1;
-
-       return SM_SUCCESS;
+       return true;
 }
 
-int
-mdcreate(Relation reln)
+/*
+ *     mdcreate() -- Create a new relation on magnetic disk.
+ *
+ * If isRedo is true, it's okay for the relation to exist already.
+ */
+bool
+mdcreate(SMgrRelation reln, bool isRedo)
 {
        char       *path;
-       int                     fd,
-                               vfd;
+       File            fd;
 
-       Assert(reln->rd_fd < 0);
+       Assert(reln->md_fd == NULL);
 
-       path = relpath(reln->rd_node);
+       path = relpath(reln->smgr_rnode);
 
        fd = FileNameOpenFile(path, O_RDWR | O_CREAT | O_EXCL | PG_BINARY, 0600);
 
@@ -134,43 +107,45 @@ mdcreate(Relation reln)
                 * During bootstrap, there are cases where a system relation will
                 * be accessed (by internal backend processes) before the
                 * bootstrap script nominally creates it.  Therefore, allow the
-                * file to exist already, but in bootstrap mode only.  (See also
+                * file to exist already, even if isRedo is not set.  (See also
                 * mdopen)
                 */
-               if (IsBootstrapProcessingMode())
+               if (isRedo || IsBootstrapProcessingMode())
                        fd = FileNameOpenFile(path, O_RDWR | PG_BINARY, 0600);
                if (fd < 0)
                {
                        pfree(path);
                        /* be sure to return the error reported by create, not open */
                        errno = save_errno;
-                       return -1;
+                       return false;
                }
                errno = 0;
        }
 
        pfree(path);
 
-       vfd = _fdvec_alloc();
-       if (vfd < 0)
-               return -1;
+       reln->md_fd = _fdvec_alloc();
 
-       Md_fdvec[vfd].mdfd_vfd = fd;
-       Md_fdvec[vfd].mdfd_flags = (uint16) 0;
+       reln->md_fd->mdfd_vfd = fd;
 #ifndef LET_OS_MANAGE_FILESIZE
-       Md_fdvec[vfd].mdfd_chain = NULL;
+       reln->md_fd->mdfd_chain = NULL;
 #endif
 
-       return vfd;
+       return true;
 }
 
 /*
  *     mdunlink() -- Unlink a relation.
+ *
+ * Note that we're passed a RelFileNode --- by the time this is called,
+ * there won't be an SMgrRelation hashtable entry anymore.
+ *
+ * If isRedo is true, it's okay for the relation to be already gone.
  */
-int
-mdunlink(RelFileNode rnode)
+bool
+mdunlink(RelFileNode rnode, bool isRedo)
 {
-       int                     status = SM_SUCCESS;
+       bool            status = true;
        int                     save_errno = 0;
        char       *path;
 
@@ -179,13 +154,16 @@ mdunlink(RelFileNode rnode)
        /* Delete the first segment, or only segment if not doing segmenting */
        if (unlink(path) < 0)
        {
-               status = SM_FAIL;
-               save_errno = errno;
+               if (!isRedo || errno != ENOENT)
+               {
+                       status = false;
+                       save_errno = errno;
+               }
        }
 
 #ifndef LET_OS_MANAGE_FILESIZE
        /* Get the additional segments, if any */
-       if (status == SM_SUCCESS)
+       if (status)
        {
                char       *segpath = (char *) palloc(strlen(path) + 12);
                BlockNumber segno;
@@ -198,7 +176,7 @@ mdunlink(RelFileNode rnode)
                                /* ENOENT is expected after the last segment... */
                                if (errno != ENOENT)
                                {
-                                       status = SM_FAIL;
+                                       status = false;
                                        save_errno = errno;
                                }
                                break;
@@ -222,16 +200,15 @@ mdunlink(RelFileNode rnode)
  *             relation (ie, blocknum is the current EOF), and so in case of
  *             failure we clean up by truncating.
  *
- *             This routine returns SM_FAIL or SM_SUCCESS, with errno set as
- *             appropriate.
+ *             This routine returns true or false, with errno set as appropriate.
  *
  * Note: this routine used to call mdnblocks() to get the block position
  * to write at, but that's pretty silly since the caller needs to know where
  * the block will be written, and accordingly must have done mdnblocks()
  * already.  Might as well pass in the position and save a seek.
  */
-int
-mdextend(Relation reln, BlockNumber blocknum, char *buffer)
+bool
+mdextend(SMgrRelation reln, BlockNumber blocknum, char *buffer)
 {
        long            seekpos;
        int                     nbytes;
@@ -256,7 +233,7 @@ mdextend(Relation reln, BlockNumber blocknum, char *buffer)
         * to make room for the new page's buffer.
         */
        if (FileSeek(v->mdfd_vfd, seekpos, SEEK_SET) != seekpos)
-               return SM_FAIL;
+               return false;
 
        if ((nbytes = FileWrite(v->mdfd_vfd, buffer, BLCKSZ)) != BLCKSZ)
        {
@@ -269,29 +246,32 @@ mdextend(Relation reln, BlockNumber blocknum, char *buffer)
                        FileSeek(v->mdfd_vfd, seekpos, SEEK_SET);
                        errno = save_errno;
                }
-               return SM_FAIL;
+               return false;
        }
 
 #ifndef LET_OS_MANAGE_FILESIZE
        Assert(_mdnblocks(v->mdfd_vfd, BLCKSZ) <= ((BlockNumber) RELSEG_SIZE));
 #endif
 
-       return SM_SUCCESS;
+       return true;
 }
 
 /*
- *     mdopen() -- Open the specified relation.
+ *     mdopen() -- Open the specified relation.  ereport's on failure.
+ *
+ * Note we only open the first segment, when there are multiple segments.
  */
-int
-mdopen(Relation reln)
+static MdfdVec *
+mdopen(SMgrRelation reln)
 {
        char       *path;
-       int                     fd;
-       int                     vfd;
+       File            fd;
 
-       Assert(reln->rd_fd < 0);
+       /* No work if already open */
+       if (reln->md_fd)
+               return reln->md_fd;
 
-       path = relpath(reln->rd_node);
+       path = relpath(reln->smgr_rnode);
 
        fd = FileNameOpenFile(path, O_RDWR | PG_BINARY, 0600);
 
@@ -309,57 +289,45 @@ mdopen(Relation reln)
                if (fd < 0)
                {
                        pfree(path);
-                       return -1;
+                       ereport(ERROR,
+                                       (errcode_for_file_access(),
+                                        errmsg("could not open relation %u/%u: %m",
+                                                       reln->smgr_rnode.tblNode,
+                                                       reln->smgr_rnode.relNode)));
                }
        }
 
        pfree(path);
 
-       vfd = _fdvec_alloc();
-       if (vfd < 0)
-               return -1;
+       reln->md_fd = _fdvec_alloc();
 
-       Md_fdvec[vfd].mdfd_vfd = fd;
-       Md_fdvec[vfd].mdfd_flags = (uint16) 0;
+       reln->md_fd->mdfd_vfd = fd;
 #ifndef LET_OS_MANAGE_FILESIZE
-       Md_fdvec[vfd].mdfd_chain = NULL;
+       reln->md_fd->mdfd_chain = NULL;
        Assert(_mdnblocks(fd, BLCKSZ) <= ((BlockNumber) RELSEG_SIZE));
 #endif
 
-       return vfd;
+       return reln->md_fd;
 }
 
 /*
  *     mdclose() -- Close the specified relation, if it isn't closed already.
  *
- *             AND FREE fd vector! It may be re-used for other relations!
- *             reln should be flushed from cache after closing !..
- *
- *             Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
+ *             Returns true or false with errno set as appropriate.
  */
-int
-mdclose(Relation reln)
+bool
+mdclose(SMgrRelation reln)
 {
-       int                     fd;
-
-       fd = RelationGetFile(reln);
-       if (fd < 0)
-               return SM_SUCCESS;              /* already closed, so no work */
-
-       mdclose_fd(fd);
-
-       reln->rd_fd = -1;
+       MdfdVec    *v = reln->md_fd;
 
-       return SM_SUCCESS;
-}
+       /* No work if already closed */
+       if (v == NULL)
+               return true;
 
-static void
-mdclose_fd(int fd)
-{
-       MdfdVec    *v;
+       reln->md_fd = NULL;                     /* prevent dangling pointer after error */
 
 #ifndef LET_OS_MANAGE_FILESIZE
-       for (v = &Md_fdvec[fd]; v != NULL;)
+       while (v != NULL)
        {
                MdfdVec    *ov = v;
 
@@ -368,32 +336,24 @@ mdclose_fd(int fd)
                        FileClose(v->mdfd_vfd);
                /* Now free vector */
                v = v->mdfd_chain;
-               if (ov != &Md_fdvec[fd])
-                       pfree(ov);
+               pfree(ov);
        }
-
-       Md_fdvec[fd].mdfd_chain = NULL;
 #else
-       v = &Md_fdvec[fd];
-       if (v != NULL)
-       {
-               if (v->mdfd_vfd >= 0)
-                       FileClose(v->mdfd_vfd);
-       }
+       if (v->mdfd_vfd >= 0)
+               FileClose(v->mdfd_vfd);
+       pfree(v);
 #endif
 
-       _fdvec_free(fd);
+       return true;
 }
 
 /*
  *     mdread() -- Read the specified block from a relation.
- *
- *             Returns SM_SUCCESS or SM_FAIL.
  */
-int
-mdread(Relation reln, BlockNumber blocknum, char *buffer)
+bool
+mdread(SMgrRelation reln, BlockNumber blocknum, char *buffer)
 {
-       int                     status;
+       bool            status;
        long            seekpos;
        int                     nbytes;
        MdfdVec    *v;
@@ -408,9 +368,9 @@ mdread(Relation reln, BlockNumber blocknum, char *buffer)
 #endif
 
        if (FileSeek(v->mdfd_vfd, seekpos, SEEK_SET) != seekpos)
-               return SM_FAIL;
+               return false;
 
-       status = SM_SUCCESS;
+       status = true;
        if ((nbytes = FileRead(v->mdfd_vfd, buffer, BLCKSZ)) != BLCKSZ)
        {
                /*
@@ -425,7 +385,7 @@ mdread(Relation reln, BlockNumber blocknum, char *buffer)
                        (nbytes > 0 && mdnblocks(reln) == blocknum))
                        MemSet(buffer, 0, BLCKSZ);
                else
-                       status = SM_FAIL;
+                       status = false;
        }
 
        return status;
@@ -433,11 +393,9 @@ mdread(Relation reln, BlockNumber blocknum, char *buffer)
 
 /*
  *     mdwrite() -- Write the supplied block at the appropriate location.
- *
- *             Returns SM_SUCCESS or SM_FAIL.
  */
-int
-mdwrite(Relation reln, BlockNumber blocknum, char *buffer)
+bool
+mdwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer)
 {
        long            seekpos;
        MdfdVec    *v;
@@ -452,69 +410,12 @@ mdwrite(Relation reln, BlockNumber blocknum, char *buffer)
 #endif
 
        if (FileSeek(v->mdfd_vfd, seekpos, SEEK_SET) != seekpos)
-               return SM_FAIL;
+               return false;
 
        if (FileWrite(v->mdfd_vfd, buffer, BLCKSZ) != BLCKSZ)
-               return SM_FAIL;
+               return false;
 
-       return SM_SUCCESS;
-}
-
-/*
- *     mdblindwrt() -- Write a block to disk blind.
- *
- *             We have to be able to do this using only the rnode of the relation
- *             in which the block belongs.  Otherwise this is much like mdwrite().
- */
-int
-mdblindwrt(RelFileNode rnode,
-                  BlockNumber blkno,
-                  char *buffer)
-{
-       int                     status;
-       long            seekpos;
-       int                     fd;
-
-       fd = _mdfd_blind_getseg(rnode, blkno);
-
-       if (fd < 0)
-               return SM_FAIL;
-
-#ifndef LET_OS_MANAGE_FILESIZE
-       seekpos = (long) (BLCKSZ * (blkno % ((BlockNumber) RELSEG_SIZE)));
-       Assert(seekpos < BLCKSZ * RELSEG_SIZE);
-#else
-       seekpos = (long) (BLCKSZ * (blkno));
-#endif
-
-       errno = 0;
-       if (lseek(fd, seekpos, SEEK_SET) != seekpos)
-       {
-               elog(LOG, "lseek(%ld) failed: %m", seekpos);
-               close(fd);
-               return SM_FAIL;
-       }
-
-       status = SM_SUCCESS;
-
-       /* write the block */
-       errno = 0;
-       if (write(fd, buffer, BLCKSZ) != BLCKSZ)
-       {
-               /* if write didn't set errno, assume problem is no disk space */
-               if (errno == 0)
-                       errno = ENOSPC;
-               elog(LOG, "write() failed: %m");
-               status = SM_FAIL;
-       }
-
-       if (close(fd) < 0)
-       {
-               elog(LOG, "close() failed: %m");
-               status = SM_FAIL;
-       }
-
-       return status;
+       return true;
 }
 
 /*
@@ -525,24 +426,16 @@ mdblindwrt(RelFileNode rnode,
  *             called, then only segments up to the last one actually touched
  *             are present in the chain...
  *
- *             Returns # of blocks, ereport's on error.
+ *             Returns # of blocks, or InvalidBlockNumber on error.
  */
 BlockNumber
-mdnblocks(Relation reln)
+mdnblocks(SMgrRelation reln)
 {
-       int                     fd;
-       MdfdVec    *v;
+       MdfdVec    *v = mdopen(reln);
 
 #ifndef LET_OS_MANAGE_FILESIZE
        BlockNumber nblocks;
-       BlockNumber segno;
-#endif
-
-       fd = _mdfd_getrelnfd(reln);
-       v = &Md_fdvec[fd];
-
-#ifndef LET_OS_MANAGE_FILESIZE
-       segno = 0;
+       BlockNumber segno = 0;
 
        /*
         * Skip through any segments that aren't the last one, to avoid
@@ -583,8 +476,7 @@ mdnblocks(Relation reln)
                         */
                        v->mdfd_chain = _mdfd_openseg(reln, segno, O_CREAT);
                        if (v->mdfd_chain == NULL)
-                               elog(ERROR, "could not count blocks of \"%s\": %m",
-                                        RelationGetRelationName(reln));
+                               return InvalidBlockNumber;              /* failed? */
                }
 
                v = v->mdfd_chain;
@@ -600,9 +492,8 @@ mdnblocks(Relation reln)
  *             Returns # of blocks or InvalidBlockNumber on error.
  */
 BlockNumber
-mdtruncate(Relation reln, BlockNumber nblocks)
+mdtruncate(SMgrRelation reln, BlockNumber nblocks)
 {
-       int                     fd;
        MdfdVec    *v;
        BlockNumber curnblk;
 
@@ -615,13 +506,14 @@ mdtruncate(Relation reln, BlockNumber nblocks)
         * that truncate/delete loop will get them all!
         */
        curnblk = mdnblocks(reln);
+       if (curnblk == InvalidBlockNumber)
+               return InvalidBlockNumber;              /* mdnblocks failed */
        if (nblocks > curnblk)
                return InvalidBlockNumber;              /* bogus request */
        if (nblocks == curnblk)
                return nblocks;                 /* no work */
 
-       fd = _mdfd_getrelnfd(reln);
-       v = &Md_fdvec[fd];
+       v = mdopen(reln);
 
 #ifndef LET_OS_MANAGE_FILESIZE
        priorblocks = 0;
@@ -641,7 +533,7 @@ mdtruncate(Relation reln, BlockNumber nblocks)
                        FileTruncate(v->mdfd_vfd, 0);
                        FileUnlink(v->mdfd_vfd);
                        v = v->mdfd_chain;
-                       Assert(ov != &Md_fdvec[fd]);            /* we never drop the 1st
+                       Assert(ov != reln->md_fd);                      /* we never drop the 1st
                                                                                                 * segment */
                        pfree(ov);
                }
@@ -682,115 +574,65 @@ mdtruncate(Relation reln, BlockNumber nblocks)
 
 /*
  *     mdcommit() -- Commit a transaction.
- *
- *             Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
  */
-int
+bool
 mdcommit(void)
 {
        /*
         * We don't actually have to do anything here...
         */
-       return SM_SUCCESS;
+       return true;
 }
 
 /*
  *     mdabort() -- Abort a transaction.
  */
-int
+bool
 mdabort(void)
 {
        /*
         * We don't actually have to do anything here...
         */
-       return SM_SUCCESS;
+       return true;
 }
 
 /*
  *     mdsync() -- Sync previous writes to stable storage.
  */
-int
+bool
 mdsync(void)
 {
        sync();
        if (IsUnderPostmaster)
                sleep(2);
        sync();
-       return SM_SUCCESS;
+       return true;
 }
 
 /*
- *     _fdvec_alloc() -- Grab a free (or new) md file descriptor vector.
+ *     _fdvec_alloc() -- Make a MdfdVec object.
  */
-static int
+static MdfdVec *
 _fdvec_alloc(void)
 {
-       MdfdVec    *nvec;
-       int                     fdvec,
-                               i;
-
-       if (Md_Free >= 0)                       /* get from free list */
-       {
-               fdvec = Md_Free;
-               Md_Free = Md_fdvec[fdvec].mdfd_nextFree;
-               Assert(Md_fdvec[fdvec].mdfd_flags == MDFD_FREE);
-               Md_fdvec[fdvec].mdfd_flags = 0;
-               if (fdvec >= CurFd)
-               {
-                       Assert(fdvec == CurFd);
-                       CurFd++;
-               }
-               return fdvec;
-       }
-
-       /* Must allocate more room */
-
-       if (Nfds != CurFd)
-               elog(FATAL, "_fdvec_alloc error");
-
-       Nfds *= 2;
-
-       nvec = (MdfdVec *) MemoryContextAlloc(MdCxt, Nfds * sizeof(MdfdVec));
-       MemSet(nvec, 0, Nfds * sizeof(MdfdVec));
-       memcpy(nvec, (char *) Md_fdvec, CurFd * sizeof(MdfdVec));
-       pfree(Md_fdvec);
+       MdfdVec *v;
 
-       Md_fdvec = nvec;
-
-       /* Set new free list */
-       for (i = CurFd; i < Nfds; i++)
-       {
-               Md_fdvec[i].mdfd_nextFree = i + 1;
-               Md_fdvec[i].mdfd_flags = MDFD_FREE;
-       }
-       Md_fdvec[Nfds - 1].mdfd_nextFree = -1;
-       Md_Free = CurFd + 1;
-
-       fdvec = CurFd;
-       CurFd++;
-       Md_fdvec[fdvec].mdfd_flags = 0;
+       v = (MdfdVec *) MemoryContextAlloc(MdCxt, sizeof(MdfdVec));
+       v->mdfd_vfd = -1;
+#ifndef LET_OS_MANAGE_FILESIZE
+       v->mdfd_chain = NULL;
+#endif
 
-       return fdvec;
+       return v;
 }
 
+#ifndef LET_OS_MANAGE_FILESIZE
 /*
- *     _fdvec_free() -- free md file descriptor vector.
- *
+ * Open the specified segment of the relation,
+ * and make a MdfdVec object for it.  Returns NULL on failure.
  */
-static
-void
-_fdvec_free(int fdvec)
-{
-
-       Assert(Md_Free < 0 || Md_fdvec[Md_Free].mdfd_flags == MDFD_FREE);
-       Assert(Md_fdvec[fdvec].mdfd_flags != MDFD_FREE);
-       Md_fdvec[fdvec].mdfd_nextFree = Md_Free;
-       Md_fdvec[fdvec].mdfd_flags = MDFD_FREE;
-       Md_Free = fdvec;
-}
-
 static MdfdVec *
-_mdfd_openseg(Relation reln, BlockNumber segno, int oflags)
+_mdfd_openseg(SMgrRelation reln, BlockNumber segno, int oflags)
 {
        MdfdVec    *v;
        int                     fd;
@@ -798,7 +640,7 @@ _mdfd_openseg(Relation reln, BlockNumber segno, int oflags)
                           *fullpath;
 
        /* be sure we have enough space for the '.segno', if any */
-       path = relpath(reln->rd_node);
+       path = relpath(reln->smgr_rnode);
 
        if (segno > 0)
        {
@@ -818,61 +660,32 @@ _mdfd_openseg(Relation reln, BlockNumber segno, int oflags)
                return NULL;
 
        /* allocate an mdfdvec entry for it */
-       v = (MdfdVec *) MemoryContextAlloc(MdCxt, sizeof(MdfdVec));
+       v = _fdvec_alloc();
 
        /* fill the entry */
        v->mdfd_vfd = fd;
-       v->mdfd_flags = (uint16) 0;
-#ifndef LET_OS_MANAGE_FILESIZE
        v->mdfd_chain = NULL;
        Assert(_mdnblocks(fd, BLCKSZ) <= ((BlockNumber) RELSEG_SIZE));
-#endif
 
        /* all done */
        return v;
 }
-
-/*
- *     _mdfd_getrelnfd() -- Get the (virtual) fd for the relation,
- *                                              opening it if it's not already open
- *
- */
-static int
-_mdfd_getrelnfd(Relation reln)
-{
-       int                     fd;
-
-       fd = RelationGetFile(reln);
-       if (fd < 0)
-       {
-               if ((fd = mdopen(reln)) < 0)
-                       elog(ERROR, "could not open relation \"%s\": %m",
-                                RelationGetRelationName(reln));
-               reln->rd_fd = fd;
-       }
-       return fd;
-}
+#endif
 
 /*
  *     _mdfd_getseg() -- Find the segment of the relation holding the
- *                                       specified block
- *
+ *                                       specified block.  ereport's on failure.
  */
 static MdfdVec *
-_mdfd_getseg(Relation reln, BlockNumber blkno)
+_mdfd_getseg(SMgrRelation reln, BlockNumber blkno)
 {
-       MdfdVec    *v;
-       int                     fd;
+       MdfdVec    *v = mdopen(reln);
 
 #ifndef LET_OS_MANAGE_FILESIZE
        BlockNumber segno;
        BlockNumber i;
-#endif
-
-       fd = _mdfd_getrelnfd(reln);
 
-#ifndef LET_OS_MANAGE_FILESIZE
-       for (v = &Md_fdvec[fd], segno = blkno / ((BlockNumber) RELSEG_SIZE), i = 1;
+       for (segno = blkno / ((BlockNumber) RELSEG_SIZE), i = 1;
                 segno > 0;
                 i++, segno--)
        {
@@ -892,65 +705,24 @@ _mdfd_getseg(Relation reln, BlockNumber blkno)
                        v->mdfd_chain = _mdfd_openseg(reln, i, (segno == 1) ? O_CREAT : 0);
 
                        if (v->mdfd_chain == NULL)
-                               elog(ERROR, "could not open segment %u of relation \"%s\" (target block %u): %m",
-                                        i, RelationGetRelationName(reln), blkno);
+                               ereport(ERROR,
+                                               (errcode_for_file_access(),
+                                                errmsg("could not open segment %u of relation %u/%u (target block %u): %m",
+                                                               i,
+                                                               reln->smgr_rnode.tblNode,
+                                                               reln->smgr_rnode.relNode,
+                                                               blkno)));
                }
                v = v->mdfd_chain;
        }
-#else
-       v = &Md_fdvec[fd];
 #endif
 
        return v;
 }
 
 /*
- * Find the segment of the relation holding the specified block.
- *
- * This performs the same work as _mdfd_getseg() except that we must work
- * "blind" with no Relation struct.  We assume that we are not likely to
- * touch the same relation again soon, so we do not create an FD entry for
- * the relation --- we just open a kernel file descriptor which will be
- * used and promptly closed.  We also assume that the target block already
- * exists, ie, we need not extend the relation.
- *
- * The return value is the kernel descriptor, or -1 on failure.
+ * Get number of blocks present in a single disk file
  */
-static int
-_mdfd_blind_getseg(RelFileNode rnode, BlockNumber blkno)
-{
-       char       *path;
-       int                     fd;
-
-#ifndef LET_OS_MANAGE_FILESIZE
-       BlockNumber segno;
-#endif
-
-       path = relpath(rnode);
-
-#ifndef LET_OS_MANAGE_FILESIZE
-       /* append the '.segno', if needed */
-       segno = blkno / ((BlockNumber) RELSEG_SIZE);
-       if (segno > 0)
-       {
-               char       *segpath = (char *) palloc(strlen(path) + 12);
-
-               sprintf(segpath, "%s.%u", path, segno);
-               pfree(path);
-               path = segpath;
-       }
-#endif
-
-       /* call fd.c to allow other FDs to be closed if needed */
-       fd = BasicOpenFile(path, O_RDWR | PG_BINARY, 0600);
-       if (fd < 0)
-               elog(LOG, "could not open \"%s\": %m", path);
-
-       pfree(path);
-
-       return fd;
-}
-
 static BlockNumber
 _mdnblocks(File file, Size blcksz)
 {
diff --git a/src/backend/storage/smgr/mm.c b/src/backend/storage/smgr/mm.c
deleted file mode 100644 (file)
index 5043fd6..0000000
+++ /dev/null
@@ -1,552 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * mm.c
- *       main memory storage manager
- *
- *       This code manages relations that reside in (presumably stable)
- *       main memory.
- *
- * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/smgr/mm.c,v 1.36 2004/01/07 18:56:27 neilc Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include <math.h>
-
-#include "storage/smgr.h"
-#include "miscadmin.h"
-
-
-#ifdef STABLE_MEMORY_STORAGE
-
-/*
- *     MMCacheTag -- Unique triplet for blocks stored by the main memory
- *                               storage manager.
- */
-
-typedef struct MMCacheTag
-{
-       Oid                     mmct_dbid;
-       Oid                     mmct_relid;
-       BlockNumber mmct_blkno;
-}      MMCacheTag;
-
-/*
- *     Shared-memory hash table for main memory relations contains
- *     entries of this form.
- */
-
-typedef struct MMHashEntry
-{
-       MMCacheTag      mmhe_tag;
-       int                     mmhe_bufno;
-}      MMHashEntry;
-
-/*
- * MMRelTag -- Unique identifier for each relation that is stored in the
- *                                     main-memory storage manager.
- */
-
-typedef struct MMRelTag
-{
-       Oid                     mmrt_dbid;
-       Oid                     mmrt_relid;
-}      MMRelTag;
-
-/*
- *     Shared-memory hash table for # blocks in main memory relations contains
- *     entries of this form.
- */
-
-typedef struct MMRelHashEntry
-{
-       MMRelTag        mmrhe_tag;
-       int                     mmrhe_nblocks;
-}      MMRelHashEntry;
-
-#define MMNBUFFERS             10
-#define MMNRELATIONS   2
-
-static int *MMCurTop;
-static int *MMCurRelno;
-static MMCacheTag *MMBlockTags;
-static char *MMBlockCache;
-static HTAB *MMCacheHT;
-static HTAB *MMRelCacheHT;
-
-int
-mminit(void)
-{
-       char       *mmcacheblk;
-       int                     mmsize = 0;
-       bool            found;
-       HASHCTL         info;
-
-       LWLockAcquire(MMCacheLock, LW_EXCLUSIVE);
-
-       mmsize += MAXALIGN(BLCKSZ * MMNBUFFERS);
-       mmsize += MAXALIGN(sizeof(*MMCurTop));
-       mmsize += MAXALIGN(sizeof(*MMCurRelno));
-       mmsize += MAXALIGN((MMNBUFFERS * sizeof(MMCacheTag)));
-       mmcacheblk = (char *) ShmemInitStruct("Main memory smgr", mmsize, &found);
-
-       if (mmcacheblk == NULL)
-       {
-               LWLockRelease(MMCacheLock);
-               return SM_FAIL;
-       }
-
-       info.keysize = sizeof(MMCacheTag);
-       info.entrysize = sizeof(MMHashEntry);
-       info.hash = tag_hash;
-
-       MMCacheHT = ShmemInitHash("Main memory store HT",
-                                                         MMNBUFFERS, MMNBUFFERS,
-                                                         &info, (HASH_ELEM | HASH_FUNCTION));
-
-       if (MMCacheHT == NULL)
-       {
-               LWLockRelease(MMCacheLock);
-               return SM_FAIL;
-       }
-
-       info.keysize = sizeof(MMRelTag);
-       info.entrysize = sizeof(MMRelHashEntry);
-       info.hash = tag_hash;
-
-       MMRelCacheHT = ShmemInitHash("Main memory rel HT",
-                                                                MMNRELATIONS, MMNRELATIONS,
-                                                                &info, (HASH_ELEM | HASH_FUNCTION));
-
-       if (MMRelCacheHT == NULL)
-       {
-               LWLockRelease(MMCacheLock);
-               return SM_FAIL;
-       }
-
-       if (IsUnderPostmaster)          /* was IsPostmaster bjm */
-       {
-               MemSet(mmcacheblk, 0, mmsize);
-               LWLockRelease(MMCacheLock);
-               return SM_SUCCESS;
-       }
-
-       LWLockRelease(MMCacheLock);
-
-       MMCurTop = (int *) mmcacheblk;
-       mmcacheblk += sizeof(int);
-       MMCurRelno = (int *) mmcacheblk;
-       mmcacheblk += sizeof(int);
-       MMBlockTags = (MMCacheTag *) mmcacheblk;
-       mmcacheblk += (MMNBUFFERS * sizeof(MMCacheTag));
-       MMBlockCache = mmcacheblk;
-
-       return SM_SUCCESS;
-}
-
-int
-mmshutdown(void)
-{
-       return SM_SUCCESS;
-}
-
-int
-mmcreate(Relation reln)
-{
-       MMRelHashEntry *entry;
-       bool            found;
-       MMRelTag        tag;
-
-       LWLockAcquire(MMCacheLock, LW_EXCLUSIVE);
-
-       if (*MMCurRelno == MMNRELATIONS)
-       {
-               LWLockRelease(MMCacheLock);
-               return SM_FAIL;
-       }
-
-       (*MMCurRelno)++;
-
-       tag.mmrt_relid = RelationGetRelid(reln);
-       if (reln->rd_rel->relisshared)
-               tag.mmrt_dbid = (Oid) 0;
-       else
-               tag.mmrt_dbid = MyDatabaseId;
-
-       entry = (MMRelHashEntry *) hash_search(MMRelCacheHT,
-                                                                                  (void *) &tag,
-                                                                                  HASH_ENTER, &found);
-
-       if (entry == NULL)
-       {
-               LWLockRelease(MMCacheLock);
-               ereport(FATAL,
-                               (errcode(ERRCODE_OUT_OF_MEMORY),
-                                errmsg("out of memory")));
-       }
-
-       if (found)
-       {
-               /* already exists */
-               LWLockRelease(MMCacheLock);
-               return SM_FAIL;
-       }
-
-       entry->mmrhe_nblocks = 0;
-
-       LWLockRelease(MMCacheLock);
-
-       return SM_SUCCESS;
-}
-
-/*
- *     mmunlink() -- Unlink a relation.
- *
- * XXX currently broken: needs to accept RelFileNode, not Relation
- */
-int
-mmunlink(RelFileNode rnode)
-{
-       int                     i;
-       MMHashEntry *entry;
-       MMRelHashEntry *rentry;
-       MMRelTag        rtag;
-
-       LWLockAcquire(MMCacheLock, LW_EXCLUSIVE);
-
-       for (i = 0; i < MMNBUFFERS; i++)
-       {
-               if (MMBlockTags[i].mmct_dbid == rnode.tblNode
-                       && MMBlockTags[i].mmct_relid == rnode.relNode)
-               {
-                       entry = (MMHashEntry *) hash_search(MMCacheHT,
-                                                                                               (void *) &MMBlockTags[i],
-                                                                                               HASH_REMOVE, NULL);
-                       if (entry == NULL)
-                       {
-                               LWLockRelease(MMCacheLock);
-                               elog(FATAL, "cache hash table corrupted");
-                       }
-                       MMBlockTags[i].mmct_dbid = (Oid) 0;
-                       MMBlockTags[i].mmct_relid = (Oid) 0;
-                       MMBlockTags[i].mmct_blkno = (BlockNumber) 0;
-               }
-       }
-       rtag.mmrt_dbid = rnode.tblNode;
-       rtag.mmrt_relid = rnode.relNode;
-
-       rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT,
-                                                                                       (void *) &rtag,
-                                                                                       HASH_REMOVE, NULL);
-
-       if (rentry == NULL)
-       {
-               LWLockRelease(MMCacheLock);
-               elog(FATAL, "rel cache hash table corrupted");
-       }
-
-       (*MMCurRelno)--;
-
-       LWLockRelease(MMCacheLock);
-       return 1;
-}
-
-/*
- *     mmextend() -- Add a block to the specified relation.
- *
- *             This routine returns SM_FAIL or SM_SUCCESS, with errno set as
- *             appropriate.
- */
-int
-mmextend(Relation reln, BlockNumber blocknum, char *buffer)
-{
-       MMRelHashEntry *rentry;
-       MMHashEntry *entry;
-       int                     i;
-       Oid                     reldbid;
-       int                     offset;
-       bool            found;
-       MMRelTag        rtag;
-       MMCacheTag      tag;
-
-       if (reln->rd_rel->relisshared)
-               reldbid = (Oid) 0;
-       else
-               reldbid = MyDatabaseId;
-
-       tag.mmct_dbid = rtag.mmrt_dbid = reldbid;
-       tag.mmct_relid = rtag.mmrt_relid = RelationGetRelid(reln);
-
-       LWLockAcquire(MMCacheLock, LW_EXCLUSIVE);
-
-       if (*MMCurTop == MMNBUFFERS)
-       {
-               for (i = 0; i < MMNBUFFERS; i++)
-               {
-                       if (MMBlockTags[i].mmct_dbid == 0 &&
-                               MMBlockTags[i].mmct_relid == 0)
-                               break;
-               }
-               if (i == MMNBUFFERS)
-               {
-                       LWLockRelease(MMCacheLock);
-                       return SM_FAIL;
-               }
-       }
-       else
-       {
-               i = *MMCurTop;
-               (*MMCurTop)++;
-       }
-
-       rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT,
-                                                                                       (void *) &rtag,
-                                                                                       HASH_FIND, NULL);
-       if (rentry == NULL)
-       {
-               LWLockRelease(MMCacheLock);
-               elog(FATAL, "rel cache hash table corrupted");
-       }
-
-       tag.mmct_blkno = rentry->mmrhe_nblocks;
-
-       entry = (MMHashEntry *) hash_search(MMCacheHT,
-                                                                               (void *) &tag,
-                                                                               HASH_ENTER, &found);
-       if (entry == NULL || found)
-       {
-               LWLockRelease(MMCacheLock);
-               elog(FATAL, "cache hash table corrupted");
-       }
-
-       entry->mmhe_bufno = i;
-       MMBlockTags[i].mmct_dbid = reldbid;
-       MMBlockTags[i].mmct_relid = RelationGetRelid(reln);
-       MMBlockTags[i].mmct_blkno = rentry->mmrhe_nblocks;
-
-       /* page numbers are zero-based, so we increment this at the end */
-       (rentry->mmrhe_nblocks)++;
-
-       /* write the extended page */
-       offset = (i * BLCKSZ);
-       memmove(&(MMBlockCache[offset]), buffer, BLCKSZ);
-
-       LWLockRelease(MMCacheLock);
-
-       return SM_SUCCESS;
-}
-
-/*
- *     mmopen() -- Open the specified relation.
- */
-int
-mmopen(Relation reln)
-{
-       /* automatically successful */
-       return 0;
-}
-
-/*
- *     mmclose() -- Close the specified relation.
- *
- *             Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
- */
-int
-mmclose(Relation reln)
-{
-       /* automatically successful */
-       return SM_SUCCESS;
-}
-
-/*
- *     mmread() -- Read the specified block from a relation.
- *
- *             Returns SM_SUCCESS or SM_FAIL.
- */
-int
-mmread(Relation reln, BlockNumber blocknum, char *buffer)
-{
-       MMHashEntry *entry;
-       int                     offset;
-       MMCacheTag      tag;
-
-       if (reln->rd_rel->relisshared)
-               tag.mmct_dbid = (Oid) 0;
-       else
-               tag.mmct_dbid = MyDatabaseId;
-
-       tag.mmct_relid = RelationGetRelid(reln);
-       tag.mmct_blkno = blocknum;
-
-       LWLockAcquire(MMCacheLock, LW_EXCLUSIVE);
-       entry = (MMHashEntry *) hash_search(MMCacheHT,
-                                                                               (void *) &tag,
-                                                                               HASH_FIND, NULL);
-
-       if (entry == NULL)
-       {
-               /* reading nonexistent pages is defined to fill them with zeroes */
-               LWLockRelease(MMCacheLock);
-               MemSet(buffer, 0, BLCKSZ);
-               return SM_SUCCESS;
-       }
-
-       offset = (entry->mmhe_bufno * BLCKSZ);
-       memmove(buffer, &MMBlockCache[offset], BLCKSZ);
-
-       LWLockRelease(MMCacheLock);
-
-       return SM_SUCCESS;
-}
-
-/*
- *     mmwrite() -- Write the supplied block at the appropriate location.
- *
- *             Returns SM_SUCCESS or SM_FAIL.
- */
-int
-mmwrite(Relation reln, BlockNumber blocknum, char *buffer)
-{
-       MMHashEntry *entry;
-       int                     offset;
-       MMCacheTag      tag;
-
-       if (reln->rd_rel->relisshared)
-               tag.mmct_dbid = (Oid) 0;
-       else
-               tag.mmct_dbid = MyDatabaseId;
-
-       tag.mmct_relid = RelationGetRelid(reln);
-       tag.mmct_blkno = blocknum;
-
-       LWLockAcquire(MMCacheLock, LW_EXCLUSIVE);
-       entry = (MMHashEntry *) hash_search(MMCacheHT,
-                                                                               (void *) &tag,
-                                                                               HASH_FIND, NULL);
-
-       if (entry == NULL)
-       {
-               LWLockRelease(MMCacheLock);
-               elog(FATAL, "cache hash table missing requested page");
-       }
-
-       offset = (entry->mmhe_bufno * BLCKSZ);
-       memmove(&MMBlockCache[offset], buffer, BLCKSZ);
-
-       LWLockRelease(MMCacheLock);
-
-       return SM_SUCCESS;
-}
-
-/*
- *     mmblindwrt() -- Write a block to stable storage blind.
- *
- *             We have to be able to do this using only the rnode of the relation
- *             in which the block belongs.  Otherwise this is much like mmwrite().
- */
-int
-mmblindwrt(RelFileNode rnode,
-                  BlockNumber blkno,
-                  char *buffer)
-{
-       return SM_FAIL;
-}
-
-/*
- *     mmnblocks() -- Get the number of blocks stored in a relation.
- *
- *             Returns # of blocks or InvalidBlockNumber on error.
- */
-BlockNumber
-mmnblocks(Relation reln)
-{
-       MMRelTag        rtag;
-       MMRelHashEntry *rentry;
-       BlockNumber nblocks;
-
-       if (reln->rd_rel->relisshared)
-               rtag.mmrt_dbid = (Oid) 0;
-       else
-               rtag.mmrt_dbid = MyDatabaseId;
-
-       rtag.mmrt_relid = RelationGetRelid(reln);
-
-       LWLockAcquire(MMCacheLock, LW_EXCLUSIVE);
-
-       rentry = (MMRelHashEntry *) hash_search(MMRelCacheHT,
-                                                                                       (void *) &rtag,
-                                                                                       HASH_FIND, NULL);
-
-       if (rentry)
-               nblocks = rentry->mmrhe_nblocks;
-       else
-               nblocks = InvalidBlockNumber;
-
-       LWLockRelease(MMCacheLock);
-
-       return nblocks;
-}
-
-/*
- *     mmcommit() -- Commit a transaction.
- *
- *             Returns SM_SUCCESS or SM_FAIL with errno set as appropriate.
- */
-int
-mmcommit(void)
-{
-       return SM_SUCCESS;
-}
-
-/*
- *     mmabort() -- Abort a transaction.
- */
-
-int
-mmabort(void)
-{
-       return SM_SUCCESS;
-}
-
-/*
- *     MMShmemSize() -- Declare amount of shared memory we require.
- *
- *             The shared memory initialization code creates a block of shared
- *             memory exactly big enough to hold all the structures it needs to.
- *             This routine declares how much space the main memory storage
- *             manager will use.
- */
-int
-MMShmemSize(void)
-{
-       int                     size = 0;
-
-       /*
-        * first compute space occupied by the (dbid,relid,blkno) hash table
-        */
-       size += hash_estimate_size(MMNBUFFERS, sizeof(MMHashEntry));
-
-       /*
-        * now do the same for the rel hash table
-        */
-       size += hash_estimate_size(MMNRELATIONS, sizeof(MMRelHashEntry));
-
-       /*
-        * finally, add in the memory block we use directly
-        */
-
-       size += MAXALIGN(BLCKSZ * MMNBUFFERS);
-       size += MAXALIGN(sizeof(*MMCurTop));
-       size += MAXALIGN(sizeof(*MMCurRelno));
-       size += MAXALIGN(MMNBUFFERS * sizeof(MMCacheTag));
-
-       return size;
-}
-
-#endif   /* STABLE_MEMORY_STORAGE */
index 0e33af5f28120a5f7fa8315bd891e0b0ed630a5f..09ee4144c50ac4b5dbb6274457bbacb46cc16574 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.68 2004/01/06 18:07:31 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.69 2004/02/10 01:55:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "storage/freespace.h"
 #include "storage/ipc.h"
 #include "storage/smgr.h"
+#include "utils/hsearch.h"
 #include "utils/memutils.h"
 
 
-static void smgrshutdown(int code, Datum arg);
-
+/*
+ * This struct of function pointers defines the API between smgr.c and
+ * any individual storage manager module.  Note that smgr subfunctions are
+ * generally expected to return TRUE on success, FALSE on error.  (For
+ * nblocks and truncate we instead say that returning InvalidBlockNumber
+ * indicates an error.)
+ */
 typedef struct f_smgr
 {
-       int                     (*smgr_init) (void);    /* may be NULL */
-       int                     (*smgr_shutdown) (void);                /* may be NULL */
-       int                     (*smgr_create) (Relation reln);
-       int                     (*smgr_unlink) (RelFileNode rnode);
-       int                     (*smgr_extend) (Relation reln, BlockNumber blocknum,
+       bool            (*smgr_init) (void);                    /* may be NULL */
+       bool            (*smgr_shutdown) (void);                /* may be NULL */
+       bool            (*smgr_close) (SMgrRelation reln);
+       bool            (*smgr_create) (SMgrRelation reln, bool isRedo);
+       bool            (*smgr_unlink) (RelFileNode rnode, bool isRedo);
+       bool            (*smgr_extend) (SMgrRelation reln, BlockNumber blocknum,
                                                                                        char *buffer);
-       int                     (*smgr_open) (Relation reln);
-       int                     (*smgr_close) (Relation reln);
-       int                     (*smgr_read) (Relation reln, BlockNumber blocknum,
+       bool            (*smgr_read) (SMgrRelation reln, BlockNumber blocknum,
                                                                                  char *buffer);
-       int                     (*smgr_write) (Relation reln, BlockNumber blocknum,
+       bool            (*smgr_write) (SMgrRelation reln, BlockNumber blocknum,
                                                                                   char *buffer);
-       int                     (*smgr_blindwrt) (RelFileNode rnode, BlockNumber blkno,
-                                                                                         char *buffer);
-       BlockNumber (*smgr_nblocks) (Relation reln);
-       BlockNumber (*smgr_truncate) (Relation reln, BlockNumber nblocks);
-       int                     (*smgr_commit) (void);  /* may be NULL */
-       int                     (*smgr_abort) (void);   /* may be NULL */
-       int                     (*smgr_sync) (void);
+       BlockNumber (*smgr_nblocks) (SMgrRelation reln);
+       BlockNumber (*smgr_truncate) (SMgrRelation reln, BlockNumber nblocks);
+       bool            (*smgr_commit) (void);                  /* may be NULL */
+       bool            (*smgr_abort) (void);                   /* may be NULL */
+       bool            (*smgr_sync) (void);                    /* may be NULL */
 } f_smgr;
 
-/*
- *     The weird placement of commas in this init block is to keep the compiler
- *     happy, regardless of what storage managers we have (or don't have).
- */
-
-static f_smgr smgrsw[] = {
 
+static const f_smgr smgrsw[] = {
        /* magnetic disk */
-       {mdinit, NULL, mdcreate, mdunlink, mdextend, mdopen, mdclose,
-               mdread, mdwrite, mdblindwrt,
-               mdnblocks, mdtruncate, mdcommit, mdabort, mdsync
-       },
-
-#ifdef STABLE_MEMORY_STORAGE
-       /* main memory */
-       {mminit, mmshutdown, mmcreate, mmunlink, mmextend, mmopen, mmclose,
-               mmread, mmwrite, mmblindwrt,
-       mmnblocks, NULL, mmcommit, mmabort, NULL},
-#endif
+       {mdinit, NULL, mdclose, mdcreate, mdunlink, mdextend,
+        mdread, mdwrite, mdnblocks, mdtruncate, mdcommit, mdabort, mdsync
+       }
 };
 
-/*
- *     This array records which storage managers are write-once, and which
- *     support overwrite.      A 'true' entry means that the storage manager is
- *     write-once.  In the best of all possible worlds, there would be no
- *     write-once storage managers.
- */
+static const int       NSmgr = lengthof(smgrsw);
 
-#ifdef NOT_USED
-static bool smgrwo[] = {
-       false,                                          /* magnetic disk */
-#ifdef STABLE_MEMORY_STORAGE
-       false,                                          /* main memory */
-#endif
-};
-#endif
 
-static int     NSmgr = lengthof(smgrsw);
+/*
+ * Each backend has a hashtable that stores all extant SMgrRelation objects.
+ */
+static HTAB *SMgrRelationHash = NULL;
 
 /*
  * We keep a list of all relations (represented as RelFileNode values)
@@ -105,7 +85,7 @@ static int   NSmgr = lengthof(smgrsw);
 typedef struct PendingRelDelete
 {
        RelFileNode relnode;            /* relation that may need to be deleted */
-       int16           which;                  /* which storage manager? */
+       int                     which;                  /* which storage manager? */
        bool            isTemp;                 /* is it a temporary relation? */
        bool            atCommit;               /* T=delete at commit; F=delete at abort */
        struct PendingRelDelete *next;          /* linked-list link */
@@ -114,12 +94,20 @@ typedef struct PendingRelDelete
 static PendingRelDelete *pendingDeletes = NULL; /* head of linked list */
 
 
+/* local function prototypes */
+static void smgrshutdown(int code, Datum arg);
+static void smgr_internal_unlink(RelFileNode rnode, int which,
+                                                                bool isTemp, bool isRedo);
+
+
 /*
  *     smgrinit(), smgrshutdown() -- Initialize or shut down all storage
  *                                                               managers.
  *
+ * Note: in the normal multiprocess scenario with a postmaster, these are
+ * called at postmaster start and stop, not per-backend.
  */
-int
+void
 smgrinit(void)
 {
        int                     i;
@@ -128,7 +116,7 @@ smgrinit(void)
        {
                if (smgrsw[i].smgr_init)
                {
-                       if ((*(smgrsw[i].smgr_init)) () == SM_FAIL)
+                       if (! (*(smgrsw[i].smgr_init)) ())
                                elog(FATAL, "smgr initialization failed on %s: %m",
                                         DatumGetCString(DirectFunctionCall1(smgrout,
                                                                                                         Int16GetDatum(i))));
@@ -137,8 +125,6 @@ smgrinit(void)
 
        /* register the shutdown proc */
        on_proc_exit(smgrshutdown, 0);
-
-       return SM_SUCCESS;
 }
 
 static void
@@ -150,7 +136,7 @@ smgrshutdown(int code, Datum arg)
        {
                if (smgrsw[i].smgr_shutdown)
                {
-                       if ((*(smgrsw[i].smgr_shutdown)) () == SM_FAIL)
+                       if (! (*(smgrsw[i].smgr_shutdown)) ())
                                elog(FATAL, "smgr shutdown failed on %s: %m",
                                         DatumGetCString(DirectFunctionCall1(smgrout,
                                                                                                         Int16GetDatum(i))));
@@ -158,58 +144,178 @@ smgrshutdown(int code, Datum arg)
        }
 }
 
+/*
+ *     smgropen() -- Return an SMgrRelation object, creating it if need be.
+ *
+ *             This does not attempt to actually open the object.
+ */
+SMgrRelation
+smgropen(RelFileNode rnode)
+{
+       SMgrRelation    reln;
+       bool            found;
+
+       if (SMgrRelationHash == NULL)
+       {
+               /* First time through: initialize the hash table */
+               HASHCTL         ctl;
+
+               MemSet(&ctl, 0, sizeof(ctl));
+               ctl.keysize = sizeof(RelFileNode);
+               ctl.entrysize = sizeof(SMgrRelationData);
+               ctl.hash = tag_hash;
+               SMgrRelationHash = hash_create("smgr relation table", 400,
+                                                                          &ctl, HASH_ELEM | HASH_FUNCTION);
+       }
+
+       /* Look up or create an entry */
+       reln = (SMgrRelation) hash_search(SMgrRelationHash,
+                                                                         (void *) &rnode,
+                                                                         HASH_ENTER, &found);
+       if (reln == NULL)
+               ereport(ERROR,
+                               (errcode(ERRCODE_OUT_OF_MEMORY),
+                                errmsg("out of memory")));
+
+       /* Initialize it if not present before */
+       if (!found)
+       {
+               /* hash_search already filled in the lookup key */
+               reln->smgr_which = 0;   /* we only have md.c at present */
+               reln->md_fd = NULL;             /* mark it not open */
+       }
+
+       return reln;
+}
+
+/*
+ *     smgrclose() -- Close and delete an SMgrRelation object.
+ *
+ * It is the caller's responsibility not to leave any dangling references
+ * to the object.  (Pointers should be cleared after successful return;
+ * on the off chance of failure, the SMgrRelation object will still exist.)
+ */
+void
+smgrclose(SMgrRelation reln)
+{
+       if (! (*(smgrsw[reln->smgr_which].smgr_close)) (reln))
+               ereport(ERROR,
+                               (errcode_for_file_access(),
+                                errmsg("could not close relation %u/%u: %m",
+                                               reln->smgr_rnode.tblNode,
+                                               reln->smgr_rnode.relNode)));
+
+       if (hash_search(SMgrRelationHash,
+                                       (void *) &(reln->smgr_rnode),
+                                       HASH_REMOVE, NULL) == NULL)
+               elog(ERROR, "SMgrRelation hashtable corrupted");
+}
+
+/*
+ *     smgrcloseall() -- Close all existing SMgrRelation objects.
+ *
+ * It is the caller's responsibility not to leave any dangling references.
+ */
+void
+smgrcloseall(void)
+{
+       HASH_SEQ_STATUS status;
+       SMgrRelation reln;
+
+       /* Nothing to do if hashtable not set up */
+       if (SMgrRelationHash == NULL)
+               return;
+
+       hash_seq_init(&status, SMgrRelationHash);
+
+       while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
+       {
+               smgrclose(reln);
+       }
+}
+
+/*
+ *     smgrclosenode() -- Close SMgrRelation object for given RelFileNode,
+ *                                        if one exists.
+ *
+ * This has the same effects as smgrclose(smgropen(rnode)), but it avoids
+ * uselessly creating a hashtable entry only to drop it again when no
+ * such entry exists already.
+ *
+ * It is the caller's responsibility not to leave any dangling references.
+ */
+void
+smgrclosenode(RelFileNode rnode)
+{
+       SMgrRelation    reln;
+
+       /* Nothing to do if hashtable not set up */
+       if (SMgrRelationHash == NULL)
+               return;
+
+       reln = (SMgrRelation) hash_search(SMgrRelationHash,
+                                                                         (void *) &rnode,
+                                                                         HASH_FIND, NULL);
+       if (reln != NULL)
+               smgrclose(reln);
+}
+
 /*
  *     smgrcreate() -- Create a new relation.
  *
- *             This routine takes a reldesc, creates the relation on the appropriate
- *             device, and returns a file descriptor for it.
+ *             Given an already-created (but presumably unused) SMgrRelation,
+ *             cause the underlying disk file or other storage to be created.
+ *
+ *             If isRedo is true, it is okay for the underlying file to exist
+ *             already because we are in a WAL replay sequence.  In this case
+ *             we should make no PendingRelDelete entry; the WAL sequence will
+ *             tell whether to drop the file.
  */
-int
-smgrcreate(int16 which, Relation reln)
+void
+smgrcreate(SMgrRelation reln, bool isTemp, bool isRedo)
 {
-       int                     fd;
        PendingRelDelete *pending;
 
-       if ((fd = (*(smgrsw[which].smgr_create)) (reln)) < 0)
+       if (! (*(smgrsw[reln->smgr_which].smgr_create)) (reln, isRedo))
                ereport(ERROR,
                                (errcode_for_file_access(),
-                                errmsg("could not create relation \"%s\": %m",
-                                               RelationGetRelationName(reln))));
+                                errmsg("could not create relation %u/%u: %m",
+                                               reln->smgr_rnode.tblNode,
+                                               reln->smgr_rnode.relNode)));
+
+       if (isRedo)
+               return;
 
        /* Add the relation to the list of stuff to delete at abort */
        pending = (PendingRelDelete *)
                MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete));
-       pending->relnode = reln->rd_node;
-       pending->which = which;
-       pending->isTemp = reln->rd_istemp;
+       pending->relnode = reln->smgr_rnode;
+       pending->which = reln->smgr_which;
+       pending->isTemp = isTemp;
        pending->atCommit = false;      /* delete if abort */
        pending->next = pendingDeletes;
        pendingDeletes = pending;
-
-       return fd;
 }
 
 /*
- *     smgrunlink() -- Unlink a relation.
+ *     smgrscheduleunlink() -- Schedule unlinking a relation at xact commit.
+ *
+ *             The relation is marked to be removed from the store if we
+ *             successfully commit the current transaction.
  *
- *             The relation is removed from the store.  Actually, we just remember
- *             that we want to do this at transaction commit.
+ * This also implies smgrclose() on the SMgrRelation object.
  */
-int
-smgrunlink(int16 which, Relation reln)
+void
+smgrscheduleunlink(SMgrRelation reln, bool isTemp)
 {
        PendingRelDelete *pending;
 
-       /* Make sure the file is closed */
-       if (reln->rd_fd >= 0)
-               smgrclose(which, reln);
-
        /* Add the relation to the list of stuff to delete at commit */
        pending = (PendingRelDelete *)
                MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete));
-       pending->relnode = reln->rd_node;
-       pending->which = which;
-       pending->isTemp = reln->rd_istemp;
+       pending->relnode = reln->smgr_rnode;
+       pending->which = reln->smgr_which;
+       pending->isTemp = isTemp;
        pending->atCommit = true;       /* delete if commit */
        pending->next = pendingDeletes;
        pendingDeletes = pending;
@@ -224,78 +330,83 @@ smgrunlink(int16 which, Relation reln)
         * immediately, but for now I'll keep the logic simple.
         */
 
-       return SM_SUCCESS;
+       /* Now close the file and throw away the hashtable entry */
+       smgrclose(reln);
 }
 
 /*
- *     smgrextend() -- Add a new block to a file.
+ *     smgrdounlink() -- Immediately unlink a relation.
  *
- *             The semantics are basically the same as smgrwrite(): write at the
- *             specified position.  However, we are expecting to extend the
- *             relation (ie, blocknum is the current EOF), and so in case of
- *             failure we clean up by truncating.
+ *             The relation is removed from the store.  This should not be used
+ *             during transactional operations, since it can't be undone.
  *
- *             Returns SM_SUCCESS on success; aborts the current transaction on
- *             failure.
+ *             If isRedo is true, it is okay for the underlying file to be gone
+ *             already.  (In practice isRedo will always be true.)
+ *
+ * This also implies smgrclose() on the SMgrRelation object.
  */
-int
-smgrextend(int16 which, Relation reln, BlockNumber blocknum, char *buffer)
+void
+smgrdounlink(SMgrRelation reln, bool isTemp, bool isRedo)
 {
-       int                     status;
+       RelFileNode     rnode = reln->smgr_rnode;
+       int                     which = reln->smgr_which;
 
-       status = (*(smgrsw[which].smgr_extend)) (reln, blocknum, buffer);
-
-       if (status == SM_FAIL)
-               ereport(ERROR,
-                               (errcode_for_file_access(),
-                                errmsg("could not extend relation \"%s\": %m",
-                                               RelationGetRelationName(reln)),
-                                errhint("Check free disk space.")));
+       /* Close the file and throw away the hashtable entry */
+       smgrclose(reln);
 
-       return status;
+       smgr_internal_unlink(rnode, which, isTemp, isRedo);
 }
 
 /*
- *     smgropen() -- Open a relation using a particular storage manager.
- *
- *             Returns the fd for the open relation on success.
- *
- *             On failure, returns -1 if failOK, else aborts the transaction.
+ * Shared subroutine that actually does the unlink ...
  */
-int
-smgropen(int16 which, Relation reln, bool failOK)
+static void
+smgr_internal_unlink(RelFileNode rnode, int which, bool isTemp, bool isRedo)
 {
-       int                     fd;
-
-       if (reln->rd_rel->relkind == RELKIND_VIEW)
-               return -1;
-       if (reln->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-               return -1;
-       if ((fd = (*(smgrsw[which].smgr_open)) (reln)) < 0)
-               if (!failOK)
-                       ereport(ERROR,
-                                       (errcode_for_file_access(),
-                                        errmsg("could not open file \"%s\": %m",
-                                                       RelationGetRelationName(reln))));
-
-       return fd;
+       /*
+        * Get rid of any leftover buffers for the rel (shouldn't be any in the
+        * commit case, but there can be in the abort case).
+        */
+       DropRelFileNodeBuffers(rnode, isTemp);
+
+       /*
+        * Tell the free space map to forget this relation.  It won't be accessed
+        * any more anyway, but we may as well recycle the map space quickly.
+        */
+       FreeSpaceMapForgetRel(&rnode);
+
+       /*
+        * And delete the physical files.
+        *
+        * Note: we treat deletion failure as a WARNING, not an error,
+        * because we've already decided to commit or abort the current xact.
+        */
+       if (! (*(smgrsw[which].smgr_unlink)) (rnode, isRedo))
+               ereport(WARNING,
+                               (errcode_for_file_access(),
+                                errmsg("could not unlink relation %u/%u: %m",
+                                               rnode.tblNode,
+                                               rnode.relNode)));
 }
 
 /*
- *     smgrclose() -- Close a relation.
+ *     smgrextend() -- Add a new block to a file.
  *
- *             Returns SM_SUCCESS on success, aborts on failure.
+ *             The semantics are basically the same as smgrwrite(): write at the
+ *             specified position.  However, we are expecting to extend the
+ *             relation (ie, blocknum is the current EOF), and so in case of
+ *             failure we clean up by truncating.
  */
-int
-smgrclose(int16 which, Relation reln)
+void
+smgrextend(SMgrRelation reln, BlockNumber blocknum, char *buffer)
 {
-       if ((*(smgrsw[which].smgr_close)) (reln) == SM_FAIL)
+       if (! (*(smgrsw[reln->smgr_which].smgr_extend)) (reln, blocknum, buffer))
                ereport(ERROR,
                                (errcode_for_file_access(),
-                                errmsg("could not close relation \"%s\": %m",
-                                               RelationGetRelationName(reln))));
-
-       return SM_SUCCESS;
+                                errmsg("could not extend relation %u/%u: %m",
+                                               reln->smgr_rnode.tblNode,
+                                               reln->smgr_rnode.relNode),
+                                errhint("Check free disk space.")));
 }
 
 /*
@@ -304,24 +415,18 @@ smgrclose(int16 which, Relation reln)
  *
  *             This routine is called from the buffer manager in order to
  *             instantiate pages in the shared buffer cache.  All storage managers
- *             return pages in the format that POSTGRES expects.  This routine
- *             dispatches the read.  On success, it returns SM_SUCCESS.  On failure,
- *             the current transaction is aborted.
+ *             return pages in the format that POSTGRES expects.
  */
-int
-smgrread(int16 which, Relation reln, BlockNumber blocknum, char *buffer)
+void
+smgrread(SMgrRelation reln, BlockNumber blocknum, char *buffer)
 {
-       int                     status;
-
-       status = (*(smgrsw[which].smgr_read)) (reln, blocknum, buffer);
-
-       if (status == SM_FAIL)
+       if (! (*(smgrsw[reln->smgr_which].smgr_read)) (reln, blocknum, buffer))
                ereport(ERROR,
                                (errcode_for_file_access(),
-                                errmsg("could not read block %d of relation \"%s\": %m",
-                                               blocknum, RelationGetRelationName(reln))));
-
-       return status;
+                                errmsg("could not read block %u of relation %u/%u: %m",
+                                               blocknum,
+                                               reln->smgr_rnode.tblNode,
+                                               reln->smgr_rnode.relNode)));
 }
 
 /*
@@ -329,56 +434,17 @@ smgrread(int16 which, Relation reln, BlockNumber blocknum, char *buffer)
  *
  *             This is not a synchronous write -- the block is not necessarily
  *             on disk at return, only dumped out to the kernel.
- *
- *             The buffer is written out via the appropriate
- *             storage manager.  This routine returns SM_SUCCESS or aborts
- *             the current transaction.
  */
-int
-smgrwrite(int16 which, Relation reln, BlockNumber blocknum, char *buffer)
-{
-       int                     status;
-
-       status = (*(smgrsw[which].smgr_write)) (reln, blocknum, buffer);
-
-       if (status == SM_FAIL)
-               ereport(ERROR,
-                               (errcode_for_file_access(),
-                                errmsg("could not write block %d of relation \"%s\": %m",
-                                               blocknum, RelationGetRelationName(reln))));
-
-       return status;
-}
-
-/*
- *     smgrblindwrt() -- Write a page out blind.
- *
- *             In some cases, we may find a page in the buffer cache that we
- *             can't make a reldesc for.  This happens, for example, when we
- *             want to reuse a dirty page that was written by a transaction
- *             that has not yet committed, which created a new relation.  In
- *             this case, the buffer manager will call smgrblindwrt() with
- *             the name and OID of the database and the relation to which the
- *             buffer belongs.  Every storage manager must be able to write
- *             this page out to stable storage in this circumstance.
- */
-int
-smgrblindwrt(int16 which,
-                        RelFileNode rnode,
-                        BlockNumber blkno,
-                        char *buffer)
+void
+smgrwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer)
 {
-       int                     status;
-
-       status = (*(smgrsw[which].smgr_blindwrt)) (rnode, blkno, buffer);
-
-       if (status == SM_FAIL)
+       if (! (*(smgrsw[reln->smgr_which].smgr_write)) (reln, blocknum, buffer))
                ereport(ERROR,
                                (errcode_for_file_access(),
-                                errmsg("could not write block %d of %u/%u blind: %m",
-                                               blkno, rnode.tblNode, rnode.relNode)));
-
-       return status;
+                                errmsg("could not write block %u of relation %u/%u: %m",
+                                               blocknum,
+                                               reln->smgr_rnode.tblNode,
+                                               reln->smgr_rnode.relNode)));
 }
 
 /*
@@ -389,11 +455,11 @@ smgrblindwrt(int16 which,
  *             transaction on failure.
  */
 BlockNumber
-smgrnblocks(int16 which, Relation reln)
+smgrnblocks(SMgrRelation reln)
 {
        BlockNumber nblocks;
 
-       nblocks = (*(smgrsw[which].smgr_nblocks)) (reln);
+       nblocks = (*(smgrsw[reln->smgr_which].smgr_nblocks)) (reln);
 
        /*
         * NOTE: if a relation ever did grow to 2^32-1 blocks, this code would
@@ -404,8 +470,9 @@ smgrnblocks(int16 which, Relation reln)
        if (nblocks == InvalidBlockNumber)
                ereport(ERROR,
                                (errcode_for_file_access(),
-                                errmsg("could not count blocks of relation \"%s\": %m",
-                                               RelationGetRelationName(reln))));
+                                errmsg("could not count blocks of relation %u/%u: %m",
+                                               reln->smgr_rnode.tblNode,
+                                               reln->smgr_rnode.relNode)));
 
        return nblocks;
 }
@@ -418,27 +485,25 @@ smgrnblocks(int16 which, Relation reln)
  *             transaction on failure.
  */
 BlockNumber
-smgrtruncate(int16 which, Relation reln, BlockNumber nblocks)
+smgrtruncate(SMgrRelation reln, BlockNumber nblocks)
 {
        BlockNumber newblks;
 
-       newblks = nblocks;
-       if (smgrsw[which].smgr_truncate)
-       {
-               /*
-                * Tell the free space map to forget anything it may have stored
-                * for the about-to-be-deleted blocks.  We want to be sure it
-                * won't return bogus block numbers later on.
-                */
-               FreeSpaceMapTruncateRel(&reln->rd_node, nblocks);
-
-               newblks = (*(smgrsw[which].smgr_truncate)) (reln, nblocks);
-               if (newblks == InvalidBlockNumber)
-                       ereport(ERROR,
-                                       (errcode_for_file_access(),
-                                        errmsg("could not truncate relation \"%s\" to %u blocks: %m",
-                                                       RelationGetRelationName(reln), nblocks)));
-       }
+       /*
+        * Tell the free space map to forget anything it may have stored
+        * for the about-to-be-deleted blocks.  We want to be sure it
+        * won't return bogus block numbers later on.
+        */
+       FreeSpaceMapTruncateRel(&reln->smgr_rnode, nblocks);
+
+       newblks = (*(smgrsw[reln->smgr_which].smgr_truncate)) (reln, nblocks);
+       if (newblks == InvalidBlockNumber)
+               ereport(ERROR,
+                               (errcode_for_file_access(),
+                                errmsg("could not truncate relation %u/%u to %u blocks: %m",
+                                               reln->smgr_rnode.tblNode,
+                                               reln->smgr_rnode.relNode,
+                                               nblocks)));
 
        return newblks;
 }
@@ -446,7 +511,7 @@ smgrtruncate(int16 which, Relation reln, BlockNumber nblocks)
 /*
  *     smgrDoPendingDeletes() -- Take care of relation deletes at end of xact.
  */
-int
+void
 smgrDoPendingDeletes(bool isCommit)
 {
        while (pendingDeletes != NULL)
@@ -455,39 +520,12 @@ smgrDoPendingDeletes(bool isCommit)
 
                pendingDeletes = pending->next;
                if (pending->atCommit == isCommit)
-               {
-                       /*
-                        * Get rid of any leftover buffers for the rel (shouldn't be
-                        * any in the commit case, but there can be in the abort
-                        * case).
-                        */
-                       DropRelFileNodeBuffers(pending->relnode, pending->isTemp);
-
-                       /*
-                        * Tell the free space map to forget this relation.  It won't
-                        * be accessed any more anyway, but we may as well recycle the
-                        * map space quickly.
-                        */
-                       FreeSpaceMapForgetRel(&pending->relnode);
-
-                       /*
-                        * And delete the physical files.
-                        *
-                        * Note: we treat deletion failure as a WARNING, not an error,
-                        * because we've already decided to commit or abort the
-                        * current xact.
-                        */
-                       if ((*(smgrsw[pending->which].smgr_unlink)) (pending->relnode) == SM_FAIL)
-                               ereport(WARNING,
-                                               (errcode_for_file_access(),
-                                                errmsg("could not unlink %u/%u: %m",
-                                                               pending->relnode.tblNode,
-                                                               pending->relnode.relNode)));
-               }
+                       smgr_internal_unlink(pending->relnode,
+                                                                pending->which,
+                                                                pending->isTemp,
+                                                                false);
                pfree(pending);
        }
-
-       return SM_SUCCESS;
 }
 
 /*
@@ -496,7 +534,7 @@ smgrDoPendingDeletes(bool isCommit)
  *
  *             This is called before we actually commit.
  */
-int
+void
 smgrcommit(void)
 {
        int                     i;
@@ -505,20 +543,18 @@ smgrcommit(void)
        {
                if (smgrsw[i].smgr_commit)
                {
-                       if ((*(smgrsw[i].smgr_commit)) () == SM_FAIL)
+                       if (! (*(smgrsw[i].smgr_commit)) ())
                                elog(FATAL, "transaction commit failed on %s: %m",
                                         DatumGetCString(DirectFunctionCall1(smgrout,
                                                                                                         Int16GetDatum(i))));
                }
        }
-
-       return SM_SUCCESS;
 }
 
 /*
  *     smgrabort() -- Abort changes made during the current transaction.
  */
-int
+void
 smgrabort(void)
 {
        int                     i;
@@ -527,20 +563,18 @@ smgrabort(void)
        {
                if (smgrsw[i].smgr_abort)
                {
-                       if ((*(smgrsw[i].smgr_abort)) () == SM_FAIL)
+                       if (! (*(smgrsw[i].smgr_abort)) ())
                                elog(FATAL, "transaction abort failed on %s: %m",
                                         DatumGetCString(DirectFunctionCall1(smgrout,
                                                                                                         Int16GetDatum(i))));
                }
        }
-
-       return SM_SUCCESS;
 }
 
 /*
  *     smgrsync() -- Sync files to disk at checkpoint time.
  */
-int
+void
 smgrsync(void)
 {
        int                     i;
@@ -549,26 +583,14 @@ smgrsync(void)
        {
                if (smgrsw[i].smgr_sync)
                {
-                       if ((*(smgrsw[i].smgr_sync)) () == SM_FAIL)
+                       if (! (*(smgrsw[i].smgr_sync)) ())
                                elog(PANIC, "storage sync failed on %s: %m",
                                         DatumGetCString(DirectFunctionCall1(smgrout,
                                                                                                         Int16GetDatum(i))));
                }
        }
-
-       return SM_SUCCESS;
 }
 
-#ifdef NOT_USED
-bool
-smgriswo(int16 smgrno)
-{
-       if (smgrno < 0 || smgrno >= NSmgr)
-               elog(ERROR, "invalid storage manager id: %d", smgrno);
-
-       return smgrwo[smgrno];
-}
-#endif
 
 void
 smgr_redo(XLogRecPtr lsn, XLogRecord *record)
index 10e084524188f12d0ce058044e1af1eca697d082..60cc305bd1b1030ce972b5e529ac957da23c17e7 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/smgr/smgrtype.c,v 1.22 2003/11/29 19:51:57 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/smgr/smgrtype.c,v 1.23 2004/02/10 01:55:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "storage/smgr.h"
 
+
 typedef struct smgrid
 {
-       char       *smgr_name;
+       const char         *smgr_name;
 } smgrid;
 
 /*
  *     StorageManager[] -- List of defined storage managers.
- *
- *             The weird comma placement is to keep compilers happy no matter
- *             which of these is (or is not) defined.
  */
-
-static smgrid StorageManager[] = {
-       {"magnetic disk"},
-#ifdef STABLE_MEMORY_STORAGE
-       {"main memory"}
-#endif
+static const smgrid StorageManager[] = {
+       {"magnetic disk"}
 };
 
-static int     NStorageManagers = lengthof(StorageManager);
+static const int       NStorageManagers = lengthof(StorageManager);
+
 
 Datum
 smgrin(PG_FUNCTION_ARGS)
index 72c9310110625831f6192b77e81d7a36967802be..8a23fcc70ef66908f409d8bc2ee0a232d0ad115e 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.209 2003/11/29 19:51:57 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.210 2004/02/10 01:55:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -48,6 +48,7 @@
 #include "parser/parse_type.h"
 #include "rewrite/rewriteDefine.h"
 #include "rewrite/rewriteRemove.h"
+#include "storage/fd.h"
 #include "tcop/pquery.h"
 #include "tcop/utility.h"
 #include "utils/acl.h"
index 90577cb6e4021a892d8250c4242aa3cf7a7edf7f..3364322dd5b89eff163493c56642475b0f016eb0 100644 (file)
@@ -74,7 +74,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.59 2003/11/29 19:52:00 pgsql Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.60 2004/02/10 01:55:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -83,6 +83,7 @@
 #include "catalog/catalog.h"
 #include "miscadmin.h"
 #include "storage/sinval.h"
+#include "storage/smgr.h"
 #include "utils/catcache.h"
 #include "utils/inval.h"
 #include "utils/memutils.h"
@@ -298,19 +299,22 @@ AddCatcacheInvalidationMessage(InvalidationListHeader *hdr,
  */
 static void
 AddRelcacheInvalidationMessage(InvalidationListHeader *hdr,
-                                                          Oid dbId, Oid relId)
+                                                          Oid dbId, Oid relId, RelFileNode physId)
 {
        SharedInvalidationMessage msg;
 
        /* Don't add a duplicate item */
-       /* We assume comparing relId is sufficient, needn't check dbId */
+       /* We assume dbId need not be checked because it will never change */
+       /* relfilenode fields must be checked to support reassignment */
        ProcessMessageList(hdr->rclist,
-                                          if (msg->rc.relId == relId) return);
+                                          if (msg->rc.relId == relId && 
+                                                  RelFileNodeEquals(msg->rc.physId, physId)) return);
 
        /* OK, add the item */
        msg.rc.id = SHAREDINVALRELCACHE_ID;
        msg.rc.dbId = dbId;
        msg.rc.relId = relId;
+       msg.rc.physId = physId;
        AddInvalidationMessage(&hdr->rclist, &msg);
 }
 
@@ -391,10 +395,10 @@ RegisterCatcacheInvalidation(int cacheId,
  * As above, but register a relcache invalidation event.
  */
 static void
-RegisterRelcacheInvalidation(Oid dbId, Oid relId)
+RegisterRelcacheInvalidation(Oid dbId, Oid relId, RelFileNode physId)
 {
        AddRelcacheInvalidationMessage(&CurrentCmdInvalidMsgs,
-                                                                  dbId, relId);
+                                                                  dbId, relId, physId);
 
        /*
         * If the relation being invalidated is one of those cached in the
@@ -435,9 +439,17 @@ LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
        }
        else if (msg->id == SHAREDINVALRELCACHE_ID)
        {
-               if (msg->rc.dbId == MyDatabaseId || msg->rc.dbId == 0)
+               /*
+                * If the message includes a valid relfilenode, we must ensure that
+                * smgr cache entry gets zapped.  The relcache will handle this if
+                * called, otherwise we must do it directly.
+                */
+               if (msg->rc.dbId == MyDatabaseId || msg->rc.dbId == InvalidOid)
                {
-                       RelationIdInvalidateRelationCacheByRelationId(msg->rc.relId);
+                       if (OidIsValid(msg->rc.physId.relNode))
+                               RelationCacheInvalidateEntry(msg->rc.relId, &msg->rc.physId);
+                       else
+                               RelationCacheInvalidateEntry(msg->rc.relId, NULL);
 
                        for (i = 0; i < cache_callback_count; i++)
                        {
@@ -447,6 +459,12 @@ LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
                                        (*ccitem->function) (ccitem->arg, msg->rc.relId);
                        }
                }
+               else
+               {
+                       /* might have smgr entry even if not in our database */
+                       if (OidIsValid(msg->rc.physId.relNode))
+                               smgrclosenode(msg->rc.physId);
+               }
        }
        else
                elog(FATAL, "unrecognized SI message id: %d", msg->id);
@@ -456,7 +474,7 @@ LocalExecuteInvalidationMessage(SharedInvalidationMessage *msg)
  *             InvalidateSystemCaches
  *
  *             This blows away all tuples in the system catalog caches and
- *             all the cached relation descriptors (and closes their files too).
+ *             all the cached relation descriptors and smgr cache entries.
  *             Relation descriptors that have positive refcounts are then rebuilt.
  *
  *             We call this when we see a shared-inval-queue overflow signal,
@@ -469,7 +487,7 @@ InvalidateSystemCaches(void)
        int                     i;
 
        ResetCatalogCaches();
-       RelationCacheInvalidate();
+       RelationCacheInvalidate();      /* gets smgr cache too */
 
        for (i = 0; i < cache_callback_count; i++)
        {
@@ -488,11 +506,15 @@ static void
 PrepareForTupleInvalidation(Relation relation, HeapTuple tuple,
                                                        void (*CacheIdRegisterFunc) (int, uint32,
                                                                                                           ItemPointer, Oid),
-                                                       void (*RelationIdRegisterFunc) (Oid, Oid))
+                                                       void (*RelationIdRegisterFunc) (Oid, Oid,
+                                                                                                                       RelFileNode))
 {
        Oid                     tupleRelId;
+       Oid                     databaseId;
        Oid                     relationId;
+       RelFileNode     rnode;
 
+       /* Do nothing during bootstrap */
        if (IsBootstrapProcessingMode())
                return;
 
@@ -524,24 +546,49 @@ PrepareForTupleInvalidation(Relation relation, HeapTuple tuple,
        tupleRelId = RelationGetRelid(relation);
 
        if (tupleRelId == RelOid_pg_class)
+       {
+               Form_pg_class classtup = (Form_pg_class) GETSTRUCT(tuple);
+
                relationId = HeapTupleGetOid(tuple);
+               if (classtup->relisshared)
+                       databaseId = InvalidOid;
+               else
+                       databaseId = MyDatabaseId;
+               rnode.tblNode = databaseId;                     /* XXX change for tablespaces */
+               rnode.relNode = classtup->relfilenode;
+               /*
+                * Note: during a pg_class row update that assigns a new relfilenode
+                * value, we will be called on both the old and new tuples, and thus
+                * will broadcast invalidation messages showing both the old and new
+                * relfilenode values.  This ensures that other backends will close
+                * smgr references to the old relfilenode file.
+                */
+       }
        else if (tupleRelId == RelOid_pg_attribute)
-               relationId = ((Form_pg_attribute) GETSTRUCT(tuple))->attrelid;
+       {
+               Form_pg_attribute atttup = (Form_pg_attribute) GETSTRUCT(tuple);
+
+               relationId = atttup->attrelid;
+               /*
+                * KLUGE ALERT: we always send the relcache event with MyDatabaseId,
+                * even if the rel in question is shared (which we can't easily tell).
+                * This essentially means that only backends in this same database
+                * will react to the relcache flush request.  This is in fact
+                * appropriate, since only those backends could see our pg_attribute
+                * change anyway.  It looks a bit ugly though.
+                */
+               databaseId = MyDatabaseId;
+               /* We assume no smgr cache flush is needed, either */
+               rnode.tblNode = InvalidOid;
+               rnode.relNode = InvalidOid;
+       }
        else
                return;
 
        /*
-        * Yes.  We need to register a relcache invalidation event for the
-        * relation identified by relationId.
-        *
-        * KLUGE ALERT: we always send the relcache event with MyDatabaseId, even
-        * if the rel in question is shared.  This essentially means that only
-        * backends in this same database will react to the relcache flush
-        * request.  This is in fact appropriate, since only those backends
-        * could see our pg_class or pg_attribute change anyway.  It looks a
-        * bit ugly though.
+        * Yes.  We need to register a relcache invalidation event.
         */
-       (*RelationIdRegisterFunc) (MyDatabaseId, relationId);
+       (*RelationIdRegisterFunc) (databaseId, relationId, rnode);
 }
 
 
@@ -660,7 +707,7 @@ CommandEndInvalidationMessages(bool isCommit)
 /*
  * CacheInvalidateHeapTuple
  *             Register the given tuple for invalidation at end of command
- *             (ie, current command is outdating this tuple).
+ *             (ie, current command is creating or outdating this tuple).
  */
 void
 CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple)
@@ -678,12 +725,44 @@ CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple)
  * This is used in places that need to force relcache rebuild but aren't
  * changing any of the tuples recognized as contributors to the relcache
  * entry by PrepareForTupleInvalidation.  (An example is dropping an index.)
+ * We assume in particular that relfilenode isn't changing.
  */
 void
-CacheInvalidateRelcache(Oid relationId)
+CacheInvalidateRelcache(Relation relation)
 {
-       /* See KLUGE ALERT in PrepareForTupleInvalidation */
-       RegisterRelcacheInvalidation(MyDatabaseId, relationId);
+       Oid                     databaseId;
+       Oid                     relationId;
+
+       relationId = RelationGetRelid(relation);
+       if (relation->rd_rel->relisshared)
+               databaseId = InvalidOid;
+       else
+               databaseId = MyDatabaseId;
+
+       RegisterRelcacheInvalidation(databaseId, relationId, relation->rd_node);
+}
+
+/*
+ * CacheInvalidateRelcacheByTuple
+ *             As above, but relation is identified by passing its pg_class tuple.
+ */
+void
+CacheInvalidateRelcacheByTuple(HeapTuple classTuple)
+{
+       Form_pg_class classtup = (Form_pg_class) GETSTRUCT(classTuple);
+       Oid                     databaseId;
+       Oid                     relationId;
+       RelFileNode     rnode;
+
+       relationId = HeapTupleGetOid(classTuple);
+       if (classtup->relisshared)
+               databaseId = InvalidOid;
+       else
+               databaseId = MyDatabaseId;
+       rnode.tblNode = databaseId;                     /* XXX change for tablespaces */
+       rnode.relNode = classtup->relfilenode;
+
+       RegisterRelcacheInvalidation(databaseId, relationId, rnode);
 }
 
 /*
index 37b81f1244f8021ffb3671ca234a7dc2ca45584d..8561cff549abe3b978be060d3af618812b895d58 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.196 2004/02/02 00:17:21 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.197 2004/02/10 01:55:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -54,6 +54,7 @@
 #include "optimizer/clauses.h"
 #include "optimizer/planmain.h"
 #include "optimizer/prep.h"
+#include "storage/fd.h"
 #include "storage/smgr.h"
 #include "utils/builtins.h"
 #include "utils/catcache.h"
@@ -91,13 +92,6 @@ static FormData_pg_attribute Desc_pg_type[Natts_pg_type] = {Schema_pg_type};
 static HTAB *RelationIdCache;
 static HTAB *RelationSysNameCache;
 
-/*
- * Bufmgr uses RelFileNode for lookup. Actually, I would like to do
- * not pass Relation to bufmgr & beyond at all and keep some cache
- * in smgr, but no time to do it right way now.                -- vadim 10/22/2000
- */
-static HTAB *RelationNodeCache;
-
 /*
  * This flag is false until we have prepared the critical relcache entries
  * that are needed to do indexscans on the tables read by relcache building.
@@ -152,18 +146,12 @@ typedef struct relnamecacheent
        Relation        reldesc;
 } RelNameCacheEnt;
 
-typedef struct relnodecacheent
-{
-       RelFileNode relnode;
-       Relation        reldesc;
-} RelNodeCacheEnt;
-
 /*
  *             macros to manipulate the lookup hashtables
  */
 #define RelationCacheInsert(RELATION)  \
 do { \
-       RelIdCacheEnt *idhentry; RelNodeCacheEnt *nodentry; bool found; \
+       RelIdCacheEnt *idhentry; bool found; \
        idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
                                                                                   (void *) &(RELATION->rd_id), \
                                                                                   HASH_ENTER, \
@@ -174,16 +162,6 @@ do { \
                                 errmsg("out of memory"))); \
        /* used to give notice if found -- now just keep quiet */ \
        idhentry->reldesc = RELATION; \
-       nodentry = (RelNodeCacheEnt*)hash_search(RelationNodeCache, \
-                                                                                  (void *) &(RELATION->rd_node), \
-                                                                                  HASH_ENTER, \
-                                                                                  &found); \
-       if (nodentry == NULL) \
-               ereport(ERROR, \
-                               (errcode(ERRCODE_OUT_OF_MEMORY), \
-                                errmsg("out of memory"))); \
-       /* used to give notice if found -- now just keep quiet */ \
-       nodentry->reldesc = RELATION; \
        if (IsSystemNamespace(RelationGetNamespace(RELATION))) \
        { \
                char *relname = RelationGetRelationName(RELATION); \
@@ -223,30 +201,14 @@ do { \
                RELATION = NULL; \
 } while(0)
 
-#define RelationNodeCacheLookup(NODE, RELATION) \
-do { \
-       RelNodeCacheEnt *hentry; \
-       hentry = (RelNodeCacheEnt*)hash_search(RelationNodeCache, \
-                                                                                  (void *)&(NODE), HASH_FIND,NULL); \
-       if (hentry) \
-               RELATION = hentry->reldesc; \
-       else \
-               RELATION = NULL; \
-} while(0)
-
 #define RelationCacheDelete(RELATION) \
 do { \
-       RelIdCacheEnt *idhentry; RelNodeCacheEnt *nodentry; \
+       RelIdCacheEnt *idhentry; \
        idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
                                                                                   (void *)&(RELATION->rd_id), \
                                                                                   HASH_REMOVE, NULL); \
        if (idhentry == NULL) \
                elog(WARNING, "trying to delete a rd_id reldesc that does not exist"); \
-       nodentry = (RelNodeCacheEnt*)hash_search(RelationNodeCache, \
-                                                                                  (void *)&(RELATION->rd_node), \
-                                                                                  HASH_REMOVE, NULL); \
-       if (nodentry == NULL) \
-               elog(WARNING, "trying to delete a rd_node reldesc that does not exist"); \
        if (IsSystemNamespace(RelationGetNamespace(RELATION))) \
        { \
                char *relname = RelationGetRelationName(RELATION); \
@@ -423,7 +385,7 @@ AllocateRelationDesc(Relation relation, Form_pg_class relp)
        relation->rd_targblock = InvalidBlockNumber;
 
        /* make sure relation is marked as having no open file yet */
-       relation->rd_fd = -1;
+       relation->rd_smgr = NULL;
 
        /*
         * Copy the relation tuple form
@@ -914,7 +876,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
        relation->rd_node.relNode = relation->rd_rel->relfilenode;
 
        /* make sure relation is marked as having no open file yet */
-       relation->rd_fd = -1;
+       relation->rd_smgr = NULL;
 
        /*
         * Insert newly created relation into relcache hash tables.
@@ -1303,7 +1265,7 @@ formrdesc(const char *relationName,
        relation->rd_targblock = InvalidBlockNumber;
 
        /* make sure relation is marked as having no open file yet */
-       relation->rd_fd = -1;
+       relation->rd_smgr = NULL;
 
        /*
         * initialize reference count
@@ -1481,30 +1443,6 @@ RelationSysNameCacheGetRelation(const char *relationName)
        return rd;
 }
 
-/*
- *             RelationNodeCacheGetRelation
- *
- *             As above, but lookup by relfilenode.
- *
- * NOTE: this must NOT try to revalidate invalidated nailed indexes, since
- * that could cause us to return an entry with a different relfilenode than
- * the caller asked for.  Currently this is used only by the buffer manager.
- * Really the bufmgr's idea of relations should be separated out from the
- * relcache ...
- */
-Relation
-RelationNodeCacheGetRelation(RelFileNode rnode)
-{
-       Relation        rd;
-
-       RelationNodeCacheLookup(rnode, rd);
-
-       if (RelationIsValid(rd))
-               RelationIncrementReferenceCount(rd);
-
-       return rd;
-}
-
 /*
  *             RelationIdGetRelation
  *
@@ -1635,14 +1573,8 @@ RelationReloadClassinfo(Relation relation)
                elog(ERROR, "could not find tuple for system relation %u",
                         relation->rd_id);
        relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
-       if (relation->rd_node.relNode != relp->relfilenode)
-       {
-               /* We have to re-insert the entry into the relcache indexes */
-               RelationCacheDelete(relation);
-               memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
-               relation->rd_node.relNode = relp->relfilenode;
-               RelationCacheInsert(relation);
-       }
+       memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE);
+       relation->rd_node.relNode = relp->relfilenode;
        heap_freetuple(pg_class_tuple);
        /* Must adjust number of blocks after we know the new relfilenode */
        relation->rd_targblock = InvalidBlockNumber;
@@ -1672,10 +1604,10 @@ RelationClearRelation(Relation relation, bool rebuild)
         * ensures that the low-level file access state is updated after, say,
         * a vacuum truncation.
         */
-       if (relation->rd_fd >= 0)
+       if (relation->rd_smgr)
        {
-               smgrclose(DEFAULT_SMGR, relation);
-               relation->rd_fd = -1;
+               smgrclose(relation->rd_smgr);
+               relation->rd_smgr = NULL;
        }
 
        /*
@@ -1866,18 +1798,31 @@ RelationForgetRelation(Oid rid)
 }
 
 /*
- *             RelationIdInvalidateRelationCacheByRelationId
+ *             RelationCacheInvalidateEntry
  *
  *             This routine is invoked for SI cache flush messages.
  *
- *             We used to skip local relations, on the grounds that they could
- *             not be targets of cross-backend SI update messages; but it seems
- *             safer to process them, so that our *own* SI update messages will
- *             have the same effects during CommandCounterIncrement for both
- *             local and nonlocal relations.
+ * Any relcache entry matching the relid must be flushed.  (Note: caller has
+ * already determined that the relid belongs to our database or is a shared
+ * relation.)  If rnode isn't NULL, we must also ensure that any smgr cache
+ * entry matching that rnode is flushed.
+ *
+ * Ordinarily, if rnode is supplied then it will match the relfilenode of
+ * the target relid.  However, it's possible for rnode to be different if
+ * someone is engaged in a relfilenode change.  In that case we want to
+ * make sure we clear the right cache entries.  This has to be done here
+ * to keep things in sync between relcache and smgr cache --- we can't have
+ * someone flushing an smgr cache entry that a relcache entry still points
+ * to.
+ *
+ * We used to skip local relations, on the grounds that they could
+ * not be targets of cross-backend SI update messages; but it seems
+ * safer to process them, so that our *own* SI update messages will
+ * have the same effects during CommandCounterIncrement for both
+ * local and nonlocal relations.
  */
 void
-RelationIdInvalidateRelationCacheByRelationId(Oid relationId)
+RelationCacheInvalidateEntry(Oid relationId, RelFileNode *rnode)
 {
        Relation        relation;
 
@@ -1886,14 +1831,27 @@ RelationIdInvalidateRelationCacheByRelationId(Oid relationId)
        if (PointerIsValid(relation))
        {
                relcacheInvalsReceived++;
+               if (rnode)
+               {
+                       /* Need to be sure smgr is flushed, but don't do it twice */
+                       if (relation->rd_smgr == NULL ||
+                               !RelFileNodeEquals(*rnode, relation->rd_node))
+                               smgrclosenode(*rnode);
+               }
                RelationFlushRelation(relation);
        }
+       else
+       {
+               if (rnode)
+                       smgrclosenode(*rnode);
+       }
 }
 
 /*
  * RelationCacheInvalidate
  *      Blow away cached relation descriptors that have zero reference counts,
- *      and rebuild those with positive reference counts.
+ *      and rebuild those with positive reference counts.  Also reset the smgr
+ *      relation cache.
  *
  *      This is currently used only to recover from SI message buffer overflow,
  *      so we do not touch new-in-transaction relations; they cannot be targets
@@ -1934,6 +1892,13 @@ RelationCacheInvalidate(void)
        {
                relation = idhentry->reldesc;
 
+               /* Must close all smgr references to avoid leaving dangling ptrs */
+               if (relation->rd_smgr)
+               {
+                       smgrclose(relation->rd_smgr);
+                       relation->rd_smgr = NULL;
+               }
+
                /* Ignore new relations, since they are never SI targets */
                if (relation->rd_isnew)
                        continue;
@@ -1970,6 +1935,13 @@ RelationCacheInvalidate(void)
 
        rebuildList = nconc(rebuildFirstList, rebuildList);
 
+       /*
+        * Now zap any remaining smgr cache entries.  This must happen before
+        * we start to rebuild entries, since that may involve catalog fetches
+        * which will re-open catalog files.
+        */
+       smgrcloseall();
+
        /* Phase 2: rebuild the items found to need rebuild in phase 1 */
        foreach(l, rebuildList)
        {
@@ -2107,7 +2079,7 @@ RelationBuildLocalRelation(const char *relname,
        rel->rd_targblock = InvalidBlockNumber;
 
        /* make sure relation is marked as having no open file yet */
-       rel->rd_fd = -1;
+       rel->rd_smgr = NULL;
 
        RelationSetReferenceCount(rel, 1);
 
@@ -2233,12 +2205,6 @@ RelationCacheInitialize(void)
        RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
                                                                  &ctl, HASH_ELEM | HASH_FUNCTION);
 
-       ctl.keysize = sizeof(RelFileNode);
-       ctl.entrysize = sizeof(RelNodeCacheEnt);
-       ctl.hash = tag_hash;
-       RelationNodeCache = hash_create("Relcache by rnode", INITRELCACHESIZE,
-                                                                       &ctl, HASH_ELEM | HASH_FUNCTION);
-
        /*
         * Try to load the relcache cache file.  If successful, we're done for
         * now.  Otherwise, initialize the cache with pre-made descriptors for
@@ -2406,65 +2372,6 @@ RelationCacheInitializePhase3(void)
        }
 }
 
-
-/* used by XLogInitCache */
-void           CreateDummyCaches(void);
-void           DestroyDummyCaches(void);
-
-void
-CreateDummyCaches(void)
-{
-       MemoryContext oldcxt;
-       HASHCTL         ctl;
-
-       if (!CacheMemoryContext)
-               CreateCacheMemoryContext();
-
-       oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
-
-       MemSet(&ctl, 0, sizeof(ctl));
-       ctl.keysize = sizeof(NameData);
-       ctl.entrysize = sizeof(RelNameCacheEnt);
-       RelationSysNameCache = hash_create("Relcache by name", INITRELCACHESIZE,
-                                                                          &ctl, HASH_ELEM);
-
-       ctl.keysize = sizeof(Oid);
-       ctl.entrysize = sizeof(RelIdCacheEnt);
-       ctl.hash = tag_hash;
-       RelationIdCache = hash_create("Relcache by OID", INITRELCACHESIZE,
-                                                                 &ctl, HASH_ELEM | HASH_FUNCTION);
-
-       ctl.keysize = sizeof(RelFileNode);
-       ctl.entrysize = sizeof(RelNodeCacheEnt);
-       ctl.hash = tag_hash;
-       RelationNodeCache = hash_create("Relcache by rnode", INITRELCACHESIZE,
-                                                                       &ctl, HASH_ELEM | HASH_FUNCTION);
-
-       MemoryContextSwitchTo(oldcxt);
-}
-
-void
-DestroyDummyCaches(void)
-{
-       MemoryContext oldcxt;
-
-       if (!CacheMemoryContext)
-               return;
-
-       oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
-
-       if (RelationIdCache)
-               hash_destroy(RelationIdCache);
-       if (RelationSysNameCache)
-               hash_destroy(RelationSysNameCache);
-       if (RelationNodeCache)
-               hash_destroy(RelationNodeCache);
-
-       RelationIdCache = RelationSysNameCache = RelationNodeCache = NULL;
-
-       MemoryContextSwitchTo(oldcxt);
-}
-
 static void
 AttrDefaultFetch(Relation relation)
 {
@@ -3125,7 +3032,7 @@ load_relcache_init_file(void)
                /*
                 * Reset transient-state fields in the relcache entry
                 */
-               rel->rd_fd = -1;
+               rel->rd_smgr = NULL;
                rel->rd_targblock = InvalidBlockNumber;
                if (rel->rd_isnailed)
                        RelationSetReferenceCount(rel, 1);
index e93dcb8a84c7eb50d02bf1685dcaca7f0da18238..075269b4ad07cbea0b2c8a57c043ee2ead6308d6 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.122 2004/02/08 22:28:57 neilc Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.123 2004/02/10 01:55:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,6 +33,7 @@
 #include "catalog/pg_shadow.h"
 #include "libpq/libpq-be.h"
 #include "miscadmin.h"
+#include "storage/fd.h"
 #include "storage/ipc.h"
 #include "storage/pg_shmem.h"
 #include "utils/builtins.h"
index af113eb66a0ffbe64ca54413d2760afed072f035..226c5c2f99c045b217d2ba258259d95f9579be2b 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_database.h,v 1.30 2003/11/29 22:40:58 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_database.h,v 1.31 2004/02/10 01:55:26 tgl Exp $
  *
  * NOTES
  *       the genbki.sh script reads this file and generates .bki
@@ -72,15 +72,6 @@ typedef FormData_pg_database *Form_pg_database;
 
 DATA(insert OID = 1 (  template1 PGUID ENCODING t t 0 0 0 "" _null_ _null_ ));
 DESCR("Default template database");
-
 #define TemplateDbOid                  1
 
-/* Just to mark OID as used for unused_oid script -:) */
-#define DATAMARKOID(x)
-
-DATAMARKOID(= 2)
-#define RecoveryDb     2
-
-#undef DATAMARKOID
-
 #endif   /* PG_DATABASE_H */
index a0b523da3d41c14f17e96a1c6d9bf45a567ac85a..84706272decba1d241e2f366b8922f0050c0a989 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/sinval.h,v 1.32 2003/11/29 22:41:13 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/storage/sinval.h,v 1.33 2004/02/10 01:55:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 
 #include "storage/backendid.h"
 #include "storage/itemptr.h"
+#include "storage/relfilenode.h"
 
 
 /*
  * ID field).  -1 means a relcache inval message.  Other negative values
  * are available to identify other inval message types.
  *
+ * Relcache invalidation messages usually also cause invalidation of entries
+ * in the smgr's relation cache.  This means they must carry both logical
+ * and physical relation ID info (ie, both dbOID/relOID and RelFileNode).
+ * In some cases RelFileNode information is not available so the sender fills
+ * those fields with zeroes --- this is okay so long as no smgr cache flush
+ * is required.
+ *
  * Shared-inval events are initially driven by detecting tuple inserts,
  * updates and deletions in system catalogs (see CacheInvalidateHeapTuple).
  * An update generates two inval events, one for the old tuple and one for
@@ -63,6 +71,12 @@ typedef struct
        int16           id;                             /* type field --- must be first */
        Oid                     dbId;                   /* database ID, or 0 if a shared relation */
        Oid                     relId;                  /* relation ID */
+       RelFileNode     physId;                 /* physical file ID */
+       /*
+        * Note: it is likely that RelFileNode will someday be changed to
+        * include database ID.  In that case the dbId field will be redundant
+        * and should be removed to save space.
+        */
 } SharedInvalRelcacheMsg;
 
 typedef union
index 0fd20fd436f3a0d8d49017490f1f3dcb7d49e7e7..738e436fb7d3320c8d3c22c841cedeb68fd2442d 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/smgr.h,v 1.39 2003/11/29 22:41:13 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/storage/smgr.h,v 1.40 2004/02/10 01:55:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "access/xlog.h"
 #include "fmgr.h"
-#include "storage/relfilenode.h"
 #include "storage/block.h"
-#include "utils/rel.h"
+#include "storage/relfilenode.h"
+
+
+/*
+ * smgr.c maintains a table of SMgrRelation objects, which are essentially
+ * cached file handles.  An SMgrRelation is created (if not already present)
+ * by smgropen(), and destroyed by smgrclose().  Note that neither of these
+ * operations imply I/O, they just create or destroy a hashtable entry.
+ * (But smgrclose() may release associated resources, such as OS-level file
+ * descriptors.)
+ */
+typedef struct SMgrRelationData
+{
+       /* rnode is the hashtable lookup key, so it must be first! */
+       RelFileNode     smgr_rnode;             /* relation physical identifier */
 
+       /* additional public fields may someday exist here */
 
-#define SM_FAIL                        0
-#define SM_SUCCESS             1
+       /*
+        * Fields below here are intended to be private to smgr.c and its
+        * submodules.  Do not touch them from elsewhere.
+        */
+       int                     smgr_which;             /* storage manager selector */
 
-#define DEFAULT_SMGR   0
+       struct _MdfdVec *md_fd;         /* for md.c; NULL if not open */
+} SMgrRelationData;
 
-extern int     smgrinit(void);
-extern int     smgrcreate(int16 which, Relation reln);
-extern int     smgrunlink(int16 which, Relation reln);
-extern int smgrextend(int16 which, Relation reln, BlockNumber blocknum,
-                  char *buffer);
-extern int     smgropen(int16 which, Relation reln, bool failOK);
-extern int     smgrclose(int16 which, Relation reln);
-extern int smgrread(int16 which, Relation reln, BlockNumber blocknum,
-                char *buffer);
-extern int smgrwrite(int16 which, Relation reln, BlockNumber blocknum,
-                 char *buffer);
-extern int smgrblindwrt(int16 which, RelFileNode rnode,
-                        BlockNumber blkno, char *buffer);
-extern BlockNumber smgrnblocks(int16 which, Relation reln);
-extern BlockNumber smgrtruncate(int16 which, Relation reln,
-                        BlockNumber nblocks);
-extern int     smgrDoPendingDeletes(bool isCommit);
-extern int     smgrcommit(void);
-extern int     smgrabort(void);
-extern int     smgrsync(void);
+typedef SMgrRelationData *SMgrRelation;
+
+
+extern void smgrinit(void);
+extern SMgrRelation smgropen(RelFileNode rnode);
+extern void smgrclose(SMgrRelation reln);
+extern void smgrcloseall(void);
+extern void smgrclosenode(RelFileNode rnode);
+extern void smgrcreate(SMgrRelation reln, bool isTemp, bool isRedo);
+extern void smgrscheduleunlink(SMgrRelation reln, bool isTemp);
+extern void smgrdounlink(SMgrRelation reln, bool isTemp, bool isRedo);
+extern void smgrextend(SMgrRelation reln, BlockNumber blocknum, char *buffer);
+extern void smgrread(SMgrRelation reln, BlockNumber blocknum, char *buffer);
+extern void smgrwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer);
+extern BlockNumber smgrnblocks(SMgrRelation reln);
+extern BlockNumber smgrtruncate(SMgrRelation reln, BlockNumber nblocks);
+extern void smgrDoPendingDeletes(bool isCommit);
+extern void smgrcommit(void);
+extern void smgrabort(void);
+extern void smgrsync(void);
 
 extern void smgr_redo(XLogRecPtr lsn, XLogRecord *record);
 extern void smgr_undo(XLogRecPtr lsn, XLogRecord *record);
@@ -55,38 +73,18 @@ extern void smgr_desc(char *buf, uint8 xl_info, char *rec);
 /* internals: move me elsewhere -- ay 7/94 */
 
 /* in md.c */
-extern int     mdinit(void);
-extern int     mdcreate(Relation reln);
-extern int     mdunlink(RelFileNode rnode);
-extern int     mdextend(Relation reln, BlockNumber blocknum, char *buffer);
-extern int     mdopen(Relation reln);
-extern int     mdclose(Relation reln);
-extern int     mdread(Relation reln, BlockNumber blocknum, char *buffer);
-extern int     mdwrite(Relation reln, BlockNumber blocknum, char *buffer);
-extern int     mdblindwrt(RelFileNode rnode, BlockNumber blkno, char *buffer);
-extern BlockNumber mdnblocks(Relation reln);
-extern BlockNumber mdtruncate(Relation reln, BlockNumber nblocks);
-extern int     mdcommit(void);
-extern int     mdabort(void);
-extern int     mdsync(void);
-
-/* mm.c */
-extern int     mminit(void);
-extern int     mmcreate(Relation reln);
-extern int     mmunlink(RelFileNode rnode);
-extern int     mmextend(Relation reln, BlockNumber blocknum, char *buffer);
-extern int     mmopen(Relation reln);
-extern int     mmclose(Relation reln);
-extern int     mmread(Relation reln, BlockNumber blocknum, char *buffer);
-extern int     mmwrite(Relation reln, BlockNumber blocknum, char *buffer);
-extern int     mmblindwrt(RelFileNode rnode, BlockNumber blkno, char *buffer);
-extern BlockNumber mmnblocks(Relation reln);
-extern BlockNumber mmtruncate(Relation reln, BlockNumber nblocks);
-extern int     mmcommit(void);
-extern int     mmabort(void);
-
-extern int     mmshutdown(void);
-extern int     MMShmemSize(void);
+extern bool mdinit(void);
+extern bool mdclose(SMgrRelation reln);
+extern bool mdcreate(SMgrRelation reln, bool isRedo);
+extern bool mdunlink(RelFileNode rnode, bool isRedo);
+extern bool mdextend(SMgrRelation reln, BlockNumber blocknum, char *buffer);
+extern bool mdread(SMgrRelation reln, BlockNumber blocknum, char *buffer);
+extern bool mdwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer);
+extern BlockNumber mdnblocks(SMgrRelation reln);
+extern BlockNumber mdtruncate(SMgrRelation reln, BlockNumber nblocks);
+extern bool mdcommit(void);
+extern bool mdabort(void);
+extern bool mdsync(void);
 
 /* smgrtype.c */
 extern Datum smgrout(PG_FUNCTION_ARGS);
index 467d15ee8395160de2c91b7cd04db52bc6757948..e7052726f27c9772b5f714b5fe429bc525329e13 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/inval.h,v 1.29 2003/11/29 22:41:15 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/utils/inval.h,v 1.30 2004/02/10 01:55:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,7 +28,9 @@ extern void CommandEndInvalidationMessages(bool isCommit);
 
 extern void CacheInvalidateHeapTuple(Relation relation, HeapTuple tuple);
 
-extern void CacheInvalidateRelcache(Oid relationId);
+extern void CacheInvalidateRelcache(Relation relation);
+
+extern void CacheInvalidateRelcacheByTuple(HeapTuple classTuple);
 
 extern void CacheRegisterSyscacheCallback(int cacheid,
                                                          CacheCallbackFunction func,
index dfdb8491e3c4f70b7b1415d2569f59300d489abc..8532c5a737abf689a959cc904375167881e2b827 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.72 2004/01/06 18:07:32 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.73 2004/02/10 01:55:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,7 +20,6 @@
 #include "catalog/pg_index.h"
 #include "rewrite/prs2lock.h"
 #include "storage/block.h"
-#include "storage/fd.h"
 #include "storage/relfilenode.h"
 
 
@@ -98,16 +97,16 @@ typedef struct PgStat_Info
        bool            index_scan_counted;
 } PgStat_Info;
 
+
 /*
  * Here are the contents of a relation cache entry.
  */
 
 typedef struct RelationData
 {
-       File            rd_fd;                  /* open file descriptor, or -1 if
-                                                                * none; this is NOT an operating
-                                                                * system file descriptor */
-       RelFileNode rd_node;            /* file node (physical identifier) */
+       RelFileNode rd_node;            /* relation physical identifier */
+       /* use "struct" here to avoid needing to include smgr.h: */
+       struct SMgrRelationData *rd_smgr; /* cached file handle, or NULL */
        BlockNumber rd_nblocks;         /* number of blocks in rel */
        BlockNumber rd_targblock;       /* current insertion target block, or
                                                                 * InvalidBlockNumber */
@@ -226,14 +225,6 @@ typedef Relation *RelationPtr;
  */
 #define RelationGetRelid(relation) ((relation)->rd_id)
 
-/*
- * RelationGetFile
- *       Returns the open file descriptor for the rel, or -1 if
- *       none. This is NOT an operating system file descriptor; see md.c
- *       for more information
- */
-#define RelationGetFile(relation) ((relation)->rd_fd)
-
 /*
  * RelationGetNumberOfAttributes
  *             Returns the number of attributes in a relation.
index c7c6a9231f5d7447ce4f283a6ebdd48ed93ac5df..848d68b2077c0b4cca11fd1c382467c799b066c8 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/relcache.h,v 1.38 2003/11/29 22:41:16 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/utils/relcache.h,v 1.39 2004/02/10 01:55:27 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -24,7 +24,6 @@ extern Relation RelationSysNameGetRelation(const char *relationName);
 
 /* finds an existing cache entry, but won't make a new one */
 extern Relation RelationIdCacheGetRelation(Oid relationId);
-extern Relation RelationNodeCacheGetRelation(RelFileNode rnode);
 
 extern void RelationClose(Relation relation);
 
@@ -61,7 +60,7 @@ extern Relation RelationBuildLocalRelation(const char *relname,
  */
 extern void RelationForgetRelation(Oid rid);
 
-extern void RelationIdInvalidateRelationCacheByRelationId(Oid relationId);
+extern void RelationCacheInvalidateEntry(Oid relationId, RelFileNode *rnode);
 
 extern void RelationCacheInvalidate(void);
 
@@ -73,11 +72,6 @@ extern void AtEOXact_RelationCache(bool commit);
 extern bool RelationIdIsInInitFile(Oid relationId);
 extern void RelationCacheInitFileInvalidate(bool beforeSend);
 
-/* XLOG support */
-extern void CreateDummyCaches(void);
-extern void DestroyDummyCaches(void);
-
-
 /* should be used only by relcache.c and catcache.c */
 extern bool criticalRelcachesBuilt;