org.yamcs.api.artemis.Protocol 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.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.MessageHandler;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.utils.ActiveMQBufferInputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yamcs.protobuf.Yamcs.ProtoDataType;
import org.yamcs.utils.ActiveMQBufferOutputStream;
import com.google.protobuf.MessageLite;
public class Protocol {
static Logger log = LoggerFactory.getLogger(Protocol.class.getName());
private static ProducerKiller killer;
public static SimpleString getReplayControlAddress(String instance) {
return new SimpleString(instance + ".replayControl");
}
public static SimpleString getYarchRetrievalControlAddress(String instance) {
return new SimpleString(instance + ".retrievalControl");
}
public static SimpleString getYarchIndexControlAddress(String instance) {
return new SimpleString(instance + ".indexControl");
}
public static SimpleString getEventRealtimeAddress(String instance) {
return new SimpleString(instance + ".events_realtime");
}
public static SimpleString getParameterRealtimeAddress(String instance) {
return new SimpleString(instance + ".parameters_realtime");
}
public static SimpleString getPacketRealtimeAddress(String instance) {
return new SimpleString(instance + ".tm_realtime");
}
public static SimpleString getPacketAddress(String instance, String streamName) {
return new SimpleString(instance + "." + streamName);
}
final static public String MSG_TYPE_HEADER_NAME = "yamcs-content";
final static public String REQUEST_TYPE_HEADER_NAME = "yamcs-req-type";
final static public String ERROR_MSG_HEADER_NAME = "yamcs-error-msg";
final static public String ERROR_TYPE_HEADER_NAME = "yamcs-error-type";
final static public SimpleString DATA_TO_HEADER_NAME = new SimpleString("yamcs-data-to");
final static public SimpleString YAMCS_SERVER_CONTROL_ADDRESS = new SimpleString("yamcsControl");
final static public SimpleString REPLYTO_HEADER_NAME = new SimpleString("yamcs-reply-to");
final public static String IN_VM_FACTORY = "org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnectorFactory";
/**
* used to send chunks of data in a stream
*/
final static public String DATA_TYPE_HEADER_NAME = "dt";
/**
* used to send one shot events (publish/subscribe)
*/
final static public String HDR_EVENT_NAME = "en";
/**
* address where all the I/O Links are registered (e.g. tmprovide and tcuplinker) there is also a queue with the
* same name that can be browsed to get the initial list
*/
final static public SimpleString LINK_INFO_ADDRESS = new SimpleString("linkInfo");
/**
* address where link control messages can be sent
*/
final static public SimpleString LINK_CONTROL_ADDRESS = new SimpleString("linkControl");
/**
* address where all the Channels are registered there is also a queue with the same name that can be browsed to get
* the initial list
*/
final static public SimpleString YPROCESSOR_INFO_ADDRESS = new SimpleString("channelInfo");
/**
* address where channel control commands can be sent
*/
final static public SimpleString YPROCESSOR_CONTROL_ADDRESS = new SimpleString("channelControl");
/**
* address where channel statistics are published regularly
*/
final static public SimpleString YPROCESSOR_STATISTICS_ADDRESS = new SimpleString("channelStatistics");
/**
* address where all the Command Queues and command stationed in the Queues are registered there is also a queue
* with the same name that can be browsed to get the initial list
*/
final static public SimpleString CMDQUEUE_INFO_ADDRESS = new SimpleString("cmdQueueInfo");
/**
* address where command queue control commands can be sent
*/
final static public SimpleString CMDQUEUE_CONTROL_ADDRESS = new SimpleString("cmdQueueControl");
public static MessageLite decode(ClientMessage msg, MessageLite.Builder builder) throws ArtemisApiException {
try {
ActiveMQBuffer buf = msg.getBodyBuffer();
return builder.mergeFrom(new ActiveMQBufferInputStream(buf)).build();
} catch (IOException e) {
throw new ArtemisApiException(e.getMessage(), e);
}
}
public static MessageLite.Builder decodeBuilder(ClientMessage msg, MessageLite.Builder builder)
throws ArtemisApiException {
try {
ActiveMQBuffer buf = msg.getBodyBuffer();
return builder.mergeFrom(new ActiveMQBufferInputStream(buf));
} catch (IOException e) {
throw new ArtemisApiException(e.getMessage(), e);
}
}
public static void encode(ClientMessage msg, MessageLite ml) {
try {
ml.writeTo(new ActiveMQBufferOutputStream(msg.getBodyBuffer()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static boolean endOfStream(ClientMessage msg) {
int type = msg.getIntProperty(DATA_TYPE_HEADER_NAME);
return (type == ProtoDataType.STATE_CHANGE.getNumber());
}
/**
* Closes producer when a consumer for address a has been detected as dead
*
* @param p
* @param a
*/
public static synchronized void killProducerOnConsumerClosed(ClientProducer p, SimpleString a) {
if ((killer == null) || killer.session.isClosed()) {// killer.session gets closed when the artemis is stopped
// (during test execution by maven)
try {
killer = new ProducerKiller();
} catch (Exception e) {
log.error("Could not create ProducerKiller", e);
}
}
if (killer != null) {
killer.add(p, a);
}
}
/**
* this is supposed to close the data producers that are stuck writing into queues for which there is no consumer
* (e.g. when the consumer loses the network connection to the server)
*
*/
static class ProducerKiller implements MessageHandler {
ClientSession session;
Map producers = new ConcurrentHashMap<>();
ServerLocator locator;
ClientSessionFactory factory;
ClientConsumer consumer ;
ProducerKiller() throws Exception {
locator = ActiveMQClient.createServerLocatorWithoutHA(new TransportConfiguration(IN_VM_FACTORY));
factory = locator.createSessionFactory();
session = factory.createSession(YamcsSession.hornetqInvmUser, YamcsSession.hornetqInvmPass, false, true,
true, true, 1);
// session.createQueue("example", "example", true);
session.createTemporaryQueue("activemq.notifications", "ProducerKiller");
consumer = session.createConsumer("ProducerKiller");
consumer.setMessageHandler(this);
session.start();
}
public void add(ClientProducer p, SimpleString a) {
producers.put(a, p);
}
@Override
public void onMessage(ClientMessage msg) {
String amq_notifType = msg.getStringProperty("_AMQ_NotifType");
if ("CONSUMER_CLOSED".equals(amq_notifType)) {
SimpleString amq_address = msg.getSimpleStringProperty("_AMQ_Address");
ClientProducer p = producers.remove(amq_address);
if (p != null && !p.isClosed()) {
try {
log.warn("closing producer {} because the consumer to the address {} has closed", p,
amq_address);
p.close();
} catch (ActiveMQException e) {
e.printStackTrace();
}
}
}
}
public void close() {
if (locator != null) {
locator.close();
}
}
}
/**
* Close killer (used in order to reduce warnings during maven builds
*/
public static synchronized void closeKiller() {
if (killer != null) {
killer.close();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy