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    }