From 600df926522919b63bfca2816ef9588b6f1c6e34 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Tue, 15 Sep 2026 17:09:57 +0000
Subject: [PATCH] [#950] Announce a ReplicaOfflineMsg before it is published, not after it may have been forwarded (#978)
---
opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChanges.java | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 53 insertions(+), 2 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChanges.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChanges.java
index 4f88b62..231298f 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChanges.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChanges.java
@@ -53,6 +53,9 @@
/** The ReplicationDomain that will be used to send UpdateMsg. */
private final ReplicationDomain domain;
+ /** Told that the replica of this domain announces itself offline, or takes that back. */
+ private final ReplicaOfflineAnnouncer replicaOfflineAnnouncer;
+
private boolean recoveringOldChanges;
/**
@@ -60,11 +63,16 @@
*
* @param csnGenerator The CSNGenerator to use to create new unique CSNs.
* @param domain The ReplicationDomain that will be used to send UpdateMsg.
+ * @param replicaOfflineAnnouncer Told that the replica of this domain announces itself
+ * offline, before the message announcing it is published, and that it takes
+ * the announcement back when the broker refused the message.
*/
- PendingChanges(CSNGenerator csnGenerator, ReplicationDomain domain)
+ PendingChanges(CSNGenerator csnGenerator, ReplicationDomain domain,
+ ReplicaOfflineAnnouncer replicaOfflineAnnouncer)
{
this.csnGenerator = csnGenerator;
this.domain = domain;
+ this.replicaOfflineAnnouncer = replicaOfflineAnnouncer;
}
/**
@@ -198,9 +206,22 @@
}
else if (msg instanceof ReplicaOfflineMsg)
{
+ /*
+ * Announce the replica offline before the message reaches the wire, and not after:
+ * a collocated replication server forwards it as soon as it has it, and a forward
+ * which finds nothing announced leaves the shutdown waiting out the whole grace
+ * period of a message the topology already has.
+ */
+ final CSN offlineCSN = msg.getCSN();
+ replicaOfflineAnnouncer.announce(offlineCSN);
if (domain.publish(msg))
{
- publishedOfflineCSN = msg.getCSN();
+ publishedOfflineCSN = offlineCSN;
+ }
+ else
+ {
+ // The broker wrote it to no session, so nobody will forward what was announced.
+ replicaOfflineAnnouncer.withdraw(offlineCSN);
}
}
@@ -266,4 +287,34 @@
}
return recoveringOldChanges;
}
+
+ /**
+ * Told that the replica of this domain announces itself offline, or takes that back.
+ * <p>
+ * A collocated replication server can forward a {@link ReplicaOfflineMsg} as soon as it is on
+ * the wire, and its shutdown waits for that forward, so the announcement has to be in place
+ * before the message is published: one made afterwards is one the forward found nothing to
+ * clear, and the shutdown spends its whole grace period on a message which has already gone
+ * out. The broker may still refuse the message once it is announced, and then the
+ * announcement is withdrawn: what stays announced is what the broker reports as written.
+ */
+ interface ReplicaOfflineAnnouncer
+ {
+ /**
+ * Announces that the replica goes offline at the provided CSN.
+ *
+ * @param offlineCSN
+ * the CSN of the ReplicaOfflineMsg which is about to be published
+ */
+ void announce(CSN offlineCSN);
+
+ /**
+ * Withdraws the announcement of a message the broker refused: it was written to no session,
+ * so nobody will forward it.
+ *
+ * @param offlineCSN
+ * the CSN of the ReplicaOfflineMsg which was announced and not published
+ */
+ void withdraw(CSN offlineCSN);
+ }
}
--
Gitblit v1.10.0