From ea07941708927aaddb5afeaf7df6a720f137faf1 Mon Sep 17 00:00:00 2001
From: fguigues <fguigues@localhost>
Date: Wed, 25 Feb 2009 13:29:21 +0000
Subject: [PATCH] Fix 3808: hasSubordinates is broken in cn=monitor Fix 3810: Parent DN entry should not be returned when using a child as search base dn
---
opends/src/server/org/opends/server/backends/MonitorBackend.java | 319 +++++++++++++++++++++++++---------------------------
1 files changed, 155 insertions(+), 164 deletions(-)
diff --git a/opends/src/server/org/opends/server/backends/MonitorBackend.java b/opends/src/server/org/opends/server/backends/MonitorBackend.java
index 90658b9..ed41ce6 100644
--- a/opends/src/server/org/opends/server/backends/MonitorBackend.java
+++ b/opends/src/server/org/opends/server/backends/MonitorBackend.java
@@ -22,12 +22,10 @@
* CDDL HEADER END
*
*
- * Copyright 2006-2008 Sun Microsystems, Inc.
+ * Copyright 2006-2009 Sun Microsystems, Inc.
*/
package org.opends.server.backends;
-
-
import static org.opends.messages.BackendMessages.*;
import static org.opends.messages.ConfigMessages.*;
import static org.opends.server.config.ConfigConstants.*;
@@ -41,6 +39,7 @@
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Set;
import org.opends.messages.Message;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.server.ConfigurationChangeListener;
@@ -102,8 +101,6 @@
*/
private static final DebugTracer TRACER = getTracer();
-
-
// The set of user-defined attributes that will be included in the base
// monitor entry.
private ArrayList<Attribute> userDefinedAttributes;
@@ -129,7 +126,10 @@
// The set of supported features for this backend.
private HashSet<String> supportedFeatures;
-
+ // The mapping between entry DNs and the corresponding entries.
+ private LinkedHashMap<DN,Entry> entryMap;
+ // The mapping between parent DNs and their immediate children.
+ private HashMap<DN,HashSet<DN>> childDNs;
/**
* Creates a new backend with the provided information. All backend
@@ -139,8 +139,6 @@
public MonitorBackend()
{
super();
-
- // Perform all initialization in initializeBackend.
}
@@ -248,6 +246,10 @@
// Register with the Directory Server as a configurable component.
currentConfig.addMonitorChangeListener(this);
+ entryMap = new LinkedHashMap<DN,Entry>();
+ childDNs = new HashMap<DN,HashSet<DN>>();
+
+ this.initEntryMaps();
// Register the monitor base as a private suffix.
try
@@ -275,6 +277,8 @@
@Override()
public void finalizeBackend()
{
+ entryMap.clear();
+ childDNs.clear();
currentConfig.removeMonitorChangeListener(this);
try
@@ -336,7 +340,10 @@
@Override()
public long getEntryCount()
{
- return DirectoryServer.getMonitorProviders().size() + 1;
+ if (entryMap != null) {
+ return entryMap.size();
+ }
+ return -1;
}
@@ -387,64 +394,40 @@
}
}
-
-
/**
* {@inheritDoc}
*/
@Override()
public long numSubordinates(DN entryDN, boolean subtree)
- throws DirectoryException
- {
- // If the requested entry was null, then return undefined.
- if (entryDN == null)
+ throws DirectoryException {
+
+ Set<DN> children = childDNs.get(entryDN);
+ if (children == null)
{
+ if(entryMap.get(entryDN) != null)
+ {
+ // The entry does exist but just no children.
+ return 0;
+ }
return -1;
}
-
- // If the requested entry was the monitor base entry, then return
- // the number of monitor providers.
- if (entryDN.equals(baseMonitorDN))
+ if(!subtree)
{
- // This backend is only 1 level deep so the count is the same for
- // subtree and immediate subordinates.
- return DirectoryServer.getMonitorProviders().size();
+ return children.size();
}
-
-
- // See if the monitor base entry is the immediate parent for the requested
- // entry. If not, then its undefined.
- DN parentDN = entryDN.getParentDNInSuffix();
- if ((parentDN == null) || (! parentDN.equals(baseMonitorDN)))
+ else
{
- return -1;
+ long count = 0;
+ for(DN child : children)
+ {
+ count += numSubordinates(child, true);
+ count++;
+ }
+ return count;
}
-
-
- // Get the RDN for the requested DN and make sure it is single-valued.
- RDN entryRDN = entryDN.getRDN();
- if (entryRDN.isMultiValued())
- {
- return -1;
- }
-
-
- // Get the RDN value and see if it matches the instance name for one of
- // the directory server monitor providers.
- String rdnValue = entryRDN.getAttributeValue(0).getValue().toString();
- MonitorProvider<? extends MonitorProviderCfg> monitorProvider =
- DirectoryServer.getMonitorProvider(rdnValue.toLowerCase());
- if (monitorProvider == null)
- {
- return -1;
- }
-
- return 0;
}
-
-
/**
* {@inheritDoc}
*/
@@ -684,8 +667,6 @@
*/
public Entry getBranchMonitorEntry(DN dn) {
- Entry e=null;
- // Construct the set of objectclasses to include in the base monitor entry.
HashMap<ObjectClass,String> monitorClasses =
new LinkedHashMap<ObjectClass,String>(3);
monitorClasses.putAll(monitorObjectClasses);
@@ -693,19 +674,9 @@
true);
monitorClasses.put(monitorOC, OC_MONITOR_BRANCH);
- // Iterate through all of the monitor providers defined in the server.
-
- for (MonitorProvider<? extends MonitorProviderCfg> monitorProvider :
- DirectoryServer.getMonitorProviders().values()) {
-
- DN providerDN = DirectoryServer.getMonitorProviderDN(monitorProvider);
- if (providerDN.isDescendantOf(dn)) {
- // Construct and return the entry.
- e = new Entry(dn, monitorClasses, null, null);
- break;
- }
- }
-
+ // Construct and return the entry.
+ Entry e = new Entry(dn, monitorClasses, null, null);
+ e.processVirtualAttributes();
return e;
}
@@ -774,22 +745,6 @@
- /**
- * Creates an attribute for a monitor entry with the following criteria.
- *
- * @param name The name for the attribute.
- * @param lowerName The name for the attribute formatted in all lowercase
- * characters.
- * @param value The value to use for the attribute.
- *
- * @return The constructed attribute.
- */
- private Attribute createAttribute(String name, String lowerName,
- String value)
- {
- return Attributes.create(name, value);
- }
-
/**
@@ -856,104 +811,100 @@
public void search(SearchOperation searchOperation)
throws DirectoryException
{
- // Get the base entry for the search, if possible. If it doesn't exist,
- // then this will throw an exception.
- DN baseDN = searchOperation.getBaseDN();
- Entry baseEntry = getEntry(baseDN);
- if (baseEntry==null) {
- Message message =
- ERR_MONITOR_NO_SUCH_PROVIDER.get(String.valueOf(baseDN.toString()));
- throw new DirectoryException(
- ResultCode.NO_SUCH_OBJECT, message, baseMonitorDN, null);
-
- }
-
- // Figure out whether the base is the monitor base entry or one of its
- // children for a specific monitor.
+ // Get the base DN, scope, and filter for the search.
+ DN baseDN = searchOperation.getBaseDN();
SearchScope scope = searchOperation.getScope();
SearchFilter filter = searchOperation.getFilter();
- if ((scope == SearchScope.BASE_OBJECT) ||
- (scope == SearchScope.WHOLE_SUBTREE))
+
+
+ // Make sure the base entry exists if it's supposed to be in this backend.
+ this.initEntryMaps();
+ Entry baseEntry = entryMap.get(baseDN);
+ if ((baseEntry == null) && handlesEntry(baseDN))
+ {
+ DN matchedDN = baseDN.getParentDNInSuffix();
+ while (matchedDN != null)
+ {
+ if (entryMap.containsKey(matchedDN))
+ {
+ break;
+ }
+
+ matchedDN = matchedDN.getParentDNInSuffix();
+ }
+
+ Message message =
+ ERR_MEMORYBACKEND_ENTRY_DOESNT_EXIST.get(String.valueOf(baseDN));
+ throw new DirectoryException(
+ ResultCode.NO_SUCH_OBJECT, message, matchedDN, null);
+ }
+
+ if (baseEntry != null)
+ {
+ baseEntry = baseEntry.duplicate(true);
+ }
+
+
+ // If it's a base-level search, then just get that entry and return it if it
+ // matches the filter.
+ if (scope == SearchScope.BASE_OBJECT)
{
if (filter.matchesEntry(baseEntry))
{
searchOperation.returnEntry(baseEntry, null);
}
-
-
- // If it is a base-level search, then we're done.
- if (scope == SearchScope.BASE_OBJECT)
- {
- return;
- }
}
-
- HashSet<DN> branches = new HashSet<DN>();
- // Iterate through all of the monitor providers defined in the server.
- // Get an entry for each and compare it against the filter.
- for (MonitorProvider<? extends MonitorProviderCfg> monitorProvider :
- DirectoryServer.getMonitorProviders().values()) {
-
- DN providerDN = DirectoryServer.getMonitorProviderDN(monitorProvider);
- if (baseDN.isAncestorOf(providerDN)) {
- DN parentDN = providerDN.getParentDNInSuffix();
- while ((parentDN!=null) && (!parentDN.equals(baseMonitorDN)) &&
- (!parentDN.equals(baseDN))) {
- if ((!branches.contains(parentDN)) && (
- isABranch(parentDN))) {
- Entry branchEntry = getBranchMonitorEntry(parentDN);
- if (filter.matchesEntry(branchEntry)) {
- searchOperation.returnEntry(branchEntry, null);
- }
- branches.add(parentDN);
+ else
+ {
+ // Walk through all entries and send the ones that match.
+ for (Entry e : entryMap.values()) {
+ boolean matched = filter.matchesEntry(e);
+ if (matched) {
+ if (e.matchesBaseAndScope(baseDN, scope)==true) {
+ searchOperation.returnEntry(e, null);
}
- parentDN = parentDN.getParentDNInSuffix();
- }
- if (!providerDN.equals(baseDN)) {
- Entry monitorEntry = getMonitorEntry(providerDN, monitorProvider);
- if (filter.matchesEntry(monitorEntry)) {
- searchOperation.returnEntry(monitorEntry, null);
- }
- }
-
+ }
}
}
}
- private boolean isABranch(DN dn) {
- boolean found=false;
+ // Build te internal monitor tree (entries, and children)
+ private void initEntryMaps() {
+ this.entryMap.clear();
+ this.childDNs.clear();
for (MonitorProvider<? extends MonitorProviderCfg> monitorProvider :
DirectoryServer.getMonitorProviders().values()) {
- DN providerDN = DirectoryServer.getMonitorProviderDN(monitorProvider);
- if (dn.equals(providerDN)) {
- found=true;
- }
+ try {
+ DN providerdn =
+ DirectoryServer.getMonitorProviderDN(monitorProvider);
+ if (!entryMap.containsKey(providerdn)) {
+ Entry entry = getEntry(providerdn);
+ entryMap.put(providerdn, entry);
+ }
+ DN parentdn = providerdn.getParentDNInSuffix();
+ DN child = providerdn;
+ while (parentdn!=null) {
+ if (!entryMap.containsKey(parentdn)) {
+ Entry entry = getEntry(parentdn);
+ entryMap.put(parentdn, entry);
+ }
+ if (childDNs.containsKey(parentdn)) {
+ HashSet<DN> children = childDNs.get(parentdn);
+ children.add(child);
+ childDNs.put(parentdn, children);
+ }
+ else {
+ HashSet<DN> children = new HashSet<DN>();
+ children.add(child);
+ childDNs.put(parentdn, children);
+ }
+ child=parentdn;
+ parentdn = parentdn.getParentDNInSuffix();
+ }
+ } catch (Exception ex) {
+ }
}
- return (!found);
- }
-
- private boolean isATreeNode(DN dn) {
- boolean found=false;
-
- if (dn.equals(baseMonitorDN)) {
- return true;
- }
- for (MonitorProvider<? extends MonitorProviderCfg> monitorProvider :
- DirectoryServer.getMonitorProviders().values()) {
- DN providerDN = DirectoryServer.getMonitorProviderDN(monitorProvider);
- if ((dn.isAncestorOf(providerDN)) ||
- (dn.equals(providerDN))) {
- found=true;
- return (found);
- }
- }
- return (found);
- }
-
- private String getRdns(DN dn) {
- int index = dn.toString().lastIndexOf(",");
- return dn.toString().substring(3, index);
}
@@ -1299,4 +1250,44 @@
public void preloadEntryCache() throws UnsupportedOperationException {
throw new UnsupportedOperationException("Operation not supported.");
}
+
+ // Private Methods
+ private boolean isATreeNode(DN dn) {
+ boolean found=false;
+
+ if (dn.equals(baseMonitorDN)) {
+ return true;
+ }
+ for (MonitorProvider<? extends MonitorProviderCfg> monitorProvider :
+ DirectoryServer.getMonitorProviders().values()) {
+ DN providerDN = DirectoryServer.getMonitorProviderDN(monitorProvider);
+ if ((dn.isAncestorOf(providerDN)) ||
+ (dn.equals(providerDN))) {
+ found=true;
+ return (found);
+ }
+ }
+ return (found);
+ }
+
+ private String getRdns(DN dn) {
+ int index = dn.toString().lastIndexOf(",");
+ return dn.toString().substring(3, index);
+ }
+
+ /**
+ * Creates an attribute for a monitor entry with the following criteria.
+ *
+ * @param name The name for the attribute.
+ * @param lowerName The name for the attribute formatted in all lowercase
+ * characters.
+ * @param value The value to use for the attribute.
+ *
+ * @return The constructed attribute.
+ */
+ private Attribute createAttribute(String name, String lowerName,
+ String value) {
+ return Attributes.create(name, value);
+ }
+
}
--
Gitblit v1.10.0