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 032 import java.util.Iterator; 033 import java.util.concurrent.ConcurrentHashMap; 034 035 import org.opends.server.loggers.debug.DebugTracer; 036 import org.opends.server.replication.common.ChangeNumber; 037 import org.opends.server.replication.common.ServerState; 038 import org.opends.server.util.TimeThread; 039 040 /** 041 * This class defines the Monitor Data that are consolidated across the 042 * whole replication topology. 043 */ 044 public class MonitorData 045 { 046 /** 047 * The tracer object for the debug logger. 048 */ 049 private static final DebugTracer TRACER = getTracer(); 050 051 /** 052 * 053 * - For each server, the max (most recent) CN produced 054 * 055 * - For each server, its state i.e. the last processed from of each 056 * other LDAP server. 057 * The change latency (missing changes) will be 058 * the difference between the max above and the state here 059 * 060 * - For each server, the date of the first missing change. 061 * The time latency (delay) will be the difference between now and the 062 * date of the first missing change. 063 */ 064 065 /* The date of the last time they have been elaborated */ 066 private long buildDate = 0; 067 068 // For each LDAP server, its server state 069 private ConcurrentHashMap<Short, ServerState> LDAPStates = 070 new ConcurrentHashMap<Short, ServerState>(); 071 072 // For each LDAP server, the last(max) CN it published 073 private ConcurrentHashMap<Short, ChangeNumber> maxCNs = 074 new ConcurrentHashMap<Short, ChangeNumber>(); 075 076 // For each LDAP server, an approximation of the date of the first missing 077 // change 078 private ConcurrentHashMap<Short, Long> fmd = 079 new ConcurrentHashMap<Short, Long>(); 080 081 private ConcurrentHashMap<Short, Long> missingChanges = 082 new ConcurrentHashMap<Short, Long>(); 083 084 // For each RS server, an approximation of the date of the first missing 085 // change 086 private ConcurrentHashMap<Short, Long> fmRSDate = 087 new ConcurrentHashMap<Short, Long>(); 088 089 090 /** 091 * Get an approximation of the latency delay of the replication. 092 * @param serverId The server ID. 093 * @return The delay 094 */ 095 public long getApproxDelay(short serverId) 096 { 097 Long afmd = fmd.get(serverId); 098 if ((afmd != null) && (afmd>0)) 099 return ((this.getBuildDate() - afmd)/1000); 100 else 101 return 0; 102 } 103 104 /** 105 * Get an approximation of the date of the first missing update. 106 * @param serverId The server ID. 107 * @return The date. 108 */ 109 public long getApproxFirstMissingDate(short serverId) 110 { 111 Long res; 112 if ((res = fmd.get(serverId)) != null) 113 return res; 114 return 0; 115 } 116 117 /** 118 * Get the number of missing changes. 119 * @param serverId The server ID. 120 * @return The number of missing changes. 121 */ 122 public long getMissingChanges(short serverId) 123 { 124 Long res = missingChanges.get(serverId); 125 if (res==null) 126 return 0; 127 else 128 return res; 129 } 130 131 /** 132 * Build the monitor data that are computed from the collected ones. 133 */ 134 public void completeComputing() 135 { 136 String mds = ""; 137 138 // Computes the missing changes counters 139 // For each LSi , 140 // Regarding each other LSj 141 // Sum the difference : max(LSj) - state(LSi) 142 143 Iterator<Short> lsiStateItr = this.LDAPStates.keySet().iterator(); 144 while (lsiStateItr.hasNext()) 145 { 146 Short lsiSid = lsiStateItr.next(); 147 ServerState lsiState = this.LDAPStates.get(lsiSid); 148 Long lsiMissingChanges = (long)0; 149 if (lsiState != null) 150 { 151 Iterator<Short> lsjMaxItr = this.maxCNs.keySet().iterator(); 152 while (lsjMaxItr.hasNext()) 153 { 154 Short lsjSid = lsjMaxItr.next(); 155 ChangeNumber lsjMaxCN = this.maxCNs.get(lsjSid); 156 ChangeNumber lsiLastCN = lsiState.getMaxChangeNumber(lsjSid); 157 158 int missingChangesLsiLsj = 159 ChangeNumber.diffSeqNum(lsjMaxCN, lsiLastCN); 160 161 mds += 162 "+ diff("+lsjMaxCN+"-" 163 +lsiLastCN+")="+missingChangesLsiLsj; 164 165 lsiMissingChanges += missingChangesLsiLsj; 166 } 167 } 168 mds += "=" + lsiMissingChanges; 169 this.missingChanges.put(lsiSid,lsiMissingChanges); 170 171 if (debugEnabled()) 172 TRACER.debugInfo( 173 "Complete monitor data : Missing changes ("+ lsiSid +")=" + mds); 174 } 175 this.setBuildDate(TimeThread.getTime()); 176 } 177 178 /** 179 * Returns a <code>String</code> object representing this 180 * object's value. 181 * @return a string representation of the value of this object in 182 */ 183 public String toString() 184 { 185 String mds = "Monitor data=\n"; 186 187 mds+= "Build date=" + this.getBuildDate(); 188 // RS data 189 Iterator<Short> rsite = fmRSDate.keySet().iterator(); 190 while (rsite.hasNext()) 191 { 192 Short sid = rsite.next(); 193 mds += "\nRSData(" + sid + ")=\t "+ "afmd=" + fmRSDate.get(sid); 194 } 195 196 // maxCNs 197 Iterator<Short> itc = maxCNs.keySet().iterator(); 198 while (itc.hasNext()) 199 { 200 Short sid = itc.next(); 201 ChangeNumber cn = maxCNs.get(sid); 202 mds += "\nmaxCNs(" + sid + ")= " + cn.toString(); 203 } 204 205 // LDAP data 206 Iterator<Short> lsite = LDAPStates.keySet().iterator(); 207 while (lsite.hasNext()) 208 { 209 Short sid = lsite.next(); 210 ServerState ss = LDAPStates.get(sid); 211 mds += "\nLSData(" + sid + ")=\t" + "state=[" + ss.toString() 212 + "] afmd=" + this.getApproxFirstMissingDate(sid); 213 if (getBuildDate()>0) 214 { 215 mds += " missingDelay=" + this.getApproxDelay(sid); 216 } 217 mds +=" missingCount=" + missingChanges.get(sid); 218 } 219 // 220 mds += "--"; 221 return mds; 222 } 223 224 /** 225 * Sets the build date of the data. 226 * @param buildDate The date. 227 */ 228 public void setBuildDate(long buildDate) 229 { 230 this.buildDate = buildDate; 231 } 232 233 /** 234 * Returns the build date of the data. 235 * @return The date. 236 */ 237 public long getBuildDate() 238 { 239 return buildDate; 240 } 241 242 /** 243 * From a provided state, sets the max CN of the monitor data. 244 * @param state the provided state. 245 */ 246 public void setMaxCNs(ServerState state) 247 { 248 Iterator<Short> it = state.iterator(); 249 while (it.hasNext()) 250 { 251 short sid = it.next(); 252 ChangeNumber newCN = state.getMaxChangeNumber(sid); 253 setMaxCN(sid, newCN); 254 } 255 } 256 257 /** 258 * For the provided serverId, sets the provided CN as the max if 259 * it is newer than the current max. 260 * @param serverId the provided serverId 261 * @param newCN the provided new CN 262 */ 263 public void setMaxCN(short serverId, ChangeNumber newCN) 264 { 265 if (newCN==null) return; 266 ChangeNumber currentMaxCN = maxCNs.get(serverId); 267 if (currentMaxCN == null) 268 { 269 maxCNs.put(serverId, newCN); 270 } 271 else 272 { 273 if (newCN.newer(currentMaxCN)) 274 maxCNs.replace(serverId, newCN); 275 } 276 } 277 278 /** 279 * Get the highest know change number of the LDAP server with the provided 280 * serverId. 281 * @param serverId The server ID. 282 * @return The highest change number. 283 */ 284 public ChangeNumber getMaxCN(short serverId) 285 { 286 return maxCNs.get(serverId); 287 } 288 289 /** 290 * Get the state of the LDAP server with the provided serverId. 291 * @param serverId The server ID. 292 * @return The server state. 293 */ 294 public ServerState getLDAPServerState(short serverId) 295 { 296 return LDAPStates.get(serverId); 297 } 298 299 /** 300 * Set the state of the LDAP server with the provided serverId. 301 * @param serverId The server ID. 302 * @param state The server state. 303 */ 304 public void setLDAPServerState(short serverId, ServerState state) 305 { 306 LDAPStates.put(serverId, state); 307 } 308 309 /** 310 * Set the state of the LDAP server with the provided serverId. 311 * @param serverId The server ID. 312 * @param newFmd The first missing date. 313 */ 314 public void setFirstMissingDate(short serverId, Long newFmd) 315 { 316 if (newFmd==null) return; 317 Long currentfmd = fmd.get(serverId); 318 if (currentfmd==null) 319 { 320 fmd.put(serverId, newFmd); 321 } 322 else 323 { 324 if ((newFmd!=0) && (newFmd<currentfmd)) 325 fmd.replace(serverId, newFmd); 326 } 327 } 328 329 }