From 17026ece22afcf33f2a522f83de6c599b6184c67 Mon Sep 17 00:00:00 2001
From: abobrov <abobrov@localhost>
Date: Sun, 02 Sep 2007 13:05:17 +0000
Subject: [PATCH] - [Issue 1481] Ability to set any JE property in config.ldif - [Issue 2031] provide core JE configurable attributes for FileSystemEntryCache - fixes to entry cache config manager for proper configuration, re-configuration, error reporting.
---
opendj-sdk/opends/src/messages/messages/extension.properties | 29 +-
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/FileSystemEntryCacheConfiguration.xml | 35 ++
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JEBackendConfiguration.xml | 30 ++
opendj-sdk/opends/src/server/org/opends/server/extensions/FIFOEntryCache.java | 40 ++
opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java | 294 +++++++++++++-------
opendj-sdk/opends/src/messages/messages/config.properties | 15 +
opendj-sdk/opends/src/server/org/opends/server/extensions/EntryCacheCommon.java | 70 ++++
opendj-sdk/opends/src/server/org/opends/server/core/EntryCacheConfigManager.java | 116 ++++---
opendj-sdk/opends/src/server/org/opends/server/extensions/SoftReferenceEntryCache.java | 43 ++
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml | 2
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/RootContainer.java | 46 ++
opendj-sdk/opends/resource/schema/02-config.ldif | 8
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ConfigurableEnvironment.java | 101 +++++++
13 files changed, 627 insertions(+), 202 deletions(-)
diff --git a/opendj-sdk/opends/resource/schema/02-config.ldif b/opendj-sdk/opends/resource/schema/02-config.ldif
index 9c9b6b9..1f0cb54 100644
--- a/opendj-sdk/opends/resource/schema/02-config.ldif
+++ b/opendj-sdk/opends/resource/schema/02-config.ldif
@@ -1519,6 +1519,9 @@
NAME 'ds-task-import-clear-backend'
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.452
+ NAME 'ds-cfg-je-property' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
+ X-ORIGIN 'OpenDS Directory Server' )
attributeTypes: ( 1.3.6.1.4.1.26027.1.1.453
NAME 'ds-task-disconnect-connection-id'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE
@@ -1662,7 +1665,7 @@
ds-cfg-database-checkpointer-bytes-interval $
ds-cfg-database-checkpointer-wakeup-interval $
ds-cfg-database-lock-num-lock-tables $ ds-cfg-database-cleaner-num-threads $
- ds-cfg-backend-compact-encoding )
+ ds-cfg-backend-compact-encoding $ ds-cfg-je-property )
X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.7 NAME 'ds-cfg-je-database'
SUP top STRUCTURAL MAY ( cn $ ds-cfg-database-cache-percent $
@@ -2180,7 +2183,8 @@
ds-cfg-max-memory-size $ ds-cfg-lock-timeout $ ds-cfg-exclude-filter $
ds-cfg-include-filter $ ds-cfg-cache-directory $ ds-cfg-cache-type $
ds-cfg-persistent-cache $ ds-cfg-backend-compact-encoding $
- ds-cfg-database-cache-percent $ ds-cfg-database-cache-size )
+ ds-cfg-database-cache-percent $ ds-cfg-database-cache-size $
+ ds-cfg-je-property )
X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.114 NAME 'ds-cfg-plugin-root'
SUP top AUXILIARY MAY ( ds-cfg-plugin-order-startup $
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 8b9e534..6abafcb 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
@@ -290,6 +290,41 @@
</adm:profile>
</adm:property>
+ <adm:property name="je-property"
+ multi-valued="true">
+ <adm:synopsis>
+ Specifies the environment properties for the Berkeley DB Java
+ Edition database providing the backend for this entry cache.
+ </adm:synopsis>
+ <adm:description>
+ Any Berkeley DB Java Edition property can be specified using the
+ following form: property-name=property-value
+ Refer to OpenDS documentation for further information on related
+ properties, their implications and range values. The definitive
+ identification of all the property parameters available in the
+ example.properties file of Berkeley DB Java Edition distribution.
+ </adm:description>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>je.log.fileMax=10485760</adm:value>
+ <adm:value>je.cleaner.minUtilization=90</adm:value>
+ <adm:value>je.cleaner.maxBatchFiles=1</adm:value>
+ <adm:value>je.cleaner.minAge=1</adm:value>
+ <adm:value>je.cleaner.minFileUtilization=50</adm:value>
+ <adm:value>je.checkpointer.bytesInterval=10485760</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:string />
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.452</ldap:oid>
+ <ldap:name>ds-cfg-je-property</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+
<adm:property-reference name="include-filter"/>
<adm:property-reference name="exclude-filter"/>
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JEBackendConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JEBackendConfiguration.xml
index a1922f6..3d0b031 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JEBackendConfiguration.xml
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/JEBackendConfiguration.xml
@@ -991,4 +991,32 @@
</ldap:attribute>
</adm:profile>
</adm:property>
-</adm:managed-object>
\ No newline at end of file
+ <adm:property name="je-property"
+ mandatory="false"
+ multi-valued="true">
+ <adm:synopsis>
+ Specifies the database and environment properties for the Berkeley DB
+ Java Edition database serving the data for this backend.
+ </adm:synopsis>
+ <adm:description>
+ Any Berkeley DB Java Edition property can be specified using the
+ following form: property-name=property-value
+ Refer to OpenDS documentation for further information on related
+ properties, their implications and range values. The definitive
+ identification of all the property parameters available in the
+ example.properties file of Berkeley DB Java Edition distribution.
+ </adm:description>
+ <adm:default-behavior>
+ <adm:undefined />
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:string />
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.452</ldap:oid>
+ <ldap:name>ds-cfg-je-property</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/RootConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
index c7fcc5e..fb079ae 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
@@ -206,7 +206,7 @@
</adm:profile>
</adm:relation>
<adm:relation name="entry-cache">
- <adm:one-to-one />
+ <adm:one-to-zero-or-one />
<adm:profile name="ldap">
<ldap:rdn-sequence>cn=Entry Cache,cn=config</ldap:rdn-sequence>
</adm:profile>
diff --git a/opendj-sdk/opends/src/messages/messages/config.properties b/opendj-sdk/opends/src/messages/messages/config.properties
index cc0b3ab..ad45acc 100644
--- a/opendj-sdk/opends/src/messages/messages/config.properties
+++ b/opendj-sdk/opends/src/messages/messages/config.properties
@@ -698,7 +698,7 @@
SEVERE_ERR_CONFIG_ENTRYCACHE_CANNOT_GET_CONFIG_ENTRY_201=An unexpected error \
occurred while attempting to get the "cn=Entry Cache,cn=config" entry, which \
holds the entry cache configuration: %s. No entry cache will be available
-SEVERE_ERR_CONFIG_ENTRYCACHE_NO_CONFIG_ENTRY_202=The entry cache \
+SEVERE_WARN_CONFIG_ENTRYCACHE_NO_CONFIG_ENTRY_202=The entry cache \
configuration entry "cn=Entry Cache,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
@@ -2148,3 +2148,16 @@
SEVERE_WARN_CONFIG_FILE_NO_STARTOK_FILE_703=No last known good configuration \
file %s exists. The server will attempt to start using the active \
configuration file %s
+SEVERE_ERR_CONFIG_JE_PROPERTY_INVALID_704=An error occurred while \
+ trying to parse and validate Berkeley DB JE property %s: %s
+SEVERE_ERR_CONFIG_JE_PROPERTY_INVALID_FORM_705=An error occurred while \
+ trying to parse and validate Berkeley DB JE property %s: the property \
+ does not follow a singular property=value form
+SEVERE_ERR_CONFIG_JE_PROPERTY_SHADOWS_CONFIG_706=An error occurred while \
+ trying to parse and validate Berkeley DB JE property %s: the property \
+ shadows configuration attribute %s
+SEVERE_ERR_CONFIG_JE_DUPLICATE_PROPERTY_707=An error occurred while \
+ trying to parse and validate Berkeley DB JE property %s: the property \
+ is already defined for this component
+INFO_CONFIG_JE_PROPERTY_REQUIRES_RESTART_708=Setting Berkeley DB JE property \
+ %s will not take effect until the component for which it is set is restarted
diff --git a/opendj-sdk/opends/src/messages/messages/extension.properties b/opendj-sdk/opends/src/messages/messages/extension.properties
index a66515c..e31c424 100644
--- a/opendj-sdk/opends/src/messages/messages/extension.properties
+++ b/opendj-sdk/opends/src/messages/messages/extension.properties
@@ -124,10 +124,8 @@
while attempting to determine the value of the ds-cfg-exclude-filter \
attribute in configuration entry %s: %s. All entries will be considered \
eligible for inclusion in the cache
-SEVERE_ERR_FIFOCACHE_INVALID_MAX_MEMORY_PCT_20=The ds-cfg-max-memory-percent \
- attribute of entry %s, which holds the maximum percentage of JVM memory \
- available for use in the entry cache, has an invalid value: %s. Its value \
- must be an integer between 1 and 100
+FATAL_ERR_FIFOCACHE_CANNOT_INITIALIZE_20=A fatal error occurred while trying \
+ to initialize fifo entry cache: %s
SEVERE_ERR_FIFOCACHE_INVALID_MAX_ENTRIES_21=The ds-cfg-max-entries attribute \
of entry %s, which specifies the maximum number of entries that may be held \
in the entry cache, has an invalid value: %s. Its value must be a positive \
@@ -973,9 +971,8 @@
of time in milliseconds that the entry cache should block while attempting to \
acquire a lock for an entry. Changes to this configuration attribute will \
take effect immediately
-SEVERE_ERR_SOFTREFCACHE_CANNOT_DETERMINE_LOCK_TIMEOUT_279=An error occurred \
- while attempting to determine the value of the ds-cfg-lock-timeout attribute \
- in configuration entry %s: %s. The default of %d will be used
+FATAL_ERR_SOFTREFCACHE_CANNOT_INITIALIZE_279=A fatal error occurred while \
+ trying to initialize soft reference entry cache: %s
INFO_SOFTREFCACHE_DESCRIPTION_INCLUDE_FILTERS_280=Specifies a set of search \
filters that may be used to indicate which entries should be included in the \
entry cache. Entries that do not match at least one of these filters will \
@@ -1581,7 +1578,7 @@
SEVERE_ERR_FSCACHE_CANNOT_STORE_PERSISTENT_DATA_487=An error occurred while \
trying to store persistent cache. Persistent cache will be flushed now
FATAL_ERR_FSCACHE_CANNOT_INITIALIZE_488=A fatal error occurred while trying \
- to initialize file system entry cache. This cache will be disabled now
+ to initialize file system entry cache: %s
SEVERE_ERR_FSCACHE_CANNOT_STORE_ENTRY_489=Unable to store new cache entry in \
the file system entry cache
SEVERE_ERR_FSCACHE_CANNOT_RETRIEVE_ENTRY_490=Unable to retrieve an existing \
@@ -1592,21 +1589,23 @@
SEVERE_ERR_FSCACHE_CANNOT_SET_JE_MEMORY_SIZE_492=Internal error occurred \
while trying to set the entry cache backend internal cache size in bytes. The \
previous or default value will be used instead
-FATAL_ERR_FSCACHE_HOMELESS_493=A fatal error occurred while trying to setup \
+SEVERE_ERR_FSCACHE_CANNOT_SET_JE_PROPERTIES_493=Internal error occurred \
+ while trying to set the entry cache backend Berkeley DB JE properties: %s
+FATAL_ERR_FSCACHE_HOMELESS_494=A fatal error occurred while trying to setup \
file system entry cache home. No suitable path can be found to host the cache \
home
-SEVERE_WARN_FSCACHE_SET_PERMISSIONS_FAILED_494=Unable to set file permissions \
+SEVERE_WARN_FSCACHE_SET_PERMISSIONS_FAILED_495=Unable to set file permissions \
for the file system entry cache backend database directory %s
-SEVERE_WARN_FSCACHE_OFFLINE_STATE_FAIL_495=%s backend current offline state \
+SEVERE_WARN_FSCACHE_OFFLINE_STATE_FAIL_496=%s backend current offline state \
does not match persistent cache last recorded offline state. All cached data \
for this backend is now discarded
-NOTICE_FSCACHE_RESTORE_PROGRESS_REPORT_496=Restored %d cache entries of %d \
+NOTICE_FSCACHE_RESTORE_PROGRESS_REPORT_497=Restored %d cache entries of %d \
total persistent cache entries found
-NOTICE_FSCACHE_SAVE_PROGRESS_REPORT_497=Made persistent %d cache entries of %d \
+NOTICE_FSCACHE_SAVE_PROGRESS_REPORT_498=Made persistent %d cache entries of %d \
total cache entries found
-NOTICE_FSCACHE_INDEX_NOT_FOUND_498=No previous persistent cache state can be \
+NOTICE_FSCACHE_INDEX_NOT_FOUND_499=No previous persistent cache state can be \
found. Starting with an empty cache
-SEVERE_ERR_FSCACHE_INDEX_IMPAIRED_499=The persistent cache index is \
+SEVERE_ERR_FSCACHE_INDEX_IMPAIRED_500=The persistent cache index is \
inconsistent or damaged. Persistent cache will be flushed now
MILD_ERR_ENTRYUUID_VATTR_NOT_SEARCHABLE_501=The %s attribute is not \
searchable and should not be included in otherwise unindexed search filters
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ConfigurableEnvironment.java b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ConfigurableEnvironment.java
index 68ffafb..caebba9 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ConfigurableEnvironment.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ConfigurableEnvironment.java
@@ -35,8 +35,11 @@
import java.util.HashMap;
import java.util.Map;
import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.SortedSet;
+import java.util.StringTokenizer;
+import org.opends.messages.Message;
-import static org.opends.server.loggers.debug.DebugLogger.*;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.admin.std.server.JEBackendCfg;
import org.opends.server.admin.std.meta.JEBackendCfgDefn;
@@ -44,6 +47,9 @@
import org.opends.server.admin.BooleanPropertyDefinition;
import org.opends.server.admin.PropertyDefinition;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.messages.ConfigMessages.*;
+
/**
* This class maps JE properties to configuration attributes.
*/
@@ -166,6 +172,13 @@
/**
+ * The name of the attribute which may specify any native JE properties.
+ */
+ public static final String ATTR_JE_PROPERTY =
+ ConfigConstants.NAME_PREFIX_CFG + "je-property";
+
+
+ /**
* A map of JE property names to the corresponding configuration attribute.
*/
private static HashMap<String, String> attrMap =
@@ -391,6 +404,92 @@
envConfig.setConfigParam(jeProperty, value);
}
+ // See if there are any native JE properties specified in the config
+ // and if so try to parse, evaluate and set them.
+ SortedSet<String> jeProperties = cfg.getJEProperty();
+ try {
+ envConfig = setJEProperties(envConfig, jeProperties, attrMap);
+ } catch (ConfigException e) {
+ throw e;
+ }
+
+ return envConfig;
+ }
+
+
+
+ /**
+ * Parse, validate and set native JE environment properties for
+ * a given environment config.
+ *
+ * @param envConfig The JE environment config for which to set
+ * the properties.
+ * @param jeProperties The JE environment properties to parse,
+ * validate and set.
+ * @param configAttrMap Component supported JE properties to
+ * their configuration attributes map.
+ * @return An environment config instance with given properties
+ * set.
+ * @throws ConfigException If there is an error while parsing,
+ * validating and setting any of the properties provided.
+ */
+ public static EnvironmentConfig setJEProperties(EnvironmentConfig envConfig,
+ SortedSet<String> jeProperties, HashMap<String, String> configAttrMap)
+ throws ConfigException
+ {
+ if (jeProperties.isEmpty()) {
+ // return default config.
+ return envConfig;
+ }
+
+ // Set to catch duplicate properties.
+ HashSet<String> uniqueJEProperties = new HashSet<String>();
+
+ // Iterate through the config values associated with a JE property.
+ for (String jeEntry : jeProperties)
+ {
+ StringTokenizer st = new StringTokenizer(jeEntry, "=");
+ if (st.countTokens() == 2) {
+ String jePropertyName = st.nextToken();
+ String jePropertyValue = st.nextToken();
+ // Check if it is a duplicate.
+ if (uniqueJEProperties.contains(jePropertyName)) {
+ Message message = ERR_CONFIG_JE_DUPLICATE_PROPERTY.get(
+ jePropertyName);
+ throw new ConfigException(message);
+ }
+ // Set JE property.
+ try {
+ envConfig.setConfigParam(jePropertyName, jePropertyValue);
+ // This is a special case that JE cannot validate before
+ // actually setting it. Validate it before it gets to JE.
+ if (jePropertyName.equals("java.util.logging.level")) {
+ java.util.logging.Level.parse(jePropertyValue);
+ }
+ // If this property shadows an existing config attribute.
+ if (configAttrMap.containsKey(jePropertyName)) {
+ Message message = ERR_CONFIG_JE_PROPERTY_SHADOWS_CONFIG.get(
+ jePropertyName, attrMap.get(jePropertyName));
+ throw new ConfigException(message);
+ }
+ // Add this property to unique set.
+ uniqueJEProperties.add(jePropertyName);
+ } catch(IllegalArgumentException e) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ Message message =
+ ERR_CONFIG_JE_PROPERTY_INVALID.get(
+ jeEntry, e.getMessage());
+ throw new ConfigException(message, e.getCause());
+ }
+ } else {
+ Message message =
+ ERR_CONFIG_JE_PROPERTY_INVALID_FORM.get(jeEntry);
+ throw new ConfigException(message);
+ }
+ }
+
return envConfig;
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/RootContainer.java b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/RootContainer.java
index 0d17c79..b26a3fc 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/RootContainer.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/RootContainer.java
@@ -43,6 +43,12 @@
import org.opends.server.types.FilePermission;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.ResultCode;
+import org.opends.server.api.Backend;
+import org.opends.server.admin.std.server.JEBackendCfg;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.config.ConfigException;
+
import static org.opends.server.loggers.ErrorLogger.logError;
import static org.opends.server.loggers.debug.DebugLogger.*;
import org.opends.server.loggers.debug.DebugTracer;
@@ -51,14 +57,8 @@
ERR_CONFIG_BACKEND_MODE_INVALID;
import static org.opends.messages.ConfigMessages.
WARN_CONFIG_BACKEND_INSANE_MODE;
-
-import org.opends.server.api.Backend;
-import org.opends.server.admin.std.server.JEBackendCfg;
-import org.opends.server.admin.server.ConfigurationChangeListener;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.config.ConfigException;
-import static org.opends.server.util.StaticUtils.getFileForPath;
-import org.opends.server.util.StaticUtils;
+import static org.opends.server.util.StaticUtils.*;
+import static org.opends.messages.ConfigMessages.*;
/**
* Wrapper class for the JE environment. Root container holds all the entry
@@ -780,6 +780,34 @@
EnvironmentConfig newEnvConfig =
ConfigurableEnvironment.parseConfigEntry(cfg);
Map paramsMap = EnvironmentParams.SUPPORTED_PARAMS;
+
+ // Iterate through native JE properties.
+ SortedSet<String> jeProperties = cfg.getJEProperty();
+ for (String jeEntry : jeProperties) {
+ // There is no need to validate properties yet again.
+ StringTokenizer st = new StringTokenizer(jeEntry, "=");
+ if (st.countTokens() == 2) {
+ String jePropertyName = st.nextToken();
+ String jePropertyValue = st.nextToken();
+ ConfigParam param = (ConfigParam) paramsMap.get(jePropertyName);
+ if (!param.isMutable()) {
+ String oldValue = oldEnvConfig.getConfigParam(param.getName());
+ String newValue = jePropertyValue;
+ if (!oldValue.equalsIgnoreCase(newValue)) {
+ adminActionRequired = true;
+ messages.add(INFO_CONFIG_JE_PROPERTY_REQUIRES_RESTART.get(
+ jePropertyName));
+ if(debugEnabled()) {
+ TRACER.debugInfo("The change to the following property " +
+ "will take effect when the component is restarted: " +
+ jePropertyName);
+ }
+ }
+ }
+ }
+ }
+
+ // Iterate through JE configuration attributes.
for (Object o : paramsMap.values())
{
ConfigParam param = (ConfigParam) o;
@@ -820,7 +848,7 @@
}
catch (Exception e)
{
- messages.add(Message.raw(StaticUtils.stackTraceToSingleLineString(e)));
+ messages.add(Message.raw(stackTraceToSingleLineString(e)));
ccr = new ConfigChangeResult(DirectoryServer.getServerErrorResultCode(),
adminActionRequired,
messages);
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 24a05d1..da3d563 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
@@ -50,18 +50,15 @@
import org.opends.server.types.DebugLogLevel;
import org.opends.server.types.InitializationException;
import org.opends.server.types.ResultCode;
+import org.opends.messages.MessageBuilder;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.loggers.ErrorLogger.*;
import static org.opends.messages.ConfigMessages.*;
-
-import org.opends.messages.MessageBuilder;
import static org.opends.server.util.StaticUtils.*;
-
-
/**
* 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
@@ -152,28 +149,16 @@
// Register as an add and delete listener with the root configuration so we
// can be notified if any entry cache entry is added or removed.
- // If entry cache configuration is using a one-to-zero-or-one relation
- // then uncomment the lines below (see issue #1558).
- /*
- // rootConfiguration.addEntryCacheAddListener(this);
- // rootConfiguration.addEntryCacheDeleteListener(this);
- */
+ rootConfiguration.addEntryCacheAddListener(this);
+ rootConfiguration.addEntryCacheDeleteListener(this);
// If the entry cache configuration is not present then keep the
// default entry cache already installed.
- // If entry cache configuration is using a one-to-zero-or-one relation
- // then uncomment the lines below (see issue #1558).
- /*
- // if (!rootConfiguration.hasEntryCache())
- // {
- // logError(
- // ErrorLogCategory.CONFIGURATION,
- // ErrorLogSeverity.SEVERE_WARNING,
- // ERR_CONFIG_ENTRYCACHE_NO_CONFIG_ENTRY
- // );
- // return;
- // }
- */
+ if (!rootConfiguration.hasEntryCache())
+ {
+ logError(WARN_CONFIG_ENTRYCACHE_NO_CONFIG_ENTRY.get());
+ return;
+ }
// Get the entry cache configuration.
EntryCacheCfg configuration = rootConfiguration.getEntryCache();
@@ -190,7 +175,7 @@
String className = configuration.getEntryCacheClass();
try
{
- loadAndInstallEntryCache (className, configuration);
+ loadAndInstallEntryCache (className);
}
catch (InitializationException ie)
{
@@ -211,21 +196,15 @@
// returned status -- all is fine by default
boolean status = true;
- if (configuration.isEnabled())
- {
- // Get the name of the class and make sure we can instantiate it as an
- // entry cache.
- String className = configuration.getEntryCacheClass();
- try
- {
- // Load the class but don't initialize it.
- loadEntryCache(className, configuration, false);
- }
- catch (InitializationException ie)
- {
- unacceptableReasons.add(ie.getMessageObject());
- status = false;
- }
+ // Get the name of the class and make sure we can instantiate it as an
+ // entry cache.
+ String className = configuration.getEntryCacheClass();
+ try {
+ // Load the class but don't initialize it.
+ loadEntryCache(className, configuration, false);
+ } catch (InitializationException ie) {
+ unacceptableReasons.add(ie.getMessageObject());
+ status = false;
}
return status;
@@ -279,7 +258,7 @@
// Instantiate the new class and initalize it.
try
{
- loadAndInstallEntryCache (newClassName, configuration);
+ loadAndInstallEntryCache (newClassName);
}
catch (InitializationException ie)
{
@@ -346,7 +325,7 @@
String className = configuration.getEntryCacheClass();
try
{
- loadAndInstallEntryCache (className, configuration);
+ loadAndInstallEntryCache (className);
}
catch (InitializationException ie)
{
@@ -368,8 +347,6 @@
List<Message> unacceptableReasons
)
{
- // NYI
-
// If we've gotten to this point, then it is acceptable as far as we are
// concerned. If it is unacceptable according to the configuration, then
// the entry cache itself will make that determination.
@@ -417,11 +394,28 @@
* to initialize the entry cache.
*/
private void loadAndInstallEntryCache(
- String className,
- EntryCacheCfg configuration
+ String className
)
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);
@@ -464,7 +458,14 @@
definition = EntryCacheCfgDefn.getInstance();
propertyDefinition = definition.getEntryCacheClassPropertyDefinition();
cacheClass = propertyDefinition.loadClass(className, EntryCache.class);
- cache = (EntryCache<? extends EntryCacheCfg>) cacheClass.newInstance();
+
+ // 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)) {
+ cache = (EntryCache<? extends EntryCacheCfg>) cacheClass.newInstance();
+ } else {
+ cache = (EntryCache<? extends EntryCacheCfg>) _entryCache;
+ }
if (initialize)
{
@@ -474,7 +475,10 @@
);
method.invoke(cache, configuration);
}
- else
+ // This will check if configuration is acceptable on disabled
+ // and uninitialized cache instance that has no "acceptable"
+ // change listener registered to invoke and verify on its own.
+ else if (!configuration.isEnabled())
{
Method method = cache.getClass().getMethod("isConfigurationAcceptable",
EntryCacheCfg.class,
@@ -507,9 +511,23 @@
}
catch (Exception e)
{
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ if (!initialize) {
+ if (e instanceof InitializationException) {
+ throw (InitializationException) e;
+ } else {
+ Message message = ERR_CONFIG_ENTRYCACHE_CONFIG_NOT_ACCEPTABLE.get(
+ String.valueOf(configuration.dn()), e.getCause() != null ?
+ e.getCause().getMessage() : stackTraceToSingleLineString(e));
+ throw new InitializationException(message);
+ }
+ }
Message message = ERR_CONFIG_ENTRYCACHE_CANNOT_INITIALIZE_CACHE.get(
- className,
- String.valueOf(configuration.dn()));
+ className, (e.getCause() != null ? e.getCause().getMessage() :
+ stackTraceToSingleLineString(e)));
throw new InitializationException(message, e);
}
}
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 40caf11..e7641c3 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
@@ -95,6 +95,10 @@
// or PHASE_APPLY.
private boolean _isAcceptable;
+ // Indicates whether administrative action is required or not. Used when
+ // _configPhase is PHASE_APPLY.
+ private boolean _isAdminActionRequired;
+
/**
* Create an error handler.
*
@@ -111,11 +115,12 @@
ArrayList<Message> errorMessages
)
{
- _configPhase = configPhase;
- _unacceptableReasons = unacceptableReasons;
- _errorMessages = errorMessages;
- _resultCode = ResultCode.SUCCESS;
- _isAcceptable = true;
+ _configPhase = configPhase;
+ _unacceptableReasons = unacceptableReasons;
+ _errorMessages = errorMessages;
+ _resultCode = ResultCode.SUCCESS;
+ _isAcceptable = true;
+ _isAdminActionRequired = false;
}
/**
@@ -135,6 +140,49 @@
{
case PHASE_INIT:
{
+ _errorMessages.add (error);
+ _isAcceptable = isAcceptable;
+ break;
+ }
+ case PHASE_ACCEPTABLE:
+ {
+ _unacceptableReasons.add (error);
+ _isAcceptable = isAcceptable;
+ break;
+ }
+ case PHASE_APPLY:
+ {
+ _errorMessages.add (error);
+ _isAcceptable = isAcceptable;
+ if (_resultCode == ResultCode.SUCCESS)
+ {
+ _resultCode = resultCode;
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * Report an error.
+ *
+ * @param error the error to report
+ * @param isAcceptable <code>true</code> if the configuration is acceptable
+ * @param resultCode the change result for the current configuration
+ * @param isAdminActionRequired <code>true</code> if administrative action
+ * is required or <code>false</code> otherwise
+ */
+ public void reportError(
+ Message error,
+ boolean isAcceptable,
+ ResultCode resultCode,
+ boolean isAdminActionRequired
+ )
+ {
+ switch (_configPhase)
+ {
+ case PHASE_INIT:
+ {
logError (error);
break;
}
@@ -152,6 +200,7 @@
{
_resultCode = resultCode;
}
+ _isAdminActionRequired = isAdminActionRequired;
break;
}
}
@@ -212,6 +261,17 @@
{
return _configPhase;
}
+
+ /**
+ * Get the current isAdminActionRequired flag as determined after apply
+ * action has been taken on a given configuration.
+ *
+ * @return the isAdminActionRequired flag
+ */
+ public boolean getIsAdminActionRequired()
+ {
+ return _isAdminActionRequired;
+ }
} // ConfigErrorHandler
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 f602d14..dd9cd90 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
@@ -58,10 +58,10 @@
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
import org.opends.server.util.ServerConstants;
+import org.opends.messages.MessageBuilder;
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.messages.ExtensionMessages.*;
-
import static org.opends.server.util.ServerConstants.*;
@@ -142,6 +142,9 @@
// The maximum number of entries that may be held in the cache.
private long maxEntries;
+ // Currently registered configuration object.
+ private FIFOEntryCacheCfg registeredConfiguration;
+
static
@@ -175,6 +178,7 @@
)
throws ConfigException, InitializationException
{
+ registeredConfiguration = configuration;
configuration.addFIFOChangeListener (this);
configEntryDN = configuration.dn();
@@ -186,11 +190,24 @@
// Read configuration and apply changes.
boolean applyChanges = true;
+ ArrayList<Message> errorMessages = new ArrayList<Message>();
EntryCacheCommon.ConfigErrorHandler errorHandler =
EntryCacheCommon.getConfigErrorHandler (
- EntryCacheCommon.ConfigPhase.PHASE_INIT, null, null
+ EntryCacheCommon.ConfigPhase.PHASE_INIT, null, errorMessages
);
- processEntryCacheConfig (configuration, applyChanges, errorHandler);
+ if (!processEntryCacheConfig(configuration, applyChanges, errorHandler)) {
+ MessageBuilder buffer = new MessageBuilder();
+ if (!errorMessages.isEmpty()) {
+ Iterator<Message> iterator = errorMessages.iterator();
+ buffer.append(iterator.next());
+ while (iterator.hasNext()) {
+ buffer.append(". ");
+ buffer.append(iterator.next());
+ }
+ }
+ Message message = ERR_FIFOCACHE_CANNOT_INITIALIZE.get(buffer.toString());
+ throw new ConfigException(message);
+ }
}
@@ -200,9 +217,11 @@
*/
public void finalizeEntryCache()
{
- // Release all memory currently in use by this cache.
cacheLock.lock();
+ registeredConfiguration.removeFIFOChangeListener (this);
+
+ // Release all memory currently in use by this cache.
try
{
idMap.clear();
@@ -911,10 +930,13 @@
EntryCacheCommon.getConfigErrorHandler (
EntryCacheCommon.ConfigPhase.PHASE_APPLY, null, errorMessages
);
- processEntryCacheConfig (configuration, applyChanges, errorHandler);
+ // Do not apply changes unless this cache is enabled.
+ if (configuration.isEnabled()) {
+ processEntryCacheConfig (configuration, applyChanges, errorHandler);
+ }
- boolean adminActionRequired = false;
+ boolean adminActionRequired = errorHandler.getIsAdminActionRequired();
ConfigChangeResult changeResult = new ConfigChangeResult(
errorHandler.getResultCode(),
adminActionRequired,
@@ -1007,8 +1029,8 @@
* @param applyChanges If true then take into account the new configuration.
* @param errorHandler An handler used to report errors.
*
- * @return The mapping between strings of character set values and the
- * minimum number of characters required from those sets.
+ * @return <CODE>true</CODE> if configuration is acceptable,
+ * or <CODE>false</CODE> otherwise.
*/
public boolean processEntryCacheConfig(
FIFOEntryCacheCfg configuration,
@@ -1083,6 +1105,8 @@
setLockTimeout(newLockTimeout);
setIncludeFilters(newIncludeFilters);
setExcludeFilters(newExcludeFilters);
+
+ registeredConfiguration = configuration;
}
return errorHandler.getIsAcceptable();
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 f23d61f..3f92627 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
@@ -29,11 +29,14 @@
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import java.util.SortedSet;
+import java.util.StringTokenizer;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -54,19 +57,21 @@
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.StatsConfig;
+import com.sleepycat.je.config.ConfigParam;
+import com.sleepycat.je.config.EnvironmentParams;
+import org.opends.messages.MessageBuilder;
import org.opends.server.api.Backend;
import org.opends.server.api.EntryCache;
import org.opends.server.admin.std.server.EntryCacheCfg;
import org.opends.server.admin.std.server.FileSystemEntryCacheCfg;
import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.backends.jeb.ConfigurableEnvironment;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.EntryEncodeConfig;
-
-
import org.opends.server.types.InitializationException;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
@@ -75,12 +80,13 @@
import org.opends.server.types.OpenDsException;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.util.ServerConstants;
+
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.server.loggers.ErrorLogger.logError;
import static org.opends.server.config.ConfigConstants.*;
import static org.opends.messages.ExtensionMessages.*;
-
import static org.opends.server.util.StaticUtils.*;
+import static org.opends.messages.ConfigMessages.*;
/**
* This class defines a Directory Server entry cache that uses JE database to
@@ -193,16 +199,6 @@
private static final String INDEXCLASSDBNAME = "IndexClassDB";
private static final String INDEXKEY = "EntryCacheIndex";
- // JE config constants.
- // TODO: All hardcoded for now but we need to use a common
- // ds-cfg-je-property like multi-valued attribute for this, see Issue 1481.
- private static final Long JEBYTESINTERVAL = 10485760L;
- private static final Long JELOGFILEMAX = 10485760L;
- private static final Integer JEMINFILEUTILIZATION = 50;
- private static final Integer JEMINUTILIZATION = 90;
- private static final Integer JEMAXBATCHFILES = 1;
- private static final Integer JEMINAGE = 1;
-
// The number of milliseconds between persistent state save/restore
// progress reports.
private long progressInterval = 5000;
@@ -215,11 +211,26 @@
private EntryEncodeConfig encodeConfig =
new EntryEncodeConfig(true, false, false);
+ // JE native properties to configuration attributes map.
+ private HashMap<String, String> configAttrMap =
+ new HashMap<String, String>();
+
+ // Currently registered configuration object.
+ private FileSystemEntryCacheCfg registeredConfiguration;
+
/**
* Creates a new instance of this entry cache.
*/
public FileSystemEntryCache() {
super();
+
+ // Register all JE native properties that map to
+ // corresponding config attributes.
+ configAttrMap.put("je.maxMemoryPercent",
+ ConfigurableEnvironment.ATTR_DATABASE_CACHE_PERCENT);
+ configAttrMap.put("je.maxMemory",
+ ConfigurableEnvironment.ATTR_DATABASE_CACHE_SIZE);
+
// All initialization should be performed in the initializeEntryCache.
}
@@ -229,16 +240,30 @@
public void initializeEntryCache(FileSystemEntryCacheCfg configuration)
throws ConfigException, InitializationException {
+ registeredConfiguration = configuration;
configuration.addFileSystemChangeListener (this);
configEntryDN = configuration.dn();
// Read and apply configuration.
boolean applyChanges = true;
+ ArrayList<Message> errorMessages = new ArrayList<Message>();
EntryCacheCommon.ConfigErrorHandler errorHandler =
EntryCacheCommon.getConfigErrorHandler (
- EntryCacheCommon.ConfigPhase.PHASE_INIT, null, null
+ EntryCacheCommon.ConfigPhase.PHASE_INIT, null, errorMessages
);
- processEntryCacheConfig(configuration, applyChanges, errorHandler);
+ if (!processEntryCacheConfig(configuration, applyChanges, errorHandler)) {
+ MessageBuilder buffer = new MessageBuilder();
+ if (!errorMessages.isEmpty()) {
+ Iterator<Message> iterator = errorMessages.iterator();
+ buffer.append(iterator.next());
+ while (iterator.hasNext()) {
+ buffer.append(". ");
+ buffer.append(iterator.next());
+ }
+ }
+ Message message = ERR_FSCACHE_CANNOT_INITIALIZE.get(buffer.toString());
+ throw new ConfigException(message);
+ }
// Set the cache type.
if (cacheType.equalsIgnoreCase("LRU")) {
@@ -273,9 +298,6 @@
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
- // Log an error message.
- logError(ERR_FSCACHE_HOMELESS.get());
-
// Not having any home directory for the cache db environment is a
// fatal error as we are unable to continue any further without it.
Message message =
@@ -283,65 +305,10 @@
throw new InitializationException(message, e);
}
- // Open JE environment and cache database.
+ // Configure and open JE environment and cache database.
try {
- entryCacheEnvConfig = new EnvironmentConfig();
-
- // All these environment properties are cranked up to their extreme
- // values, either max or min, to get the smallest space consumption,
- // which turns into memory consumption for memory based filesystems,
- // possible. This will negate the performance somewhat but preserves
- // the memory to a much greater extent.
- //
- // TODO: All these options should be configurable, see Issue 1481.
- //
- entryCacheEnvConfig.setConfigParam("je.log.fileMax",
- JELOGFILEMAX.toString());
- entryCacheEnvConfig.setConfigParam("je.cleaner.minUtilization",
- JEMINUTILIZATION.toString());
- entryCacheEnvConfig.setConfigParam("je.cleaner.maxBatchFiles",
- JEMAXBATCHFILES.toString());
- entryCacheEnvConfig.setConfigParam("je.cleaner.minAge",
- JEMINAGE.toString());
- entryCacheEnvConfig.setConfigParam("je.cleaner.minFileUtilization",
- JEMINFILEUTILIZATION.toString());
- entryCacheEnvConfig.setConfigParam("je.checkpointer.bytesInterval",
- JEBYTESINTERVAL.toString());
-
entryCacheEnvConfig.setAllowCreate(true);
entryCacheEnv = new Environment(new File(cacheHome), entryCacheEnvConfig);
-
- // Set JE cache percent and size where the size value will prevail if set.
- entryCacheEnvMutableConfig = new EnvironmentMutableConfig();
- if (jeCachePercent != 0) {
- try {
- entryCacheEnvMutableConfig.setCachePercent(jeCachePercent);
- } catch (IllegalArgumentException e) {
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- // Its safe to ignore and continue here, JE will use its default
- // value for this however we have to let the user know about it
- // so just log an error message.
- logError(ERR_FSCACHE_CANNOT_SET_JE_MEMORY_PCT.get());
- }
- }
- if (jeCacheSize != 0) {
- try {
- entryCacheEnvMutableConfig.setCacheSize(jeCacheSize);
- } catch (IllegalArgumentException e) {
- if (debugEnabled()) {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- // Its safe to ignore and continue here, JE will use its default
- // value for this however we have to let the user know about it
- // so just log an error message.
- logError(ERR_FSCACHE_CANNOT_SET_JE_MEMORY_SIZE.get());
- }
- }
-
entryCacheEnv.setMutableConfig(entryCacheEnvMutableConfig);
entryCacheDBConfig = new DatabaseConfig();
entryCacheDBConfig.setAllowCreate(true);
@@ -513,7 +480,9 @@
}
Message message =
- ERR_FSCACHE_CANNOT_INITIALIZE.get();
+ ERR_FSCACHE_CANNOT_INITIALIZE.get(
+ (e.getCause() != null ? e.getCause().getMessage() :
+ stackTraceToSingleLineString(e)));
throw new InitializationException(message, e);
}
@@ -526,6 +495,8 @@
cacheWriteLock.lock();
+ registeredConfiguration.removeFileSystemChangeListener (this);
+
// Store index/maps in case of persistent cache. Since the cache database
// already exist at this point all we have to do is to serialize cache
// index maps @see FileSystemEntryCacheIndex and put them under indexkey
@@ -1076,10 +1047,13 @@
EntryCacheCommon.getConfigErrorHandler (
EntryCacheCommon.ConfigPhase.PHASE_APPLY, null, errorMessages
);
- processEntryCacheConfig (configuration, applyChanges, errorHandler);
+ // Do not apply changes unless this cache is enabled.
+ if (configuration.isEnabled()) {
+ processEntryCacheConfig (configuration, applyChanges, errorHandler);
+ }
- boolean adminActionRequired = false;
+ boolean adminActionRequired = errorHandler.getIsAdminActionRequired();
ConfigChangeResult changeResult = new ConfigChangeResult(
errorHandler.getResultCode(),
adminActionRequired,
@@ -1188,8 +1162,8 @@
* @param applyChanges If true then take into account the new configuration.
* @param errorHandler An handler used to report errors.
*
- * @return The mapping between strings of character set values and the
- * minimum number of characters required from those sets.
+ * @return <CODE>true</CODE> if configuration is acceptable,
+ * or <CODE>false</CODE> otherwise.
*/
public boolean processEntryCacheConfig(
FileSystemEntryCacheCfg configuration,
@@ -1198,18 +1172,24 @@
)
{
// Local variables to read configuration.
- DN newConfigEntryDN;
- long newLockTimeout;
- long newMaxEntries;
- long newMaxAllowedMemory;
- HashSet<SearchFilter> newIncludeFilters = null;
- HashSet<SearchFilter> newExcludeFilters = null;
- int newJECachePercent;
- long newJECacheSize;
- boolean newPersistentCache;
- boolean newCompactEncoding;
- String newCacheType = DEFAULT_FSCACHE_TYPE;
- String newCacheHome = DEFAULT_FSCACHE_HOME;
+ DN newConfigEntryDN;
+ long newLockTimeout;
+ long newMaxEntries;
+ long newMaxAllowedMemory;
+ HashSet<SearchFilter> newIncludeFilters = null;
+ HashSet<SearchFilter> newExcludeFilters = null;
+ int newJECachePercent;
+ long newJECacheSize;
+ boolean newPersistentCache;
+ boolean newCompactEncoding;
+ String newCacheType = DEFAULT_FSCACHE_TYPE;
+ String newCacheHome = DEFAULT_FSCACHE_HOME;
+ SortedSet<String> newJEProperties;
+
+ EnvironmentMutableConfig newMutableEnvConfig =
+ new EnvironmentMutableConfig();
+ EnvironmentConfig newEnvConfig =
+ new EnvironmentConfig();
// Read configuration.
newConfigEntryDN = configuration.dn();
@@ -1237,6 +1217,9 @@
// Check if this cache should use compact encoding.
newCompactEncoding = configuration.isBackendCompactEncoding();
+ // Get native JE properties.
+ newJEProperties = configuration.getJEProperty();
+
switch (errorHandler.getConfigPhase())
{
case PHASE_INIT:
@@ -1260,6 +1243,45 @@
errorHandler,
configEntryDN
);
+ // JE configuration properties.
+ try {
+ newMutableEnvConfig.setCachePercent((newJECachePercent != 0 ?
+ newJECachePercent :
+ EnvironmentConfig.DEFAULT.getCachePercent()));
+ } catch (Exception e) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ errorHandler.reportError(
+ ERR_FSCACHE_CANNOT_SET_JE_MEMORY_PCT.get(),
+ false,
+ DirectoryServer.getServerErrorResultCode()
+ );
+ }
+ try {
+ newMutableEnvConfig.setCacheSize(newJECacheSize);
+ } catch (Exception e) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ errorHandler.reportError(
+ ERR_FSCACHE_CANNOT_SET_JE_MEMORY_SIZE.get(),
+ false,
+ DirectoryServer.getServerErrorResultCode()
+ );
+ }
+ // JE native properties.
+ try {
+ newEnvConfig = ConfigurableEnvironment.setJEProperties(
+ newEnvConfig, newJEProperties, configAttrMap);
+ } catch (Exception e) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ errorHandler.reportError(
+ ERR_FSCACHE_CANNOT_SET_JE_PROPERTIES.get(e.getMessage()),
+ false, DirectoryServer.getServerErrorResultCode());
+ }
break;
case PHASE_ACCEPTABLE: // acceptable and apply are using the same
case PHASE_APPLY: // error ID codes
@@ -1277,6 +1299,54 @@
errorHandler,
configEntryDN
);
+ // Iterate through native JE properties.
+ try {
+ Map paramsMap = EnvironmentParams.SUPPORTED_PARAMS;
+ // If this entry cache is disabled then there is no open JE
+ // environment to check against, skip mutable check if so.
+ if (configuration.isEnabled()) {
+ newMutableEnvConfig =
+ ConfigurableEnvironment.setJEProperties(
+ entryCacheEnv.getConfig(), newJEProperties, configAttrMap);
+ EnvironmentConfig oldEnvConfig = entryCacheEnv.getConfig();
+ for (String jeEntry : newJEProperties) {
+ // There is no need to validate properties yet again.
+ StringTokenizer st = new StringTokenizer(jeEntry, "=");
+ if (st.countTokens() == 2) {
+ String jePropertyName = st.nextToken();
+ String jePropertyValue = st.nextToken();
+ ConfigParam param = (ConfigParam) paramsMap.get(jePropertyName);
+ if (!param.isMutable()) {
+ String oldValue = oldEnvConfig.getConfigParam(param.getName());
+ String newValue = jePropertyValue;
+ if (!oldValue.equalsIgnoreCase(newValue)) {
+ Message message =
+ INFO_CONFIG_JE_PROPERTY_REQUIRES_RESTART.get(
+ jePropertyName);
+ errorHandler.reportError(message, true, ResultCode.SUCCESS,
+ true);
+ if (debugEnabled()) {
+ TRACER.debugInfo("The change to the following property " +
+ "will take effect when the component is restarted: " +
+ jePropertyName);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ newMutableEnvConfig =
+ ConfigurableEnvironment.setJEProperties(
+ new EnvironmentConfig(), newJEProperties, configAttrMap);
+ }
+ } catch (ConfigException ce) {
+ errorHandler.reportError(ce.getMessageObject(),
+ false, DirectoryServer.getServerErrorResultCode());
+ } catch (Exception e) {
+ errorHandler.reportError(
+ Message.raw(stackTraceToSingleLineString(e)),
+ false, DirectoryServer.getServerErrorResultCode());
+ }
break;
}
@@ -1284,19 +1354,19 @@
{
switch (errorHandler.getConfigPhase()) {
case PHASE_INIT:
- cacheType = newCacheType;
- cacheHome = newCacheHome;
- jeCachePercent = newJECachePercent;
- jeCacheSize = newJECacheSize;
+ cacheType = newCacheType;
+ cacheHome = newCacheHome;
+ entryCacheEnvConfig = newEnvConfig;
+ entryCacheEnvMutableConfig = newMutableEnvConfig;
break;
case PHASE_APPLY:
- jeCachePercent = newJECachePercent;
try {
- EnvironmentMutableConfig envConfig =
+ newMutableEnvConfig =
entryCacheEnv.getMutableConfig();
- envConfig.setCachePercent((jeCachePercent != 0 ? jeCachePercent :
+ newMutableEnvConfig.setCachePercent((newJECachePercent != 0 ?
+ newJECachePercent :
EnvironmentConfig.DEFAULT.getCachePercent()));
- entryCacheEnv.setMutableConfig(envConfig);
+ entryCacheEnv.setMutableConfig(newMutableEnvConfig);
entryCacheEnv.evictMemory();
} catch (Exception e) {
if (debugEnabled()) {
@@ -1308,12 +1378,11 @@
DirectoryServer.getServerErrorResultCode()
);
}
- jeCacheSize = newJECacheSize;
try {
- EnvironmentMutableConfig envConfig =
+ newMutableEnvConfig =
entryCacheEnv.getMutableConfig();
- envConfig.setCacheSize(jeCacheSize);
- entryCacheEnv.setMutableConfig(envConfig);
+ newMutableEnvConfig.setCacheSize(newJECacheSize);
+ entryCacheEnv.setMutableConfig(newMutableEnvConfig);
entryCacheEnv.evictMemory();
} catch (Exception e) {
if (debugEnabled()) {
@@ -1325,6 +1394,23 @@
DirectoryServer.getServerErrorResultCode()
);
}
+ try {
+ EnvironmentConfig oldEnvConfig = entryCacheEnv.getConfig();
+ newEnvConfig = ConfigurableEnvironment.setJEProperties(
+ oldEnvConfig, newJEProperties, configAttrMap);
+ // This takes care of changes to the JE environment for those
+ // properties that are mutable at runtime.
+ entryCacheEnv.setMutableConfig(newEnvConfig);
+ } catch (Exception e) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ errorHandler.reportError(
+ ERR_FSCACHE_CANNOT_SET_JE_PROPERTIES.get(e.getMessage()),
+ false,
+ DirectoryServer.getServerErrorResultCode()
+ );
+ }
break;
}
@@ -1339,6 +1425,8 @@
setLockTimeout(newLockTimeout);
setIncludeFilters(newIncludeFilters);
setExcludeFilters(newExcludeFilters);
+
+ registeredConfiguration = configuration;
}
return errorHandler.getIsAcceptable();
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 82974fc..d517506 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
@@ -33,9 +33,11 @@
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
+import org.opends.messages.MessageBuilder;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.std.server.EntryCacheCfg;
@@ -58,7 +60,6 @@
import static org.opends.server.loggers.debug.DebugLogger.*;
import static org.opends.messages.ExtensionMessages.*;
-
import static org.opends.server.util.ServerConstants.*;
@@ -100,10 +101,15 @@
// reference is freed.
private ReferenceQueue<CacheEntry> referenceQueue;
+ // Currently registered configuration object.
+ private SoftReferenceEntryCacheCfg registeredConfiguration;
+
private Thread cleanerThread;
private volatile boolean shutdown = false;
+
+
static
{
timeUnits.put(TIME_UNIT_MILLISECONDS_ABBR, 1D);
@@ -148,6 +154,7 @@
)
throws ConfigException, InitializationException
{
+ registeredConfiguration = configuration;
configuration.addSoftReferenceChangeListener (this);
configEntryDN = configuration.dn();
@@ -156,11 +163,25 @@
// Read configuration and apply changes.
boolean applyChanges = true;
+ ArrayList<Message> errorMessages = new ArrayList<Message>();
EntryCacheCommon.ConfigErrorHandler errorHandler =
EntryCacheCommon.getConfigErrorHandler (
- EntryCacheCommon.ConfigPhase.PHASE_INIT, null, null
+ EntryCacheCommon.ConfigPhase.PHASE_INIT, null, errorMessages
);
- processEntryCacheConfig (configuration, applyChanges, errorHandler);
+ if (!processEntryCacheConfig(configuration, applyChanges, errorHandler)) {
+ MessageBuilder buffer = new MessageBuilder();
+ if (!errorMessages.isEmpty()) {
+ Iterator<Message> iterator = errorMessages.iterator();
+ buffer.append(iterator.next());
+ while (iterator.hasNext()) {
+ buffer.append(". ");
+ buffer.append(iterator.next());
+ }
+ }
+ Message message = ERR_SOFTREFCACHE_CANNOT_INITIALIZE.get(
+ buffer.toString());
+ throw new ConfigException(message);
+ }
}
@@ -170,7 +191,10 @@
*/
public synchronized void finalizeEntryCache()
{
+ registeredConfiguration.removeSoftReferenceChangeListener (this);
+
shutdown = true;
+
dnMap.clear();
idMap.clear();
if (cleanerThread != null) {
@@ -510,9 +534,12 @@
EntryCacheCommon.getConfigErrorHandler (
EntryCacheCommon.ConfigPhase.PHASE_APPLY, null, errorMessages
);
- processEntryCacheConfig (configuration, applyChanges, errorHandler);
+ // Do not apply changes unless this cache is enabled.
+ if (configuration.isEnabled()) {
+ processEntryCacheConfig (configuration, applyChanges, errorHandler);
+ }
- boolean adminActionRequired = false;
+ boolean adminActionRequired = errorHandler.getIsAdminActionRequired();
ConfigChangeResult changeResult = new ConfigChangeResult(
errorHandler.getResultCode(),
adminActionRequired,
@@ -530,8 +557,8 @@
* @param applyChanges If true then take into account the new configuration.
* @param errorHandler An handler used to report errors.
*
- * @return The mapping between strings of character set values and the
- * minimum number of characters required from those sets.
+ * @return <CODE>true</CODE> if configuration is acceptable,
+ * or <CODE>false</CODE> otherwise.
*/
public boolean processEntryCacheConfig(
SoftReferenceEntryCacheCfg configuration,
@@ -594,6 +621,8 @@
setLockTimeout(newLockTimeout);
setIncludeFilters(newIncludeFilters);
setExcludeFilters(newExcludeFilters);
+
+ registeredConfiguration = configuration;
}
return errorHandler.getIsAcceptable();
--
Gitblit v1.10.0