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) { 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) { 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) { 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) { 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) 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) { 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) { 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) { 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) { opends/src/server/org/opends/server/core/BaseDnRegistry.java
New file @@ -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(); } } } 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,200 +6383,29 @@ * 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) { 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 @@ -6580,7 +6417,6 @@ } } } } @@ -6589,147 +6425,32 @@ * * @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); } } } @@ -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) 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) { 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) { 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")); }