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

abobrov
02.54.2007 a79aa3ddbd25b8c7c0abc6c8d5a00c7ed27dd81d
opends/resource/config/config.ldif
@@ -487,13 +487,37 @@
ds-cfg-listen-port: 1689
ds-cfg-ssl-cert-nickname: server-cert
dn: cn=Entry Cache,cn=config
dn: cn=Entry Caches,cn=config
objectClass: top
objectClass: ds-cfg-branch
cn: Entry Caches
dn: cn=Soft Reference,cn=Entry Caches,cn=config
objectClass: top
objectClass: ds-cfg-entry-cache
objectClass: ds-cfg-soft-reference-entry-cache
cn: Entry Cache
ds-cfg-java-class: org.opends.server.extensions.SoftReferenceEntryCache
cn: Soft Reference
ds-cfg-enabled: false
ds-cfg-cache-level: 1
ds-cfg-java-class: org.opends.server.extensions.SoftReferenceEntryCache
dn: cn=FIFO,cn=Entry Caches,cn=config
objectClass: top
objectClass: ds-cfg-entry-cache
objectClass: ds-cfg-fifo-entry-cache
cn: FIFO
ds-cfg-enabled: false
ds-cfg-cache-level: 2
ds-cfg-java-class: org.opends.server.extensions.FIFOEntryCache
dn: cn=File System,cn=Entry Caches,cn=config
objectClass: top
objectClass: ds-cfg-entry-cache
objectClass: ds-cfg-file-system-entry-cache
cn: File System
ds-cfg-enabled: false
ds-cfg-cache-level: 3
ds-cfg-java-class: org.opends.server.extensions.FileSystemEntryCache
dn: cn=Extended Operations,cn=config
objectClass: top
@@ -1171,11 +1195,11 @@
ds-cfg-java-class: org.opends.server.monitors.ClientConnectionMonitorProvider
ds-cfg-enabled: true
dn: cn=Entry Cache,cn=Monitor Providers,cn=config
dn: cn=Entry Caches,cn=Monitor Providers,cn=config
objectClass: top
objectClass: ds-cfg-monitor-provider
objectClass: ds-cfg-entry-cache-monitor-provider
cn: Entry Cache
cn: Entry Caches
ds-cfg-java-class: org.opends.server.monitors.EntryCacheMonitorProvider
ds-cfg-enabled: true
opends/resource/schema/02-config.ldif
@@ -1543,6 +1543,11 @@
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
  SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.999
  NAME 'ds-cfg-cache-level'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
  SINGLE-VALUE
  X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.315
  NAME 'ds-cfg-allow-retrieving-membership'
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
@@ -2328,7 +2333,8 @@
  STRUCTURAL
  MUST ( cn $
         ds-cfg-java-class $
         ds-cfg-enabled )
         ds-cfg-enabled $
         ds-cfg-cache-level )
  X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.15
  NAME 'ds-cfg-fifo-entry-cache'
opends/src/admin/defn/org/opends/server/admin/std/EntryCacheConfiguration.xml
@@ -80,4 +80,19 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="cache-level" mandatory="true">
    <adm:synopsis>
      The entry cache level which specifies this cache position in the
      cache order if more than one instance of the cache is configured.
    </adm:synopsis>
    <adm:syntax>
      <adm:integer lower-limit="1" />
    </adm:syntax>
    <adm:profile name="ldap">
      <ldap:attribute>
        <ldap:name>ds-cfg-cache-level</ldap:name>
      </ldap:attribute>
    </adm:profile>
  </adm:property>
</adm:managed-object>
opends/src/admin/defn/org/opends/server/admin/std/EntryCacheMonitorProviderConfiguration.xml
@@ -33,7 +33,7 @@
  <adm:synopsis>
    The
    <adm:user-friendly-name />
    exposes monitor information about Directory Server entry cache
    exposes monitor information about Directory Server entry caches
    state.
  </adm:synopsis>
  <adm:profile name="ldap">
opends/src/admin/defn/org/opends/server/admin/std/FileSystemEntryCacheConfiguration.xml
@@ -151,7 +151,7 @@
      </ldap:attribute>
    </adm:profile>
  </adm:property>
  <adm:property name="cache-directory" mandatory="true">
  <adm:property name="cache-directory">
    <adm:synopsis>
      Specifies the directory in which the JE environment should store
      the cache.
opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
@@ -204,12 +204,13 @@
    </adm:profile>
  </adm:relation>
  <adm:relation name="entry-cache">
    <adm:one-to-zero-or-one />
    <adm:one-to-many />
    <adm:profile name="ldap">
      <ldap:rdn-sequence>cn=Entry Cache,cn=config</ldap:rdn-sequence>
      <ldap:rdn-sequence>cn=Entry Caches,cn=config</ldap:rdn-sequence>
    </adm:profile>
    <adm:profile name="cli">
      <cli:relation>
        <cli:default-property name="cache-level" />
        <cli:default-property name="enabled" />
      </cli:relation>
    </adm:profile>
opends/src/messages/messages/config.properties
@@ -692,11 +692,10 @@
 invalid value for configuration attribute ds-cfg-check-schema (it should be a \
 Boolean value of true or false):  %s
SEVERE_ERR_CONFIG_ENTRYCACHE_CANNOT_INSTALL_DEFAULT_CACHE_200=An unexpected \
 error occurred that prevented the server from installing a temporary default \
 entry cache for use until the actual cache could be created from the \
 configuration:  %s
 error occurred that prevented the server from installing its default entry \
 cache framework:  %s
SEVERE_WARN_CONFIG_ENTRYCACHE_NO_CONFIG_ENTRY_201=The entry cache \
 configuration entry "cn=Entry Cache,cn=config" does not exist in the \
 configuration entry "cn=Entry Caches,cn=config" does not exist in the \
 Directory Server configuration.  No entry cache will be available until this \
 entry is created with a valid entry cache configuration
SEVERE_ERR_CONFIG_ENTRYCACHE_CANNOT_INITIALIZE_CACHE_202=An error occurred \
@@ -705,6 +704,15 @@
 disabled
SEVERE_ERR_CONFIG_ENTRYCACHE_CONFIG_NOT_ACCEPTABLE_203=The configuration for \
 the entry cache defined in configuration entry %s was not acceptable:  %s
SEVERE_ERR_CONFIG_ENTRYCACHE_CONFIG_LEVEL_NOT_ACCEPTABLE_204=The configuration \
 for the entry cache defined in configuration entry %s was not acceptable:  \
 the entry cache level %d is already in use
INFO_WARN_CONFIG_ENTRYCACHE_NO_MONITOR_CONFIG_ENTRY_205=The configuration for \
 the entry cache %s monitor provider was not available. As a result this \
 monitor provider %s will not be enabled
INFO_WARN_CONFIG_ENTRYCACHE_MONITOR_CONFIG_DISABLED_206=The configuration for \
 the entry cache %s monitor provider was disabled. As a result the monitor \
 provider %s will not be enabled
MILD_ERR_CONFIG_ENTRY_CANNOT_REMOVE_CHILD_215=An unexpected error occurred \
 while attempting to remove entry %s as a child of configuration entry %s:  %s
SEVERE_WARN_CONFIG_SCHEMA_CANNOT_PARSE_NAME_FORM_216=Unable to parse a name \
opends/src/server/org/opends/server/api/EntryCache.java
@@ -30,10 +30,10 @@
import java.util.List;
import java.util.ArrayList;
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;
@@ -45,9 +45,10 @@
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 org.opends.server.monitors.EntryCacheMonitorProvider;
import org.opends.server.types.Attribute;
import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -70,8 +71,8 @@
 *       mechanism to determine which entries to store, and entries
 *       not matching the appropriate criteria may not be stored.</LI>
 *   <LI>The entry cache may not actually store any entries (this is
 *       the behavior of the default cache that will be used if none
 *       is configured).</LI>
 *       the behavior of the default cache if no implementation
 *       specific entry cache is available).</LI>
 * </UL>
 *
 * @param  <T>  The type of configuration handled by this entry
@@ -92,14 +93,12 @@
   */
  private static final DebugTracer TRACER = getTracer();
  //  The set of filters that define the entries that should be
  // The set of filters that define the entries that should be
  // excluded from the cache.
  private Set<SearchFilter> excludeFilters =
       new HashSet<SearchFilter>(0);
  //  The set of filters that define the entries that should be
  // The set of filters that define the entries that should be
  // included in the cache.
  private Set<SearchFilter> includeFilters =
       new HashSet<SearchFilter>(0);
@@ -118,6 +117,8 @@
   */
  protected AtomicLong cacheMisses = new AtomicLong(0);
  // The monitor associated with this entry cache.
  private EntryCacheMonitorProvider entryCacheMonitor = null;
  /**
@@ -253,7 +254,7 @@
    if (!containsEntry(entryDN)) {
      // Indicate cache miss.
      cacheMisses.set(cacheMisses.incrementAndGet());
      cacheMisses.getAndIncrement();
      return null;
    }
@@ -408,7 +409,7 @@
    DN entryDN = getEntryDN(backend, entryID);
    if (entryDN == null) {
      // Indicate cache miss.
      cacheMisses.set(cacheMisses.incrementAndGet());
      cacheMisses.getAndIncrement();
      return null;
    }
@@ -450,7 +451,7 @@
   * @return  The entry DN for the requested entry, or
   *          {@code null} if it is not present in the cache.
   */
  protected abstract DN getEntryDN(Backend backend, long entryID);
  public abstract DN getEntryDN(Backend backend, long entryID);
@@ -545,6 +546,33 @@
  /**
   * Retrieves the monitor that is associated with this entry
   * cache.
   *
   * @return  The monitor that is associated with this entry
   *          cache, or {@code null} if none has been assigned.
   */
  public final EntryCacheMonitorProvider getEntryCacheMonitor()
  {
    return entryCacheMonitor;
  }
  /**
   * Sets the monitor for this entry cache.
   *
   * @param  entryCacheMonitor  The monitor for this entry cache.
   */
  public final void setEntryCacheMonitor(
    EntryCacheMonitorProvider entryCacheMonitor)
  {
    this.entryCacheMonitor = entryCacheMonitor;
  }
  /**
   * Retrieves a set of attributes containing monitor data that should
   * be returned to the client if the corresponding monitor entry is
   * requested.
@@ -558,6 +586,39 @@
  /**
   * Retrieves the curent number of entries stored within the cache.
   *
   * @return  The current number of entries stored within the cache.
   */
  public abstract Long getCacheCount();
  /**
   * Retrieves the curent number of cache hits for this cache.
   *
   * @return  The current number of cache hits for this cache.
   */
  public Long getCacheHits()
  {
    return new Long(cacheHits.longValue());
  }
  /**
   * Retrieves the curent number of cache misses for this cache.
   *
   * @return  The current number of cache misses for this cache.
   */
  public Long getCacheMisses()
  {
    return new Long(cacheMisses.longValue());
  }
  /**
   * Retrieves the maximum length of time in milliseconds to wait for
   * a lock before giving up.
   *
@@ -667,7 +728,7 @@
   * @return  {@code true} if current set of filters allow caching the
   *          entry and {@code false} otherwise.
   */
  protected boolean filtersAllowCaching(Entry entry)
  public boolean filtersAllowCaching(Entry entry)
  {
    // If there is a set of exclude filters, then make sure that the
    // provided entry doesn't match any of them.
opends/src/server/org/opends/server/config/ConfigConstants.java
@@ -2771,8 +2771,8 @@
   * The DN of the entry that will hold the configuration for the Directory
   * Server entry cache.
   */
  public static final String DN_ENTRY_CACHE_CONFIG =
       "cn=Entry Cache," + DN_CONFIG_ROOT;
  public static final String DN_ENTRY_CACHE_BASE =
       "cn=Entry Caches," + DN_CONFIG_ROOT;
@@ -2982,6 +2982,15 @@
  /**
   * The DN of the entry that will serve as the entry cache monitor provider
   * configuration for all Directory Server entry cache monitors.
   */
  public static final String DN_ENTRY_CACHE_MONITOR_CONFIG =
       "cn=Entry Caches," + DN_MONITOR_CONFIG_BASE;
  /**
   * The DN of the entry that will serve as the base for all Directory Server
   * monitor information.
   */
opends/src/server/org/opends/server/core/EntryCacheConfigManager.java
@@ -31,8 +31,11 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import org.opends.server.admin.ClassPropertyDefinition;
import org.opends.server.admin.server.ConfigurationAddListener;
@@ -44,13 +47,18 @@
import org.opends.server.admin.std.meta.EntryCacheCfgDefn;
import org.opends.server.api.EntryCache;
import org.opends.server.config.ConfigException;
import org.opends.server.extensions.DefaultEntryCache;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.InitializationException;
import org.opends.server.types.ResultCode;
import org.opends.messages.MessageBuilder;
import org.opends.server.admin.std.server.EntryCacheMonitorProviderCfg;
import org.opends.server.config.ConfigConstants;
import org.opends.server.config.ConfigEntry;
import org.opends.server.extensions.DefaultEntryCache;
import org.opends.server.monitors.EntryCacheMonitorProvider;
import org.opends.server.types.DN;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.loggers.ErrorLogger.*;
@@ -61,8 +69,8 @@
/**
 * This class defines a utility that will be used to manage the configuration
 * for the Directory Server entry cache.  Only a single entry cache may be
 * defined, but if it is absent or disabled, then a default cache will be used.
 * for the Directory Server entry cache.  The default entry cache is always
 * enabled.
 */
public class EntryCacheConfigManager
       implements
@@ -75,13 +83,21 @@
   */
  private static final DebugTracer TRACER = getTracer();
  // The current entry cache registered in the server
  private EntryCache _entryCache = null;
  // The default entry cache.
  private DefaultEntryCache _defaultEntryCache = null;
  // The default entry cache to use when no entry cache has been configured
  // or when the configured entry cache could not be initialized.
  private EntryCache _defaultEntryCache = null;
  // The entry cache order map sorted by the cache level.
  private static SortedMap<Integer, EntryCache<? extends
    EntryCacheCfg>> cacheOrderMap = new TreeMap<Integer,
    EntryCache<? extends EntryCacheCfg>>();
  // The entry cache name to level map.
  private static HashMap<String, Integer>
    cacheNameToLevelMap = new HashMap<String, Integer>();
  // Global entry cache monitor provider name.
  private static final String
    DEFAULT_ENTRY_CACHE_MONITOR_PROVIDER = "Entry Caches";
  /**
   * Creates a new instance of this entry cache config manager.
@@ -127,8 +143,8 @@
  /**
   * Initializes the configuration associated with the Directory Server entry
   * cache.  This should only be called at Directory Server startup.  If an
   * error occurs, then a message will be logged and the default entry cache
   * will be installed.
   * error occurs, then a message will be logged for each entry cache that is
   * failed to initialize.
   *
   * @throws  ConfigException  If a configuration problem causes the entry
   *                           cache initialization process to fail.
@@ -152,34 +168,61 @@
    rootConfiguration.addEntryCacheAddListener(this);
    rootConfiguration.addEntryCacheDeleteListener(this);
    // If the entry cache configuration is not present then keep the
    // default entry cache already installed.
    if (!rootConfiguration.hasEntryCache())
    // Get the base entry cache configuration entry.
    ConfigEntry entryCacheBase;
    try {
      DN configEntryDN = DN.decode(ConfigConstants.DN_ENTRY_CACHE_BASE);
      entryCacheBase   = DirectoryServer.getConfigEntry(configEntryDN);
    } catch (Exception e) {
      if (debugEnabled())
      {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      logError(WARN_CONFIG_ENTRYCACHE_NO_CONFIG_ENTRY.get());
      return;
    }
    // If the configuration base entry is null, then assume it doesn't exist.
    // At least that entry must exist in the configuration, even if there are
    // no entry cache defined below it.
    if (entryCacheBase == null)
    {
      logError(WARN_CONFIG_ENTRYCACHE_NO_CONFIG_ENTRY.get());
      return;
    }
    // Get the entry cache configuration.
    EntryCacheCfg configuration = rootConfiguration.getEntryCache();
    // At this point, we have a configuration entry. Register a change
    // listener with it so we can be notified of changes to it over time.
    configuration.addChangeListener(this);
    // Initialize the entry cache.
    if (configuration.isEnabled())
    // Initialize every entry cache configured.
    for (String cacheName : rootConfiguration.listEntryCaches())
    {
      // Load the entry cache implementation class and install the entry
      // cache with the server.
      String className = configuration.getJavaClass();
      try
      {
        loadAndInstallEntryCache (className);
      // Get the entry cache configuration.
      EntryCacheCfg configuration = rootConfiguration.getEntryCache(cacheName);
      // At this point, we have a configuration entry. Register a change
      // listener with it so we can be notified of changes to it over time.
      configuration.addChangeListener(this);
      // Check if there is another entry cache installed at the same level.
      if (!cacheOrderMap.isEmpty()) {
        if (cacheOrderMap.containsKey(configuration.getCacheLevel())) {
          // Log error and skip this cache.
          logError(ERR_CONFIG_ENTRYCACHE_CONFIG_LEVEL_NOT_ACCEPTABLE.get(
            String.valueOf(configuration.dn()),
            configuration.getCacheLevel()));
          continue;
        }
      }
      catch (InitializationException ie)
      {
        logError(ie.getMessageObject());
      // Initialize the entry cache.
      if (configuration.isEnabled()) {
        // Load the entry cache implementation class and install the entry
        // cache with the server.
        String className = configuration.getJavaClass();
        try {
          loadAndInstallEntryCache(className, configuration);
        } catch (InitializationException ie) {
          logError(ie.getMessageObject());
        }
      }
    }
  }
@@ -207,6 +250,23 @@
      status = false;
    }
    if (!cacheOrderMap.isEmpty() && !cacheNameToLevelMap.isEmpty() &&
      (cacheNameToLevelMap.get(
       configuration.dn().toNormalizedString()) != null)) {
      int currentCacheLevel = cacheNameToLevelMap.get(
        configuration.dn().toNormalizedString());
      // Check if there any existing cache at the same level.
      if ((currentCacheLevel != configuration.getCacheLevel()) &&
        (cacheOrderMap.containsKey(configuration.getCacheLevel()))) {
        unacceptableReasons.add(
          ERR_CONFIG_ENTRYCACHE_CONFIG_LEVEL_NOT_ACCEPTABLE.get(
            String.valueOf(configuration.dn()),
            configuration.getCacheLevel()));
        status = false;
      }
    }
    return status;
  }
@@ -218,34 +278,64 @@
      EntryCacheCfg configuration
      )
  {
    EntryCache<? extends EntryCacheCfg> entryCache = null;
    // If we this entry cache is already installed and active it
    // should be present in the cache maps, if so use it.
    if (!cacheOrderMap.isEmpty() && !cacheNameToLevelMap.isEmpty() &&
      (cacheNameToLevelMap.get(
       configuration.dn().toNormalizedString()) != null)) {
      int currentCacheLevel = cacheNameToLevelMap.get(
        configuration.dn().toNormalizedString());
      entryCache = cacheOrderMap.get(currentCacheLevel);
      // Check if the existing cache just shifted its level.
      if (currentCacheLevel != configuration.getCacheLevel()) {
        // Update the maps then.
        cacheOrderMap.remove(currentCacheLevel);
        cacheOrderMap.put(configuration.getCacheLevel(), entryCache);
        cacheNameToLevelMap.put(configuration.dn().toNormalizedString(),
          configuration.getCacheLevel());
      }
    }
    // Returned result.
    ConfigChangeResult changeResult = new ConfigChangeResult(
        ResultCode.SUCCESS, false, new ArrayList<Message>()
        );
    // If the new configuration has the entry cache disabled, then install
    // the default entry cache with the server.
    if (! configuration.isEnabled())
    // If an entry cache was installed then remove it.
    if (!configuration.isEnabled())
    {
      DirectoryServer.setEntryCache (_defaultEntryCache);
      // If an entry cache was installed then clean it.
      if (_entryCache != null)
      configuration.getCacheLevel();
      if (entryCache != null)
      {
        _entryCache.finalizeEntryCache();
        _entryCache = null;
        EntryCacheMonitorProvider monitor = entryCache.getEntryCacheMonitor();
        if (monitor != null)
        {
          String instanceName = toLowerCase(monitor.getMonitorInstanceName());
          DirectoryServer.deregisterMonitorProvider(instanceName);
          monitor.finalizeMonitorProvider();
          entryCache.setEntryCacheMonitor(null);
        }
        entryCache.finalizeEntryCache();
        cacheOrderMap.remove(configuration.getCacheLevel());
        entryCache = null;
      }
      return changeResult;
    }
    // Push any changes made to the cache order map.
    _defaultEntryCache.setCacheOrder(cacheOrderMap);
    // At this point, new configuration is enabled...
    // If the current entry cache is already enabled then we don't do
    // anything unless the class has changed in which case we should
    // indicate that administrative action is required.
    String newClassName = configuration.getJavaClass();
    if (_entryCache !=null)
    if ( entryCache != null)
    {
      String curClassName = _entryCache.getClass().getName();
      String curClassName = entryCache.getClass().getName();
      boolean classIsNew = (! newClassName.equals (curClassName));
      if (classIsNew)
      {
@@ -258,7 +348,7 @@
    // Instantiate the new class and initalize it.
    try
    {
      loadAndInstallEntryCache (newClassName);
      loadAndInstallEntryCache (newClassName, configuration);
    }
    catch (InitializationException ie)
    {
@@ -282,6 +372,18 @@
    // returned status -- all is fine by default
    boolean status = true;
    // Check if there is another entry cache installed at the same level.
    if (!cacheOrderMap.isEmpty()) {
      if (cacheOrderMap.containsKey(configuration.getCacheLevel())) {
        unacceptableReasons.add(
          ERR_CONFIG_ENTRYCACHE_CONFIG_LEVEL_NOT_ACCEPTABLE.get(
            String.valueOf(configuration.dn()),
            configuration.getCacheLevel()));
        status = false;
        return status;
      }
    }
    if (configuration.isEnabled())
    {
      // Get the name of the class and make sure we can instantiate it as
@@ -325,7 +427,7 @@
      String className = configuration.getJavaClass();
      try
      {
        loadAndInstallEntryCache (className);
        loadAndInstallEntryCache (className, configuration);
      }
      catch (InitializationException ie)
      {
@@ -361,18 +463,38 @@
      EntryCacheCfg configuration
      )
  {
    EntryCache<? extends EntryCacheCfg> entryCache = null;
    // If we this entry cache is already installed and active it
    // should be present in the current cache order map, use it.
    if (!cacheOrderMap.isEmpty()) {
      entryCache = cacheOrderMap.get(configuration.getCacheLevel());
    }
    // Returned result.
    ConfigChangeResult changeResult = new ConfigChangeResult(
        ResultCode.SUCCESS, false, new ArrayList<Message>()
        );
    // If the entry cache was installed then replace it with the
    // default entry cache, and clean it.
    if (_entryCache != null)
    // If the entry cache was installed then remove it.
    if (entryCache != null)
    {
      DirectoryServer.setEntryCache (_defaultEntryCache);
      _entryCache.finalizeEntryCache();
      _entryCache = null;
      EntryCacheMonitorProvider monitor = entryCache.getEntryCacheMonitor();
      if (monitor != null)
      {
        String instanceName = toLowerCase(monitor.getMonitorInstanceName());
        DirectoryServer.deregisterMonitorProvider(instanceName);
        monitor.finalizeMonitorProvider();
        entryCache.setEntryCacheMonitor(null);
      }
      entryCache.finalizeEntryCache();
      cacheOrderMap.remove(configuration.getCacheLevel());
      cacheNameToLevelMap.remove(configuration.dn().toNormalizedString());
      // Push any changes made to the cache order map.
      _defaultEntryCache.setCacheOrder(cacheOrderMap);
      entryCache = null;
    }
    return changeResult;
@@ -394,34 +516,47 @@
   *                                   to initialize the entry cache.
   */
  private void loadAndInstallEntryCache(
    String        className
    String        className,
    EntryCacheCfg configuration
    )
    throws InitializationException
  {
    EntryCacheCfg configuration;
    // Get the root configuration object.
    ServerManagementContext managementContext =
      ServerManagementContext.getInstance();
    RootCfg rootConfiguration =
      managementContext.getRootConfiguration();
    // Get the entry cache configuration.
    try {
      configuration = rootConfiguration.getEntryCache();
    } catch (ConfigException ce) {
      Message message = ERR_CONFIG_ENTRYCACHE_CANNOT_INITIALIZE_CACHE.get(
        className, (ce.getCause() != null ? ce.getCause().getMessage() :
          stackTraceToSingleLineString(ce)));
      throw new InitializationException(message, ce);
    }
    // Load the entry cache class...
    EntryCache entryCache = loadEntryCache (className, configuration, true);
    EntryCache<? extends EntryCacheCfg> entryCache =
      loadEntryCache (className, configuration, true);
    // ... and install the entry cache in the server.
    DirectoryServer.setEntryCache(entryCache);
    _entryCache = entryCache;
    // Add this entry cache to the current cache config maps.
    cacheOrderMap.put(configuration.getCacheLevel(), entryCache);
    cacheNameToLevelMap.put(configuration.dn().toNormalizedString(),
      configuration.getCacheLevel());
    // Push any changes made to the cache order map.
    _defaultEntryCache.setCacheOrder(cacheOrderMap);
    // Install and register the monitor for this cache.
    EntryCacheMonitorProvider monitor = new EntryCacheMonitorProvider(
        configuration.definition().getUserFriendlyName().toString(),
        entryCache);
    try {
      monitor.initializeMonitorProvider((EntryCacheMonitorProviderCfg)
        rootConfiguration.getMonitorProvider(
        DEFAULT_ENTRY_CACHE_MONITOR_PROVIDER));
    } catch (ConfigException ce) {
      // ConfigException here means that either the entry cache monitor
      // config entry is not present or the monitor is not enabled. In
      // either case that means no monitor provider for this cache.
      return;
    }
    entryCache.setEntryCacheMonitor(monitor);
    DirectoryServer.registerMonitorProvider(monitor);
  }
@@ -448,6 +583,14 @@
    )
    throws InitializationException
  {
    EntryCache entryCache = null;
    // If we this entry cache is already installed and active it
    // should be present in the current cache order map, use it.
    if (!cacheOrderMap.isEmpty()) {
      entryCache = cacheOrderMap.get(configuration.getCacheLevel());
    }
    try
    {
      EntryCacheCfgDefn                   definition;
@@ -461,10 +604,10 @@
      // If there is some entry cache instance already initialized work with
      // it instead of creating a new one unless explicit init is requested.
      if (initialize || (_entryCache == null)) {
      if (initialize || (entryCache == null)) {
        cache = (EntryCache<? extends EntryCacheCfg>) cacheClass.newInstance();
      } else {
        cache = (EntryCache<? extends EntryCacheCfg>) _entryCache;
        cache = (EntryCache<? extends EntryCacheCfg>) entryCache;
      }
      if (initialize)
opends/src/server/org/opends/server/extensions/DefaultEntryCache.java
@@ -22,42 +22,59 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.extensions;
import java.lang.reflect.Method;
import org.opends.messages.Message;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.concurrent.locks.Lock;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.std.server.EntryCacheCfg;
import org.opends.server.api.Backend;
import org.opends.server.api.EntryCache;
import org.opends.server.config.ConfigException;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.Attribute;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.Entry;
import org.opends.server.types.InitializationException;
import org.opends.server.types.LockType;
import org.opends.server.types.ResultCode;
import static org.opends.server.loggers.debug.DebugLogger.*;
/**
 * This class defines the default entry cache that will be used in the server if
 * none is configured.  It does not actually store any entries, so all calls to
 * <CODE>getEntry</CODE> will return <CODE>null</CODE>, and all calls to
 * <CODE>putEntry</CODE> will return immediately without doing anything.
 * This class defines the default entry cache which acts as an arbiter for
 * every entry cache implemenation configured and installed withhin the
 * Directory Server or acts an an empty cache if no implementation specific
 * entry cache is configured.  It does not actually store any entries, so
 * all calls to the entry cache public API are routed to underlying entry
 * cache according to the current configuration order and preferences.
 */
public class DefaultEntryCache
       extends EntryCache<EntryCacheCfg>
       implements ConfigurationChangeListener<EntryCacheCfg>
{
  /**
   * The tracer object for the debug logger.
   */
  private static final DebugTracer TRACER = getTracer();
  // The entry cache order array reflects all currently configured and
  // active entry cache implementations in cache level specific order.
  private static EntryCache<? extends EntryCacheCfg>[] cacheOrder =
    new EntryCache<?>[0];
  /**
   * Creates a new instance of this default entry cache.
@@ -65,11 +82,9 @@
  public DefaultEntryCache()
  {
    super();
  }
  /**
   * {@inheritDoc}
   */
@@ -80,7 +95,6 @@
  }
  /**
   * {@inheritDoc}
   */
@@ -90,25 +104,98 @@
  }
  /**
   * {@inheritDoc}
   */
  public boolean containsEntry(DN entryDN)
  {
    // This implementation does not store any entries.
    if (entryDN == null) {
      return false;
    }
    for (EntryCache entryCache : cacheOrder) {
      if (entryCache.containsEntry(entryDN)) {
        return true;
      }
    }
    return false;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public Entry getEntry(DN entryDN,
                        LockType lockType,
                        List<Lock> lockList)
  {
    Entry entry = null;
    for (EntryCache<? extends EntryCacheCfg> entryCache : cacheOrder) {
      entry = entryCache.getEntry(entryDN, lockType, lockList);
      if (entry != null) {
        break;
      }
    }
    // Indicate global cache miss.
    if ((entry == null) && (cacheOrder.length != 0)) {
      cacheMisses.getAndIncrement();
    }
    return entry;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public Entry getEntry(Backend backend, long entryID,
                                 LockType lockType,
                                 List<Lock> lockList)
  {
    Entry entry = null;
    for (EntryCache<? extends EntryCacheCfg> entryCache : cacheOrder) {
      entry = entryCache.getEntry(backend, entryID, lockType,
          lockList);
      if (entry != null) {
        break;
      }
    }
    // Indicate global cache miss.
    if ((entry == null) && (cacheOrder.length != 0)) {
      cacheMisses.getAndIncrement();
    }
    return entry;
  }
  /**
   * {@inheritDoc}
   */
  public Entry getEntry(DN entryDN)
  {
    // This implementation does not store any entries.
    return null;
    Entry entry = null;
    for (EntryCache entryCache : cacheOrder) {
      entry = entryCache.getEntry(entryDN);
      if (entry != null) {
        break;
      }
    }
    // Indicate global cache miss.
    if ((entry == null) && (cacheOrder.length != 0)) {
      cacheMisses.getAndIncrement();
    }
    return entry;
  }
@@ -118,8 +205,16 @@
   */
  public long getEntryID(DN entryDN)
  {
    // This implementation does not store any entries.
    return -1;
    long entryID = -1;
    for (EntryCache entryCache : cacheOrder) {
      entryID = entryCache.getEntryID(entryDN);
      if (entryID != -1) {
        break;
      }
    }
    return entryID;
  }
@@ -127,10 +222,18 @@
  /**
   * {@inheritDoc}
   */
  protected DN getEntryDN(Backend backend, long entryID)
  public DN getEntryDN(Backend backend, long entryID)
  {
    // This implementation does not store any entries.
    return null;
    DN entryDN = null;
    for (EntryCache entryCache : cacheOrder) {
      entryDN = entryCache.getEntryDN(backend, entryID);
      if (entryDN != null) {
        break;
      }
    }
    return entryDN;
  }
@@ -140,7 +243,14 @@
   */
  public void putEntry(Entry entry, Backend backend, long entryID)
  {
    // This implementation does not store entries.
    for (EntryCache entryCache : cacheOrder) {
      // The first cache in the order which can take this entry
      // gets it.
      if (entryCache.filtersAllowCaching(entry)) {
        entryCache.putEntry(entry, backend, entryID);
        break;
      }
    }
  }
@@ -150,9 +260,15 @@
   */
  public boolean putEntryIfAbsent(Entry entry, Backend backend, long entryID)
  {
    // This implementation does not store entries, so we will never have a
    // conflict.
    return true;
    for (EntryCache entryCache : cacheOrder) {
      // The first cache in the order which can take this entry
      // gets it.
      if (entryCache.filtersAllowCaching(entry)) {
        return entryCache.putEntryIfAbsent(entry, backend, entryID);
      }
    }
    return false;
  }
@@ -162,7 +278,12 @@
   */
  public void removeEntry(DN entryDN)
  {
    // This implementation does not store entries.
    for (EntryCache entryCache : cacheOrder) {
      if (entryCache.containsEntry(entryDN)) {
        entryCache.removeEntry(entryDN);
        break;
      }
    }
  }
@@ -172,7 +293,9 @@
   */
  public void clear()
  {
    // This implementation does not store entries.
    for (EntryCache entryCache : cacheOrder) {
      entryCache.clear();
    }
  }
@@ -182,7 +305,9 @@
   */
  public void clearBackend(Backend backend)
  {
    // This implementation does not store entries.
    for (EntryCache entryCache : cacheOrder) {
      entryCache.clearBackend(backend);
    }
  }
@@ -192,7 +317,9 @@
   */
  public void clearSubtree(DN baseDN)
  {
    // This implementation does not store entries.
    for (EntryCache entryCache : cacheOrder) {
      entryCache.clearSubtree(baseDN);
    }
  }
@@ -202,8 +329,9 @@
   */
  public void handleLowMemory()
  {
    // This implementation does not store entries, so there are no resources
    // that it can free.
    for (EntryCache entryCache : cacheOrder) {
      entryCache.handleLowMemory();
    }
  }
@@ -230,7 +358,6 @@
      )
  {
    // No implementation required.
    ConfigChangeResult changeResult = new ConfigChangeResult(
        ResultCode.SUCCESS, false, new ArrayList<Message>()
        );
@@ -245,9 +372,124 @@
   */
  public ArrayList<Attribute> getMonitorData()
  {
    // This implementation does not store entries,
    // so there is no monitoring data to provide.
    return new ArrayList<Attribute>();
    ArrayList<Attribute> attrs = new ArrayList<Attribute>();
    // The sum of cache hits of all active entry cache
    // implementations.
    Long entryCacheHits = new Long(0);
    // Common for all active entry cache implementations.
    Long entryCacheMisses = new Long(cacheMisses.longValue());
    // The sum of cache counts of all active entry cache
    // implementations.
    Long currentEntryCacheCount = new Long(0);
    for (EntryCache entryCache : cacheOrder) {
      // Get cache hits and counts from every active cache.
      entryCacheHits += entryCache.getCacheHits();
      currentEntryCacheCount += entryCache.getCacheCount();
    }
    try {
      attrs = EntryCacheCommon.getGenericMonitorData(
        entryCacheHits,
        entryCacheMisses,
        null,
        null,
        currentEntryCacheCount,
        null
        );
    } catch (Exception e) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
    }
    return attrs;
  }
  /**
   * {@inheritDoc}
   */
  public Long getCacheCount()
  {
    Long cacheCount = new Long(0);
    for (EntryCache entryCache : cacheOrder) {
      cacheCount += entryCache.getCacheCount();
    }
    return cacheCount;
  }
  /**
   * 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.
   * @return String verbose string representation of the current cache
   *                maps in the following format: dn:id:backend
   *                one cache entry map representation per line
   *                or <CODE>null</CODE> if all maps are empty.
   */
  private String toVerboseString()
  {
    String verboseString = new String();
    StringBuilder sb = new StringBuilder();
    for (EntryCache entryCache : cacheOrder) {
      final Method[] cacheMethods =
        entryCache.getClass().getDeclaredMethods();
      for (int i = 0; i < cacheMethods.length; ++i) {
        if (cacheMethods[i].getName().equals("toVerboseString")) {
          cacheMethods[i].setAccessible(true);
          try {
            Object cacheVerboseString =
              cacheMethods[i].invoke(entryCache, (Object[]) null);
            if (cacheVerboseString != null) {
              sb.append((String) cacheVerboseString);
            }
          } catch (Exception e) {
            if (debugEnabled()) {
              TRACER.debugCaught(DebugLogLevel.ERROR, e);
            }
          }
        }
      }
    }
    verboseString = sb.toString();
    return (verboseString.length() > 0 ? verboseString : null);
  }
  /**
   * Retrieves the current cache order array.
   *
   * @return  The current cache order array.
   */
  public final EntryCache<? extends EntryCacheCfg>[] getCacheOrder()
  {
    return this.cacheOrder;
  }
  /**
   * Sets the current cache order array.
   *
   * @param  cacheOrderMap  The current cache order array.
   */
  public final void setCacheOrder(
    SortedMap<Integer,
    EntryCache<? extends EntryCacheCfg>> cacheOrderMap)
  {
    this.cacheOrder =
      cacheOrderMap.values().toArray(new EntryCache<?>[0]);
  }
}
opends/src/server/org/opends/server/extensions/EntryCacheCommon.java
@@ -381,7 +381,7 @@
  {
    ArrayList<Attribute> attrs = new ArrayList<Attribute>();
    if ((cacheHits != null) && (cacheMisses != null)) {
    if (cacheHits != null) {
      AttributeType hitsAttrType =
        DirectoryServer.getDefaultAttributeType("entryCacheHits");
      LinkedHashSet<AttributeValue> hitsValues =
@@ -390,29 +390,31 @@
        cacheHits.toString()));
      attrs.add(new Attribute(hitsAttrType, "entryCacheHits",
        hitsValues));
      // Cache misses is required to get cache tries and hit ratio.
      if (cacheMisses != null) {
        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 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));
        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) {
opends/src/server/org/opends/server/extensions/FIFOEntryCache.java
@@ -213,6 +213,10 @@
   */
  public boolean containsEntry(DN entryDN)
  {
    if (entryDN == null) {
      return false;
    }
    // Indicate whether the DN map contains the specified DN.
    return dnMap.containsKey(entryDN);
  }
@@ -229,13 +233,13 @@
    if (e == null)
    {
      // Indicate cache miss.
      cacheMisses.set(cacheMisses.incrementAndGet());
      cacheMisses.getAndIncrement();
      return null;
    }
    else
    {
      // Indicate cache hit.
      cacheHits.set(cacheHits.incrementAndGet());
      cacheHits.getAndIncrement();
      return e.getEntry();
    }
  }
@@ -264,7 +268,7 @@
  /**
   * {@inheritDoc}
   */
  protected DN getEntryDN(Backend backend, long entryID)
  public DN getEntryDN(Backend backend, long entryID)
  {
    // Locate specific backend map and return the entry DN by ID.
    HashMap<Long,CacheEntry> backendMap = idMap.get(backend);
@@ -284,11 +288,6 @@
   */
  public void putEntry(Entry entry, Backend backend, long entryID)
  {
    // Check exclude and include filters first.
    if (!filtersAllowCaching(entry)) {
      return;
    }
    // Create the cache entry based on the provided information.
    CacheEntry cacheEntry = new CacheEntry(entry, backend, entryID);
@@ -400,11 +399,6 @@
   */
  public boolean putEntryIfAbsent(Entry entry, Backend backend, long entryID)
  {
    // Check exclude and include filters first.
    if (!filtersAllowCaching(entry)) {
      return true;
    }
    // Create the cache entry based on the provided information.
    CacheEntry cacheEntry = new CacheEntry(entry, backend, entryID);
@@ -1004,7 +998,9 @@
    try {
      attrs = EntryCacheCommon.getGenericMonitorData(
        new Long(cacheHits.longValue()),
        new Long(cacheMisses.longValue()),
        // If cache misses is maintained by default cache
        // get it from there and if not point to itself.
        DirectoryServer.getEntryCache().getCacheMisses(),
        null,
        new Long(maxAllowedMemory),
        new Long(dnMap.size()),
@@ -1024,6 +1020,16 @@
  /**
   * {@inheritDoc}
   */
  public Long getCacheCount()
  {
    return new Long(dnMap.size());
  }
  /**
   * 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,8 +78,8 @@
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.types.Attribute;
import org.opends.server.util.ServerConstants;
import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -607,6 +607,10 @@
   */
  public boolean containsEntry(DN entryDN)
  {
    if (entryDN == null) {
      return false;
    }
    // Indicate whether the DN map contains the specified DN.
    boolean containsEntry = false;
    cacheReadLock.lock();
@@ -631,10 +635,10 @@
      if (dnMap.get(entryDN) != null) {
        entry = getEntryFromDB(entryDN);
        // Indicate cache hit.
        cacheHits.set(cacheHits.incrementAndGet());
        cacheHits.getAndIncrement();
      } else {
        // Indicate cache miss.
        cacheMisses.set(cacheMisses.incrementAndGet());
        cacheMisses.getAndIncrement();
      }
    } finally {
      cacheReadLock.unlock();
@@ -662,7 +666,7 @@
  /**
   * {@inheritDoc}
   */
  protected DN getEntryDN(Backend backend, long entryID) {
  public DN getEntryDN(Backend backend, long entryID) {
    DN entryDN = null;
    cacheReadLock.lock();
@@ -684,13 +688,8 @@
  /**
   * {@inheritDoc}
   */
  public void putEntry(Entry entry, Backend backend, long entryID) {
    // Check exclude and include filters first.
    if (!filtersAllowCaching(entry)) {
      return;
    }
  public void putEntry(Entry entry, Backend backend, long entryID)
  {
    // Obtain a lock on the cache.  If this fails, then don't do anything.
    try {
      if (!cacheWriteLock.tryLock(getLockTimeout(), TimeUnit.MILLISECONDS)) {
@@ -714,11 +713,6 @@
   */
  public boolean putEntryIfAbsent(Entry entry, Backend backend, long entryID)
  {
    // Check exclude and include filters first.
    if (!filtersAllowCaching(entry)) {
      return true;
    }
    try {
      // Obtain a lock on the cache.  If this fails, then don't do anything.
      if (! cacheWriteLock.tryLock(getLockTimeout(), TimeUnit.MILLISECONDS)) {
@@ -1350,7 +1344,9 @@
    try {
      attrs = EntryCacheCommon.getGenericMonitorData(
        new Long(cacheHits.longValue()),
        new Long(cacheMisses.longValue()),
        // If cache misses is maintained by default cache
        // get it from there and if not point to itself.
        DirectoryServer.getEntryCache().getCacheMisses(),
        new Long(entryCacheEnv.getStats(
          entryCacheEnvStatsConfig).getTotalLogSize()),
        new Long(maxAllowedMemory),
@@ -1369,6 +1365,14 @@
  }
  /**
   * {@inheritDoc}
   */
  public Long getCacheCount()
  {
    return new Long(dnMap.size());
  }
  /**
   * Retrieves and decodes the entry with the specified DN from JE backend db.
   *
   * @param  entryDN   The DN of the entry to retrieve.
opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java
@@ -195,6 +195,10 @@
   */
  public boolean containsEntry(DN entryDN)
  {
    if (entryDN == null) {
      return false;
    }
    // Indicate whether the DN map contains the specified DN.
    return dnMap.containsKey(entryDN);
  }
@@ -210,7 +214,7 @@
    if (ref == null)
    {
      // Indicate cache miss.
      cacheMisses.set(cacheMisses.incrementAndGet());
      cacheMisses.getAndIncrement();
      return null;
    }
    else
@@ -219,13 +223,13 @@
      if (cacheEntry == null)
      {
        // Indicate cache miss.
        cacheMisses.set(cacheMisses.incrementAndGet());
        cacheMisses.getAndIncrement();
        return null;
      }
      else
      {
        // Indicate cache hit.
        cacheHits.set(cacheHits.incrementAndGet());
        cacheHits.getAndIncrement();
        return cacheEntry.getEntry();
      }
    }
@@ -262,7 +266,7 @@
  /**
   * {@inheritDoc}
   */
  protected DN getEntryDN(Backend backend, long entryID)
  public DN getEntryDN(Backend backend, long entryID)
  {
    // Locate specific backend map and return the entry DN by ID.
    ConcurrentHashMap<Long,SoftReference<CacheEntry>>
@@ -286,11 +290,6 @@
   */
  public void putEntry(Entry entry, Backend backend, long entryID)
  {
    // Check exclude and include filters first.
    if (!filtersAllowCaching(entry)) {
      return;
    }
    // Create the cache entry based on the provided information.
    CacheEntry cacheEntry = new CacheEntry(entry, backend, entryID);
    SoftReference<CacheEntry> ref =
@@ -327,11 +326,6 @@
  public boolean putEntryIfAbsent(Entry entry, Backend backend,
                                  long entryID)
  {
    // Check exclude and include filters first.
    if (!filtersAllowCaching(entry)) {
      return true;
    }
    // See if the entry already exists.  If so, then return false.
    if (dnMap.containsKey(entry.getDN()))
    {
@@ -667,7 +661,9 @@
    try {
      attrs = EntryCacheCommon.getGenericMonitorData(
        new Long(cacheHits.longValue()),
        new Long(cacheMisses.longValue()),
        // If cache misses is maintained by default cache
        // get it from there and if not point to itself.
        DirectoryServer.getEntryCache().getCacheMisses(),
        null,
        null,
        new Long(dnMap.size()),
@@ -685,6 +681,16 @@
  /**
   * {@inheritDoc}
   */
  public Long getCacheCount()
  {
    return new Long(dnMap.size());
  }
  /**
   * 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
@@ -27,21 +27,20 @@
package org.opends.server.monitors;
import java.util.ArrayList;
import org.opends.messages.Message;
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.ConfigConstants;
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.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.messages.ConfigMessages.*;
/**
 * This class defines a Directory Server monitor provider that can be used to
@@ -51,29 +50,73 @@
public class EntryCacheMonitorProvider
       extends MonitorProvider<EntryCacheMonitorProviderCfg>
{
  /**
   * The tracer object for the debug logger.
   */
  private static final DebugTracer TRACER = getTracer();
  // The name for this monitor.
  private String monitorName;
  // The entry cache common name.
  private String entryCacheName;
  // The entry cache with which this monitor is associated.
  private EntryCache<? extends EntryCacheCfg> entryCache;
  // Global entry cache monitor configuration.
  private static EntryCacheMonitorProviderCfg monitorConfiguration;
  /**
   * Creates an instance of this monitor provider.
   * Creates default instance of this monitor provider.
   */
  public EntryCacheMonitorProvider()
  {
    super("Entry Cache Monitor Provider");
    super("Entry Caches Monitor Provider");
    this.entryCacheName = "Entry Caches";
    this.entryCache = (EntryCache<? extends EntryCacheCfg>)
      DirectoryServer.getEntryCache();
  }
    // No initialization should be performed here.
  /**
   * Creates implementation specific instance of this monitor provider.
   *
   * @param  entryCacheName  The name to use for this monitor provider.
   * @param  entryCache      The entry cache to associate this monitor
   *                         provider with.
   */
  public EntryCacheMonitorProvider(
    String entryCacheName,
    EntryCache<? extends EntryCacheCfg> entryCache)
  {
    super(entryCacheName + " Entry Cache Monitor Provider");
    this.entryCacheName = entryCacheName;
    this.entryCache = entryCache;
  }
  /**
   * {@inheritDoc}
   */
  public void initializeMonitorProvider(
                   EntryCacheMonitorProviderCfg configuration)
         throws ConfigException, InitializationException
    EntryCacheMonitorProviderCfg configuration)
    throws ConfigException
  {
    // No initialization is required.
    monitorName = entryCacheName;
    if (configuration != null) {
      monitorConfiguration = configuration;
    }
    if (monitorConfiguration == null) {
      Message message =
        INFO_WARN_CONFIG_ENTRYCACHE_NO_MONITOR_CONFIG_ENTRY.get(
        ConfigConstants.DN_ENTRY_CACHE_MONITOR_CONFIG,
        monitorName);
      logError(message);
      throw new ConfigException(message);
    }
    if (!monitorConfiguration.isEnabled()) {
      Message message =
        INFO_WARN_CONFIG_ENTRYCACHE_MONITOR_CONFIG_DISABLED.get(
        ConfigConstants.DN_ENTRY_CACHE_MONITOR_CONFIG,
        monitorName);
      logError(message);
      throw new ConfigException(message);
    }
  }
  /**
@@ -81,7 +124,7 @@
   */
  public String getMonitorInstanceName()
  {
    return "Entry Cache";
    return monitorName;
  }
  /**
@@ -108,35 +151,12 @@
  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();
    if ((entryCache != null) &&
        (monitorConfiguration != null) &&
        (monitorConfiguration.isEnabled())) {
      // Get monitor data from the cache.
      attrs = entryCache.getMonitorData();
    }
    return attrs;
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DefaultEntryCacheTestCase.java
@@ -22,315 +22,507 @@
 * CDDL HEADER END
 *
 *
 *      Portions Copyright 2006-2007 Sun Microsystems, Inc.
 *      Portions Copyright 2007 Sun Microsystems, Inc.
 */
package org.opends.server.extensions;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.concurrent.locks.Lock;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import java.util.SortedMap;
import java.util.TreeMap;
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.server.AdminTestCaseUtils;
import org.testng.annotations.BeforeClass;
import org.opends.server.admin.std.meta.*;
import org.opends.server.admin.std.server.EntryCacheCfg;
import org.opends.server.admin.std.server.FileSystemEntryCacheCfg;
import org.opends.server.api.Backend;
import org.opends.server.api.EntryCache;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.LockType;
import org.opends.server.util.ServerConstants;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
/**
 * A set of test cases for the default entry cache.
 * A set of test cases for default entry cache implementation.
 */
@Test(groups = "entrycache", sequential=true)
public class DefaultEntryCacheTestCase
       extends ExtensionsTestCase
       extends CommonEntryCacheTestCase
{
  // Entry cache implementations participating in this test.
  private EntryCache softRefCache = null;
  private EntryCache fifoCache = null;
  private EntryCache fsCache = null;
  // ... and their configuration entries.
  Entry cacheSoftReferenceConfigEntry = null;
  Entry cacheFIFOConfigEntry = null;
  Entry cacheFSConfigEntry = null;
  // The entry cache order map sorted by the cache level.
  private SortedMap<Integer, EntryCache<? extends EntryCacheCfg>>
    cacheOrderMap = new TreeMap<Integer,
    EntryCache<? extends EntryCacheCfg>>();
  // Dummy test entries for each participating implementation.
  private ArrayList<Entry> testSoftRefEntriesList = null;
  private ArrayList<Entry> testFIFOEntriesList = null;
  private ArrayList<Entry> testFSEntriesList = null;
  /**
   * Ensures that the Directory Server is running.
   * Initialize the entry cache test.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @BeforeClass()
  public void startServer()
  @SuppressWarnings("unchecked")
  public void entryCacheTestInit()
         throws Exception
  {
    // Ensure that the server is running.
    TestCaseUtils.startServer();
    // Get default cache.
    super.cache = DirectoryServer.getEntryCache();
    // Configure and initialize all entry cache implementations.
    softRefCache = new SoftReferenceEntryCache();
    cacheSoftReferenceConfigEntry = TestCaseUtils.makeEntry(
      "dn: cn=Soft Reference,cn=Entry Caches,cn=config",
      "objectClass: ds-cfg-soft-reference-entry-cache",
      "objectClass: ds-cfg-entry-cache",
      "objectClass: top",
      "cn: Soft Reference",
      "ds-cfg-cache-level: 1",
      "ds-cfg-java-class: " +
      "org.opends.server.extensions.SoftReferenceEntryCache",
      "ds-cfg-enabled: true",
      "ds-cfg-include-filter: uid=softref*",
      "ds-cfg-include-filter: uid=test1*",
      "ds-cfg-exclude-filter: uid=test0*");
    softRefCache.initializeEntryCache(AdminTestCaseUtils.getConfiguration(
      EntryCacheCfgDefn.getInstance(), cacheSoftReferenceConfigEntry));
    cacheOrderMap.put(1, softRefCache);
    fifoCache = new FIFOEntryCache();
    cacheFIFOConfigEntry = TestCaseUtils.makeEntry(
      "dn: cn=FIFO,cn=Entry Caches,cn=config",
      "objectClass: ds-cfg-fifo-entry-cache",
      "objectClass: ds-cfg-entry-cache",
      "objectClass: top",
      "cn: FIFO",
      "ds-cfg-cache-level: 2",
      "ds-cfg-java-class: org.opends.server.extensions.FIFOEntryCache",
      "ds-cfg-enabled: true",
      "ds-cfg-include-filter: uid=fifo*",
      "ds-cfg-include-filter: uid=test2*",
      "ds-cfg-exclude-filter: uid=test0*");
    fifoCache.initializeEntryCache(AdminTestCaseUtils.getConfiguration(
      EntryCacheCfgDefn.getInstance(), cacheFIFOConfigEntry));
    cacheOrderMap.put(2, fifoCache);
    fsCache = new FileSystemEntryCache();
    cacheFSConfigEntry = TestCaseUtils.makeEntry(
      "dn: cn=File System,cn=Entry Caches,cn=config",
      "objectClass: ds-cfg-file-system-entry-cache",
      "objectClass: ds-cfg-entry-cache",
      "objectClass: top",
      "cn: File System",
      "ds-cfg-cache-level: 3",
      "ds-cfg-java-class: " +
      "org.opends.server.extensions.FileSystemEntryCache",
      "ds-cfg-enabled: true",
      "ds-cfg-include-filter: uid=fs*",
      "ds-cfg-include-filter: uid=test3*",
      "ds-cfg-include-filter: uid=test0*");
    fsCache.initializeEntryCache(AdminTestCaseUtils.getConfiguration(
      EntryCacheCfgDefn.getInstance(), cacheFSConfigEntry));
    cacheOrderMap.put(3, fsCache);
    // Plug all cache implementations into default entry cache.
    final Method[] defaultCacheMethods =
        super.cache.getClass().getDeclaredMethods();
    for (int i = 0; i < defaultCacheMethods.length; ++i) {
      if (defaultCacheMethods[i].getName().equals("setCacheOrder")) {
        defaultCacheMethods[i].setAccessible(true);
        Object arglist[] = new Object[] { cacheOrderMap };
        defaultCacheMethods[i].invoke(cache, arglist);
      }
    }
    // Make some dummy test entries.
    super.testEntriesList = new ArrayList<Entry>(super.NUMTESTENTRIES);
    for(int i = 0; i < super.NUMTESTENTRIES; i++ ) {
      super.testEntriesList.add(TestCaseUtils.makeEntry(
        "dn: uid=test" + Integer.toString(i) + ".user" + Integer.toString(i)
         + ",ou=test" + Integer.toString(i) + ",o=test",
        "objectClass: person",
        "objectClass: inetorgperson",
        "objectClass: top",
        "objectClass: organizationalperson",
        "postalAddress: somewhere in Testville" + Integer.toString(i),
        "street: Under Construction Street" + Integer.toString(i),
        "l: Testcounty" + Integer.toString(i),
        "st: Teststate" + Integer.toString(i),
        "telephoneNumber: +878 8378 8378" + Integer.toString(i),
        "mobile: +878 8378 8378" + Integer.toString(i),
        "homePhone: +878 8378 8378" + Integer.toString(i),
        "pager: +878 8378 8378" + Integer.toString(i),
        "mail: test" + Integer.toString(i) + ".user" + Integer.toString(i)
         + "@testdomain.net",
        "postalCode: 8378" + Integer.toString(i),
        "userPassword: testpassword" + Integer.toString(i),
        "description: description for Test" + Integer.toString(i) + "User"
         + Integer.toString(i),
        "cn: Test" + Integer.toString(i) + "User" + Integer.toString(i),
        "sn: User" + Integer.toString(i),
        "givenName: Test" + Integer.toString(i),
        "initials: TST" + Integer.toString(i),
        "employeeNumber: 8378" + Integer.toString(i),
        "uid: test" + Integer.toString(i) + ".user" + Integer.toString(i))
      );
    }
    testSoftRefEntriesList = new ArrayList<Entry>(super.NUMTESTENTRIES);
    for(int i = 0; i < super.NUMTESTENTRIES; i++ ) {
      testSoftRefEntriesList.add(TestCaseUtils.makeEntry(
        "dn: uid=softref" + Integer.toString(i) + ".user" + Integer.toString(i)
         + ",ou=test" + Integer.toString(i) + ",o=test",
        "objectClass: person",
        "objectClass: inetorgperson",
        "objectClass: top",
        "objectClass: organizationalperson",
        "uid: softref" + Integer.toString(i) + ".user" + Integer.toString(i))
      );
    }
    testFIFOEntriesList = new ArrayList<Entry>(super.NUMTESTENTRIES);
    for(int i = 0; i < super.NUMTESTENTRIES; i++ ) {
      testFIFOEntriesList.add(TestCaseUtils.makeEntry(
        "dn: uid=fifo" + Integer.toString(i) + ".user" + Integer.toString(i)
         + ",ou=test" + Integer.toString(i) + ",o=test",
        "objectClass: person",
        "objectClass: inetorgperson",
        "objectClass: top",
        "objectClass: organizationalperson",
        "uid: fifo" + Integer.toString(i) + ".user" + Integer.toString(i))
      );
    }
    testFSEntriesList = new ArrayList<Entry>(super.NUMTESTENTRIES);
    for(int i = 0; i < super.NUMTESTENTRIES; i++ ) {
      testFSEntriesList.add(TestCaseUtils.makeEntry(
        "dn: uid=fs" + Integer.toString(i) + ".user" + Integer.toString(i)
         + ",ou=test" + Integer.toString(i) + ",o=test",
        "objectClass: person",
        "objectClass: inetorgperson",
        "objectClass: top",
        "objectClass: organizationalperson",
        "uid: fs" + Integer.toString(i) + ".user" + Integer.toString(i))
      );
    }
    // Force GC to make sure we have enough memory for
    // the cache capping constraints to work properly.
    System.gc();
  }
  /**
   * Tests the process of creating, initializing, and finalizing the cache.
   * Finalize the entry cache test.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void testInitializeAndFinalizeCache()
  @AfterClass()
  public void entryCacheTestFini()
         throws Exception
  {
    DefaultEntryCache cache = new DefaultEntryCache();
    cache.initializeEntryCache(null);
    cache.finalizeEntryCache();
    // Finilize all entry cache implementations.
    for (EntryCache entryCache : cacheOrderMap.values()) {
      entryCache.finalizeEntryCache();
    }
    // Remove default FS cache JE environment.
    FileSystemEntryCacheCfg config = (FileSystemEntryCacheCfg)
      AdminTestCaseUtils.getConfiguration(EntryCacheCfgDefn.getInstance(),
      cacheFSConfigEntry);
    TestCaseUtils.deleteDirectory(new File(config.getCacheDirectory()));
  }
  /**
   * Tests the <CODE>containsEntry</CODE> method.
   *
   * @throws  Exception  If an unexpected problem occurs.
   * {@inheritDoc}
   */
  @Test()
  @Override
  public void testContainsEntry()
         throws Exception
  {
    DefaultEntryCache cache = new DefaultEntryCache();
    cache.initializeEntryCache(null);
    assertFalse(cache.containsEntry(DN.decode("uid=test,o=test")));
    cache.finalizeEntryCache();
    super.testContainsEntry();
  }
  /**
   * Tests the first <CODE>getEntry</CODE> method, which takes a single DN
   * argument.
   *
   * @throws  Exception  If an unexpected problem occurs.
   * {@inheritDoc}
   */
  @Test()
  @Override
  public void testGetEntry1()
         throws Exception
  {
    DefaultEntryCache cache = new DefaultEntryCache();
    cache.initializeEntryCache(null);
    assertNull(cache.getEntry(DN.decode("uid=test,o=test")));
    cache.finalizeEntryCache();
    super.testGetEntry1();
  }
  /**
   * Tests the second <CODE>getEntry</CODE> method, which takes a DN, lock type,
   * and list attributes.
   *
   * @throws  Exception  If an unexpected problem occurs.
   * {@inheritDoc}
   */
  @Test()
  @Override
  public void testGetEntry2()
         throws Exception
  {
    DefaultEntryCache cache = new DefaultEntryCache();
    cache.initializeEntryCache(null);
    assertNull(cache.getEntry(DN.decode("uid=test,o=test"), LockType.NONE,
                              new ArrayList<Lock>()));
    cache.finalizeEntryCache();
    super.testGetEntry2();
  }
  /**
   * Tests the third <CODE>getEntry</CODE> method, which takes a backend, entry
   * ID, lock type, and list attributes.
   *
   * @throws  Exception  If an unexpected problem occurs.
   * {@inheritDoc}
   */
  @Test()
  @Override
  public void testGetEntry3()
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
    DefaultEntryCache cache = new DefaultEntryCache();
    cache.initializeEntryCache(null);
    assertNull(cache.getEntry(b, -1, LockType.NONE, new ArrayList<Lock>()));
    cache.finalizeEntryCache();
    super.testGetEntry3();
  }
  /**
   * Tests the <CODE>getEntryID</CODE> method.
   *
   * @throws  Exception  If an unexpected problem occurs.
   * {@inheritDoc}
   */
  @Test()
  @Override
  public void testGetEntryID()
         throws Exception
  {
    DefaultEntryCache cache = new DefaultEntryCache();
    cache.initializeEntryCache(null);
    assertEquals(cache.getEntryID(DN.decode("uid=test,o=test")), -1);
    cache.finalizeEntryCache();
    super.testGetEntryID();
  }
  /**
   * Tests the <CODE>putEntry</CODE> method.
   *
   * @throws  Exception  If an unexpected problem occurs.
   * {@inheritDoc}
   */
  @Test()
  @Override
  public void testPutEntry()
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
    Entry e = TestCaseUtils.makeEntry("dn: o=test",
                                      "objectClass: top",
                                      "objectClass: organization",
                                      "o: test");
    DefaultEntryCache cache = new DefaultEntryCache();
    cache.initializeEntryCache(null);
    cache.putEntry(e, b, 1);
    cache.finalizeEntryCache();
    super.testPutEntry();
  }
  /**
   * Tests the <CODE>putEntryIfAbsent</CODE> method.
   *
   * @throws  Exception  If an unexpected problem occurs.
   * {@inheritDoc}
   */
  @Test()
  @Override
  public void testPutEntryIfAbsent()
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
    Entry e = TestCaseUtils.makeEntry("dn: o=test",
                                      "objectClass: top",
                                      "objectClass: organization",
                                      "o: test");
    DefaultEntryCache cache = new DefaultEntryCache();
    cache.initializeEntryCache(null);
    assertTrue(cache.putEntryIfAbsent(e, b, 1));
    cache.finalizeEntryCache();
    super.testPutEntryIfAbsent();
  }
  /**
   * Tests the <CODE>removeEntry</CODE> method.
   *
   * @throws  Exception  If an unexpected problem occurs.
   * {@inheritDoc}
   */
  @Test()
  @Override
  public void testRemoveEntry()
         throws Exception
  {
    DefaultEntryCache cache = new DefaultEntryCache();
    cache.initializeEntryCache(null);
    cache.removeEntry(DN.decode("uid=test,o=test"));
    cache.finalizeEntryCache();
    super.testRemoveEntry();
  }
  /**
   * Tests the <CODE>clear</CODE> method.
   *
   * @throws  Exception  If an unexpected problem occurs.
   * {@inheritDoc}
   */
  @Test()
  @Override
  public void testClear()
         throws Exception
  {
    DefaultEntryCache cache = new DefaultEntryCache();
    cache.initializeEntryCache(null);
    cache.clear();
    cache.finalizeEntryCache();
    super.testClear();
  }
  /**
   * Tests the <CODE>clearBackend</CODE> method.
   *
   * @throws  Exception  If an unexpected problem occurs.
   * {@inheritDoc}
   */
  @Test()
  @Override
  public void testClearBackend()
         throws Exception
  {
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
    DefaultEntryCache cache = new DefaultEntryCache();
    cache.initializeEntryCache(null);
    cache.clearBackend(b);
    cache.finalizeEntryCache();
    super.testClearBackend();
  }
  /**
   * Tests the <CODE>clearSubtree</CODE> method.
   *
   * @throws  Exception  If an unexpected problem occurs.
   * {@inheritDoc}
   */
  @Test()
  @Override
  public void testClearSubtree()
         throws Exception
  {
    DefaultEntryCache cache = new DefaultEntryCache();
    cache.initializeEntryCache(null);
    cache.clearSubtree(DN.decode("o=test"));
    cache.finalizeEntryCache();
    super.testClearSubtree();
  }
  /**
   * Tests the <CODE>handleLowMemory</CODE> method.
   * {@inheritDoc}
   */
  @Test()
  @Override
  public void testHandleLowMemory()
         throws Exception
  {
    super.testHandleLowMemory();
  }
  /**
   * Tests the entry cache level functionality where each set
   * of entries land on a specific cache level by some form
   * of selection criteria such as include / exclude filters.
   *
   * @throws  Exception  If an unexpected problem occurs.
   */
  @Test()
  public void handleLowMemory()
  public void testCacheLevels()
         throws Exception
  {
    DefaultEntryCache cache = new DefaultEntryCache();
    cache.initializeEntryCache(null);
    assertNull(toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      toVerboseString());
    cache.handleLowMemory();
    TestCaseUtils.initializeTestBackend(false);
    Backend b = DirectoryServer.getBackend(DN.decode("o=test"));
    cache.finalizeEntryCache();
    // Spread test entries among all cache levels via default cache.
    for (int i = 0; i < NUMTESTENTRIES; i++) {
      super.cache.putEntry(testSoftRefEntriesList.get(i), b, i);
      super.cache.putEntry(testFIFOEntriesList.get(i), b, i);
      super.cache.putEntry(testFSEntriesList.get(i), b, i);
    }
    // Ensure all test entries are available via default cache.
    for (int i = 0; i < NUMTESTENTRIES; i++) {
      assertNotNull(super.cache.getEntry(
        testSoftRefEntriesList.get(0).getDN()),
        "Expected to find " +
        testSoftRefEntriesList.get(0).getDN().toString() +
        " in the cache.  Cache contents:" +
        ServerConstants.EOL + toVerboseString());
      assertNotNull(super.cache.getEntry(
        testFIFOEntriesList.get(0).getDN()),
        "Expected to find " +
        testFIFOEntriesList.get(0).getDN().toString() +
        " in the cache.  Cache contents:" +
        ServerConstants.EOL + toVerboseString());
      assertNotNull(super.cache.getEntry(
        testFSEntriesList.get(0).getDN()),
        "Expected to find " +
        testFSEntriesList.get(0).getDN().toString() +
        " in the cache.  Cache contents:" +
        ServerConstants.EOL + toVerboseString());
    }
    // Ensure all test entries landed on their levels.
    for (int i = 0; i < NUMTESTENTRIES; i++) {
      assertNotNull(softRefCache.getEntry(
        testSoftRefEntriesList.get(0).getDN()),
        "Expected to find " +
        testSoftRefEntriesList.get(0).getDN().toString() +
        " in the cache.  Cache contents:" +
        ServerConstants.EOL + toVerboseString());
      assertNotNull(fifoCache.getEntry(
        testFIFOEntriesList.get(0).getDN()),
        "Expected to find " +
        testFIFOEntriesList.get(0).getDN().toString() +
        " in the cache.  Cache contents:" +
        ServerConstants.EOL + toVerboseString());
      assertNotNull(fsCache.getEntry(
        testFSEntriesList.get(0).getDN()),
        "Expected to find " +
        testFSEntriesList.get(0).getDN().toString() +
        " in the cache.  Cache contents:" +
        ServerConstants.EOL + toVerboseString());
    }
    // Clear the cache so that other tests can start from scratch.
    super.cache.clear();
  }
  @BeforeGroups(groups = "testDefaultCacheConcurrency")
  public void cacheConcurrencySetup()
         throws Exception
  {
    assertNull(super.toVerboseString(),
      "Expected empty cache.  " + "Cache contents:" + ServerConstants.EOL +
      super.toVerboseString());
  }
  @AfterGroups(groups = "testDefaultCacheConcurrency")
  public void cacheConcurrencyCleanup()
         throws Exception
  {
    // Clear the cache so that other tests can start from scratch.
    super.cache.clear();
  }
  /**
   * {@inheritDoc}
   */
  @Test(groups = { "slow", "testDefaultCacheConcurrency" },
        threadPoolSize = 10,
        invocationCount = 10,
        timeOut = 60000)
  @Override
  public void testCacheConcurrency()
         throws Exception
  {
    super.testCacheConcurrency();
  }
}
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FIFOEntryCacheTestCase.java
@@ -68,11 +68,12 @@
    // Configure this entry cache.
    Entry cacheConfigEntry = TestCaseUtils.makeEntry(
      "dn: cn=Entry Cache,cn=config",
      "dn: cn=FIFO,cn=Entry Caches,cn=config",
      "objectClass: ds-cfg-fifo-entry-cache",
      "objectClass: ds-cfg-entry-cache",
      "objectClass: top",
      "cn: Entry Cache",
      "cn: FIFO",
      "ds-cfg-cache-level: 1",
      "ds-cfg-java-class: org.opends.server.extensions.FIFOEntryCache",
      "ds-cfg-enabled: true",
      "ds-cfg-max-entries: " + Integer.toString(super.MAXENTRIES));
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FileSystemEntryCacheTestCase.java
@@ -40,9 +40,7 @@
import org.opends.server.types.Attribute;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.OperatingSystem;
import org.opends.server.util.ServerConstants;
import org.opends.server.util.StaticUtils;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups;
@@ -200,11 +198,12 @@
    // Configure this entry cache.
    cacheConfigEntry = TestCaseUtils.makeEntry(
      "dn: cn=Entry Cache,cn=config",
      "dn: cn=File System,cn=Entry Caches,cn=config",
      "objectClass: ds-cfg-file-system-entry-cache",
      "objectClass: ds-cfg-entry-cache",
      "objectClass: top",
      "cn: Entry Cache",
      "cn: File System",
      "ds-cfg-cache-level: 1",
      "ds-cfg-java-class: " +
      "org.opends.server.extensions.FileSystemEntryCache",
      "ds-cfg-enabled: true",
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SoftReferenceEntryCacheTestCase.java
@@ -65,11 +65,12 @@
    // Configure this entry cache.
    Entry cacheConfigEntry = TestCaseUtils.makeEntry(
      "dn: cn=Entry Cache,cn=config",
      "dn: cn=Soft Reference,cn=Entry Caches,cn=config",
      "objectClass: ds-cfg-soft-reference-entry-cache",
      "objectClass: ds-cfg-entry-cache",
      "objectClass: top",
      "cn: Entry Cache",
      "cn: Soft Reference",
      "ds-cfg-cache-level: 1",
      "ds-cfg-java-class: " +
      "org.opends.server.extensions.SoftReferenceEntryCache",
      "ds-cfg-enabled: true");