/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2009-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2013 ForgeRock AS
*/
package org.opends.server.replication.server;
import java.io.IOException;
import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
import static org.opends.server.loggers.debug.DebugLogger.getTracer;
import org.opends.server.api.DirectoryThread;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.replication.protocol.MonitorMsg;
/**
* This thread regularly publishes monitoring information:
* - it sends monitoring messages regarding the direct topology (directly
* connected DSs and RSs) to the connected RSs
* - it sends monitoring messages regarding the whole topology (also includes
* the local RS) to the connected DSs
* Note: as of today, monitoring messages mainly contains the server state of
* the entities.
*/
public class MonitoringPublisher extends DirectoryThread
{
private volatile boolean shutdown = false;
/**
* The tracer object for the debug logger.
*/
private static final DebugTracer TRACER = getTracer();
// The domain we send monitoring for
private final ReplicationServerDomain replicationServerDomain;
// Sleep time (in ms) before sending new monitoring messages.
private volatile long period;
// Is the thread terminated ?
private volatile boolean done = false;
private final Object shutdownLock = new Object();
/**
* Create a monitoring publisher.
* @param replicationServerDomain The ReplicationServerDomain the monitoring
* publisher is for.
* @param period The sleep time to use
*/
public MonitoringPublisher(ReplicationServerDomain replicationServerDomain,
long period)
{
super("Replication server RS("
+ replicationServerDomain.getReplicationServer()
.getServerId() + ") monitor publisher for domain \""
+ replicationServerDomain.getBaseDn() + "\"");
this.replicationServerDomain = replicationServerDomain;
this.period = period;
}
/**
* Run method for the monitoring publisher.
*/
@Override
public void run()
{
if (debugEnabled())
{
TRACER.debugInfo("Monitoring publisher starting for dn "
+ replicationServerDomain.getBaseDn());
}
try
{
while (!shutdown)
{
synchronized (shutdownLock)
{
if (!shutdown)
{
shutdownLock.wait(period);
}
}
// Send global topology information to peer DSs
MonitorData monitorData = replicationServerDomain
.computeDomainMonitorData();
MonitorMsg monitorMsg = replicationServerDomain
.createGlobalTopologyMonitorMsg(0, 0, monitorData);
int localServerId = replicationServerDomain
.getReplicationServer().getServerId();
for (ServerHandler serverHandler : replicationServerDomain
.getConnectedDSs().values())
{
// Set the right sender and destination ids
monitorMsg.setSenderID(localServerId);
monitorMsg.setDestination(serverHandler.getServerId());
try
{
serverHandler.send(monitorMsg);
}
catch (IOException e)
{
// Server is disconnecting ? Forget it
}
}
}
}
catch (InterruptedException e)
{
TRACER.debugInfo("Monitoring publisher for dn "
+ replicationServerDomain.getBaseDn()
+ " in RS "
+ replicationServerDomain.getReplicationServer()
.getServerId()
+ " has been interrupted while sleeping.");
}
done = true;
TRACER.debugInfo("Monitoring publisher for dn "
+ replicationServerDomain.getBaseDn()
+ " is terminated."
+ " This is in RS "
+ replicationServerDomain.getReplicationServer()
.getServerId());
}
/**
* Stops the thread.
*/
public void shutdown()
{
synchronized (shutdownLock)
{
shutdown = true;
shutdownLock.notifyAll();
if (debugEnabled())
{
TRACER.debugInfo("Shutting down monitoring publisher for dn " +
replicationServerDomain.getBaseDn() + " in RS " +
replicationServerDomain.getReplicationServer().getServerId());
}
}
}
/**
* Waits for thread death. If not terminated within 2 seconds,
* forces interruption
*/
public void waitForShutdown()
{
try
{
int FACTOR = 40; // Wait for 2 seconds before interrupting the thread
int n = 0;
while ((!done) && (this.isAlive()))
{
Thread.sleep(50);
n++;
if (n >= FACTOR)
{
TRACER.debugInfo("Interrupting monitoring publisher for dn " +
replicationServerDomain.getBaseDn() + " in RS " +
replicationServerDomain.getReplicationServer().getServerId());
this.interrupt();
}
}
} catch (InterruptedException e)
{
// exit the loop if this thread is interrupted.
}
}
/**
* Sets the period value.
* @param period The new period value.
*/
public void setPeriod(long period)
{
if (debugEnabled())
{
TRACER.debugInfo("Monitoring publisher for dn " +
replicationServerDomain.getBaseDn() +
" changing period value to " + period);
}
this.period = period;
}
}