From 5d176c691527e3fe4bc529ff8947f3b3648970bd Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Thu, 10 Sep 2026 11:58:57 +0000
Subject: [PATCH] [#916] Keep an update that lands during a ServerState save out of the saved flag (#948)

---
 opendj-server-legacy/src/main/java/org/opends/server/replication/common/ServerState.java |   21 +++++++++++++++------
 1 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/common/ServerState.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/common/ServerState.java
index 82ba7ba..d1561b2 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/common/ServerState.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/common/ServerState.java
@@ -46,7 +46,10 @@
   private final ConcurrentMap<Integer, CSN> serverIdToCSN = new ConcurrentSkipListMap<>();
   /**
    * Whether the state has been saved to persistent storage. It starts at true,
-   * and moves to false when an update is made to the current object.
+   * and moves to false when a change is actually made to the current object -
+   * once that change is visible in {@link #serverIdToCSN}, never before, so
+   * that a reader cannot see the flag cleared for a change its own view of the
+   * map does not hold yet.
    */
   private volatile boolean saved = true;
 
@@ -58,12 +61,18 @@
 
   /**
    * Empty the ServerState.
-   * After this call the Server State will be in the same state
-   * as if it was just created.
+   * After this call the Server State no longer holds any CSN. A state which
+   * held one is marked as not saved: dropping it is a change like any other,
+   * which persistent storage has yet to be told about. A state which held
+   * nothing is left alone, the way an update which changes nothing is.
    */
   public void clear()
   {
-    serverIdToCSN.clear();
+    if (!serverIdToCSN.isEmpty())
+    {
+      serverIdToCSN.clear();
+      saved = false;
+    }
   }
 
   /**
@@ -82,8 +91,6 @@
       return false;
     }
 
-    saved = false;
-
     final int serverId = csn.getServerId();
     while (true)
     {
@@ -92,6 +99,7 @@
       {
         if (serverIdToCSN.putIfAbsent(serverId, csn) == null)
         {
+          saved = false;
           return true;
         }
         // oops, a concurrent modification happened, run the same process again
@@ -101,6 +109,7 @@
       {
         if (serverIdToCSN.replace(serverId, existingCSN, csn))
         {
+          saved = false;
           return true;
         }
         // oops, a concurrent modification happened, run the same process again

--
Gitblit v1.10.0