package org.yamcs.xtceproc; import java.nio.ByteBuffer; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yamcs.ConfigurationException; import org.yamcs.ContainerExtractionResult; import org.yamcs.InvalidIdentification; import org.yamcs.TmProcessor; import org.yamcs.Processor; import org.yamcs.archive.PacketWithTime; import org.yamcs.container.ContainerProvider; import org.yamcs.parameter.ParameterProvider; import org.yamcs.parameter.ParameterRequestManager; import org.yamcs.parameter.ParameterValueList; import org.yamcs.protobuf.Yamcs.NamedObjectId; import org.yamcs.utils.LoggingUtils; import org.yamcs.utils.TimeEncoding; import org.yamcs.xtce.Container; import org.yamcs.xtce.Parameter; import org.yamcs.xtce.SequenceContainer; import org.yamcs.xtce.XtceDb; import com.google.common.util.concurrent.AbstractService; /** * * Does the job of getting containers and transforming them into parameters which are then sent to the * parameter request manager for the distribution to the requesters. * * Relies on {@link XtceTmExtractor} for extracting the parameters out of containers * * @author mache * */ public class XtceTmProcessor extends AbstractService implements TmProcessor, ParameterProvider, ContainerProvider { Logger log=LoggerFactory.getLogger(this.getClass().getName()); private ParameterRequestManager parameterRequestManager; private ContainerListener containerRequestManager; public final Processor processor; public final XtceDb xtcedb; final XtceTmExtractor tmExtractor; final String CONFIG_KEY_ignoreOutOfContainerEntries = "ignoreOutOfContainerEntries"; public XtceTmProcessor(Processor proc, Map<String, Object> tmProcessorConfig) { log = LoggingUtils.getLogger(this.getClass(), proc); this.processor=proc; this.xtcedb=proc.getXtceDb(); tmExtractor = new XtceTmExtractor(xtcedb, proc.getProcessorData()); if(tmProcessorConfig != null) { if(tmProcessorConfig.containsKey(CONFIG_KEY_ignoreOutOfContainerEntries)) { Object o = tmProcessorConfig.get(CONFIG_KEY_ignoreOutOfContainerEntries); if(!(o instanceof Boolean)) { throw new ConfigurationException(CONFIG_KEY_ignoreOutOfContainerEntries+" has to be a boolean"); } boolean iooce = (Boolean) o; tmExtractor.setIgnoreOutOfContainerEntries(iooce); } } } public XtceTmProcessor(Processor proc) { log = LoggingUtils.getLogger(this.getClass(), proc); this.processor = proc; this.xtcedb = proc.getXtceDb(); tmExtractor = new XtceTmExtractor(xtcedb, proc.getProcessorData()); } /** * Creates a TmProcessor to be used in "standalone" mode, outside of any processor */ public XtceTmProcessor(XtceDb xtcedb) { log = LoggerFactory.getLogger(this.getClass()); this.processor = null; this.xtcedb = xtcedb; tmExtractor = new XtceTmExtractor(xtcedb); } /** * See {@link XtceTmExtractor#setIgnoreOutOfContainerEntries} * @param ignoreOutOfContainerEntries */ public void setIgnoreOutOfContainerEntries(boolean ignoreOutOfContainerEntries) { tmExtractor.setIgnoreOutOfContainerEntries(ignoreOutOfContainerEntries); } @Override public void init(Processor processor) throws ConfigurationException { //do nothing, we already know the processor } @Override public void setParameterListener(ParameterRequestManager p) { this.parameterRequestManager=p; } @Override public void setContainerListener(ContainerListener c) { this.containerRequestManager=c; } /** * Adds a parameter to the current subscription list: * finds all the SequenceContainers in which this parameter may appear and adds them to the list. * also for each sequence container adds the parameter needed to instantiate the sequence container. * @param param parameter to be added to the current subscription list */ @Override public void startProviding(Parameter param) { tmExtractor.startProviding(param); } /** * adds all parameters to the subscription */ @Override public void startProvidingAll() { tmExtractor.startProvidingAll(); } @Override public void stopProviding(Parameter param) { tmExtractor.stopProviding(param); } @Override public boolean canProvide(NamedObjectId paraId) { Parameter p = xtcedb.getParameter(paraId); if(p==null) { return false; } return xtcedb.getParameterEntries(p)!=null; } @Override public boolean canProvide(Parameter para) { return xtcedb.getParameterEntries(para)!=null; } @Override public Parameter getParameter(NamedObjectId paraId) throws InvalidIdentification { Parameter p = xtcedb.getParameter(paraId); if(p==null) { throw new InvalidIdentification(paraId); } return p; } private long getCurrentTime() { if(processor!=null) { return processor.getCurrentTime(); } else { return TimeEncoding.getWallclockTime(); } } /** * Process telemetry packets * */ @Override public void processPacket(PacketWithTime pwrt){ try { ByteBuffer bb= ByteBuffer.wrap(pwrt.getPacket()); tmExtractor.processPacket(bb, pwrt.getGenerationTime(), getCurrentTime()); ParameterValueList paramResult=tmExtractor.getParameterResult(); List<ContainerExtractionResult> containerResult=tmExtractor.getContainerResult(); if((parameterRequestManager!=null) &&( paramResult.size()>0)) { //careful out of the synchronized block in order to avoid dead locks // with the parameterRequestManager trying to add/remove parameters // while we are sending updates parameterRequestManager.update(paramResult); } if((containerRequestManager!=null) && (containerResult.size()>0)) { containerRequestManager.update(containerResult); } } catch (Exception e) { log.error("got exception in tmprocessor ", e); } } @Override public void processPacket(PacketWithTime pwrt, SequenceContainer sc){ try { ByteBuffer bb= ByteBuffer.wrap(pwrt.getPacket()); tmExtractor.processPacket(bb, pwrt.getGenerationTime(), TimeEncoding.getWallclockTime(), sc); ParameterValueList paramResult=tmExtractor.getParameterResult(); List<ContainerExtractionResult> containerResult = tmExtractor.getContainerResult(); if((parameterRequestManager!=null) &&( paramResult.size()>0)) { //careful out of the synchronized block in order to avoid dead locks // with the parameterRequestManager trying to add/remove parameters // while we are sending updates parameterRequestManager.update(paramResult); } if((containerRequestManager!=null) && (containerResult.size()>0)) { containerRequestManager.update(containerResult); } } catch (Exception e) { log.error("got exception in tmprocessor ", e); } } @Override public void finished() { notifyStopped(); if(processor!=null) { processor.quit(); } } public void resetStatistics() { tmExtractor.resetStatistics(); } public ProcessingStatistics getStatistics(){ return tmExtractor.getStatistics(); } @Override public boolean canProvideContainer(NamedObjectId containerId) { return xtcedb.getSequenceContainer(containerId) != null; } @Override public void startProviding(SequenceContainer container) { tmExtractor.startProviding(container); } @Override public void stopProviding(SequenceContainer container) { tmExtractor.stopProviding(container); } @Override public void startProvidingAllContainers() { tmExtractor.startProvidingAll(); } @Override public Container getContainer(NamedObjectId containerId) throws InvalidIdentification { SequenceContainer c = xtcedb.getSequenceContainer(containerId); if(c==null) { throw new InvalidIdentification(containerId); } return c; } /* public void subscribePackets(List<ItemIdPacketConsumerStruct> iipcs) { synchronized(subscription) { for(ItemIdPacketConsumerStruct i:iipcs) { subscription.addSequenceContainer(i.def); } } } */ public Subscription getSubscription() { return tmExtractor.getSubscription(); } @Override protected void doStart() { notifyStarted(); } @Override protected void doStop() { notifyStopped(); } public XtceDb getXtceDb() { return xtcedb; } }