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

abobrov
09.48.2007 4166c20ed1817f2792c6c4a6d12b810c7c256b72
- [Issue 1594] entry caches should have monitor information:
implement generic entry cache monitor provider which allows any entry cache implementation current or future
to provide a common or custom set of entry cache state data. update all existing entry cache implementations
so that they provide their common state data to the entry cache monitor provider.
2 files added
8 files modified
515 ■■■■■ changed files
opends/resource/config/config.ldif 8 ●●●●● patch | view | raw | blame | history
opends/resource/schema/02-config.ldif 3 ●●●●● patch | view | raw | blame | history
opends/src/admin/defn/org/opends/server/admin/std/EntryCacheMonitorProviderConfiguration.xml 60 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/api/EntryCache.java 32 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/DefaultEntryCache.java 15 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/EntryCacheCommon.java 121 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/FIFOEntryCache.java 34 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java 64 ●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java 34 ●●●●● patch | view | raw | blame | history
opends/src/server/org/opends/server/monitors/EntryCacheMonitorProvider.java 144 ●●●●● patch | view | raw | blame | history
opends/resource/config/config.ldif
@@ -1179,6 +1179,14 @@
ds-cfg-monitor-provider-class: org.opends.server.monitors.VersionMonitorProvider
ds-cfg-monitor-provider-enabled: true
dn: cn=Entry Cache,cn=Monitor Providers,cn=config
objectClass: top
objectClass: ds-cfg-monitor-provider
objectClass: ds-cfg-entry-cache-monitor-provider
cn: Entry Cache
ds-cfg-monitor-provider-class: org.opends.server.monitors.EntryCacheMonitorProvider
ds-cfg-monitor-provider-enabled: true
dn: cn=Password Generators,cn=config
objectClass: top
objectClass: ds-cfg-branch
opends/resource/schema/02-config.ldif
@@ -2467,4 +2467,7 @@
  NAME 'ds-cfg-ldif-connection-handler' SUP ds-cfg-connection-handler
  MUST ( ds-cfg-ldif-directory $ ds-cfg-poll-interval )
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.173
  NAME 'ds-cfg-entry-cache-monitor-provider' SUP ds-cfg-monitor-provider
  STRUCTURAL X-ORIGIN 'OpenDS Directory Server' )
opends/src/admin/defn/org/opends/server/admin/std/EntryCacheMonitorProviderConfiguration.xml
New file
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
! 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.
! -->
<adm:managed-object
  name="entry-cache-monitor-provider"
  plural-name="entry-cache-monitor-providers"
  package="org.opends.server.admin.std"
  extends="monitor-provider"
  xmlns:adm="http://www.opends.org/admin"
  xmlns:ldap="http://www.opends.org/admin-ldap">
  <adm:synopsis>
    The <adm:user-friendly-name /> exposes monitor information about
    Directory Server entry cache state.
  </adm:synopsis>
  <adm:profile name="ldap">
    <ldap:object-class>
      <ldap:oid>1.3.6.1.4.1.26027.1.2.173</ldap:oid>
      <ldap:name>ds-cfg-entry-cache-monitor-provider</ldap:name>
      <ldap:superior>ds-cfg-monitor-provider</ldap:superior>
    </ldap:object-class>
  </adm:profile>
  <adm:property-override name="monitor-class">
    <adm:default-behavior>
      <adm:defined>
        <adm:value>
          org.opends.server.monitors.EntryCacheMonitorProvider
        </adm:value>
      </adm:defined>
    </adm:default-behavior>
  </adm:property-override>
</adm:managed-object>
opends/src/server/org/opends/server/api/EntryCache.java
@@ -33,6 +33,8 @@
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicLong;
import org.opends.server.core.DirectoryServer;
import org.opends.server.config.ConfigException;
@@ -43,6 +45,7 @@
import org.opends.server.types.LockManager;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.Attribute;
import org.opends.server.admin.std.server.EntryCacheCfg;
import org.opends.server.loggers.debug.DebugTracer;
import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -105,6 +108,16 @@
  // up.
  private long lockTimeout = LockManager.DEFAULT_TIMEOUT;
  /**
   * Arbitrary number of cache hits for monitoring.
   */
  protected AtomicLong cacheHits = new AtomicLong(0);
  /**
   * Arbitrary number of cache misses for monitoring.
   */
  protected AtomicLong cacheMisses = new AtomicLong(0);
  /**
@@ -239,6 +252,9 @@
                        List<Lock> lockList) {
    if (!containsEntry(entryDN)) {
      // Indicate cache miss.
      cacheMisses.set(cacheMisses.incrementAndGet());
      return null;
    }
@@ -391,6 +407,9 @@
    // Translate given backend/entryID pair to entryDN.
    DN entryDN = getEntryDN(backend, entryID);
    if (entryDN == null) {
      // Indicate cache miss.
      cacheMisses.set(cacheMisses.incrementAndGet());
      return null;
    }
@@ -526,6 +545,19 @@
  /**
   * Retrieves a set of attributes containing monitor data that should
   * be returned to the client if the corresponding monitor entry is
   * requested.
   *
   * @return  A set of attributes containing monitor data that should
   *          be returned to the client if the corresponding monitor
   *          entry is requested.
   */
  public abstract ArrayList<Attribute> getMonitorData();
  /**
   * Retrieves the maximum length of time in milliseconds to wait for
   * a lock before giving up.
   *
opends/src/server/org/opends/server/extensions/DefaultEntryCache.java
@@ -37,6 +37,7 @@
import org.opends.server.api.Backend;
import org.opends.server.api.EntryCache;
import org.opends.server.config.ConfigException;
import org.opends.server.types.Attribute;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
@@ -235,6 +236,18 @@
        );
    return changeResult;
    }
  }
  /**
   * {@inheritDoc}
   */
  public ArrayList<Attribute> getMonitorData()
  {
    // This implementation does not store entries,
    // so there is no monitoring data to provide.
    return new ArrayList<Attribute>();
  }
}
opends/src/server/org/opends/server/extensions/EntryCacheCommon.java
@@ -27,21 +27,24 @@
package org.opends.server.extensions;
import org.opends.messages.Message;
import static org.opends.server.loggers.ErrorLogger.logError;
import org.opends.messages.MessageDescriptor;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.SortedSet;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.AttributeValue;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
import org.opends.messages.MessageDescriptor;
import static org.opends.server.loggers.ErrorLogger.logError;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
/**
 * This class provides some common tools to all entry cache implementations.
@@ -351,5 +354,113 @@
    return errorHandler;
  }
  /**
   * Constructs a set of generic attributes containing entry cache
   * monitor data. Note that <code>null</code> can be passed in
   * place of any argument to denote the argument is omitted, such
   * is when no state data of a given kind is available or can be
   * provided.
   *
   * @param cacheHits      number of cache hits.
   * @param cacheMisses    number of cache misses.
   * @param cacheSize      size of the current cache, in bytes.
   * @param maxCacheSize   maximum allowed cache size, in bytes.
   * @param cacheCount     number of entries stored in the cache.
   * @param maxCacheCount  maximum number of cache entries allowed.
   *
   * @return  A set of generic attributes containing monitor data.
   */
  public static ArrayList<Attribute> getGenericMonitorData(
    Long cacheHits,
    Long cacheMisses,
    Long cacheSize,
    Long maxCacheSize,
    Long cacheCount,
    Long maxCacheCount)
  {
    ArrayList<Attribute> attrs = new ArrayList<Attribute>();
    if ((cacheHits != null) && (cacheMisses != null)) {
      AttributeType hitsAttrType =
        DirectoryServer.getDefaultAttributeType("entryCacheHits");
      LinkedHashSet<AttributeValue> hitsValues =
        new LinkedHashSet<AttributeValue>();
      hitsValues.add(new AttributeValue(hitsAttrType,
        cacheHits.toString()));
      attrs.add(new Attribute(hitsAttrType, "entryCacheHits",
        hitsValues));
      AttributeType triesAttrType =
        DirectoryServer.getDefaultAttributeType("entryCacheTries");
      LinkedHashSet<AttributeValue> triesValues =
        new LinkedHashSet<AttributeValue>();
      Long cacheTries = cacheHits + cacheMisses;
      triesValues.add(new AttributeValue(triesAttrType,
        cacheTries.toString()));
      attrs.add(new Attribute(triesAttrType, "entryCacheTries",
        triesValues));
      AttributeType hitRatioAttrType =
        DirectoryServer.getDefaultAttributeType("entryCacheHitRatio");
      LinkedHashSet<AttributeValue> hitRatioValues =
        new LinkedHashSet<AttributeValue>();
      Double hitRatioRaw = cacheTries > 0 ?
        cacheHits.doubleValue() / cacheTries.doubleValue() :
        cacheHits.doubleValue() / 1;
      Double hitRatio = hitRatioRaw * 100D;
      hitRatioValues.add(new AttributeValue(hitRatioAttrType,
        Long.toString(hitRatio.longValue())));
      attrs.add(new Attribute(hitRatioAttrType, "entryCacheHitRatio",
        hitRatioValues));
    }
    if (cacheSize != null) {
      AttributeType memoryAttrType =
        DirectoryServer.getDefaultAttributeType("currentEntryCacheSize");
      LinkedHashSet<AttributeValue> memoryValues =
        new LinkedHashSet<AttributeValue>();
      memoryValues.add(new AttributeValue(memoryAttrType,
        cacheSize.toString()));
      attrs.add(new Attribute(memoryAttrType, "currentEntryCacheSize",
        memoryValues));
    }
    if (maxCacheSize != null) {
      AttributeType maxMemoryAttrType =
        DirectoryServer.getDefaultAttributeType("maxEntryCacheSize");
      LinkedHashSet<AttributeValue> maxMemoryValues =
        new LinkedHashSet<AttributeValue>();
      maxMemoryValues.add(new AttributeValue(maxMemoryAttrType,
        maxCacheSize.toString()));
      attrs.add(new Attribute(maxMemoryAttrType, "maxEntryCacheSize",
        maxMemoryValues));
    }
    if (cacheCount != null) {
      AttributeType entriesAttrType =
        DirectoryServer.getDefaultAttributeType("currentEntryCacheCount");
      LinkedHashSet<AttributeValue> entriesValues =
        new LinkedHashSet<AttributeValue>();
      entriesValues.add(new AttributeValue(entriesAttrType,
        cacheCount.toString()));
      attrs.add(new Attribute(entriesAttrType, "currentEntryCacheCount",
        entriesValues));
    }
    if (maxCacheCount != null) {
      AttributeType maxEntriesAttrType =
        DirectoryServer.getDefaultAttributeType("maxEntryCacheCount");
      LinkedHashSet<AttributeValue> maxEntriesValues =
        new LinkedHashSet<AttributeValue>();
      maxEntriesValues.add(new AttributeValue(maxEntriesAttrType,
        maxCacheCount.toString()));
      attrs.add(new Attribute(maxEntriesAttrType, "maxEntryCacheCount",
        maxEntriesValues));
    }
    return attrs;
  }
}
opends/src/server/org/opends/server/extensions/FIFOEntryCache.java
@@ -55,6 +55,7 @@
import org.opends.server.types.Entry;
import org.opends.server.types.InitializationException;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.Attribute;
import org.opends.server.util.ServerConstants;
import org.opends.messages.MessageBuilder;
@@ -231,10 +232,14 @@
    CacheEntry e = dnMap.get(entryDN);
    if (e == null)
    {
      // Indicate cache miss.
      cacheMisses.set(cacheMisses.incrementAndGet());
      return null;
    }
    else
    {
      // Indicate cache hit.
      cacheHits.set(cacheHits.incrementAndGet());
      return e.getEntry();
    }
  }
@@ -990,6 +995,35 @@
  /**
   * {@inheritDoc}
   */
  public ArrayList<Attribute> getMonitorData()
  {
    ArrayList<Attribute> attrs = new ArrayList<Attribute>();
    try {
      attrs = EntryCacheCommon.getGenericMonitorData(
        new Long(cacheHits.longValue()),
        new Long(cacheMisses.longValue()),
        null,
        new Long(maxAllowedMemory),
        new Long(dnMap.size()),
        (((maxEntries != Integer.MAX_VALUE) &&
          (maxEntries != Long.MAX_VALUE)) ?
           new Long(maxEntries) : new Long(0))
        );
    } catch (Exception e) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
    }
    return attrs;
  }
  /**
   * Return a verbose string representation of the current cache maps.
   * This is useful primary for debugging and diagnostic purposes such
   * as in the entry cache unit tests.
opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java
@@ -78,6 +78,7 @@
import org.opends.server.types.FilePermission;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.OpenDsException;
import org.opends.server.types.Attribute;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.util.ServerConstants;
@@ -626,6 +627,11 @@
      // Use get to generate entry access.
      if (dnMap.get(entryDN) != null) {
        entry = getEntryFromDB(entryDN);
        // Indicate cache hit.
        cacheHits.set(cacheHits.incrementAndGet());
      } else {
        // Indicate cache miss.
        cacheMisses.set(cacheMisses.incrementAndGet());
      }
    } finally {
      cacheReadLock.unlock();
@@ -1326,6 +1332,34 @@
  }
  /**
   * {@inheritDoc}
   */
  public ArrayList<Attribute> getMonitorData()
  {
    ArrayList<Attribute> attrs = new ArrayList<Attribute>();
    try {
      attrs = EntryCacheCommon.getGenericMonitorData(
        new Long(cacheHits.longValue()),
        new Long(cacheMisses.longValue()),
        new Long(entryCacheEnv.getStats(
          entryCacheEnvStatsConfig).getTotalLogSize()),
        new Long(maxAllowedMemory),
        new Long(dnMap.size()),
        (((maxEntries.longValue() != Integer.MAX_VALUE) &&
          (maxEntries.longValue() != Long.MAX_VALUE)) ?
           new Long(maxEntries.longValue()) : new Long(0))
        );
    } catch (Exception e) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
    }
    return attrs;
  }
  /**
   * Retrieves and decodes the entry with the specified DN from JE backend db.
   *
   * @param  entryDN   The DN of the entry to retrieve.
@@ -1451,15 +1485,15 @@
    }
  }
 /**
  * Checks if the cache home exist and if not tries to recursively create it.
  * If either is successful adjusts cache home access permissions accordingly
  * to allow only process owner or the superuser to access JE environment.
  *
  * @param  cacheHome  String representation of complete file system path.
  *
  * @throws Exception  If failed to establish cache home.
  */
  /**
   * Checks if the cache home exist and if not tries to recursively create it.
   * If either is successful adjusts cache home access permissions accordingly
   * to allow only process owner or the superuser to access JE environment.
   *
   * @param  cacheHome  String representation of complete file system path.
   *
   * @throws Exception  If failed to establish cache home.
   */
  private void checkAndSetupCacheHome(String cacheHome) throws Exception {
    boolean cacheHasHome = false;
@@ -1575,12 +1609,12 @@
    return (verboseString.length() > 0 ? verboseString : null);
  }
 /**
  * This inner class exist solely to override <CODE>removeEldestEntry()</CODE>
  * method of the LinkedHashMap.
  *
  * @see  java.util.LinkedHashMap
  */
  /**
   * This inner class exist solely to override <CODE>removeEldestEntry()</CODE>
   * method of the LinkedHashMap.
   *
   * @see  java.util.LinkedHashMap
   */
  private class LinkedHashMapRotator<K,V> extends LinkedHashMap<K,V> {
    static final long serialVersionUID = 5271482121415968435L;
opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java
@@ -46,6 +46,7 @@
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.Attribute;
import org.opends.server.types.CacheEntry;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DebugLogLevel;
@@ -209,6 +210,8 @@
    SoftReference<CacheEntry> ref = dnMap.get(entryDN);
    if (ref == null)
    {
      // Indicate cache miss.
      cacheMisses.set(cacheMisses.incrementAndGet());
      return null;
    }
    else
@@ -216,10 +219,14 @@
      CacheEntry cacheEntry = ref.get();
      if (cacheEntry == null)
      {
        // Indicate cache miss.
        cacheMisses.set(cacheMisses.incrementAndGet());
        return null;
      }
      else
      {
        // Indicate cache hit.
        cacheHits.set(cacheHits.incrementAndGet());
        return cacheEntry.getEntry();
      }
    }
@@ -652,6 +659,33 @@
  /**
   * {@inheritDoc}
   */
  public ArrayList<Attribute> getMonitorData()
  {
    ArrayList<Attribute> attrs = new ArrayList<Attribute>();
    try {
      attrs = EntryCacheCommon.getGenericMonitorData(
        new Long(cacheHits.longValue()),
        new Long(cacheMisses.longValue()),
        null,
        null,
        new Long(dnMap.size()),
        null
        );
    } catch (Exception e) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
    }
    return attrs;
  }
  /**
   * Return a verbose string representation of the current cache maps.
   * This is useful primary for debugging and diagnostic purposes such
   * as in the entry cache unit tests.
opends/src/server/org/opends/server/monitors/EntryCacheMonitorProvider.java
New file
@@ -0,0 +1,144 @@
/*
 * 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.monitors;
import java.util.ArrayList;
import org.opends.server.admin.server.ServerManagementContext;
import org.opends.server.admin.std.server.EntryCacheCfg;
import org.opends.server.admin.std.server.EntryCacheMonitorProviderCfg;
import org.opends.server.admin.std.server.RootCfg;
import org.opends.server.api.EntryCache;
import org.opends.server.api.MonitorProvider;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.Attribute;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.InitializationException;
import static org.opends.server.loggers.debug.DebugLogger.*;
/**
 * This class defines a Directory Server monitor provider that can be used to
 * obtain information about the entry cache state. Note that the information
 * reported is obtained with no locking, so it may not be entirely consistent.
 */
public class EntryCacheMonitorProvider
       extends MonitorProvider<EntryCacheMonitorProviderCfg>
{
  /**
   * The tracer object for the debug logger.
   */
  private static final DebugTracer TRACER = getTracer();
  /**
   * Creates an instance of this monitor provider.
   */
  public EntryCacheMonitorProvider()
  {
    super("Entry Cache Monitor Provider");
    // No initialization should be performed here.
  }
  /**
   * {@inheritDoc}
   */
  public void initializeMonitorProvider(
                   EntryCacheMonitorProviderCfg configuration)
         throws ConfigException, InitializationException
  {
    // No initialization is required.
  }
  /**
   * {@inheritDoc}
   */
  public String getMonitorInstanceName()
  {
    return "Entry Cache";
  }
  /**
   * {@inheritDoc}
   */
  public long getUpdateInterval()
  {
    // This monitor does not need to run periodically.
    return 0;
  }
  /**
   * {@inheritDoc}
   */
  public void updateMonitorData()
  {
    // This monitor does not need to run periodically.
    return;
  }
  /**
   * {@inheritDoc}
   */
  public ArrayList<Attribute> getMonitorData()
  {
    ArrayList<Attribute> attrs = new ArrayList<Attribute>();
    EntryCacheCfg configuration = null;
    // Get the root configuration object.
    ServerManagementContext managementContext =
      ServerManagementContext.getInstance();
    RootCfg rootConfiguration =
      managementContext.getRootConfiguration();
    // Get the entry cache configuration.
    try {
      configuration = rootConfiguration.getEntryCache();
    } catch (Exception e) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      return attrs;
    }
    // Get the entry cache.
    EntryCache<? extends EntryCacheCfg> cache =
      (EntryCache<? extends EntryCacheCfg>)
       DirectoryServer.getEntryCache();
    if ((cache != null) &&
        (configuration != null) &&
         configuration.isEnabled()) {
      // Get data from the cache.
      attrs = cache.getMonitorData();
    }
    return attrs;
  }
}