org.yamcs.api.artemis.YamcsConnector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of yamcs-artemis Show documentation
Show all versions of yamcs-artemis Show documentation
Yamcs Artemis senders/receivers
package org.yamcs.api.artemis;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
import org.apache.activemq.artemis.api.core.client.SessionFailureListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yamcs.YamcsException;
import org.yamcs.api.YamcsConnectionProperties;
import org.yamcs.protobuf.YamcsInstance;
import org.yamcs.protobuf.YamcsInstances;
/**
* this is like a yamcssession but performs reconnection and implements some callbacks to announce the state. to be used
* by all the gui data receivers (event viewer, archive browser, etc)
*
* @author nm
*
*/
public class YamcsConnector implements SessionFailureListener {
public int getMaxAttempts() {
return maxAttempts;
}
public void setMaxAttempts(int maxAttempts) {
this.maxAttempts = maxAttempts;
}
CopyOnWriteArrayList connectionListeners = new CopyOnWriteArrayList<>();
volatile boolean connected, connecting;
protected YamcsSession yamcsSession;
protected YamcsConnectionProperties connectionParams;
static Logger log = LoggerFactory.getLogger(YamcsConnector.class);
private boolean retry = true;
private boolean reconnecting = false;
final private ExecutorService executor = Executors.newSingleThreadScheduledExecutor();
int maxAttempts = 10;
public YamcsConnector() {
}
public YamcsConnector(boolean retry) {
this.retry = retry;
}
public void addConnectionListener(ConnectionListener connectionListener) {
this.connectionListeners.add(connectionListener);
}
public List getYamcsInstances() {
try {
YamcsSession ys = YamcsSession.newBuilder().setConnectionParams(connectionParams).build();
YamcsClient mc = ys.newClientBuilder().setRpc(true).build();
YamcsInstances ainst = (YamcsInstances) mc.executeRpc(Protocol.YAMCS_SERVER_CONTROL_ADDRESS,
"getYamcsInstances", null, YamcsInstances.newBuilder());
mc.close();
List instances = new ArrayList<>(ainst.getInstanceCount());
for (YamcsInstance ai : ainst.getInstanceList()) {
instances.add(ai.getName());
}
ys.close();
return instances;
} catch (ActiveMQException hqe) {
// If we don't have permissions, treat as a failed connection
if (hqe.getType() == ActiveMQExceptionType.SECURITY_EXCEPTION
|| hqe.getType() == ActiveMQExceptionType.SESSION_CREATION_REJECTED) {
String message = "Connection failed with security exception: " + hqe.getMessage();
log.warn(message);
if (connected) {
disconnect();
}
for (ConnectionListener cl : connectionListeners) {
cl.connectionFailed(connectionParams.getUrl(), new YamcsException(message));
}
} else {
// Other errors may not be fatal
for (ConnectionListener cl : connectionListeners) {
cl.log("failed to retrieve instances: " + hqe);
}
}
} catch (Exception e) {
for (ConnectionListener cl : connectionListeners) {
cl.log("failed to retrieve instances: " + e);
}
}
return null;
}
public Future connect(YamcsConnectionProperties cp) {
this.connectionParams = cp;
return doConnect();
}
private FutureTask doConnect() {
if (connected) {
disconnect();
}
final String url = connectionParams.getUrl();
FutureTask future = new FutureTask<>(() -> {
// connect to yamcs
try {
if (reconnecting && !retry) {
log.warn("Retries are disabled, cancelling reconnection");
reconnecting = false;
return;
}
connecting = true;
for (ConnectionListener cl1 : connectionListeners) {
cl1.connecting(url);
}
for (int i = 0; i < maxAttempts; i++) {
try {
log.debug("Connecting to {} attempt {}", url, i);
yamcsSession = YamcsSession.newBuilder().setConnectionParams(connectionParams).build();
log.debug("Connection successful");
yamcsSession.session.addFailureListener(YamcsConnector.this);
connected = true;
for (ConnectionListener cl2 : connectionListeners) {
cl2.connected(url);
}
return;
} catch (ArtemisApiException e1) {
// If we don't have permissions, treat as a failed connection and don't re-try
Throwable cause = e1.getCause();
if (cause != null && cause instanceof ActiveMQException
&& ((ActiveMQException) cause).getType() == ActiveMQExceptionType.SECURITY_EXCEPTION) {
String message = "Connection failed with security exception: " + e1.getMessage();
log.warn(message);
if (connected) {
disconnect();
}
for (ConnectionListener cl3 : connectionListeners) {
cl3.connectionFailed(url, new YamcsException(message));
}
return;
}
// For anything other than a security exception, re-try
for (ConnectionListener cl4 : connectionListeners) {
cl4.log("Connection to " + url + " failed :" + e1.getMessage());
}
log.warn("Connection to " + url + " failed :!", e1);
Thread.sleep(5000);
}
}
connecting = false;
for (ConnectionListener cl5 : connectionListeners) {
cl5.log(maxAttempts + " connection attempts failed, giving up.");
cl5.connectionFailed(url,
new YamcsException(maxAttempts + " connection attempts failed, giving up."));
}
log.warn(maxAttempts + " connection attempts failed, giving up.");
} catch (InterruptedException e2) {
Thread.currentThread().interrupt();
for (ConnectionListener cl6 : connectionListeners) {
cl6.connectionFailed(url, new YamcsException("Thread interrupted", e2));
}
}
}, url);
executor.submit(future);
return future;
}
public void disconnect() {
log.warn("Disconnection requested");
if (!connected) {
return;
}
try {
yamcsSession.close();
connected = false;
} catch (ActiveMQException e) {
for (ConnectionListener cl : connectionListeners) {
cl.log(e.toString());
}
}
}
public String getUrl() {
return connectionParams.getUrl();
}
public boolean isConnected() {
return connected;
}
public boolean isConnecting() {
return connecting;
}
@Override
public void connectionFailed(ActiveMQException e, boolean failedOver, String scaleDownTargetNodeID) {
connectionFailed(e, failedOver);
}
@Override
public void connectionFailed(ActiveMQException e, boolean failedOver) {
connected = false;
for (ConnectionListener cl : connectionListeners) {
cl.disconnected();
}
log.warn("Connection to Yamcs lost: ", e);
doConnect();
}
@Override
public void beforeReconnect(ActiveMQException e) {
// should not be called because reconnection is not configured in the factory
// log.warn("Before reconnect: ", creatorContext);
log.warn("Before reconnect: ", e);
reconnecting = true;
}
public YamcsSession getSession() {
return yamcsSession;
}
public YamcsConnectionProperties getConnectionParams() {
return connectionParams;
}
public void close() throws ActiveMQException {
yamcsSession.close();
}
public ExecutorService getExecutor() {
return executor;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy