org.jgroups.protocols.FD_ALL Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including
all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and
JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
package org.jgroups.protocols;
import org.jgroups.Address;
import org.jgroups.annotations.ManagedOperation;
import org.jgroups.annotations.Property;
import org.jgroups.conf.AttributeType;
import org.jgroups.util.TimeService;
import org.jgroups.util.Util;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
/**
* Failure detection based on simple heartbeat protocol. Every member periodically multicasts a heartbeat.
* Every member also maintains a table of all members (minus itself). When data or a heartbeat from P is received,
* we reset the timestamp for P to the current time. Periodically, we check for expired members, and suspect those.
* Reduced number of messages exchanged on suspect event: https://issues.redhat.com/browse/JGRP-1241
*
* @author Bela Ban
*/
public class FD_ALL extends FailureDetection {
@Property(description="Interval at which the HEARTBEAT timeouts are checked",type=AttributeType.TIME)
protected long timeout_check_interval=2000;
@Property(description="Uses TimeService to get the current time rather than calling System.nanoTime().")
protected boolean use_time_service=true;
// Map of addresses and timestamps of last updates (ns)
protected final ConcurrentMap timestamps=Util.createConcurrentMap();
protected TimeService time_service;
protected Map getTimestamps() {return timestamps;}
public long getTimeoutCheckInterval() {return timeout_check_interval;}
public T setTimeoutCheckInterval(long i) {this.timeout_check_interval=i; return (T)this;}
@ManagedOperation(description="Prints timestamps")
public String printTimestamps() {
return _printTimestamps();
}
public void init() throws Exception {
super.init();
time_service=getTransport().getTimeService();
if(time_service == null)
log.warn("%s: time service is not available, using System.nanoTime() instead", local_addr);
else {
if(time_service.interval() > timeout) {
log.warn("%s: interval of time service (%d) is greater than timeout (%d), disabling time service",
local_addr, time_service.interval(), timeout);
use_time_service=false;
}
}
if(interval > timeout)
log.warn("interval (%d) is bigger than timeout (%d); this will lead to false suspicions", interval, timeout);
}
@Override protected void update(Address sender, boolean log_msg, boolean skip_if_exists) {
if(sender != null && !sender.equals(local_addr)) {
if(skip_if_exists)
timestamps.putIfAbsent(sender, getTimestamp());
else
timestamps.put(sender, getTimestamp());
}
if(log_msg && log.isTraceEnabled())
log.trace("%s: received heartbeat from %s", local_addr, sender);
}
protected long getTimestamp() {
return use_time_service && time_service != null? time_service.timestamp() : System.nanoTime();
}
protected boolean needsToBeSuspected(Address mbr, T value) {
long val=(long)value;
long diff=TimeUnit.MILLISECONDS.convert(getTimestamp() - val, TimeUnit.NANOSECONDS);
if(diff > timeout) {
log.debug("%s: haven't received a heartbeat from %s for %s ms, adding it to suspect list",
local_addr, mbr, diff);
return true;
}
return false;
}
protected String getTimeoutCheckerInfo() {
return FD_ALL.class.getSimpleName() + ": " + getClass().getSimpleName() + " (interval=" + timeout_check_interval + " ms)";
}
protected String _printTimestamps() {
StringBuilder sb=new StringBuilder();
long current_time=getTimestamp();
for(Iterator> it=timestamps.entrySet().iterator(); it.hasNext();) {
Entry entry=it.next();
sb.append(entry.getKey()).append(": ");
sb.append(TimeUnit.SECONDS.convert (current_time - entry.getValue(), TimeUnit.NANOSECONDS)).append(" secs old\n");
}
return sb.toString();
}
}