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 2008-2010 Sun Microsystems, Inc.
025 *      Portions Copyright 2011-2015 ForgeRock AS
026 */
027package org.opends.server.replication.server;
028
029import java.util.ArrayList;
030import java.util.Date;
031import java.util.List;
032
033import org.forgerock.i18n.slf4j.LocalizedLogger;
034import org.forgerock.opendj.config.server.ConfigException;
035import org.opends.server.admin.std.server.MonitorProviderCfg;
036import org.opends.server.api.MonitorProvider;
037import org.opends.server.core.DirectoryServer;
038import org.opends.server.replication.common.DSInfo;
039import org.opends.server.replication.common.ServerState;
040import org.opends.server.types.Attribute;
041import org.opends.server.types.AttributeBuilder;
042import org.opends.server.types.Attributes;
043import org.opends.server.types.InitializationException;
044
045/**
046 * This class defines a server handler dedicated to the remote LDAP servers
047 * connected to a remote Replication Server.
048 * This class is necessary because we want to provide monitor entries for them
049 * and because the monitor API only allows one entry by MonitorProvider instance
050 * so that no other class can provide the monitor entry for these objects.
051 *
052 * One instance of this class is created for each instance of remote LDAP server
053 * connected to a remote Replication Server.
054 */
055public class LightweightServerHandler
056  extends MonitorProvider<MonitorProviderCfg>
057{
058  /** The tracer object for the debug logger. */
059  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
060
061  private final ReplicationServerHandler replServerHandler;
062
063  /** All the information for this DS. */
064  private final DSInfo dsInfo;
065
066  /**
067   * Creates a new LightweightServerHandler with the provided serverId,
068   * connected to the remote Replication Server represented by
069   * replServerHandler.
070   *
071   * @param replServerHandler
072   *          The server handler of the RS this remote DS is connected to
073   * @param dsInfo
074   *          all the info for the represented DS
075   */
076  public LightweightServerHandler(ReplicationServerHandler replServerHandler,
077      DSInfo dsInfo)
078  {
079    this.replServerHandler = replServerHandler;
080    this.dsInfo = dsInfo;
081
082    if (logger.isTraceEnabled())
083    {
084      debugInfo("()");
085    }
086  }
087
088  /**
089   * Creates a DSInfo structure representing this remote DS.
090   * @return The DSInfo structure representing this remote DS
091   */
092  public DSInfo toDSInfo()
093  {
094    return dsInfo;
095  }
096
097  /**
098   * Get the serverID associated with this LDAP server / directory server.
099   *
100   * @return The serverId.
101   */
102  public int getServerId()
103  {
104    return dsInfo.getDsId();
105  }
106
107  /**
108   * Start this server handler processing.
109   */
110  public void startHandler()
111  {
112    if (logger.isTraceEnabled())
113    {
114      debugInfo("start");
115    }
116    DirectoryServer.deregisterMonitorProvider(this);
117    DirectoryServer.registerMonitorProvider(this);
118  }
119
120  /**
121   * Stop this server handler processing.
122   */
123  public void stopHandler()
124  {
125    if (logger.isTraceEnabled())
126    {
127      debugInfo("stop");
128    }
129    DirectoryServer.deregisterMonitorProvider(this);
130  }
131
132  private void debugInfo(String message)
133  {
134    final ReplicationServerDomain domain = replServerHandler.getDomain();
135    logger.trace("In " + domain.getLocalRSMonitorInstanceName()
136        + " LWSH for remote server " + getServerId() + " connected to:"
137        + replServerHandler.getMonitorInstanceName() + " " + message);
138  }
139
140  /** {@inheritDoc} */
141  @Override
142  public void initializeMonitorProvider(MonitorProviderCfg configuration)
143                          throws ConfigException,InitializationException
144  {
145    // Nothing to do for now
146  }
147
148  /**
149   * Retrieves the name of this monitor provider.  It should be unique among all
150   * monitor providers, including all instances of the same monitor provider.
151   *
152   * @return  The name of this monitor provider.
153   */
154  @Override
155  public String getMonitorInstanceName()
156  {
157    return "Connected directory server DS(" + dsInfo.getDsId() + ") "
158        + dsInfo.getDsUrl()
159        + ",cn=" + replServerHandler.getMonitorInstanceName();
160  }
161
162  /**
163   * Retrieves a set of attributes containing monitor data that should be
164   * returned to the client if the corresponding monitor entry is requested.
165   *
166   * @return  A set of attributes containing monitor data that should be
167   *          returned to the client if the corresponding monitor entry is
168   *          requested.
169   */
170  @Override
171  public List<Attribute> getMonitorData()
172  {
173    List<Attribute> attributes = new ArrayList<>();
174
175    final int serverId = dsInfo.getDsId();
176    final ReplicationServerDomain domain = replServerHandler.getDomain();
177    attributes.add(Attributes.create("server-id", String.valueOf(serverId)));
178    attributes.add(Attributes.create("domain-name",
179        domain.getBaseDN().toString()));
180    attributes.add(Attributes.create("connected-to",
181        replServerHandler.getMonitorInstanceName()));
182
183    // Retrieves the topology counters
184    final ReplicationDomainMonitorData md = domain.getDomainMonitorData();
185    ServerState remoteState = md.getLDAPServerState(serverId);
186    if (remoteState == null)
187    {
188      remoteState = new ServerState();
189    }
190
191    // get the Server State
192    AttributeBuilder builder = new AttributeBuilder("server-state");
193    builder.addAllStrings(remoteState.toStringSet());
194    if (builder.size() == 0)
195    {
196      builder.add("unknown");
197    }
198    attributes.add(builder.toAttribute());
199
200    // Oldest missing update
201    long approxFirstMissingDate = md.getApproxFirstMissingDate(serverId);
202    if (approxFirstMissingDate > 0)
203    {
204      Date date = new Date(approxFirstMissingDate);
205      attributes.add(Attributes.create(
206          "approx-older-change-not-synchronized", date.toString()));
207      attributes.add(Attributes.create(
208          "approx-older-change-not-synchronized-millis", String
209          .valueOf(approxFirstMissingDate)));
210    }
211
212    // Missing changes
213    long missingChanges = md.getMissingChanges(serverId);
214    attributes.add(Attributes.create("missing-changes",
215        String.valueOf(missingChanges)));
216
217    // Replication delay
218    long delay = md.getApproxDelay(serverId);
219    attributes.add(Attributes.create("approximate-delay",
220        String.valueOf(delay)));
221
222    return attributes;
223  }
224}