From 92d88ca699cd8090a26b92cbe46789d2b848195f Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Mon, 07 Sep 2026 09:30:36 +0000
Subject: [PATCH] [#889] Keep a change the replay could not apply out of the ServerState (#892)
---
opendj-server-legacy/src/test/java/org/opends/server/plugins/ShortCircuitPlugin.java | 68 +++++++++++++++++++++++++++++++--
1 files changed, 63 insertions(+), 5 deletions(-)
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/plugins/ShortCircuitPlugin.java b/opendj-server-legacy/src/test/java/org/opends/server/plugins/ShortCircuitPlugin.java
index 2a04473..751daac 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/plugins/ShortCircuitPlugin.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/plugins/ShortCircuitPlugin.java
@@ -13,6 +13,7 @@
*
* Copyright 2006-2008 Sun Microsystems, Inc.
* Portions Copyright 2014-2016 ForgeRock AS.
+ * Portions Copyright 2026 3A Systems, LLC.
*/
package org.opends.server.plugins;
@@ -25,6 +26,7 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.opendj.config.server.ConfigException;
@@ -614,11 +616,18 @@
}
// Check for registered short circuits.
- Integer resultCode = shortCircuits.get(
- operation.getOperationType() + "/" + section.toLowerCase());
+ final String key = operation.getOperationType() + "/" + section.toLowerCase();
+ Integer resultCode = shortCircuits.get(key);
if (resultCode != null)
{
- return resultCode;
+ final int reached = shortCircuitCounts.computeIfAbsent(key, k -> new AtomicInteger()).incrementAndGet();
+ final Integer maxTimes = shortCircuitLimits.get(key);
+ if (maxTimes == null || reached <= maxTimes)
+ {
+ return resultCode;
+ }
+ // The short circuit was applied as many times as it was asked for: from now on the
+ // operations are let through, which is how a transient failure is simulated.
}
// If we've gotten here, then we shouldn't short-circuit the operation
@@ -662,6 +671,28 @@
/** Registered short circuits for operations regardless of controls. */
private static Map<String, Integer> shortCircuits = new ConcurrentHashMap<>();
+ /** How many times a registered short circuit was reached. */
+ private static final Map<String, AtomicInteger> shortCircuitCounts = new ConcurrentHashMap<>();
+
+ /** How many times a registered short circuit must be applied, when it is limited. */
+ private static final Map<String, Integer> shortCircuitLimits = new ConcurrentHashMap<>();
+
+ /**
+ * Returns how many times the short circuit registered for the given operation type and
+ * plugin point was reached. A short circuit registered for a limited number of times is
+ * counted as reached by the operations it let through once that number was used up.
+ *
+ * @param operation The type of operation the short circuit applies to.
+ * @param section The plugin point the short circuit applies to.
+ * @return the number of operations which reached the short circuit
+ */
+ public static int getShortCircuitCount(OperationType operation, String section)
+ {
+ final AtomicInteger count = shortCircuitCounts.get(operation + "/" + section.toLowerCase());
+ return count != null ? count.get() : 0;
+ }
+
+
/**
* Register a short circuit for the given operation type and plugin point.
* @param operation The type of operation the short circuit applies to.
@@ -670,7 +701,29 @@
*/
public static void registerShortCircuit(OperationType operation, String section, int resultCode)
{
- shortCircuits.put(operation + "/" + section.toLowerCase(), resultCode);
+ final String key = operation + "/" + section.toLowerCase();
+ // This registration applies to every operation, and it counts from zero: a limit or
+ // a count left behind by a previous registration is not part of it.
+ shortCircuitCounts.remove(key);
+ shortCircuitLimits.remove(key);
+ shortCircuits.put(key, resultCode);
+ }
+
+ /**
+ * Register a short circuit which only applies to the given number of operations, the
+ * ones which follow being let through: this is how a transient failure is simulated.
+ *
+ * @param operation The type of operation the short circuit applies to.
+ * @param section The plugin point the short circuit applies to.
+ * @param resultCode The result code to be returned for the short circuit.
+ * @param maxTimes How many operations must be short circuited.
+ */
+ public static void registerShortCircuit(OperationType operation, String section, int resultCode, int maxTimes)
+ {
+ final String key = operation + "/" + section.toLowerCase();
+ shortCircuitCounts.remove(key);
+ shortCircuitLimits.put(key, maxTimes);
+ shortCircuits.put(key, resultCode);
}
/**
@@ -680,6 +733,11 @@
*/
public static void deregisterShortCircuit(OperationType operation, String section)
{
- shortCircuits.remove(operation + "/" + section.toLowerCase());
+ final String key = operation + "/" + section.toLowerCase();
+ shortCircuits.remove(key);
+ shortCircuitLimits.remove(key);
+ // The count belongs to the registration which is being removed: a test which counts
+ // the operations it short circuits must not inherit the count of the previous one.
+ shortCircuitCounts.remove(key);
}
}
--
Gitblit v1.10.0