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 }