From 32a3660838f983699af8ff548507288cc9a1bc07 Mon Sep 17 00:00:00 2001
From: Maxim Thomas <maxim.thomas@gmail.com>
Date: Wed, 09 Sep 2026 07:20:47 +0000
Subject: [PATCH] [#921] Bound the transaction replay of PDBStorage.write() (#937)

---
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java |   17 ++++++++++++++---
 1 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java
index cf04069..2164d2e 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java
@@ -73,13 +73,24 @@
   <T> T read(ReadOperation<T> readOperation) throws Exception;
 
   /**
-   * Executes a write operation. In case of a write operation rollback, implementations must ensure
-   * the write operation is retried until it succeeds.
+   * Executes a write operation. In case of a write operation rollback, implementations may replay the write
+   * operation rather than propagate the failure: a {@link WriteOperation} is required to be idempotent for
+   * exactly that reason. A replay must be bounded - by a number of attempts, by a window of time, or by both -
+   * so that a conflict which does not clear reaches the caller instead of being retried forever. The pluggable
+   * backend holds locks across this method, up to the exclusive lock of an entry container, and every thread
+   * waiting on one of those locks waits for as long as this method does.
+   * <p>
+   * A caller that mutates state around this method must handle that bound being spent. Removing an entry from an
+   * in-memory map before the write so that a replay still finds the work to do, or reading configuration back out
+   * of the operation once it returns, both assume the write is applied; when it is not, this method throws with
+   * that state already changed and the transaction not applied, and the caller is the only place that can reconcile
+   * the two.
    *
    * @param writeOperation
    *          the write operation to execute
    * @throws Exception
-   *           if a problem occurs with the underlying storage engine
+   *           if a problem occurs with the underlying storage engine, including a conflict that outlasted the
+   *           replays the implementation makes
    */
   void write(WriteOperation writeOperation) throws Exception;
 

--
Gitblit v1.10.0