From 45794c50d0b48bd59d0b318f781a7b653f134752 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Wed, 23 Sep 2026 13:50:35 +0000
Subject: [PATCH] [#1041] Claim the import context for the length of a session restart, and refuse the total update which lands across it (#1045)

---
 opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java |   17 +++++++++++++----
 1 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java
index 1467c35..1238dbd 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -4287,13 +4287,17 @@
     final long wakes;
     synchronized (serviceStateLock)
     {
-      if (sessionHasAnOwner())
+      /*
+       * The domain is going away or is being imported into: the session is not this
+       * thread's to stop. The total update is claimed against rather than read (issue
+       * #1041): the listener thread claims one this replica did not ask for under no lock,
+       * and a read here a few statements before that claim would stop the session the
+       * import is about to read.
+       */
+      if (ownsItsSession() || !disableServiceUnlessImportInProgress())
       {
-        // The domain is going away or is being imported into: the session is not this
-        // thread's to stop.
         return;
       }
-      disableService();
       stoppedSession = getSessionGeneration();
       wakes = sessionRestartBackoffWakes();
     }
@@ -6213,6 +6217,11 @@
    * it carries: the domain itself, when it is shutting down or disabled
    * ({@link #ownsItsSession()}), or a total update into this replica.
    * <p>
+   * What this reads, {@link #restartSession(boolean)} claims: a total update the listener
+   * thread is about to claim is not visible to a read, and the restart must not stop the
+   * session such a total update reads (issue #1041). This is the early exit of the roads
+   * which lead to that restart, and the answer for the ones which never restart anything.
+   * <p>
    * The total update owns the session from the moment it is asked for, not from the
    * moment its entries stream: the {@code InitializeTargetMsg} which answers the request
    * arrives over that session, so a restart made while it is on its way loses it, and the

--
Gitblit v1.10.0