001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.api; 028 import org.opends.messages.Message; 029 030 031 032 import java.util.List; 033 034 import org.opends.server.admin.std.server.MonitorProviderCfg; 035 import org.opends.server.config.ConfigException; 036 import org.opends.server.types.Attribute; 037 import org.opends.server.types.DebugLogLevel; 038 import org.opends.server.types.DirectoryConfig; 039 import org.opends.server.types.InitializationException; 040 import org.opends.server.types.ObjectClass; 041 042 import static org.opends.server.loggers.debug.DebugLogger.*; 043 import org.opends.server.loggers.debug.DebugTracer; 044 import static org.opends.server.util.ServerConstants.*; 045 046 047 048 /** 049 * This class defines the set of methods and structures that must be 050 * implemented by a Directory Server module that can provide usage, 051 * performance, availability, or other kinds of monitor information 052 * to clients. 053 * 054 * @param <T> The type of configuration handled by this monitor 055 * provider. 056 */ 057 @org.opends.server.types.PublicAPI( 058 stability=org.opends.server.types.StabilityLevel.VOLATILE, 059 mayInstantiate=false, 060 mayExtend=true, 061 mayInvoke=false) 062 public abstract class MonitorProvider<T extends MonitorProviderCfg> 063 extends DirectoryThread 064 { 065 /** 066 * The tracer object for the debug logger. 067 */ 068 private static final DebugTracer TRACER = getTracer(); 069 070 // Indicates whether a request has been received to stop running. 071 private boolean stopRequested; 072 073 // The thread used to run this monitor provider. 074 private Thread monitorThread; 075 076 077 078 /** 079 * Initializes this monitor provider. Note that no initialization 080 * should be done here, since it should be performed in the 081 * {@code initializeMonitorProvider} class. 082 * 083 * @param threadName The name to use for this thread for debugging 084 * purposes. 085 */ 086 protected MonitorProvider(String threadName) 087 { 088 super(threadName); 089 090 091 stopRequested = false; 092 monitorThread = null; 093 } 094 095 096 097 /** 098 * Initializes this monitor provider based on the information in the 099 * provided configuration entry. 100 * 101 * @param configuration The configuration to use to initialize 102 * this monitor provider. 103 * 104 * @throws ConfigException If an unrecoverable problem arises in 105 * the process of performing the 106 * initialization. 107 * 108 * @throws InitializationException If a problem occurs during 109 * initialization that is not 110 * related to the server 111 * configuration. 112 */ 113 public abstract void initializeMonitorProvider(T configuration) 114 throws ConfigException, InitializationException; 115 116 117 118 /** 119 * Indicates whether the provided configuration is acceptable for 120 * this monitor provider. It should be possible to call this method 121 * on an uninitialized monitor provider instance in order to 122 * determine whether the monitor provider would be able to use the 123 * provided configuration. 124 * <BR><BR> 125 * Note that implementations which use a subclass of the provided 126 * configuration class will likely need to cast the configuration 127 * to the appropriate subclass type. 128 * 129 * @param configuration The monitor provider configuration 130 * for which to make the determination. 131 * @param unacceptableReasons A list that may be used to hold the 132 * reasons that the provided 133 * configuration is not acceptable. 134 * 135 * @return {@code true} if the provided configuration is acceptable 136 * for this monitor provider, or {@code false} if not. 137 */ 138 public boolean isConfigurationAcceptable( 139 MonitorProviderCfg configuration, 140 List<Message> unacceptableReasons) 141 { 142 // This default implementation does not perform any special 143 // validation. It should be overridden by monitor provider 144 // implementations that wish to perform more detailed validation. 145 return true; 146 } 147 148 149 150 /** 151 * Finalizes this monitor provider so that it may be unloaded and 152 * taken out of service. This method should be overridden by any 153 * monitor provider that has resources that should be released when 154 * the monitor is no longer needed. Any monitor that does override 155 * this method must first invoke this version by calling 156 * {@code super.finalizeMonitorProvider}. 157 */ 158 public void finalizeMonitorProvider() 159 { 160 // Signal the monitor thread that it should stop. 161 stopRequested = true; 162 163 try 164 { 165 if (monitorThread != null) 166 { 167 monitorThread.interrupt(); 168 } 169 } 170 catch (Exception e) 171 { 172 if (debugEnabled()) 173 { 174 TRACER.debugCaught(DebugLogLevel.ERROR, e); 175 } 176 } 177 } 178 179 180 181 /** 182 * Retrieves the name of this monitor provider. It should be unique 183 * among all monitor providers, including all instances of the same 184 * monitor provider. 185 * 186 * @return The name of this monitor provider. 187 */ 188 public abstract String getMonitorInstanceName(); 189 190 191 192 /** 193 * Retrieves the objectclass that should be included in the monitor 194 * entry created from this monitor provider. This may be overridden 195 * by subclasses that wish to include their own custom objectclass 196 * in the monitor entry (e.g., to make it easier to search for 197 * monitor entries of that type). The default implementation 198 * returns the "extensibleObject" objectclass. 199 * 200 * @return The objectclass that should be included in the monitor 201 * entry created from this monitor provider. 202 */ 203 public ObjectClass getMonitorObjectClass() 204 { 205 return DirectoryConfig.getObjectClass(OC_EXTENSIBLE_OBJECT_LC, 206 true); 207 } 208 209 210 211 /** 212 * Retrieves the length of time in milliseconds that should elapse 213 * between calls to the {@code updateMonitorData} method. A 214 * negative or zero return value indicates that the 215 * {@code updateMonitorData} method should not be periodically 216 * invoked. 217 * 218 * @return The length of time in milliseconds that should elapse 219 * between calls to the {@code updateMonitorData()} method. 220 */ 221 public abstract long getUpdateInterval(); 222 223 224 225 /** 226 * Performs any processing periodic processing that may be desired 227 * to update the information associated with this monitor. Note 228 * that best-effort attempts will be made to ensure that calls to 229 * this method come {@code getUpdateInterval} milliseconds apart, 230 * but no guarantees will be made. 231 */ 232 public abstract void updateMonitorData(); 233 234 235 236 /** 237 * Retrieves a set of attributes containing monitor data that should 238 * be returned to the client if the corresponding monitor entry is 239 * requested. 240 * 241 * @return A set of attributes containing monitor data that should 242 * be returned to the client if the corresponding monitor 243 * entry is requested. 244 */ 245 public abstract List<Attribute> getMonitorData(); 246 247 248 249 /** 250 * Enters a loop, periodically invoking the 251 * {@code getUpdateInterval} method to updates the data associated 252 * with this monitor. 253 */ 254 public final void run() 255 { 256 monitorThread = Thread.currentThread(); 257 258 259 // If this monitor should not perform any checks to periodically 260 // update its information, then there is no need to run this 261 // method. 262 if (getUpdateInterval() <= 0) 263 { 264 return; 265 } 266 267 268 // Set the name of this thread for debugging purposes. 269 setName(getMonitorInstanceName() + " Monitor Provider"); 270 271 272 // Operate in a loop until it is detected that the server is 273 // shutting down. 274 while (! stopRequested) 275 { 276 long stopSleepTime = 277 System.currentTimeMillis() + getUpdateInterval(); 278 try 279 { 280 updateMonitorData(); 281 } 282 catch (Exception e) 283 { 284 if (debugEnabled()) 285 { 286 TRACER.debugCaught(DebugLogLevel.ERROR, e); 287 } 288 } 289 290 long remainingSleepTime = 291 stopSleepTime - System.currentTimeMillis(); 292 while ((! stopRequested) && (remainingSleepTime > 0)) 293 { 294 if (remainingSleepTime > 1000) 295 { 296 try 297 { 298 Thread.sleep(1000); 299 } catch (Exception e) {} 300 } 301 else 302 { 303 try 304 { 305 Thread.sleep(remainingSleepTime); 306 } catch (Exception e) {} 307 } 308 309 remainingSleepTime = 310 stopSleepTime - System.currentTimeMillis(); 311 } 312 } 313 } 314 } 315