001: package org.jgroups.protocols;
002:
003: import org.apache.commons.logging.Log;
004: import org.jgroups.stack.IpAddress;
005: import org.jgroups.util.Util;
006:
007: import java.io.IOException;
008: import java.io.InputStream;
009: import java.io.InputStreamReader;
010: import java.util.Properties;
011:
012: /**
013: * Protocol which uses an executable (e.g. /sbin/ping, or a script) to check whether a given host is up or not,
014: * taking 1 argument; the host name of the host to be pinged. Property 'cmd' determines the program to be executed
015: * (use a fully qualified name if the program is not on the path).
016: * @author Bela Ban
017: * @version $Id: FD_PING.java,v 1.3.2.1 2007/04/27 08:03:51 belaban Exp $
018: */
019: public class FD_PING extends FD {
020: /** Command (script or executable) to ping a host: a return value of 0 means success, anything else is a failure.
021: * The only argument passed to cmd is the host's address (symbolic name or dotted-decimal IP address) */
022: String cmd = "ping";
023:
024: /** Write the stdout of the command to the log */
025: boolean verbose = true;
026:
027: public String getName() {
028: return "FD_PING";
029: }
030:
031: public boolean setProperties(Properties props) {
032: String str;
033: str = props.getProperty("cmd");
034: if (str != null) {
035: cmd = str;
036: props.remove("cmd");
037: }
038:
039: str = props.getProperty("verbose");
040: if (str != null) {
041: verbose = new Boolean(str).booleanValue();
042: props.remove("verbose");
043: }
044:
045: super .setProperties(props);
046:
047: if (props.size() > 0) {
048: log.error("the following properties are not recognized: "
049: + props);
050: return false;
051: }
052: return true;
053: }
054:
055: protected Monitor createMonitor() {
056: return new PingMonitor();
057: }
058:
059: /**
060: * Executes the ping command. Each time the command fails, we increment num_tries. If num_tries > max_tries, we
061: * emit a SUSPECT message. If ping_dest changes, or we do receive traffic from ping_dest, we reset num_tries to 0.
062: */
063: protected class PingMonitor extends Monitor {
064:
065: public void run() {
066: if (ping_dest == null) {
067: if (log.isWarnEnabled())
068: log.warn("ping_dest is null: members=" + members
069: + ", pingable_mbrs=" + pingable_mbrs
070: + ", local_addr=" + local_addr);
071: return;
072: }
073:
074: // 1. execute ping command
075: String host = ping_dest instanceof IpAddress ? ((IpAddress) ping_dest)
076: .getIpAddress().getHostAddress()
077: : ping_dest.toString();
078: String command = cmd + " " + host;
079: if (log.isDebugEnabled())
080: log.debug("executing \"" + command + "\" (own address="
081: + local_addr + ')');
082: try {
083: Log tmp_log = verbose ? log : null;
084: int rc = Pinger.execute(command, tmp_log);
085: num_heartbeats++;
086: if (rc == 0) { // success
087: num_tries = 0;
088: } else { // failure
089: num_tries++;
090: if (log.isDebugEnabled())
091: log.debug("could not ping " + ping_dest
092: + " (tries=" + num_tries + ')');
093: }
094:
095: if (num_tries >= max_tries) {
096: if (log.isDebugEnabled())
097: log.debug("[" + local_addr
098: + "]: could not ping " + ping_dest
099: + " for " + (num_tries + 1)
100: + " times ("
101: + ((num_tries + 1) * timeout)
102: + " milliseconds), suspecting it");
103: // broadcast a SUSPECT message to all members - loop until
104: // unsuspect or view change is received
105: bcast_task.addSuspectedMember(ping_dest);
106: num_tries = 0;
107: if (stats) {
108: num_suspect_events++;
109: suspect_history.add(ping_dest);
110: }
111: }
112: } catch (Exception ex) {
113: if (log.isErrorEnabled())
114: log
115: .error("failed executing command "
116: + command, ex);
117: }
118: }
119: }
120:
121: protected static class Pinger {
122:
123: static int execute(String command, Log log) throws IOException,
124: InterruptedException {
125: Process p = Runtime.getRuntime().exec(command);
126: InputStream in = p.getInputStream(), err = p
127: .getErrorStream();
128: try {
129: Reader in_reader, err_reader;
130: in_reader = new Reader(in, log);
131: err_reader = new Reader(err, log);
132: in_reader.start();
133: err_reader.start();
134: in_reader.join();
135: err_reader.join();
136: return p.exitValue();
137: } finally {
138: Util.close(in);
139: Util.close(err);
140: }
141: }
142:
143: static class Reader extends Thread {
144: InputStreamReader in;
145: Log log = null;
146: boolean trace = false;
147:
148: Reader(InputStream in, Log log) {
149: this .in = new InputStreamReader(in);
150: this .log = log;
151: if (log != null) {
152: trace = log.isTraceEnabled();
153: }
154: }
155:
156: public void run() {
157: int c;
158: StringBuffer sb = new StringBuffer();
159: while (true) {
160: try {
161: c = in.read();
162: if (c == -1)
163: break;
164: sb.append((char) c);
165: } catch (IOException e) {
166: break;
167: }
168: }
169: if (log.isTraceEnabled())
170: log.trace(sb.toString());
171: }
172: }
173: }
174:
175: }
|