From 3e256e550672657375fc3058b2b8ff6568d65cef Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Fri, 30 Mar 2018 16:56:41 -0700 Subject: [PATCH] Add SKIP_LOCKED option to RangeVarGetRelidExtended(). This will be used for VACUUM (SKIP LOCKED). Author: Nathan Bossart Reviewed-By: Michael Paquier and Andres Freund Discussion: https://postgr.es/m/20180306005349.b65whmvj7z6hbe2y@alap3.anarazel.de --- src/backend/catalog/namespace.c | 22 +++++++++++++++++++--- src/include/catalog/namespace.h | 3 ++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c index 687d31e083..d69b015c69 100644 --- a/src/backend/catalog/namespace.c +++ b/src/backend/catalog/namespace.c @@ -212,6 +212,15 @@ static bool MatchNamedCall(HeapTuple proctup, int nargs, List *argnames, * If flags contains RVR_NOWAIT, throw an error if we'd have to wait for a * lock. * + * If flags contains RVR_SKIP_LOCKED, return InvalidOid if we'd have to wait + * for a lock. + * + * flags cannot contain both RVR_NOWAIT and RVR_SKIP_LOCKED. + * + * Note that if RVR_MISSING_OK and RVR_SKIP_LOCKED are both specified, a + * return value of InvalidOid could either mean the relation is missing or it + * could not be locked. + * * Callback allows caller to check permissions or acquire additional locks * prior to grabbing the relation lock. */ @@ -226,6 +235,9 @@ RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, bool retry = false; bool missing_ok = (flags & RVR_MISSING_OK) != 0; + /* verify that flags do no conflict */ + Assert(!((flags & RVR_NOWAIT) && (flags & RVR_SKIP_LOCKED))); + /* * We check the catalog name and then ignore it. */ @@ -363,20 +375,24 @@ RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, */ if (!OidIsValid(relId)) AcceptInvalidationMessages(); - else if (!(flags & RVR_NOWAIT)) + else if (!(flags & (RVR_NOWAIT | RVR_SKIP_LOCKED))) LockRelationOid(relId, lockmode); else if (!ConditionalLockRelationOid(relId, lockmode)) { + int elevel = (flags & RVR_SKIP_LOCKED) ? DEBUG1 : ERROR; + if (relation->schemaname) - ereport(ERROR, + ereport(elevel, (errcode(ERRCODE_LOCK_NOT_AVAILABLE), errmsg("could not obtain lock on relation \"%s.%s\"", relation->schemaname, relation->relname))); else - ereport(ERROR, + ereport(elevel, (errcode(ERRCODE_LOCK_NOT_AVAILABLE), errmsg("could not obtain lock on relation \"%s\"", relation->relname))); + + return InvalidOid; } /* diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h index 0bccf910a9..7991de5e21 100644 --- a/src/include/catalog/namespace.h +++ b/src/include/catalog/namespace.h @@ -53,7 +53,8 @@ typedef struct OverrideSearchPath typedef enum RVROption { RVR_MISSING_OK = 1 << 0, /* don't error if relation doesn't exist */ - RVR_NOWAIT = 1 << 1 /* error if relation cannot be locked */ + RVR_NOWAIT = 1 << 1, /* error if relation cannot be locked */ + RVR_SKIP_LOCKED = 1 << 2 /* skip if relation cannot be locked */ } RVROption; typedef void (*RangeVarGetRelidCallback) (const RangeVar *relation, Oid relId,