From d75c93322e20bdad4cc2c57bd784a03d95fd3105 Mon Sep 17 00:00:00 2001
From: kenneth_suter <kenneth_suter@localhost>
Date: Mon, 24 Sep 2007 12:15:23 +0000
Subject: [PATCH] Creation of a base DN registry for managing the base DN and naming context to backend maps. Supports a 'test' mode that can be used to test whether registration/deregistration operations will be acceptable.
---
opends/src/server/org/opends/server/core/BackendConfigManager.java | 14
opends/src/server/org/opends/server/core/BaseDnRegistry.java | 516 ++++++++++++++++++++++++++++++
opends/src/server/org/opends/server/backends/BackupBackend.java | 4
opends/tests/unit-tests-testng/src/server/org/opends/server/core/BackendConfigManagerTestCase.java | 2
opends/src/server/org/opends/server/backends/LDIFBackend.java | 4
opends/src/server/org/opends/server/backends/MemoryBackend.java | 4
opends/src/server/org/opends/server/core/DirectoryServer.java | 396 +++--------------------
opends/src/server/org/opends/server/backends/MonitorBackend.java | 4
opends/src/server/org/opends/server/backends/jeb/BackendImpl.java | 8
opends/src/server/org/opends/server/backends/TrustStoreBackend.java | 4
opends/src/server/org/opends/server/extensions/ConfigFileHandler.java | 5
opends/src/server/org/opends/server/replication/server/ReplicationBackend.java | 4
opends/src/server/org/opends/server/backends/SchemaBackend.java | 8
opends/src/server/org/opends/server/backends/task/TaskBackend.java | 4
14 files changed, 602 insertions(+), 375 deletions(-)
diff --git a/opends/src/server/org/opends/server/backends/BackupBackend.java b/opends/src/server/org/opends/server/backends/BackupBackend.java
index 0f7332b..6e22fce 100644
--- a/opends/src/server/org/opends/server/backends/BackupBackend.java
+++ b/opends/src/server/org/opends/server/backends/BackupBackend.java
@@ -213,7 +213,7 @@
// Register the backup base as a private suffix.
try
{
- DirectoryServer.registerBaseDN(backupBaseDN, this, true, false);
+ DirectoryServer.registerBaseDN(backupBaseDN, this, true);
}
catch (Exception e)
{
@@ -247,7 +247,7 @@
try
{
- DirectoryServer.deregisterBaseDN(backupBaseDN, false);
+ DirectoryServer.deregisterBaseDN(backupBaseDN);
}
catch (Exception e)
{
diff --git a/opends/src/server/org/opends/server/backends/LDIFBackend.java b/opends/src/server/org/opends/server/backends/LDIFBackend.java
index 98d81d7..17f9cf3 100644
--- a/opends/src/server/org/opends/server/backends/LDIFBackend.java
+++ b/opends/src/server/org/opends/server/backends/LDIFBackend.java
@@ -170,7 +170,7 @@
{
try
{
- DirectoryServer.registerBaseDN(dn, this, false, false);
+ DirectoryServer.registerBaseDN(dn, this, false);
}
catch (Exception e)
{
@@ -375,7 +375,7 @@
{
try
{
- DirectoryServer.deregisterBaseDN(dn, false);
+ DirectoryServer.deregisterBaseDN(dn);
}
catch (Exception e)
{
diff --git a/opends/src/server/org/opends/server/backends/MemoryBackend.java b/opends/src/server/org/opends/server/backends/MemoryBackend.java
index 4060aac..2541f93 100644
--- a/opends/src/server/org/opends/server/backends/MemoryBackend.java
+++ b/opends/src/server/org/opends/server/backends/MemoryBackend.java
@@ -203,7 +203,7 @@
{
try
{
- DirectoryServer.registerBaseDN(dn, this, false, false);
+ DirectoryServer.registerBaseDN(dn, this, false);
}
catch (Exception e)
{
@@ -243,7 +243,7 @@
{
try
{
- DirectoryServer.deregisterBaseDN(dn, false);
+ DirectoryServer.deregisterBaseDN(dn);
}
catch (Exception e)
{
diff --git a/opends/src/server/org/opends/server/backends/MonitorBackend.java b/opends/src/server/org/opends/server/backends/MonitorBackend.java
index f820978..15678b6 100644
--- a/opends/src/server/org/opends/server/backends/MonitorBackend.java
+++ b/opends/src/server/org/opends/server/backends/MonitorBackend.java
@@ -247,7 +247,7 @@
// Register the monitor base as a private suffix.
try
{
- DirectoryServer.registerBaseDN(baseMonitorDN, this, true, false);
+ DirectoryServer.registerBaseDN(baseMonitorDN, this, true);
}
catch (Exception e)
{
@@ -281,7 +281,7 @@
try
{
- DirectoryServer.deregisterBaseDN(baseMonitorDN, false);
+ DirectoryServer.deregisterBaseDN(baseMonitorDN);
}
catch (Exception e)
{
diff --git a/opends/src/server/org/opends/server/backends/SchemaBackend.java b/opends/src/server/org/opends/server/backends/SchemaBackend.java
index 46ae527..565440e 100644
--- a/opends/src/server/org/opends/server/backends/SchemaBackend.java
+++ b/opends/src/server/org/opends/server/backends/SchemaBackend.java
@@ -366,7 +366,7 @@
{
try
{
- DirectoryServer.registerBaseDN(baseDNs[i], this, true, false);
+ DirectoryServer.registerBaseDN(baseDNs[i], this, true);
}
catch (Exception e)
{
@@ -514,7 +514,7 @@
{
try
{
- DirectoryServer.deregisterBaseDN(baseDN, false);
+ DirectoryServer.deregisterBaseDN(baseDN);
}
catch (Exception e)
{
@@ -5156,7 +5156,7 @@
{
try
{
- DirectoryServer.deregisterBaseDN(dn, false);
+ DirectoryServer.deregisterBaseDN(dn);
messages.add(INFO_SCHEMA_DEREGISTERED_BASE_DN.get(
String.valueOf(dn)));
}
@@ -5179,7 +5179,7 @@
{
try
{
- DirectoryServer.registerBaseDN(dn, this, true, false);
+ DirectoryServer.registerBaseDN(dn, this, true);
messages.add(INFO_SCHEMA_REGISTERED_BASE_DN.get(String.valueOf(dn)));
}
catch (Exception e)
diff --git a/opends/src/server/org/opends/server/backends/TrustStoreBackend.java b/opends/src/server/org/opends/server/backends/TrustStoreBackend.java
index 00f2d5a..4c85335 100644
--- a/opends/src/server/org/opends/server/backends/TrustStoreBackend.java
+++ b/opends/src/server/org/opends/server/backends/TrustStoreBackend.java
@@ -366,7 +366,7 @@
// Register the trust store base as a private suffix.
try
{
- DirectoryServer.registerBaseDN(baseDN, this, true, false);
+ DirectoryServer.registerBaseDN(baseDN, this, true);
}
catch (Exception e)
{
@@ -392,7 +392,7 @@
try
{
- DirectoryServer.deregisterBaseDN(baseDN, false);
+ DirectoryServer.deregisterBaseDN(baseDN);
}
catch (Exception e)
{
diff --git a/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java b/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java
index fc4ee52..0b7bcf7 100644
--- a/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java
+++ b/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java
@@ -340,7 +340,7 @@
{
try
{
- DirectoryServer.registerBaseDN(dn, this, false, false);
+ DirectoryServer.registerBaseDN(dn, this, false);
}
catch (Exception e)
{
@@ -386,7 +386,7 @@
{
try
{
- DirectoryServer.deregisterBaseDN(dn, false);
+ DirectoryServer.deregisterBaseDN(dn);
}
catch (Exception e)
{
@@ -1571,7 +1571,7 @@
if (!found)
{
// The base DN was deleted.
- DirectoryServer.deregisterBaseDN(baseDN, false);
+ DirectoryServer.deregisterBaseDN(baseDN);
EntryContainer ec =
rootContainer.unregisterEntryContainer(baseDN);
ec.delete();
@@ -1588,7 +1588,7 @@
EntryContainer ec =
rootContainer.openEntryContainer(baseDN, null);
rootContainer.registerEntryContainer(baseDN, ec);
- DirectoryServer.registerBaseDN(baseDN, this, false, false);
+ DirectoryServer.registerBaseDN(baseDN, this, false);
}
catch (Exception e)
{
diff --git a/opends/src/server/org/opends/server/backends/task/TaskBackend.java b/opends/src/server/org/opends/server/backends/task/TaskBackend.java
index afe3b7c..6dccc78 100644
--- a/opends/src/server/org/opends/server/backends/task/TaskBackend.java
+++ b/opends/src/server/org/opends/server/backends/task/TaskBackend.java
@@ -255,7 +255,7 @@
// Register the task base as a private suffix.
try
{
- DirectoryServer.registerBaseDN(taskRootDN, this, true, false);
+ DirectoryServer.registerBaseDN(taskRootDN, this, true);
}
catch (Exception e)
{
@@ -318,7 +318,7 @@
try
{
- DirectoryServer.deregisterBaseDN(taskRootDN, false);
+ DirectoryServer.deregisterBaseDN(taskRootDN);
}
catch (Exception e)
{
diff --git a/opends/src/server/org/opends/server/core/BackendConfigManager.java b/opends/src/server/org/opends/server/core/BackendConfigManager.java
index daab51b..2f272e7 100644
--- a/opends/src/server/org/opends/server/core/BackendConfigManager.java
+++ b/opends/src/server/org/opends/server/core/BackendConfigManager.java
@@ -402,11 +402,14 @@
}
}
- for (DN dn : addedDNs)
+ // Copy the directory server's base DN registry and make the
+ // requested changes to see if it complains.
+ BaseDnRegistry reg = DirectoryServer.copyBaseDnRegistry();
+ for (DN dn : removedDNs)
{
try
{
- DirectoryServer.registerBaseDN(dn, backend, false, true);
+ reg.deregisterBaseDN(dn);
}
catch (DirectoryException de)
{
@@ -420,11 +423,11 @@
}
}
- for (DN dn : removedDNs)
+ for (DN dn : addedDNs)
{
try
{
- DirectoryServer.deregisterBaseDN(dn, true);
+ reg.registerBaseDN(dn, backend, false);
}
catch (DirectoryException de)
{
@@ -928,11 +931,12 @@
// Make sure that all of the base DNs are acceptable for use in the server.
+ BaseDnRegistry reg = DirectoryServer.copyBaseDnRegistry();
for (DN baseDN : baseDNs)
{
try
{
- DirectoryServer.registerBaseDN(baseDN, backend, false, true);
+ reg.registerBaseDN(baseDN, backend, false);
}
catch (DirectoryException de)
{
diff --git a/opends/src/server/org/opends/server/core/BaseDnRegistry.java b/opends/src/server/org/opends/server/core/BaseDnRegistry.java
new file mode 100644
index 0000000..8303f09
--- /dev/null
+++ b/opends/src/server/org/opends/server/core/BaseDnRegistry.java
@@ -0,0 +1,516 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.core;
+
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.ResultCode;
+import org.opends.server.api.Backend;
+import static org.opends.server.util.Validator.ensureNotNull;
+import org.opends.messages.Message;
+import static org.opends.messages.CoreMessages.*;
+
+import java.util.TreeMap;
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Map;
+
+/**
+ * Registry for maintaining the set of registered base DN's, assocated
+ * backends and naming context information.
+ */
+public class BaseDnRegistry {
+
+ // The set of base DNs registered with the server.
+ private TreeMap<DN,Backend> baseDNs;
+
+ // The set of private naming contexts registered with the server.
+ private TreeMap<DN,Backend> privateNamingContexts;
+
+ // The set of public naming contexts registered with the server.
+ private TreeMap<DN,Backend> publicNamingContexts;
+
+ // Indicates whether or not this base DN registry is in test mode.
+ // A registry instance that is in test mode will not modify backend
+ // objects referred to in the above maps.
+ private boolean testOnly;
+
+ /**
+ * Registers a base DN with this registry.
+ *
+ * @param baseDN to register
+ * @param backend with which the base DN is assocated
+ * @param isPrivate indicates whether or not this base DN is private
+ * @return list of error messages generated by registering the base DN
+ * that should be logged if the changes to this registry are
+ * committed to the server
+ * @throws DirectoryException if the base DN cannot be registered
+ */
+ public List<Message> registerBaseDN(DN baseDN, Backend backend,
+ boolean isPrivate)
+ throws DirectoryException
+ {
+
+ List<Message> errors = new LinkedList<Message>();
+
+ // Check to see if the base DN is already registered with the server.
+ Backend existingBackend = baseDNs.get(baseDN);
+ if (existingBackend != null)
+ {
+ Message message = ERR_REGISTER_BASEDN_ALREADY_EXISTS.
+ get(String.valueOf(baseDN), backend.getBackendID(),
+ existingBackend.getBackendID());
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+ }
+
+
+ // Check to see if the backend is already registered with the server for
+ // any other base DN(s). The new base DN must not have any hierarchical
+ // relationship with any other base Dns for the same backend.
+ LinkedList<DN> otherBaseDNs = new LinkedList<DN>();
+ for (DN dn : baseDNs.keySet())
+ {
+ Backend b = baseDNs.get(dn);
+ if (b.equals(backend))
+ {
+ otherBaseDNs.add(dn);
+
+ if (baseDN.isAncestorOf(dn) || baseDN.isDescendantOf(dn))
+ {
+ Message message = ERR_REGISTER_BASEDN_HIERARCHY_CONFLICT.
+ get(String.valueOf(baseDN), backend.getBackendID(),
+ String.valueOf(dn));
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
+ message);
+ }
+ }
+ }
+
+
+ // Check to see if the new base DN is subordinate to any other base DN
+ // already defined. If it is, then any other base DN(s) for the same
+ // backend must also be subordinate to the same base DN.
+ Backend superiorBackend = null;
+ DN superiorBaseDN ;
+ DN parentDN = baseDN.getParent();
+ while (parentDN != null)
+ {
+ if (baseDNs.containsKey(parentDN))
+ {
+ superiorBaseDN = parentDN;
+ superiorBackend = baseDNs.get(parentDN);
+
+ for (DN dn : otherBaseDNs)
+ {
+ if (! dn.isDescendantOf(superiorBaseDN))
+ {
+ Message message = ERR_REGISTER_BASEDN_DIFFERENT_PARENT_BASES.
+ get(String.valueOf(baseDN), backend.getBackendID(),
+ String.valueOf(dn));
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
+ message);
+ }
+ }
+
+ break;
+ }
+
+ parentDN = parentDN.getParent();
+ }
+
+ if (superiorBackend == null)
+ {
+ if (backend.getParentBackend() != null)
+ {
+ Message message = ERR_REGISTER_BASEDN_NEW_BASE_NOT_SUBORDINATE.
+ get(String.valueOf(baseDN), backend.getBackendID(),
+ backend.getParentBackend().getBackendID());
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
+ message);
+ }
+ }
+
+
+ // Check to see if the new base DN should be the superior base DN for any
+ // other base DN(s) already defined.
+ LinkedList<Backend> subordinateBackends = new LinkedList<Backend>();
+ LinkedList<DN> subordinateBaseDNs = new LinkedList<DN>();
+ for (DN dn : baseDNs.keySet())
+ {
+ Backend b = baseDNs.get(dn);
+ parentDN = dn.getParent();
+ while (parentDN != null)
+ {
+ if (parentDN.equals(baseDN))
+ {
+ subordinateBaseDNs.add(dn);
+ subordinateBackends.add(b);
+ break;
+ }
+ else if (baseDNs.containsKey(parentDN))
+ {
+ break;
+ }
+
+ parentDN = parentDN.getParent();
+ }
+ }
+
+
+ // If we've gotten here, then the new base DN is acceptable. If we should
+ // actually apply the changes then do so now.
+
+ // Check to see if any of the registered backends already contain an
+ // entry with the DN specified as the base DN. This could happen if
+ // we're creating a new subordinate backend in an existing directory
+ // (e.g., moving the "ou=People,dc=example,dc=com" branch to its own
+ // backend when that data already exists under the "dc=example,dc=com"
+ // backend). This condition shouldn't prevent the new base DN from
+ // being registered, but it's definitely important enough that we let
+ // the administrator know about it and remind them that the existing
+ // backend will need to be reinitialized.
+ if (superiorBackend != null)
+ {
+ if (superiorBackend.entryExists(baseDN))
+ {
+ Message message = WARN_REGISTER_BASEDN_ENTRIES_IN_MULTIPLE_BACKENDS.
+ get(superiorBackend.getBackendID(), String.valueOf(baseDN),
+ backend.getBackendID());
+ errors.add(message);
+ }
+ }
+
+
+ baseDNs.put(baseDN, backend);
+
+ if (superiorBackend == null)
+ {
+ if (isPrivate)
+ {
+ if (!testOnly)
+ {
+ backend.setPrivateBackend(true);
+ }
+ privateNamingContexts.put(baseDN, backend);
+ }
+ else
+ {
+ if (!testOnly)
+ {
+ backend.setPrivateBackend(false);
+ }
+ publicNamingContexts.put(baseDN, backend);
+ }
+ }
+ else if (otherBaseDNs.isEmpty())
+ {
+ if (!testOnly)
+ {
+ backend.setParentBackend(superiorBackend);
+ superiorBackend.addSubordinateBackend(backend);
+ }
+ }
+
+ if (!testOnly)
+ {
+ for (Backend b : subordinateBackends)
+ {
+ Backend oldParentBackend = b.getParentBackend();
+ if (oldParentBackend != null)
+ {
+ oldParentBackend.removeSubordinateBackend(b);
+ }
+
+ b.setParentBackend(backend);
+ backend.addSubordinateBackend(b);
+ }
+ }
+
+ for (DN dn : subordinateBaseDNs)
+ {
+ publicNamingContexts.remove(dn);
+ privateNamingContexts.remove(dn);
+ }
+
+ return errors;
+ }
+
+
+ /**
+ * Deregisters a base DN with this registry.
+ *
+ * @param baseDN to deregister
+ * @return list of error messages generated by deregistering the base DN
+ * that should be logged if the changes to this registry are
+ * committed to the server
+ * @throws DirectoryException if the base DN could not be deregistered
+ */
+ public List<Message> deregisterBaseDN(DN baseDN)
+ throws DirectoryException
+ {
+ LinkedList<Message> errors = new LinkedList<Message>();
+
+ ensureNotNull(baseDN);
+
+ // Make sure that the Directory Server actually contains a backend with
+ // the specified base DN.
+ Backend backend = baseDNs.get(baseDN);
+ if (backend == null)
+ {
+ Message message =
+ ERR_DEREGISTER_BASEDN_NOT_REGISTERED.get(String.valueOf(baseDN));
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
+ }
+
+
+ // Check to see if the backend has a parent backend, and whether it has
+ // any subordinates with base DNs that are below the base DN to remove.
+ Backend superiorBackend = backend.getParentBackend();
+ LinkedList<Backend> subordinateBackends = new LinkedList<Backend>();
+ if (backend.getSubordinateBackends() != null)
+ {
+ for (Backend b : backend.getSubordinateBackends())
+ {
+ for (DN dn : b.getBaseDNs())
+ {
+ if (dn.isDescendantOf(baseDN))
+ {
+ subordinateBackends.add(b);
+ break;
+ }
+ }
+ }
+ }
+
+
+ // See if there are any other base DNs registered within the same backend.
+ LinkedList<DN> otherBaseDNs = new LinkedList<DN>();
+ for (DN dn : baseDNs.keySet())
+ {
+ if (dn.equals(baseDN))
+ {
+ continue;
+ }
+
+ Backend b = baseDNs.get(dn);
+ if (backend.equals(b))
+ {
+ otherBaseDNs.add(dn);
+ }
+ }
+
+
+ // If we've gotten here, then it's OK to make the changes.
+
+ // Get rid of the references to this base DN in the mapping tree
+ // information.
+ baseDNs.remove(baseDN);
+ publicNamingContexts.remove(baseDN);
+ privateNamingContexts.remove(baseDN);
+
+ if (superiorBackend == null)
+ {
+ // If there were any subordinate backends, then all of their base DNs
+ // will now be promoted to naming contexts.
+ for (Backend b : subordinateBackends)
+ {
+ if (!testOnly)
+ {
+ b.setParentBackend(null);
+ backend.removeSubordinateBackend(b);
+ }
+
+ for (DN dn : b.getBaseDNs())
+ {
+ if (b.isPrivateBackend())
+ {
+ privateNamingContexts.put(dn, b);
+ }
+ else
+ {
+ publicNamingContexts.put(dn, b);
+ }
+ }
+ }
+ }
+ else
+ {
+ // If there are no other base DNs for the associated backend, then
+ // remove this backend as a subordinate of the parent backend.
+ if (otherBaseDNs.isEmpty())
+ {
+ if (!testOnly)
+ {
+ superiorBackend.removeSubordinateBackend(backend);
+ }
+ }
+
+
+ // If there are any subordinate backends, then they need to be made
+ // subordinate to the parent backend. Also, we should log a warning
+ // message indicating that there may be inconsistent search results
+ // because some of the structural entries will be missing.
+ if (! subordinateBackends.isEmpty())
+ {
+ Message message = WARN_DEREGISTER_BASEDN_MISSING_HIERARCHY.get(
+ String.valueOf(baseDN), backend.getBackendID());
+ errors.add(message);
+
+ if (!testOnly)
+ {
+ for (Backend b : subordinateBackends)
+ {
+ backend.removeSubordinateBackend(b);
+ superiorBackend.addSubordinateBackend(b);
+ b.setParentBackend(superiorBackend);
+ }
+ }
+ }
+ }
+ return errors;
+ }
+
+
+ /**
+ * Creates a default instance.
+ */
+ BaseDnRegistry()
+ {
+ this(new TreeMap<DN,Backend>(), new TreeMap<DN,Backend>(),
+ new TreeMap<DN,Backend>(), false);
+ }
+
+ /**
+ * Returns a copy of this registry.
+ *
+ * @return copy of this registry
+ */
+ BaseDnRegistry copy()
+ {
+ return new BaseDnRegistry(
+ new TreeMap<DN,Backend>(baseDNs),
+ new TreeMap<DN,Backend>(publicNamingContexts),
+ new TreeMap<DN,Backend>(privateNamingContexts),
+ true);
+ }
+
+
+ /**
+ * Creates a parameterized instance.
+ *
+ * @param baseDNs map
+ * @param publicNamingContexts map
+ * @param privateNamingContexts map
+ * @param testOnly indicates whether this registry will be used for testing;
+ * when <code>true</code> this registry will not modify backends
+ */
+ private BaseDnRegistry(TreeMap<DN, Backend> baseDNs,
+ TreeMap<DN, Backend> publicNamingContexts,
+ TreeMap<DN, Backend> privateNamingContexts,
+ boolean testOnly)
+ {
+ this.baseDNs = baseDNs;
+ this.publicNamingContexts = publicNamingContexts;
+ this.privateNamingContexts = privateNamingContexts;
+ this.testOnly = testOnly;
+ }
+
+
+ /**
+ * Gets the mapping of registered base DNs to their associated backend.
+ *
+ * @return mapping from base DN to backend
+ */
+ Map<DN,Backend> getBaseDnMap() {
+ return this.baseDNs;
+ }
+
+
+ /**
+ * Gets the mapping of registered public naming contexts to their
+ * associated backend.
+ *
+ * @return mapping from naming context to backend
+ */
+ Map<DN,Backend> getPublicNamingContextsMap() {
+ return this.publicNamingContexts;
+ }
+
+
+ /**
+ * Gets the mapping of registered private naming contexts to their
+ * associated backend.
+ *
+ * @return mapping from naming context to backend
+ */
+ Map<DN,Backend> getPrivateNamingContextsMap() {
+ return this.privateNamingContexts;
+ }
+
+
+
+
+ /**
+ * Indicates whether the specified DN is contained in this registry as
+ * a naming contexts.
+ *
+ * @param dn The DN for which to make the determination.
+ *
+ * @return {@code true} if the specified DN is a naming context in this
+ * registry, or {@code false} if it is not.
+ */
+ boolean containsNamingContext(DN dn)
+ {
+ return (privateNamingContexts.containsKey(dn) ||
+ publicNamingContexts.containsKey(dn));
+ }
+
+
+ /**
+ * Clear and nullify this registry's internal state.
+ */
+ void clear() {
+
+ if (baseDNs != null)
+ {
+ baseDNs.clear();
+ }
+
+ if (privateNamingContexts != null)
+ {
+ privateNamingContexts.clear();
+ }
+
+ if (publicNamingContexts != null)
+ {
+ publicNamingContexts.clear();
+ }
+
+ }
+
+}
diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index ab214a2..07e6df6 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -674,14 +674,10 @@
// The thread group for all threads associated with the Directory Server.
private ThreadGroup directoryThreadGroup;
- // The set of base DNs registered with the server.
- private TreeMap<DN,Backend> baseDNs;
- // The set of private naming contexts registered with the server.
- private TreeMap<DN,Backend> privateNamingContexts;
+ // Registry for base DN and naming context information.
+ private BaseDnRegistry baseDnRegistry;
- // The set of public naming contexts registered with the server.
- private TreeMap<DN,Backend> publicNamingContexts;
// The set of backends registered with the server.
private TreeMap<String,Backend> backends;
@@ -895,9 +891,7 @@
new ConcurrentHashMap<String,Long>();
directoryServer.backendInitializationListeners =
new CopyOnWriteArraySet<BackendInitializationListener>();
- directoryServer.baseDNs = new TreeMap<DN,Backend>();
- directoryServer.publicNamingContexts = new TreeMap<DN,Backend>();
- directoryServer.privateNamingContexts = new TreeMap<DN,Backend>();
+ directoryServer.baseDnRegistry = new BaseDnRegistry();
directoryServer.changeNotificationListeners =
new CopyOnWriteArrayList<ChangeNotificationListener>();
directoryServer.persistentSearches =
@@ -6307,7 +6301,7 @@
*/
public static Map<DN,Backend> getBaseDNs()
{
- return directoryServer.baseDNs;
+ return directoryServer.baseDnRegistry.getBaseDnMap();
}
@@ -6323,7 +6317,7 @@
*/
public static Backend getBackendWithBaseDN(DN baseDN)
{
- return directoryServer.baseDNs.get(baseDN);
+ return directoryServer.baseDnRegistry.getBaseDnMap().get(baseDN);
}
@@ -6346,7 +6340,7 @@
return directoryServer.rootDSEBackend;
}
- TreeMap<DN,Backend> baseDNs = directoryServer.baseDNs;
+ Map<DN,Backend> baseDNs = directoryServer.baseDnRegistry.getBaseDnMap();
Backend b = baseDNs.get(entryDN);
while (b == null)
{
@@ -6363,6 +6357,20 @@
}
+ /**
+ * Obtains a copy of the server's base DN registry. The copy can be used
+ * to test registration/deregistration of base DNs but cannot be used to
+ * modify the backends. To modify the server's live base DN to backend
+ * mappings use {@link #registerBaseDN(DN, Backend, boolean)} and
+ * {@link #deregisterBaseDN(DN)}.
+ *
+ * @return copy of the base DN regsitry
+ */
+ public static BaseDnRegistry copyBaseDnRegistry()
+ {
+ return directoryServer.baseDnRegistry.copy();
+ }
+
/**
* Registers the provided base DN with the server.
@@ -6375,209 +6383,37 @@
* private base DN. If the provided base DN is a naming
* context, then this controls whether it is public or
* private.
- * @param testOnly Indicates whether to only test whether the new base DN
- * registration would be successful without actually
- * applying any changes.
*
* @throws DirectoryException If a problem occurs while attempting to
* register the provided base DN.
*/
public static void registerBaseDN(DN baseDN, Backend backend,
- boolean isPrivate, boolean testOnly)
+ boolean isPrivate)
throws DirectoryException
{
ensureNotNull(baseDN, backend);
synchronized (directoryServer)
{
- TreeMap<DN,Backend> newBaseDNs =
- new TreeMap<DN,Backend>(directoryServer.baseDNs);
- TreeMap<DN,Backend> newPublicNamingContexts =
- new TreeMap<DN,Backend>(directoryServer.publicNamingContexts);
- TreeMap<DN,Backend> newPrivateNamingContexts =
- new TreeMap<DN,Backend>(directoryServer.privateNamingContexts);
+ List<Message> warnings =
+ directoryServer.baseDnRegistry.registerBaseDN(
+ baseDN, backend, isPrivate);
-
- // Check to see if the base DN is already registered with the server.
- Backend existingBackend = newBaseDNs.get(baseDN);
- if (existingBackend != null)
- {
- Message message = ERR_REGISTER_BASEDN_ALREADY_EXISTS.
- get(String.valueOf(baseDN), backend.getBackendID(),
- existingBackend.getBackendID());
- throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
- }
-
-
- // Check to see if the backend is already registered with the server for
- // any other base DN(s). The new base DN must not have any hierarchical
- // relationship with any other base Dns for the same backend.
- LinkedList<DN> otherBaseDNs = new LinkedList<DN>();
- for (DN dn : newBaseDNs.keySet())
- {
- Backend b = newBaseDNs.get(dn);
- if (b.equals(backend))
- {
- otherBaseDNs.add(dn);
-
- if (baseDN.isAncestorOf(dn) || baseDN.isDescendantOf(dn))
- {
- Message message = ERR_REGISTER_BASEDN_HIERARCHY_CONFLICT.
- get(String.valueOf(baseDN), backend.getBackendID(),
- String.valueOf(dn));
- throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
- message);
- }
+ // Since we've committed the changes we need to log any issues
+ // that this registration has caused
+ if (warnings != null) {
+ for (Message warning : warnings) {
+ logError(warning);
}
}
-
- // Check to see if the new base DN is subordinate to any other base DN
- // already defined. If it is, then any other base DN(s) for the same
- // backend must also be subordinate to the same base DN.
- Backend superiorBackend = null;
- DN superiorBaseDN = null;
- DN parentDN = baseDN.getParent();
- while (parentDN != null)
+ // Now create a workflow for the registered baseDN and register
+ // the workflow with the network groups, but don't register the
+ // workflow if the backend happens to be the configuration backend
+ // because it's too soon.
+ if (! baseDN.equals(DN.decode("cn=config")))
{
- if (newBaseDNs.containsKey(parentDN))
- {
- superiorBaseDN = parentDN;
- superiorBackend = newBaseDNs.get(parentDN);
-
- for (DN dn : otherBaseDNs)
- {
- if (! dn.isDescendantOf(superiorBaseDN))
- {
- Message message = ERR_REGISTER_BASEDN_DIFFERENT_PARENT_BASES.
- get(String.valueOf(baseDN), backend.getBackendID(),
- String.valueOf(dn));
- throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
- message);
- }
- }
-
- break;
- }
-
- parentDN = parentDN.getParent();
- }
-
- if (superiorBackend == null)
- {
- if (backend.getParentBackend() != null)
- {
- Message message = ERR_REGISTER_BASEDN_NEW_BASE_NOT_SUBORDINATE.
- get(String.valueOf(baseDN), backend.getBackendID(),
- backend.getParentBackend().getBackendID());
- throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
- message);
- }
- }
-
-
- // Check to see if the new base DN should be the superior base DN for any
- // other base DN(s) already defined.
- LinkedList<Backend> subordinateBackends = new LinkedList<Backend>();
- LinkedList<DN> subordinateBaseDNs = new LinkedList<DN>();
- for (DN dn : newBaseDNs.keySet())
- {
- Backend b = newBaseDNs.get(dn);
- parentDN = dn.getParent();
- while (parentDN != null)
- {
- if (parentDN.equals(baseDN))
- {
- subordinateBaseDNs.add(dn);
- subordinateBackends.add(b);
- break;
- }
- else if (newBaseDNs.containsKey(parentDN))
- {
- break;
- }
-
- parentDN = parentDN.getParent();
- }
- }
-
-
- // If we've gotten here, then the new base DN is acceptable. If we should
- // actually apply the changes then do so now.
- if (! testOnly)
- {
- // Check to see if any of the registered backends already contain an
- // entry with the DN specified as the base DN. This could happen if
- // we're creating a new subordinate backend in an existing directory
- // (e.g., moving the "ou=People,dc=example,dc=com" branch to its own
- // backend when that data already exists under the "dc=example,dc=com"
- // backend). This condition shouldn't prevent the new base DN from
- // being registered, but it's definitely important enough that we let
- // the administrator know about it and remind them that the existing
- // backend will need to be reinitialized.
- if (superiorBackend != null)
- {
- if (superiorBackend.entryExists(baseDN))
- {
- Message message = WARN_REGISTER_BASEDN_ENTRIES_IN_MULTIPLE_BACKENDS.
- get(superiorBackend.getBackendID(), String.valueOf(baseDN),
- backend.getBackendID());
- logError(message);
- }
- }
-
-
- newBaseDNs.put(baseDN, backend);
-
- if (superiorBackend == null)
- {
- if (isPrivate)
- {
- backend.setPrivateBackend(true);
- newPrivateNamingContexts.put(baseDN, backend);
- }
- else
- {
- backend.setPrivateBackend(false);
- newPublicNamingContexts.put(baseDN, backend);
- }
- }
- else if (otherBaseDNs.isEmpty())
- {
- backend.setParentBackend(superiorBackend);
- superiorBackend.addSubordinateBackend(backend);
- }
-
- for (Backend b : subordinateBackends)
- {
- Backend oldParentBackend = b.getParentBackend();
- if (oldParentBackend != null)
- {
- oldParentBackend.removeSubordinateBackend(b);
- }
-
- b.setParentBackend(backend);
- backend.addSubordinateBackend(b);
- }
-
- for (DN dn : subordinateBaseDNs)
- {
- newPublicNamingContexts.remove(dn);
- newPrivateNamingContexts.remove(dn);
- }
-
- directoryServer.baseDNs = newBaseDNs;
- directoryServer.publicNamingContexts = newPublicNamingContexts;
- directoryServer.privateNamingContexts = newPrivateNamingContexts;
-
- // Now create a workflow for the registered baseDN and register
- // the workflow with the network groups, but don't register the
- // workflow if the backend happens to be the configuration backend
- // because it's too soon.
- if (! baseDN.equals(DN.decode("cn=config")))
- {
- createAndRegisterWorkflow(baseDN, backend);
- }
+ createAndRegisterWorkflow(baseDN, backend);
}
}
}
@@ -6589,145 +6425,30 @@
*
* @param baseDN The base DN to deregister with the server. It must not
* be {@code null}.
- * @param testOnly Indicates whether to only test whether the new base DN
- * registration would be successful without actually
- * applying any changes.
*
* @throws DirectoryException If a problem occurs while attempting to
* deregister the provided base DN.
*/
- public static void deregisterBaseDN(DN baseDN, boolean testOnly)
+ public static void deregisterBaseDN(DN baseDN)
throws DirectoryException
{
ensureNotNull(baseDN);
- synchronized (directoryServer)
- {
- TreeMap<DN,Backend> newBaseDNs =
- new TreeMap<DN,Backend>(directoryServer.baseDNs);
- TreeMap<DN,Backend> newPublicNamingContexts =
- new TreeMap<DN,Backend>(directoryServer.publicNamingContexts);
- TreeMap<DN,Backend> newPrivateNamingContexts =
- new TreeMap<DN,Backend>(directoryServer.privateNamingContexts);
+ synchronized(directoryServer) {
+ List<Message> warnings =
+ directoryServer.baseDnRegistry.deregisterBaseDN(baseDN);
- // Make sure that the Directory Server actually contains a backend with
- // the specified base DN.
- Backend backend = newBaseDNs.get(baseDN);
- if (backend == null)
- {
- Message message =
- ERR_DEREGISTER_BASEDN_NOT_REGISTERED.get(String.valueOf(baseDN));
- throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
- }
-
-
- // Check to see if the backend has a parent backend, and whether it has
- // any subordinates with base DNs that are below the base DN to remove.
- Backend superiorBackend = backend.getParentBackend();
- LinkedList<Backend> subordinateBackends = new LinkedList<Backend>();
- if (backend.getSubordinateBackends() != null)
- {
- for (Backend b : backend.getSubordinateBackends())
- {
- for (DN dn : b.getBaseDNs())
- {
- if (dn.isDescendantOf(baseDN))
- {
- subordinateBackends.add(b);
- break;
- }
- }
+ // Since we've committed the changes we need to log any issues
+ // that this registration has caused
+ if (warnings != null) {
+ for (Message error : warnings) {
+ logError(error);
}
}
-
- // See if there are any other base DNs registered within the same backend.
- LinkedList<DN> otherBaseDNs = new LinkedList<DN>();
- for (DN dn : newBaseDNs.keySet())
- {
- if (dn.equals(baseDN))
- {
- continue;
- }
-
- Backend b = newBaseDNs.get(dn);
- if (backend.equals(b))
- {
- otherBaseDNs.add(dn);
- }
- }
-
-
- // If we've gotten here, then it's OK to make the changes.
- if (! testOnly)
- {
- // Get rid of the references to this base DN in the mapping tree
- // information.
- newBaseDNs.remove(baseDN);
- newPublicNamingContexts.remove(baseDN);
- newPrivateNamingContexts.remove(baseDN);
-
-
- if (superiorBackend == null)
- {
- // If there were any subordinate backends, then all of their base DNs
- // will now be promoted to naming contexts.
- for (Backend b : subordinateBackends)
- {
- b.setParentBackend(null);
- backend.removeSubordinateBackend(b);
-
- for (DN dn : b.getBaseDNs())
- {
- if (b.isPrivateBackend())
- {
- newPrivateNamingContexts.put(dn, b);
- }
- else
- {
- newPublicNamingContexts.put(dn, b);
- }
- }
- }
- }
- else
- {
- // If there are no other base DNs for the associated backend, then
- // remove this backend as a subordinate of the parent backend.
- if (otherBaseDNs.isEmpty())
- {
- superiorBackend.removeSubordinateBackend(backend);
- }
-
-
- // If there are any subordinate backends, then they need to be made
- // subordinate to the parent backend. Also, we should log a warning
- // message indicating that there may be inconsistent search results
- // because some of the structural entries will be missing.
- if (! subordinateBackends.isEmpty())
- {
- Message message = WARN_DEREGISTER_BASEDN_MISSING_HIERARCHY.get(
- String.valueOf(baseDN), backend.getBackendID());
- logError(message);
-
- for (Backend b : subordinateBackends)
- {
- backend.removeSubordinateBackend(b);
- superiorBackend.addSubordinateBackend(b);
- b.setParentBackend(superiorBackend);
- }
- }
- }
-
-
- directoryServer.baseDNs = newBaseDNs;
- directoryServer.publicNamingContexts = newPublicNamingContexts;
- directoryServer.privateNamingContexts = newPrivateNamingContexts;
-
- // Now deregister the workflow that was associated with the base DN.
- deregisterWorkflow(baseDN);
- }
+ // Now deregister the workflow that was associated with the base DN.
+ deregisterWorkflow(baseDN);
}
}
@@ -6741,7 +6462,7 @@
*/
public static Map<DN,Backend> getPublicNamingContexts()
{
- return directoryServer.publicNamingContexts;
+ return directoryServer.baseDnRegistry.getPublicNamingContextsMap();
}
@@ -6755,7 +6476,7 @@
*/
public static Map<DN,Backend> getPrivateNamingContexts()
{
- return directoryServer.privateNamingContexts;
+ return directoryServer.baseDnRegistry.getPrivateNamingContextsMap();
}
@@ -6771,8 +6492,7 @@
*/
public static boolean isNamingContext(DN dn)
{
- return (directoryServer.publicNamingContexts.containsKey(dn) ||
- directoryServer.privateNamingContexts.containsKey(dn));
+ return directoryServer.baseDnRegistry.containsNamingContext(dn);
}
@@ -8578,22 +8298,10 @@
shutdownHook = null;
workQueue = null;
- if (privateNamingContexts != null)
+ if (baseDnRegistry != null)
{
- privateNamingContexts.clear();
- privateNamingContexts = null;
- }
-
- if (publicNamingContexts != null)
- {
- publicNamingContexts.clear();
- publicNamingContexts = null;
- }
-
- if (baseDNs != null)
- {
- baseDNs.clear();
- baseDNs = null;
+ baseDnRegistry.clear();
+ baseDnRegistry = null;
}
if (backends != null)
diff --git a/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java b/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
index 1a54df8..e1ddbf4 100644
--- a/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
+++ b/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
@@ -735,8 +735,7 @@
// conflict with user backend identifiers.
setBackendID("__config.ldif__");
- DirectoryServer.registerBaseDN(configRootEntry.getDN(), this, true,
- false);
+ DirectoryServer.registerBaseDN(configRootEntry.getDN(), this, true);
}
catch (Exception e)
{
@@ -1026,7 +1025,7 @@
{
try
{
- DirectoryServer.deregisterBaseDN(configRootEntry.getDN(), false);
+ DirectoryServer.deregisterBaseDN(configRootEntry.getDN());
}
catch (Exception e)
{
diff --git a/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java b/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java
index 4b82e06..9f85cda 100644
--- a/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java
+++ b/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java
@@ -232,7 +232,7 @@
{
try
{
- DirectoryServer.registerBaseDN(dn, this, false, false);
+ DirectoryServer.registerBaseDN(dn, this, false);
}
catch (Exception e)
{
@@ -269,7 +269,7 @@
{
try
{
- DirectoryServer.deregisterBaseDN(dn, false);
+ DirectoryServer.deregisterBaseDN(dn);
}
catch (Exception e)
{
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/BackendConfigManagerTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/BackendConfigManagerTestCase.java
index d0e66a5..8a4d599 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/core/BackendConfigManagerTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/core/BackendConfigManagerTestCase.java
@@ -111,7 +111,7 @@
public void testDeregisterNonExistentBaseDN()
throws Exception
{
- DirectoryServer.deregisterBaseDN(DN.decode("o=unregistered"), false);
+ DirectoryServer.deregisterBaseDN(DN.decode("o=unregistered"));
}
--
Gitblit v1.10.0