diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-06-30 07:04:23 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-06-30 07:04:23 +0000 |
commit | b41f4ab8c448fc1bb13b52d00c9c4f1868d97941 (patch) | |
tree | 5e832a1210f93033aeab63a572dc81229ad4aa7c /src/backend/rewrite/rewriteSupport.c | |
parent | c9ec78a6b89e846c5b1be0aa40b6532ca209c850 (diff) | |
download | postgresql-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/rewrite/rewriteSupport.c')
-rw-r--r-- | src/backend/rewrite/rewriteSupport.c | 196 |
1 files changed, 18 insertions, 178 deletions
diff --git a/src/backend/rewrite/rewriteSupport.c b/src/backend/rewrite/rewriteSupport.c index 113e0b73c59..fe87f569387 100644 --- a/src/backend/rewrite/rewriteSupport.c +++ b/src/backend/rewrite/rewriteSupport.c @@ -8,13 +8,12 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.42 2000/06/28 03:31:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteSupport.c,v 1.43 2000/06/30 07:04:23 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" - #include "access/heapam.h" #include "catalog/catname.h" #include "catalog/indexing.h" @@ -22,60 +21,6 @@ #include "utils/catcache.h" #include "utils/syscache.h" -/* - * RuleIdGetActionInfo - - * given a rule oid, look it up and return the rule-event-qual and - * list of parsetrees for the rule (in parseTrees) - */ -#ifdef NOT_USED -static Node * -RuleIdGetActionInfo(Oid ruleoid, bool *instead_flag, Query **parseTrees) -{ - HeapTuple ruletuple; - char *ruleaction = NULL; - bool action_is_null = false; - bool instead_is_null = false; - Relation ruleRelation = NULL; - TupleDesc ruleTupdesc = NULL; - Query *ruleparse = NULL; - char *rule_evqual_string = NULL; - Node *rule_evqual = NULL; - - ruleRelation = heap_openr(RewriteRelationName, AccessShareLock); - ruleTupdesc = RelationGetDescr(ruleRelation); - ruletuple = SearchSysCacheTuple(RULEOID, - ObjectIdGetDatum(ruleoid), - 0, 0, 0); - if (ruletuple == NULL) - elog(ERROR, "rule %u isn't in rewrite system relation", ruleoid); - - ruleaction = (char *) heap_getattr(ruletuple, - Anum_pg_rewrite_ev_action, - ruleTupdesc, - &action_is_null); - rule_evqual_string = (char *) heap_getattr(ruletuple, - Anum_pg_rewrite_ev_qual, - ruleTupdesc, &action_is_null); - *instead_flag = !!heap_getattr(ruletuple, - Anum_pg_rewrite_is_instead, - ruleTupdesc, &instead_is_null); - - if (action_is_null || instead_is_null) - elog(ERROR, "internal error: rewrite rule not properly set up"); - - ruleaction = textout((struct varlena *) ruleaction); - rule_evqual_string = textout((struct varlena *) rule_evqual_string); - - ruleparse = (Query *) stringToNode(ruleaction); - rule_evqual = (Node *) stringToNode(rule_evqual_string); - - heap_close(ruleRelation, AccessShareLock); - - *parseTrees = ruleparse; - return rule_evqual; -} - -#endif int IsDefinedRewriteRule(char *ruleName) @@ -88,7 +33,20 @@ IsDefinedRewriteRule(char *ruleName) return HeapTupleIsValid(tuple); } -static void +/* + * setRelhasrulesInRelation + * Set the value of the relation's relhasrules field in pg_class. + * + * NOTE: caller should be holding an appropriate lock on the relation. + * + * NOTE: an important side-effect of this operation is that an SI invalidation + * message is sent out to all backends --- including me --- causing relcache + * entries to be flushed or updated with the new set of rules for the table. + * Therefore, we execute the update even if relhasrules has the right value + * already. Possible future improvement: skip the disk update and just send + * an SI message in that case. + */ +void setRelhasrulesInRelation(Oid relationId, bool relhasrules) { Relation relationRelation; @@ -96,9 +54,7 @@ setRelhasrulesInRelation(Oid relationId, bool relhasrules) Relation idescs[Num_pg_class_indices]; /* - * Lock a relation given its Oid. Go to the RelationRelation (i.e. - * pg_relation), find the appropriate tuple, and add the specified - * lock to it. + * Find the tuple to update in pg_class, using syscache for the lookup. */ relationRelation = heap_openr(RelationRelationName, RowExclusiveLock); tuple = SearchSysCacheTupleCopy(RELOID, @@ -106,10 +62,11 @@ setRelhasrulesInRelation(Oid relationId, bool relhasrules) 0, 0, 0); Assert(HeapTupleIsValid(tuple)); + /* Do the update */ ((Form_pg_class) GETSTRUCT(tuple))->relhasrules = relhasrules; heap_update(relationRelation, &tuple->t_self, tuple, NULL); - /* keep the catalog indices up to date */ + /* Keep the catalog indices up to date */ CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs); CatalogIndexInsert(idescs, Num_pg_class_indices, relationRelation, tuple); CatalogCloseIndices(Num_pg_class_indices, idescs); @@ -117,120 +74,3 @@ setRelhasrulesInRelation(Oid relationId, bool relhasrules) heap_freetuple(tuple); heap_close(relationRelation, RowExclusiveLock); } - -void -prs2_addToRelation(Oid relid, - Oid ruleId, - CmdType event_type, - AttrNumber attno, - bool isInstead, - Node *qual, - List *actions) -{ - Relation relation; - RewriteRule *thisRule; - RuleLock *rulelock; - MemoryContext oldcxt; - - /* - * create an in memory RewriteRule data structure which is cached by - * every Relation descriptor. (see utils/cache/relcache.c) - */ - oldcxt = MemoryContextSwitchTo(CacheMemoryContext); - thisRule = (RewriteRule *) palloc(sizeof(RewriteRule)); - if (qual != NULL) - qual = copyObject(qual); - if (actions != NIL) - actions = copyObject(actions); - MemoryContextSwitchTo(oldcxt); - - thisRule->ruleId = ruleId; - thisRule->event = event_type; - thisRule->attrno = attno; - thisRule->qual = qual; - thisRule->actions = actions; - thisRule->isInstead = isInstead; - - relation = heap_open(relid, AccessShareLock); - - /* - * modify or create a RuleLock cached by Relation - */ - if (relation->rd_rules == NULL) - { - - oldcxt = MemoryContextSwitchTo(CacheMemoryContext); - rulelock = (RuleLock *) palloc(sizeof(RuleLock)); - rulelock->numLocks = 1; - rulelock->rules = (RewriteRule **) palloc(sizeof(RewriteRule *)); - rulelock->rules[0] = thisRule; - relation->rd_rules = rulelock; - MemoryContextSwitchTo(oldcxt); - - /* - * the fact that relation->rd_rules is NULL means the relhasrules - * attribute of the tuple of this relation in pg_class is false. - * We need to set it to true. - */ - setRelhasrulesInRelation(relid, TRUE); - } - else - { - int numlock; - - rulelock = relation->rd_rules; - numlock = rulelock->numLocks; - /* expand, for safety reasons */ - oldcxt = MemoryContextSwitchTo(CacheMemoryContext); - rulelock->rules = (RewriteRule **) repalloc(rulelock->rules, - sizeof(RewriteRule *) * (numlock + 1)); - MemoryContextSwitchTo(oldcxt); - rulelock->rules[numlock] = thisRule; - rulelock->numLocks++; - } - - heap_close(relation, AccessShareLock); -} - -void -prs2_deleteFromRelation(Oid relid, Oid ruleId) -{ - RuleLock *rulelock; - Relation relation; - int numlock; - int i; - MemoryContext oldcxt; - - relation = heap_open(relid, AccessShareLock); - rulelock = relation->rd_rules; - Assert(rulelock != NULL); - - numlock = rulelock->numLocks; - for (i = 0; i < numlock; i++) - { - if (rulelock->rules[i]->ruleId == ruleId) - break; - } - Assert(i < numlock); - oldcxt = MemoryContextSwitchTo(CacheMemoryContext); - pfree(rulelock->rules[i]); - MemoryContextSwitchTo(oldcxt); - if (numlock == 1) - { - relation->rd_rules = NULL; - - /* - * we don't have rules any more, flag the relhasrules attribute of - * the tuple of this relation in pg_class false. - */ - setRelhasrulesInRelation(relid, FALSE); - } - else - { - rulelock->rules[i] = rulelock->rules[numlock - 1]; - rulelock->rules[numlock - 1] = NULL; - rulelock->numLocks--; - } - - heap_close(relation, AccessShareLock); -} |