From e57d7909735bb06d3cdb231043a97669262c3b8c Mon Sep 17 00:00:00 2001
From: Dilip Kumar <dilip.kumar@enterprisedb.com>
Date: Fri, 13 Mar 2020 18:55:04 +0530
Subject: [PATCH v6 3/4] Relation extension lock to conflict among parallel 
 group members.

Make relation extension lock conflicting among the parallel group members.
So that multiple worker will not get the lock at the same time and create
the race condition.  Also, remove this lock from participate in deadlock
detection.
---
 src/backend/storage/lmgr/deadlock.c | 8 ++++++++
 src/backend/storage/lmgr/lock.c     | 8 ++++++++
 src/backend/storage/lmgr/proc.c     | 8 +++++++-
 src/include/storage/lock.h          | 1 +
 4 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/backend/storage/lmgr/deadlock.c b/src/backend/storage/lmgr/deadlock.c
index f8c5df0..6106c2d 100644
--- a/src/backend/storage/lmgr/deadlock.c
+++ b/src/backend/storage/lmgr/deadlock.c
@@ -555,6 +555,14 @@ FindLockCycleRecurseMember(PGPROC *checkProc,
 	int			numLockModes,
 				lm;
 
+	/*
+	 * The relation extension lock can never participate in actual deadlock
+	 * cycle.  See Asserts in LockAcquireExtended.  So, there is no advantage in
+	 * checking wait edges from it.
+	 */
+	if (LOCK_LOCKTAG(*lock) == LOCKTAG_RELATION_EXTEND)
+		return false;
+
 	lockMethodTable = GetLocksMethodTable(lock);
 	numLockModes = lockMethodTable->numLockModes;
 	conflictMask = lockMethodTable->conflictTab[checkProc->waitLockMode];
diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index e182ec7..02d7758 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -1461,6 +1461,14 @@ LockCheckConflicts(LockMethod lockMethodTable,
 		return true;
 	}
 
+	/* The relation extension lock conflict even between the group members. */
+	if (LOCK_LOCKTAG(*lock) == LOCKTAG_RELATION_EXTEND)
+	{
+		PROCLOCK_PRINT("LockCheckConflicts: conflicting (group)",
+				proclock);
+		return true;
+	}
+
 	/*
 	 * Locks held in conflicting modes by members of our own lock group are
 	 * not real conflicts; we can subtract those out and see if we still have
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index eb321f7..1127168 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -1077,7 +1077,13 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
 
 	/*
 	 * If group locking is in use, locks held by members of my locking group
-	 * need to be included in myHeldLocks.
+	 * need to be included in myHeldLocks.  This is not required for
+	 * relation extension lock which conflict among group members. However,
+	 * including them in myHeldLocks will give group members the priority to get
+	 * those locks as compared to other backends which are also trying to
+	 * acquire those locks.  OTOH, we can avoid giving priority to group members
+	 * for that kind of locks, but there doesn't appear to be a clear advantage
+	 * of the same.
 	 */
 	if (leader != NULL)
 	{
diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h
index bb8e4e6..fac979d 100644
--- a/src/include/storage/lock.h
+++ b/src/include/storage/lock.h
@@ -301,6 +301,7 @@ typedef struct LOCK
 } LOCK;
 
 #define LOCK_LOCKMETHOD(lock) ((LOCKMETHODID) (lock).tag.locktag_lockmethodid)
+#define LOCK_LOCKTAG(lock) ((LockTagType) (lock).tag.locktag_type)
 
 
 /*
-- 
1.8.3.1

