mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

fguigues
12.13.2008 d90a8f4889fdc359bfe5f089b937b303a4d58973
* Ability to create monitor provider with hierarchical naming
* Modification of Network Monitor provider names (includes hierarchical naming)
* Provide basic Monitoring objects.
* Add monitoring instrumentation for the connection handlers.
* Add the ability to do a subtree search in the monitor backend.

14 files modified
662 ■■■■ changed files
opends/resource/schema/02-config.ldif 6 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/ConnectionHandler.java 9 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/backends/MonitorBackend.java 205 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/DirectoryServer.java 7 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/networkgroups/NetworkGroup.java 3 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/core/networkgroups/NetworkGroupStatistics.java 10 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/monitors/ClientConnectionMonitorProvider.java 72 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/monitors/ConnectionHandlerMonitor.java 11 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/internal/InternalConnectionHandler.java 14 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java 127 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java 4 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/protocols/ldap/LDAPStatistics.java 175 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/util/ServerConstants.java 11 ●●●●● patch | view | raw | blame | history
opends/tests/unit-tests-testng/src/server/org/opends/server/monitors/InternalSearchMonitorTestCase.java 8 ●●●● patch | view | raw | blame | history
opends/resource/schema/02-config.ldif
@@ -3968,3 +3968,9 @@
        ds-cfg-allowed-subtrees $
        ds-cfg-prohibited-subtrees )
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.950
  NAME 'ds-mon-branch'
  SUP top
  STRUCTURAL
  MUST cn
  X-ORIGIN 'OpenDS Directory Server' )
opends/src/server/org/opends/server/api/ConnectionHandler.java
@@ -35,6 +35,7 @@
import org.opends.server.admin.std.server.*;
import org.opends.server.config.ConfigException;
import org.opends.server.monitors.ConnectionHandlerMonitor;
import org.opends.server.types.DN;
import org.opends.server.types.HostPort;
import org.opends.server.types.InitializationException;
@@ -115,6 +116,14 @@
  public abstract String getConnectionHandlerName();
   /**
   * Retrieves the DN of the configuration entry with which this alert
   * generator is associated.
   *
   * @return The DN of the configuration entry with which this alert
   *         generator is associated.
   */
  public abstract DN getComponentEntryDN();
  /**
   * Retrieves the name of the protocol used to communicate with
opends/src/server/org/opends/server/backends/MonitorBackend.java
@@ -467,25 +467,10 @@
      return getBaseMonitorEntry();
    }
    // See if the monitor base entry is the immediate parent for the requested
    // entry.  If not, then throw an exception.
    DN parentDN = entryDN.getParentDNInSuffix();
    if ((parentDN == null) || (! parentDN.equals(baseMonitorDN)))
    {
      if (baseMonitorDN.isAncestorOf(entryDN))
      {
        Message message = ERR_MONITOR_BASE_TOO_DEEP.get(
            String.valueOf(entryDN), String.valueOf(baseMonitorDN));
        throw new DirectoryException(
                ResultCode.NO_SUCH_OBJECT, message, baseMonitorDN, null);
      }
      else
      {
        Message message = ERR_MONITOR_INVALID_BASE.get(
            String.valueOf(entryDN), String.valueOf(baseMonitorDN));
        throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message);
      }
    if (!isATreeNode(entryDN)) {
      Message message = ERR_MONITOR_INVALID_BASE.get(
          String.valueOf(entryDN), String.valueOf(baseMonitorDN));
      throw new DirectoryException(ResultCode.NO_SUCH_OBJECT, message);
    }
@@ -499,20 +484,14 @@
              ResultCode.NO_SUCH_OBJECT, message, baseMonitorDN, null);
    }
    // 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).getStringValue();
    String rdnValue = getRdns(entryDN);
    MonitorProvider<? extends MonitorProviderCfg> monitorProvider =
         DirectoryServer.getMonitorProvider(rdnValue.toLowerCase());
    if (monitorProvider == null)
    {
      Message message =
          ERR_MONITOR_NO_SUCH_PROVIDER.get(String.valueOf(rdnValue));
      throw new DirectoryException(
              ResultCode.NO_SUCH_OBJECT, message, baseMonitorDN, null);
    }
    // Could be a monitor branch
    if (monitorProvider == null) {
       return getBranchMonitorEntry(entryDN);
    }
    // Take the data from the monitor provider and stuff it into an entry.
    return getMonitorEntry(entryDN, monitorProvider);
@@ -527,27 +506,7 @@
  public boolean entryExists(DN entryDN)
         throws DirectoryException
  {
    if (entryDN.equals(baseMonitorDN))
    {
      return true;
    }
    DN parentDN = entryDN.getParentDNInSuffix();
    if ((parentDN == null) || (! parentDN.equals(baseMonitorDN)))
    {
      return false;
    }
    RDN rdn = entryDN.getRDN();
    if (rdn.isMultiValued())
    {
      return false;
    }
    String rdnValue = rdn.getAttributeValue(0).getStringValue();
    MonitorProvider<?> monitorProvider =
         DirectoryServer.getMonitorProvider(toLowerCase(rdnValue));
    return (monitorProvider != null);
      return this.isATreeNode(entryDN);
  }
@@ -718,7 +677,37 @@
    return e;
  }
   /**
   * Retrieves the branch monitor entry for the Directory Server.
   * @param dn to get.
   * @return  The branch monitor entry for the Directory Server.
   */
  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);
    ObjectClass monitorOC = DirectoryServer.getObjectClass(OC_MONITOR_BRANCH,
                                                           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;
      }
    }
    return e;
  }
  /**
   * Generates and returns a monitor entry based on the contents of the
@@ -872,60 +861,100 @@
    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.
    SearchScope  scope  = searchOperation.getScope();
    SearchFilter filter = searchOperation.getFilter();
    if (baseMonitorDN.equals(baseDN))
    if ((scope == SearchScope.BASE_OBJECT) ||
        (scope == SearchScope.WHOLE_SUBTREE))
    {
      // If it is a base-level or subtree search, then we need to look at the
      // base monitor entry.
      if ((scope == SearchScope.BASE_OBJECT) ||
          (scope == SearchScope.WHOLE_SUBTREE))
      if (filter.matchesEntry(baseEntry))
      {
        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;
        }
        searchOperation.returnEntry(baseEntry, null);
      }
      // 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())
      // If it is a base-level search, then we're done.
      if (scope == SearchScope.BASE_OBJECT)
      {
        DN providerDN = DirectoryServer.getMonitorProviderDN(monitorProvider);
        Entry monitorEntry = getMonitorEntry(providerDN, monitorProvider);
        if (filter.matchesEntry(monitorEntry))
        {
          searchOperation.returnEntry(monitorEntry, null);
        }
        return;
      }
    }
    else
    {
      // Look at the scope for the search.  We only need to return something if
      // it is a base-level or subtree search.
      if ((scope == SearchScope.BASE_OBJECT) ||
          (scope == SearchScope.WHOLE_SUBTREE))
      {
        if (filter.matchesEntry(baseEntry))
        {
          searchOperation.returnEntry(baseEntry, null);
        }
    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);
            }
            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;
      for (MonitorProvider<? extends MonitorProviderCfg> monitorProvider :
           DirectoryServer.getMonitorProviders().values()) {
         DN providerDN = DirectoryServer.getMonitorProviderDN(monitorProvider);
         if (dn.equals(providerDN)) {
             found=true;
         }
      }
      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);
  }
  /**
opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -163,7 +163,6 @@
import org.opends.server.types.OperatingSystem;
import org.opends.server.types.OperationType;
import org.opends.server.types.Privilege;
import org.opends.server.types.RDN;
import org.opends.server.types.RestoreConfig;
import org.opends.server.types.ResultCode;
import org.opends.server.types.Schema;
@@ -9827,7 +9826,8 @@
    DN monitorRootDN;
    try
    {
      monitorRootDN = DN.decode(DN_MONITOR_ROOT);
      // Get a complete DN which could be a tree naming schema
      monitorRootDN = DN.decode("cn="+monitorName+","+DN_MONITOR_ROOT);
    }
    catch (DirectoryException e)
    {
@@ -9835,8 +9835,7 @@
      throw new RuntimeException();
    }
    RDN rdn = RDN.create(cnType, new AttributeValue(cnType, monitorName));
    return monitorRootDN.concat(rdn);
    return monitorRootDN;
  }
opends/src/server/org/opends/server/core/networkgroups/NetworkGroup.java
@@ -156,8 +156,7 @@
    isAdminNetworkGroup    = ADMIN_NETWORK_GROUP_NAME.equals(networkGroupID);
    isDefaultNetworkGroup  = DEFAULT_NETWORK_GROUP_NAME.equals(networkGroupID);
    stats = new NetworkGroupStatistics(this,
        networkGroupID + " Network Group Statistics");
    stats = new NetworkGroupStatistics(this);
  }
opends/src/server/org/opends/server/core/networkgroups/NetworkGroupStatistics.java
@@ -69,12 +69,10 @@
  /**
   * Constructor.
   * @param networkGroup The network group owning these stats
   * @param instanceName The name of the stat object
   */
  public NetworkGroupStatistics(
          NetworkGroup networkGroup, String instanceName) {
    super("LDAP Statistics Monitor Provider");
    this.instanceName = instanceName;
  public NetworkGroupStatistics(NetworkGroup networkGroup) {
    super(networkGroup.getID());
    this.instanceName = networkGroup.getID();
    this.networkGroup = networkGroup;
    DirectoryServer.registerMonitorProvider(this);
  }
@@ -148,7 +146,7 @@
   * {@inheritDoc}
   */
  public String getMonitorInstanceName() {
    return instanceName;
      return this.instanceName+",cn=Network Groups";
  }
  /**
opends/src/server/org/opends/server/monitors/ClientConnectionMonitorProvider.java
@@ -56,13 +56,26 @@
public class ClientConnectionMonitorProvider
       extends MonitorProvider<ClientConnectionMonitorProviderCfg>
{
  private ConnectionHandler<?> handler;
  /**
   * Creates an instance of this monitor provider.
   */
  public ClientConnectionMonitorProvider()
  {
    super("Client Connection Monitor Provider");
    // No initialization should be performed here.
  }
  /**
   * Creates an instance of this monitor provider.
   * @param handler to which the monitor provider is associated.
   */
  public ClientConnectionMonitorProvider(ConnectionHandler handler)
  {
    super("Client Connection Monitor Provider");
    this.handler=handler;
    // No initialization should be performed here.
  }
@@ -88,7 +101,14 @@
   */
  public String getMonitorInstanceName()
  {
    return "Client Connections";
    if (this.handler==null) {
       return "Client Connections";
    }
    else {
       // Client connections of a connection handler
       return "Client Connections"+",cn="+
               this.handler.getConnectionHandlerName();
    }
  }
@@ -135,31 +155,38 @@
   */
  public ArrayList<Attribute> getMonitorData()
  {
    // Get information about all the available connections.
    ArrayList<Collection<ClientConnection>> connCollections =
         new ArrayList<Collection<ClientConnection>>();
    for (ConnectionHandler<?> handler : DirectoryServer.getConnectionHandlers())
    {
      ConnectionHandler<? extends ConnectionHandlerCfg> connHandler =
           (ConnectionHandler<? extends ConnectionHandlerCfg>) handler;
      connCollections.add(connHandler.getClientConnections());
    }
    // Re-order the connections by connection ID.
    TreeMap<Long,ClientConnection> connMap =
         new TreeMap<Long,ClientConnection>();
    for (Collection<ClientConnection> collection : connCollections)
    {
      for (ClientConnection conn : collection)
      {
        connMap.put(conn.getConnectionID(), conn);
      }
             new TreeMap<Long,ClientConnection>();
    if (this.handler==null) {
        // Get information about all the available connections.
        ArrayList<Collection<ClientConnection>> connCollections =
             new ArrayList<Collection<ClientConnection>>();
        for (ConnectionHandler<?> hdl : DirectoryServer.getConnectionHandlers())
        {
          ConnectionHandler<? extends ConnectionHandlerCfg> connHandler =
               (ConnectionHandler<? extends ConnectionHandlerCfg>) hdl;
          connCollections.add(connHandler.getClientConnections());
        }
        for (Collection<ClientConnection> collection : connCollections)
        {
          for (ClientConnection conn : collection)
          {
            connMap.put(conn.getConnectionID(), conn);
          }
        }
    }
    else {
       Collection<ClientConnection> collection =
               this.handler.getClientConnections();
       for (ClientConnection conn : collection) {
            connMap.put(conn.getConnectionID(), conn);
       }
    }
    // Iterate through all the client connections and create a one-line summary
    // of each.
    AttributeType attrType = DirectoryServer
        .getDefaultAttributeType("connection");
    AttributeBuilder builder = new AttributeBuilder(attrType);
@@ -168,8 +195,7 @@
      builder.add(new AttributeValue(attrType, conn.getMonitorSummary()));
    }
    ArrayList<Attribute> attrs = new ArrayList<Attribute>(1);
    ArrayList<Attribute> attrs = new ArrayList<Attribute>(2);
    attrs.add(builder.toAttribute());
    return attrs;
  }
opends/src/server/org/opends/server/monitors/ConnectionHandlerMonitor.java
@@ -70,6 +70,9 @@
  // The attribute type that will be used to report the protocol.
  private AttributeType protocolType;
  // The attribute type that will be used to report the config dn .
  private AttributeType configDnType;
  // The connection handler with which this monitor is associated.
  private ConnectionHandler<?> connectionHandler;
@@ -118,6 +121,10 @@
    protocolType =
         DirectoryConfig.getAttributeType(ATTR_MONITOR_CONNHANDLER_PROTOCOL,
                                          true);
    configDnType =
         DirectoryConfig.getAttributeType(ATTR_MONITOR_CONFIG_DN,
                                          true);
  }
@@ -174,6 +181,10 @@
  {
    LinkedList<Attribute> attrs = new LinkedList<Attribute>();
    // Configuration DN
    attrs.add(Attributes.create(configDnType, String.valueOf(
            connectionHandler.getComponentEntryDN().toNormalizedString())));
    int numConnections = 0;
    LinkedList<ClientConnection> conns = new LinkedList<ClientConnection>(
        connectionHandler.getClientConnections());
opends/src/server/org/opends/server/protocols/internal/InternalConnectionHandler.java
@@ -36,6 +36,7 @@
import org.opends.server.api.ClientConnection;
import org.opends.server.api.ConnectionHandler;
import org.opends.server.config.ConfigException;
import org.opends.server.types.DN;
import org.opends.server.types.InitializationException;
import org.opends.server.types.HostPort;
@@ -67,6 +68,8 @@
  // The name of the protocol for this connection handler.
  private String protocol;
  // Configuration object of the connection hanlder
  private ConnectionHandlerCfg configuration;
  /**
@@ -124,7 +127,7 @@
                   ConnectionHandlerCfg configuration)
      throws ConfigException, InitializationException
  {
    // No implementation required.
    this.configuration = configuration;
  }
@@ -269,5 +272,14 @@
    InternalClientConnection.clearRootClientConnectionAtShutdown();
  }
  /**
   * Return the configuration dn of the object.
   * @return DN of the entry.
   */
  @Override()
  public DN getComponentEntryDN() {
      return this.configuration.dn();
  }
}
opends/src/server/org/opends/server/protocols/ldap/LDAPClientConnection.java
@@ -64,6 +64,7 @@
import org.opends.server.extensions.TLSCapableConnection;
import org.opends.server.extensions.TLSConnectionSecurityProvider;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.monitors.OperationMonitor;
import org.opends.server.protocols.asn1.ASN1Element;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.asn1.ASN1Sequence;
@@ -90,6 +91,7 @@
import static org.opends.server.protocols.ldap.LDAPConstants.*;
import static org.opends.server.util.StaticUtils.getExceptionMessage;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
import static org.opends.server.types.OperationType.*;
@@ -192,6 +194,9 @@
  // The statistics tracker associated with this client connection.
  private LDAPStatistics statTracker;
  // The connectionHandler statistic tracker.
  private LDAPStatistics parentTracker;
  // The connection ID assigned to this connection.
  private long connectionID;
@@ -224,6 +229,18 @@
  //during a SASL bind (GSSAPI and DIGEST-MD5 only).
  private ConnectionSecurityProvider saslSecurityProvider;
  // Statistics for the processed operations
  private OperationMonitor addMonitor;
  private OperationMonitor searchMonitor;
  private OperationMonitor abandonMonitor;
  private OperationMonitor bindMonitor;
  private OperationMonitor compareMonitor;
  private OperationMonitor delMonitor;
  private OperationMonitor extendedMonitor;
  private OperationMonitor modMonitor;
  private OperationMonitor moddnMonitor;
  private OperationMonitor unbindMonitor;
  /**
   * Creates a new LDAP client connection with the provided information.
   *
@@ -276,10 +293,12 @@
    serverAddress = clientChannel.socket().getLocalAddress().getHostAddress();
    serverPort    = clientChannel.socket().getLocalPort();
    LDAPStatistics parentTracker = connectionHandler.getStatTracker();
    parentTracker = connectionHandler.getStatTracker();
    String         instanceName  = parentTracker.getMonitorInstanceName() +
                                   " for " + toString();
    statTracker = new LDAPStatistics(instanceName, parentTracker);
    this.initializeOperationMonitors();
    statTracker = new LDAPStatistics(connectionHandler,
            instanceName, parentTracker);
    if (keepStats)
    {
@@ -1846,28 +1865,89 @@
    // the connection being terminated.
    try
    {
      boolean result;
      switch (message.getProtocolOpType())
      {
        case OP_TYPE_ABANDON_REQUEST:
          return processAbandonRequest(message, opControls);
          if (keepStats) this.abandonMonitor.start();
          result=processAbandonRequest(message, opControls);
          if (keepStats) {
              this.abandonMonitor.stop();
              this.abandonMonitor.updateMonitorProvider(statTracker);
          }
          return result;
        case OP_TYPE_ADD_REQUEST:
          return processAddRequest(message, opControls);
          if (keepStats) this.addMonitor.start();
          result=processAddRequest(message, opControls);
          if (keepStats) {
              this.addMonitor.stop();
              this.addMonitor.updateMonitorProvider(statTracker);
          }
          return result;
        case OP_TYPE_BIND_REQUEST:
          return processBindRequest(message, opControls);
          if (keepStats) this.bindMonitor.start();
          result=processBindRequest(message, opControls);
          if (keepStats) {
              this.bindMonitor.stop();
              this.bindMonitor.updateMonitorProvider(statTracker);
          }
          return result;
        case OP_TYPE_COMPARE_REQUEST:
          return processCompareRequest(message, opControls);
          if (keepStats) this.compareMonitor.start();
          result=processCompareRequest(message, opControls);
          if (keepStats) {
              this.compareMonitor.stop();
              this.compareMonitor.updateMonitorProvider(statTracker);
          }
          return result;
        case OP_TYPE_DELETE_REQUEST:
          return processDeleteRequest(message, opControls);
          if (keepStats) this.delMonitor.start();
          result=processDeleteRequest(message, opControls);
          if (keepStats) {
              this.delMonitor.stop();
              this.delMonitor.updateMonitorProvider(statTracker);
          }
          return result;
        case OP_TYPE_EXTENDED_REQUEST:
          return processExtendedRequest(message, opControls);
          if (keepStats) this.extendedMonitor.start();
          result=processExtendedRequest(message, opControls);
          if (keepStats) {
              this.extendedMonitor.stop();
              this.extendedMonitor.updateMonitorProvider(statTracker);
          }
          return result;
        case OP_TYPE_MODIFY_REQUEST:
          return processModifyRequest(message, opControls);
          if (keepStats) this.modMonitor.start();
          result=processModifyRequest(message, opControls);
          if (keepStats) {
              this.modMonitor.stop();
              this.modMonitor.updateMonitorProvider(statTracker);
          }
          return result;
        case OP_TYPE_MODIFY_DN_REQUEST:
          return processModifyDNRequest(message, opControls);
          if (keepStats) this.moddnMonitor.start();
          result=processModifyDNRequest(message, opControls);
          if (keepStats) {
              this.moddnMonitor.stop();
              this.moddnMonitor.updateMonitorProvider(statTracker);
          }
          return result;
        case OP_TYPE_SEARCH_REQUEST:
          return processSearchRequest(message, opControls);
          if (keepStats) this.searchMonitor.start();
          result=processSearchRequest(message, opControls);
          if (keepStats) {
              this.searchMonitor.stop();
              this.searchMonitor.updateMonitorProvider(statTracker);
          }
          return result;
        case OP_TYPE_UNBIND_REQUEST:
          return processUnbindRequest(message, opControls);
          if (keepStats) this.unbindMonitor.start();
          result=processUnbindRequest(message, opControls);
          if (keepStats) {
              this.unbindMonitor.stop();
              this.unbindMonitor.updateMonitorProvider(statTracker);
          }
          return result;
        default:
          Message msg = ERR_LDAP_DISCONNECT_DUE_TO_INVALID_REQUEST_TYPE.get(
                  message.getProtocolOpName(), message.getMessageID());
@@ -2893,5 +2973,28 @@
      return 0L;
    }
  }
  private void initializeOperationMonitors() {
    this.addMonitor = OperationMonitor.getOperationMonitor(
            ADD);
    this.searchMonitor = OperationMonitor.getOperationMonitor(
            SEARCH);
    this.abandonMonitor = OperationMonitor.getOperationMonitor(
            ABANDON);
    this.bindMonitor = OperationMonitor.getOperationMonitor(
            BIND);
    this.compareMonitor = OperationMonitor.getOperationMonitor(
            COMPARE);
    this.delMonitor = OperationMonitor.getOperationMonitor(
            DELETE);
    this.extendedMonitor = OperationMonitor.getOperationMonitor(
            EXTENDED);
    this.modMonitor = OperationMonitor.getOperationMonitor(
            MODIFY);
    this.moddnMonitor = OperationMonitor.getOperationMonitor(
            MODIFY_DN);
    this.unbindMonitor = OperationMonitor.getOperationMonitor(
            UNBIND);
  }
}
opends/src/server/org/opends/server/protocols/ldap/LDAPConnectionHandler.java
@@ -293,7 +293,7 @@
    if (currentConfig.isAllowLDAPV2() != config.isAllowLDAPV2()) {
      if (config.isAllowLDAPV2()) {
        if (statTracker == null) {
          statTracker = new LDAPStatistics(handlerName
          statTracker = new LDAPStatistics(this,handlerName
              + " Statistics");
        } else {
          statTracker.clearStatistics();
@@ -736,7 +736,7 @@
    }
    // Perform any additional initialization that might be required.
    statTracker = new LDAPStatistics(handlerName + " Statistics");
    statTracker = new LDAPStatistics(this, handlerName + " Statistics");
    // Attempt to bind to the listen port on all configured addresses to
    // verify whether the connection handler will be able to start.
opends/src/server/org/opends/server/protocols/ldap/LDAPStatistics.java
@@ -32,10 +32,13 @@
import org.opends.messages.Message;
import org.opends.server.admin.std.server.MonitorProviderCfg;
import org.opends.server.api.ConnectionHandler;
import org.opends.server.api.MonitorProvider;
import org.opends.server.core.DirectoryServer;
import org.opends.server.config.ConfigException;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.monitors.ClientConnectionMonitorProvider;
import org.opends.server.monitors.OperationMonitor;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeBuilder;
@@ -46,6 +49,7 @@
import static org.opends.messages.ProtocolMessages.*;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.protocols.ldap.LDAPConstants.*;
import static org.opends.server.types.OperationType.*;
@@ -128,17 +132,43 @@
  // The instance name for this monitor provider instance.
  private String instanceName;
  // Connection Handler to which the statistics belong to.
  private ConnectionHandler handler;
    // Monitor Objects : for Operations.
    private OperationMonitor addRequestsMonitor =
            OperationMonitor.getOperationMonitor(ADD);
    private OperationMonitor searchRequestsMonitor =
            OperationMonitor.getOperationMonitor(SEARCH);
    private OperationMonitor delRequestsMonitor =
            OperationMonitor.getOperationMonitor(DELETE);
    private OperationMonitor bindRequestsMonitor =
            OperationMonitor.getOperationMonitor(BIND);
    private OperationMonitor unbindRequestsMonitor =
            OperationMonitor.getOperationMonitor(UNBIND);
    private OperationMonitor compareRequestsMonitor =
            OperationMonitor.getOperationMonitor(COMPARE);
    private OperationMonitor modRequestsMonitor =
            OperationMonitor.getOperationMonitor(MODIFY);
    private OperationMonitor moddnRequestsMonitor =
            OperationMonitor.getOperationMonitor(MODIFY);
    private OperationMonitor abandonRequestsMonitor =
            OperationMonitor.getOperationMonitor(ABANDON);
    private OperationMonitor extendedRequestsMonitor =
            OperationMonitor.getOperationMonitor(EXTENDED);
  /**
   * Creates a new instance of this class with no parent.
   *
   * @param handler to which the stats belong  to.
   * @param  instanceName  The name for this monitor provider instance.
   */
  public LDAPStatistics(String instanceName)
  public LDAPStatistics(ConnectionHandler handler,
          String instanceName)
  {
    this(instanceName, null);
    this(handler, instanceName, null);
    DirectoryServer.registerMonitorProvider(this);
  }
@@ -148,18 +178,21 @@
  /**
   * Creates a new instance of this class with the specified parent.
   *
   * @param  handler       the handler to which the stats belong to.
   * @param  instanceName  The name for this monitor provider instance.
   * @param  parent        The parent object that should also be updated
   *                       whenever this class is updated.  It may be null if
   *                       there should not be a parent.
   */
  public LDAPStatistics(String instanceName, LDAPStatistics parent)
  public LDAPStatistics(ConnectionHandler handler,
          String instanceName, LDAPStatistics parent)
  {
    super("LDAP Statistics Monitor Provider");
    this.instanceName = instanceName;
    this.parent       = parent;
    this.handler = handler;
    abandonLock    = new Object();
    connectLock    = new Object();
@@ -196,6 +229,11 @@
    searchResultReferences = 0;
    searchResultsDone      = 0;
    unbindRequests         = 0;
    ClientConnectionMonitorProvider connections =
                new ClientConnectionMonitorProvider(this.handler);
    DirectoryServer.registerMonitorProvider(connections);
  }
@@ -407,7 +445,89 @@
    attrs.add(createAttribute("unbindRequests",
                              String.valueOf(tmpUnbindRequests)));
    return attrs;
     // adds
     attrs.add(createAttribute(
                "ds-mon-add-operations-total-count",
                String.valueOf(addRequestsMonitor.getCounter().getCount())));
     attrs.add(createAttribute(
                "ds-mon-resident-time-add-operations-total-time",
                String.valueOf(addRequestsMonitor.getTotalTime())));
     // search
     attrs.add(createAttribute(
              "ds-mon-search-operations-total-count",
                String.valueOf(searchRequestsMonitor.getCounter().getCount())));
     attrs.add(createAttribute(
                "ds-mon-resident-time-search-operations-total-time",
                String.valueOf(searchRequestsMonitor.getTotalTime())));
     // bind
     attrs.add(createAttribute(
                "ds-mon-bind-operations-total-count",
                String.valueOf(bindRequestsMonitor.getCounter().getCount())));
     attrs.add(createAttribute(
                "ds-mon-resident-time-bind-operations-total-time",
                String.valueOf(bindRequestsMonitor.getTotalTime())));
     // unbind
     attrs.add(createAttribute(
              "ds-mon-unbind-operations-total-count",
              String.valueOf(unbindRequestsMonitor.getCounter().getCount())));
     attrs.add(createAttribute(
                "ds-mon-resident-time-unbind-operations-total-time",
                String.valueOf(unbindRequestsMonitor.getTotalTime())));
     // compare
     attrs.add(createAttribute(
             "ds-mon-compare-operations-total-count",
             String.valueOf(
             compareRequestsMonitor.getCounter().getCount())));
     attrs.add(createAttribute(
             "ds-mon-resident-time-compare-operations-total-time",
             String.valueOf(compareRequestsMonitor.getTotalTime())));
     // del
     attrs.add(createAttribute(
             "ds-mon-delete-operations-total-count",
             String.valueOf(delRequestsMonitor.getCounter().getCount())));
     attrs.add(createAttribute(
             "ds-mon-resident-time-delete-operations-total-time",
             String.valueOf(delRequestsMonitor.getTotalTime())));
     // mod
     attrs.add(createAttribute(
             "ds-mon-mod-operations-total-count",
             String.valueOf(modRequestsMonitor.getCounter().getCount())));
     attrs.add(createAttribute(
            "ds-mon-resident-time-mod-operations-total-time",
            String.valueOf(modRequestsMonitor.getTotalTime())));
     // moddn
     attrs.add(createAttribute(
            "ds-mon-moddn-operations-total-count",
            String.valueOf(moddnRequestsMonitor.getCounter().getCount())));
     attrs.add(createAttribute(
            "ds-mon-resident-time-moddn-operations-total-time",
            String.valueOf(moddnRequestsMonitor.getTotalTime())));
     // abandon
     attrs.add(createAttribute(
             "ds-mon-abandon-operations-total-count",
             String.valueOf(
             abandonRequestsMonitor.getCounter().getCount())));
     attrs.add(createAttribute(
             "ds-mon-resident-time-abandon-operations-total-time",
             String.valueOf(abandonRequestsMonitor.getTotalTime())));
     // extended
     attrs.add(createAttribute(
             "ds-mon-extended-operations-total-count",
             String.valueOf(
             extendedRequestsMonitor.getCounter().getCount())));
     attrs.add(createAttribute(
             "ds-mon-resident-time-extended-operations-total-time",
             String.valueOf(extendedRequestsMonitor.getTotalTime())));
     return attrs;
  }
@@ -1163,5 +1283,52 @@
  {
    return parent;
  }
   /**
     * Updates the monitor object.
     * @param opMonitor monitor object.
     */
    public void updateMonitor(OperationMonitor opMonitor) {
        synchronized (readLock) {
            switch (opMonitor.getType()) {
                case ABANDON:
                    this.abandonRequestsMonitor.add(opMonitor);
                    break;
                case ADD:
                    this.addRequestsMonitor.add(opMonitor);
                    break;
                case BIND:
                    this.bindRequestsMonitor.add(opMonitor);
                    break;
                case COMPARE:
                    this.compareRequestsMonitor.add(opMonitor);
                    break;
                case DELETE:
                    this.delRequestsMonitor.add(opMonitor);
                    break;
                case EXTENDED:
                    this.extendedRequestsMonitor.add(opMonitor);
                    break;
                case MODIFY:
                    this.modRequestsMonitor.add(opMonitor);
                    break;
                case MODIFY_DN:
                    this.moddnRequestsMonitor.add(opMonitor);
                    break;
                case SEARCH:
                    this.searchRequestsMonitor.add(opMonitor);
                    break;
                case UNBIND:
                    this.unbindRequestsMonitor.add(opMonitor);
                    break;
                default:
            }
            if (parent!=null) {
                parent.updateMonitor(opMonitor);
            }
            opMonitor.reset();
        }
    }
}
opends/src/server/org/opends/server/util/ServerConstants.java
@@ -287,6 +287,12 @@
  public static final String ATTR_MONITOR_CONNHANDLER_LISTENER =
       "ds-connectionhandler-listener";
   /**
   * The name of the monitor attribute that is used to hold the connection
   * handler listeners.
   */
  public static final String ATTR_MONITOR_CONFIG_DN =
       "ds-mon-config-dn";
  /**
@@ -847,6 +853,11 @@
   */
  public static final String OC_MONITOR_ENTRY = "ds-monitor-entry";
   /**
   * The name of the objectclass that will be used as the structural class for
   * monitor branches.
   */
  public static final String OC_MONITOR_BRANCH = "ds-mon-branch";
  /**
opends/tests/unit-tests-testng/src/server/org/opends/server/monitors/InternalSearchMonitorTestCase.java
@@ -140,12 +140,8 @@
  public void testWithBaseObjectMonitorSearch(String monitorName)
         throws Exception
  {
    AttributeType cnType = DirectoryServer.getAttributeType(ATTR_COMMON_NAME);
    RDN[] rdns = new RDN[2];
    rdns[0] = RDN.create(cnType, new AttributeValue(cnType, monitorName));
    rdns[1] = RDN.create(cnType, new AttributeValue(cnType, "monitor"));
    DN monitorDN = new DN(rdns);
    // could be more than one level
    DN monitorDN = DN.decode("cn="+monitorName+",cn=monitor");
    InternalClientConnection conn =
         InternalClientConnection.getRootConnection();