From 5be072c20e46f0921bb00401ff26d0defb3e8991 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Tue, 05 Dec 2006 21:41:50 +0000
Subject: [PATCH] Update the base DN registration process to address a number of issues:
---
opends/src/server/org/opends/server/core/DirectoryServer.java | 710 +++++++++++++++++++++++++++++++++++++---------------------
1 files changed, 448 insertions(+), 262 deletions(-)
diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index e255767..e113da4 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -34,8 +34,11 @@
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -161,6 +164,7 @@
import static org.opends.server.util.DynamicConstants.*;
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
+import static org.opends.server.util.Validator.*;
@@ -398,19 +402,6 @@
// The key manager provider configuration manager for the Directory Server.
private KeyManagerProviderConfigManager keyManagerProviderConfigManager;
- // The set of "private" suffixes that will be used to provide server-generated
- // data (e.g., monitor information, schema, etc.) to clients but will not be
- // searchable by default.
- private LinkedHashMap<DN,Backend> privateSuffixes;
-
- // The set of backends that have been registered with the server (mapped
- // between the normalized suffix and the backend).
- private LinkedHashMap<DN,Backend> suffixes;
-
- // The set of backends that have been registered with the server (mapped
- // between their backend ID and the backend).
- private LinkedHashMap<String,Backend> backends;
-
// The set of connections that are currently established.
private LinkedHashSet<ClientConnection> establishedConnections;
@@ -498,6 +489,18 @@
// 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;
+
+ // 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;
+
// The set of supported controls registered with the Directory Server.
private TreeSet<String> supportedControls;
@@ -606,9 +609,10 @@
directoryServer.defaultPasswordPolicy = null;
directoryServer.monitorProviders =
new ConcurrentHashMap<String,MonitorProvider>();
- directoryServer.privateSuffixes = new LinkedHashMap<DN,Backend>();
- directoryServer.suffixes = new LinkedHashMap<DN,Backend>();
- directoryServer.backends = new LinkedHashMap<String,Backend>();
+ directoryServer.backends = new TreeMap<String,Backend>();
+ directoryServer.baseDNs = new TreeMap<DN,Backend>();
+ directoryServer.publicNamingContexts = new TreeMap<DN,Backend>();
+ directoryServer.privateNamingContexts = new TreeMap<DN,Backend>();
directoryServer.changeNotificationListeners =
new CopyOnWriteArrayList<ChangeNotificationListener>();
directoryServer.persistentSearches =
@@ -5210,12 +5214,12 @@
/**
* Retrieves the set of backends that have been registered with the Directory
- * Server.
+ * Server, as a mapping between the backend ID and the corresponding backend.
*
* @return The set of backends that have been registered with the Directory
* Server.
*/
- public static LinkedHashMap<String,Backend> getBackends()
+ public static Map<String,Backend> getBackends()
{
assert debugEnter(CLASS_NAME, "getBackends");
@@ -5229,7 +5233,7 @@
*
* @param backendID The backend ID of the backend to retrieve.
*
- * @return The backend with the specified backend ID, or <CODE>null</CODE> if
+ * @return The backend with the specified backend ID, or {@code null} if
* there is none.
*/
public static Backend getBackend(String backendID)
@@ -5247,8 +5251,8 @@
*
* @param backendID The backend ID for which to make the determination.
*
- * @return <CODE>true</CODE> if the Directory Server has a backend with the
- * specified backend ID, or <CODE>false</CODE> if not.
+ * @return {@code true} if the Directory Server has a backend with the
+ * specified backend ID, or {@code false} if not.
*/
public static boolean hasBackend(String backendID)
{
@@ -5264,13 +5268,40 @@
* will not register the set of configured suffixes with the server, as that
* must be done by the backend itself.
*
- * @param backend The backend to register with the server.
+ * @param backend The backend to register with the server. Neither the
+ * backend nor its backend ID may be null.
+ *
+ * @throws DirectoryException If the backend ID for the provided backend
+ * conflicts with the backend ID of an existing
+ * backend.
*/
public static void registerBackend(Backend backend)
+ throws DirectoryException
{
assert debugEnter(CLASS_NAME, "registerBackend", String.valueOf(backend));
- directoryServer.backends.put(backend.getBackendID(), backend);
+ ensureNotNull(backend);
+
+ String backendID = backend.getBackendID();
+ ensureNotNull(backendID);
+
+ synchronized (directoryServer)
+ {
+ TreeMap<String,Backend> newBackends =
+ new TreeMap<String,Backend>(directoryServer.backends);
+ if (newBackends.containsKey(backendID))
+ {
+ int msgID = MSGID_REGISTER_BACKEND_ALREADY_EXISTS;
+ String message = getMessage(msgID, backendID);
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message,
+ msgID);
+ }
+ else
+ {
+ newBackends.put(backendID, backend);
+ directoryServer.backends = newBackends;
+ }
+ }
}
@@ -5280,370 +5311,525 @@
* will not deregister the set of configured suffixes with the server, as that
* must be done by the backend itself.
*
- * @param backend the backend to deregister with the server.
+ * @param backend The backend to deregister with the server. It must not be
+ * {@code null}.
*/
public static void deregisterBackend(Backend backend)
{
assert debugEnter(CLASS_NAME, "deregisterBackend", String.valueOf(backend));
- directoryServer.backends.remove(backend.getBackendID());
+ ensureNotNull(backend);
+
+ synchronized (directoryServer)
+ {
+ TreeMap<String,Backend> newBackends =
+ new TreeMap<String,Backend>(directoryServer.backends);
+ newBackends.remove(backend.getBackendID());
+
+ directoryServer.backends = newBackends;
+ }
}
/**
- * Retrieves the set of suffixes that have been registered with the Directory
- * Server.
+ * Retrieves the entire set of base DNs registered with the Directory Server,
+ * mapped from the base DN to the backend responsible for that base DN. The
+ * same backend may be present multiple times, mapped from different base DNs.
*
- * @return The set of suffixes that have been registered with the Directory
- * Server.
+ * @return The entire set of base DNs registered with the Directory Server.
*/
- public static LinkedHashMap<DN,Backend> getSuffixes()
+ public static Map<DN,Backend> getBaseDNs()
{
- assert debugEnter(CLASS_NAME, "getSuffixes");
+ assert debugEnter(CLASS_NAME, "getBaseDNs");
- return directoryServer.suffixes;
+ return directoryServer.baseDNs;
}
/**
- * Retrieves the set of "private" suffixes that have been registered with the
- * server that will provide server-specific data to clients (e.g., monitor
- * data, schema, etc.) but should not be considered for normal operations
- * that may target all "user" suffixes.
+ * Retrieves the backend with the specified base DN.
*
- * @return The set of "private" suffixes that have been registered with the
- * server.
+ * @param baseDN The DN that is registered as one of the base DNs for the
+ * backend to retrieve.
+ *
+ * @return The backend with the specified base DN, or {@code null} if there
+ * is no backend registered with the specified base DN.
*/
- public static LinkedHashMap<DN,Backend> getPrivateSuffixes()
+ public static Backend getBackendWithBaseDN(DN baseDN)
{
- assert debugEnter(CLASS_NAME, "getPrivateSuffixes");
+ assert debugEnter(CLASS_NAME, "getBackendWithBaseDN",
+ String.valueOf(baseDN));
- return directoryServer.privateSuffixes;
+ return directoryServer.baseDNs.get(baseDN);
}
/**
- * Indicates whether the provided DN is one of the suffixes defined in the
- * Directory Server.
+ * Retrieves the backend that should be used to handle operations on the
+ * specified entry.
*
- * @param dn The DN for which to make the determination.
+ * @param entryDN The DN of the entry for which to retrieve the
+ * corresponding backend.
*
- * @return <CODE>true</CODE> if the provided DN is one of the suffixes
- * defined in the Directory Server, or <CODE>false</CODE> if not.
+ * @return The backend that should be used to handle operations on the
+ * specified entry, or {@code null} if no appropriate backend is
+ * registered with the server.
*/
- public static boolean isSuffix(DN dn)
+ public static Backend getBackend(DN entryDN)
{
- assert debugEnter(CLASS_NAME, "isSuffix", String.valueOf(dn));
+ assert debugEnter(CLASS_NAME, "getBackendForEntry",
+ String.valueOf(entryDN));
- return (directoryServer.suffixes.containsKey(dn) ||
- directoryServer.privateSuffixes.containsKey(dn));
- }
-
-
-
- /**
- * Retrieves the backend that should be used to handle operations for the
- * provided entry DN.
- *
- * @param dn The DN of the entry for which to retrieve the appropriate
- * backend.
- *
- * @return The backend that should be used to handle the provided DN, or
- * <CODE>null</CODE> if there is no backend for the provided DN.
- */
- public static Backend getBackend(DN dn)
- {
- assert debugEnter(CLASS_NAME, "getBackend", String.valueOf(dn));
-
- if (dn.isNullDN())
+ if (entryDN.isNullDN())
{
return directoryServer.rootDSEBackend;
}
- Backend backend = directoryServer.suffixes.get(dn);
- if (backend == null)
+ TreeMap<DN,Backend> baseDNs = directoryServer.baseDNs;
+ Backend b = baseDNs.get(entryDN);
+ while (b == null)
{
- backend = directoryServer.privateSuffixes.get(dn);
- }
-
- while (backend == null)
- {
- dn = dn.getParentDNInSuffix();
- if (dn == null)
+ entryDN = entryDN.getParent();
+ if (entryDN == null)
{
- break;
+ return null;
}
- backend = directoryServer.suffixes.get(dn);
- if (backend == null)
- {
- backend = directoryServer.privateSuffixes.get(dn);
- }
+ b = baseDNs.get(entryDN);
}
- return backend;
+ return b;
}
/**
- * Registers the specified suffix to be handled by the provided backend.
+ * Registers the provided base DN with the server.
*
- * @param suffixDN The base DN for this suffix.
- * @param backend The backend to handle operations for the provided base.
+ * @param baseDN The base DN to register with the server. It must not be
+ * {@code null}.
+ * @param backend The backend responsible for the provided base DN. It
+ * must not be {@code null}.
+ * @param isPrivate Indicates whether the base DN should be considered a
+ * 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 ConfigException If the specified suffix is already registered
- * with the Directory Server.
+ * @throws DirectoryException If a problem occurs while attempting to
+ * register the provided base DN.
*/
- public static void registerSuffix(DN suffixDN, Backend backend)
- throws ConfigException
+ public static void registerBaseDN(DN baseDN, Backend backend,
+ boolean isPrivate, boolean testOnly)
+ throws DirectoryException
{
- assert debugEnter(CLASS_NAME, "registerSuffix", String.valueOf(suffixDN),
- String.valueOf(backend));
+ assert debugEnter(CLASS_NAME, "registerBaseDN", String.valueOf(baseDN),
+ String.valueOf(backend), String.valueOf(isPrivate),
+ String.valueOf(testOnly));
- backend.setPrivateBackend(false);
+ ensureNotNull(baseDN, backend);
- synchronized (directoryServer.suffixes)
+ synchronized (directoryServer)
{
- // Check to see if this suffix is already in use. It may be a suffix, or
- // it may be a sub-suffix of an existing suffix.
- Backend b = directoryServer.suffixes.get(suffixDN);
- if (b != null)
- {
- int msgID = MSGID_CANNOT_REGISTER_DUPLICATE_SUFFIX;
- String message = getMessage(msgID, String.valueOf(suffixDN),
- b.getClass().getName());
+ 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);
- throw new ConfigException(msgID, message);
+
+ // Check to see if the base DN is already registered with the server.
+ Backend existingBackend = newBaseDNs.get(baseDN);
+ if (existingBackend != null)
+ {
+ int msgID = MSGID_REGISTER_BASEDN_ALREADY_EXISTS;
+ String message = getMessage(msgID, String.valueOf(baseDN),
+ backend.getBackendID(),
+ existingBackend.getBackendID());
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message,
+ msgID);
}
- boolean found = false;
- DN parentDN = suffixDN.getParentDNInSuffix();
+
+ // 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))
+ {
+ int msgID = MSGID_REGISTER_BASEDN_HIERARCHY_CONFLICT;
+ String message = getMessage(msgID, String.valueOf(baseDN),
+ backend.getBackendID(),
+ String.valueOf(dn));
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
+ message, msgID);
+ }
+ }
+ }
+
+
+ // 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)
{
- b = directoryServer.suffixes.get(suffixDN);
- if (b != null)
+ if (newBaseDNs.containsKey(parentDN))
{
- if (b.hasSubSuffix(suffixDN))
+ superiorBaseDN = parentDN;
+ superiorBackend = newBaseDNs.get(parentDN);
+
+ for (DN dn : otherBaseDNs)
{
- int msgID = MSGID_CANNOT_REGISTER_DUPLICATE_SUBSUFFIX;
- String message = getMessage(msgID, String.valueOf(suffixDN),
- String.valueOf(parentDN));
-
- throw new ConfigException(msgID, message);
+ if (! dn.isDescendantOf(superiorBaseDN))
+ {
+ int msgID = MSGID_REGISTER_BASEDN_DIFFERENT_PARENT_BASES;
+ String message = getMessage(msgID, String.valueOf(baseDN),
+ backend.getBackendID(),
+ String.valueOf(dn));
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
+ message, msgID);
+ }
}
- else
- {
- b.addSubordinateBackend(backend);
- found = true;
- break;
- }
+
+ break;
}
- parentDN = parentDN.getParentDNInSuffix();
+ parentDN = parentDN.getParent();
}
-
- if (! found)
+ if (superiorBackend == null)
{
- // If we've gotten here, then it is not in use. Register it.
- directoryServer.suffixes.put(suffixDN, backend);
- }
-
-
- // See if there are any supported controls or features that we want to
- // advertise.
- Set<String> supportedControls = backend.getSupportedControls();
- if (supportedControls != null)
- {
- for (String controlOID : supportedControls)
+ if (backend.getParentBackend() != null)
{
- registerSupportedControl(controlOID);
+ int msgID = MSGID_REGISTER_BASEDN_NEW_BASE_NOT_SUBORDINATE;
+ String message = getMessage(msgID, String.valueOf(baseDN),
+ backend.getBackendID(),
+ backend.getParentBackend().getBackendID());
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
+ message, msgID);
}
}
- Set<String> supportedFeatures = backend.getSupportedFeatures();
- if (supportedFeatures != null)
+
+ // 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())
{
- for (String featureOID : supportedFeatures)
- {
- registerSupportedFeature(featureOID);
- }
- }
- }
- }
-
-
-
- /**
- * Registers the specified private suffix to be handled by the provided
- * backend.
- *
- * @param suffixDN The base DN for this suffix.
- * @param backend The backend to handle operations for the provided base.
- *
- * @throws ConfigException If the specified suffix is already registered
- * with the Directory Server.
- */
- public static void registerPrivateSuffix(DN suffixDN, Backend backend)
- throws ConfigException
- {
- assert debugEnter(CLASS_NAME, "registerPrivateSuffix",
- String.valueOf(suffixDN), String.valueOf(backend));
-
- backend.setPrivateBackend(true);
-
- synchronized (directoryServer.privateSuffixes)
- {
- // Check to see if this suffix is already in use for a "user" suffix. It
- // may be a suffix, or it may be a sub-suffix of an existing suffix.
- synchronized (directoryServer.suffixes)
- {
- Backend b = directoryServer.suffixes.get(suffixDN);
- if (b != null)
- {
- int msgID = MSGID_CANNOT_REGISTER_DUPLICATE_SUFFIX;
- String message = getMessage(msgID, String.valueOf(suffixDN),
- b.getClass().getName());
-
- throw new ConfigException(msgID, message);
- }
-
- DN parentDN = suffixDN.getParentDNInSuffix();
+ Backend b = newBaseDNs.get(dn);
+ parentDN = dn.getParent();
while (parentDN != null)
{
- b = directoryServer.suffixes.get(suffixDN);
- if (b != null)
+ if (parentDN.equals(baseDN))
{
- int msgID = MSGID_CANNOT_REGISTER_PRIVATE_SUFFIX_BELOW_USER_PARENT;
- String message = getMessage(msgID, String.valueOf(suffixDN),
- String.valueOf(parentDN));
- throw new ConfigException(msgID, message);
+ subordinateBaseDNs.add(dn);
+ subordinateBackends.add(b);
+ break;
+ }
+ else if (newBaseDNs.containsKey(parentDN))
+ {
+ break;
}
- parentDN = suffixDN.getParentDNInSuffix();
+ parentDN = parentDN.getParent();
}
}
- // Check to see if this suffix is already registered as a private suffix
- // or sub-suffix.
- Backend b = directoryServer.privateSuffixes.get(suffixDN);
- if (b != null)
+ // 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)
{
- int msgID = MSGID_CANNOT_REGISTER_DUPLICATE_SUFFIX;
- String message = getMessage(msgID, String.valueOf(suffixDN),
- b.getClass().getName());
-
- throw new ConfigException(msgID, message);
- }
-
- DN parentDN = suffixDN.getParentDNInSuffix();
- while (parentDN != null)
- {
- b = directoryServer.privateSuffixes.get(suffixDN);
- if (b != null)
+ // 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 (b.hasSubSuffix(suffixDN))
+ if (superiorBackend.entryExists(baseDN))
{
- int msgID = MSGID_CANNOT_REGISTER_DUPLICATE_SUBSUFFIX;
- String message = getMessage(msgID, String.valueOf(suffixDN),
- String.valueOf(parentDN));
+ int msgID = MSGID_REGISTER_BASEDN_ENTRIES_IN_MULTIPLE_BACKENDS;
+ String message = getMessage(msgID, superiorBackend.getBackendID(),
+ String.valueOf(baseDN),
+ backend.getBackendID());
+ logError(ErrorLogCategory.CONFIGURATION,
+ ErrorLogSeverity.SEVERE_WARNING, message, msgID);
+ }
+ }
- throw new ConfigException(msgID, message);
+
+ newBaseDNs.put(baseDN, backend);
+
+ if (superiorBackend == null)
+ {
+ if (isPrivate)
+ {
+ backend.setPrivateBackend(true);
+ newPrivateNamingContexts.put(baseDN, backend);
}
else
{
- b.addSubordinateBackend(backend);
- return;
+ backend.setPrivateBackend(false);
+ newPublicNamingContexts.put(baseDN, backend);
}
}
+ else if (otherBaseDNs.isEmpty())
+ {
+ backend.setParentBackend(superiorBackend);
+ superiorBackend.addSubordinateBackend(backend);
+ }
- parentDN = suffixDN.getParentDNInSuffix();
+ 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;
}
-
-
- // If we've gotten here, then it is not in use. Register it.
- directoryServer.privateSuffixes.put(suffixDN, backend);
}
}
/**
- * Deregisters the specified suffix with the Directory Server. This should
- * work regardless of whether the specified DN is a normal suffix or a private
- * suffix.
+ * Deregisters the provided base DN with the server.
*
- * @param suffixDN The suffix DN to deregister with the server.
+ * @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 ConfigException If a problem occurs while attempting to
- * deregister the specified suffix.
+ * @throws DirectoryException If a problem occurs while attempting to
+ * deregister the provided base DN.
*/
- public static void deregisterSuffix(DN suffixDN)
- throws ConfigException
+ public static void deregisterBaseDN(DN baseDN, boolean testOnly)
+ throws DirectoryException
{
- assert debugEnter(CLASS_NAME, "deregisterSuffix", String.valueOf(suffixDN));
+ assert debugEnter(CLASS_NAME, "deregisterBaseDN", String.valueOf(baseDN));
+ ensureNotNull(baseDN);
- // First, check to see if it is a "user" suffix or sub-suffix.
- synchronized (directoryServer.suffixes)
+ synchronized (directoryServer)
{
- Backend b = directoryServer.suffixes.remove(suffixDN);
- if (b != null)
+ 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);
+
+
+ // Make sure that the Directory Server actually contains a backend with
+ // the specified base DN.
+ Backend backend = newBaseDNs.get(baseDN);
+ if (backend == null)
{
- return;
+ int msgID = MSGID_DEREGISTER_BASEDN_NOT_REGISTERED;
+ String message = getMessage(msgID, String.valueOf(baseDN));
+ throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message,
+ msgID);
}
- DN parentDN = suffixDN.getParentDNInSuffix();
- while (parentDN != null)
- {
- b = directoryServer.suffixes.get(parentDN);
- if (b != null)
- {
- if (b.hasSubSuffix(suffixDN))
- {
- b.removeSubSuffix(suffixDN, parentDN);
- }
- return;
+ // 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;
+ }
+ }
}
}
- }
- // Check the set of private suffixes and sub-suffixes.
- synchronized (directoryServer.privateSuffixes)
- {
- Backend b = directoryServer.privateSuffixes.remove(suffixDN);
- if (b != null)
+ // See if there are any other base DNs registered within the same backend.
+ LinkedList<DN> otherBaseDNs = new LinkedList<DN>();
+ for (DN dn : newBaseDNs.keySet())
{
- return;
- }
-
- DN parentDN = suffixDN.getParentDNInSuffix();
- while (parentDN != null)
- {
- b = directoryServer.privateSuffixes.get(parentDN);
- if (b != null)
+ if (dn.equals(baseDN))
{
- if (b.hasSubSuffix(suffixDN))
- {
- b.removeSubSuffix(suffixDN, parentDN);
- }
+ continue;
+ }
- return;
+ 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())
+ {
+ int msgID = MSGID_DEREGISTER_BASEDN_MISSING_HIERARCHY;
+ String message = getMessage(msgID, String.valueOf(baseDN),
+ backend.getBackendID());
+ logError(ErrorLogCategory.CONFIGURATION,
+ ErrorLogSeverity.SEVERE_WARNING, message, msgID);
+
+ for (Backend b : subordinateBackends)
+ {
+ backend.removeSubordinateBackend(b);
+ superiorBackend.addSubordinateBackend(b);
+ b.setParentBackend(superiorBackend);
+ }
+ }
+ }
+
+
+ directoryServer.baseDNs = newBaseDNs;
+ directoryServer.publicNamingContexts = newPublicNamingContexts;
+ directoryServer.privateNamingContexts = newPrivateNamingContexts;
+ }
}
}
/**
+ * Retrieves the set of public naming contexts defined in the Directory
+ * Server, mapped from the naming context DN to the corresponding backend.
+ *
+ * @return The set of public naming contexts defined in the Directory Server.
+ */
+ public static Map<DN,Backend> getPublicNamingContexts()
+ {
+ assert debugEnter(CLASS_NAME, "getPublicNamingContexts");
+
+ return directoryServer.publicNamingContexts;
+ }
+
+
+
+ /**
+ * Retrieves the set of private naming contexts defined in the Directory
+ * Server, mapped from the naming context DN to the corresponding backend.
+ *
+ * @return The set of private naming contexts defined in the Directory
+ * Server.
+ */
+ public static Map<DN,Backend> getPrivateNamingContexts()
+ {
+ assert debugEnter(CLASS_NAME, "getPrivateNamingContexts");
+
+ return directoryServer.privateNamingContexts;
+ }
+
+
+
+ /**
+ * Indicates whether the specified DN is one of the Directory Server naming
+ * contexts.
+ *
+ * @param dn The DN for which to make the determination.
+ *
+ * @return {@code true} if the specified DN is a naming context for the
+ * Directory Server, or {@code false} if it is not.
+ */
+ public static boolean isNamingContext(DN dn)
+ {
+ assert debugEnter(CLASS_NAME, "isNamingContext");
+
+ return (directoryServer.publicNamingContexts.containsKey(dn) ||
+ directoryServer.privateNamingContexts.containsKey(dn));
+ }
+
+
+
+ /**
* Retrieves the root DSE entry for the Directory Server.
*
* @return The root DSE entry for the Directory Server.
--
Gitblit v1.10.0