From 90997a88f290bc77d77a7690d2adeadc3e91fdc1 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Mon, 07 Jan 2008 19:45:19 +0000
Subject: [PATCH] Fix issue 2462: NPE when changing index configuration while import ongoing
---
opends/src/server/org/opends/server/admin/server/ConfigChangeListenerAdaptor.java | 121 +++++++++++++++++------
/dev/null | 149 -----------------------------
opends/src/server/org/opends/server/admin/server/ServerManagedObject.java | 3
opends/src/server/org/opends/server/backends/jeb/EntryContainer.java | 23 +++-
4 files changed, 108 insertions(+), 188 deletions(-)
diff --git a/opends/src/server/org/opends/server/admin/server/CleanerConfigDeleteListener.java b/opends/src/server/org/opends/server/admin/server/CleanerConfigDeleteListener.java
deleted file mode 100644
index 5fe1092..0000000
--- a/opends/src/server/org/opends/server/admin/server/CleanerConfigDeleteListener.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.admin.server;
-import org.opends.messages.Message;
-
-
-
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.loggers.ErrorLogger.*;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.opends.server.api.ConfigChangeListener;
-import org.opends.server.api.ConfigDeleteListener;
-import org.opends.server.config.ConfigEntry;
-import org.opends.server.config.ConfigException;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.loggers.debug.DebugTracer;
-import org.opends.messages.AdminMessages;
-import org.opends.messages.MessageBuilder;
-import org.opends.server.types.ConfigChangeResult;
-import org.opends.server.types.DN;
-import org.opends.server.types.DebugLogLevel;
-import org.opends.server.types.ResultCode;
-import org.opends.server.util.StaticUtils;
-
-
-
-/**
- * A configuration delete listener which detects when a specified
- * entry is removed and, when it is, cleans up any listeners
- * associated with it.
- */
-final class CleanerConfigDeleteListener implements ConfigDeleteListener {
-
- /**
- * The tracer object for the debug logger.
- */
- private static final DebugTracer TRACER = getTracer();
-
- // The change listeners.
- private Map<DN, ConfigChangeListener> changeListeners =
- new HashMap<DN, ConfigChangeListener>();
-
- // The DN of the monitored configuration entry.
- private final DN dn;
-
-
-
- /**
- * Creates a new cleaner configuration change listener which will
- * remove any registered listeners when then configuration entry it
- * is monitoring is removed.
- *
- * @param dn
- * The DN of the entry to be monitored.
- */
- public CleanerConfigDeleteListener(DN dn) {
- this.dn = dn;
- }
-
-
-
- /**
- * Register a configuration change listener for removal when the
- * monitored entry is removed.
- *
- * @param dn
- * The name of the entry associated with the configuration
- * change listener.
- * @param listener
- * The configuration change listener.
- */
- public void addConfigChangeListener(DN dn, ConfigChangeListener listener) {
- changeListeners.put(dn, listener);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry) {
- // Remove the listeners if the deleted entry is the monitored
- // entry.
- if (configEntry.getDN().equals(dn)) {
- for (Map.Entry<DN, ConfigChangeListener> me :
- changeListeners.entrySet()) {
- ConfigEntry listenerConfigEntry = getConfigEntry(me.getKey());
- if (listenerConfigEntry != null) {
- listenerConfigEntry.deregisterChangeListener(me.getValue());
- }
- }
-
- // Now remove this listener as we are no longer needed.
- ConfigEntry parentConfigEntry = getConfigEntry(dn.getParent());
- if (parentConfigEntry != null) {
- parentConfigEntry.deregisterDeleteListener(this);
- }
- }
-
- return new ConfigChangeResult(ResultCode.SUCCESS, false);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public boolean configDeleteIsAcceptable(ConfigEntry configEntry,
- MessageBuilder unacceptableReason) {
- // Always acceptable.
- return true;
- }
-
-
-
- // Returns the named configuration entry or null if it could not be
- // retrieved.
- private ConfigEntry getConfigEntry(DN dn) {
- try {
- ConfigEntry configEntry = DirectoryServer.getConfigEntry(dn);
- if (configEntry != null) {
- return configEntry;
- } else {
- Message message = AdminMessages.ERR_ADMIN_MANAGED_OBJECT_DOES_NOT_EXIST.
- get(String.valueOf(dn));
- logError(message);
- }
- } catch (ConfigException e) {
- // The dependent entry could not be retrieved.
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- Message message = AdminMessages.ERR_ADMIN_CANNOT_GET_MANAGED_OBJECT.get(
- String.valueOf(dn), StaticUtils.getExceptionMessage(e));
- logError(message);
- }
-
- return null;
- }
-}
diff --git a/opends/src/server/org/opends/server/admin/server/ConfigChangeListenerAdaptor.java b/opends/src/server/org/opends/server/admin/server/ConfigChangeListenerAdaptor.java
index c4e4848..d5aee62 100644
--- a/opends/src/server/org/opends/server/admin/server/ConfigChangeListenerAdaptor.java
+++ b/opends/src/server/org/opends/server/admin/server/ConfigChangeListenerAdaptor.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2007 Sun Microsystems, Inc.
+ * Portions Copyright 2007-2008 Sun Microsystems, Inc.
*/
package org.opends.server.admin.server;
@@ -54,6 +54,7 @@
import org.opends.server.admin.RelativeInheritedDefaultBehaviorProvider;
import org.opends.server.admin.UndefinedDefaultBehaviorProvider;
import org.opends.server.api.ConfigChangeListener;
+import org.opends.server.api.ConfigDeleteListener;
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
@@ -202,12 +203,16 @@
// Cached managed object between accept/apply call-backs.
private ServerManagedObject<? extends S> cachedManagedObject;
+ // The delete listener which is used to remove this listener and any
+ // dependencies.
+ private final ConfigDeleteListener cleanerListener;
+
// The names of entries that this change listener depends on.
private final Set<DN> dependencies;
// The listener used to notify this listener when dependency entries
// are modified.
- private final DependencyConfigChangeListener dependencyListener;
+ private final ConfigChangeListener dependencyListener;
// The DN associated with this listener.
private final DN dn;
@@ -239,14 +244,43 @@
// are modified. Determine the dependencies and register change
// listeners against them.
this.dependencies = new HashSet<DN>();
- this.dependencyListener = new DependencyConfigChangeListener(dn, this);
+ this.dependencyListener = new ConfigChangeListener() {
+
+ public ConfigChangeResult applyConfigurationChange(
+ ConfigEntry configEntry) {
+ ConfigEntry dependentConfigEntry = getConfigEntry(dn);
+ if (dependentConfigEntry != null) {
+ return ConfigChangeListenerAdaptor.this
+ .applyConfigurationChange(dependentConfigEntry);
+ } else {
+ // The dependent entry was not found.
+ configEntry.deregisterChangeListener(this);
+ return new ConfigChangeResult(ResultCode.SUCCESS, false);
+ }
+ }
+
+
+
+ public boolean configChangeIsAcceptable(ConfigEntry configEntry,
+ MessageBuilder unacceptableReason) {
+ ConfigEntry dependentConfigEntry = getConfigEntry(dn);
+ if (dependentConfigEntry != null) {
+ return ConfigChangeListenerAdaptor.this.configChangeIsAcceptable(
+ dependentConfigEntry, unacceptableReason, configEntry);
+ } else {
+ // The dependent entry was not found.
+ configEntry.deregisterChangeListener(this);
+ return true;
+ }
+ }
+
+ };
AbstractManagedObjectDefinition<?, ?> d = path.getManagedObjectDefinition();
for (PropertyDefinition<?> pd : d.getAllPropertyDefinitions()) {
Visitor.find(path, pd, dependencies);
}
- CleanerConfigDeleteListener cleaner = new CleanerConfigDeleteListener(dn);
for (DN entryDN : dependencies) {
// Be careful not to register listeners against the dependent
// entry itself.
@@ -254,22 +288,40 @@
ConfigEntry configEntry = getConfigEntry(entryDN);
if (configEntry != null) {
configEntry.registerChangeListener(dependencyListener);
- cleaner.addConfigChangeListener(entryDN, dependencyListener);
}
}
}
- // Register a delete listener which will remove the dependency
- // listeners when this entry is removed.
+ // Register a delete listener against the parent which will
+ // finalize this change listener when the monitored configuration
+ // entry is removed.
+ this.cleanerListener = new ConfigDeleteListener() {
- // FIXME: we should really remove the dependency listeners when
- // this listener is deregistered, but we have no way to track
- // that.
+ public ConfigChangeResult applyConfigurationDelete(
+ ConfigEntry configEntry) {
+ // Perform finalization if the deleted entry is the monitored
+ // entry.
+ if (configEntry.getDN().equals(dn)) {
+ finalizeChangeListener();
+ }
+ return new ConfigChangeResult(ResultCode.SUCCESS, false);
+ }
+
+
+
+ public boolean configDeleteIsAcceptable(ConfigEntry configEntry,
+ MessageBuilder unacceptableReason) {
+ // Always acceptable.
+ return true;
+ }
+
+ };
+
DN parent = dn.getParent();
if (parent != null) {
ConfigEntry configEntry = getConfigEntry(dn.getParent());
if (configEntry != null) {
- configEntry.registerDeleteListener(cleaner);
+ configEntry.registerDeleteListener(cleanerListener);
}
}
}
@@ -280,28 +332,7 @@
* {@inheritDoc}
*/
public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry) {
- return applyConfigurationChange(configEntry, configEntry);
- }
-
-
-
- /**
- * Attempts to apply a new configuration to this Directory Server
- * component based on the provided changed entry.
- *
- * @param configEntry
- * The configuration entry that containing the updated
- * configuration for this component.
- * @param newConfigEntry
- * The configuration entry that caused the notification
- * (will be different from <code>configEntry</code> if a
- * dependency was modified).
- * @return Information about the result of processing the
- * configuration change.
- */
- public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry,
- ConfigEntry newConfigEntry) {
- // TODO: looking at the ConfigFileHandler implementation reveals
+ // Looking at the ConfigFileHandler implementation reveals
// that this ConfigEntry will actually be a different object to
// the one passed in the previous call-back (it will have the same
// content though). This configuration entry has the correct
@@ -396,6 +427,30 @@
/**
+ * Finalizes this configuration change listener adaptor. This method
+ * must be called before this change listener is removed.
+ */
+ public void finalizeChangeListener() {
+ // Remove the dependency listeners.
+ for (DN dependency : dependencies) {
+ ConfigEntry listenerConfigEntry = getConfigEntry(dependency);
+ if (listenerConfigEntry != null) {
+ listenerConfigEntry.deregisterChangeListener(dependencyListener);
+ }
+ }
+
+ // Now remove the cleaner listener as it will no longer be
+ // needed.
+ ConfigEntry parentConfigEntry = getConfigEntry(dn.getParent());
+ if (parentConfigEntry != null) {
+ parentConfigEntry.deregisterDeleteListener(cleanerListener);
+ }
+
+ }
+
+
+
+ /**
* Get the configuration change listener associated with this
* adaptor.
*
diff --git a/opends/src/server/org/opends/server/admin/server/DependencyConfigChangeListener.java b/opends/src/server/org/opends/server/admin/server/DependencyConfigChangeListener.java
deleted file mode 100644
index 588193e..0000000
--- a/opends/src/server/org/opends/server/admin/server/DependencyConfigChangeListener.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.admin.server;
-
-
-
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import static org.opends.server.loggers.ErrorLogger.*;
-import org.opends.server.api.ConfigChangeListener;
-import org.opends.server.config.ConfigEntry;
-import org.opends.server.config.ConfigException;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.loggers.debug.DebugTracer;
-import org.opends.messages.AdminMessages;
-import org.opends.messages.MessageBuilder;
-import org.opends.messages.Message;
-
-import org.opends.server.types.ConfigChangeResult;
-import org.opends.server.types.DN;
-import org.opends.server.types.DebugLogLevel;
-import org.opends.server.types.ResultCode;
-import org.opends.server.util.StaticUtils;
-
-
-
-/**
- * A configuration change listener which can be used to notify a
- * change listener when modifications are made to configuration
- * entries that it depends upon.
- */
-final class DependencyConfigChangeListener implements ConfigChangeListener {
-
- /**
- * The tracer object for the debug logger.
- */
- private static final DebugTracer TRACER = getTracer();
-
- // The DN of the dependent configuration entry.
- private final DN dependentDN;
-
- // The dependent configuration change listener adaptor.
- private final ConfigChangeListenerAdaptor<?> dependentListener;
-
-
-
- /**
- * Creates a new dependency configuration change listener which will
- * notify the dependent listener whenever the configuration entry
- * that this listener monitors is modified.
- *
- * @param dependentDN
- * The DN of the dependent configuration entry.
- * @param dependentListener
- * The dependent configuration change listener adaptor.
- */
- public DependencyConfigChangeListener(DN dependentDN,
- ConfigChangeListenerAdaptor<?> dependentListener) {
- this.dependentDN = dependentDN;
- this.dependentListener = dependentListener;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry) {
- ConfigEntry dependentConfigEntry = getConfigEntry(dependentDN);
- if (dependentConfigEntry != null) {
- return dependentListener.applyConfigurationChange(dependentConfigEntry,
- configEntry);
- } else {
- // The dependent entry was not found.
- configEntry.deregisterChangeListener(this);
- return new ConfigChangeResult(ResultCode.SUCCESS, false);
- }
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public boolean configChangeIsAcceptable(ConfigEntry configEntry,
- MessageBuilder unacceptableReason) {
- ConfigEntry dependentConfigEntry = getConfigEntry(dependentDN);
- if (dependentConfigEntry != null) {
- return dependentListener.configChangeIsAcceptable(dependentConfigEntry,
- unacceptableReason, configEntry);
- } else {
- // The dependent entry was not found.
- configEntry.deregisterChangeListener(this);
- return true;
- }
- }
-
-
-
- // Returns the named configuration entry or null if it could not be
- // retrieved.
- private ConfigEntry getConfigEntry(DN dn) {
- try {
- ConfigEntry configEntry = DirectoryServer.getConfigEntry(dn);
- if (configEntry != null) {
- return configEntry;
- } else {
- Message message = AdminMessages.ERR_ADMIN_MANAGED_OBJECT_DOES_NOT_EXIST.
- get(String.valueOf(dn));
- logError(message);
- }
- } catch (ConfigException e) {
- // The dependent entry could not be retrieved.
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- Message message = AdminMessages.ERR_ADMIN_CANNOT_GET_MANAGED_OBJECT.get(
- String.valueOf(dn), StaticUtils.getExceptionMessage(e));
- logError(message);
- }
-
- return null;
- }
-
-}
diff --git a/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java b/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java
index 89103c6..2b970a4 100644
--- a/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java
+++ b/opends/src/server/org/opends/server/admin/server/ServerManagedObject.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2008 Sun Microsystems, Inc.
*/
package org.opends.server.admin.server;
@@ -185,6 +185,7 @@
ConfigChangeListenerAdaptor<?> adaptor =
(ConfigChangeListenerAdaptor<?>) l;
if (adaptor.getConfigurationChangeListener() == listener) {
+ adaptor.finalizeChangeListener();
configEntry.deregisterChangeListener(adaptor);
}
}
diff --git a/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java b/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
index 75143ae..9bc6038 100644
--- a/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
+++ b/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2008 Sun Microsystems, Inc.
*/
package org.opends.server.backends.jeb;
import org.opends.messages.Message;
@@ -551,11 +551,24 @@
public void close()
throws DatabaseException
{
- List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>();
- listDatabases(databases);
- for(DatabaseContainer db : databases)
+ // Close core indexes.
+ dn2id.close();
+ id2entry.close();
+ dn2uri.close();
+ id2children.close();
+ id2subtree.close();
+ state.close();
+
+ // Close attribute indexes and deregister any listeners.
+ for (AttributeIndex index : attrIndexMap.values())
{
- db.close();
+ index.close();
+ }
+
+ // Close VLV indexes and deregister any listeners.
+ for (VLVIndex vlvIndex : vlvIndexMap.values())
+ {
+ vlvIndex.close();
}
config.removeLocalDBChangeListener(this);
--
Gitblit v1.10.0