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 2007-2008 Sun Microsystems, Inc.
026 */
027
028 package org.opends.server.replication.plugin;
029
030 import static org.opends.messages.ReplicationMessages.*;
031 import static org.opends.server.loggers.ErrorLogger.logError;
032 import static org.opends.server.loggers.debug.DebugLogger.*;
033 import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
034
035 import org.opends.server.loggers.debug.DebugTracer;
036
037 import java.io.IOException;
038
039 import org.opends.server.api.DirectoryThread;
040 import org.opends.server.replication.protocol.ProtocolSession;
041
042 /**
043 * This class implements a thread to monitor heartbeat messages from the
044 * replication server. Each broker runs one of these threads.
045 */
046 public class HeartbeatMonitor extends DirectoryThread
047 {
048 /**
049 * The tracer object for the debug logger.
050 */
051 private static final DebugTracer TRACER = getTracer();
052
053
054
055 /**
056 * The session on which heartbeats are to be monitored.
057 */
058 private ProtocolSession session;
059
060
061 /**
062 * The time in milliseconds between heartbeats from the replication
063 * server. Zero means heartbeats are off.
064 */
065 private long heartbeatInterval;
066
067
068 /**
069 * Set this to stop the thread.
070 */
071 private boolean shutdown = false;
072
073
074 /**
075 * Create a heartbeat monitor thread.
076 * @param threadName The name of the heartbeat thread.
077 * @param session The session on which heartbeats are to be monitored.
078 * @param heartbeatInterval The expected interval between heartbeats in
079 * milliseconds.
080 */
081 public HeartbeatMonitor(String threadName, ProtocolSession session,
082 long heartbeatInterval)
083 {
084 super(threadName);
085 this.session = session;
086 this.heartbeatInterval = heartbeatInterval;
087 }
088
089 /**
090 * Call this method to stop the thread.
091 */
092 public void shutdown()
093 {
094 shutdown = true;
095 }
096
097
098 /**
099 * {@inheritDoc}
100 */
101 @Override
102 public void run()
103 {
104 boolean gotOneFailure = false;
105 if (debugEnabled())
106 {
107 TRACER.debugInfo("Heartbeat monitor is starting, expected interval is " +
108 heartbeatInterval +
109 stackTraceToSingleLineString(new Exception()));
110 }
111 try
112 {
113 while (!shutdown)
114 {
115 long now = System.currentTimeMillis();
116 long lastReceiveTime = session.getLastReceiveTime();
117 if (now > lastReceiveTime + heartbeatInterval)
118 {
119 if (gotOneFailure == true)
120 {
121 // Heartbeat is well overdue so the server is assumed to be dead.
122 logError(NOTE_HEARTBEAT_FAILURE.get(currentThread().getName()));
123 session.close();
124 break;
125 }
126 else
127 {
128 gotOneFailure = true;
129 }
130 }
131 else
132 {
133 gotOneFailure = false;
134 }
135 try
136 {
137 Thread.sleep(heartbeatInterval);
138 }
139 catch (InterruptedException e)
140 {
141 // That's OK.
142 }
143 }
144 }
145 catch (IOException e)
146 {
147 // Hope that's OK.
148 }
149 finally
150 {
151 if (debugEnabled())
152 {
153 TRACER.debugInfo("Heartbeat monitor is exiting." +
154 stackTraceToSingleLineString(new Exception()));
155 }
156 }
157 }
158 }