All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.yamcs.tctm.AbstractLink Maven / Gradle / Ivy

There is a newer version: 5.10.9
Show newest version
package org.yamcs.tctm;

import static org.yamcs.parameter.SystemParametersService.getPV;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

import org.yamcs.ConfigurationException;
import org.yamcs.YConfiguration;
import org.yamcs.YamcsServer;
import org.yamcs.events.EventProducer;
import org.yamcs.events.EventProducerFactory;
import org.yamcs.logging.Log;
import org.yamcs.parameter.ParameterValue;
import org.yamcs.parameter.SystemParametersProducer;
import org.yamcs.parameter.SystemParametersService;
import org.yamcs.protobuf.Yamcs.Value.Type;
import org.yamcs.time.TimeService;
import org.yamcs.utils.DataRateMeter;
import org.yamcs.xtce.EnumeratedParameterType;
import org.yamcs.xtce.Parameter;
import org.yamcs.xtce.UnitType;

import com.google.common.util.concurrent.AbstractService;
import com.google.common.util.concurrent.Service;

import io.netty.channel.nio.NioEventLoopGroup;

/**
 * Abstract link implementation as a {@link Service} handling the basic enable/disable getConfig operations and data
 * in/out counts
 * 
 *
 */
public abstract class AbstractLink extends AbstractService
        implements Link, SystemParametersProducer, LinkActionProvider {
    public static String LINK_NAMESPACE = "links/";

    protected String yamcsInstance;
    protected String linkName;
    protected Log log;
    protected EventProducer eventProducer;
    protected YConfiguration config;
    protected AtomicBoolean disabled = new AtomicBoolean(false);
    private Parameter spLinkStatus, spDataOutCount, spDataInCount, spDataInRate, spDataOutRate;
    protected TimeService timeService;
    private Map actions = new LinkedHashMap<>(); // Keep them in order of registration
    private AggregatedDataLink parent = null;
    protected AtomicLong dataOutCount = new AtomicLong();
    protected AtomicLong dataInCount = new AtomicLong();
    DataRateMeter dataInRateMeter = new DataRateMeter();
    DataRateMeter dataOutRateMeter = new DataRateMeter();

    /**
     * singleton for netty worker group. In the future we may have an option to create different worker groups for
     * different links but for now we stick to one.
     */
    static NioEventLoopGroup nelg = new NioEventLoopGroup();

    @Override
    public void init(String instance, String name, YConfiguration config) throws ConfigurationException {
        this.yamcsInstance = instance;
        this.linkName = name;
        this.config = config;
        log = new Log(getClass(), instance);
        log.setContext(name);
        eventProducer = EventProducerFactory.getEventProducer(yamcsInstance, name, 10000);
        timeService = YamcsServer.getTimeService(yamcsInstance);
    }

    @Override
    public YConfiguration getConfig() {
        return config;
    }

    @Override
    public String getName() {
        return linkName;
    }

    @Override
    public Status getLinkStatus() {
        if (isDisabled()) {
            return Status.DISABLED;
        }
        if (state() == State.FAILED) {
            return Status.FAILED;
        }

        return connectionStatus();
    }

    @Override
    public String getDetailedStatus() {
        return "";
    }

    protected static NioEventLoopGroup getEventLoop() {
        return nelg;
    }

    /**
     * Sets the disabled to false such that getNextPacket does not ignore the received datagrams
     */
    @Override
    public void enable() {
        boolean b = disabled.getAndSet(false);
        if (b) {
            try {
                doEnable();
            } catch (Exception e) {
                disabled.set(true);
                log.warn("Failed to enable link", e);
            }
        }
    }

    @Override
    public void disable() {
        boolean b = disabled.getAndSet(true);
        if (!b) {
            try {
                doDisable();
            } catch (Exception e) {
                disabled.set(false);
                log.warn("Failed to disable link", e);
            }
        }
    }

    @Override
    public boolean isDisabled() {
        return disabled.get();
    }

    public boolean isRunningAndEnabled() {
        State state = state();
        return (state == State.RUNNING || state == State.STARTING) && !disabled.get();
    }

    protected void doDisable() throws Exception {
    }

    protected void doEnable() throws Exception {
    }

    /**
     * In case the link should be connected (i.e. is running and enabled) this method is called to return the actual
     * connection status
     */
    protected abstract Status connectionStatus();

    protected long getCurrentTime() {
        return timeService.getMissionTime();
    }

    @Override
    public void setupSystemParameters(SystemParametersService sysParamService) {
        spLinkStatus = sysParamService.createEnumeratedSystemParameter(LINK_NAMESPACE + linkName + "/linkStatus",
                Status.class, "The current status of this link");
        EnumeratedParameterType spLinkStatusType = (EnumeratedParameterType) spLinkStatus.getParameterType();
        spLinkStatusType.enumValue(Status.OK.name())
                .setDescription("This link is up and ready to receive (or send) data");
        spLinkStatusType.enumValue(Status.UNAVAIL.name()).setDescription("This link is down unexpectedly");
        spLinkStatusType.enumValue(Status.DISABLED.name()).setDescription("This link was disabled by a user");
        spLinkStatusType.enumValue(Status.FAILED.name())
                .setDescription("An internal error occurred while processing data");

        UnitType bps = new UnitType("Bps");
        spDataOutCount = sysParamService.createSystemParameter(LINK_NAMESPACE + linkName + "/dataOutCount", Type.UINT64,
                "The total number of items (e.g. telecommand packets) that have been sent through this link");
        spDataInCount = sysParamService.createSystemParameter(LINK_NAMESPACE + linkName + "/dataInCount", Type.UINT64,
                "The total number of items (e.g. telemetry packets) that have been received through this link");

        spDataInRate = sysParamService.createSystemParameter(LINK_NAMESPACE + linkName + "/dataInRate", Type.DOUBLE,
                bps, "The number of incoming bytes per second computed over a five second interval");

        spDataOutRate = sysParamService.createSystemParameter(LINK_NAMESPACE + linkName + "/dataOutRate", Type.DOUBLE,
                bps, "The number of outgoing bytes per second computed over a five second interval");

    }

    @Override
    public List getSystemParameters(long time) {

        ArrayList list = new ArrayList<>();
        try {
            collectSystemParameters(time, list);
        } catch (Exception e) {
            log.error("Exception caught when collecting link system parameters", e);
        }
        return list;
    }

    /**
     * adds system parameters link status and data in/out to the list.
     * 

* The inheriting classes should call super.collectSystemParameters and then add their own parameters to the list * * @param time * @param list */ protected void collectSystemParameters(long time, List list) { list.add(getPV(spLinkStatus, time, getLinkStatus())); list.add(getPV(spDataOutCount, time, getDataOutCount())); list.add(getPV(spDataInCount, time, getDataInCount())); list.add(getPV(spDataOutRate, time, dataOutRateMeter.getFiveSecondsRate())); list.add(getPV(spDataInRate, time, dataInRateMeter.getFiveSecondsRate())); } protected void addAction(LinkAction action) { if (actions.containsKey(action.getId())) { throw new IllegalArgumentException("Action '" + action.getId() + "' already registered"); } actions.put(action.getId(), action); } @Override public List getActions() { return new ArrayList<>(actions.values()); } @Override public LinkAction getAction(String actionId) { return actions.get(actionId); } @Override public AggregatedDataLink getParent() { return parent; } @Override public void setParent(AggregatedDataLink parent) { this.parent = parent; } public String getYamcsInstance() { return yamcsInstance; } @Override public long getDataOutCount() { return dataOutCount.get(); } @Override public long getDataInCount() { return dataInCount.get(); } @Override public void resetCounters() { dataInCount.set(0); dataOutCount.set(0); } /** * Update the dataOutCount with the given number of items sent *

* Should be called by the inheriting classes each time data is sent out */ protected void dataOut(long outCount, long size) { dataOutCount.addAndGet(outCount); dataOutRateMeter.mark(size); } /** * Update the dataInCount with the given number of items received *

* Should be called by the inheriting classes each time data is received * */ protected void dataIn(long inCount, long size) { dataInCount.addAndGet(inCount); dataInRateMeter.mark(size); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy