From 100e551066fc2b42a7578906a0a7a734896a2961 Mon Sep 17 00:00:00 2001
From: abobrov <abobrov@localhost>
Date: Tue, 08 Jan 2008 10:13:19 +0000
Subject: [PATCH] - [Issue 1595] need a fast way to prime the FileSystemEntryCache: Add generic entry cache pre-load mechanism which is backend and entry cache implementations independent.
---
opends/resource/schema/02-config.ldif | 13
opends/src/server/org/opends/server/core/EntryCacheConfigManager.java | 10
opends/src/admin/defn/org/opends/server/admin/std/DefaultEntryCacheConfiguration.xml | 69 ++++
opends/src/server/org/opends/server/backends/BackupBackend.java | 13
opends/src/server/org/opends/server/api/Backend.java | 23 +
opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml | 13
opends/resource/config/config.ldif | 3
opends/src/server/org/opends/server/backends/LDIFBackend.java | 20 +
opends/src/server/org/opends/server/backends/MemoryBackend.java | 15
opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PreloadEntryCacheTestCase.java | 235 +++++++++++++
opends/src/server/org/opends/server/backends/MonitorBackend.java | 14
opends/src/server/org/opends/server/extensions/EntryCachePreloader.java | 386 ++++++++++++++++++++++
opends/src/server/org/opends/server/backends/jeb/BackendImpl.java | 50 ++
opends/src/server/org/opends/server/backends/RootDSEBackend.java | 13
opends/src/server/org/opends/server/backends/TrustStoreBackend.java | 14
opends/src/server/org/opends/server/extensions/ConfigFileHandler.java | 14
opends/src/server/org/opends/server/replication/server/ReplicationBackend.java | 14
opends/src/messages/messages/extension.properties | 19 +
opends/src/server/org/opends/server/backends/SchemaBackend.java | 14
opends/src/server/org/opends/server/backends/task/TaskBackend.java | 14
20 files changed, 948 insertions(+), 18 deletions(-)
diff --git a/opends/resource/config/config.ldif b/opends/resource/config/config.ldif
index 308bff9..8e6d921 100644
--- a/opends/resource/config/config.ldif
+++ b/opends/resource/config/config.ldif
@@ -20,7 +20,7 @@
#
# CDDL HEADER END
#
-# Portions Copyright 2006-2007 Sun Microsystems, Inc.
+# Portions Copyright 2006-2008 Sun Microsystems, Inc.
#
#
# This file contains the primary Directory Server configuration. It must not
@@ -490,6 +490,7 @@
dn: cn=Entry Caches,cn=config
objectClass: top
objectClass: ds-cfg-branch
+objectClass: ds-cfg-default-entry-cache
cn: Entry Caches
dn: cn=FIFO,cn=Entry Caches,cn=config
diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index 3b6cb05..a88fbdf 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -21,7 +21,7 @@
# CDDL HEADER END
#
#
-# Portions Copyright 2006-2007 Sun Microsystems, Inc.
+# Portions Copyright 2006-2008 Sun Microsystems, Inc.
#
#
# This file contains the attribute type and objectclass definitions for use
@@ -2177,6 +2177,11 @@
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.446
+ NAME 'ds-cfg-cache-preload'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
+ SINGLE-VALUE
+ X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
NAME 'ds-cfg-access-control-handler'
SUP top
@@ -3677,3 +3682,9 @@
STRUCTURAL
MUST ( ds-cfg-backend )
X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.180
+ NAME 'ds-cfg-default-entry-cache'
+ SUP ds-cfg-branch
+ STRUCTURAL
+ MAY ds-cfg-cache-preload
+ X-ORIGIN 'OpenDS Directory Server' )
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/DefaultEntryCacheConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/DefaultEntryCacheConfiguration.xml
new file mode 100644
index 0000000..24d568d
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/DefaultEntryCacheConfiguration.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ! CDDL HEADER START
+ !
+ ! The contents of this file are subject to the terms of the
+ ! Common Development and Distribution License, Version 1.0 only
+ ! (the "License"). You may not use this file except in compliance
+ ! with the License.
+ !
+ ! You can obtain a copy of the license at
+ ! trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ ! or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ ! See the License for the specific language governing permissions
+ ! and limitations under the License.
+ !
+ ! When distributing Covered Code, include this CDDL HEADER in each
+ ! file and include the License file at
+ ! trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ ! add the following below this CDDL HEADER, with the fields enclosed
+ ! by brackets "[]" replaced with your own identifying information:
+ ! Portions Copyright [yyyy] [name of copyright owner]
+ !
+ ! CDDL HEADER END
+ !
+ !
+ ! Portions Copyright 2008 Sun Microsystems, Inc.
+ ! -->
+<adm:managed-object name="default-entry-cache" plural-name="default-entry-cache"
+ package="org.opends.server.admin.std"
+ xmlns:adm="http://www.opends.org/admin"
+ xmlns:ldap="http://www.opends.org/admin-ldap"
+ xmlns:cli="http://www.opends.org/admin-cli">
+ <adm:synopsis>
+ <adm:user-friendly-name />
+ represents the Directory Server entry cache framework.
+ </adm:synopsis>
+ <adm:tag name="database" />
+ <adm:profile name="ldap">
+ <ldap:object-class>
+ <ldap:name>ds-cfg-default-entry-cache</ldap:name>
+ <ldap:superior>ds-cfg-branch</ldap:superior>
+ </ldap:object-class>
+ </adm:profile>
+ <adm:profile name="cli">
+ <cli:managed-object custom="true" />
+ </adm:profile>
+ <adm:property name="cache-preload" mandatory="false">
+ <adm:synopsis>
+ Indicates whether or not to preload the entry cache on startup.
+ </adm:synopsis>
+ <adm:requires-admin-action>
+ <adm:server-restart />
+ </adm:requires-admin-action>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>false</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:boolean />
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:name>ds-cfg-cache-preload</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+
+</adm:managed-object>
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
index a61c45e..67334c8 100644
--- a/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
+++ b/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
@@ -23,7 +23,7 @@
! CDDL HEADER END
!
!
- ! Portions Copyright 2007 Sun Microsystems, Inc.
+ ! Portions Copyright 2007-2008 Sun Microsystems, Inc.
! -->
<adm:root-managed-object xmlns:adm="http://www.opends.org/admin"
xmlns:ldap="http://www.opends.org/admin-ldap"
@@ -203,6 +203,17 @@
</cli:relation>
</adm:profile>
</adm:relation>
+ <adm:relation name="default-entry-cache">
+ <adm:one-to-one />
+ <adm:profile name="ldap">
+ <ldap:rdn-sequence>cn=Entry Caches,cn=config</ldap:rdn-sequence>
+ </adm:profile>
+ <adm:profile name="cli">
+ <cli:relation>
+ <cli:default-property name="cache-preload" />
+ </cli:relation>
+ </adm:profile>
+ </adm:relation>
<adm:relation name="entry-cache">
<adm:one-to-many />
<adm:profile name="ldap">
diff --git a/opends/src/messages/messages/extension.properties b/opends/src/messages/messages/extension.properties
index f4100b1..12eaff6 100644
--- a/opends/src/messages/messages/extension.properties
+++ b/opends/src/messages/messages/extension.properties
@@ -20,7 +20,7 @@
#
# CDDL HEADER END
#
-# Portions Copyright 2006-2007 Sun Microsystems, Inc.
+# Portions Copyright 2006-2008 Sun Microsystems, Inc.
@@ -72,6 +72,21 @@
to initialize fifo entry cache: %s
FATAL_ERR_SOFTREFCACHE_CANNOT_INITIALIZE_9=A fatal error occurred while \
trying to initialize soft reference entry cache: %s
+NOTICE_CACHE_PRELOAD_PROGRESS_START_10=Starting the entry cache preload
+NOTICE_CACHE_PRELOAD_PROGRESS_REPORT_11=The entry cache preload has processed \
+ %d entries, %d MB free heap memory available
+NOTICE_CACHE_PRELOAD_PROGRESS_DONE_12=The entry cache preload is complete \
+ with the total of %d entries processed
+SEVERE_WARN_CACHE_PRELOAD_INTERRUPTED_13=The entry cache preload has been \
+ interrupted
+SEVERE_ERR_CACHE_PRELOAD_COLLECTOR_FAILED_14=The entry cache preload was \
+ unable to complete collector processing for %s backend, and as a result \
+ the entry cache preload for this backend will be incomplete
+SEVERE_WARN_CACHE_PRELOAD_BACKEND_FAILED_15=The entry cache preload is not \
+ supported by %s backend, and as a result no entries from this backend will \
+ be preloaded onto the entry cache
+SEVERE_ERR_CACHE_PRELOAD_ENTRY_FAILED_16=Failed to preload %s entry onto \
+ the entry cache: %s
MILD_ERR_EXTOP_PASSMOD_ILLEGAL_REQUEST_ELEMENT_TYPE_32=The password modify \
extended request sequence included an ASN.1 element of an invalid type: %s
MILD_ERR_EXTOP_PASSMOD_CANNOT_DECODE_REQUEST_33=An unexpected error occurred \
@@ -1613,4 +1628,4 @@
SEVERE_ERR_SDTUACM_ATTR_UNINDEXED_569=The subject DN to user attribute \
certificate mapper defined in configuration entry %s references attribute \
type %s which is does not have an equality index defined in backend %s
-
+
diff --git a/opends/src/server/org/opends/server/api/Backend.java b/opends/src/server/org/opends/server/api/Backend.java
index fc26580..3775e7a 100644
--- a/opends/src/server/org/opends/server/api/Backend.java
+++ b/opends/src/server/org/opends/server/api/Backend.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2008 Sun Microsystems, Inc.
*/
package org.opends.server.api;
import org.opends.messages.Message;
@@ -30,6 +30,7 @@
import java.util.ArrayList;
+import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -210,6 +211,26 @@
/**
+ * Retrieves the set of all DNs that are stored within this backend.
+ * Note that this can be a slow operation depending on a particular
+ * backend implementation and might be unsupported by some backends.
+ *
+ * @param storedDNs Collection to retrieve all stored DNs into.
+ * Note that for async operation a thread-safe collection
+ * should be used.
+ *
+ * @return {@code true} if all DNs stored within this backend were
+ * successfully retrieved, or {@code false} otherwise.
+ *
+ * @throws UnsupportedOperationException if backend implementation
+ * does not support this operation.
+ */
+ public abstract boolean collectStoredDNs(Collection<DN> storedDNs)
+ throws UnsupportedOperationException;
+
+
+
+ /**
* Indicates whether the data associated with this backend may be
* considered local (i.e., in a repository managed by the Directory
* Server) rather than remote (i.e., in an external repository
diff --git a/opends/src/server/org/opends/server/backends/BackupBackend.java b/opends/src/server/org/opends/server/backends/BackupBackend.java
index bc024fd..68f1dd0 100644
--- a/opends/src/server/org/opends/server/backends/BackupBackend.java
+++ b/opends/src/server/org/opends/server/backends/BackupBackend.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2008 Sun Microsystems, Inc.
*/
package org.opends.server.backends;
@@ -1297,5 +1297,16 @@
new AttributeValue(rdnAttrType, rdnStringValue);
return parentDN.concat(RDN.create(rdnAttrType, attrValue));
}
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean collectStoredDNs(Collection<DN> storedDNs)
+ throws UnsupportedOperationException
+ {
+ throw new UnsupportedOperationException("Operation not supported.");
+ }
}
diff --git a/opends/src/server/org/opends/server/backends/LDIFBackend.java b/opends/src/server/org/opends/server/backends/LDIFBackend.java
index e1251b4..1e06268 100644
--- a/opends/src/server/org/opends/server/backends/LDIFBackend.java
+++ b/opends/src/server/org/opends/server/backends/LDIFBackend.java
@@ -22,13 +22,14 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2007 Sun Microsystems, Inc.
+ * Portions Copyright 2007-2008 Sun Microsystems, Inc.
*/
package org.opends.server.backends;
import java.io.File;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -1572,5 +1573,22 @@
return alerts;
}
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean collectStoredDNs(Collection<DN> storedDNs)
+ throws UnsupportedOperationException
+ {
+ backendLock.readLock().lock();
+ try {
+ storedDNs.addAll(entryMap.keySet());
+ return true;
+ } finally {
+ backendLock.readLock().unlock();
+ }
+ }
}
diff --git a/opends/src/server/org/opends/server/backends/MemoryBackend.java b/opends/src/server/org/opends/server/backends/MemoryBackend.java
index 9ec6f22..e3524e8 100644
--- a/opends/src/server/org/opends/server/backends/MemoryBackend.java
+++ b/opends/src/server/org/opends/server/backends/MemoryBackend.java
@@ -22,12 +22,13 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2008 Sun Microsystems, Inc.
*/
package org.opends.server.backends;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -987,5 +988,17 @@
Message message = ERR_MEMORYBACKEND_BACKUP_RESTORE_NOT_SUPPORTED.get();
throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message);
}
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized boolean collectStoredDNs(Collection<DN> storedDNs)
+ throws UnsupportedOperationException
+ {
+ storedDNs.addAll(entryMap.keySet());
+ return true;
+ }
}
diff --git a/opends/src/server/org/opends/server/backends/MonitorBackend.java b/opends/src/server/org/opends/server/backends/MonitorBackend.java
index 504e064..1b739d6 100644
--- a/opends/src/server/org/opends/server/backends/MonitorBackend.java
+++ b/opends/src/server/org/opends/server/backends/MonitorBackend.java
@@ -22,13 +22,14 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2008 Sun Microsystems, Inc.
*/
package org.opends.server.backends;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -1276,5 +1277,16 @@
currentConfig = backendCfg;
return new ConfigChangeResult(resultCode, adminActionRequired, messages);
}
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean collectStoredDNs(Collection<DN> storedDNs)
+ throws UnsupportedOperationException
+ {
+ throw new UnsupportedOperationException("Operation not supported.");
+ }
}
diff --git a/opends/src/server/org/opends/server/backends/RootDSEBackend.java b/opends/src/server/org/opends/server/backends/RootDSEBackend.java
index 959d022..f68a60b 100644
--- a/opends/src/server/org/opends/server/backends/RootDSEBackend.java
+++ b/opends/src/server/org/opends/server/backends/RootDSEBackend.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2008 Sun Microsystems, Inc.
*/
package org.opends.server.backends;
@@ -1529,5 +1529,16 @@
return new ConfigChangeResult(resultCode, adminActionRequired, messages);
}
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean collectStoredDNs(Collection<DN> storedDNs)
+ throws UnsupportedOperationException
+ {
+ throw new UnsupportedOperationException("Operation not supported.");
+ }
}
diff --git a/opends/src/server/org/opends/server/backends/SchemaBackend.java b/opends/src/server/org/opends/server/backends/SchemaBackend.java
index de9f810..e70a6e4 100644
--- a/opends/src/server/org/opends/server/backends/SchemaBackend.java
+++ b/opends/src/server/org/opends/server/backends/SchemaBackend.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2008 Sun Microsystems, Inc.
*/
package org.opends.server.backends;
@@ -37,6 +37,7 @@
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@@ -5575,5 +5576,16 @@
return
new Attribute(attributeTypesType, ATTR_ATTRIBUTE_TYPES, valueSetCopy);
}
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean collectStoredDNs(Collection<DN> storedDNs)
+ throws UnsupportedOperationException
+ {
+ throw new UnsupportedOperationException("Operation not supported.");
+ }
}
diff --git a/opends/src/server/org/opends/server/backends/TrustStoreBackend.java b/opends/src/server/org/opends/server/backends/TrustStoreBackend.java
index 678dd60..d4db669 100644
--- a/opends/src/server/org/opends/server/backends/TrustStoreBackend.java
+++ b/opends/src/server/org/opends/server/backends/TrustStoreBackend.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2007 Sun Microsystems, Inc.
+ * Portions Copyright 2007-2008 Sun Microsystems, Inc.
*/
package org.opends.server.backends;
@@ -42,6 +42,7 @@
import java.security.KeyStoreException;
import java.security.cert.Certificate;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -1898,5 +1899,16 @@
}
}
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean collectStoredDNs(Collection<DN> storedDNs)
+ throws UnsupportedOperationException
+ {
+ throw new UnsupportedOperationException("Operation not supported.");
+ }
}
diff --git a/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java b/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java
index 7a16bdf..bbdb7a8 100644
--- a/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java
+++ b/opends/src/server/org/opends/server/backends/jeb/BackendImpl.java
@@ -22,9 +22,12 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ * Portions Copyright 2007-2008 Sun Microsystems, Inc.
*/
package org.opends.server.backends.jeb;
+import com.sleepycat.je.Cursor;
+import com.sleepycat.je.CursorConfig;
+import com.sleepycat.je.DatabaseEntry;
import org.opends.messages.Message;
import java.io.IOException;
@@ -39,6 +42,8 @@
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.EnvironmentConfig;
+import com.sleepycat.je.LockMode;
+import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.RunRecoveryException;
import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn;
@@ -67,6 +72,8 @@
import org.opends.server.admin.std.server.LocalDBBackendCfg;
import org.opends.server.admin.Configuration;
import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.types.DN;
/**
* This is an implementation of a Directory Server Backend which stores entries
@@ -1729,4 +1736,45 @@
throw new InitializationException(message, e);
}
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean collectStoredDNs(Collection<DN> storedDNs)
+ throws UnsupportedOperationException
+ {
+ for (EntryContainer entryContainer : rootContainer.getEntryContainers()) {
+ DN2ID dn2id = entryContainer.getDN2ID();
+ Cursor cursor = null;
+ try {
+ cursor = dn2id.openCursor(null, new CursorConfig());
+ DatabaseEntry key = new DatabaseEntry();
+ DatabaseEntry data = new DatabaseEntry();
+ OperationStatus status;
+ for (status = cursor.getFirst(key, data, LockMode.DEFAULT);
+ status == OperationStatus.SUCCESS;
+ status = cursor.getNext(key, data, LockMode.DEFAULT)) {
+ DN entryDN = DN.decode(new ASN1OctetString(key.getData()));
+ storedDNs.add(entryDN);
+ }
+ } catch (Exception e) {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ return false;
+ } finally {
+ if (cursor != null) {
+ try {
+ cursor.close();
+ } catch (DatabaseException de) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
+ }
+ }
+ }
+ }
+ return true;
+ }
}
diff --git a/opends/src/server/org/opends/server/backends/task/TaskBackend.java b/opends/src/server/org/opends/server/backends/task/TaskBackend.java
index e81ff8a..631be58 100644
--- a/opends/src/server/org/opends/server/backends/task/TaskBackend.java
+++ b/opends/src/server/org/opends/server/backends/task/TaskBackend.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2008 Sun Microsystems, Inc.
*/
package org.opends.server.backends.task;
@@ -31,6 +31,7 @@
import java.io.File;
import java.net.InetAddress;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -1544,5 +1545,16 @@
{
return taskScheduler.getRecurringTask(taskEntryDN);
}
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean collectStoredDNs(Collection<DN> storedDNs)
+ throws UnsupportedOperationException
+ {
+ throw new UnsupportedOperationException("Operation not supported.");
+ }
}
diff --git a/opends/src/server/org/opends/server/core/EntryCacheConfigManager.java b/opends/src/server/org/opends/server/core/EntryCacheConfigManager.java
index c803931..21ce273 100644
--- a/opends/src/server/org/opends/server/core/EntryCacheConfigManager.java
+++ b/opends/src/server/org/opends/server/core/EntryCacheConfigManager.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2008 Sun Microsystems, Inc.
*/
package org.opends.server.core;
import org.opends.messages.Message;
@@ -57,6 +57,7 @@
import org.opends.server.config.ConfigConstants;
import org.opends.server.config.ConfigEntry;
import org.opends.server.extensions.DefaultEntryCache;
+import org.opends.server.extensions.EntryCachePreloader;
import org.opends.server.monitors.EntryCacheMonitorProvider;
import org.opends.server.types.DN;
@@ -225,6 +226,13 @@
}
}
}
+
+ // If requested preload the entry cache.
+ if (rootConfiguration.getDefaultEntryCache().isCachePreload()) {
+ // Kick off preload arbiter main thread.
+ EntryCachePreloader preloadThread = new EntryCachePreloader();
+ preloadThread.start();
+ }
}
diff --git a/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java b/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
index 6b57243..90e2ff5 100644
--- a/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
+++ b/opends/src/server/org/opends/server/extensions/ConfigFileHandler.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2006-2007 Sun Microsystems, Inc.
+ * Portions Copyright 2006-2008 Sun Microsystems, Inc.
*/
package org.opends.server.extensions;
@@ -36,6 +36,7 @@
import java.io.OutputStream;
import java.security.MessageDigest;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
@@ -3615,5 +3616,16 @@
logError(message);
}
}
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean collectStoredDNs(Collection<DN> storedDNs)
+ throws UnsupportedOperationException
+ {
+ throw new UnsupportedOperationException("Operation not supported.");
+ }
}
diff --git a/opends/src/server/org/opends/server/extensions/EntryCachePreloader.java b/opends/src/server/org/opends/server/extensions/EntryCachePreloader.java
new file mode 100644
index 0000000..847952e
--- /dev/null
+++ b/opends/src/server/org/opends/server/extensions/EntryCachePreloader.java
@@ -0,0 +1,386 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2008 Sun Microsystems, Inc.
+ */
+
+package org.opends.server.extensions;
+import org.opends.messages.Message;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.Lock;
+import org.opends.server.api.Backend;
+import org.opends.server.api.DirectoryThread;
+import org.opends.server.api.ServerShutdownListener;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.loggers.debug.DebugTracer;
+
+import org.opends.server.types.LockManager;
+import static org.opends.server.util.StaticUtils.*;
+import static org.opends.server.loggers.debug.DebugLogger.*;
+import static org.opends.server.loggers.ErrorLogger.logError;
+import static org.opends.messages.ExtensionMessages.*;
+
+/**
+ * This class defines a utility that will be used to pre-load the Directory
+ * Server entry cache. Pre-loader is multi-threaded and consist of the
+ * following threads:
+ *
+ * - The Arbiter thread which monitors overall pre-load progress and manages
+ * pre-load worker threads by adding or removing them as deemed necessary.
+ *
+ * - The Collector thread which collects all entry DNs stored within every
+ * configured and active backend to a shared object workers consume from.
+ *
+ * - Worker threads which are responsible for monitoring the collector feed
+ * and requesting the actual entries for retrieval and in cache storage.
+ *
+ * This implementation is entry cache and backend independent and can be
+ * used to pre-load from any backend to any entry cache as long as both
+ * are capable of initiating and sustaining such pre-load activity.
+ *
+ * This implementation is fully synchronized and safe to use with the server
+ * online which pre-load activities going in parallel with server operations.
+ *
+ * This implementation is self-adjusting to any system workload and does not
+ * require any configuration parameters to optimize for initial system
+ * resources availability and/or any subsequent fluctuations.
+ */
+public class EntryCachePreloader
+ extends DirectoryThread
+ implements ServerShutdownListener
+{
+ /**
+ * The tracer object for the debug logger.
+ */
+ private static final DebugTracer TRACER = getTracer();
+
+ /**
+ * Interrupt flag for the arbiter to terminate worker threads.
+ */
+ private AtomicBoolean interruptFlag = new AtomicBoolean(false);
+
+ /**
+ * Processed entries counter.
+ */
+ private AtomicLong processedEntries = new AtomicLong(0);
+
+ /**
+ * Progress report resolution.
+ */
+ private static final long progressInterval = 5000;
+
+ /**
+ * Default arbiter resolution time.
+ */
+ public static final long
+ PRELOAD_ARBITER_DEFAULT_SLEEP_TIME = 1000;
+
+ /**
+ * Effective arbiter resolution time.
+ */
+ private static long arbiterSleepTime;
+
+ /**
+ * Pre-load arbiter thread name.
+ */
+ private String preloadArbiterThreadName;
+
+ /**
+ * Pre-load arbiter thread.
+ */
+ private Thread preloadArbiterThread;
+
+ /**
+ * Worker threads.
+ */
+ private List<Thread> preloadThreads =
+ Collections.synchronizedList(
+ new LinkedList<Thread>());
+
+ /**
+ * DN Collector thread.
+ */
+ private EntryCacheDNCollector dnCollector =
+ new EntryCacheDNCollector();
+
+ /**
+ * This queue is for workers to take from.
+ */
+ private LinkedBlockingQueue<DN> dnQueue =
+ new LinkedBlockingQueue<DN>();
+
+ /**
+ * The number of bytes in a megabyte.
+ */
+ private static final int bytesPerMegabyte = 1024*1024;
+
+ /**
+ * Default constructor.
+ */
+ public EntryCachePreloader() {
+ super("Entry Cache Preload Arbiter");
+ preloadArbiterThreadName = getName();
+ DirectoryServer.registerShutdownListener(this);
+ // This should not be exposed as configuration
+ // parameter and is only useful for testing.
+ arbiterSleepTime = Long.getLong(
+ "org.opends.server.entrycache.preload.sleep",
+ PRELOAD_ARBITER_DEFAULT_SLEEP_TIME);
+ }
+
+ /**
+ * The Arbiter thread.
+ */
+ @Override
+ public void run() {
+ preloadArbiterThread = Thread.currentThread();
+ logError(NOTE_CACHE_PRELOAD_PROGRESS_START.get());
+ // Start DN collector thread first.
+ dnCollector.start();
+ // Kick off a single worker.
+ EntryCachePreloadWorker singleWorkerThread =
+ new EntryCachePreloadWorker();
+ singleWorkerThread.start();
+ preloadThreads.add(singleWorkerThread);
+ // Progress report timer task.
+ Timer timer = new Timer();
+ TimerTask progressTask = new TimerTask() {
+ // Persistent state restore progress report.
+ public void run() {
+ if (processedEntries.get() > 0) {
+ long freeMemory =
+ Runtime.getRuntime().freeMemory() / bytesPerMegabyte;
+ Message message = NOTE_CACHE_PRELOAD_PROGRESS_REPORT.get(
+ processedEntries.get(), freeMemory);
+ logError(message);
+ }
+ }
+ };
+ timer.scheduleAtFixedRate(progressTask, progressInterval,
+ progressInterval);
+ // Cycle to monitor progress and adjust workers.
+ long processedEntriesDeltaLow = 0;
+ long processedEntriesDeltaHigh = 0;
+ long lastKnownProcessedEntries = 0;
+ try {
+ while (!dnQueue.isEmpty() || dnCollector.isAlive()) {
+ long processedEntriesCycle = processedEntries.get();
+ long processedEntriesDelta =
+ processedEntriesCycle - lastKnownProcessedEntries;
+ lastKnownProcessedEntries = processedEntriesCycle;
+ // Spawn another worker if scaling up.
+ if (processedEntriesDelta > processedEntriesDeltaHigh) {
+ processedEntriesDeltaLow = processedEntriesDeltaHigh;
+ processedEntriesDeltaHigh = processedEntriesDelta;
+ EntryCachePreloadWorker workerThread =
+ new EntryCachePreloadWorker();
+ workerThread.start();
+ preloadThreads.add(workerThread);
+ }
+ // Interrupt random worker if scaling down.
+ if (processedEntriesDelta < processedEntriesDeltaLow) {
+ processedEntriesDeltaHigh = processedEntriesDeltaLow;
+ processedEntriesDeltaLow = processedEntriesDelta;
+ // Leave at least one worker to progress.
+ if (preloadThreads.size() > 1) {
+ interruptFlag.set(true);
+ }
+ }
+ Thread.sleep(arbiterSleepTime);
+ }
+ // Join the collector.
+ dnCollector.join();
+ // Join all spawned workers.
+ for (Thread workerThread : preloadThreads) {
+ workerThread.join();
+ }
+ // Cancel progress report task and report done.
+ timer.cancel();
+ Message message = NOTE_CACHE_PRELOAD_PROGRESS_DONE.get(
+ processedEntries.get());
+ logError(message);
+ } catch (InterruptedException ex) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+ }
+ // Interrupt the collector.
+ dnCollector.interrupt();
+ // Interrupt all preload threads.
+ for (Thread thread : preloadThreads) {
+ thread.interrupt();
+ }
+ logError(WARN_CACHE_PRELOAD_INTERRUPTED.get());
+ } finally {
+ // Kill the task in case of exception.
+ timer.cancel();
+ }
+ }
+
+ /**
+ * The worker thread.
+ */
+ private class EntryCachePreloadWorker extends DirectoryThread {
+ public EntryCachePreloadWorker() {
+ super("Entry Cache Preload Worker");
+ }
+ @Override
+ public void run() {
+ while (!dnQueue.isEmpty() || dnCollector.isAlive()) {
+ // Check if interrupted.
+ if (Thread.interrupted()) {
+ break;
+ }
+ if (interruptFlag.compareAndSet(true, false)) {
+ break;
+ }
+ // Dequeue the next entry DN.
+ try {
+ DN entryDN = dnQueue.take();
+ Lock readLock = null;
+ try {
+ // Acquire a read lock on the entry.
+ readLock = LockManager.lockRead(entryDN);
+ if (readLock == null) {
+ // It is cheaper to put this DN back on the
+ // queue then pick it up and process later.
+ dnQueue.add(entryDN);
+ continue;
+ }
+ // Even if getEntry() below fails the entry is
+ // still treated as a processed entry anyways.
+ processedEntries.getAndIncrement();
+ // getEntry() will trigger putEntryIfAbsent() to the
+ // cache if given entry is not in the cache already.
+ DirectoryServer.getEntry(entryDN);
+ } catch (DirectoryException ex) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+ }
+ Message message = ERR_CACHE_PRELOAD_ENTRY_FAILED.get(
+ entryDN.toNormalizedString(),
+ (ex.getCause() != null ? ex.getCause().getMessage() :
+ stackTraceToSingleLineString(ex)));
+ logError(message);
+ } finally {
+ LockManager.unlock(entryDN, readLock);
+ }
+ } catch (InterruptedException ex) {
+ break;
+ }
+ }
+ preloadThreads.remove(Thread.currentThread());
+ }
+ }
+
+ /**
+ * The Collector thread.
+ */
+ private class EntryCacheDNCollector extends DirectoryThread {
+ public EntryCacheDNCollector() {
+ super("Entry Cache Preload Collector");
+ }
+ @Override
+ public void run() {
+ Map<DN, Backend> baseDNMap =
+ DirectoryServer.getPublicNamingContexts();
+ Set<Backend> proccessedBackends = new HashSet<Backend>();
+ // Collect all DNs from every active public backend.
+ for (Backend backend : baseDNMap.values()) {
+ // Check if interrupted.
+ if (Thread.interrupted()) {
+ return;
+ }
+ if (!proccessedBackends.contains(backend)) {
+ proccessedBackends.add(backend);
+ try {
+ if (!backend.collectStoredDNs(dnQueue)) {
+ // DN collection is incomplete, likely
+ // due to some backend problem occured.
+ // Log an error message and carry on.
+ Message message =
+ ERR_CACHE_PRELOAD_COLLECTOR_FAILED.get(
+ backend.getBackendID());
+ logError(message);
+ }
+ } catch (UnsupportedOperationException ex) {
+ // Some backends dont have collectStoredDNs()
+ // method implemented, log a warning, skip
+ // such backend and continue.
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+ }
+ Message message =
+ WARN_CACHE_PRELOAD_BACKEND_FAILED.get(
+ backend.getBackendID());
+ logError(message);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getShutdownListenerName() {
+ return preloadArbiterThreadName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void processServerShutdown(Message reason) {
+ if ((preloadArbiterThread != null) &&
+ preloadArbiterThread.isAlive()) {
+ // Interrupt the arbiter so it can interrupt
+ // the collector and all spawned workers.
+ preloadArbiterThread.interrupt();
+ try {
+ // This should be quick although if it
+ // gets interrupted it is no big deal.
+ preloadArbiterThread.join();
+ } catch (InterruptedException ex) {
+ if (debugEnabled()) {
+ TRACER.debugCaught(DebugLogLevel.ERROR, ex);
+ }
+ }
+ }
+ DirectoryServer.deregisterShutdownListener(this);
+ }
+}
diff --git a/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java b/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java
index 74b3fd5..bace04f 100644
--- a/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java
+++ b/opends/src/server/org/opends/server/replication/server/ReplicationBackend.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Portions Copyright 2007 Sun Microsystems, Inc.
+ * Portions Copyright 2007-2008 Sun Microsystems, Inc.
*/
package org.opends.server.replication.server;
import static org.opends.messages.BackendMessages.*;
@@ -40,6 +40,7 @@
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -1325,5 +1326,16 @@
return new LDIFReader(config);
}
}
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean collectStoredDNs(Collection<DN> storedDNs)
+ throws UnsupportedOperationException
+ {
+ throw new UnsupportedOperationException("Operation not supported.");
+ }
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PreloadEntryCacheTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PreloadEntryCacheTestCase.java
new file mode 100644
index 0000000..c2e5f0b
--- /dev/null
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/extensions/PreloadEntryCacheTestCase.java
@@ -0,0 +1,235 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.extensions;
+
+
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+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.core.DirectoryServer;
+import org.opends.server.types.Entry;
+import org.opends.server.util.ServerConstants;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+
+
+/**
+ * The entry cache pre-load test class.
+ */
+@Test(groups = { "entrycache", "slow" }, sequential=true)
+public class PreloadEntryCacheTestCase
+ extends ExtensionsTestCase
+{
+ /**
+ * Number of unique dummy test entries.
+ */
+ protected int NUMTESTENTRIES = 1000;
+
+ /**
+ * Dummy test entries.
+ */
+ protected ArrayList<Entry> testEntriesList;
+
+ /**
+ * Entry cache configuration instance.
+ */
+ protected EntryCacheCfg configuration;
+
+ /**
+ * Initialize the entry cache pre-load test.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @BeforeClass()
+ @SuppressWarnings("unchecked")
+ public void preloadEntryCacheTestInit()
+ throws Exception
+ {
+ // Ensure that the server is running.
+ TestCaseUtils.startServer();
+
+ // Initialize a backend with a base entry.
+ TestCaseUtils.clearJEBackend(true, "userRoot", "dc=example,dc=com");
+
+ // Configure the entry cache, use FileSystemEntryCache.
+ Entry cacheConfigEntry = 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: 1",
+ "ds-cfg-java-class: " +
+ "org.opends.server.extensions.FileSystemEntryCache",
+ "ds-cfg-enabled: true");
+ configuration = AdminTestCaseUtils.getConfiguration(
+ EntryCacheCfgDefn.getInstance(), cacheConfigEntry);
+
+ // Make some dummy test entries.
+ testEntriesList = new ArrayList<Entry>(NUMTESTENTRIES);
+ for(int i = 0; i < NUMTESTENTRIES; i++ ) {
+ Entry testEntry = TestCaseUtils.makeEntry(
+ "dn: uid=test" + Integer.toString(i) + ".user" + Integer.toString(i)
+ + ",dc=example,dc=com",
+ "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)
+ );
+ testEntriesList.add(testEntry);
+ TestCaseUtils.addEntry(testEntry);
+ }
+
+ // Initialize the cache reflecting on DirectoryServer
+ // and EntryCacheConfigManager.
+ final Field[] directoryFields =
+ DirectoryServer.class.getDeclaredFields();
+ for (int i = 0; i < directoryFields.length; ++i) {
+ if (directoryFields[i].getName().equals("entryCacheConfigManager")) {
+ directoryFields[i].setAccessible(true);
+ final Method[] cacheManagerMethods =
+ directoryFields[i].getType().getDeclaredMethods();
+ for (int j = 0; j < cacheManagerMethods.length; ++j) {
+ if (cacheManagerMethods[j].getName().equals(
+ "loadAndInstallEntryCache")) {
+ cacheManagerMethods[j].setAccessible(true);
+ cacheManagerMethods[j].invoke(directoryFields[i].get(
+ DirectoryServer.getInstance()),
+ configuration.getJavaClass(), configuration);
+ }
+ }
+ }
+ }
+
+ // Attempt to force GC to possibly free some memory.
+ System.gc();
+ }
+
+
+
+ /**
+ * Tests the entry cache pre-load.
+ */
+ @Test()
+ public void testEntryCachePreload()
+ throws Exception
+ {
+ // Make sure the entry cache is empty.
+ assertNull(toVerboseString(),
+ "Expected empty cache. " + "Cache contents:" + ServerConstants.EOL +
+ toVerboseString());
+
+ // Start pre-load and wait for it to complete.
+ EntryCachePreloader preloadThread = new EntryCachePreloader();
+ preloadThread.start();
+ preloadThread.join();
+
+ // Check that all test entries are preloaded.
+ for(int i = 0; i < NUMTESTENTRIES; i++ ) {
+ assertNotNull(DirectoryServer.getEntryCache().getEntry(
+ testEntriesList.get(i).getDN()), "Expected to find " +
+ testEntriesList.get(i).getDN().toString() +
+ " in the cache. Cache contents:" +
+ ServerConstants.EOL + toVerboseString());
+ }
+ }
+
+
+
+ /**
+ * Finalize the entry cache pre-load test.
+ *
+ * @throws Exception If an unexpected problem occurs.
+ */
+ @AfterClass()
+ public void preloadEntryCacheTestFini()
+ throws Exception
+ {
+ // Clear backend.
+ TestCaseUtils.clearJEBackend(false, "userRoot", "dc=example,dc=com");
+ // Sanity in-core restart.
+ TestCaseUtils.restartServer();
+ // Remove default FS cache JE environment.
+ FileSystemEntryCacheCfg config =
+ (FileSystemEntryCacheCfg) configuration;
+ TestCaseUtils.deleteDirectory(new File(config.getCacheDirectory()));
+ }
+
+
+
+ /**
+ * Reflection of the toVerboseString implementation method.
+ */
+ protected String toVerboseString()
+ throws Exception
+ {
+ final Method[] cacheMethods =
+ DirectoryServer.getEntryCache().getClass().getDeclaredMethods();
+
+ for (int i = 0; i < cacheMethods.length; ++i) {
+ if (cacheMethods[i].getName().equals("toVerboseString")) {
+ cacheMethods[i].setAccessible(true);
+ Object verboseString =
+ cacheMethods[i].invoke(DirectoryServer.getEntryCache(),
+ (Object[]) null);
+ return (String) verboseString;
+ }
+ }
+
+ return null;
+ }
+}
--
Gitblit v1.10.0