From bf4ea603433151433d712402173f4de5e7ad3b3c Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@enterprisedb.com>
Date: Fri, 8 Dec 2017 14:48:12 +1300
Subject: [PATCH] Provide a way for static barriers to deal with worker launch
 failure.

If using a static barrier, we need a way to deal with the failure of workers
to launch.  Provide a function that the leader process can call after
determining the true number of workers running, to reduce the number of
participants if necessary.  This avoids the need to use the more complicated
dynamic barrier API.

Author: Thomas Munro
Discussion: https://postgr.es/m/CAEepm%3D03YnefpCeB%3DZ67HtQAOEMuhKGyPCY_S1TeH%3D9a2Rr0LQ%40mail.gmail.com
---
 src/backend/storage/ipc/barrier.c | 20 ++++++++++++++++++--
 src/include/storage/barrier.h     |  1 +
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/backend/storage/ipc/barrier.c b/src/backend/storage/ipc/barrier.c
index 7dde932738..12a017c9c5 100644
--- a/src/backend/storage/ipc/barrier.c
+++ b/src/backend/storage/ipc/barrier.c
@@ -202,6 +202,8 @@ BarrierArriveAndWait(Barrier *barrier, uint32 wait_event_info)
 bool
 BarrierArriveAndDetach(Barrier *barrier)
 {
+	Assert(!barrier->static_party);
+
 	return BarrierDetachImpl(barrier, true);
 }
 
@@ -233,9 +235,25 @@ BarrierAttach(Barrier *barrier)
 bool
 BarrierDetach(Barrier *barrier)
 {
+	Assert(!barrier->static_party);
+
 	return BarrierDetachImpl(barrier, false);
 }
 
+/*
+ * Forget about some number of static participants.  This is used only to
+ * reduce the static party size, typically as the result of failure to start
+ * worker processes.
+ */
+void
+BarrierForgetParticipants(Barrier *barrier, int n)
+{
+	Assert(barrier->static_party);
+
+	while (n-- > 0)
+		BarrierDetachImpl(barrier, true);
+}
+
 /*
  * Return the current phase of a barrier.  The caller must be attached.
  */
@@ -280,8 +298,6 @@ BarrierDetachImpl(Barrier *barrier, bool arrive)
 	bool		release;
 	bool		last;
 
-	Assert(!barrier->static_party);
-
 	SpinLockAcquire(&barrier->mutex);
 	Assert(barrier->participants > 0);
 	--barrier->participants;
diff --git a/src/include/storage/barrier.h b/src/include/storage/barrier.h
index 0abaa2b98b..b67e5aa3f3 100644
--- a/src/include/storage/barrier.h
+++ b/src/include/storage/barrier.h
@@ -39,6 +39,7 @@ extern bool BarrierArriveAndWait(Barrier *barrier, uint32 wait_event_info);
 extern bool BarrierArriveAndDetach(Barrier *barrier);
 extern int	BarrierAttach(Barrier *barrier);
 extern bool BarrierDetach(Barrier *barrier);
+extern void BarrierForgetParticipants(Barrier *barrier, int n);
 extern int	BarrierPhase(Barrier *barrier);
 extern int	BarrierParticipants(Barrier *barrier);
 
-- 
2.15.0

