From 2c29d3cfa15cc231430fd6ddffe52bfc082d3a35 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 5 Apr 2018 16:52:56 +0000 Subject: [PATCH v8 02/12] Add skip_locked argument to find_all_inheritors(). --- contrib/sepgsql/dml.c | 2 +- src/backend/catalog/pg_inherits.c | 30 +++++++++++++++++++++++++++--- src/backend/commands/analyze.c | 2 +- src/backend/commands/publicationcmds.c | 2 +- src/backend/commands/tablecmds.c | 16 ++++++++-------- src/backend/commands/trigger.c | 2 +- src/backend/commands/vacuum.c | 2 +- src/backend/executor/execPartition.c | 2 +- src/backend/optimizer/prep/prepunion.c | 2 +- src/backend/partitioning/partbounds.c | 2 +- src/backend/tcop/utility.c | 3 ++- src/include/catalog/pg_inherits.h | 2 +- 12 files changed, 46 insertions(+), 21 deletions(-) diff --git a/contrib/sepgsql/dml.c b/contrib/sepgsql/dml.c index 9bdbd7b60f..bb7713380a 100644 --- a/contrib/sepgsql/dml.c +++ b/contrib/sepgsql/dml.c @@ -330,7 +330,7 @@ sepgsql_dml_privileges(List *rangeTabls, bool abort_on_violation) if (!rte->inh) tableIds = list_make1_oid(rte->relid); else - tableIds = find_all_inheritors(rte->relid, NoLock, NULL); + tableIds = find_all_inheritors(rte->relid, NoLock, NULL, false); foreach(li, tableIds) { diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c index 1b936123c5..a64037a958 100644 --- a/src/backend/catalog/pg_inherits.c +++ b/src/backend/catalog/pg_inherits.c @@ -180,10 +180,12 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode, bool skip_locked, * The specified lock type is acquired on all child relations (but not on the * given rel; caller should already have locked it). If lockmode is NoLock * then no locks are acquired, but caller must beware of race conditions - * against possible DROPs of child relations. + * against possible DROPs of child relations. If skip_locked is true and a + * child relation can not be locked immediately without waiting, both the + * returned OID list and *numparents will be set to NIL. */ List * -find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents) +find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents, bool skip_locked) { /* hash table for O(1) rel_oid -> rel_numparents cell lookup */ HTAB *seen_rels; @@ -191,6 +193,7 @@ find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents) List *rels_list, *rel_numparents; ListCell *l; + bool skipped = false; memset(&ctl, 0, sizeof(ctl)); ctl.keysize = sizeof(Oid); @@ -219,7 +222,7 @@ find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents) ListCell *lc; /* Get the direct children of this rel */ - currentchildren = find_inheritance_children(currentrel, lockmode, false, NULL); + currentchildren = find_inheritance_children(currentrel, lockmode, skip_locked, &skipped); /* * Add to the queue only those children not already seen. This avoids @@ -248,6 +251,27 @@ find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents) hash_entry->numparents_cell = rel_numparents->tail; } } + + if (skipped) + break; + } + + /* if a child relation was skipped, set the return lists to NIL */ + if (skipped) + { + /* release all locks */ + foreach(l, rels_list) + { + Oid currentrel = lfirst_oid(l); + + if (currentrel != parentrelId) + UnlockRelationOid(currentrel, lockmode); + } + + list_free(rel_numparents); + list_free(rels_list); + rel_numparents = NIL; + rels_list = NIL; } if (numparents) diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index 25194e871c..651cf1f78e 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -1335,7 +1335,7 @@ acquire_inherited_sample_rows(Relation onerel, int elevel, * the children. */ tableOIDs = - find_all_inheritors(RelationGetRelid(onerel), AccessShareLock, NULL); + find_all_inheritors(RelationGetRelid(onerel), AccessShareLock, NULL, false); /* * Check that there's at least one descendant, else fail. This could diff --git a/src/backend/commands/publicationcmds.c b/src/backend/commands/publicationcmds.c index 6f7762a906..a5e01ea61e 100644 --- a/src/backend/commands/publicationcmds.c +++ b/src/backend/commands/publicationcmds.c @@ -530,7 +530,7 @@ OpenTableList(List *tables) List *children; children = find_all_inheritors(myrelid, ShareUpdateExclusiveLock, - NULL); + NULL, false); foreach(child, children) { diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 4f0640e9ba..a46aa8806e 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -1356,7 +1356,7 @@ ExecuteTruncate(TruncateStmt *stmt) ListCell *child; List *children; - children = find_all_inheritors(myrelid, AccessExclusiveLock, NULL); + children = find_all_inheritors(myrelid, AccessExclusiveLock, NULL, false); foreach(child, children) { @@ -2754,7 +2754,7 @@ renameatt_internal(Oid myrelid, * outside the inheritance hierarchy being processed. */ child_oids = find_all_inheritors(myrelid, AccessExclusiveLock, - &child_numparents); + &child_numparents, false); /* * find_all_inheritors does the recursive search of the inheritance @@ -2964,7 +2964,7 @@ rename_constraint_internal(Oid myrelid, *li; child_oids = find_all_inheritors(myrelid, AccessExclusiveLock, - &child_numparents); + &child_numparents, false); forboth(lo, child_oids, li, child_numparents) { @@ -5030,7 +5030,7 @@ ATSimpleRecursion(List **wqueue, Relation rel, ListCell *child; List *children; - children = find_all_inheritors(relid, lockmode, NULL); + children = find_all_inheritors(relid, lockmode, NULL, false); /* * find_all_inheritors does the recursive search of the inheritance @@ -8006,7 +8006,7 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse, */ if (!recursing && !con->connoinherit) children = find_all_inheritors(RelationGetRelid(rel), - lockmode, NULL); + lockmode, NULL, false); /* * For CHECK constraints, we must ensure that we only mark the @@ -9210,7 +9210,7 @@ ATPrepAlterColumnType(List **wqueue, ListCell *child; List *children; - children = find_all_inheritors(relid, lockmode, NULL); + children = find_all_inheritors(relid, lockmode, NULL, false); /* * find_all_inheritors does the recursive search of the inheritance @@ -11443,7 +11443,7 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode) * We use weakest lock we can on child's children, namely AccessShareLock. */ children = find_all_inheritors(RelationGetRelid(child_rel), - AccessShareLock, NULL); + AccessShareLock, NULL, false); if (list_member_oid(children, RelationGetRelid(parent_rel))) ereport(ERROR, @@ -14126,7 +14126,7 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) * weaker lock now and the stronger one only when needed. */ attachrel_children = find_all_inheritors(RelationGetRelid(attachrel), - AccessExclusiveLock, NULL); + AccessExclusiveLock, NULL, false); if (list_member_oid(attachrel_children, RelationGetRelid(rel))) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_TABLE), diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 24de0c58c0..34c4cc0ef8 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -364,7 +364,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString, rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE; if (partition_recurse) list_free(find_all_inheritors(RelationGetRelid(rel), - ShareRowExclusiveLock, NULL)); + ShareRowExclusiveLock, NULL, false)); /* Compute tgtype */ TRIGGER_CLEAR_TYPE(tgtype); diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index d90cb9a902..74049741a7 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -479,7 +479,7 @@ expand_vacuum_rel(VacuumRelation *vrel) */ if (include_parts) { - List *part_oids = find_all_inheritors(relid, NoLock, NULL); + List *part_oids = find_all_inheritors(relid, NoLock, NULL, false); ListCell *part_lc; foreach(part_lc, part_oids) diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index 7a4665cc4e..bfe2d1e1d6 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -89,7 +89,7 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, Relation rel) * Get the information about the partition tree after locking all the * partitions. */ - (void) find_all_inheritors(RelationGetRelid(rel), RowExclusiveLock, NULL); + (void) find_all_inheritors(RelationGetRelid(rel), RowExclusiveLock, NULL, false); proute = (PartitionTupleRouting *) palloc0(sizeof(PartitionTupleRouting)); proute->partition_dispatch_info = RelationGetPartitionDispatchInfo(rel, &proute->num_dispatch, diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 0ab4014be6..3019d4a335 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -1556,7 +1556,7 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti) lockmode = AccessShareLock; /* Scan for all members of inheritance set, acquire needed locks */ - inhOIDs = find_all_inheritors(parentOID, lockmode, NULL); + inhOIDs = find_all_inheritors(parentOID, lockmode, NULL, false); /* * Check that there's at least one descendant, else treat as no-child diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c index b19c76acc8..dcfe452a94 100644 --- a/src/backend/partitioning/partbounds.c +++ b/src/backend/partitioning/partbounds.c @@ -629,7 +629,7 @@ check_default_partition_contents(Relation parent, Relation default_rel, */ if (default_rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) all_parts = find_all_inheritors(RelationGetRelid(default_rel), - AccessExclusiveLock, NULL); + AccessExclusiveLock, NULL, false); else all_parts = list_make1_oid(RelationGetRelid(default_rel)); diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index bdfb66fa74..82397eb9f5 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1325,7 +1325,8 @@ ProcessUtilitySlow(ParseState *pstate, ListCell *lc; List *inheritors = NIL; - inheritors = find_all_inheritors(relid, lockmode, NULL); + inheritors = find_all_inheritors(relid, lockmode, + NULL, false); foreach(lc, inheritors) { char relkind = get_rel_relkind(lfirst_oid(lc)); diff --git a/src/include/catalog/pg_inherits.h b/src/include/catalog/pg_inherits.h index a89b3f44a5..ccbf756ce5 100644 --- a/src/include/catalog/pg_inherits.h +++ b/src/include/catalog/pg_inherits.h @@ -47,7 +47,7 @@ typedef FormData_pg_inherits *Form_pg_inherits; extern List *find_inheritance_children(Oid parentrelId, LOCKMODE lockmode, bool skip_locked, bool *skipped); extern List *find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, - List **parents); + List **parents, bool skip_locked); extern bool has_subclass(Oid relationId); extern bool has_superclass(Oid relationId); extern bool typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId); -- 2.16.2