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 legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2006-2010 Sun Microsystems, Inc.
025 *      Portions Copyright 2014-2015 ForgeRock AS
026 */
027package org.opends.server.api;
028
029
030import java.util.List;
031import java.util.concurrent.*;
032
033import org.forgerock.i18n.LocalizableMessage;
034import org.forgerock.opendj.config.server.ConfigException;
035import org.opends.server.admin.std.server.MonitorProviderCfg;
036import org.opends.server.types.Attribute;
037import org.opends.server.types.DirectoryConfig;
038import org.opends.server.types.InitializationException;
039import org.opends.server.types.ObjectClass;
040
041import static org.opends.server.util.ServerConstants.*;
042
043/**
044 * This class defines the set of methods and structures that must be
045 * implemented by a Directory Server module that can provide usage,
046 * performance, availability, or other kinds of monitor information
047 * to clients.
048 *
049 * @param  <T>  The type of configuration handled by this monitor
050 *              provider.
051 */
052@org.opends.server.types.PublicAPI(
053     stability=org.opends.server.types.StabilityLevel.VOLATILE,
054     mayInstantiate=false,
055     mayExtend=true,
056     mayInvoke=false)
057public abstract class MonitorProvider<T extends MonitorProviderCfg>
058{
059  /** The scheduler. */
060  private static final ScheduledExecutorService SCHEDULER =
061      Executors.newSingleThreadScheduledExecutor(
062          new MonitorThreadFactory());
063
064  /**
065   * Thread factory used by the scheduled execution service.
066   */
067  private static final class MonitorThreadFactory implements
068      ThreadFactory
069  {
070
071    /** {@inheritDoc} */
072    public Thread newThread(Runnable r)
073    {
074      Thread t =
075          new DirectoryThread(r, "Monitor Provider State Updater");
076      t.setDaemon(true);
077      return t;
078    }
079
080  }
081
082  private ScheduledFuture<?> scheduledFuture;
083
084  /**
085   * Initializes this monitor provider based on the information in the
086   * provided configuration entry.
087   *
088   * @param  configuration  The configuration to use to initialize
089   *                        this monitor provider.
090   *
091   * @throws  ConfigException  If an unrecoverable problem arises in
092   *                           the process of performing the
093   *                           initialization.
094   *
095   * @throws  InitializationException  If a problem occurs during
096   *                                   initialization that is not
097   *                                   related to the server
098   *                                   configuration.
099   */
100  public abstract void initializeMonitorProvider(T configuration)
101         throws ConfigException, InitializationException;
102
103
104
105  /**
106   * Indicates whether the provided configuration is acceptable for
107   * this monitor provider.  It should be possible to call this method
108   * on an uninitialized monitor provider instance in order to
109   * determine whether the monitor provider would be able to use the
110   * provided configuration.
111   * <BR><BR>
112   * Note that implementations which use a subclass of the provided
113   * configuration class will likely need to cast the configuration
114   * to the appropriate subclass type.
115   *
116   * @param  configuration        The monitor provider configuration
117   *                              for which to make the determination.
118   * @param  unacceptableReasons  A list that may be used to hold the
119   *                              reasons that the provided
120   *                              configuration is not acceptable.
121   *
122   * @return  {@code true} if the provided configuration is acceptable
123   *          for this monitor provider, or {@code false} if not.
124   */
125  public boolean isConfigurationAcceptable(
126                      MonitorProviderCfg configuration,
127                      List<LocalizableMessage> unacceptableReasons)
128  {
129    // This default implementation does not perform any special
130    // validation.  It should be overridden by monitor provider
131    // implementations that wish to perform more detailed validation.
132    return true;
133  }
134
135
136
137  /**
138   * Finalizes this monitor provider so that it may be unloaded and
139   * taken out of service.  This method should be overridden by any
140   * monitor provider that has resources that should be released when
141   * the monitor is no longer needed.  Any monitor that does override
142   * this method must first invoke this version by calling
143   * {@code super.finalizeMonitorProvider}.
144   */
145  public void finalizeMonitorProvider()
146  {
147    if(scheduledFuture != null)
148    {
149      scheduledFuture.cancel(true);
150    }
151  }
152
153
154
155  /**
156   * Retrieves the name of this monitor provider.  It should be unique
157   * among all monitor providers, including all instances of the same
158   * monitor provider.
159   *
160   * @return  The name of this monitor provider.
161   */
162  public abstract String getMonitorInstanceName();
163
164
165
166  /**
167   * Retrieves the objectclass that should be included in the monitor
168   * entry created from this monitor provider.  This may be overridden
169   * by subclasses that wish to include their own custom objectclass
170   * in the monitor entry (e.g., to make it easier to search for
171   * monitor entries of that type).  The default implementation
172   * returns the "extensibleObject" objectclass.
173   *
174   * @return  The objectclass that should be included in the monitor
175   *          entry created from this monitor provider.
176   */
177  public ObjectClass getMonitorObjectClass()
178  {
179    return DirectoryConfig.getObjectClass(OC_EXTENSIBLE_OBJECT_LC,
180                                          true);
181  }
182
183
184  /**
185   * Schedules any periodic processing that may be desired
186   * to update the information associated with this monitor.  Note
187   * that best-effort attempts will be made to ensure that calls to
188   * this method come {@code getUpdateInterval} milliseconds apart,
189   * but no guarantees will be made.
190   *
191   * @param updater The updater to execute.
192   * @param initialDelay The time to delay first execution.
193   * @param period The period between successive executions.
194   * @param unit The time unit of the initialDelay and period
195   *             parameters.
196   */
197  protected final void scheduleUpdate(Runnable updater,
198                                      long initialDelay,
199                                      long period, TimeUnit unit)
200  {
201    if(scheduledFuture != null)
202    {
203      scheduledFuture.cancel(true);
204    }
205
206    scheduledFuture =
207        SCHEDULER.scheduleAtFixedRate(updater, initialDelay,
208            period, unit);
209  }
210
211
212
213  /**
214   * Retrieves a set of attributes containing monitor data that should
215   * be returned to the client if the corresponding monitor entry is
216   * requested.
217   *
218   * @return  A set of attributes containing monitor data that should
219   *          be returned to the client if the corresponding monitor
220   *          entry is requested.
221   */
222  public abstract List<Attribute> getMonitorData();
223}
224