org.yamcs.mdb.ProcessingData Maven / Gradle / Ivy
package org.yamcs.mdb;
import java.util.List;
import java.util.Map;
import org.yamcs.commanding.ArgumentValue;
import org.yamcs.parameter.LastValueCache;
import org.yamcs.parameter.ParameterValue;
import org.yamcs.parameter.ParameterValueList;
import org.yamcs.parameter.RawEngValue;
import org.yamcs.parameter.Value;
import org.yamcs.xtce.Argument;
import org.yamcs.xtce.ArgumentInstanceRef;
import org.yamcs.xtce.DataSource;
import org.yamcs.xtce.DynamicIntegerValue;
import org.yamcs.xtce.Parameter;
import org.yamcs.xtce.ParameterInstanceRef;
import org.yamcs.xtce.ParameterOrArgumentRef;
/**
* This class holds live information used during a (XTCE) processing.
*
* It is created when data is incoming and is used in a processing pipeline. For example when a packet is
* received, the following pipeline is executed:
*
* - a new processing data object is instantiated containing an empty parameter list and a reference to the latest
* parameter value cache
* - parameters are added to it as extracted from the packet
* - calibration (raw to engineering conversion) is performed on the newly added parameters
* - algorithms are run creating new parameters also added to the processing data object
* - monitoring and generation of alarms is done for the new parameters
* - command verifiers are run (possibly creating new parameters TBD)
* - the parameter archive is populated
*
*
* A processing can also start when receiving command history information (used as part of
* command verification), when receiving processed parameters via the pp stream or periodically by algorithms.
*
* There will be different threads running in parallel, each with its own ProcessingData object but one object cannot be
* shared with another thread.
*
*
* The following data is part of this object:
*
* - tmParamsCache - stores the latest values of the "released" TM parameters from a processor (processor's
* lastValueCache). Data can be updated from outside of this processing thread. The cache will buffer older values for
* some parameters if required (for example algorithms or match criteria can require old instances of parameter
* values).
* - tmParams - stores the "current" delivery - parameters that are being produced during the current pipeline
* execution. This list will only modify from within the pipeline (and is not visible outside) and all the data here is
* considered "more recent" than the data from the tmParamsCache. At the end of the execution of the pipeline, the data
* is moved from here to the tmParamsCache (i.e the processor lastValueCache)
* - cmdArgs - if the processing is part of a command, this stores the arguments of the command. Otherwise it is
* null. The command arguments are not modified during the pipeline execution.
* - cmdParamsCache - this is similar with the tmParams but stores parameters that are contextualized to the
* command. This includes command properties and command history parameters. The list can modify from outside the
* pipeline.
* - cmdParams - stores the "current" delivery command parameters. It is initialised when command history
* information is received. New elements can be added by algorithms producing command parameter values. A command
* parameter is one whose datasource is {@link DataSource#COMMAND}.
*
*
*
*/
public class ProcessingData {
final protected LastValueCache tmParamsCache;
final protected ParameterValueList tmParams;
final protected Map cmdArgs;
final protected LastValueCache cmdParamsCache;
final protected ParameterValueList cmdParams;
/**
* Used in a TM processing pipeline - for example when a TM packet is received
*/
public static ProcessingData createForTmProcessing(LastValueCache tmValueCache) {
return new ProcessingData(tmValueCache, new ParameterValueList(), null, null, null);
}
/**
* Used in TC processing when command history events are received, they will be added to the cmdParams.
*/
public static ProcessingData createForCmdProcessing(LastValueCache tmValueCache,
Map arguments, LastValueCache cmdLastValueCache) {
return new ProcessingData(tmValueCache, new ParameterValueList(), arguments, cmdLastValueCache,
new ParameterValueList());
}
/**
* Processing data which contains values to be used in algorithm initialisation.
*
* The tmParams and cmdParams will be null.
*/
public static ProcessingData createInitial(LastValueCache tmParamsCache, Map arguments,
LastValueCache cmdParamsCache) {
return new ProcessingData(tmParamsCache, null, arguments, cmdParamsCache, null);
}
/**
* Create a new processing data object with the tmParamsCache and tmParams shared with the data object, but with new
* cmdParams. To be used in command verifiers - each command has its own context with different cmdParams.
*
* It is used when starting a command processing chain.
*/
public static ProcessingData cloneForCommanding(ProcessingData data, Map arguments,
LastValueCache cmdParams) {
return new ProcessingData(data.tmParamsCache, data.tmParams, arguments, cmdParams, new ParameterValueList());
}
/**
* keeps the tmParamsCache and tmParams from the given data
*/
public static ProcessingData cloneForTm(ProcessingData data) {
return new ProcessingData(data.tmParamsCache, data.tmParams, null, null, null);
}
/**
* creates an object with an empty cache and with the given values as current tm delivery. Used in unit tests
*/
public static ProcessingData createForTestTm(ParameterValue... pvlist) {
ProcessingData data = new ProcessingData(new LastValueCache(), new ParameterValueList(), null, null, null);
for (ParameterValue pv : pvlist) {
data.addTmParam(pv);
}
return data;
}
/**
* same as above but creates command parameters
*/
public static ProcessingData createForTestCmd(ParameterValue... pvlist) {
ProcessingData data = new ProcessingData(new LastValueCache(), null,
null, new LastValueCache(), new ParameterValueList());
for (ParameterValue pv : pvlist) {
data.addCmdParam(pv);
}
return data;
}
public ProcessingData(LastValueCache lastValueCache, ParameterValueList tmParams,
Map cmdArgs, LastValueCache cmdParamsCache, ParameterValueList cmdParams) {
this.tmParams = tmParams;
this.tmParamsCache = lastValueCache;
this.cmdArgs = cmdArgs;
this.cmdParams = cmdParams;
this.cmdParamsCache = cmdParamsCache;
}
public ParameterValueList getTmParams() {
return tmParams;
}
public void addTmParam(ParameterValue pv) {
tmParams.add(pv);
}
public void addTmParams(List params) {
tmParams.addAll(params);
}
public void addCmdParam(ParameterValue pv) {
cmdParams.add(pv);
}
/**
* Returns a parameter value associated to the parameter reference or null if none is found.
*
* The instance is according to XTCE rules: if tmParams/cmdParams contains multiple values for the parameter,
* then the oldest one (first inserted in the list) is instance 0, the next one is instance 1, etc.
*
* The negative instances are retrieved from the cache: -1 is the latest value in tmParamsCache (the one
* which was added last), -2 is the previous one and so on.
*
*
* If {@code allowOld = true} and the tmParams/cmdParams does not contain a value for the parameter, then the
* instances in the cache are counted down from 0 instead of -1.
*
* If {@code allowOld = false}, the return will always be null if the tmParams/cmdParams does not contain a value
* for the parameter.
*
*/
public ParameterValue getParameterInstance(ParameterInstanceRef pref, boolean allowOld) {
Parameter param = pref.getParameter();
if (param.isCommandParameter()) {
return get(cmdParams, cmdParamsCache, param, pref.getInstance(), allowOld);
} else {
return get(tmParams, tmParamsCache, param, pref.getInstance(), allowOld);
}
}
private static ParameterValue get(ParameterValueList tmParams, LastValueCache tmParamsCache, Parameter param,
int instance, boolean allowOld) {
if (tmParams == null || tmParams.getFirstInserted(param) == null) {
if (!allowOld || tmParamsCache == null || instance > 0) {
return null;
}
return tmParamsCache.getValue(param, instance);
} else {
if (instance >= 0) {
return tmParams.get(param, instance);
} else {
return tmParamsCache.getValue(param, instance + 1);
}
}
}
public ArgumentValue getCmdArgument(Argument arg) {
return (cmdArgs == null) ? null : cmdArgs.get(arg);
}
public Map getCmdArgs() {
return cmdArgs;
}
/**
* Returns true if the {@code tmParams} or {@code cmdParams} contains a value for {@code param}
*/
public boolean containsUpdate(Parameter param) {
if (param.isCommandParameter()) {
return cmdParams != null && cmdParams.getFirstInserted(param) != null;
} else {
return tmParams != null && tmParams.getFirstInserted(param) != null;
}
}
public ParameterValueList getCmdParams() {
return cmdParams;
}
public long resolveDynamicIntegerValue(DynamicIntegerValue div, boolean allowOld) throws XtceProcessingException {
ParameterOrArgumentRef ref = div.getDynamicInstanceRef();
RawEngValue pv = null;
if (ref instanceof ParameterInstanceRef) {
pv = getParameterInstance((ParameterInstanceRef) ref, allowOld);
} else if (ref instanceof ArgumentInstanceRef) {
ArgumentInstanceRef argRef = (ArgumentInstanceRef) ref;
Argument arg = cmdArgs.keySet().stream().filter(a -> a.getName().equals(argRef.getName())).findFirst()
.orElse(null);
if (arg == null) {
throw new XtceProcessingException("Missing argument for dynamic integer value: " + ref.getName());
}
pv = cmdArgs.get(arg);
}
if (pv == null) {
throw new XtceProcessingException("Missing value for dynamic integer value: " + ref.getName());
}
Value value = ref.useCalibratedValue() ? pv.getEngValue() : pv.getRawValue();
if (value == null) {
throw new XtceProcessingException("Missing " + (ref.useCalibratedValue() ? "engineering" : "raw")
+ " value for dynamic size in bits parameter: " + ref.getName());
}
try {
return div.transform(value.toLong());
} catch (UnsupportedOperationException e) {
throw new XtceProcessingException("Cannot interpret value of type " + value.getClass()
+ " as integer; used in the dynamic value specification");
}
}
@Override
public String toString() {
return "EvaluatorInput [params=" + tmParams
+ ", cmdArgs=" + ((cmdArgs == null) ? null : cmdArgs.values())
+ ", cmdParams=" + cmdParams
+ ", cmdParamsCache=" + cmdParamsCache + "]";
}
}