]> granicus.if.org Git - postgresql/commitdiff
Add SKIP_LOCKED option to RangeVarGetRelidExtended().
authorAndres Freund <andres@anarazel.de>
Fri, 30 Mar 2018 23:56:41 +0000 (16:56 -0700)
committerAndres Freund <andres@anarazel.de>
Sat, 31 Mar 2018 00:05:16 +0000 (17:05 -0700)
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
src/include/catalog/namespace.h

index 687d31e083ba511b084374493211fd4ea4e56836..d69b015c6980089a2d37b51bfc7bd6665cddb768 100644 (file)
@@ -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;
                }
 
                /*
index 0bccf910a9ec50dbb726097d2682a384de6ecf4d..7991de5e210bb5800fb652d5350b914cecf48f52 100644 (file)
@@ -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,