/* * 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 2006-2007 Sun Microsystems, Inc. */ package org.opends.server.extensions; import org.opends.messages.Message; 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. */ public class EntryCacheCommon { /** * Configuration phases. Each value identifies a configuration step: * - PHASE_INIT when invoking method initializeEntryCache() * - PHASE_ACCEPTABLE when invoking method isConfigurationChangeAcceptable() * - PHASE_APPLY when invoking method applyConfigurationChange() */ public static enum ConfigPhase { /** * Indicates that entry cache is in initialization check phase. */ PHASE_INIT, /** * Indicates that entry cache is in configuration check phase. */ PHASE_ACCEPTABLE, /** * Indicates that entry cache is applying its configuration. */ PHASE_APPLY } /** * Error handler used by local methods to report configuration error. * The error handler simplifies the code of initializeEntryCache(), * isConfigurationChangeAcceptable() and applyConfigurationChanges() methods. */ public class ConfigErrorHandler { // Configuration phase. private EntryCacheCommon.ConfigPhase _configPhase; // Unacceptable reasons. Used when _configPhase is PHASE_ACCEPTABLE. private List _unacceptableReasons; // Error messages. Used when _configPhase is PHASE_APPLY. private ArrayList _errorMessages; // Result code. Used when _configPhase is PHASE_APPLY. private ResultCode _resultCode; // Acceptable Configuration ? Used when _configPhase is PHASE_ACCEPTABLE // 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. * * @param configPhase the configuration phase for which the * error handler is used * @param unacceptableReasons the reasons why the configuration cannot * be applied (during PHASE_ACCEPTABLE phase) * @param errorMessages the errors found when applying a new * configuration (during PHASE_APPLY phase) */ public ConfigErrorHandler ( EntryCacheCommon.ConfigPhase configPhase, List unacceptableReasons, ArrayList errorMessages ) { _configPhase = configPhase; _unacceptableReasons = unacceptableReasons; _errorMessages = errorMessages; _resultCode = ResultCode.SUCCESS; _isAcceptable = true; _isAdminActionRequired = false; } /** * Report an error. * * @param error the error to report * @param isAcceptable true if the configuration is acceptable * @param resultCode the change result for the current configuration */ public void reportError( Message error, boolean isAcceptable, ResultCode resultCode ) { switch (_configPhase) { 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 true if the configuration is acceptable * @param resultCode the change result for the current configuration * @param isAdminActionRequired true if administrative action * is required or false otherwise */ public void reportError( Message error, boolean isAcceptable, ResultCode resultCode, boolean isAdminActionRequired ) { switch (_configPhase) { case PHASE_INIT: { logError (error); break; } case PHASE_ACCEPTABLE: { _unacceptableReasons.add (error); _isAcceptable = isAcceptable; break; } case PHASE_APPLY: { _errorMessages.add (error); _isAcceptable = isAcceptable; if (_resultCode == ResultCode.SUCCESS) { _resultCode = resultCode; } _isAdminActionRequired = isAdminActionRequired; break; } } } /** * Get the current result code that was elaborated right after a * configuration has been applied. * * @return the current result code */ public ResultCode getResultCode() { return _resultCode; } /** * Get the current isAcceptable flag. The isAcceptable flag is elaborated * right after the configuration was checked. * * @return the isAcceptable flag */ public boolean getIsAcceptable() { return _isAcceptable; } /** * Get the current unacceptable reasons. The unacceptable reasons are * elaborated when the configuration is checked. * * @return the list of unacceptable reasons */ public List getUnacceptableReasons() { return _unacceptableReasons; } /** * Get the current error messages. The error messages are elaborated * when the configuration is applied. * * @return the list of error messages */ public ArrayList getErrorMessages() { return _errorMessages; } /** * Get the current configuration phase. The configuration phase indicates * whether the entry cache is in initialization step, or in configuration * checking step or in configuration being applied step. * * @return the current configuration phase. */ public ConfigPhase getConfigPhase() { 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 /** * Reads a list of string filters and convert it to a list of search * filters. * * @param filters the list of string filter to convert to search filters * @param decodeErrorMsg the error message ID to use in case of error * @param errorHandler error handler to report filter decoding errors on * @param configEntryDN the entry cache configuration DN * * @return the set of search filters */ public static HashSet getFilters ( SortedSet filters, MessageDescriptor.Arg3 decodeErrorMsg, ConfigErrorHandler errorHandler, DN configEntryDN ) { // Returned value HashSet searchFilters = new HashSet(); // Convert the string filters to search filters. if ((filters != null) && (! filters.isEmpty())) { for (String curFilter: filters) { try { searchFilters.add (SearchFilter.createFilterFromString (curFilter)); } catch (DirectoryException de) { // We couldn't decode this filter. Report an error and continue. Message message = decodeErrorMsg.get(String.valueOf(configEntryDN), curFilter, (de.getMessage() != null ? de.getMessage() : stackTraceToSingleLineString(de))); errorHandler.reportError(message, false, ResultCode.INVALID_ATTRIBUTE_SYNTAX); } } } // done return searchFilters; } /** * Create a new error handler. * * @param configPhase the configuration phase for which the * error handler is used * @param unacceptableReasons the reasons why the configuration cannot * be applied (during PHASE_ACCEPTABLE phase) * @param errorMessages the errors found when applying a new * configuration (during PHASE_APPLY phase) * * @return a new configuration error handler */ public static ConfigErrorHandler getConfigErrorHandler ( EntryCacheCommon.ConfigPhase configPhase, List unacceptableReasons, ArrayList errorMessages ) { ConfigErrorHandler errorHandler = null; EntryCacheCommon ec = new EntryCacheCommon(); errorHandler = ec.new ConfigErrorHandler ( configPhase, unacceptableReasons, errorMessages ); return errorHandler; } /** * Constructs a set of generic attributes containing entry cache * monitor data. Note that null 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 getGenericMonitorData( Long cacheHits, Long cacheMisses, Long cacheSize, Long maxCacheSize, Long cacheCount, Long maxCacheCount) { ArrayList attrs = new ArrayList(); if ((cacheHits != null) && (cacheMisses != null)) { AttributeType hitsAttrType = DirectoryServer.getDefaultAttributeType("entryCacheHits"); LinkedHashSet hitsValues = new LinkedHashSet(); hitsValues.add(new AttributeValue(hitsAttrType, cacheHits.toString())); attrs.add(new Attribute(hitsAttrType, "entryCacheHits", hitsValues)); AttributeType triesAttrType = DirectoryServer.getDefaultAttributeType("entryCacheTries"); LinkedHashSet triesValues = new LinkedHashSet(); Long cacheTries = cacheHits + cacheMisses; triesValues.add(new AttributeValue(triesAttrType, cacheTries.toString())); attrs.add(new Attribute(triesAttrType, "entryCacheTries", triesValues)); AttributeType hitRatioAttrType = DirectoryServer.getDefaultAttributeType("entryCacheHitRatio"); LinkedHashSet hitRatioValues = new LinkedHashSet(); 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 memoryValues = new LinkedHashSet(); memoryValues.add(new AttributeValue(memoryAttrType, cacheSize.toString())); attrs.add(new Attribute(memoryAttrType, "currentEntryCacheSize", memoryValues)); } if (maxCacheSize != null) { AttributeType maxMemoryAttrType = DirectoryServer.getDefaultAttributeType("maxEntryCacheSize"); LinkedHashSet maxMemoryValues = new LinkedHashSet(); maxMemoryValues.add(new AttributeValue(maxMemoryAttrType, maxCacheSize.toString())); attrs.add(new Attribute(maxMemoryAttrType, "maxEntryCacheSize", maxMemoryValues)); } if (cacheCount != null) { AttributeType entriesAttrType = DirectoryServer.getDefaultAttributeType("currentEntryCacheCount"); LinkedHashSet entriesValues = new LinkedHashSet(); entriesValues.add(new AttributeValue(entriesAttrType, cacheCount.toString())); attrs.add(new Attribute(entriesAttrType, "currentEntryCacheCount", entriesValues)); } if (maxCacheCount != null) { AttributeType maxEntriesAttrType = DirectoryServer.getDefaultAttributeType("maxEntryCacheCount"); LinkedHashSet maxEntriesValues = new LinkedHashSet(); maxEntriesValues.add(new AttributeValue(maxEntriesAttrType, maxCacheCount.toString())); attrs.add(new Attribute(maxEntriesAttrType, "maxEntryCacheCount", maxEntriesValues)); } return attrs; } }