From 6bc9517c206b0b8d7cfec7ea4abb7f9dfad535ac Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Tue, 23 Oct 2007 21:16:19 +0000
Subject: [PATCH] Fix for issue 2505 (Provide monitoring information about the number of entries on a given base DN)

---
 opends/resource/schema/02-config.ldif                                           |    6 +
 opends/src/server/org/opends/server/monitors/BackendMonitor.java                |   54 +++++++++++++
 opends/src/guitools/org/opends/guitools/statuspanel/ConfigFromFile.java         |    2 
 opends/src/guitools/org/opends/guitools/statuspanel/ConfigFromLDAP.java         |   62 ++++++++++++++
 opends/src/guitools/org/opends/guitools/statuspanel/BaseDNDescriptor.java       |   24 +++++
 opends/src/guitools/org/opends/guitools/statuspanel/ui/DatabasesTableModel.java |   22 +----
 opends/src/messages/messages/admin_tool.properties                              |    1 
 opends/src/ads/org/opends/admin/ads/ServerDescriptor.java                       |   57 +++++++------
 opends/src/server/org/opends/server/util/ServerConstants.java                   |    6 +
 9 files changed, 180 insertions(+), 54 deletions(-)

diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index e83ca56..2a0ebe5 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -2128,6 +2128,11 @@
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
   SINGLE-VALUE
   X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.434
+  NAME 'ds-base-dn-entry-count'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+  SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
   NAME 'ds-cfg-access-control-handler'
   SUP top
@@ -2900,6 +2905,7 @@
   MAY ( ds-backend-id $
         ds-backend-base-dn $
         ds-backend-entry-count $
+        ds-base-dn-entry-count $
         ds-backend-writability-mode $
         ds-backend-is-private )
   X-ORIGIN 'OpenDS Directory Server' )
diff --git a/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java b/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
index 361b086..c8890e7 100644
--- a/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
+++ b/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
@@ -681,7 +681,7 @@
       {
         Set<String> baseDns = getValues(sr, "ds-cfg-base-dn");
 
-        int nEntries = getEntryCount(ctx, id);
+        Set<String> entries = getBaseDNEntryCount(ctx, id);
 
         Set<ReplicaDescriptor> replicas = desc.getReplicas();
         for (String baseDn : baseDns)
@@ -695,15 +695,28 @@
           r.add(replica);
           suffix.setReplicas(r);
           replica.setSuffix(suffix);
-          if (baseDns.size() == 1)
+          int nEntries = -1;
+          for (String s : entries)
           {
-            replica.setEntries(nEntries);
+            int index = s.indexOf(" ");
+            if (index != -1)
+            {
+              String dn = s.substring(index + 1);
+              if (Utils.areDnsEqual(baseDn, dn))
+              {
+                try
+                {
+                  nEntries = Integer.parseInt(s.substring(0, index));
+                }
+                catch (Throwable t)
+                {
+                  /* Ignore */
+                }
+                break;
+              }
+            }
           }
-          else
-          {
-            /* Cannot know how many entries correspond to this replica */
-            replica.setEntries(-1);
-          }
+          replica.setEntries(nEntries);
         }
         desc.setReplicas(replicas);
       }
@@ -1031,23 +1044,22 @@
   }
 
   /**
-   * Returns the number of entries in a given backend using the provided
-   * InitialLdapContext.
+   * Returns the values of the ds-base-dn-entry count attributes for the given
+   * backend monitor entry using the provided InitialLdapContext.
    * @param ctx the InitialLdapContext to use to update the configuration.
    * @param backendID the id of the backend.
-   * @return the number of entries in the backend.
+   * @return the values of the ds-base-dn-entry count attribute.
    * @throws NamingException if there was an error.
    */
-  private static int getEntryCount(InitialLdapContext ctx, String backendID)
-  throws NamingException
+  private static Set<String> getBaseDNEntryCount(InitialLdapContext ctx,
+      String backendID) throws NamingException
   {
-    int nEntries = -1;
-    String v = null;
+    LinkedHashSet<String> v = new LinkedHashSet<String>();
     SearchControls ctls = new SearchControls();
     ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
     ctls.setReturningAttributes(
         new String[] {
-            "ds-backend-entry-count"
+            "ds-base-dn-entry-count"
         });
     String filter = "(ds-backend-id="+backendID+")";
 
@@ -1058,18 +1070,9 @@
     {
       SearchResult sr = (SearchResult)listeners.next();
 
-      v = getFirstValue(sr, "ds-backend-entry-count");
+      v.addAll(getValues(sr, "ds-base-dn-entry-count"));
     }
-    try
-    {
-      nEntries = Integer.parseInt(v);
-    }
-    catch (Exception ex)
-    {
-      /* ignore */
-    }
-    return nEntries;
-
+    return v;
   }
 
   /*
diff --git a/opends/src/guitools/org/opends/guitools/statuspanel/BaseDNDescriptor.java b/opends/src/guitools/org/opends/guitools/statuspanel/BaseDNDescriptor.java
index bf58266..5ae217b 100644
--- a/opends/src/guitools/org/opends/guitools/statuspanel/BaseDNDescriptor.java
+++ b/opends/src/guitools/org/opends/guitools/statuspanel/BaseDNDescriptor.java
@@ -56,6 +56,7 @@
     REPLICATED
   };
 
+  private int nEntries;
   private int missingChanges;
   private DatabaseDescriptor db;
   private int ageOfOldestMissingChange;
@@ -71,15 +72,17 @@
    * @param type the type of replication.
    * @param baseDn the base DN associated with the Replication.
    * @param db the database containing this base DN.
+   * @param nEntries the number of entries for the base DN.
    * @param ageOfOldestMissingChange the number of missing changes.
    * @param missingChanges the number of missing changes.
    */
   public BaseDNDescriptor(Type type, String baseDn, DatabaseDescriptor db,
-      int ageOfOldestMissingChange, int missingChanges)
+      int nEntries, int ageOfOldestMissingChange, int missingChanges)
   {
     this.baseDn = baseDn;
     this.db = db;
     this.type = type;
+    this.nEntries = nEntries;
     this.ageOfOldestMissingChange = ageOfOldestMissingChange;
     this.missingChanges = missingChanges;
     try
@@ -130,7 +133,7 @@
         (getMissingChanges() == desc.getMissingChanges()) &&
         getDatabase().getBackendID().equals(
             desc.getDatabase().getBackendID()) &&
-        (getDatabase().getEntries() == desc.getDatabase().getEntries());
+        (getEntries() == desc.getEntries());
       }
     }
     else
@@ -162,6 +165,14 @@
     return returnValue;
   }
 
+  /**
+   * Returns the number of entries in the database for this base DN.
+   * @return the number of entries in the database for this base DN.
+   */
+  public int getEntries()
+  {
+    return nEntries;
+  }
 
   /**
    * Returns the number of missing changes in the replication topology for
@@ -221,6 +232,15 @@
     this.db = db;
   }
 
+  /**
+   * Sets the number of entries for this base DN in this database.
+   * @param nEntries the number of entries.
+   */
+  void setEntries(int nEntries)
+  {
+    this.nEntries = nEntries;
+  }
+
   private String unescapeUtf8(String v) throws UnsupportedEncodingException
   {
     byte[] stringBytes = v.getBytes("UTF-8");
diff --git a/opends/src/guitools/org/opends/guitools/statuspanel/ConfigFromFile.java b/opends/src/guitools/org/opends/guitools/statuspanel/ConfigFromFile.java
index f3d1ce0..5986cb7 100644
--- a/opends/src/guitools/org/opends/guitools/statuspanel/ConfigFromFile.java
+++ b/opends/src/guitools/org/opends/guitools/statuspanel/ConfigFromFile.java
@@ -730,6 +730,6 @@
   private BaseDNDescriptor getBaseDNDescriptor(Entry entry, String baseDn)
   {
     return new BaseDNDescriptor(BaseDNDescriptor.Type.NOT_REPLICATED,
-        baseDn, null, -1, -1);
+        baseDn, null, -1, -1, -1);
   }
 }
diff --git a/opends/src/guitools/org/opends/guitools/statuspanel/ConfigFromLDAP.java b/opends/src/guitools/org/opends/guitools/statuspanel/ConfigFromLDAP.java
index cbd8327..b764c95 100644
--- a/opends/src/guitools/org/opends/guitools/statuspanel/ConfigFromLDAP.java
+++ b/opends/src/guitools/org/opends/guitools/statuspanel/ConfigFromLDAP.java
@@ -29,6 +29,7 @@
 
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.Set;
 import java.util.TreeSet;
 
@@ -43,6 +44,7 @@
 import javax.naming.ldap.LdapName;
 
 import org.opends.admin.ads.util.ApplicationTrustManager;
+import org.opends.admin.ads.util.ConnectionUtils;
 import org.opends.quicksetup.util.Utils;
 
 import org.opends.messages.Message;
@@ -798,8 +800,8 @@
       type = BaseDNDescriptor.Type.NOT_REPLICATED;
     }
 
-    return new BaseDNDescriptor(type, baseDn, null, ageOfOldestMissingChange,
-      missingChanges);
+    return new BaseDNDescriptor(type, baseDn, null, -1,
+        ageOfOldestMissingChange, missingChanges);
   }
 
   /**
@@ -932,13 +934,35 @@
       Set<String> baseDns = getValues(entry, "ds-cfg-base-dn");
       TreeSet<BaseDNDescriptor> replicas = new TreeSet<BaseDNDescriptor>();
       int nEntries = getEntryCount(ctx, id);
-
+      Set<String> baseDnEntries = getBaseDNEntryCount(ctx, id);
       DatabaseDescriptor db = new DatabaseDescriptor(id, replicas, nEntries);
 
       for (String baseDn : baseDns)
       {
         BaseDNDescriptor rep = getBaseDNDescriptor(ctx, baseDn);
         rep.setDatabase(db);
+        nEntries = -1;
+        for (String s : baseDnEntries)
+        {
+          int index = s.indexOf(" ");
+          if (index != -1)
+          {
+            String dn = s.substring(index +1);
+            if (Utils.areDnsEqual(baseDn, dn))
+            {
+              try
+              {
+                nEntries = Integer.parseInt(s.substring(0, index));
+              }
+              catch (Throwable t)
+              {
+                /* Ignore */
+              }
+              break;
+            }
+          }
+        }
+        rep.setEntries(nEntries);
         db.getBaseDns().add(rep);
       }
 
@@ -1019,4 +1043,36 @@
   {
     return ConfigFromFile.isConfigBackend(id);
   }
+
+  /**
+   * Returns the values of the ds-base-dn-entry count attributes for the given
+   * backend monitor entry using the provided InitialLdapContext.
+   * @param ctx the InitialLdapContext to use to update the configuration.
+   * @param backendID the id of the backend.
+   * @return the values of the ds-base-dn-entry count attribute.
+   * @throws NamingException if there was an error.
+   */
+  private static Set<String> getBaseDNEntryCount(InitialLdapContext ctx,
+      String backendID) throws NamingException
+  {
+    LinkedHashSet<String> v = new LinkedHashSet<String>();
+    SearchControls ctls = new SearchControls();
+    ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
+    ctls.setReturningAttributes(
+        new String[] {
+            "ds-base-dn-entry-count"
+        });
+    String filter = "(ds-backend-id="+backendID+")";
+
+    LdapName jndiName = new LdapName("cn=monitor");
+    NamingEnumeration listeners = ctx.search(jndiName, filter, ctls);
+
+    while(listeners.hasMore())
+    {
+      SearchResult sr = (SearchResult)listeners.next();
+
+      v.addAll(ConnectionUtils.getValues(sr, "ds-base-dn-entry-count"));
+    }
+    return v;
+  }
 }
diff --git a/opends/src/guitools/org/opends/guitools/statuspanel/ui/DatabasesTableModel.java b/opends/src/guitools/org/opends/guitools/statuspanel/ui/DatabasesTableModel.java
index c028965..35b5372 100644
--- a/opends/src/guitools/org/opends/guitools/statuspanel/ui/DatabasesTableModel.java
+++ b/opends/src/guitools/org/opends/guitools/statuspanel/ui/DatabasesTableModel.java
@@ -413,8 +413,8 @@
 
   private int compareEntries(BaseDNDescriptor desc1, BaseDNDescriptor desc2)
   {
-    int n1 = desc1.getDatabase().getEntries();
-    int n2 = desc2.getDatabase().getEntries();
+    int n1 = desc1.getEntries();
+    int n2 = desc2.getEntries();
     return compareIntegers(n1, n2);
   }
 
@@ -458,27 +458,13 @@
 
   /**
    * Returns the Object describing the number of entries of a given Base DN.
-   * The Object will be an Integer unless the database of the Base DN contains
-   * several Base DNs.  In this case we return a String.
+   * The Object will be an Integer.
    * @param rep the Base DN object to handle.
    * @return the Object describing the number of entries of a given Base DN.
    */
   private Object getValueForEntries(BaseDNDescriptor rep)
   {
-    Object v;
-    int nEntries = rep.getDatabase().getEntries();
-    if ((rep.getDatabase().getBaseDns().size() > 1) &&
-      (nEntries >= 0))
-    {
-      v = INFO_NUMBER_ENTRIES_MULTIPLE_SUFFIXES_IN_DB.get(
-              String.valueOf(nEntries),
-              rep.getDatabase().getBackendID());
-    }
-    else
-    {
-      v = new Integer(nEntries);
-    }
-    return v;
+    return rep.getEntries();
   }
 
   /**
diff --git a/opends/src/messages/messages/admin_tool.properties b/opends/src/messages/messages/admin_tool.properties
index 9989a29..16621a8 100644
--- a/opends/src/messages/messages/admin_tool.properties
+++ b/opends/src/messages/messages/admin_tool.properties
@@ -257,7 +257,6 @@
 INFO_NOTHING_SELECTED_TO_UNINSTALL=You must select something to be \
  uninstalled.
 INFO_NUMBER_ENTRIES_COLUMN=Entries
-INFO_NUMBER_ENTRIES_MULTIPLE_SUFFIXES_IN_DB=%s (for all base DNs in %s)
 INFO_OPENDS_VERSION_LABEL=OpenDS Version:
 INFO_PROGRESS_REMOVING_REFERENCES=Removing references on %s
 INFO_PROTOCOL_COLUMN=Protocol
diff --git a/opends/src/server/org/opends/server/monitors/BackendMonitor.java b/opends/src/server/org/opends/server/monitors/BackendMonitor.java
index 293f7b7..1df1d69 100644
--- a/opends/src/server/org/opends/server/monitors/BackendMonitor.java
+++ b/opends/src/server/org/opends/server/monitors/BackendMonitor.java
@@ -35,15 +35,19 @@
 import org.opends.server.admin.std.server.MonitorProviderCfg;
 import org.opends.server.api.Backend;
 import org.opends.server.api.MonitorProvider;
+import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.schema.BooleanSyntax;
 import org.opends.server.types.Attribute;
 import org.opends.server.types.AttributeType;
 import org.opends.server.types.AttributeValue;
 import org.opends.server.types.ByteStringFactory;
+import org.opends.server.types.DebugLogLevel;
 import org.opends.server.types.DirectoryConfig;
 import org.opends.server.types.DN;
 import org.opends.server.types.ObjectClass;
 
+import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
+import static org.opends.server.loggers.debug.DebugLogger.getTracer;
 import static org.opends.server.util.ServerConstants.*;
 
 
@@ -65,6 +69,10 @@
   // The attribute type that will be used to report the number of entries.
   private AttributeType entryCountType;
 
+  // The attribute type that will be used to report the number of entries per
+  // base DN.
+  private AttributeType baseDNEntryCountType;
+
   // The attribute type that will be used to indicate if a backend is private.
   private AttributeType isPrivateType;
 
@@ -77,7 +85,10 @@
   // The name for this monitor.
   private String monitorName;
 
-
+  /**
+   * The tracer object for the debug logger.
+   */
+  private static final DebugTracer TRACER = getTracer();
 
   /**
    * Creates a new instance of this backend monitor provider that will work with
@@ -113,6 +124,10 @@
          DirectoryConfig.getAttributeType(ATTR_MONITOR_BACKEND_ENTRY_COUNT,
                                           true);
 
+    baseDNEntryCountType =
+         DirectoryConfig.getAttributeType(ATTR_MONITOR_BASE_DN_ENTRY_COUNT,
+                                          true);
+
     isPrivateType =
          DirectoryConfig.getAttributeType(ATTR_MONITOR_BACKEND_IS_PRIVATE,
                                           true);
@@ -196,12 +211,47 @@
                             values));
 
     values = new LinkedHashSet<AttributeValue>();
+    long backendCount = backend.getEntryCount();
     values.add(new AttributeValue(entryCountType,
-         ByteStringFactory.create(String.valueOf(backend.getEntryCount()))));
+         ByteStringFactory.create(String.valueOf(backendCount))));
     attrs.add(new Attribute(entryCountType, ATTR_MONITOR_BACKEND_ENTRY_COUNT,
                             values));
 
     values = new LinkedHashSet<AttributeValue>();
+    if (baseDNs.length != 1)
+    {
+      for (DN dn : baseDNs)
+      {
+        long entryCount = -1;
+        try
+        {
+          entryCount = backend.numSubordinates(dn, true) + 1;
+        }
+        catch (Exception ex)
+        {
+          if (debugEnabled())
+          {
+            TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+          }
+        }
+        String s = entryCount + " " + dn.toString();
+        values.add(new AttributeValue(baseDNEntryCountType,
+            ByteStringFactory.create(s)));
+      }
+    }
+    else
+    {
+      // This is done to avoid recalculating the number of entries using the
+      // hasNumSubordinates method in the case where the backend has a single
+      // base DN.
+      String s = backendCount + " " + baseDNs[0].toString();
+      values.add(new AttributeValue(baseDNEntryCountType,
+          ByteStringFactory.create(s)));
+    }
+    attrs.add(new Attribute(baseDNEntryCountType,
+        ATTR_MONITOR_BASE_DN_ENTRY_COUNT, values));
+
+    values = new LinkedHashSet<AttributeValue>();
     values.add(new AttributeValue(writabilityModeType,
          ByteStringFactory.create(
               String.valueOf(backend.getWritabilityMode()))));
diff --git a/opends/src/server/org/opends/server/util/ServerConstants.java b/opends/src/server/org/opends/server/util/ServerConstants.java
index d91894a..55ac28e 100644
--- a/opends/src/server/org/opends/server/util/ServerConstants.java
+++ b/opends/src/server/org/opends/server/util/ServerConstants.java
@@ -255,6 +255,12 @@
        "ds-backend-entry-count";
 
 
+  /**
+   * The name of the monitor attribute that is used to hold the base DN entry
+   * count.
+   */
+  public static final String ATTR_MONITOR_BASE_DN_ENTRY_COUNT =
+       "ds-base-dn-entry-count";
 
   /**
    * The name of the monitor attribute that is used to hold the backend

--
Gitblit v1.10.0