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 2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.replication.server;
028
029 import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
030 import static org.opends.server.loggers.debug.DebugLogger.getTracer;
031 import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
032
033 import java.util.ArrayList;
034 import java.util.Date;
035 import java.util.LinkedHashSet;
036
037 import org.opends.server.admin.std.server.MonitorProviderCfg;
038 import org.opends.server.api.MonitorProvider;
039 import org.opends.server.config.ConfigException;
040 import org.opends.server.core.DirectoryServer;
041 import org.opends.server.loggers.debug.DebugTracer;
042 import org.opends.server.replication.common.ServerState;
043 import org.opends.server.types.Attribute;
044 import org.opends.server.types.AttributeType;
045 import org.opends.server.types.AttributeValue;
046 import org.opends.server.types.DN;
047 import org.opends.server.types.InitializationException;
048
049 /**
050 * This class defines a server handler dedicated to the remote LDAP servers
051 * connected to a remote Replication Server.
052 * This class is necessary because we want to provide monitor entries for them
053 * and because the monitor API only allows one entry by MonitorProvider instance
054 * so that no other class can provide the monitor entry for these objects.
055 *
056 * One instance of this class is created for each instance of remote LDAP server
057 * connected to a remote Replication Server.
058 */
059 public class LightweightServerHandler
060 extends MonitorProvider<MonitorProviderCfg>
061 {
062 // The tracer object for the debug logger.
063 private static final DebugTracer TRACER = getTracer();
064
065 short serverId;
066 ServerHandler replServerHandler;
067 ReplicationServerDomain rsDomain;
068 DN baseDn;
069
070 /**
071 * Creates a new LighweightServerHandler with the provided serverid, connected
072 * to the remote Replication Server represented by replServerHandler.
073 *
074 * @param serverId The serverId of this remote LDAP server.
075 * @param replServerHandler The server handler of the Replication Server to
076 * which this LDAP server is remotely connected.
077 */
078 public LightweightServerHandler(String serverId,
079 ServerHandler replServerHandler)
080 {
081 super("Server Handler");
082 this.serverId = Short.valueOf(serverId);
083 this.replServerHandler = replServerHandler;
084 this.rsDomain = replServerHandler.getDomain();
085 this.baseDn = rsDomain.getBaseDn();
086
087 if (debugEnabled())
088 TRACER.debugInfo(
089 "In " +
090 replServerHandler.getDomain().getReplicationServer().getMonitorInstanceName()+
091 " LWSH for remote server " + this.serverId +
092 " connected to:" + this.replServerHandler.getMonitorInstanceName() +
093 " ()");
094 }
095
096 /**
097 * Get the serverID associated with this LDAP server.
098 * @return The serverId.
099 */
100 public short getServerId()
101 {
102 return Short.valueOf(serverId);
103 }
104
105 /**
106 * Stop this server handler processing.
107 */
108 public void startHandler()
109 {
110 if (debugEnabled())
111 TRACER.debugInfo(
112 "In " +
113 replServerHandler.getDomain().getReplicationServer().getMonitorInstanceName() +
114 " LWSH for remote server " + this.serverId +
115 " connected to:" + this.replServerHandler.getMonitorInstanceName() +
116 " start");
117 DirectoryServer.deregisterMonitorProvider(getMonitorInstanceName());
118 DirectoryServer.registerMonitorProvider(this);
119
120 }
121
122 /**
123 * Stop this server handler processing.
124 */
125 public void stopHandler()
126 {
127 if (debugEnabled())
128 TRACER.debugInfo(
129 "In " +
130 replServerHandler.getDomain().getReplicationServer().getMonitorInstanceName() +
131 " LWSH for remote server " + this.serverId +
132 " connected to:" + this.replServerHandler.getMonitorInstanceName() +
133 " stop");
134 DirectoryServer.deregisterMonitorProvider(getMonitorInstanceName());
135 }
136
137 /**
138 * {@inheritDoc}
139 */
140 @Override
141 public void initializeMonitorProvider(MonitorProviderCfg configuration)
142 throws ConfigException,InitializationException
143 {
144 // Nothing to do for now
145 }
146
147 /**
148 * Retrieves the name of this monitor provider. It should be unique among all
149 * monitor providers, including all instances of the same monitor provider.
150 *
151 * @return The name of this monitor provider.
152 */
153 @Override
154 public String getMonitorInstanceName()
155 {
156 String serverURL=""; // FIXME
157 String str = baseDn.toString() + " " + serverURL + " "
158 + String.valueOf(serverId);
159 return "Undirect LDAP Server " + str;
160 }
161
162 /**
163 * Retrieves the length of time in milliseconds that should elapse between
164 * calls to the <CODE>updateMonitorData()</CODE> method. A negative or zero
165 * return value indicates that the <CODE>updateMonitorData()</CODE> method
166 * should not be periodically invoked.
167 *
168 * @return The length of time in milliseconds that should elapse between
169 * calls to the <CODE>updateMonitorData()</CODE> method.
170 */
171 @Override
172 public long getUpdateInterval()
173 {
174 /* we don't wont to do polling on this monitor */
175 return 0;
176 }
177
178 /**
179 * Performs any processing periodic processing that may be desired to update
180 * the information associated with this monitor. Note that best-effort
181 * attempts will be made to ensure that calls to this method come
182 * <CODE>getUpdateInterval()</CODE> milliseconds apart, but no guarantees will
183 * be made.
184 */
185 @Override
186 public void updateMonitorData()
187 {
188 // As long as getUpdateInterval() returns 0, this will never get called
189
190 }
191
192 /**
193 * Retrieves a set of attributes containing monitor data that should be
194 * returned to the client if the corresponding monitor entry is requested.
195 *
196 * @return A set of attributes containing monitor data that should be
197 * returned to the client if the corresponding monitor entry is
198 * requested.
199 */
200 @Override
201 public ArrayList<Attribute> getMonitorData()
202 {
203 ArrayList<Attribute> attributes = new ArrayList<Attribute>();
204
205 attributes.add(new Attribute("server-id",
206 String.valueOf(serverId)));
207 attributes.add(new Attribute("base-dn",
208 rsDomain.getBaseDn().toNormalizedString()));
209 attributes.add(new Attribute("connected-to",
210 replServerHandler.getMonitorInstanceName()));
211
212 // Retrieves the topology counters
213 MonitorData md;
214 try
215 {
216 md = rsDomain.getMonitorData();
217
218 ServerState remoteState = md.getLDAPServerState(serverId);
219 if (remoteState == null)
220 {
221 remoteState = new ServerState();
222 }
223
224 /* get the Server State */
225 final String ATTR_SERVER_STATE = "server-state";
226 AttributeType type =
227 DirectoryServer.getDefaultAttributeType(ATTR_SERVER_STATE);
228 LinkedHashSet<AttributeValue> values =
229 new LinkedHashSet<AttributeValue>();
230 for (String str : remoteState.toStringSet())
231 {
232 values.add(new AttributeValue(type,str));
233 }
234 if (values.size() == 0)
235 {
236 values.add(new AttributeValue(type,"unknown"));
237 }
238 Attribute attr = new Attribute(type, ATTR_SERVER_STATE, values);
239 attributes.add(attr);
240
241 // Oldest missing update
242 Long approxFirstMissingDate=md.getApproxFirstMissingDate(serverId);
243 if ((approxFirstMissingDate != null) && (approxFirstMissingDate>0))
244 {
245 Date date = new Date(approxFirstMissingDate);
246 attributes.add(new Attribute("approx-older-change-not-synchronized",
247 date.toString()));
248 attributes.add(
249 new Attribute("approx-older-change-not-synchronized-millis",
250 String.valueOf(approxFirstMissingDate)));
251 }
252
253 // Missing changes
254 long missingChanges = md.getMissingChanges(serverId);
255 attributes.add(new Attribute("missing-changes",
256 String.valueOf(missingChanges)));
257
258 // Replication delay
259 long delay = md.getApproxDelay(serverId);
260 attributes.add(new Attribute("approximate-delay",
261 String.valueOf(delay)));
262
263 }
264 catch(Exception e)
265 {
266 // TODO: improve the log
267 // We failed retrieving the remote monitor data.
268 attributes.add(new Attribute("error",
269 stackTraceToSingleLineString(e)));
270 }
271 return attributes;
272 }
273 }