From 776339a8c63c0bd8c83cfe8a619f6146794358e8 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Sat, 12 Sep 2026 11:53:58 +0000
Subject: [PATCH] [#922] Give a change back when the replay which owns it is unwound (#958)
---
opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChange.java | 37 +++++++++++++++++++++++++++++--------
1 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChange.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChange.java
index 34f4c4f..fa96a19 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChange.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/PendingChange.java
@@ -17,6 +17,8 @@
*/
package org.opends.server.replication.plugin;
+import net.jcip.annotations.GuardedBy;
+
import org.opends.server.replication.common.CSN;
import org.opends.server.replication.protocol.LDAPUpdateMsg;
import org.opends.server.replication.protocol.UpdateMsg;
@@ -36,11 +38,18 @@
*/
private volatile UpdateMsg msg;
/**
- * Whether a replay thread owns this change: it is being replayed, or it waits for the
+ * The replay thread which owns this change: it is being replayed, or it waits for the
* change it depends on. A remote change which no thread owns is one whose replay
* failed and which the replication server is expected to deliver again.
+ * <p>
+ * The owner is kept rather than the bare fact that there is one, so that a change is
+ * given back by the thread it was handed to and by nobody else: a release which arrives
+ * from a thread which does not own the change anymore - it reports a failure on a change
+ * which has been taken over since - would hand a change which is being replayed right
+ * now to a second thread (issue #922).
*/
- private boolean owned;
+ @GuardedBy("RemotePendingChanges.pendingChangesLock")
+ private Thread owner;
/**
* How many times in a row the replay of this change failed, and when the first of
* those failures happened - on a clock which only moves forward.
@@ -138,18 +147,30 @@
*/
public boolean isOwned()
{
- return owned;
+ return owner != null;
}
/**
- * Sets whether a replay thread owns this change.
+ * Returns whether the provided thread owns this change.
*
- * @param owned {@code true} when a replay thread takes the change over, {@code false}
- * when its replay failed and the change must be delivered again
+ * @param thread the thread which claims the change
+ * @return {@code true} if that thread is the one this change was handed to
*/
- public void setOwned(boolean owned)
+ public boolean isOwnedBy(Thread thread)
{
- this.owned = owned;
+ // A change nobody owns is not owned by a caller which has no thread to name either.
+ return thread != null && owner == thread;
+ }
+
+ /**
+ * Sets the replay thread which owns this change.
+ *
+ * @param owner the thread which takes the change over, or {@code null} when it is given
+ * back - its replay failed, or it has been applied
+ */
+ public void setOwner(Thread owner)
+ {
+ this.owner = owner;
}
/**
--
Gitblit v1.10.0