From a970360bc97f5d59b4d6919700432ae7d2573c73 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Thu, 5 Apr 2018 16:52:56 +0000 Subject: [PATCH v7 02/12] Add skip_locked argument to find_all_inheritors(). --- contrib/sepgsql/dml.c | 2 +- src/backend/catalog/partition.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 | 18 +++++++++--------- 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/tcop/utility.c | 2 +- src/include/catalog/pg_inherits_fn.h | 2 +- 12 files changed, 46 insertions(+), 22 deletions(-) diff --git a/contrib/sepgsql/dml.c b/contrib/sepgsql/dml.c index c1fa320eb4..bbc72a59a2 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/partition.c b/src/backend/catalog/partition.c index 42453c5007..b701073dcb 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -1270,7 +1270,7 @@ check_default_allows_bound(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/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c index 17f8b58fba..c986540974 100644 --- a/src/backend/catalog/pg_inherits.c +++ b/src/backend/catalog/pg_inherits.c @@ -181,10 +181,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; @@ -192,6 +194,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); @@ -220,7 +223,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 @@ -249,6 +252,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 378784a93c..451e923132 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 9c5aa9ebc2..b347d671a5 100644 --- a/src/backend/commands/publicationcmds.c +++ b/src/backend/commands/publicationcmds.c @@ -516,7 +516,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 15017c5a62..3d19dd728f 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) { @@ -2667,7 +2667,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 @@ -2877,7 +2877,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) { @@ -4943,7 +4943,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 @@ -7918,7 +7918,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 @@ -9122,7 +9122,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 @@ -11355,7 +11355,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, @@ -14059,7 +14059,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), @@ -14252,7 +14252,7 @@ ATExecAttachPartition(List **wqueue, Relation rel, PartitionCmd *cmd) get_proposed_default_constraint(partBoundConstraint); defaultrel_children = find_all_inheritors(defaultPartOid, - AccessExclusiveLock, NULL); + AccessExclusiveLock, NULL, false); ValidatePartitionConstraints(wqueue, defaultrel, defaultrel_children, defPartConstraint, true); diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index a7e549e0ae..1aa65ffc97 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -371,7 +371,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 a1782c2874..db1b6e2d26 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 ad532773a3..bf77eedbcb 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -77,7 +77,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 5236ab378e..d5112a6ec8 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/tcop/utility.c b/src/backend/tcop/utility.c index 84f2591736..af4e1fb0ff 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1323,7 +1323,7 @@ ProcessUtilitySlow(ParseState *pstate, rel = heap_open(relid, NoLock); if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE) inheritors = find_all_inheritors(relid, lockmode, - NULL); + NULL, false); heap_close(rel, NoLock); } diff --git a/src/include/catalog/pg_inherits_fn.h b/src/include/catalog/pg_inherits_fn.h index 34d2a2f39f..5374dc48da 100644 --- a/src/include/catalog/pg_inherits_fn.h +++ b/src/include/catalog/pg_inherits_fn.h @@ -20,7 +20,7 @@ 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