/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.livedata.server;
import java.util.Timer;
import java.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.Lifecycle;
import com.opengamma.livedata.server.StandardLiveDataServer.ConnectionStatus;
import com.opengamma.util.ArgumentChecker;
/**
* Monitors the state of the connection to the underlying market data API
* and reconnects if the connection has been lost.
* <p>
* This beans depends-on the Live Data Server, and any Spring configuration must reflect
* this. See <a href="http://jira.springframework.org/browse/SPR-2325">http://jira.springframework.org/browse/SPR-2325</a>.
*/
public class ReconnectManager implements Lifecycle {
/** Logger. */
private static final Logger s_logger = LoggerFactory.getLogger(ReconnectManager.class);
/**
* How often connection status should be checked. Milliseconds
*/
public static final long DEFAULT_CHECK_PERIOD = 5000;
/**
* The live data server.
*/
private final StandardLiveDataServer _server;
/**
* The timer.
*/
private final Timer _timer;
/**
* The checking period.
*/
private final long _checkPeriod;
/**
* The checking task.
*/
private volatile CheckTask _checkTask;
/**
* Creates an instance wrapping an underlying server.
*
* @param server the server, not null
*/
public ReconnectManager(StandardLiveDataServer server) {
this(server, DEFAULT_CHECK_PERIOD);
}
/**
* Creates an instance wrapping an underlying server.
*
* @param server the server, not null
* @param checkIntervalMillis the checking interval in milliseconds
*/
public ReconnectManager(StandardLiveDataServer server, long checkIntervalMillis) {
this(server, checkIntervalMillis, new Timer("ReconnectManager Timer"));
}
/**
* Creates an instance wrapping an underlying server.
*
* @param server the server, not null
* @param checkIntervalMillis the checking interval in milliseconds
* @param timer the timer, not null
*/
public ReconnectManager(StandardLiveDataServer server, long checkIntervalMillis, Timer timer) {
ArgumentChecker.notNull(server, "server");
ArgumentChecker.notNull(timer, "timer");
if (checkIntervalMillis <= 0) {
throw new IllegalArgumentException("Please give positive check period");
}
_server = server;
_timer = timer;
_checkPeriod = checkIntervalMillis;
}
//-------------------------------------------------------------------------
@Override
public boolean isRunning() {
return _checkTask != null;
}
@Override
public void start() {
_checkTask = new CheckTask();
_timer.schedule(_checkTask, _checkPeriod, _checkPeriod);
}
@Override
public void stop() {
_checkTask.cancel();
_checkTask = null;
}
//-------------------------------------------------------------------------
private class CheckTask extends TimerTask {
@Override
public void run() {
try {
check();
} catch (RuntimeException e) {
s_logger.error("Checking for reconnection failed", e);
}
}
}
// called by the timer task
private void check() {
if (_server.getConnectionStatus() == ConnectionStatus.NOT_CONNECTED) {
s_logger.warn("Connection to market data API down. Attemping to reconnect to {}.", _server);
try {
_server.connect();
} catch (RuntimeException e) {
s_logger.warn("Could not reconnect", e);
return;
}
s_logger.info("Reconnection successful. Reestablishing subscriptions.");
_server.reestablishSubscriptions();
s_logger.info("Reconnect done.");
} else {
s_logger.debug("Connection up to server {}", _server.getClass().getSimpleName());
}
}
}