mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Fabio Pistolesi
22.25.2016 e69422e8141e3551e310919a35ecc56cf69a6935
OPENDJ-3041 Strictly select the backend where an entry reside taking into account all child backends

A side effect of fixing OPENDJ-2946 is the selection of which backend should contain a given entry.
We were basing the choice on the longest match for the backend, but if there are backends who are
sub-suffixes of another, it does not work.
Revert to scan the list of backends for a match or walking the parent DNs of the entry, depending of which we deem the fastest
2 files modified
83 ■■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java 37 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElementTest.java 46 ●●●●● patch | view | raw | blame | history
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;
    }
  }
  /**
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);
  }
}