From c6650aedac5c1ade8aee9e7a76eb0dd100a3e179 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Mon, 02 Nov 2026 15:39:56 +0000
Subject: [PATCH] [#1246] Keep the messages of the last local changes, and have a recovery publish the changes done before it began from them, as they were done (#1251)
---
opendj-server-legacy/src/main/java/org/opends/server/api/LocalBackend.java | 35 +++++++++++++++++++++++++++++++++++
1 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/api/LocalBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/api/LocalBackend.java
index ea42838..88c8de3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/api/LocalBackend.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/api/LocalBackend.java
@@ -20,6 +20,8 @@
import static org.opends.messages.BackendMessages.*;
import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -76,6 +78,39 @@
{
private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
+ /** Process-lifetime write barriers for data which cannot safely be used after an online replacement. */
+ private static final Map<DN, LocalizableMessage> writeFailures = new ConcurrentHashMap<>();
+
+ /**
+ * Prevents writes overlapping a failed data replacement until the server process is restarted.
+ * An in-core restart keeps the barrier, as it keeps the JVM running.
+ * The barrier survives backend and synchronization-provider reconfiguration.
+ * @param baseDN the suffix whose data cannot safely be written
+ * @param reason the reason to report to the operator and to rejected updates
+ */
+ public static void quarantineWrites(DN baseDN, LocalizableMessage reason)
+ {
+ writeFailures.putIfAbsent(baseDN, reason);
+ }
+
+ /**
+ * Returns the reason writes overlapping a suffix are forbidden, or null if none are forbidden.
+ * Ancestors are included because deleting or moving a subtree affects the suffix below it.
+ * @param dn the DN of the entry or subtree an operation changes
+ * @return the recorded failure, or null
+ */
+ public static LocalizableMessage getWriteFailure(DN dn)
+ {
+ for (Map.Entry<DN, LocalizableMessage> failure : writeFailures.entrySet())
+ {
+ if (dn.isSubordinateOrEqualTo(failure.getKey()) || dn.isSuperiorOrEqualTo(failure.getKey()))
+ {
+ return failure.getValue();
+ }
+ }
+ return null;
+ }
+
/** Indicates whether this is a private backend or one that holds user data. */
private boolean isPrivateBackend;
--
Gitblit v1.10.0