From 4a58a441a5b81031a86bc01b630b9e19894f4d80 Mon Sep 17 00:00:00 2001
From: abobrov <abobrov@localhost>
Date: Sun, 02 Dec 2007 17:54:15 +0000
Subject: [PATCH] - [Issue 2007] generic mechanism for using mulitple caches. - [Issue 2049] dsconfig is unable to configure the entry cache.
---
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/FileSystemEntryCacheConfiguration.xml | 2
opendj-sdk/opends/src/server/org/opends/server/extensions/DefaultEntryCache.java | 306 ++++++++++-
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SoftReferenceEntryCacheTestCase.java | 5
opendj-sdk/opends/src/server/org/opends/server/config/ConfigConstants.java | 13
opendj-sdk/opends/src/server/org/opends/server/extensions/FIFOEntryCache.java | 34
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FileSystemEntryCacheTestCase.java | 7
opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java | 38
opendj-sdk/opends/src/messages/messages/config.properties | 16
opendj-sdk/opends/src/server/org/opends/server/extensions/EntryCacheCommon.java | 48
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/EntryCacheConfiguration.xml | 15
opendj-sdk/opends/src/server/org/opends/server/core/EntryCacheConfigManager.java | 279 ++++++++--
opendj-sdk/opends/src/server/org/opends/server/api/EntryCache.java | 85 ++
opendj-sdk/opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java | 36
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DefaultEntryCacheTestCase.java | 492 +++++++++++++-----
opendj-sdk/opends/resource/config/config.ldif | 34 +
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FIFOEntryCacheTestCase.java | 5
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/EntryCacheMonitorProviderConfiguration.xml | 2
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml | 5
opendj-sdk/opends/src/server/org/opends/server/monitors/EntryCacheMonitorProvider.java | 108 ++-
opendj-sdk/opends/resource/schema/02-config.ldif | 8
20 files changed, 1,139 insertions(+), 399 deletions(-)
diff --git a/opendj-sdk/opends/resource/config/config.ldif b/opendj-sdk/opends/resource/config/config.ldif
index ffb4bd3..7729c7d 100644
--- a/opendj-sdk/opends/resource/config/config.ldif
+++ b/opendj-sdk/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
diff --git a/opendj-sdk/opends/resource/schema/02-config.ldif b/opendj-sdk/opends/resource/schema/02-config.ldif
index 07e1710..cfc6b9f 100644
--- a/opendj-sdk/opends/resource/schema/02-config.ldif
+++ b/opendj-sdk/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'
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/EntryCacheConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/EntryCacheConfiguration.xml
index 39546c8..84e34ca 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/EntryCacheConfiguration.xml
+++ b/opendj-sdk/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>
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/EntryCacheMonitorProviderConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/EntryCacheMonitorProviderConfiguration.xml
index 73eec0b..28ae32e 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/EntryCacheMonitorProviderConfiguration.xml
+++ b/opendj-sdk/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">
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/FileSystemEntryCacheConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/FileSystemEntryCacheConfiguration.xml
index 4ad5179..b9c5c1c 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/FileSystemEntryCacheConfiguration.xml
+++ b/opendj-sdk/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.
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
index bcb4b58..5adcdb1 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
+++ b/opendj-sdk/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>
diff --git a/opendj-sdk/opends/src/messages/messages/config.properties b/opendj-sdk/opends/src/messages/messages/config.properties
index e3b1b98..104a964 100644
--- a/opendj-sdk/opends/src/messages/messages/config.properties
+++ b/opendj-sdk/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 \
diff --git a/opendj-sdk/opends/src/server/org/opends/server/api/EntryCache.java b/opendj-sdk/opends/src/server/org/opends/server/api/EntryCache.java
index 75dae36..aa60026 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/api/EntryCache.java
+++ b/opendj-sdk/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.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/config/ConfigConstants.java b/opendj-sdk/opends/src/server/org/opends/server/config/ConfigConstants.java
index 5b61c05..2d3ebcd 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/config/ConfigConstants.java
+++ b/opendj-sdk/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.
*/
diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/EntryCacheConfigManager.java b/opendj-sdk/opends/src/server/org/opends/server/core/EntryCacheConfigManager.java
index 710b430..b0eede9 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/EntryCacheConfigManager.java
+++ b/opendj-sdk/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)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/DefaultEntryCache.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/DefaultEntryCache.java
index 4ba492d..c7912cf 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/DefaultEntryCache.java
+++ b/opendj-sdk/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]);
}
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/EntryCacheCommon.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/EntryCacheCommon.java
index eac3bbb..49edcdf 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/EntryCacheCommon.java
+++ b/opendj-sdk/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) {
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/FIFOEntryCache.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/FIFOEntryCache.java
index 63fb87e..2508aba 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/FIFOEntryCache.java
+++ b/opendj-sdk/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.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java
index 991f644..4928f94 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java
+++ b/opendj-sdk/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.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java
index f35c776..209b180 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java
+++ b/opendj-sdk/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.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/monitors/EntryCacheMonitorProvider.java b/opendj-sdk/opends/src/server/org/opends/server/monitors/EntryCacheMonitorProvider.java
index 8cba70c..bdef0f1 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/monitors/EntryCacheMonitorProvider.java
+++ b/opendj-sdk/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;
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DefaultEntryCacheTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DefaultEntryCacheTestCase.java
index ef4e54d..53c5a3e 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/DefaultEntryCacheTestCase.java
+++ b/opendj-sdk/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();
}
}
-
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FIFOEntryCacheTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FIFOEntryCacheTestCase.java
index 408a864..9813778 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FIFOEntryCacheTestCase.java
+++ b/opendj-sdk/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));
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FileSystemEntryCacheTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FileSystemEntryCacheTestCase.java
index 22ebcc6..cf80800 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/FileSystemEntryCacheTestCase.java
+++ b/opendj-sdk/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",
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SoftReferenceEntryCacheTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SoftReferenceEntryCacheTestCase.java
index 612d0be..74e4ba9 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/SoftReferenceEntryCacheTestCase.java
+++ b/opendj-sdk/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");
--
Gitblit v1.10.0