From e69422e8141e3551e310919a35ecc56cf69a6935 Mon Sep 17 00:00:00 2001
From: Fabio Pistolesi <fabio.pistolesi@forgerock.com>
Date: Wed, 22 Jun 2016 14:54:31 +0000
Subject: [PATCH] OPENDJ-3041 Strictly select the backend where an entry reside taking into account all child backends
---
opendj-server-legacy/src/test/java/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElementTest.java | 46 +++++++++++++++++++++-
opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java | 37 ++++++++++++++++--
2 files changed, 75 insertions(+), 8 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java b/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
index faa103f..8487d34 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
@@ -20,7 +20,6 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import java.util.TreeMap;
import org.forgerock.i18n.LocalizableMessage;
@@ -903,12 +902,40 @@
{
return registeredLocalBackends.get(entryDN);
}
- Map.Entry<DN, LocalBackendWorkflowElement> backendWorkflow = registeredLocalBackends.floorEntry(entryDN);
- if (backendWorkflow.getKey().isSuperiorOrEqualTo(entryDN))
+ /*
+ * Try to minimize the number of lookups in the Map to find the backend containing the entry.
+ * If the DN contains many RDNs it is faster to iterate through the list of registered backends,
+ * otherwise iterating through the parents requires less lookups. It also avoids some attacks
+ * where we would spend time going through the list of all parents to finally decide the
+ * baseDN is absent.
+ */
+ if (entryDN.size() <= registeredLocalBackends.size())
{
- return backendWorkflow.getValue();
+ while (!entryDN.isRootDN())
+ {
+ final LocalBackendWorkflowElement workflow = registeredLocalBackends.get(entryDN);
+ if (workflow != null)
+ {
+ return workflow;
+ }
+ entryDN = entryDN.parent();
+ }
+ return null;
}
- return null;
+ else
+ {
+ LocalBackendWorkflowElement workflow = null;
+ int currentSize = 0;
+ for (DN backendDN : registeredLocalBackends.keySet())
+ {
+ if (entryDN.isSubordinateOrEqualTo(backendDN) && backendDN.size() > currentSize)
+ {
+ workflow = registeredLocalBackends.get(backendDN);
+ currentSize = backendDN.size();
+ }
+ }
+ return workflow;
+ }
}
/**
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElementTest.java b/opendj-server-legacy/src/test/java/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElementTest.java
index a8143c2..998850d 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElementTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElementTest.java
@@ -145,6 +145,37 @@
}
}
+ @Test
+ public void testParentBackendSelection() throws Exception
+ {
+ String parentID = "parent";
+ String childID1 = "child1";
+ String strangerID = "stranger";
+ String parent = "dc=abc";
+ String child1 = "dc=example,dc=abc";
+ String child2 = "dc=example2,dc=abc";
+ String stranger = "dc=abc1";
+
+ try
+ {
+ TestCaseUtils.clearDataBackends();
+ TestCaseUtils.initializeMemoryBackend(parentID, parent, true);
+ TestCaseUtils.initializeMemoryBackend(childID1, child1, true);
+ TestCaseUtils.initializeMemoryBackend(strangerID, stranger, true);
+
+ assertEquals(getMatchedDN("cn=user," + parent), DN.valueOf(parent));
+ assertEquals(getMatchedDN("cn=user," + child1), DN.valueOf(child1));
+ assertEquals(getMatchedDN("cn=user," + child2), DN.valueOf(parent));
+ assertEquals(getMatchedDN("cn=user," + stranger), DN.valueOf(stranger));
+ }
+ finally
+ {
+ TestCaseUtils.clearMemoryBackend(parentID);
+ TestCaseUtils.clearMemoryBackend(childID1);
+ TestCaseUtils.clearMemoryBackend(strangerID);
+ }
+ }
+
/**
* This test checks that the workflow takes into account the subordinate
* naming context defined in the RootDSEBackend.
@@ -258,9 +289,18 @@
private void modifyAttribute(String baseDN, ModificationType modType, String attrName, String attrValue)
throws Exception
{
- ModifyRequest modifyRequest = Requests.newModifyRequest(baseDN)
- .addModification(modType, attrName, attrValue);
- ModifyOperation modifyOperation = getRootConnection().processModify(modifyRequest);
+ ModifyOperation modifyOperation = getModifyOperation(baseDN, modType, attrName, attrValue);
assertEquals(modifyOperation.getResultCode(), ResultCode.SUCCESS);
}
+
+ private DN getMatchedDN(String entryDN)
+ {
+ return getModifyOperation(entryDN, ADD, "sn", "dummy").getMatchedDN();
+ }
+
+ private ModifyOperation getModifyOperation(String baseDN, ModificationType modType, String attrName, String attrValue)
+ {
+ ModifyRequest modifyRequest = Requests.newModifyRequest(baseDN).addModification(modType, attrName, attrValue);
+ return getRootConnection().processModify(modifyRequest);
+ }
}
--
Gitblit v1.10.0