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 }