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