aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/relcache.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2001-06-29 21:08:25 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2001-06-29 21:08:25 +0000
commitaf5ced9cfdb1aefd5e64af405d7e582c99a55106 (patch)
tree0134c96dae92bd3000cc399a4a76c65cdca4ad01 /src/backend/utils/cache/relcache.c
parent0eab92c0e674815d3b33868c14886845b68d7cfd (diff)
downloadpostgresql-af5ced9cfdb1aefd5e64af405d7e582c99a55106.tar.gz
postgresql-af5ced9cfdb1aefd5e64af405d7e582c99a55106.zip
Further work on connecting the free space map (which is still just a
stub) into the rest of the system. Adopt a cleaner approach to preventing deadlock in concurrent heap_updates: allow RelationGetBufferForTuple to select any page of the rel, and put the onus on it to lock both buffers in a consistent order. Remove no-longer-needed isExtend hack from API of ReleaseAndReadBuffer.
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r--src/backend/utils/cache/relcache.c112
1 files changed, 97 insertions, 15 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 00b66b2575b..670cdf6ddaa 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.140 2001/06/27 23:31:39 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.141 2001/06/29 21:08:25 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1928,33 +1928,111 @@ RelationCacheAbortWalker(Relation *relationPtr, Datum dummy)
}
/*
- * RelationRegisterRelation -
- * register the Relation descriptor of a newly created relation
- * with the relation descriptor Cache.
+ * RelationBuildLocalRelation
+ * Build a relcache entry for an about-to-be-created relation,
+ * and enter it into the relcache.
*/
-void
-RelationRegisterRelation(Relation relation)
+Relation
+RelationBuildLocalRelation(const char *relname,
+ TupleDesc tupDesc,
+ Oid relid, Oid dbid,
+ bool nailit)
{
+ Relation rel;
MemoryContext oldcxt;
+ int natts = tupDesc->natts;
+ int i;
- RelationInitLockInfo(relation);
+ AssertArg(natts > 0);
+
+ /*
+ * switch to the cache context to create the relcache entry.
+ */
+ if (!CacheMemoryContext)
+ CreateCacheMemoryContext();
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
- RelationCacheInsert(relation);
+ /*
+ * allocate a new relation descriptor.
+ */
+ rel = (Relation) palloc(sizeof(RelationData));
+ MemSet((char *) rel, 0, sizeof(RelationData));
+ rel->rd_targblock = InvalidBlockNumber;
+
+ /* make sure relation is marked as having no open file yet */
+ rel->rd_fd = -1;
+
+ RelationSetReferenceCount(rel, 1);
+
+ /*
+ * nail the reldesc if this is a bootstrap create reln and we may need
+ * it in the cache later on in the bootstrap process so we don't ever
+ * want it kicked out. e.g. pg_attribute!!!
+ */
+ if (nailit)
+ rel->rd_isnailed = true;
+
+ /*
+ * create a new tuple descriptor from the one passed in
+ * (we do this to copy it into the cache context)
+ */
+ rel->rd_att = CreateTupleDescCopyConstr(tupDesc);
+
+ /*
+ * initialize relation tuple form (caller may add/override data later)
+ */
+ rel->rd_rel = (Form_pg_class) palloc(CLASS_TUPLE_SIZE);
+ MemSet((char *) rel->rd_rel, 0, CLASS_TUPLE_SIZE);
+
+ strcpy(RelationGetPhysicalRelationName(rel), relname);
+
+ rel->rd_rel->relkind = RELKIND_UNCATALOGED;
+ rel->rd_rel->relnatts = natts;
+ rel->rd_rel->reltype = InvalidOid;
+ if (tupDesc->constr)
+ rel->rd_rel->relchecks = tupDesc->constr->num_check;
+
+ /*
+ * Insert relation OID and database/tablespace ID into the right places.
+ * XXX currently we assume physical tblspace/relnode are same as logical
+ * dbid/reloid. Probably should pass an extra pair of parameters.
+ */
+ rel->rd_rel->relisshared = (dbid == InvalidOid);
+
+ RelationGetRelid(rel) = relid;
+
+ for (i = 0; i < natts; i++)
+ rel->rd_att->attrs[i]->attrelid = relid;
+
+ RelationInitLockInfo(rel); /* see lmgr.c */
+
+ rel->rd_node.tblNode = dbid;
+ rel->rd_node.relNode = relid;
+ rel->rd_rel->relfilenode = relid;
+
+ /*
+ * Okay to insert into the relcache hash tables.
+ */
+ RelationCacheInsert(rel);
/*
* we've just created the relation. It is invisible to anyone else
* before the transaction is committed. Setting rd_myxactonly allows
* us to use the local buffer manager for select/insert/etc before the
* end of transaction. (We also need to keep track of relations
- * created during a transaction and does the necessary clean up at the
+ * created during a transaction and do the necessary clean up at the
* end of the transaction.) - ay 3/95
*/
- relation->rd_myxactonly = TRUE;
- newlyCreatedRelns = lcons(relation, newlyCreatedRelns);
+ rel->rd_myxactonly = true;
+ newlyCreatedRelns = lcons(rel, newlyCreatedRelns);
+ /*
+ * done building relcache entry.
+ */
MemoryContextSwitchTo(oldcxt);
+
+ return rel;
}
/*
@@ -1972,14 +2050,18 @@ RelationPurgeLocalRelation(bool xactCommitted)
List *l = newlyCreatedRelns;
Relation reln = lfirst(l);
+ newlyCreatedRelns = lnext(newlyCreatedRelns);
+ pfree(l);
+
Assert(reln != NULL && reln->rd_myxactonly);
reln->rd_myxactonly = false; /* mark it not on list anymore */
- newlyCreatedRelns = lnext(newlyCreatedRelns);
- pfree(l);
-
- /* XXX is this step still needed? If so, why? */
+ /*
+ * XXX while we clearly must throw out new Relation entries at
+ * xact abort, it's not clear why we need to do it at commit.
+ * Could this be improved?
+ */
if (!IsBootstrapProcessingMode())
RelationClearRelation(reln, false);
}