From 06e91a18f48ddf1cae6cbc9946688dea6a161425 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Sat, 11 Jul 2026 10:36:01 +0000
Subject: [PATCH] [#730] Fix import/export context leak on failed initializeRemote validation (#731)
---
opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationDomain.java | 58 ++++++++++++++++++++++++++++++++++++++++++++--------------
1 files changed, 44 insertions(+), 14 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationDomain.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationDomain.java
index 8781e70..a63f74a 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationDomain.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationDomain.java
@@ -1442,8 +1442,6 @@
int serverRunningTheTask, Task initTask, int initWindow)
throws DirectoryException
{
- final ImportExportContext ieCtx = acquireIEContext(false);
-
/*
We manage the list of servers to initialize in order :
- to test at the end that all expected servers have reconnected
@@ -1451,7 +1449,12 @@
- to update the task with the server(s) where this test failed
*/
- Map<Integer, DSInfo> replicaInfos = getReplicaInfos();
+ // Validate the request before acquiring the import/export context: a
+ // validation failure must not leave the context acquired, otherwise
+ // ieRunning() would remain true forever and the domain would reject every
+ // subsequent total update as a simultaneous import/export.
+ final Map<Integer, DSInfo> replicaInfos = getReplicaInfos();
+ final DSInfo targetDsi;
if (serverToInitialize == RoutableMsg.ALL_SERVERS)
{
if (replicaInfos.isEmpty())
@@ -1459,7 +1462,44 @@
throw new DirectoryException(UNWILLING_TO_PERFORM,
ERR_FULL_UPDATE_NO_REMOTES.get(getBaseDN(), getServerId()));
}
+ targetDsi = null;
+ }
+ else
+ {
+ targetDsi = getDsInfoOrNull(replicaInfos.values(), serverToInitialize);
+ if (targetDsi == null)
+ {
+ throw new DirectoryException(UNWILLING_TO_PERFORM,
+ ERR_FULL_UPDATE_MISSING_REMOTE.get(getBaseDN(), getServerId(), serverToInitialize));
+ }
+ }
+ final ImportExportContext ieCtx = acquireIEContext(false);
+ try
+ {
+ initializeRemote(ieCtx, replicaInfos, targetDsi, serverToInitialize,
+ serverRunningTheTask, initTask, initWindow);
+ }
+ finally
+ {
+ // Release the context whatever the outcome, otherwise ieRunning() would
+ // remain true forever (resolves the historical "FIXME should not this
+ // be in a finally?").
+ releaseIEContext();
+ }
+ }
+
+ /**
+ * Performs the remote initialization with the import/export context already
+ * acquired - and released - by the caller.
+ */
+ private void initializeRemote(ImportExportContext ieCtx,
+ Map<Integer, DSInfo> replicaInfos, DSInfo targetDsi,
+ int serverToInitialize, int serverRunningTheTask, Task initTask,
+ int initWindow) throws DirectoryException
+ {
+ if (serverToInitialize == RoutableMsg.ALL_SERVERS)
+ {
logger.info(NOTE_FULL_UPDATE_ENGAGED_FOR_REMOTE_START_ALL,
countEntries(), getBaseDN(), getServerId());
@@ -1475,18 +1515,11 @@
}
else
{
- DSInfo dsi = getDsInfoOrNull(replicaInfos.values(), serverToInitialize);
- if (dsi == null)
- {
- throw new DirectoryException(UNWILLING_TO_PERFORM,
- ERR_FULL_UPDATE_MISSING_REMOTE.get(getBaseDN(), getServerId(), serverToInitialize));
- }
-
logger.info(NOTE_FULL_UPDATE_ENGAGED_FOR_REMOTE_START, countEntries(),
getBaseDN(), getServerId(), serverToInitialize);
ieCtx.startList.add(serverToInitialize);
- ieCtx.setAckVal(dsi.getDsId(), 0);
+ ieCtx.setAckVal(targetDsi.getDsId(), 0);
}
DirectoryException exportRootException = null;
@@ -1625,9 +1658,6 @@
ERR_INIT_NO_SUCCESS_END_FROM_SERVERS.get(getGenerationID(), ieCtx.failureList));
}
- // Don't forget to release IEcontext acquired at beginning.
- releaseIEContext(); // FIXME should not this be in a finally?
-
final String cause = exportRootException == null ? ""
: exportRootException.getLocalizedMessage();
if (serverToInitialize == RoutableMsg.ALL_SERVERS)
--
Gitblit v1.10.0