aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-06-30 07:04:23 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-06-30 07:04:23 +0000
commitb41f4ab8c448fc1bb13b52d00c9c4f1868d97941 (patch)
tree5e832a1210f93033aeab63a572dc81229ad4aa7c /src/backend/utils
parentc9ec78a6b89e846c5b1be0aa40b6532ca209c850 (diff)
downloadpostgresql-b41f4ab8c448fc1bb13b52d00c9c4f1868d97941.tar.gz
postgresql-b41f4ab8c448fc1bb13b52d00c9c4f1868d97941.zip
Use a private memory context to store rule information in each relcache
entry that has rules. This allows us to release the rule parsetrees on relcache flush without needing a working freeObject() routine. Formerly, the rule trees were leaked permanently at relcache flush. Also, clean up handling of rule creation and deletion --- there was not sufficient locking of the relation being modified, and there was no reliable notification of other backends that a relcache reload was needed. Also, clean up relcache.c code so that scans of system tables needed to load a relcache entry are done in the caller's memory context, not in CacheMemoryContext. This prevents any un-pfreed memory from those scans from becoming a permanent memory leak.
Diffstat (limited to 'src/backend/utils')
-rw-r--r--src/backend/utils/cache/relcache.c349
1 files changed, 188 insertions, 161 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index b0ee20fce98..dc69a0e508f 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.104 2000/06/28 03:32:24 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.105 2000/06/30 07:04:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,9 +22,6 @@
* RelationClose - close an open relation
*
* NOTES
- * This file is in the process of being cleaned up
- * before I add system attribute indexing. -cim 1/13/91
- *
* The following code contains many undocumented hacks. Please be
* careful....
*
@@ -59,6 +56,7 @@
#include "storage/smgr.h"
#include "utils/catcache.h"
#include "utils/fmgroids.h"
+#include "utils/memutils.h"
#include "utils/relcache.h"
#include "utils/temprel.h"
@@ -77,7 +75,7 @@ static FormData_pg_attribute Desc_pg_log[Natts_pg_log] = {Schema_pg_log};
/* ----------------
* Hash tables that index the relation cache
*
- * Relations are cached two ways, by name and by id,
+ * Relations are looked up two ways, by name and by id,
* thus there are two hash tables for referencing them.
* ----------------
*/
@@ -91,6 +89,12 @@ static HTAB *RelationIdCache;
*/
static List *newlyCreatedRelns = NULL;
+/*
+ * 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.
+ */
+static bool criticalRelcachesBuilt = false;
+
/* ----------------
* RelationBuildDescInfo exists so code can be shared
@@ -211,20 +215,19 @@ static void RelationCacheAbortWalker(Relation *relationPtr, int dummy);
static void init_irels(void);
static void write_irels(void);
-static void formrdesc(char *relationName, u_int natts,
+static void formrdesc(char *relationName, int natts,
FormData_pg_attribute *att);
static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo);
static HeapTuple scan_pg_rel_seq(RelationBuildDescInfo buildinfo);
static HeapTuple scan_pg_rel_ind(RelationBuildDescInfo buildinfo);
-static Relation AllocateRelationDesc(Relation relation, u_int natts,
- Form_pg_class relp);
+static Relation AllocateRelationDesc(Relation relation, Form_pg_class relp);
static void RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
- Relation relation, u_int natts);
+ Relation relation);
static void build_tupdesc_seq(RelationBuildDescInfo buildinfo,
- Relation relation, u_int natts);
+ Relation relation);
static void build_tupdesc_ind(RelationBuildDescInfo buildinfo,
- Relation relation, u_int natts);
+ Relation relation);
static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo,
Relation oldrelation);
static void IndexedAccessMethodInitialize(Relation relation);
@@ -232,7 +235,6 @@ static void AttrDefaultFetch(Relation relation);
static void RelCheckFetch(Relation relation);
static List *insert_ordered_oid(List *list, Oid datum);
-static bool criticalRelcacheBuild = false;
/* ----------------------------------------------------------------
* RelationIdGetRelation() and RelationNameGetRelation()
@@ -262,7 +264,7 @@ ScanPgRelation(RelationBuildDescInfo buildinfo)
* can, and do.
*/
- if (IsIgnoringSystemIndexes() || !criticalRelcacheBuild)
+ if (IsIgnoringSystemIndexes() || !criticalRelcachesBuilt)
return scan_pg_rel_seq(buildinfo);
else
return scan_pg_rel_ind(buildinfo);
@@ -379,34 +381,23 @@ scan_pg_rel_ind(RelationBuildDescInfo buildinfo)
* ----------------
*/
static Relation
-AllocateRelationDesc(Relation relation, u_int natts,
- Form_pg_class relp)
+AllocateRelationDesc(Relation relation, Form_pg_class relp)
{
+ MemoryContext oldcxt;
Form_pg_class relationForm;
- /* ----------------
- * Copy the relation tuple form
- *
- * We only allocate space for the fixed fields, ie, CLASS_TUPLE_SIZE.
- * relacl is NOT stored in the relcache --- there'd be little point
- * in it, since we don't copy the tuple's nullvalues bitmap and hence
- * wouldn't know if the value is valid ... bottom line is that relacl
- * *cannot* be retrieved from the relcache. Get it from the syscache
- * if you need it.
- * ----------------
- */
- relationForm = (Form_pg_class) palloc(CLASS_TUPLE_SIZE);
-
- memcpy((char *) relationForm, (char *) relp, CLASS_TUPLE_SIZE);
+ /* Relcache entries must live in CacheMemoryContext */
+ oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
/* ----------------
* allocate space for new relation descriptor, if needed
+ * ----------------
*/
if (relation == NULL)
relation = (Relation) palloc(sizeof(RelationData));
/* ----------------
- * clear new reldesc
+ * clear all fields of reldesc
* ----------------
*/
MemSet((char *) relation, 0, sizeof(RelationData));
@@ -414,12 +405,29 @@ AllocateRelationDesc(Relation relation, u_int natts,
/* make sure relation is marked as having no open file yet */
relation->rd_fd = -1;
- /* initialize attribute tuple form */
- relation->rd_att = CreateTemplateTupleDesc(natts);
+ /* ----------------
+ * Copy the relation tuple form
+ *
+ * We only allocate space for the fixed fields, ie, CLASS_TUPLE_SIZE.
+ * relacl is NOT stored in the relcache --- there'd be little point
+ * in it, since we don't copy the tuple's nullvalues bitmap and hence
+ * wouldn't know if the value is valid ... bottom line is that relacl
+ * *cannot* be retrieved from the relcache. Get it from the syscache
+ * if you need it.
+ * ----------------
+ */
+ relationForm = (Form_pg_class) palloc(CLASS_TUPLE_SIZE);
- /* and initialize relation tuple form */
+ memcpy((char *) relationForm, (char *) relp, CLASS_TUPLE_SIZE);
+
+ /* initialize relation tuple form */
relation->rd_rel = relationForm;
+ /* and allocate attribute tuple form storage */
+ relation->rd_att = CreateTemplateTupleDesc(relationForm->relnatts);
+
+ MemoryContextSwitchTo(oldcxt);
+
return relation;
}
@@ -432,8 +440,7 @@ AllocateRelationDesc(Relation relation, u_int natts,
*/
static void
RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
- Relation relation,
- u_int natts)
+ Relation relation)
{
/*
@@ -442,14 +449,17 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
* can, and do.
*/
- if (IsIgnoringSystemIndexes() || !criticalRelcacheBuild)
- build_tupdesc_seq(buildinfo, relation, natts);
+ if (IsIgnoringSystemIndexes() || !criticalRelcachesBuilt)
+ build_tupdesc_seq(buildinfo, relation);
else
- build_tupdesc_ind(buildinfo, relation, natts);
+ build_tupdesc_ind(buildinfo, relation);
}
static void
-SetConstrOfRelation(Relation relation, TupleConstr *constr, int ndef, AttrDefault *attrdef)
+SetConstrOfRelation(Relation relation,
+ TupleConstr *constr,
+ int ndef,
+ AttrDefault *attrdef)
{
if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks)
{
@@ -471,8 +481,9 @@ SetConstrOfRelation(Relation relation, TupleConstr *constr, int ndef, AttrDefaul
if (relation->rd_rel->relchecks > 0) /* CHECKs */
{
constr->num_check = relation->rd_rel->relchecks;
- constr->check = (ConstrCheck *) palloc(constr->num_check *
- sizeof(ConstrCheck));
+ constr->check = (ConstrCheck *)
+ MemoryContextAlloc(CacheMemoryContext,
+ constr->num_check * sizeof(ConstrCheck));
MemSet(constr->check, 0, constr->num_check * sizeof(ConstrCheck));
RelCheckFetch(relation);
}
@@ -488,8 +499,7 @@ SetConstrOfRelation(Relation relation, TupleConstr *constr, int ndef, AttrDefaul
static void
build_tupdesc_seq(RelationBuildDescInfo buildinfo,
- Relation relation,
- u_int natts)
+ Relation relation)
{
HeapTuple pg_attribute_tuple;
Relation pg_attribute_desc;
@@ -497,11 +507,14 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
Form_pg_attribute attp;
ScanKeyData key;
int need;
- TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr));
+ TupleConstr *constr;
AttrDefault *attrdef = NULL;
int ndef = 0;
+ constr = (TupleConstr *) MemoryContextAlloc(CacheMemoryContext,
+ sizeof(TupleConstr));
constr->has_not_null = false;
+
/* ----------------
* form a scan key
* ----------------
@@ -522,7 +535,7 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
* add attribute data to relation->rd_att
* ----------------
*/
- need = natts;
+ need = relation->rd_rel->relnatts;
pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0);
while (HeapTupleIsValid(pg_attribute_tuple) && need > 0)
@@ -532,12 +545,14 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
if (attp->attnum > 0)
{
relation->rd_att->attrs[attp->attnum - 1] =
- (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
+ (Form_pg_attribute) MemoryContextAlloc(CacheMemoryContext,
+ ATTRIBUTE_TUPLE_SIZE);
memcpy((char *) (relation->rd_att->attrs[attp->attnum - 1]),
(char *) attp,
ATTRIBUTE_TUPLE_SIZE);
need--;
+
/* Update if this attribute have a constraint */
if (attp->attnotnull)
constr->has_not_null = true;
@@ -546,10 +561,12 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
{
if (attrdef == NULL)
{
- attrdef = (AttrDefault *) palloc(relation->rd_rel->relnatts *
- sizeof(AttrDefault));
+ attrdef = (AttrDefault *)
+ MemoryContextAlloc(CacheMemoryContext,
+ relation->rd_rel->relnatts *
+ sizeof(AttrDefault));
MemSet(attrdef, 0,
- relation->rd_rel->relnatts * sizeof(AttrDefault));
+ relation->rd_rel->relnatts * sizeof(AttrDefault));
}
attrdef[ndef].adnum = attp->attnum;
attrdef[ndef].adbin = NULL;
@@ -575,17 +592,18 @@ build_tupdesc_seq(RelationBuildDescInfo buildinfo,
static void
build_tupdesc_ind(RelationBuildDescInfo buildinfo,
- Relation relation,
- u_int natts)
+ Relation relation)
{
Relation attrel;
HeapTuple atttup;
Form_pg_attribute attp;
- TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr));
+ TupleConstr *constr;
AttrDefault *attrdef = NULL;
int ndef = 0;
int i;
+ constr = (TupleConstr *) MemoryContextAlloc(CacheMemoryContext,
+ sizeof(TupleConstr));
constr->has_not_null = false;
attrel = heap_openr(AttributeRelationName, AccessShareLock);
@@ -616,7 +634,8 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
}
relation->rd_att->attrs[i - 1] = attp =
- (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
+ (Form_pg_attribute) MemoryContextAlloc(CacheMemoryContext,
+ ATTRIBUTE_TUPLE_SIZE);
memcpy((char *) attp,
(char *) (Form_pg_attribute) GETSTRUCT(atttup),
@@ -638,8 +657,10 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
{
if (attrdef == NULL)
{
- attrdef = (AttrDefault *) palloc(relation->rd_rel->relnatts *
- sizeof(AttrDefault));
+ attrdef = (AttrDefault *)
+ MemoryContextAlloc(CacheMemoryContext,
+ relation->rd_rel->relnatts *
+ sizeof(AttrDefault));
MemSet(attrdef, 0,
relation->rd_rel->relnatts * sizeof(AttrDefault));
}
@@ -652,7 +673,6 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
heap_close(attrel, AccessShareLock);
SetConstrOfRelation(relation, constr, ndef, attrdef);
-
}
/* --------------------------------
@@ -660,11 +680,22 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
*
* Form the relation's rewrite rules from information in
* the pg_rewrite system catalog.
+ *
+ * Note: The rule parsetrees are potentially very complex node structures.
+ * To allow these trees to be freed when the relcache entry is flushed,
+ * we make a private memory context to hold the RuleLock information for
+ * each relcache entry that has associated rules. The context is used
+ * just for rule info, not for any other subsidiary data of the relcache
+ * entry, because that keeps the update logic in RelationClearRelation()
+ * manageable. The other subsidiary data structures are simple enough
+ * to be easy to free explicitly, anyway.
* --------------------------------
*/
static void
RelationBuildRuleLock(Relation relation)
{
+ MemoryContext rulescxt;
+ MemoryContext oldcxt;
HeapTuple pg_rewrite_tuple;
Relation pg_rewrite_desc;
TupleDesc pg_rewrite_tupdesc;
@@ -675,13 +706,25 @@ RelationBuildRuleLock(Relation relation)
RewriteRule **rules;
int maxlocks;
+ /*
+ * Make the private context. Parameters are set on the assumption
+ * that it'll probably not contain much data.
+ */
+ rulescxt = AllocSetContextCreate(CacheMemoryContext,
+ RelationGetRelationName(relation),
+ 0, /* minsize */
+ 1024, /* initsize */
+ 1024); /* maxsize */
+ relation->rd_rulescxt = rulescxt;
+
/* ----------------
* form an array to hold the rewrite rules (the array is extended if
* necessary)
* ----------------
*/
maxlocks = 4;
- rules = (RewriteRule **) palloc(sizeof(RewriteRule *) * maxlocks);
+ rules = (RewriteRule **)
+ MemoryContextAlloc(rulescxt, sizeof(RewriteRule *) * maxlocks);
numlocks = 0;
/* ----------------
@@ -710,26 +753,32 @@ RelationBuildRuleLock(Relation relation)
char *rule_evqual_str;
RewriteRule *rule;
- rule = (RewriteRule *) palloc(sizeof(RewriteRule));
+ rule = (RewriteRule *) MemoryContextAlloc(rulescxt,
+ sizeof(RewriteRule));
rule->ruleId = pg_rewrite_tuple->t_data->t_oid;
- rule->event = (int) heap_getattr(pg_rewrite_tuple,
- Anum_pg_rewrite_ev_type, pg_rewrite_tupdesc,
- &isnull) - 48;
- rule->attrno = (int) heap_getattr(pg_rewrite_tuple,
- Anum_pg_rewrite_ev_attr, pg_rewrite_tupdesc,
- &isnull);
- rule->isInstead = !!heap_getattr(pg_rewrite_tuple,
- Anum_pg_rewrite_is_instead, pg_rewrite_tupdesc,
- &isnull);
+ rule->event = DatumGetInt32(heap_getattr(pg_rewrite_tuple,
+ Anum_pg_rewrite_ev_type,
+ pg_rewrite_tupdesc,
+ &isnull)) - 48;
+ rule->attrno = DatumGetInt16(heap_getattr(pg_rewrite_tuple,
+ Anum_pg_rewrite_ev_attr,
+ pg_rewrite_tupdesc,
+ &isnull));
+ rule->isInstead = DatumGetBool(heap_getattr(pg_rewrite_tuple,
+ Anum_pg_rewrite_is_instead,
+ pg_rewrite_tupdesc,
+ &isnull));
ruleaction = heap_getattr(pg_rewrite_tuple,
Anum_pg_rewrite_ev_action,
pg_rewrite_tupdesc,
&isnull);
ruleaction_str = lztextout((lztext *) DatumGetPointer(ruleaction));
+ oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
rule->actions = (List *) stringToNode(ruleaction_str);
+ MemoryContextSwitchTo(oldcxt);
pfree(ruleaction_str);
rule_evqual = heap_getattr(pg_rewrite_tuple,
@@ -737,13 +786,16 @@ RelationBuildRuleLock(Relation relation)
pg_rewrite_tupdesc,
&isnull);
rule_evqual_str = lztextout((lztext *) DatumGetPointer(rule_evqual));
+ oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
rule->qual = (Node *) stringToNode(rule_evqual_str);
+ MemoryContextSwitchTo(oldcxt);
pfree(rule_evqual_str);
if (numlocks >= maxlocks)
{
maxlocks *= 2;
- rules = (RewriteRule **) repalloc(rules, sizeof(RewriteRule *) * maxlocks);
+ rules = (RewriteRule **)
+ repalloc(rules, sizeof(RewriteRule *) * maxlocks);
}
rules[numlocks++] = rule;
}
@@ -759,7 +811,7 @@ RelationBuildRuleLock(Relation relation)
* form a RuleLock and insert into relation
* ----------------
*/
- rulelock = (RuleLock *) palloc(sizeof(RuleLock));
+ rulelock = (RuleLock *) MemoryContextAlloc(rulescxt, sizeof(RuleLock));
rulelock->numLocks = numlocks;
rulelock->rules = rules;
@@ -767,35 +819,6 @@ RelationBuildRuleLock(Relation relation)
}
/* --------------------------------
- * FreeRuleLock
- *
- * Release the storage used for a set of rewrite rules.
- *
- * Probably this should be in the rules code someplace...
- * --------------------------------
- */
-static void
-FreeRuleLock(RuleLock *rlock)
-{
- int i;
-
- if (rlock == NULL)
- return;
- for (i = 0; i < rlock->numLocks; i++)
- {
- RewriteRule *rule = rlock->rules[i];
-
-#if 0 /* does freefuncs.c still work? Not sure */
- freeObject(rule->actions);
- freeObject(rule->qual);
-#endif
- pfree(rule);
- }
- pfree(rlock->rules);
- pfree(rlock);
-}
-
-/* --------------------------------
* equalRuleLocks
*
* Determine whether two RuleLocks are equivalent
@@ -886,7 +909,6 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
{
File fd;
Relation relation;
- u_int natts;
Oid relid;
Oid relam;
HeapTuple pg_class_tuple;
@@ -912,17 +934,19 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
*/
relid = pg_class_tuple->t_data->t_oid;
relp = (Form_pg_class) GETSTRUCT(pg_class_tuple);
- natts = relp->relnatts;
/* ----------------
* allocate storage for the relation descriptor,
- * initialize relation->rd_rel and get the access method id.
- * The storage is allocated in memory context CacheMemoryContext.
+ * and copy pg_class_tuple to relation->rd_rel.
* ----------------
*/
- oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
- relation = AllocateRelationDesc(oldrelation, natts, relp);
- relam = relation->rd_rel->relam;
+ relation = AllocateRelationDesc(oldrelation, relp);
+
+ /* -------------------
+ * now we can free the memory allocated for pg_class_tuple
+ * -------------------
+ */
+ heap_freetuple(pg_class_tuple);
/* ----------------
* initialize the relation's relation id (relation->rd_id)
@@ -946,26 +970,30 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
* initialize the access method information (relation->rd_am)
* ----------------
*/
+ relam = relation->rd_rel->relam;
if (OidIsValid(relam))
- relation->rd_am = AccessMethodObjectIdGetForm(relam);
+ relation->rd_am = AccessMethodObjectIdGetForm(relam,
+ CacheMemoryContext);
/* ----------------
* initialize the tuple descriptor (relation->rd_att).
* ----------------
*/
- RelationBuildTupleDesc(buildinfo, relation, natts);
+ RelationBuildTupleDesc(buildinfo, relation);
/* ----------------
- * initialize rules that affect this relation
+ * Fetch rules and triggers that affect this relation
* ----------------
*/
- if (relp->relhasrules)
+ if (relation->rd_rel->relhasrules)
RelationBuildRuleLock(relation);
else
+ {
relation->rd_rules = NULL;
+ relation->rd_rulescxt = NULL;
+ }
- /* Triggers */
- if (relp->reltriggers > 0)
+ if (relation->rd_rel->reltriggers > 0)
RelationBuildTriggers(relation);
else
relation->trigdesc = NULL;
@@ -993,7 +1021,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
Assert(fd >= -1);
if (fd == -1)
elog(NOTICE, "RelationIdBuildRelation: smgropen(%s): %m",
- NameStr(relp->relname));
+ NameStr(relation->rd_rel->relname));
relation->rd_fd = fd;
@@ -1002,17 +1030,10 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
* restore memory context and return the new reldesc.
* ----------------
*/
+ oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
RelationCacheInsert(relation);
-
MemoryContextSwitchTo(oldcxt);
- /* -------------------
- * free the memory allocated for pg_class_tuple
- * and for lock data pointed to by pg_class_tuple
- * -------------------
- */
- heap_freetuple(pg_class_tuple);
-
return relation;
}
@@ -1030,13 +1051,15 @@ IndexedAccessMethodInitialize(Relation relation)
natts = relation->rd_rel->relnatts;
relamstrategies = relation->rd_am->amstrategies;
stratSize = AttributeNumberGetIndexStrategySize(natts, relamstrategies);
- strategy = (IndexStrategy) palloc(stratSize);
- relamsupport = relation->rd_am->amsupport;
+ strategy = (IndexStrategy) MemoryContextAlloc(CacheMemoryContext,
+ stratSize);
+ relamsupport = relation->rd_am->amsupport;
if (relamsupport > 0)
{
supportSize = natts * (relamsupport * sizeof(RegProcedure));
- support = (RegProcedure *) palloc(supportSize);
+ support = (RegProcedure *) MemoryContextAlloc(CacheMemoryContext,
+ supportSize);
}
else
support = (RegProcedure *) NULL;
@@ -1052,20 +1075,20 @@ IndexedAccessMethodInitialize(Relation relation)
/* --------------------------------
* formrdesc
*
- * This is a special version of RelationBuildDesc()
- * used by RelationInitialize() in initializing the
- * relcache. The system relation descriptors built
- * here are all nailed in the descriptor caches, for
- * bootstrapping.
+ * This is a special cut-down version of RelationBuildDesc()
+ * used by RelationInitialize() in initializing the relcache.
+ * The relation descriptor is built just from the supplied parameters.
+ *
+ * NOTE: we assume we are already switched into CacheMemoryContext.
* --------------------------------
*/
static void
formrdesc(char *relationName,
- u_int natts,
+ int natts,
FormData_pg_attribute *att)
{
Relation relation;
- u_int i;
+ int i;
/* ----------------
* allocate new relation desc
@@ -1095,8 +1118,9 @@ formrdesc(char *relationName,
strcpy(RelationGetPhysicalRelationName(relation), relationName);
/* ----------------
- initialize attribute tuple form
- */
+ * initialize attribute tuple form
+ * ----------------
+ */
relation->rd_att = CreateTemplateTupleDesc(natts);
/*
@@ -1120,7 +1144,7 @@ formrdesc(char *relationName,
relation->rd_rel->relpages = 1; /* XXX */
relation->rd_rel->reltuples = 1; /* XXX */
relation->rd_rel->relkind = RELKIND_RELATION;
- relation->rd_rel->relnatts = (uint16) natts;
+ relation->rd_rel->relnatts = (int16) natts;
relation->rd_isnailed = true;
/* ----------------
@@ -1157,6 +1181,10 @@ formrdesc(char *relationName,
* Determining this requires a scan on pg_class, but to do the scan
* the rdesc for pg_class must already exist. Therefore we must do
* the check (and possible set) after cache insertion.
+ *
+ * XXX I believe the above comment is misguided; we should be
+ * running in bootstrap or init processing mode, and CatalogHasIndex
+ * relies on hard-wired info in those cases.
*/
relation->rd_rel->relhasindex =
CatalogHasIndex(relationName, RelationGetRelid(relation));
@@ -1171,8 +1199,9 @@ formrdesc(char *relationName,
/* --------------------------------
* RelationIdCacheGetRelation
*
- * Lookup a reldesc by OID.
- * Only try to get the reldesc by looking up the cache
+ * Lookup an existing reldesc by OID.
+ *
+ * Only try to get the reldesc by looking in the cache,
* do not go to the disk.
*
* NB: relation ref count is incremented if successful.
@@ -1355,7 +1384,7 @@ RelationClose(Relation relation)
* (one with refcount > 0). However, this routine just does whichever
* it's told to do; callers must determine which they want.
*
- * If we detect a change in the relation's TupleDesc or trigger data
+ * If we detect a change in the relation's TupleDesc, rules, or triggers
* while rebuilding, we complain unless refcount is 0.
* --------------------------------
*/
@@ -1383,8 +1412,6 @@ RelationClearRelation(Relation relation, bool rebuildIt)
if (relation->rd_isnailed)
return;
- oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
-
/*
* Remove relation from hash tables
*
@@ -1392,7 +1419,9 @@ RelationClearRelation(Relation relation, bool rebuildIt)
* visible in the hash tables until it's valid again, so don't try to
* optimize this away...
*/
+ oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
RelationCacheDelete(relation);
+ MemoryContextSwitchTo(oldcxt);
/* Clear out catcache's entries for this relation */
SystemCacheRelationFlushed(RelationGetRelid(relation));
@@ -1425,7 +1454,8 @@ RelationClearRelation(Relation relation, bool rebuildIt)
{
/* ok to zap remaining substructure */
FreeTupleDesc(relation->rd_att);
- FreeRuleLock(relation->rd_rules);
+ if (relation->rd_rulescxt)
+ MemoryContextDelete(relation->rd_rulescxt);
FreeTriggerDesc(relation->trigdesc);
pfree(relation);
}
@@ -1443,6 +1473,7 @@ RelationClearRelation(Relation relation, bool rebuildIt)
bool old_myxactonly = relation->rd_myxactonly;
TupleDesc old_att = relation->rd_att;
RuleLock *old_rules = relation->rd_rules;
+ MemoryContext old_rulescxt = relation->rd_rulescxt;
TriggerDesc *old_trigdesc = relation->trigdesc;
int old_nblocks = relation->rd_nblocks;
bool relDescChanged = false;
@@ -1455,7 +1486,8 @@ RelationClearRelation(Relation relation, bool rebuildIt)
{
/* Should only get here if relation was deleted */
FreeTupleDesc(old_att);
- FreeRuleLock(old_rules);
+ if (old_rulescxt)
+ MemoryContextDelete(old_rulescxt);
FreeTriggerDesc(old_trigdesc);
pfree(relation);
elog(ERROR, "RelationClearRelation: relation %u deleted while still in use",
@@ -1475,12 +1507,15 @@ RelationClearRelation(Relation relation, bool rebuildIt)
}
if (equalRuleLocks(old_rules, relation->rd_rules))
{
- FreeRuleLock(relation->rd_rules);
+ if (relation->rd_rulescxt)
+ MemoryContextDelete(relation->rd_rulescxt);
relation->rd_rules = old_rules;
+ relation->rd_rulescxt = old_rulescxt;
}
else
{
- FreeRuleLock(old_rules);
+ if (old_rulescxt)
+ MemoryContextDelete(old_rulescxt);
relDescChanged = true;
}
if (equalTriggerDescs(old_trigdesc, relation->trigdesc))
@@ -1505,8 +1540,6 @@ RelationClearRelation(Relation relation, bool rebuildIt)
elog(ERROR, "RelationClearRelation: relation %u modified while in use",
buildinfo.i.info_id);
}
-
- MemoryContextSwitchTo(oldcxt);
}
/* --------------------------------
@@ -1570,12 +1603,9 @@ RelationForgetRelation(Oid rid)
{
if (relation->rd_myxactonly)
{
- MemoryContext oldcxt;
List *curr;
List *prev = NIL;
- oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
-
foreach(curr, newlyCreatedRelns)
{
Relation reln = lfirst(curr);
@@ -1593,7 +1623,6 @@ RelationForgetRelation(Oid rid)
else
lnext(prev) = lnext(curr);
pfree(curr);
- MemoryContextSwitchTo(oldcxt);
}
/* Unconditionally destroy the relcache entry */
@@ -1731,10 +1760,10 @@ RelationRegisterRelation(Relation relation)
{
MemoryContext oldcxt;
- oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
-
RelationInitLockInfo(relation);
+ oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
+
RelationCacheInsert(relation);
/*
@@ -1761,13 +1790,9 @@ RelationRegisterRelation(Relation relation)
void
RelationPurgeLocalRelation(bool xactCommitted)
{
- MemoryContext oldcxt;
-
if (newlyCreatedRelns == NULL)
return;
- oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
-
while (newlyCreatedRelns)
{
List *l = newlyCreatedRelns;
@@ -1796,8 +1821,6 @@ RelationPurgeLocalRelation(bool xactCommitted)
if (!IsBootstrapProcessingMode())
RelationClearRelation(reln, false);
}
-
- MemoryContextSwitchTo(oldcxt);
}
/* --------------------------------
@@ -1943,7 +1966,9 @@ AttrDefaultFetch(Relation relation)
elog(NOTICE, "AttrDefaultFetch: adbin IS NULL for attr %s in rel %s",
NameStr(relation->rd_att->attrs[adform->adnum - 1]->attname),
RelationGetRelationName(relation));
- attrdef[i].adbin = textout(val);
+ else
+ attrdef[i].adbin = MemoryContextStrdup(CacheMemoryContext,
+ textout(val));
break;
}
if (hasindex)
@@ -2039,14 +2064,16 @@ RelCheckFetch(Relation relation)
if (isnull)
elog(ERROR, "RelCheckFetch: rcname IS NULL for rel %s",
RelationGetRelationName(relation));
- check[found].ccname = pstrdup(NameStr(*rcname));
+ check[found].ccname = MemoryContextStrdup(CacheMemoryContext,
+ NameStr(*rcname));
val = (struct varlena *) fastgetattr(htup,
Anum_pg_relcheck_rcbin,
rcrel->rd_att, &isnull);
if (isnull)
elog(ERROR, "RelCheckFetch: rcbin IS NULL for rel %s",
RelationGetRelationName(relation));
- check[found].ccbin = textout(val);
+ check[found].ccbin = MemoryContextStrdup(CacheMemoryContext,
+ textout(val));
found++;
if (hasindex)
ReleaseBuffer(buffer);
@@ -2416,7 +2443,7 @@ init_irels(void)
RelationCacheInsert(ird);
}
- criticalRelcacheBuild = true;
+ criticalRelcachesBuilt = true;
}
static void
@@ -2489,7 +2516,7 @@ write_irels(void)
irel[2] = RelationBuildDesc(bi, NULL);
irel[2]->rd_isnailed = true;
- criticalRelcacheBuild = true;
+ criticalRelcachesBuilt = true;
/*
* Removed the following ProcessingMode -- inoue