package org.yamcs.artemis;
import java.util.Random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yamcs.yarch.Stream;
import org.yamcs.yarch.StreamSubscriber;
import org.yamcs.yarch.Tuple;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.MessageHandler;
import org.yamcs.api.YamcsApiException;
import org.yamcs.api.artemis.YamcsClient;
import org.yamcs.api.artemis.YamcsSession;
/**
* converts between hornet addresses and yamcs streams
*
* To avoid a ping-pong effect:
* - it creates a queue with a filter on hornet side
* - it remembers a thread local version of the tuple in transition on yarch side
*
*
* this class is deprecated because it converts data in both directions whereas we want to be able to do it separately and have the incoming data as Data Links.
*
* The ActiveMQ XYZ Providers shall be used for ActiveMQ to stream translator and the ActiveMQXYZService (based on AbstractActiveMQTranslatorService) in the other direction.
*
* Currently used only for events - once event providers are also shown as data links, we should get rid of this.
*
*/
@Deprecated
public class StreamAdapter implements StreamSubscriber, MessageHandler {
final private SimpleString hornetAddress;
final private TupleTranslator translator;
YamcsSession yamcsSession;
final private YamcsClient yClient;
final private Stream stream;
static final public String UNIQUEID_HDR_NAME="_y_uniqueid";
static final public int UNIQUEID = new Random().nextInt();
Logger log=LoggerFactory.getLogger(this.getClass().getName());
ThreadLocal<Tuple> currentProcessingTuple=new ThreadLocal<Tuple>();
public StreamAdapter(Stream stream, SimpleString hornetAddress, TupleTranslator translator) throws ActiveMQException, YamcsApiException {
this.stream=stream;
this.hornetAddress=hornetAddress;
this.translator=translator;
SimpleString queue=new SimpleString(hornetAddress.toString()+"-StreamAdapter");
yamcsSession=YamcsSession.newBuilder().build();
yClient=yamcsSession.newClientBuilder().setDataProducer(true).setDataConsumer(hornetAddress, queue).
setFilter(new SimpleString(UNIQUEID_HDR_NAME+"<>"+UNIQUEID)).
build();
yClient.dataConsumer.setMessageHandler(this);
stream.addSubscriber(this);
}
@Override
public void onTuple(Stream s, Tuple tuple) {
if(tuple==currentProcessingTuple.get()){
return;
}
try {
ClientMessage msg=translator.buildMessage(yamcsSession.session.createMessage(false), tuple);
msg.putIntProperty(UNIQUEID_HDR_NAME, UNIQUEID);
yClient.sendData(hornetAddress, msg);
} catch (IllegalArgumentException e) {
log.warn(e.getMessage());
} catch (YamcsApiException e) {
log.warn("Got exception when sending message:", e);
}
}
@Override
public void streamClosed(Stream istream) {
}
@Override
public void onMessage(ClientMessage msg) {
try {
Tuple tuple=translator.buildTuple(stream.getDefinition(), msg);
currentProcessingTuple.set(tuple);
stream.emitTuple(tuple);
} catch(IllegalArgumentException e){
log.warn( "{} for message: {}", e.getMessage(), msg);
}
}
public void quit() {
try {
yamcsSession.close();
} catch (ActiveMQException e) {
log.warn("Got exception when quiting:", e);
}
stream.removeSubscriber(this);
}
@Override
public String toString() {
return "StreamAdapter["+stream.getName()+"<->"+hornetAddress+"]";
}
}