/*
* Created on Nov 5, 2004
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*
* CHANGES
* 2005-02-09 JW * main() removed; see de.desy.tine.client.test.sine
* 2005-02-10 JW * Constructors made public
* * registerProperty(), registerDeviceName() made public
* * getExportPro[pertyNames(), getExportDeviceNames() added (wrappers)
* * Made (almost...) independent from TEquipmentModuleFactory-Singleton
* * SetBackgroundTask removed; belongs to EqmFactory.
* * CreateEquipmentModule removed / replaced by initialize().
* 2004-02-14 JW * old stock properties replaced by TPropertyList
* * Stock Equipment function removed, replaced by property handlers
* 2004-02-15 JW * registerStockProperties changed; register only those properties which
* are actually supported.
* 13.7.05 * PD added getExportInformationFromFile()
*
*/
package de.desy.tine.server.equipment;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentLinkedQueue;
import de.desy.tine.addrUtils.TSrvEntry;
import de.desy.tine.client.*;
import de.desy.tine.csvUtils.*;
import de.desy.tine.dataUtils.TDataTime;
import de.desy.tine.dataUtils.TDataType;
import de.desy.tine.definitions.*;
import de.desy.tine.endianUtils.Swap;
import de.desy.tine.headers.TContract;
import de.desy.tine.queryUtils.PropertyQuery;
import de.desy.tine.queryUtils.TPropertyQuery;
import de.desy.tine.queryUtils.XPropertyQuery;
import de.desy.tine.server.alarms.*;
import de.desy.tine.server.connections.TClient;
import de.desy.tine.server.connections.TClientEntry;
import de.desy.tine.server.connections.TContractTable;
import de.desy.tine.server.devices.TDevice;
import de.desy.tine.server.devices.TDeviceList;
import de.desy.tine.server.histories.THistoryRecord;
import de.desy.tine.server.histories.THistoryRecordStruct;
import de.desy.tine.server.histories.THistorySpecification;
import de.desy.tine.server.logger.*;
import de.desy.tine.server.properties.TExportProperty;
import de.desy.tine.server.properties.TMetaProperties;
import de.desy.tine.server.properties.TPropertyDescription;
import de.desy.tine.server.properties.TPropertyEGU;
import de.desy.tine.server.properties.TPropertyHandler;
import de.desy.tine.server.properties.TPropertyList;
import de.desy.tine.server.properties.TStockProperties;
import de.desy.tine.startup.TInitializer;
import de.desy.tine.startup.TInitializerFactory;
import de.desy.tine.stringUtils.StringToName;
import de.desy.tine.stringUtils.WildcardMatch;
import de.desy.tine.structUtils.TStructRegistry;
import de.desy.tine.types.*;
import de.desy.tine.xmlUtils.AlarmDefinitionCfg;
import de.desy.tine.xmlUtils.DeviceCfg;
import de.desy.tine.xmlUtils.EqmCfg;
import de.desy.tine.xmlUtils.FecCfg;
import de.desy.tine.xmlUtils.NameCfgList;
import de.desy.tine.xmlUtils.PropertyCfg;
/**
* A server handles all data requests through its equipment module.
*
* An exported device server refers to one and only one equipment module. The
* equipment module will have a property list and a device list associated with it.
*
* @author duval
*/
public class TEquipmentModule
{
public Object eqmMutex = new Object();
private String context; // the server context (necessary here?)
private String subsystem;
private String exportName = null; // the device server name
private String moduleName = null; // the 'local' name
private String groupName = null; // the device group (if any)
private String groupDevicePrefix = null; // group device prefix (if any)
private String groupDevicePostfix = null; // group device postfix (if any)
private int groupIndex = 0; // the device group index (if any)
private String master; // failover master (if set)
private String slaveMaster; // failover slave master (if set and eqm is a slave)
private int failoverType = TEquipmentModuleFactory.FAILOVER_NONE;
public int getFailoverType() { return failoverType; }
protected TEquipmentModuleFactory gEqmFactory = null;
public TEquipmentModuleFactory getEquipmentModuleFactory()
{
if (gEqmFactory == null) gEqmFactory = TEquipmentModuleFactory.getInstance();
return gEqmFactory;
}
public class ACLGroup
{
protected String groupName;
protected LinkedList<String> members = new LinkedList<String>();
}
protected LinkedList<String> gRegisteredUsersList = new LinkedList<String>();
protected LinkedList<String> gRegisteredGroupsList = new LinkedList<String>();
protected LinkedList<String> gRegisteredNetsList = new LinkedList<String>();
protected LinkedList<String> gGCastNetsList = new LinkedList<String>();
protected HashMap<Integer,TAlarmDefinition> alarmDefinitionList = new HashMap<Integer,TAlarmDefinition>();
protected boolean gRejectAllNets = false;
public class PrpDbaItem
{
String prp;
String usr;
long lastAccess;
InetAddress addr;
int deadband;
int access;
PrpDbaItem(String property,int access,int deadbandInMilliseconds)
{
prp = new String(property);
this.access = access;
deadband = deadbandInMilliseconds;
}
}
protected HashMap<String,PrpDbaItem> dbgList = new HashMap<String,PrpDbaItem>();
protected void addPrpDbaItem(String property,int access,int deadbandInMilliseconds)
{
PrpDbaItem dba = null;
if (dbgList.containsKey(property))
{
dba = dbgList.get(property);
dba.deadband = deadbandInMilliseconds;
dba.access = access;
}
else
{
dba = new PrpDbaItem(property,access,deadbandInMilliseconds);
dbgList.put(property, dba);
}
}
protected PrpDbaItem getPrpDbaItem(String property)
{
return dbgList.get(property);
}
public void dumpDeadbands()
{
Set<String> prpSet = dbgList.keySet();
if (prpSet == null)
{
TLinkFactory.dbgPrint("there are no registered deadband access properties!");
return;
}
TLinkFactory.dbgPrint("current deadband access for "+getExportName()+":");
TLinkFactory.dbgPrint("\tProperty : deadband, applies to, last access");
Iterator<String> it = prpSet.iterator();
String prp;
PrpDbaItem dba;
while (it.hasNext())
{
prp = it.next();
if ((dba=dbgList.get(prp)) == null) continue;
TLinkFactory.dbgPrint("\t"+prp+" : "+dba.deadband+" ms, "+
TAccess.toString((short)dba.access)+", "+
TDataTime.toString(dba.lastAccess)+", "+
dba.usr+", "+dba.addr.getHostAddress());
}
}
public HashMap<Integer, TAlarmDefinition> getAlarmDefinitionList() { return alarmDefinitionList; }
protected HashMap<String,TPropertySignalHandler> prpSigHdlrList = new HashMap<String,TPropertySignalHandler>();
/**
* Registers a property signal handler for the given property
*
* Passing a 'null' handler will remove any property signal handler which
* might be associated with the property in question.
*
* @param property is the designated property for which signals are to be
* raised.
* @param handler is the property signal handler function which should be called
* when the property in question is being accessed.
*
* @return 0 upon success or a TINE error code.
*/
public int registerPropertySignalHandler(String property,TPropertySignalHandler handler)
{
if (!propertyList.hasProperty(property)) return TErrorList.illegal_property;
if (handler == null)
{
prpSigHdlrList.remove(property);
}
else
{
prpSigHdlrList.put(property, handler);
}
return 0;
}
protected void sendPropertySignal(String prp,TContract con,int sig,int sts)
{
TPropertySignalHandler psh = prpSigHdlrList.get(prp);
if (psh == null) return;
psh.handler(sig, prp, con, sts);
}
/**
* Inserts an alarm definition into the alarm definition table.
*
* As an alternative to the <local name>-alarms.csv configuration file,
* the front end server can make use of this API call in order to fill
* in the alarm definition table describing locally generated alarms.
* This is particularly useful for embedded platforms where there is
* no file system, or where a TINE server is used as a translation layer
* and needs to map a given alarm system onto the TINE alarm system.
*
* @param code is a specific alarm code to apply the alarm definition to.
* (Use the method without this parameter to simply apply the
* code registered in the TAlarmDefinition instance.)
* @param adef is an instance of an Alarm Definition Structure (ADS)
* containing the alarm table information which is to be appended
* to the alarm definition table
*
* @return 0 or a TINE error code.
*/
public int addAlarmDefinition(int code,TAlarmDefinition adef)
{
if (code < 0 || adef == null) return TErrorList.argument_list_error;
alarmDefinitionList.put(new Integer(code),adef);
return 0;
}
/**
* Inserts an alarm definition into the alarm definition table.
*
* As an alternative to the <local name>-alarms.csv configuration file,
* the front end server can make use of this API call in order to fill
* in the alarm definition table describing locally generated alarms.
* This is particularly useful for embedded platforms where there is
* no file system, or where a TINE server is used as a translation layer
* and needs to map a given alarm system onto the TINE alarm system.
*
* @param adef is an instance of an Alarm Definition Structure (ADS)
* containing the alarm table information which is to be appended
* to the alarm definition table
*
* @return 0 or a TINE error code.
*/
public int addAlarmDefinition(TAlarmDefinition adef)
{
if (adef == null) return TErrorList.argument_list_error;
return addAlarmDefinition(adef.getAlarmCode(),adef);
}
public TAlarmDefinition getAlarmDefinition(int code)
{
return alarmDefinitionList.get(new Integer(code));
}
TPropertyList stockList; // = new TPropertyList(); // a list or a query fcn
TPropertyList propertyList = new TPropertyList(); // a list or a query fcn
TDeviceList deviceList = new TDeviceList();
int numDevicesFromExportsFile = 0;
public int getNumberDevicesFromExportsFile() { return numDevicesFromExportsFile; }
public TDeviceList getDeviceList() { return deviceList; }
public TPropertyList getPropertyList() { return propertyList; }
/**
* Obtains a TDevice instance for the input device name
*
* @param devName is the device name for which the TDevice
* instance is desired
*
* @return a TDevice Instance or null
*/
public TDevice getDevice(String devName)
{
return deviceList.getDevice(devName);
}
/**
* Obtains a TDevice instance for the input device number
*
* @param devNumber is the device number for which the TDevice
* instance is desired
*
* @return a TDevice Instance or null
*/
public TDevice getDevice(int devNumber)
{
return deviceList.getDevice(devNumber);
}
public int getDeviceNumber(String devName)
{
try
{
if (devName.startsWith("#")) return Integer.parseInt(devName.substring(1));
return deviceList.getDeviceNumber(devName);
}
catch (Exception e)
{
MsgLog.log("getDeviceNumber",e.toString(),TErrorList.code_failure,e,0);
return -1;
}
}
public int getDeviceNumber(String devName,String devProperty)
{
try
{
if (devName == null) return -TErrorList.argument_list_error;
if (devName.startsWith("#")) return Integer.parseInt(devName.substring(1));
if (deviceList.isPropertyOriented() && devProperty != null)
{
TExportProperty prp = propertyList.getFirstProperty(devProperty);
if (prp != null)
{
ArrayList<String> lst = prp.getDeviceList();
if (lst != null) return lst.indexOf(devName);
}
}
return deviceList.getDeviceNumber(devName);
}
catch (Exception e)
{
MsgLog.log("getDeviceNumber",e.toString(),TErrorList.code_failure,e,0);
return -1;
}
}
protected TAlarmDynSet almDynSet = new TAlarmDynSet();
protected String[] gPropertyNameList = null;
protected LinkedList<TAlarmWatchEntry> gAlarmWatchList = new LinkedList<TAlarmWatchEntry>();
protected LinkedList<THistoryRecord> gLclHstList = new LinkedList<THistoryRecord>();
private boolean useMonthlyHistoryFiles = false;
public void setUseMSecHistoryTimestamps(boolean useMsecHistoryTimestamps)
{
useMinimalStorage = !useMsecHistoryTimestamps;
}
private boolean useMinimalStorage = false;
public boolean isUseMinimalStorage() { return useMinimalStorage; }
public boolean isUseMSecHistoryTimestamps() { return !useMinimalStorage; }
public void setUseMonthlyHistoryFiles(boolean useMonthlyFiles)
{
useMonthlyHistoryFiles = useMonthlyFiles;
}
public boolean isUseMonthlyHistoryFiles() { return useMonthlyHistoryFiles; }
public THistoryRecord getLocalHistoryRecord(String property,String device)
{
return getLocalHistoryRecord(property,device,0,TFormat.CF_NULL);
}
public THistoryRecord getLocalHistoryRecord(String property,String device,int size,short format)
{
int listsize = gLclHstList.size();
THistoryRecord lhr = null;
if (property == null || property.length() == 0) return null;
for (int i=0; i<listsize; i++)
{
lhr = (THistoryRecord)gLclHstList.get(i);
if (lhr.getPrp().compareTo(property) != 0) continue;
if (device != null && device.length() > 0 &&
!device.startsWith("#") &&
lhr.getDev().compareToIgnoreCase(device) != 0)
continue;
if (size > 0 && lhr.getArraySize() != size) continue;
if (format != TFormat.CF_NULL && lhr.getFmt() != (byte)format) continue;
return lhr;
}
return null;
}
/**
* Inserts a property to be monitored into the local alarm server's Watch Table.
*
* Certain alarms are to be set whenever the value of a property exceeds a
* definable threshold. Such alarms can be managed automatically by the
* local alarm server if the alarm criteria are entered into the alarm watch
* table. This can be achieved by calling this routine (or supplying a
* startup configuration file almwatch.csv).
*
* @param deviceName is the device name associated with the property to be
* called by the local alarm server.
* @param propertyName is the property which is to be called by the
* local alarm server.
* @param dataSize is the data array size to be called by the local alarm server.
* @param dataFormat is the TINE data format to be called by the local alarm server
* @param alarmSystem is the alarm system identifier to be associated with the alarm.
* The value of '0' signals the Central Alarm Server to apply the designated
* alarm system code for the server in question.
* @param alarmSeverity is the severity of the alarm issued when the data returned
* by the call exceed the given thresholds.
* @param alarmCode is the designated alarm code to apply to any alarm condition.
* Pass a '0' to distinguish between the alarmCodeHigh and alarmCodeLow
* conditions (next 2 parameters).
* @param alarmCodeHigh is the alarm code to apply when the high threshold value
* is exceeded by the readback data. (parameter alarmCode must be '0').
* If both alarmCode and alarmCodeHigh are '0', then the code
* TErrorList.value_too_high (or TErrorList.warn_too_high) is applied.
* @param alarmCodeLow is the alarm code to apply when the low threshold value
* is exceeded by the readback data. (parameter alarmCode must be '0').
* If both alarmCode and alarmCodeLow are '0', then the code
* TErrorList.value_too_low (or TErrorList.warn_too_low) is applied.
* @param alarmWatchThreshold is an intance of a TAlarmWatchThreshold which
* defines the threshold conditions for applying an alarm.
* @return 0 or an TINE error code (e.g. TErrorList.illegal_property).
*/
public int addAlarmWatchTableEntry(String deviceName,String propertyName,int dataSize,int dataFormat,
int alarmSystem,int alarmSeverity,int alarmCode,int alarmCodeHigh,int alarmCodeLow,
TAlarmWatchThreshold alarmWatchThreshold)
{
TExportProperty p = propertyList.getFirstProperty(propertyName);
if (p == null) return TErrorList.illegal_property;
TPropertyDescription pd = p.getDescription();
short arrayType = pd == null ? TArrayType.AT_UNKNOWN : pd.getArrayType();
TAlarmWatchEntry awe = new TAlarmWatchEntry(this,deviceName,
propertyName,dataSize,dataFormat,
arrayType,alarmSystem,
alarmSeverity,alarmCode,
alarmCodeHigh,alarmCodeLow,alarmWatchThreshold);
gAlarmWatchList.add(awe);
return 0;
}
/**
* Inserts a property to be monitored into the local alarm server's Watch Table.
*
* Certain alarms are to be set whenever the value of a property exceeds a
* definable threshold. Such alarms can be managed automatically by the
* local alarm server if the alarm criteria are entered into the alarm watch
* table. This can be achieved by calling this routine (or supplying a
* startup configuration file almwatch.csv).
*
* @param deviceName is the device name associated with the property to be
* called by the local alarm server.
* @param propertyName is the property which is to be called by the
* local alarm server.
* @param dataSize is the data array size to be called by the local alarm server.
* @param dataFormat is the TINE data format to be called by the local alarm server
* @param alarmSeverity is the severity of the alarm issued when the data returned
* by the call exceed the given thresholds.
* @param alarmCodeHigh is the alarm code to apply when the high threshold value
* is exceeded by the readback data.
* If alarmCodeHigh is '0', then the code
* TErrorList.value_too_high (or TErrorList.warn_too_high) is applied.
* @param alarmCodeLow is the alarm code to apply when the low threshold value
* is exceeded by the readback data.
* If alarmCodeLow is '0', then the code
* TErrorList.value_too_low (or TErrorList.warn_too_low) is applied.
* @param alarmWatchThreshold is an intance of a TAlarmWatchThreshold which
* defines the threshold conditions for applying an alarm.
* @return 0 or an TINE error code (e.g. TErrorList.illegal_property).
*/
public int addAlarmWatchTableEntry(String deviceName,String propertyName,int dataSize,int dataFormat,
int alarmSeverity,int alarmCodeHigh,int alarmCodeLow,
TAlarmWatchThreshold alarmWatchThreshold)
{
return addAlarmWatchTableEntry(deviceName,propertyName,dataSize,dataFormat,
0,alarmSeverity,0,alarmCodeHigh,alarmCodeLow,alarmWatchThreshold);
}
/**
* Inserts a property to be monitored into the local alarm server's Watch Table.
*
* Certain alarms are to be set whenever the value of a property exceeds a
* definable threshold. Such alarms can be managed automatically by the
* local alarm server if the alarm criteria are entered into the alarm watch
* table. This can be achieved by calling this routine (or supplying a
* startup configuration file almwatch.csv).
*
* @param deviceName is the device name associated with the property to be
* called by the local alarm server.
* @param propertyName is the property which is to be called by the
* local alarm server.
* @param dataSize is the data array size to be called by the local alarm server.
* @param dataFormat is the TINE data format to be called by the local alarm server
* @param alarmSeverity is the severity of the alarm issued when the data returned
* by the call exceed the given thresholds.
* @param alarmCode is the designated alarm code to apply to any alarm condition.
* Pass a '0' to distinguish between the alarmCodeHigh and alarmCodeLow
* conditions (next 2 parameters).
* @param alarmWatchThreshold is an instance of a TAlarmWatchThreshold which
* defines the threshold conditions for applying an alarm.
* @return 0 or an TINE error code (e.g. TErrorList.illegal_property).
*/
public int addAlarmWatchTableEntry(String deviceName,String propertyName,int dataSize,int dataFormat,
int alarmSeverity,int alarmCode,
TAlarmWatchThreshold alarmWatchThreshold)
{
return addAlarmWatchTableEntry(deviceName,propertyName,dataSize,dataFormat,
0,alarmSeverity,alarmCode,0,0,alarmWatchThreshold);
}
/**
* Inserts a local history element into the local history server.
*
* A server can instruct the local history server to keep a history of
* the given property by utilizing this call. The local history server
* will periodically call the property as specified according to the
* following input parameters.
*
* @param recordIndex is the local history index to be identified with
* this local history element (Note: this must be unique with this
* server process and within the history data repository).
* @param device is the device name to be associated with the property
* name supplied as the second parameter.
* @param property is the requested property for which a history is to
* be kept
* @param dataSize is the length of the local history call.
* @param dataFormat is the TINE format of the local history call.
*
* @note This call will use the default history acquisition specifications
* of 1 Hz polling and archive intervals, 5 minutes short term and 1 month
* long term depths, 30 minutes archive heartbeat and 10 percent tolerance.
*
* @return
*/
public int addLocalHistoryRecord(int recordIndex,String device,String property,int dataSize,int dataFormat)
{
short arrayType = TArrayType.AT_UNKNOWN;
TExportProperty p = propertyList.getFirstProperty(property);
if (p != null)
{
TPropertyDescription pd = p.getDescription();
arrayType = pd == null ? TArrayType.AT_UNKNOWN : pd.getArrayType();
}
return addLocalHistoryRecord(recordIndex,device,property,dataSize,dataFormat,arrayType);
}
public int addLocalHistoryRecord(int recordIndex,String device,String property,int dataSize,int dataFormat,int arrayType)
{
THistorySpecification spc = THistorySpecification.getDefaultInstance();
return addLocalHistoryRecord(recordIndex,device,property,dataSize,dataFormat,arrayType,spc);
}
/**
* Inserts a local history element into the local history server.
*
* A server can instruct the local history server to keep a history of
* the given property by utilizing this call. The local history server
* will periodically call the property as specified according to the
* following input parameters.
*
* @param recordIndex is the local history index to be identified with
* this local history element (Note: this must be unique with this
* server process and within the history data repository).
* @param device is the device name to be associated with the property
* name supplied as the second parameter.
* @param property is the requested property for which a history is to
* be kept
* @param dataSize is the length of the local history call.
* @param dataFormat is the TINE format of the local history call.
* @param arrayType is the input property's array type. Passing a value
* of '0' (AT_UNKNOWN) will instruct the subsystem to determine
* the property's array type from the property registry.
* @param histSpec is an instance of t THistorySpecification object
* which instructs the local history subsystem how to maintain
* the local history information (e.g. short and long term
* storage depths, filtering conditions, polling and archive
* intervals).
*
* @return
*/
public int addLocalHistoryRecord(int recordIndex,String device,String property,int dataSize,int dataFormat,int arrayType,THistorySpecification histSpec)
{
if (device == null || property == null || dataSize < 1 || recordIndex < 0) return TErrorList.invalid_parameter;
if (isHstRecordInLst(device,property,dataSize,dataFormat)) return 0;
if (arrayType == TArrayType.AT_UNKNOWN)
{
TExportProperty p = propertyList.getFirstProperty(property);
if (p == null) return TErrorList.illegal_property;
TPropertyDescription pd = p.getDescription();
arrayType = pd == null ? TArrayType.AT_UNKNOWN : pd.getArrayType();
}
THistoryRecord hst = new THistoryRecord(this,device,property,dataSize,dataFormat,arrayType,recordIndex,histSpec);
if (useMinimalStorage) hst.setUseMinimalStorage(true);
if (useMonthlyHistoryFiles) hst.setUseMonthlyHistoryFiles(true);
gLclHstList.add(hst);
if (histSpec.getDepthLong() <= 0 && histSpec.getDepthShortInSeconds() > 3600 * 6)
{ // no long term storage and more than 6 hours worth of short-term !
hst.needsToFillSTS = true;
}
return 0;
}
private boolean isHstRecordInLst(String dev,String prp,int siz,int fmt)
{
if (gLclHstList == null) return false;
THistoryRecord thr;
Iterator<THistoryRecord> it = gLclHstList.iterator();
while (it.hasNext())
{
thr = it.next();
if (thr.getPrp().compareTo(prp) != 0) continue;
if (thr.getDev().compareTo(dev) != 0) continue;
if (thr.getArraySize() != siz) continue;
if (thr.getFmt() != fmt) continue;
return true;
}
return false;
}
private boolean isIdle = false;
public boolean isIdleState() { return isIdle; }
public void setIdleState(boolean value)
{
isIdle = value;
Iterator<TEquipmentBackgroundTask> li = bkgTasks.iterator();
while (li.hasNext())
{ // pass on to any associated background tasks ...
li.next().setIdleState(value);
}
}
public boolean hasInitialized = false;
public boolean isRegistered; // registered with name server
public boolean hasCasAttached = false;
public boolean casReadRequired = false;
public boolean grpRegistered = false;
public boolean registerAsMaster = false;
private String casName;
public String getCasName() { return casName; }
//TAlarmTable alarms; // active alarms + alarm definitions
int numClients;
int numContracts;
boolean isCasInClientList()
{
if (casName == null) return false;
TClientEntry[] tce = getClientList();
for (int i=0; i<tce.length; i++)
if (tce[i].cln.userName.compareTo(casName) == 0)
{
casReadRequired = true;
hasCasAttached = true;
return true;
}
return false;
}
public boolean hasExclusiveRead(String propertyName,boolean checkLocked)
{
if (checkLocked)
{ // check exclusive read condition in a locked state
if (accessLock.getLockType() == AccessLock.LOCK_UNLOCKED)
{ // not locked !
return false;
}
}
TExportProperty txp = propertyList.getFirstProperty(propertyName);
if (txp == null) return false;
if (!checkLocked) return txp.hasUnlockedExclusiveRead;
return txp.hasExclusiveRead;
}
public boolean hasExclusiveRead(String propertyName)
{
return hasExclusiveRead(propertyName,true);
}
class AccessLock
{
static final int LOCK_UNLOCKED = 0;
static final int LOCK_PREEMPTIVE = 1;
static final int LOCK_PERSISTENT = 2;
static final int LOCK_ABORT = 3;
static final int LOCK_XREAD = 0x100;
private TClient cln;
private int lockType = LOCK_UNLOCKED;
private long lockDuration = 0;
private long lockStart;
long getLockDuration() { return lockDuration; }
int getLockType() { return lockType; }
long getLockStart() { return lockStart; }
void checkAccessLocks()
{
long t = System.currentTimeMillis();
if (t > lockStart + lockDuration)
{
lockStart = 0;
lockType = LOCK_UNLOCKED;
}
}
boolean clientCanWrite(TClient tc)
{
if (lockType == LOCK_UNLOCKED) return true;
if (tc.IPaddress == cln.IPaddress &&
tc.userName.compareTo(cln.userName) == 0 &&
tc.port == cln.port)
return true;
return false;
}
int setAccessLock(TClient tc,int type,int duration)
{
boolean passed = false;
int baseType = type & 0xff;
if (baseType < LOCK_UNLOCKED || baseType > LOCK_ABORT) return TErrorList.out_of_range;
if (clientCanWrite(tc)) passed = true;
else if ((lockType & 0xff) != LOCK_PERSISTENT) passed = true;
if (!passed) return TErrorList.access_denied;
if (duration < 0) duration = 0;
if (duration > TEquipmentModuleFactory.MAXIMUM_LOCK_DURATION)
duration = TEquipmentModuleFactory.MAXIMUM_LOCK_DURATION;
if (!getEquipmentModuleFactory().gPutCommandsInFeclog)
{
String cmdString = "COMMAND ACCESSLOCK" + " called by " + tc.userName +
" from addr " + tc.IPaddress.getHostAddress() + " : ";
if (lockType != type) TFecLog.log(cmdString);
}
if (baseType == LOCK_ABORT || baseType == LOCK_UNLOCKED)
{
lockStart = 0;
lockType = LOCK_UNLOCKED;
}
else
{
cln = tc;
lockType = type;
lockDuration = duration * 1000;
lockStart = System.currentTimeMillis();
}
return 0;
}
String[] getAccessLockAsString()
{
String[] s = new String[3];
if (lockType == LOCK_UNLOCKED)
{
s[0] = s[1] = "";
}
else
{
int secs = (int)((lockStart + lockDuration - System.currentTimeMillis())/1000);
if (secs < 0) secs = 0;
s[0] = cln.userName;
s[1] = cln.IPaddress.getHostAddress();
s[2] = new String("" + secs + " sec remaining");
}
return s;
}
}
public AccessLock accessLock = new AccessLock();
// REMOVED TEquipmentFunction stkMod; // stock meta property eqp. fcn.
//TEquipmentFunction stkFcn; // stock property eqp. fcn.
TEquipmentFunction eqpFcn = null;
//TEquipmentBackgroundTask eqpBkg;
private TEquipmentInitRoutine eqpIni;
public TEquipmentInitRoutine getInitializationRoutine() { return eqpIni; }
public void setInitializationRoutine(TEquipmentInitRoutine initRoutine)
{
eqpIni = initRoutine;
}
private TEquipmentExitRoutine eqpExi;
public TEquipmentExitRoutine getExitRoutine() { return eqpExi; }
public void setExitRoutine(TEquipmentExitRoutine exitRoutine)
{
eqpExi = exitRoutine;
}
public NAME16[] getRegisteredUsers() { return StringToName.stringSetToName16(gRegisteredUsersList); }
public int addRegisteredUser(String newUser)
{
if (newUser == null) return TErrorList.argument_list_error;
newUser = newUser.toUpperCase();
synchronized (gRegisteredUsersList)
{
if (gRegisteredUsersList.contains(newUser)) return TErrorList.already_assigned;
gRegisteredUsersList.add(newUser);
}
return 0;
}
public int addRegisteredUser(LinkedList<String> lst, String newUser)
{
if (lst == null || newUser == null) return TErrorList.argument_list_error;
if (!newUser.startsWith("<")) newUser = newUser.toUpperCase();
synchronized (lst)
{
if (lst.contains(newUser)) return TErrorList.already_assigned;
lst.add(newUser);
}
return 0;
}
public int removeRegisteredUser(String oldUser)
{
if (oldUser == null) return TErrorList.argument_list_error;
oldUser = oldUser.toUpperCase();
synchronized (gRegisteredUsersList)
{
if (!gRegisteredUsersList.contains(oldUser)) return TErrorList.invalid_name;
gRegisteredUsersList.remove(oldUser);
}
return 0;
}
public void removeAllRegisteredUsers()
{
synchronized (gRegisteredUsersList)
{
gRegisteredUsersList.clear();
}
}
public int addRegisteredNet(LinkedList<String> lst,String newNet)
{
if (lst == null || newNet == null) return TErrorList.argument_list_error;
synchronized (lst)
{
if (lst.contains(newNet)) return TErrorList.already_assigned;
lst.add(newNet);
}
return 0;
}
public int addRegisteredNet(String newNet)
{
if (newNet == null) return TErrorList.argument_list_error;
synchronized (gRegisteredNetsList)
{
if (gRegisteredNetsList.contains(newNet)) return TErrorList.already_assigned;
gRegisteredNetsList.add(newNet);
}
return 0;
}
public int removeRegisteredNet(String oldNet)
{
if (oldNet == null) return TErrorList.argument_list_error;
synchronized (gRegisteredNetsList)
{
if (!gRegisteredNetsList.contains(oldNet)) return TErrorList.invalid_name;
gRegisteredNetsList.remove(oldNet);
}
return 0;
}
public void removeAllRegisteredNets()
{
synchronized (gRegisteredNetsList)
{
gRegisteredNetsList.clear();
}
}
public NAME16[] getRegisteredNets() { return StringToName.stringSetToName16(gRegisteredNetsList); }
public int addGCastNet(String newNet)
{
if (gGCastNetsList.contains(newNet)) return TErrorList.already_assigned;
gGCastNetsList.add(newNet);
return 0;
}
public int removeGCastNet(String oldNet)
{
if (!gGCastNetsList.contains(oldNet)) return TErrorList.invalid_name;
gGCastNetsList.remove(oldNet);
return 0;
}
public void removeAllGCastNets()
{
gGCastNetsList.clear();
}
public NAME16[] getGCastNets() { return StringToName.stringSetToName16(gGCastNetsList); }
public void setCompletionString(String completionString)
{
TContractTable tct = this.getTEqmFactory().getCurrentContractEntry();
if (tct != null) tct.compString = completionString;
}
/**
* Sets the desired local equipment module name for this equipment
* module.
*
* This name is not directly visible to client-side API calls
* outside the server process, although it will show up in log files
* and in address information. Client API calls make use of the
* 'exported' device server name.
* It largely serves as an internal
* reference name and is currently restricted to 6 characters.
* This must
* be set prior to initializing the server with systemInit() from
* TEquipmentModuleFactory or prior to adding the equipment module to
* the Factory in case it has already been initialized. *
* @param localName is the desired local equipment module name.
*
* @return 0 upon success.
*
* @see setExportName().
*/
public int setLocalName(String localName)
{
moduleName = localName;
if (localName.length() > TStrings.EQM_NAME_SHORTSIZE)
{
moduleName = localName.substring(0,TStrings.EQM_NAME_SHORTSIZE);
TFecLog.log("module name "+localName+" too long; truncating to "+moduleName);
}
TStrings.validateLocalName(moduleName);
getEquipmentModuleFactory().registrationPending = true;
return 0;
}
/**
* @return the current setting of the local equipment module name.
*/
public String getLocalName() { return moduleName; }
public String getModuleName() { return moduleName; }
/**
* Directly sets the export name to use for this equipment module, i.e.
* the 'device server' name.
*
* @param exportName is the desired export name. This must
* be set prior to initializing the server with systemInit() from
* TEquipmentModuleFactory or prior to adding the equipment module to
* the Factory in case it has already been initialized. Also the current setting
* must be a null string, otherwise it will not be accepted. Such
* parameters may also be established via a configuration database.
*
* @return 0 upon success.
*/
public int setExportName(String exportName)
{
if (this.exportName == null)
{
this.exportName = new String(exportName);
TStrings.validateExportName(this.exportName);
return 0;
}
return TErrorList.already_assigned;
}
/**
* @return the current setting for the server's export name.
*/
public String getExportName()
{
return exportName;
}
/**
* Sets an optional group server name which this server should join.
*
* A device server exported under a particular name represents a physical
* device server managing its devices and properties itself (unless explicitly
* redirecting). A device server can also join a 'group server' by
* calling this routine at initialization. The group server will be
* created at the GENS if it does not already exist and the device server
* will become a member of the group. The metric order of the device server's
* devices can be set by calling setGroupIndex(). The device names can
* also be pre-pended or post-pended with specific tags (if necessary) by
* calling setGroupDevicePrefix() or setGroupDevicePostfix().
*
* @param grpName is the name of the group server to join. A null or empty value (true in most cases) indicates that the
* server is not to be a member of a group server.
*/
public void setGroupName(String grpName)
{
if (groupName == null)
{
groupName = new String(grpName);
TStrings.validateExportName(groupName);
grpRegistered = false;
getEquipmentModuleFactory().registrationPending = true;
}
}
/**
* Gets the current group server name setting.
*
* A device server exported under a particular name represents a physical
* device server managing its devices and properties itself (unless explicitly
* redirecting). A device server can also join a 'group server' by
* calling setGroupName() at initialization. The group server will be
* created at the GENS if it does not already exist and the device server
* will become a member of the group.
*
* @return the name of the group server with this device server will or has
* joined. A null or empty value (true in most cases) indicates that the
* server is not a member of a group server.
*/
public String getGroupName() { return groupName; }
/**
* Sets the device name prefix to use if the device server joins a group.
*
* @param prefix is the desired device name prefix.
*
* @see setGroupName
*/
public void setGroupDevicePrefix(String prefix)
{
if (prefix != null && prefix.length() > 8)
{
prefix = prefix.substring(0, 8);
}
groupDevicePrefix = prefix;
}
/**
* Gets the device name prefix to use if the device server joins a group.
*
* @return the current setting of the device name prefix.
*
* @see setGroupName
*/
public String getGroupDevicePrefix()
{
return groupDevicePrefix;
}
/**
* Sets the device name postfix to use if the device server joins a group.
*
* @param postfix is the desired device name postfix.
*
* @see setGroupName
*/
public void setGroupDevicePostfix(String postfix)
{
if (postfix != null && postfix.length() > 8)
{
postfix = postfix.substring(0, 8);
}
groupDevicePostfix = postfix;
}
/**
* Gets the device name postfix to use if the device server joins a group.
*
* @return the current setting of the device name postfix.
*
* @see setGroupName
*/
public String getGroupDevicePostfix()
{
return groupDevicePostfix;
}
/**
* Sets the device list metric to use if the device server joins a group.
*
* @param metric is the desired device group metric. This determines
* the order of the device server devices in the group server's device
* list. (default = 0). Group members with the same metric will have
* their devices listed in the order they were originally received by
* the group server.
*
* @see setGroupName
*/
public void setGroupIndex(int metric)
{
groupIndex = metric;
}
/**
* Gets the device list metric used if the device server joins a group.
*
* @return the current setting of this value.
*/
public int getGroupIndex() { return groupIndex; }
/**
* Directly sets the export context to use for this equipment module.
*
* @param exportContext is the desired export context. This must
* be set prior to initializing the server with systemInit() from
* TEquipmentModuleFactory or prior to adding the equipment module to
* the Factory in case it has already been initialized. Such
* parameters may also be established via a configuration database.
*
* @return 0 upon success.
*/
public int setContext(String exportContext)
{
if (context == null && exportContext != null)
{
context = exportContext;
TStrings.validateContextName(exportContext);
return 0;
}
return TErrorList.already_assigned;
}
/**
* @return the current setting for the export context.
*/
public String getContext()
{
return context;
}
public String getPrimaryContext()
{
if (context == null) return context;
if (subsystem == null || subsystem.length() == 0) return context;
int idx = context.indexOf('.');
if (idx < 1) return context;
return context.substring(0, idx);
}
public int setMaster(String expMaster)
{
if (master == null && expMaster != null)
{
master = expMaster;
TStrings.validateExportName(expMaster);
if (master.length() > 0)
{
failoverType = TEquipmentModuleFactory.FAILOVER_MASTER;
registerAsMaster = true;
}
else
{
failoverType = TEquipmentModuleFactory.FAILOVER_NONE;
registerAsMaster = false;
}
}
return 0;
}
public String getMaster() { return master; }
public int setSlaveMaster(String expMaster, String slvMaster)
{
if (master != null && expMaster != null)
{
master = expMaster; slaveMaster = slvMaster;
TStrings.validateExportName(expMaster);
TStrings.validateExportName(slvMaster);
if (master.length() > 0 && slaveMaster.length() > 0)
{
failoverType = TEquipmentModuleFactory.FAILOVER_SLAVE;
startFailoverMonitor();
}
else
{
failoverType = TEquipmentModuleFactory.FAILOVER_NONE;
}
registerAsMaster = false;
}
return 0;
}
public String getSlaveMaster() { return slaveMaster; }
private int foPollingInterval = 1000;
private int foThreshold = 5;
private boolean foMonitorStarted = false;
class FailOverCallback implements TLinkCallback
{
int errcnt=0;
int last_cc=0;
boolean ismaster = false;
public void callback(TLink link)
{
int cc = link.getLinkStatus();
if (last_cc != cc)
{
TFecLog.log("failover slave link status changed from "+
TErrorList.getErrorString(last_cc)+" to "+TErrorList.getErrorString(cc));
last_cc = cc;
}
if (cc != 0)
{
errcnt++;
if (errcnt > foThreshold && !ismaster)
{ // need to take over as the master !
getEquipmentModuleFactory().registrationPending = true;
registerAsMaster = true;
ismaster = true;
ClsLog.log(getExportName()+" is taking over as "+getMaster()+" master",
getContext(),"FAILOVER",gEqmFactory.getFecName(),ClsLog.ClogPriority.CLOG_PRIORITY_IMPORTANT,ClsLog.ClogStatus.CLOG_STATUS_WARN);
}
return;
}
errcnt = 0;
ismaster = false;
}
}
private int startFailoverMonitor()
{
if (foMonitorStarted) return TErrorList.already_assigned;
if (failoverType != TEquipmentModuleFactory.FAILOVER_SLAVE) return TErrorList.not_allowed;
String mstr = getSlaveMaster();
if (mstr == null || mstr.length() == 0) return TErrorList.not_allowed;
String tgt = "/"+getContext()+"/"+mstr;
int[] lval = new int[1];
TDataType dout = new TDataType(lval);
TLink lnk = new TLink(tgt,"SRVSTARTTIME",dout,null,TAccess.CA_READ);
int id = lnk.attach(TMode.CM_TIMER, new FailOverCallback(), foPollingInterval);
foMonitorStarted = true;
TFecLog.log("failover slave link to "+tgt+" : "+(id < 0 ? lnk.getLastError() : "success"));
return ( id < 0) ? -id : 0;
}
public TEquipmentModuleFactory getTEqmFactory() { return gEqmFactory; }
public TClient getCaller()
{
TContractTable tct = gEqmFactory.getCurrentContractEntry();
TClientEntry tce = null;
if (tct != null)
{
try
{
tce = (TClientEntry)tct.clt.element();
}
catch (NoSuchElementException e)
{
DbgLog.log("getCaller", "contract does not have a client list");
}
}
return tce != null ? tce.cln : null;
}
public TClientEntry[] getClientList()
{
TContractTable tct = gEqmFactory.getCurrentContractEntry();
return tct != null ? ((TClientEntry[])tct.clt.toArray(new TClientEntry[0])) : null;
}
protected int clearCASAlarmList()
{
String ctx = getPrimaryContext();
String exp = getExportName();
String eqm = getLocalName();
if (ctx == null || exp == null || eqm == null) return TErrorList.invalid_name;
if (eqm.compareTo(TSrvEntry.SRVEQM_NAME) == 0) return 0;
String devName = "/" + ctx + "/CAS/" + exp;
int cc = TErrorList.address_unknown;
String fec = null;
try
{
TLink lnk = new TLink(devName,"REMOVEALARMS",null,null,TAccess.CA_WRITE);
cc = lnk.execute(200,true);
fec = lnk.srvAddr.fecName;
lnk.close();
}
catch (Exception e)
{ // a non-existent server runtime exception is often normal here !
// just continue (in many cases, there is NO CAS in the corresponding context!)
}
if (cc == 0)
{ // CAS exists in this context and is monitoring this FEC
casReadRequired = true;
casName = fec;
TFecLog.log("clear alarm list at " + devName + "(" + casName + ")");
}
else
{
TFecLog.log("this server not monitored by a central alarm server");
}
return cc;
}
/**
* Initializer used by constructors.
*
* @param name Module name.
* @param eqpFunction The TEquipmentFunction to attach to the equipment module.
*/
private void initialize(String name, TEquipmentFunction eqpFunction)
{
gEqmFactory = TEquipmentModuleFactory.getInstance();
if (name != null)
{
moduleName = name.length() > TStrings.EQM_NAME_SHORTSIZE ? name.substring(0, TStrings.EQM_NAME_SHORTSIZE) : name;
}
else
{
moduleName = "";
}
if (eqpFunction != null)
{
this.eqpFcn = eqpFunction;
this.eqpFcn.setEquipmentModule(this);
}
registerStockProperties();
getRegisteredUsersFromFile(gRegisteredUsersList,gRegisteredGroupsList,null,null);
if (getRegisteredNetsFromFile(gRegisteredNetsList,null,null))
{
if (gRegisteredNetsList.size() == 0) gRejectAllNets = true;
}
getRegisteredAlarmDefinitionsFromFile();
gEqmFactory.setPendingEqm(this);
getExportInformationFromFile();
gEqmFactory.addEquipmentModule(this);
gEqmFactory.setPendingEqm(null);
if (gEqmFactory.isInitialized())
{ // this is being called late (after the normal system start)
if (!hasInitialized)
{ // have not yet initialized -> call startup routine myself !
startup();
}
}
hasInitialized = true;
}
private static final int PRE_DUMP_WINDOW = 300 * 1000;
private long lastHistoryCycleTime = 0;
public void setLastHistoryCycleTime(long time) { lastHistoryCycleTime = time; }
private int historyCycleInterval = 1000; // milliseconds
private boolean hstManifestDumped = false;
private static final String hstmfHdr = "INDEX, LOCAL_NAME, PROPERTY, DEVICE, DATA_LENGTH, FORMAT, HEARTBEAT, POLLING_RATE, ARCHIVE_RATE, TOLERANCE, SHORT_DEPTH, LONG_DEPTH";
private String getStrToleranceForManifest(float aTol, float pTol)
{
if (pTol > 0) return ""+pTol*100+"%";
return ""+aTol;
}
public void dumpHistoryManifest()
{
int nHistoryRecords = gLclHstList.size();
THistoryRecord hst = null;
THistorySpecification spc = null;
TInitializer initializer = TInitializerFactory.getInstance().getInitializer();
String eqm = getLocalName();
String filename = initializer.getFecHome()+File.separator+eqm;
String nl = System.getProperty("line.separator");
try
{
new File(filename).mkdirs();
filename += File.separator+"hstmf.csv";
FileWriter fw = new FileWriter(filename);
String ln = hstmfHdr + nl;
fw.write(ln);
for (int i=0; i<nHistoryRecords; i++)
{
hst = (THistoryRecord)gLclHstList.get(i);
if (hst.getEqm() != this) continue;
spc = hst.getHspec();
ln = ""+hst.getRcdIdx()+", "+eqm+", "+hst.getPrp()+", "+hst.getDev()+
", "+hst.getArraySize()+", "+ TFormat.toString(hst.getFmt())+
", "+spc.getHeartbeat()+", "+spc.getPollngRate()+", "+spc.getArchiveRate()+
", "+getStrToleranceForManifest(spc.getAbsoluteTolerance(),spc.getPercentTolerance())+
", "+spc.getDepthShort()+", "+spc.getDepthLong()+nl;
fw.write(ln);
}
fw.close();
MsgLog.log("dumpHistoryManifest", "wrote history manifest for <"+eqm+">",0,null,0);
}
catch (Exception e)
{
MsgLog.log("dumpHistoryManifest", "cannot write history manifest!",TErrorList.file_error,e,0);
};
}
public void setHistoryCycleInterval(int cycleInterval)
{
historyCycleInterval = cycleInterval;
TFecLog.log("THistoryRecord: set history cycle interval from "+historyCycleInterval+" to "+cycleInterval+" msec");
}
public int getHistoryCycleInterval() { return historyCycleInterval; }
/**
* Inserts local history data into the local history ring buffer.
*
* A server can insert data into the local history ring buffer directly
* with this call. The inserted data behave in exactly the same manner
* as if added via a call the the designated equipment module from the
* local history subsystem.
*
* The information provided in the call MUST correspond to a registered
* local history element or the call will fail. The server developer
* can ensure that history data are inserted ONLY via this call
* (and not via the local history subsystem) by trapping the CA_HIST
* big in the access flag within the equipment module dispatch and
* returning an error condition such as 'not_implemented'.
*
* @param property is the requested property for which a history record is being kept.
* @param device is the device name for which a history record is being kept.
* @param dout is aTDataType object specifying the array length, data format, and
* timestamp and other data stamps of the history record along with the
* accompanying data.
*
* @return 0 upon success.
*/
public int appendHistoryData(String property,String device,TDataType dout)
{
int size = dout.dArrayLength;
short format = dout.dFormat;
THistoryRecord hst = getLocalHistoryRecord(property, device, size, format);
if (hst == null) return TErrorList.un_allocated;
if (dout.getTimeStamp() < hst.getTimestamp()) return TErrorList.out_of_sequence;
synchronized (hst)
{ // don't concur with historyCycle
hst.writeRecordToSTS(dout);
if (needToArchiveRecord(hst))
{
hst.writeRecordToLTS(dout);
if (hst.isPointOfInterest()) hst.writeRecordToPIF(dout);
}
}
return 0;
}
protected void historyCycle(boolean isScheduled)
{
if (!hasInitialized) return;
long thisCycleTime = System.currentTimeMillis();
THistoryRecord hst = null;
THistorySpecification spc = null;
TDataType dout = null;
TDataType din = new TDataType();
TAccess access = new TAccess(TAccess.CA_HIST + TAccess.CA_READ);
int cc = 0;
boolean skip;
if (!isScheduled && thisCycleTime-lastHistoryCycleTime < historyCycleInterval) return;
lastHistoryCycleTime = thisCycleTime;
int nHistoryRecords = gLclHstList.size();
if (nHistoryRecords == 0) return;
TEquipmentModuleFactory f = getEquipmentModuleFactory();
f.setCurrentContractEntry(f.hstcon);
for (int i=0; i<nHistoryRecords; i++)
{
hst = (THistoryRecord)gLclHstList.get(i);
spc = hst.getHspec();
if (spc.getDepthShort() <= 0) continue;
if (hst.needsToFillSTS) hst.fillSTS();
hst.setArchiveFileName(thisCycleTime); // will also remove outdated files if necessary
skip = (thisCycleTime-hst.getTimestamp()) < spc.getPollngRate();
if (hst.isScheduled()) skip = false;
hst.setScheduled(false);
if (skip) continue;
dout = new TDataType(hst.getArraySize(),hst.getFmt());
dout.setDataTimeStamp(TDataTime.getDataTimeStamp());
dout.setSystemDataStamp(TEquipmentModuleFactory.getSystemStamp());
cc = callProperty(hst.getPrp(),hst.getDev(),dout,din,access);
if (cc != 0) continue;
synchronized (hst)
{ // don't concur with appendHistoryData
hst.writeRecordToSTS(dout);
if (needToArchiveRecord(hst))
{
hst.writeRecordToLTS(dout);
if (hst.isPointOfInterest()) hst.writeRecordToPIF(dout);
}
}
}
if (!hstManifestDumped &&
lastHistoryCycleTime > getEquipmentModuleFactory().getServerStartTime() + PRE_DUMP_WINDOW)
{
dumpHistoryManifest();
hstManifestDumped = true;
}
return;
}
private boolean needToArchiveRecord(THistoryRecord hst)
{
long ts = System.currentTimeMillis();
THistorySpecification spc;
if (hst == null) return false;
if (!hst.isPastFilter()) return false;
if((spc=hst.getHspec()) == null) return false;
if (spc.getArchiveRate() < 0 ||
spc.getHeartbeat() < 0 ||
spc.getDepthLong() <= 0) return false;/* no long term storage */
if (hst.getRngBufferSize() <= 0) return false;
if (hst.getTimestamp() <= hst.getLastArchiveTime()) return false;/* data timestamp hasn't changed */
if (!hst.isScheduled() &&
ts < hst.getLastArchiveTime() + spc.getArchiveRate()) return false;
if (ts >= hst.getLastArchiveTime() + spc.getHeartbeat()*1000) return true; /* archive no matter what */
if (hst.isWithinTolerance()) return false;
return true;
}
private long lastAlarmCycleTime = 0;
private long alarmCycleInterval = 500;
protected void checkAlarmsInWatchTable()
{
long thisCycleTime = System.currentTimeMillis();
if (thisCycleTime-lastAlarmCycleTime < alarmCycleInterval) return;
lastAlarmCycleTime = thisCycleTime;
TDataType dout = null;
TDataType din = new TDataType();
TAccess access = new TAccess(TAccess.CA_ALARM + TAccess.CA_READ);
TAlarmWatchEntry awe = null;
TAlarmDefinition adef = null;
TAlarm alm = null;
TDevice dev = null;
int cc = 0, cnt = 0, siz = 0, sev = 0, devNr, code = 0, asys = 0;
String tag = null;
float fvals[] = null;
int ivals[] = null;
byte[] abytes = null;
synchronized (gAlarmWatchList)
{
TEquipmentModuleFactory f = getEquipmentModuleFactory();
f.setCurrentContractEntry(f.awtcon);
int awlength = gAlarmWatchList.size();
for (int i=0; i<awlength; i++)
{
awe = (TAlarmWatchEntry)gAlarmWatchList.get(i);
int chk = awe.checkNormal();
if (chk != 0)
{
ivals = new int[awe.getSiz()];
dout = new TDataType(ivals);
cc = callProperty(awe.getPrp(),awe.getDev(),dout,din,access);
}
else
{
fvals = new float[awe.getSiz()];
dout = new TDataType(fvals);
cc = callProperty(awe.getPrp(),awe.getDev(),dout,din,access);
}
if (cc != 0) continue;
boolean hasAlarm = false;
devNr = deviceList.getDeviceNumber(awe.getDev());
cnt = 0; siz = awe.getSiz();
for (int j=0; j<siz; j++)
{
if (awe.getAtyp() == TArrayType.AT_CHANNEL) devNr = j;
if (awe.getAtyp() != TArrayType.AT_WAVEFORM && siz == deviceList.getNumberOfDevices())
devNr = j; /* assume array of devices */
dev = deviceList.getDevice(devNr);
hasAlarm = false;
if (ivals != null)
{
int nval = awe.getNormal();
if ((chk == 1 && nval != (awe.getMask() & ivals[j])) ||
(chk == -1 && nval == (awe.getMask() & ivals[j])) )
{
if (TEquipmentModuleFactory.debugLevel > 1)
DbgLog.log("checkAlarmsInWatchTable", awe.getPrp()+" "+awe.getDev()+
" alarm state ! : "+(awe.getMask() & ivals[j])+" vs "+nval);
code = awe.getCode();
if (code == 0) code = TErrorList.invalid_data;
sev = awe.getSev();
asys = awe.getAsys();
hasAlarm = true;
}
abytes = Swap.LongToBytes(ivals[j]);
}
else if (fvals != null)
{
if (fvals[j] > awe.getHi())
{
if (TEquipmentModuleFactory.debugLevel > 1)
DbgLog.log("checkAlarmsInWatchTable", awe.getPrp()+" "+awe.getDev()+
" alarm state ! : "+fvals[j]+" > "+awe.getHi());
code = awe.getCode();
if (code == 0) code = awe.getCodeHigh();
if (code == 0) code = TErrorList.value_too_high;
sev = awe.getSev();
asys = awe.getAsys();
tag = awe.getTagHigh();
hasAlarm = true;
}
else if (fvals[j] > awe.getHiwarn())
{
if (TEquipmentModuleFactory.debugLevel > 1)
DbgLog.log("checkAlarmsInWatchTable", awe.getPrp()+" "+awe.getDev()+
" warn state ! : "+fvals[j]+" > "+awe.getHiwarn());
code = awe.getCode();
if (code == 0) code = awe.getCodeHigh();
if (code == 0) code = TErrorList.warn_too_high;
sev = awe.getSev()-2;
asys = awe.getAsys();
tag = awe.getTagHigh();
hasAlarm = true;
}
else if (fvals[j] < awe.getLo())
{
if (TEquipmentModuleFactory.debugLevel > 1)
DbgLog.log("checkAlarmsInWatchTable", awe.getPrp()+" "+awe.getDev()+
" alarm state ! : "+fvals[j]+" < "+awe.getLo());
code = awe.getCode();
if (code == 0) code = awe.getCodeLow();
if (code == 0) code = TErrorList.value_too_low;
sev = awe.getSev();
asys = awe.getAsys();
tag = awe.getTagLow();
hasAlarm = true;
}
else if (fvals[j] < awe.getLowarn())
{
if (TEquipmentModuleFactory.debugLevel > 1)
DbgLog.log("checkAlarmsInWatchTable", awe.getPrp()+" "+awe.getDev()+
" warn state ! : "+fvals[j]+" < "+awe.getLowarn());
code = awe.getCode();
if (code == 0) code = awe.getCodeLow();
if (code == 0) code = TErrorList.warn_too_low;
sev = awe.getSev()-2;
asys = awe.getAsys();
tag = awe.getTagLow();
hasAlarm = true;
}
abytes = Swap.Float(fvals[j]);
}
if (!hasAlarm)
{ // run through clearAlarm()
dev.clearAlarm(TErrorList.invalid_data,awe);
dev.clearAlarm(TErrorList.value_too_high,awe);
dev.clearAlarm(TErrorList.value_too_low,awe);
dev.clearAlarm(TErrorList.warn_too_high,awe);
dev.clearAlarm(TErrorList.warn_too_low,awe);
if (awe.getCode() > 0) dev.clearAlarm(awe.getCode(),awe);
if (awe.getCodeHigh() > 0) dev.clearAlarm(awe.getCodeHigh(),awe);
if (awe.getCodeLow() > 0) dev.clearAlarm(awe.getCodeLow(),awe);
continue;
}
if (code == 0) continue;
if (!awe.isPastFilter()) continue;
cnt = awe.getCnt() + 1;
awe.setCnt(cnt);
if (cnt > awe.getCntThreshold() && dev != null)
{
alm = dev.setAlarm(code,abytes,awe);
if (alm != null)
{
adef = alm.getAlmDef();
if (sev != 0) adef.setAlarmSeverity(sev);
if (asys != 0) adef.setAlarmSystem(asys);
if (tag != null && tag.length() > 0) adef.setAlarmTag(tag);
}
}
}
/* only clear the watch table counter when a complete pass has no alarms */
if (cnt == 0) awe.setCnt(0);
}
}
}
private void updateAlarmDynSet()
{
long ts = System.currentTimeMillis();
int tss = (int)(ts/1000);
int tsu = (int)(ts%1000)*1000;
if (deviceList.getNumberOfAlarms() <= TAlarm.getAlmCollapseWindow())
{ // no need to collapse
if (almDynSet.starttime == 0) return;
if ((almDynSet.descriptor & TAlarmDescriptor.TERMINATE) == TAlarmDescriptor.TERMINATE)
return;
almDynSet.descriptor = TAlarmDescriptor.TERMINATE;
almDynSet.timestamp = tss;
almDynSet.timestampUSec = tsu;
return;
}
if (almDynSet.descriptor == 0 ||
(almDynSet.descriptor & TAlarmDescriptor.TERMINATE) == TAlarmDescriptor.TERMINATE)
{ // either never set or last set to terminated -> this is now NEW !
almDynSet.descriptor = TAlarmDescriptor.NEW;
almDynSet.timestamp = tss;
almDynSet.timestampUSec = tsu;
almDynSet.starttime = almDynSet.timestamp;
almDynSet.starttimeUSec = almDynSet.timestampUSec;
return;
}
if (almDynSet.timestamp + TAlarm.getAlmHeartbeatWindow() < tss)
{ // set the heartbeat
almDynSet.descriptor = TAlarmDescriptor.HEARTBEAT;
almDynSet.timestamp = tss;
almDynSet.timestampUSec = tsu;
return;
}
}
protected void update()
{
if (isIdle) return;
accessLock.checkAccessLocks();
checkAlarmsInWatchTable();
deviceList.refreshAlarms();
updateAlarmDynSet();
historyCycle(false);
}
/**
* Registers the equipment module's stock properties
*/
private int prpQueryCall(String devName, TDataType dout, TDataType din, TAccess devAccess)
{ // use in calls for "PROPS" or "PROPERTIES"
int cc = 0;
TDevice dev = getDeviceList().getDevice(devName);
LinkedList<String> lst = null;
boolean checkWildCard = (devName.compareTo("*") != 0 && devName.indexOf("*") != -1);
if (dev != null && (lst=dev.getPropertyList()) != null)
{
String[] slst = new String[lst.size()];
lst.toArray(slst);
if (checkWildCard) slst = StringToName.matchStringsInArray(slst,devName);
if (dout.getFormat() == TFormat.CF_USTRING)
{
USTRING[] ustr = new USTRING[slst.length];
char[] cha;
StringBuffer sb = new StringBuffer(80);
TExportProperty prp;
for (int i = 0; i<slst.length; i++)
{
ustr[i] = new USTRING();
if ((prp = propertyList.getFirstProperty(slst[i])) == null) continue;
cha = prp.getName().toCharArray();
sb.insert(0,cha);
for (int c=cha.length; c<32; c++) sb.insert(c,(char)0);
cha = prp.getDescription().getText().toCharArray();
sb.insert(32,cha);
ustr[i].setValues(prp.getOutputSize(),0,0,prp.getOutputFormat(),new String(sb));
}
cc = dout.putData(ustr);
}
else
{
cc = dout.putData(StringToName.stringArrayToName64(slst));
}
if (dout.getArrayLength() > slst.length) dout.setArrayLength(slst.length);
}
else
{
String[] slst = new String[propertyList.countUniqueProperties()];
propertyList.getPropertyNames().toArray(slst);
if (checkWildCard) slst = StringToName.matchStringsInArray(slst,devName);
if (dout.getFormat() == TFormat.CF_USTRING)
{
USTRING[] ustr = new USTRING[slst.length];
char[] cha;
StringBuffer sb = new StringBuffer(80);
TExportProperty prp;
for (int i = 0; i<slst.length; i++)
{
ustr[i] = new USTRING();
if ((prp = propertyList.getFirstProperty(slst[i])) == null) continue;
cha = prp.getName().toCharArray();
sb.insert(0,cha);
for (int c=cha.length; c<32; c++) sb.insert(c,(char)0);
cha = prp.getDescription().getText().toCharArray();
sb.insert(32,cha);
ustr[i].setValues(prp.getOutputSize(),0,0,prp.getOutputFormat(),new String(sb));
}
cc = dout.putData(ustr);
}
else
{
cc = dout.putData(StringToName.stringArrayToName64(slst));
}
if (dout.getArrayLength() > slst.length) dout.setArrayLength(slst.length);
}
if (cc == 0)
{
if (propertyList.isDeviceOriented())
cc = TErrorList.has_query_function | TErrorList.CE_SENDDATA;
}
return cc;
}
private int getMetaPrpsCallFilter(TDataType din)
{
int filter = 0x7fffffff;
if (din != null && TFormat.isSimpleString(din.dFormat))
{
String tgt = din.toString();
if (tgt.startsWith("."))
{
filter = 0;
String[] fltrs = tgt.split(",");
for (String s : fltrs)
{
if (s.compareToIgnoreCase(".DESC") == 0 || s.compareToIgnoreCase(".DSC") == 0)
filter |= TMetaProperties.DSC_FLTR;
if (s.compareToIgnoreCase(".HIST") == 0 || s.compareToIgnoreCase(".HST") == 0)
filter |= TMetaProperties.HST_FLTR;
if (s.compareToIgnoreCase(".EGU") == 0) filter |= TMetaProperties.EGU_FLTR;
if (s.compareToIgnoreCase(".XEGU") == 0) filter |= TMetaProperties.XEGU_FLTR;
if (s.compareToIgnoreCase(".MAX") == 0) filter |= TMetaProperties.MAX_FLTR;
if (s.compareToIgnoreCase(".XMAX") == 0) filter |= TMetaProperties.XMAX_FLTR;
if (s.compareToIgnoreCase(".ONLINE") == 0) filter |= TMetaProperties.ONL_FLTR;
}
}
}
if (filter == 0) filter = 0x7fffffff;
return filter;
}
private int metaprpQueryCall(String devName, TDataType dout, TDataType din, TAccess devAccess)
{ // use in calls for "METAPROPERTIES"
int cc = 0, filter = getMetaPrpsCallFilter(din);
TDevice dev = getDeviceList().getDevice(devName);
LinkedList<String> lst = null;
if (dev != null && (lst=dev.getPropertyList()) != null)
{
String[] slst = new String[lst.size()];
lst.toArray(slst);
LinkedList<TExportProperty> plst = new LinkedList<TExportProperty>();
LinkedList<TExportProperty> thesePrps;
for (int i = 0; i<slst.length; i++)
{
thesePrps = propertyList.getFilledMetaProperties(slst[i],filter);
if (thesePrps.size() > 0) plst.addAll(thesePrps);
}
int size = plst.size();
if (dout.getFormat() == TFormat.CF_USTRING)
{
USTRING[] ustr = new USTRING[size];
char[] cha;
StringBuffer sb = new StringBuffer(80);
TExportProperty prp;
for (int i = 0; i<size; i++)
{
ustr[i] = new USTRING();
if ((prp = plst.get(i)) == null) continue;
cha = prp.getName().toCharArray();
sb.insert(0,cha);
for (int c=cha.length; c<32; c++) sb.insert(c,(char)0);
cha = prp.getDescription().getText().toCharArray();
sb.insert(32,cha);
ustr[i].setValues(prp.getOutputSize(),0,0,prp.getOutputFormat(),new String(sb));
}
cc = dout.putData(ustr);
}
else
{
slst = new String[size];
for (int i=0; i<size; i++) slst[i] = plst.get(i).getName();
cc = dout.putData(StringToName.stringArrayToName64(slst));
}
if (dout.getArrayLength() > slst.length) dout.setArrayLength(slst.length);
}
else
{
String[] slst = new String[propertyList.countUniqueProperties()];
propertyList.getPropertyNames().toArray(slst);
LinkedList<TExportProperty> plst = new LinkedList<TExportProperty>();
LinkedList<TExportProperty> thesePrps;
for (int i = 0; i<slst.length; i++)
{
thesePrps = propertyList.getFilledMetaProperties(slst[i],filter);
if (thesePrps.size() > 0) plst.addAll(thesePrps);
}
int size = plst.size();
if (dout.getFormat() == TFormat.CF_USTRING)
{
USTRING[] ustr = new USTRING[size];
char[] cha;
StringBuffer sb = new StringBuffer(80);
TExportProperty prp;
for (int i = 0; i<size; i++)
{
ustr[i] = new USTRING();
if ((prp = plst.get(i)) == null) continue;
cha = prp.getName().toCharArray();
sb.insert(0,cha);
for (int c=cha.length; c<32; c++) sb.insert(c,(char)0);
cha = prp.getDescription().getText().toCharArray();
sb.insert(32,cha);
ustr[i].setValues(prp.getOutputSize(),0,0,prp.getOutputFormat(),new String(sb));
}
cc = dout.putData(ustr);
}
else
{
slst = new String[size];
for (int i=0; i<size; i++) slst[i] = plst.get(i).getName();
cc = dout.putData(StringToName.stringArrayToName64(slst));
}
if (dout.getArrayLength() > slst.length) dout.setArrayLength(slst.length);
}
if (cc == 0)
{
if (propertyList.isDeviceOriented())
cc = TErrorList.has_query_function | TErrorList.CE_SENDDATA;
}
return cc;
}
private int hstCall(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
String tgt = null;
if (din != null)
{ // input given ...
switch (din.getFormat())
{
case TFormat.CF_TEXT:
case TFormat.CF_NAME16:
case TFormat.CF_NAME32:
case TFormat.CF_NAME64:
char[] tgtc = new char[64];
din.getData(tgtc);
tgt = new String(tgtc).trim();
break;
}
}
THistoryRecord[] hsts = (THistoryRecord[])gLclHstList.toArray(new THistoryRecord[0]);
NAME64[] nams = null;
THistoryRecordStruct[] hrs = null;
if (dout.getFormat() == TFormat.CF_STRUCT)
{
hrs = new THistoryRecordStruct[hsts.length];
}
else
{
nams = new NAME64[hsts.length];
}
int n = 0;
String p;
for (int i=0; i<hsts.length; i++)
{
p = hsts[i].getPrp();
if (tgt != null && p.compareToIgnoreCase(tgt) != 0) continue;
if (hrs != null)
{
hrs[n++] = new THistoryRecordStruct(hsts[i].getDev(),hsts[i].getPrp(),hsts[i].getArraySize(),hsts[i].getFmt(),hsts[i].getHspec());
}
else
{
nams[n++] = new NAME64(p);
}
}
return hrs != null ? dout.putData(hrs,n,0) : dout.putData(nams,n,0);
}
private boolean stockPropertiesRegistered = false;
void registerStockProperties()
{
if (stockPropertiesRegistered) return;
final TEquipmentModule thisEqm = this;
if (gEqmFactory == null) gEqmFactory = TEquipmentModuleFactory.getInstance();
stockList = new TPropertyList();
// TODO Separate handlers for overloaded properties
stockList.addProperty(TStockProperties.SRVCOMMANDS, new TPropertyHandler()
{
protected int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
return getTEqmFactory().callWrAccessTableInfo(moduleName,devName, dout, din, devAccess);
}
});
TPropertyHandler propertiesStructHandler = new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
if (dout != null)
{
switch (dout.dFormat)
{ // TODO: tidy this copy-and-past job up !
case TFormat.CF_STRUCT:
if (dout.getTag().compareTo("PRPQSr4") == 0 || (dout.getArrayLength() % TPropertyQuery.sizeInBytes) == 0)
{
if (din != null)
{ // looking for a specific property ...
LinkedList<TExportProperty> propInstances;
String propertyName = din.toString();
propertyName = propertyName.replace('\n', (char) 0).trim();
propInstances = propertyList.getEqualProperties(propertyName);
if ((propInstances == null) || (propInstances.size() == 0))
return TErrorList.not_exported;
// fill in the targeted property info
THistoryRecord lhr = null;
TPropertyQuery[] prpq = new TPropertyQuery[propInstances.size()];
byte[] tba = new byte[prpq.length * TPropertyQuery.sizeInBytes];
Iterator<TExportProperty> it = propInstances.iterator();
for (int i = 0; (it.hasNext()) && (i < prpq.length); i++)
{
prpq[i] = new TPropertyQuery((TExportProperty) it.next(), propInstances.size() - 1);
if ((lhr=getLocalHistoryRecord(prpq[i].prpName,"#0")) != null)
{
prpq[i].prpHistoryDepthLong = (short)lhr.getHspec().getDepthLong();
prpq[i].prpHistoryDepthShort = (short)lhr.getHspec().getDepthShort();
}
System.arraycopy(prpq[i].toByteArray(), 0, tba, i * TPropertyQuery.sizeInBytes,
TPropertyQuery.sizeInBytes);
}
return dout.putData(tba, "PRPQSr4");
}
else
{ // want the whole list ...
String[] slst = new String[propertyList.countUniqueProperties()];
propertyList.getPropertyNames().toArray(slst);
TPropertyQuery[] prpq = new TPropertyQuery[slst.length];
if (slst.length == 0) break;
byte[] tba = new byte[slst.length * TPropertyQuery.sizeInBytes];
TExportProperty prp;
for (int i=0; i<slst.length; i++)
{
prp = propertyList.getFirstProperty(slst[i]);
prpq[i] = new TPropertyQuery(prp,1);
System.arraycopy(prpq[i].toByteArray(), 0, tba, i * TPropertyQuery.sizeInBytes,
TPropertyQuery.sizeInBytes);
}
return dout.putData(tba, "PRPQSr4");
}
}
else if (dout.getTag().compareTo("XPQS") == 0 || (dout.getArrayLength() % XPropertyQuery.sizeInBytes) == 0)
{
if (din != null)
{ // looking for a specific property ...
LinkedList<TExportProperty> propInstances;
String propertyName = din.toString();
propertyName = propertyName.replace('\n', (char) 0).trim();
propInstances = propertyList.getEqualProperties(propertyName);
if ((propInstances == null) || (propInstances.size() == 0))
return TErrorList.not_exported;
// fill in the targeted property info
THistoryRecord lhr = null;
XPropertyQuery[] xpq = new XPropertyQuery[propInstances.size()];
byte[] tba = new byte[xpq.length * XPropertyQuery.sizeInBytes];
Iterator<TExportProperty> it = propInstances.iterator();
for (int i = 0; (it.hasNext()) && (i < xpq.length); i++)
{
xpq[i] = new XPropertyQuery((TExportProperty) it.next(), propInstances.size() - 1);
if ((lhr=getLocalHistoryRecord(xpq[i].prpName,"#0")) != null)
{
xpq[i].prpHistoryDepthLong = (short)lhr.getHspec().getDepthLong();
xpq[i].prpHistoryDepthShort = (short)lhr.getHspec().getDepthShort();
}
System.arraycopy(xpq[i].toByteArray(), 0, tba, i * XPropertyQuery.sizeInBytes,
XPropertyQuery.sizeInBytes);
}
return dout.putData(tba, "XPQS");
}
else
{ // want the whole list ...
String[] slst = new String[propertyList.countUniqueProperties()];
propertyList.getPropertyNames().toArray(slst);
XPropertyQuery[] xpq = new XPropertyQuery[slst.length];
if (slst.length == 0) break;
byte[] tba = new byte[slst.length * XPropertyQuery.sizeInBytes];
TExportProperty prp;
for (int i=0; i<slst.length; i++)
{
prp = propertyList.getFirstProperty(slst[i]);
xpq[i] = new XPropertyQuery(prp,1);
System.arraycopy(xpq[i].toByteArray(), 0, tba, i * XPropertyQuery.sizeInBytes,
XPropertyQuery.sizeInBytes);
}
return dout.putData(tba, "XPQS");
}
}
else if (dout.getTag().compareTo("PQS") == 0 || (dout.getArrayLength() % PropertyQuery.sizeInBytes) == 0)
{ // legacy request ...
if (din != null)
{ // looking for a specific property ...
LinkedList<TExportProperty> propInstances;
String propertyName = din.toString();
propertyName = propertyName.replace('\n', (char) 0).trim();
propInstances = propertyList.getEqualProperties(propertyName);
if ((propInstances == null) || (propInstances.size() == 0))
return TErrorList.not_exported;
// fill in the targeted property info
PropertyQuery[] pqs = new PropertyQuery[1];
TExportProperty prp = propertyList.getFirstProperty(propertyName);
byte[] tba = new byte[PropertyQuery.sizeInBytes];
pqs[0] = new PropertyQuery();
pqs[0].name = propertyName;
pqs[0].prpDesc = prp.getDescription().getText();
pqs[0].prpAccess = (byte)prp.getAccessMode();
pqs[0].prpFormat = (byte)(prp.getOutputFormat()%512);
pqs[0].prpSize = (short)prp.getOutputSize();
System.arraycopy(pqs[0].toByteArray(), 0, tba, 0, PropertyQuery.sizeInBytes);
return dout.putData(tba, "PQS");
}
else
{ // want the whole list ...
String[] slst = new String[propertyList.countUniqueProperties()];
propertyList.getPropertyNames().toArray(slst);
if (slst.length == 0) break;
PropertyQuery[] pqs = new PropertyQuery[slst.length];
byte[] tba = new byte[slst.length * PropertyQuery.sizeInBytes];
TExportProperty prp;
for (int i=0; i<slst.length; i++)
{
pqs[i] = new PropertyQuery();
pqs[i].name = slst[i];
prp = propertyList.getFirstProperty(slst[i]);
pqs[i].prpDesc = prp.getDescription().getText();
pqs[i].prpAccess = (byte)prp.getAccessMode();
pqs[i].prpFormat = (byte)(prp.getOutputFormat()%512);
pqs[i].prpSize = (short)prp.getOutputSize();
System.arraycopy(pqs[i].toByteArray(), 0, tba, i * PropertyQuery.sizeInBytes,
PropertyQuery.sizeInBytes);
}
return dout.putData(tba, "PQS");
}
}
}
}
/**/
return TErrorList.illegal_format;
}
};
TPropertyHandler metapropertiesStructHandler = new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
if (dout != null)
{
int filter = getMetaPrpsCallFilter(din);
switch (dout.dFormat)
{ // TODO: tidy this copy-and-past job up !
case TFormat.CF_STRUCT:
LinkedList<TExportProperty> propInstances;
if (dout.getTag().compareTo("PRPQSr4") == 0 || (dout.getArrayLength() % TPropertyQuery.sizeInBytes) == 0)
{
if (din != null && filter != 0x7fffffff)
{ // looking for a specific property ...
String propertyName = din.toString();
propertyName = propertyName.replace('\n', (char) 0).trim();
propInstances = propertyList.getFilledMetaProperties(propertyName,filter);
if ((propInstances == null) || (propInstances.size() == 0))
return TErrorList.not_exported;
// fill in the targeted property info
TPropertyQuery[] prpq = new TPropertyQuery[propInstances.size()];
byte[] tba = new byte[prpq.length * TPropertyQuery.sizeInBytes];
Iterator<TExportProperty> it = propInstances.iterator();
for (int i = 0; (it.hasNext()) && (i < prpq.length); i++)
{
prpq[i] = new TPropertyQuery((TExportProperty) it.next(), propInstances.size() - 1);
System.arraycopy(prpq[i].toByteArray(), 0, tba, i * TPropertyQuery.sizeInBytes,
TPropertyQuery.sizeInBytes);
}
return dout.putData(tba, "PRPQSr4");
}
else
{ // want the whole list ...
String[] slst = new String[propertyList.countUniqueProperties()];
propertyList.getPropertyNames().toArray(slst);
if (slst.length == 0) break;
propInstances = new LinkedList<TExportProperty>();
LinkedList<TExportProperty> theseInstances;
for (int i=0; i<slst.length; i++)
{
theseInstances = propertyList.getFilledMetaProperties(slst[i],filter);
if (theseInstances.size() > 0) propInstances.addAll(theseInstances);
}
int size = propInstances.size();
TExportProperty prp;
TPropertyQuery[] prpq = new TPropertyQuery[size];
byte[] tba = new byte[size * TPropertyQuery.sizeInBytes];
for (int i=0; i<size; i++)
{
prp = propInstances.get(i);
prpq[i] = new TPropertyQuery(prp,1);
System.arraycopy(prpq[i].toByteArray(), 0, tba, i * TPropertyQuery.sizeInBytes,
TPropertyQuery.sizeInBytes);
}
return dout.putData(tba, "PRPQSr4");
}
}
else if (dout.getTag().compareTo("PQS") == 0 || (dout.getArrayLength() % PropertyQuery.sizeInBytes) == 0)
{ // legacy request ...
if (din != null && filter != 0x7fffffff)
{ // looking for a specific property ...
String propertyName = din.toString();
propertyName = propertyName.replace('\n', (char) 0).trim();
propInstances = propertyList.getFilledMetaProperties(propertyName,filter);
if ((propInstances == null) || (propInstances.size() == 0))
return TErrorList.not_exported;
// fill in the targeted property info
PropertyQuery[] pqs = new PropertyQuery[1];
TExportProperty prp = propertyList.getFirstProperty(propertyName);
byte[] tba = new byte[PropertyQuery.sizeInBytes];
pqs[0] = new PropertyQuery();
pqs[0].name = propertyName;
pqs[0].prpDesc = prp.getDescription().getText();
pqs[0].prpAccess = (byte)prp.getAccessMode();
pqs[0].prpFormat = (byte)(prp.getOutputFormat()%512);
pqs[0].prpSize = (short)prp.getOutputSize();
System.arraycopy(pqs[0].toByteArray(), 0, tba, 0, PropertyQuery.sizeInBytes);
return dout.putData(tba, "PQS");
}
else
{ // want the whole list ...
String[] slst = new String[propertyList.countUniqueProperties()];
propertyList.getPropertyNames().toArray(slst);
if (slst.length == 0) break;
propInstances = new LinkedList<TExportProperty>();
LinkedList<TExportProperty> theseInstances;
for (int i=0; i<slst.length; i++)
{
theseInstances = propertyList.getFilledMetaProperties(slst[i],filter);
if (theseInstances.size() > 0) propInstances.addAll(theseInstances);
}
int size = propInstances.size();
PropertyQuery[] pqs = new PropertyQuery[size];
byte[] tba = new byte[size * PropertyQuery.sizeInBytes];
TExportProperty prp;
for (int i=0; i<size; i++)
{
prp = propInstances.get(i);
pqs[i] = new PropertyQuery();
pqs[i].name = prp.getName();
pqs[i].prpDesc = prp.getDescription().getText();
pqs[i].prpAccess = (byte)prp.getAccessMode();
pqs[i].prpFormat = (byte)(prp.getOutputFormat()%512);
pqs[i].prpSize = (short)prp.getOutputSize();
System.arraycopy(pqs[i].toByteArray(), 0, tba, i * PropertyQuery.sizeInBytes,
PropertyQuery.sizeInBytes);
}
return dout.putData(tba, "PQS");
}
}
}
}
/**/
return TErrorList.illegal_format;
}
};
TPropertyHandler alarmsStructHandler = new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
if (dout == null) return TErrorList.dimension_error;
if (dout.dFormat != TFormat.CF_STRUCT) return TErrorList.illegal_format;
int[] amrb = new int[4];
if (din != null)
{
switch (din.dFormat)
{
case TFormat.CF_STRUCT:
if (din.dArrayLength != 16) return TErrorList.illegal_format;
byte[] bdata = din.getDataBuffer();
byte[] ival = new byte[4];
for (int i=0; i<3; i++)
{
System.arraycopy(bdata,i*4,ival,0,4);
amrb[i] = Swap.Long(ival);
}
break;
case TFormat.CF_LONG:
din.getData(amrb);
break;
default:
return TErrorList.illegal_format;
}
}
else
{
amrb[0] = 0; // start time
amrb[1] = (int)(System.currentTimeMillis()/1000); // stop time
amrb[2] = 0; // minimum severity
amrb[3] = 0; // as yet unused ...
}
boolean collapse = false;
int dstart, dstop;
int astart = amrb[0];
int astop = amrb[1];
int asev = amrb[2];
if (devName == null || devName.length() == 0 || devName.startsWith("#") || devName.contains("*"))
{ // currently any of these is a signal that the caller want's ALL alarms
int nalms = deviceList.getNumberOfAlarms();
if (nalms > TAlarm.getAlmCollapseWindow()) collapse = true;
dstart = 0; dstop = deviceList.getNumberOfDevices();
}
else
{
dstart = deviceList.getDeviceNumber(devName);
dstop = dstart + 1;
}
TAlarm[] alms = null;
TAlarmMessage[] ams = null;
int buflength = 0;
//byte[] tba = null;
int code = TErrorList.max_alarms_exceeded, na = 0;
if (collapse)
{ // collapse to a single message
na = buflength = 1;
ams = new TAlarmMessage[buflength];
String atag = "more than "+TAlarm.getAlmCollapseWindow()+" total alarms";
short[] tna = new short[32];
int itna = 1;
tna[0] = (short)deviceList.getNumberOfAlarms();
TDevice[] tdevs = deviceList.getDeviceList();
TAlarm[] as;
int n = 0;
for (TDevice td : tdevs)
{ // scan thru the device list
if ((as=td.getAlarmList()) == null ||
as.length == 0 || as[0] == null) continue;
for (int i=0; i<as.length; i++)
if (isCasInClientList()) as[i].allowRemoval();
if (code == TErrorList.max_alarms_exceeded) code = as[0].getCode();
if (itna < 32 && code != tna[itna]) tna[itna] = (short)code;
if (code != as[0].getCode()) break;
n++;
}
if (n > TAlarm.getAlmCollapseWindow())
{ // at least this many with the same code
code = TAlarm.isDiskSpaceAlarm(code) ? (code & 0xff) : TAlarm.getBaseCode(code);
TAlarmDefinition ad = getAlarmDefinition(code);
atag = ""+n+" alarms: "+ ad != null ? ad.getAlarmTag() : "<no defined alarm tag>";
}
TDataType dt = new TDataType(tna);
ams[0] = new TAlarmMessage(thisEqm.getExportName(),thisEqm.getExportName(),atag,code,
deviceList.getHighestAlarmSeverity(null,0),almDynSet,dt);
//tba = new byte[buflength * TAlarmMessage.sizeInBytes];
}
else
{
int ts = 0;
buflength = deviceList.getNumberOfAlarms();
ams = new TAlarmMessage[buflength];
//tba = new byte[buflength * TAlarmMessage.sizeInBytes];
TDevice[] dlst = deviceList.getDeviceList();
String dnam = null, atag = null;
for (int i=dstart; i<dstop; i++)
{
alms = dlst[i].getAlarmList();
if ((alms == null) || (alms.length == 0)) continue;
for (int n=0; n<alms.length && na<buflength; n++)
{
if ((ts=alms[n].getTimeStamp()) < astart || ts > astop) continue;
if (alms[n].getSeverity() < asev) continue;
dnam = dlst[i].getName();
code = alms[n].getCode();
atag = null;
if (TAlarm.isLinkErrorAlarm(code))
{
dnam = thisEqm.getExportName();
int lid = TAlarm.decodeLinkErrorAlarm(code);
TLink lnk = TLinkFactory.getInstance().getLinkFromTable(lid);
if (lnk != null) atag = "link error: "+lnk.getDeviceServer();
}
// TODO: if (TAlarm.isDiskSpaceAlarm(code)) dnam = getDiskName();
ams[na] = new TAlarmMessage(thisEqm,dnam,atag,alms[n]);
if (TAlarm.isHiddenAlarm(alms[n].getCode()))
{ // flagged as hidden
ams[na].setAlarmSystem(TAlarm.hideAlarmSystem(ams[na].getAlarmSystem()));
}
//System.arraycopy(ams[na].toByteArray(), 0, tba, (na)*TAlarmMessage.sizeInBytes, TAlarmMessage.sizeInBytes);
// CAS is configured and has now read the alarm => can remove it !
if (casReadRequired && isCasInClientList()) alms[n].allowRemoval();
na++;
}
}
}
byte[] tba = new byte[buflength * TAlarmMessage.sizeInBytes];
if (dout.getTag().compareTo("AMSr4") == 0)
{ // modern
for (int i=0; i<buflength && i<na; i++)
{
System.arraycopy(ams[i].toByteArray(), 0, tba, i*TAlarmMessage.sizeInBytes, TAlarmMessage.sizeInBytes);
}
if (na < dout.getArrayLength()) dout.setArrayLength(na);
return dout.putData(tba, "AMSr4");
}
else
{ // is legacy support necessary ?
}
return TErrorList.invalid_structure_tag;
}
};
TPropertyHandler alarmDefsStructHandler = new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
TAlarmDefinition[] adef = (TAlarmDefinition[])alarmDefinitionList.values().toArray(new TAlarmDefinition[0]);
int almdefsize = alarmDefinitionList.size();
if (devAccess.isWrite())
{
if (din == null) return TErrorList.dimension_error;
if (din.dFormat != TFormat.CF_STRUCT) return TErrorList.illegal_format;
if (din.getTag().compareTo("ADSr4") != 0) return TErrorList.invalid_structure_tag;
TAlarmDefinition[] inpt = new TAlarmDefinition[1];
inpt[0] = new TAlarmDefinition();
din.getData(inpt);
boolean found = false;
for (int i=0; i<almdefsize; i++)
{
if (adef[i].getAlarmCode() == inpt[0].getAlarmCode())
{ // got it
adef[i].setFields(inpt[0]);
found = true;
break;
}
}
if (!found) return TErrorList.un_allocated;
if (dout == null || dout.getArrayLength() == 0) return 0;
}
if (dout == null) return TErrorList.dimension_error;
if (dout.dFormat != TFormat.CF_STRUCT) return TErrorList.illegal_format;
int adssize = TStructRegistry.getSizeInBytes("ADSr4");
byte[] tba = new byte[almdefsize * adssize];
if (dout.getTag().compareTo("ADSr4") == 0)
{ // modern
for (int i=0; i<almdefsize; i++)
{
System.arraycopy(adef[i].toByteArray(), 0, tba, i*adssize, adssize);
}
if (almdefsize < dout.getArrayLength()) dout.setArrayLength(almdefsize);
return dout.putData(tba, "ADSr4");
}
else
{ // is legacy support necessary ?
}
return TErrorList.invalid_structure_tag;
}
};
TPropertyHandler alarmWatchStructHandler = new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
if (dout == null) return TErrorList.dimension_error;
if (dout.dFormat != TFormat.CF_STRUCT) return TErrorList.illegal_format;
synchronized (gAlarmWatchList)
{
int almwtblsize = gAlarmWatchList.size();
int awssize = TStructRegistry.getSizeInBytes("AWSr4");
byte[] tba = new byte[almwtblsize * awssize];
TAlarmWatchEntry[] aws = (TAlarmWatchEntry[])gAlarmWatchList.toArray(new TAlarmWatchEntry[0]);
if (devAccess.isWrite())
{
if (din.getFormat() != TFormat.CF_STRUCT) return TErrorList.illegal_format;
if (din.getTag().compareTo("AWSr4") == 0)
{
TAlarmWatchEntry[] awe = new TAlarmWatchEntry[1];
awe[0] = new TAlarmWatchEntry();
din.getData(awe);
awe[0].setEquipmentModule(getLocalName());
boolean isNew = false;
for (int i=0; i<aws.length; i++)
{
if (aws[i].equals(awe[0]))
{
aws[i].adjustFrom(awe[0]);
isNew = true;
break;
}
}
if (isNew)
{ // wasn't in list
TExportProperty p = propertyList.getFirstProperty(awe[0].getPrp());
if (p == null) return TErrorList.illegal_property;
if (awe[0].getSiz() <= 0 || awe[0].getSiz() > p.getOutputSize())
{
awe[0].setSiz(p.getOutputSize());
}
awe[0].setFmt(p.getOutputFormat());
gAlarmWatchList.add(awe[0]);
}
}
else
{
return TErrorList.invalid_structure_tag;
}
}
if (dout.getTag().compareTo("AWSr4") == 0)
{ // modern
for (int i=0; i<almwtblsize; i++)
{
System.arraycopy(aws[i].toByteArray(), 0, tba, i*awssize, awssize);
}
if (almwtblsize < dout.getArrayLength()) dout.setArrayLength(almwtblsize);
return dout.putData(tba, "AWSr4");
}
}
return TErrorList.invalid_structure_tag;
}
};
stockList.addProperty(TStockProperties.NALARMS, new TPropertyHandler()
{
int nalmdefs = alarmDefinitionList.size();
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
int devnr = -1;
if (!devName.contains("*") && !devName.startsWith("#"))
{
devnr = deviceList.getDeviceNumber(devName);
}
if (casName != null && !hasCasAttached) isCasInClientList();
int[] nalms = new int[6];
if (devnr < 0)
{ // all of them
nalms[0] = deviceList.getNumberOfAlarms();
nalms[1] = deviceList.getMostRecentAlarmTimestamp(nalms,3);
nalms[2] = deviceList.getHighestAlarmSeverity(nalms,4);
nalms[5] = nalmdefs;
if (nalms[0] > TAlarm.getAlmCollapseWindow())
{
nalms[1] = almDynSet.timestamp;
nalms[4] = nalms[3] = nalms[0] = 1;
}
}
else
{ // just the device given ...
int mrts = 0, ts, hsv = 0, sv, nts = 0, nsv = 0;
TDevice[] dlst = deviceList.getDeviceList();
if (devnr >= dlst.length) return TErrorList.device_not_connected;
TAlarm[] alms = dlst[devnr].getAlarmList();
nalms[0] = alms.length;
for (int i=0; i<alms.length; i++)
{
if ((ts=alms[i].getTimeStamp()) > mrts)
{
mrts = ts;
nts = 0;
}
if (ts == mrts) nts++;
if ((sv=alms[i].getSeverity()) > hsv)
{
hsv = sv;
nsv = 0;
}
if (sv == hsv) nsv++;
}
nalms[1] = mrts;
nalms[2] = hsv;
nalms[3] = nts;
nalms[4] = nsv;
nalms[5] = nalmdefs;
}
if (dout.dArrayLength > 5) nalms[5] = getAlarmDefinitionList().size();
return dout.putData(nalms);
}
});
stockList.addProperty(TStockProperties.NALARMDEFS, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
return dout.putData((short)alarmDefinitionList.size());
}
});
stockList.addProperty(TStockProperties.NALMWATCH, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
return dout.putData((short)gAlarmWatchList.size());
}
});
stockList.addProperty(TStockProperties.ALARMS, alarmsStructHandler);
stockList.addProperty(TStockProperties.ALARMSEXT, alarmsStructHandler);
stockList.addProperty(TStockProperties.ALARMSEXT_STRUCTIN, alarmsStructHandler);
stockList.addProperty(TStockProperties.ALARMDEFS, alarmDefsStructHandler);
stockList.addProperty(TStockProperties.ALMWATCHTBL, alarmWatchStructHandler);
stockList.addProperty(TStockProperties.NHISTORIES, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
return dout.putData((short)gLclHstList.size());
}
});
stockList.addProperty(TStockProperties.HISTORIES, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
return hstCall(devName,dout,din,devAccess);
}
});
stockList.addProperty(TStockProperties.HISTORIES_STRUCT, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
return hstCall(devName,dout,din,devAccess);
}
});
stockList.addProperty(TStockProperties.ADDHISTORY, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
if (devAccess.isWrite())
{
if (din.getFormat() != TFormat.CF_STRUCT) return TErrorList.illegal_format;
if (din.getTag().compareTo("HRSr4") == 0)
{
THistoryRecordStruct[] hrs = new THistoryRecordStruct[1];
hrs[0] = new THistoryRecordStruct();
din.getData(hrs);
String prp = hrs[0].getProperty();
String dev = hrs[0].getDevice();
THistoryRecord hr = getLocalHistoryRecord(prp,dev);
if (hr == null)
{ // wasn't in list
TExportProperty p = getPropertyList().getFirstProperty(prp);
TPropertyDescription pd = p.getDescription();
int at = pd != null ? pd.getArrayType() : TArrayType.AT_UNKNOWN;
int idx = TEquipmentModuleFactory.getInstance().getNextHistoryRecordIndex();
THistorySpecification hspec = new THistorySpecification(hrs[0].getPollingRate(), hrs[0].getArchiveRate(), hrs[0].getDepthShort(), hrs[0].getDepthLong(), hrs[0].getHeartbeat(), hrs[0].getPercentTolerance(), hrs[0].getAbsoluteTolerance(), null);
addLocalHistoryRecord(idx, dev, prp, hrs[0].getSize(), hrs[0].getFormat(),at,hspec);
dumpHistoryManifest();
}
else
{ // just an edit ...
THistorySpecification hsp = hr.getHspec();
hsp.setAbsoluteTolerance(hrs[0].getAbsoluteTolerance());
hsp.setPercentTolerance(hrs[0].getPercentTolerance());
hsp.setArchiveRate(hrs[0].getArchiveRate());
hsp.setPollngRate(hrs[0].getPollingRate());
hsp.setDepthLong(hrs[0].getDepthLong());
hsp.setDepthShort(hrs[0].getDepthShort());
hsp.setHeartbeat(hrs[0].getHeartbeat());
}
return 0;
}
else
{
return TErrorList.invalid_structure_tag;
}
}
return TErrorList.illegal_read_write;
}
});
stockList.addProperty(TStockProperties.ADDHISTORY_STR, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
if (devAccess.isWrite())
{
short fmt = din.getFormat();
if (!TFormat.isName(fmt) && fmt != TFormat.CF_CHAR) return TErrorList.illegal_format;
NAME64[] tgt = new NAME64[1];
int cc = din.getData(tgt);
if (cc != 0) return cc;
String prp = tgt[0].getName();
TExportProperty p = getPropertyList().getFirstProperty(prp);
if (p == null) return TErrorList.invalid_property;
int hfmt = p.getOutputFormat();
int hsiz = p.getOutputSize();
int idx = gEqmFactory.getNextHistoryRecordIndex(getLocalName(),prp,devName,hfmt,hsiz);
addLocalHistoryRecord(idx, devName, prp, hsiz, hfmt);
dumpHistoryManifest();
return 0;
}
return TErrorList.illegal_read_write;
}
});
//TODO: finish these ...
stockList.addProperty(TStockProperties.METAPROPERTIES, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
return metaprpQueryCall(devName,dout,din,devAccess);
}
});
stockList.addProperty(TStockProperties.METAPROPS, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
return metaprpQueryCall(devName,dout,din,devAccess);
}
});
stockList.addProperty(TStockProperties.METAPROPERTIES_STRUCT, metapropertiesStructHandler);
stockList.addProperty(TStockProperties.METAPROPS_STRUCT, metapropertiesStructHandler);
stockList.addProperty(TStockProperties.DEVLOCATION, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
TDevice tdv = deviceList.getDevice(devName);
if (tdv == null) return TErrorList.illegal_device;
if (din != null && devAccess.isWrite())
{
int cc = 0;
char[] newLocation = new char[64];
if ((cc=din.getData(newLocation)) != 0) return cc;
tdv.setLocation(new String(newLocation));
}
String dloc = tdv.getLocation();
if (dloc == null) dloc = gEqmFactory.getFecLocation();
if (dloc != null && dloc.startsWith("<"))
{ /* redirection character */
String rdrstr = null, envstr;
dloc = dloc.substring(1); dloc.trim();
if (dloc.startsWith("$"))
{
int idx = dloc.indexOf('/');
if (idx < 0) idx = dloc.length();
envstr = dloc.substring(1, idx);
rdrstr = System.getenv(envstr);
if (rdrstr == null) MsgLog.log("TEquipmentModule:DEVLOCATION", "environment variable "+envstr+" not set",TErrorList.not_defined,null,0);
dloc = dloc.substring(idx);
}
if (rdrstr == null) rdrstr = "";
rdrstr += dloc;
if (rdrstr.indexOf('[') < 0) rdrstr += "[Location]";
return gEqmFactory.setRedirectionString(rdrstr);
}
return dout.putData(dloc == null ? "" : dloc);
}
});
stockList.addProperty(TStockProperties.DEVMASK, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
TDevice tdv = deviceList.getDevice(devName);
if (tdv == null) return TErrorList.illegal_device;
if (din != null && devAccess.isWrite())
{
int cc = 0;
int[] newMask = new int[1];
if ((cc=din.getData(newMask)) != 0) return cc;
tdv.setMask(newMask[0]);
}
int mask = tdv.getMask();
return dout.putData(mask);
}
});
stockList.addProperty(TStockProperties.ZPOSITION, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
TDevice tdv = deviceList.getDevice(devName);
if (tdv == null) return TErrorList.illegal_device;
if (din != null && devAccess.isWrite())
{
int cc = 0;
float[] newZPos = new float[1];
if ((cc=din.getData(newZPos)) != 0) return cc;
tdv.setZposition(newZPos[0]);
}
float p = tdv.getZposition();
return dout.putData(p);
}
});
stockList.addProperty(TStockProperties.DEVONLINE, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
TDevice tdv = deviceList.getDevice(devName);
if (tdv == null) return TErrorList.illegal_device;
if (din != null && devAccess.isWrite())
{
int cc = 0;
int[] newFlg = new int[1];
if ((cc=din.getData(newFlg)) != 0) return cc;
tdv.setOffline(newFlg[0] == 0 ? true : false);
}
boolean p = !tdv.isOffline();
return dout.putData(p);
}
});
stockList.addProperty(TStockProperties.PROPERTIES, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
return prpQueryCall(devName,dout,din,devAccess);
}
});
stockList.addProperty(TStockProperties.PROPERTIES_USTRING, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
return prpQueryCall(devName,dout,din,devAccess);
}
});
stockList.addProperty(TStockProperties.PROPERTIES_STRUCT, propertiesStructHandler);
stockList.addProperty(TStockProperties.PROPS, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
return prpQueryCall(devName,dout,din,devAccess);
}
});
stockList.addProperty(TStockProperties.PROPS_USTRING, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
return prpQueryCall(devName,dout,din,devAccess);
}
});
stockList.addProperty(TStockProperties.PROPS_STRUCT, propertiesStructHandler);
stockList.addProperty(TStockProperties.NPROPERTIES, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
return dout.putData(propertyList.countUniqueProperties());
}
});
// Same as NPROPERTIES
stockList.addProperty(TStockProperties.NPROPS, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
return dout.putData(propertyList.countUniqueProperties());
}
});
stockList.addProperty(TStockProperties.NDEVICES, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
//return dout.putData(deviceList.size());
return dout.putData(deviceList.getNumberOfDevices());
}
});
stockList.addProperty(TStockProperties.DEVICES, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
String[] namlst;
if (devName.compareTo("*") != 0 && devName.indexOf("*") != -1)
{ // query for a subset of device names ...
WildcardMatch wc = new WildcardMatch(devName);
TDevice dev;
LinkedList<String> nl = new LinkedList<String>();
String dn;
int n = 0, mask = 0;
if (din != null && din.dArrayLength == 1 && din.dFormat == TFormat.CF_INT32)
{
int[] msk = new int[1];
din.getData(msk);
mask = msk[0];
}
for (int i=0; i<deviceList.getNumberOfDevices(); i++)
{
if ((dev=deviceList.getDevice(i)) == null) continue;
if (dev.isOffline()) continue;
if (mask > 0 && !dev.isMaskSet(mask)) continue;
dn = dev.getName();
if (!wc.matches(dn)) continue;
nl.add(dn);
n++;
}
namlst = nl.toArray(new String[n]);
}
else
{
namlst = deviceList.getDeviceNameList();
}
int cc = dout.putData(StringToName.stringArrayToName64(namlst));
if (cc == 0)
{
if (dout.getArrayLength() > namlst.length) dout.setArrayLength(namlst.length);
if (getDeviceList().isPropertyOriented())
cc = TErrorList.has_query_function | TErrorList.CE_SENDDATA;
}
return cc;
}
});
stockList.addProperty(TStockProperties.DEVDESCRIPTION, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
TDevice tdv = deviceList.getDevice(devName);
if (tdv == null) return TErrorList.illegal_device;
String dsc = tdv.getDescription();
return dout.putData(dsc == null ? "" : dsc);
}
});
stockList.addProperty(TStockProperties.SRVSUBSYSTEM, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
String subs = getSubsystem();
return dout.putData(subs == null ? "" : subs);
}
});
stockList.addProperty(TStockProperties.SRVIDLE, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
int cc = 0;
int[] idleState = new int[1];
if (din != null && devAccess.isWrite())
{
if ((cc=din.getData(idleState)) != 0) return cc;
isIdle = idleState[0] == 0 ? false : true;
}
if (dout != null && dout.dArrayLength > 0)
{
idleState[0] = isIdle ? -1 : 0;
cc = dout.putData(idleState);
}
return cc;
}
});
stockList.addProperty(TStockProperties.SRVINIT, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
int cc = 0;
if (!devAccess.isWrite()) return TErrorList.illegal_read_write;
{
if (eqpIni == null) return TErrorList.not_implemented;
cc = eqpIni.initialize();
}
return cc;
}
});
stockList.addProperty(TStockProperties.SRVADDR, new TPropertyHandler()
{
protected int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
NAME32[] n32 = new NAME32[dout.dArrayLength];
String eqm, exp;
TEquipmentModule eq;
int cc = 0;
if (gEqmFactory.isServiceRequest(moduleName))
{
NAME32[] tgt = new NAME32[3];
if ((cc=din.getData(tgt)) != 0) return cc;
String ctxName = tgt[0].getName();
//String eqmName = tgt[1].getName();
String expName = tgt[2].getName();
if ((eq=gEqmFactory.getEquipmentModuleFromExportName(expName)) == null)
return TErrorList.invalid_data;
if (eq.context.compareToIgnoreCase(ctxName) != 0) return TErrorList.invalid_data;
eqm = eq.moduleName;
exp = eq.exportName;
}
else
{
eqm = moduleName;
exp = exportName;
}
cc = gEqmFactory.getSrvAddress(n32,eqm,exp);
return (short) dout.putData(n32);
}
});
stockList.addProperty(TStockProperties.USERS, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
NAME16[] n16 = getRegisteredUsers();
if (din != null && din.dArrayLength > 0)
{
if (!TFormat.isString(din.dFormat)) return TErrorList.illegal_format;
char[] data = new char[TStrings.PROPERTY_NAME_SIZE];
int cc = din.getData(data);
if (cc != 0) return cc;
String str = new String(data).trim();
TExportProperty txp = getPropertyList().getFirstProperty(str);
if (txp != null)
{ // property name given as input
n16 = txp.getRegisteredUsers();
}
else
{ // maybe a device name then ...
TDevice dev = getDeviceList().getDevice(str);
if (dev != null) n16 = dev.getRegisteredUsers();
else return TErrorList.invalid_keyword;
}
}
if (n16 == null)
{
n16 = new NAME16[1];
n16[0] = new NAME16("");
}
dout.dArrayLength = n16 == null ? 0 : n16.length;
return n16 == null ? 0 : dout.putData(n16);
}
});
stockList.addProperty(TStockProperties.NUSERS, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
short n = (short)gRegisteredUsersList.size();
if (din != null && din.dArrayLength > 0)
{
if (!TFormat.isString(din.dFormat)) return TErrorList.illegal_format;
char[] data = new char[TStrings.PROPERTY_NAME_SIZE];
int cc = din.getData(data);
if (cc != 0) return cc;
String str = new String(data).trim();
TExportProperty txp = getPropertyList().getFirstProperty(str);
if (txp != null)
{ // property name given as input
n = (short)txp.getNumberRegisteredUsers();
}
else
{ // maybe a device name then ...
TDevice dev = getDeviceList().getDevice(str);
if (dev != null) n = (short)dev.getNumberRegisteredUsers();
else return TErrorList.invalid_keyword;
}
}
return dout.putData(n);
}
});
stockList.addProperty(TStockProperties.ADDUSER, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
int cc;
if (din != null && devAccess.isWrite())
{
NAME16[] usr = new NAME16[1];
if ((cc=din.getData(usr)) != 0) return cc;
return addRegisteredUser(usr[0].getName());
}
return TErrorList.illegal_read_write;
}
});
stockList.addProperty(TStockProperties.DELUSER, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
int cc;
if (din != null && devAccess.isWrite())
{
NAME16[] usr = new NAME16[1];
if ((cc=din.getData(usr)) != 0) return cc;
return removeRegisteredUser(usr[0].getName());
}
return TErrorList.illegal_read_write;
}
});
stockList.addProperty(TStockProperties.IPNETS, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
NAME16[] n16 = getRegisteredNets();
if (din != null && din.dArrayLength > 0)
{
if (!TFormat.isString(din.dFormat)) return TErrorList.illegal_format;
char[] data = new char[TStrings.PROPERTY_NAME_SIZE];
int cc = din.getData(data);
if (cc != 0) return cc;
String str = new String(data).trim();
TExportProperty txp = getPropertyList().getFirstProperty(str);
if (txp != null)
{ // property name given as input
n16 = txp.getRegisteredNets();
}
else
{ // maybe a device name then ...
TDevice dev = getDeviceList().getDevice(str);
if (dev != null) n16 = dev.getRegisteredNets();
else return TErrorList.invalid_keyword;
}
}
dout.dArrayLength = n16 == null ? 0 : n16.length;
return n16 == null ? 0 : dout.putData(n16);
}
});
stockList.addProperty(TStockProperties.NIPNETS, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
short n = (short)gRegisteredNetsList.size();
if (din != null && din.dArrayLength > 0)
{
if (!TFormat.isString(din.dFormat)) return TErrorList.illegal_format;
char[] data = new char[TStrings.PROPERTY_NAME_SIZE];
int cc = din.getData(data);
if (cc != 0) return cc;
String str = new String(data).trim();
TExportProperty txp = getPropertyList().getFirstProperty(str);
if (txp != null)
{ // property name given as input
n = (short)txp.getNumberRegisteredUsers();
}
else
{ // maybe a device name then ...
TDevice dev = getDeviceList().getDevice(str);
if (dev != null) n = (short)dev.getNumberRegisteredNets();
else return TErrorList.invalid_keyword;
}
}
return dout.putData(n);
}
});
stockList.addProperty(TStockProperties.ADDIPNET, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
int cc;
if (din != null && devAccess.isWrite())
{
NAME16[] ip = new NAME16[1];
if ((cc=din.getData(ip)) != 0) return cc;
return addRegisteredNet(ip[0].getName());
}
return TErrorList.illegal_read_write;
}
});
stockList.addProperty(TStockProperties.DELIPNET, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
int cc;
if (din != null && devAccess.isWrite())
{
NAME16[] ip = new NAME16[1];
if ((cc=din.getData(ip)) != 0) return cc;
return removeRegisteredNet(ip[0].getName());
}
return TErrorList.illegal_read_write;
}
});
stockList.addProperty(TStockProperties.ACCESSLOCK, new TPropertyHandler()
{
public int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
int cc = 0;
if (din != null && devAccess.isWrite())
{
short[] svals = new short[2];
if ((cc=din.getData(svals)) != 0) return cc;
TClient tc = getCaller();
if ((cc=accessLock.setAccessLock(tc,svals[0],svals[1])) != 0) return cc;
gEqmFactory.lockToExclusiveRead(tc);
}
if (dout != null)
{
String[] s = accessLock.getAccessLockAsString();
NAME32[] n32 = new NAME32[3];
n32[0] = new NAME32(s[0]);
n32[1] = new NAME32(s[1]);
n32[2] = new NAME32(s[2]);
cc = dout.putData(n32);
}
return cc;
}
});
stockList.addProperty(TStockProperties.SRVSELFTEST, new TPropertyHandler()
{
protected int call(String devName, TDataType dout, TDataType din, TAccess devAccess)
{
if (dout.getFormat() != TFormat.CF_TEXT) return TErrorList.illegal_format;
String fileName = gEqmFactory.getInitializer().getFecHome() + "/" + getLocalName() + "-selftest.csv";
if (!TFecLog.fileExists(fileName)) return TErrorList.no_such_file;
int nlines = dout.getArrayLength()/80;
return (short) dout.putData(TFecLog.getLines(fileName,nlines));
}
});
stockPropertiesRegistered = true;
/* TEMPLATE */
/*
* stockList.setPropertyHandler("?", new TPropertyHandler() { public short
* call(String devName, TDataType dout, TDataType din, short devAccess) {
* return (short) 0; } });
*/
}
public TEquipmentModule(TEquipmentFunction eqpFunction)
{
String name = eqpFunction.getClass().getName();
StringTokenizer t = new StringTokenizer(name, ".$");
String lastToken = name;
while (t.hasMoreTokens()) lastToken = t.nextToken();
initialize(lastToken, eqpFunction);
}
public TEquipmentModule(String localName, TEquipmentFunction eqpFunction)
{
initialize(localName, eqpFunction);
}
public TEquipmentModule(String localName)
{
initialize(localName, null);
}
/**
* Principal constructor
*
* Use this constructor in most cases. This will attempt to determine
* a suitable local name for the equipment module.
*
*/
public TEquipmentModule()
{
String name = this.getClass().getName();
StringTokenizer t = new StringTokenizer(name, ".$");
String localName = name;
while (t.hasMoreTokens()) localName = t.nextToken();
initialize(localName, null);
}
/**
* Assigns an equipment function.
*
* @param eqpFunction
*/
public void setEquipmentFunction(TEquipmentFunction eqpFunction)
{
this.eqpFcn = eqpFunction;
this.eqpFcn.setEquipmentModule(this);
}
class restorePrpRowHndlr implements RowHandler
{ // the Row Handler will be called when all columns have been read in
public String devName;
public String prpValue;
private int devNumber = 0;
private TExportProperty prp = null;
private TDataType srData = null;
public String prpValuesFile = null;
restorePrpRowHndlr(TExportProperty property,TDataType dt)
{
prpValue = "0";
devName = "";
srData = dt;
prp = property;
}
public int process(int index)
{
TDeviceList dlst = getDeviceList();
if (dlst == null) return TErrorList.device_not_connected;
int ndevs = dlst.getNumberOfDevices();
if (ndevs == 0) return TErrorList.device_not_connected;
if (devNumber < 0 && devNumber >= ndevs) return TErrorList.illegal_equipment_number;
if (srData == null) return TErrorList.not_implemented;
int i = index;
int len = srData.getArrayLength();
short fmt = srData.getFormat();
if (devName.length() > 0)
{ // device name given
i = getDeviceNumber(devName, prp.getName());
if (i < 0) i = index;
if (i > len) return TErrorList.illegal_device;
}
TDataType dt = null;
int offset = i;
try
{
if (prpValue.compareToIgnoreCase("<$FILE") == 0)
{ // an array property
len /= ndevs;
if (prpValuesFile == null) return TErrorList.file_error;
int p = prpValuesFile.lastIndexOf('.');
if (p < 1) return TErrorList.invalid_name;
prpValuesFile = prpValuesFile.substring(0, p) + "." + i;
DataInputStream dis = new DataInputStream(new FileInputStream(prpValuesFile));
hasSrValues[i] = true;
switch (fmt)
{
case TFormat.CF_BYTE:
{
byte[] d = new byte[len];
for (int k=0; k<len; k++) d[k] = dis.readByte();
dt = new TDataType(d);
break;
}
case TFormat.CF_INT16:
{
short[] d = new short[len];
for (int k=0; k<len; k++) d[k] = dis.readShort();
dt = new TDataType(d);
break;
}
case TFormat.CF_INT32:
{
int[] d = new int[len];
for (int k=0; k<len; k++) d[k] = dis.readInt();
dt = new TDataType(d);
break;
}
case TFormat.CF_INT64:
{
long[] d = new long[len];
for (int k=0; k<len; k++) d[k] = dis.readLong();
dt = new TDataType(d);
break;
}
case TFormat.CF_FLOAT:
{
float[] d = new float[len];
for (int k=0; k<len; k++) d[k] = dis.readFloat();
dt = new TDataType(d);
break;
}
case TFormat.CF_DOUBLE:
{
double[] d = new double[len];
for (int k=0; k<len; k++) d[k] = dis.readDouble();
dt = new TDataType(d);
break;
}
default:
dis.close();
return TErrorList.not_supported;
}
dis.close();
offset = i * len;
}
else
{ // normal scalar attribute or MCA property
dt = TDataType.toTDataType(prpValue, fmt, true);
}
dt.getData(srData.getDataObject(),len,offset);
}
catch (FileNotFoundException e)
{ // don't break the csv iterations: this is allowed !
hasSrValues[i] = false;
return 0;
}
catch (Exception any)
{ // parsing error probably
return TErrorList.illegal_format;
}
return 0;
}
}
private LinkedList<String> srLst = new LinkedList<String>();
public int restorePropertyValues(String prpName,TDataType target)
{
if (prpName == null || target == null) return TErrorList.invalid_parameter;
TExportProperty prp = propertyList.getFirstProperty(prpName);
if (prp == null) return TErrorList.illegal_property;
TInitializer initializer = TInitializerFactory.getInstance().getInitializer();
String fn = initializer.getFecHome();
String filename = prpName+"-settings.csv";
csv csvFile = null;
if (moduleName != null) csvFile = new csv(fn+File.separator+moduleName+File.separator+filename);
if (csvFile == null || !csvFile.fileAvailable())
csvFile = new csv(fn+File.separator+filename);
return restorePropertyValues(csvFile,new restorePrpRowHndlr(prp, target));
}
private int restorePropertyValues(csv csvFile,restorePrpRowHndlr srRows)
{
if (srRows == null) return TErrorList.invalid_parameter;
// register the csv database structure:
srRows.prpValuesFile = csvFile.getFileName();
csvColumn[] srCols = new csvColumn[2];
srCols[0] = new csvColumn("VALUES","",new StringFieldHandler(srRows,"prpValue"));
srCols[1] = new csvColumn("DEVICES","",new StringFieldHandler(srRows,"devName"));
// read the file
int rc = csvFile.readFile(srCols,srRows);
// close it
csvFile.close();
return rc;
}
public int savePropertyValues(String prpName,TDataType source)
{
return savePropertyValues(prpName,null,source);
}
public int savePropertyValues(String prpName,String devName,TDataType source)
{
if (prpName == null || source == null) return TErrorList.invalid_parameter;
TExportProperty prp = propertyList.getFirstProperty(prpName);
if (prp == null) return TErrorList.illegal_property;
try
{
ArrayList<String>alst = prp.getDeviceList();
String[] dlst = (alst != null) ?
alst.toArray(new String[0]) :
deviceList.getDeviceNameList();
TInitializer initializer = TInitializerFactory.getInstance().getInitializer();
String fn = initializer.getFecHome()+File.separator;
if (moduleName != null && new File(fn+moduleName+File.separator).exists())
fn += moduleName+File.separator;
String filename = fn + prpName+"-settings.csv";
String nl = System.getProperty("line.separator");
FileWriter fw = new FileWriter(filename);
String ln = "DEVICES, VALUES"+nl;
fw.write(ln);
int len = dlst != null ? dlst.length : 1;
String dev = "";
int devnr = getDeviceNumber(devName, prpName);
if (devnr < 0) devnr = 0;
Object obj = source.getDataObject();
boolean isSrArray = source.isArrayOfPrimitives() && !prp.isMultiChannelArray();
for (int i=0; i<len; i++)
{
dev = dlst != null ? dlst[i] : "#"+i;
if (isSrArray)
{
ln = dev+", <$FILE"+nl;
if (i == devnr)
{ // the targeted device
int alen = prp.getInputSize();
int offset = i * alen;
int p = filename.lastIndexOf('.');
if (p < 1) return TErrorList.invalid_name;
String vfn = filename.substring(0, p) + "." + i;
DataOutputStream dos = new DataOutputStream(new FileOutputStream(vfn));
switch (source.dFormat)
{
case TFormat.CF_BYTE:
for (int k=0; k<alen; k++)
dos.writeByte(((byte[])obj)[k+offset]);
break;
case TFormat.CF_INT16:
for (int k=0; k<alen; k++)
dos.writeShort(((short[])obj)[k+offset]);
break;
case TFormat.CF_INT32:
for (int k=0; k<alen; k++)
dos.writeInt(((int[])obj)[k+offset]);
break;
case TFormat.CF_INT64:
for (int k=0; k<alen; k++)
dos.writeLong(((long[])obj)[k+offset]);
break;
case TFormat.CF_FLOAT:
for (int k=0; k<alen; k++)
dos.writeFloat(((float[])obj)[k+offset]);
break;
case TFormat.CF_DOUBLE:
for (int k=0; k<alen; k++)
dos.writeDouble(((double[])obj)[k+offset]);
break;
default:
dos.close();
return TErrorList.not_supported;
}
dos.close();
}
}
else
{
ln = dev+", "+TDataType.pushToCsvString(obj, i)+nl;
}
fw.write(ln);
}
fw.close();
}
catch (Exception e)
{
TFecLog.log("savePropertyValues","cannot save "+prpName+" values: "+e.getMessage());
}
return 0;
}
private boolean validateSaveRestoreProperty(TExportProperty prp)
{
if (prp == null || !prp.isSaveAndRestore) return false;
try
{
int sizOut,sizIn,sizSr=0;
TDataType srData = prp.getSaveRestoreData();
if (srData != null) return true;
if (!TAccess.isWrite((byte)prp.getAccessMode())) return false;
if ((sizIn=prp.getInputSize()) < 1) return false;
if ((sizOut=prp.getOutputSize()) < 1) return false;
short fmt=prp.getOutputFormat();
if (fmt != prp.getInputFormat()) return false;
if (!TFormat.isAllowedSaveAndRestoreFormat(fmt)) return false;
//if (!TFormat.isSimpleFormat(fmt)) return false;
if (fmt == TFormat.CF_TEXT)
{ // actually 1 string = an array of chars
fmt = TFormat.CF_STRING;
sizSr = deviceList.getNumberOfDevices();
if (sizSr < 1) sizSr = numDevicesFromExportsFile;
}
else if (sizIn == 1)
{ // property sets one at a time
if (sizOut == 1)
{ /* attribute style */
sizSr = deviceList.getNumberOfDevices();
}
else
{ /* part of a multi-channel array ? */
if (!TArrayType.isChannel(prp.getDescription().getArrayType())) return false;
sizSr = sizOut;
}
}
else
{ // property sets multiple values : allow only if multi-channel array
if (sizIn != sizOut) return false;
if (TArrayType.isChannel(prp.getDescription().getArrayType()))
{
sizSr = sizOut;
}
else if (TFormat.isNumberFormat(fmt))
{ // an array of primitives -> make allocation adjustments
int n = deviceList.getNumberOfDevices();
ArrayList<String> pdl = prp.getDeviceList();
if (pdl != null) n = pdl.size();
sizSr = n * sizOut;
}
else
{
return false;
}
}
prp.setSaveRestoreData(new TDataType(sizSr,fmt));
return true;
}
catch (Exception any)
{
return false;
}
}
private boolean[] hasSrValues = null;
protected void applyStoredPropertyValues()
{
if (srLst.size() == 0) return;
Iterator<String> it = srLst.iterator();
String prp = null, dev = "";
TExportProperty p = null;
TDataType srdt = null, tdt = null, ndt = new TDataType();
int len = 0, siz = 1, cc = 0;
TAccess wacc = new TAccess(TAccess.CA_WRITE|TAccess.CA_SAVERESTORE);
TAccess racc = new TAccess(TAccess.CA_READ|TAccess.CA_SAVERESTORE);
ArrayList<String>alst = null;
String[] dlst = null;
TEquipmentModuleFactory f = TEquipmentModuleFactory.getInstance();
TContractTable tct = new TContractTable();
TClientEntry tce = new TClientEntry();
tce.cln = new TClient();
tce.cln.userName = "INITIALIZATION";
tct.clt.add(tce);
while (it.hasNext())
{
prp = it.next();
it.remove();
if ((p=propertyList.getFirstProperty(prp)) == null) continue;
if ((srdt=p.getSaveRestoreData()) == null) continue;
alst = p.getDeviceList();
dlst = (alst != null) ?
alst.toArray(new String[0]) :
deviceList.getDeviceNameList();
siz = 1; hasSrValues = null;
if (srdt.isArrayOfPrimitives())
{
siz = p.getInputSize();
if (siz > 1) hasSrValues = new boolean[siz];
}
tdt = new TDataType(siz,srdt.getFormat());
len = srdt.getArrayLength();
if (dlst != null && dlst.length > 0 && len > dlst.length)
{ // TODO: this should always be the case :
len = dlst.length;
}
if (restorePropertyValues(prp, srdt) == 0)
{ // found a save and restore file
Object obj = srdt.getDataObject();
for (int i=0; i<len; i++)
{
if (hasSrValues != null && !hasSrValues[i]) continue;
dev = (dlst != null && dlst.length > 0) ? dlst[i] : "#"+i;
tdt.replaceData(obj, i*siz, 0, siz);
f.setCurrentContractEntry(tct);
cc = callProperty(prp, dev, ndt, tdt, wacc);
TFecLog.log("applyStoredPropertyValues","restore ("+moduleName+")/"+dev+"["+prp+"] : "+TErrorList.getErrorString(cc));
}
}
else
{ // no file: get initial values
for (int i=0; i<len; i++)
{
dev = (dlst != null && dlst.length > 0) ? dlst[i] : "#"+i;
f.setCurrentContractEntry(tct);
cc = callProperty(prp, dev, tdt, ndt, racc);
tdt.getData(srdt.getDataObject(),siz,i*siz);
TFecLog.log("applyStoredPropertyValues","acquire initial value ("+moduleName+")/"+dev+"["+prp+"] : "+TErrorList.getErrorString(cc));
}
}
}
hasSrValues = null;
}
/**
* Registers a property without a handler. This property has to be handled by
* the equipment function.
*
* @param prpName is the property name
* @param dout Provides output format specification
* @param din Provides input format specification
* @param acc Access information
* @param prpDesc Property description, parsed into a string description
* of the property as well as range values and units.
* @param prpId an assigned Property ID
* @return
*/
public void registerProperty(String prpName, TDataType dout, TDataType din, short acc,
TPropertyDescription prpDesc, int prpId)
{
TStrings.validatePropertyName(prpName);
if (prpDesc == null) prpDesc = new TPropertyDescription(null);
if (prpDesc.getArrayRowLength() == 0) prpDesc.setArrayRowLength(dout.dArrayLength);
if (dout.dArrayLength == 1) prpDesc.setArrayType(TArrayType.AT_SCALAR);
TExportProperty prp = new TExportProperty(prpId, prpName, acc, din, dout);
prp.setDescription(prpDesc);
propertyList.addProperty(this, prp, null);
if (prpName.endsWith(".NAM")) deviceList.setPropertyOriented(true);
if ((acc & TAccess.CA_SAVERESTORE) != 0 && validateSaveRestoreProperty(prp))
{
if (!srLst.contains(prpName)) srLst.add(prpName);
}
if ((acc & TAccess.CA_HIST) != 0)
{ // add a 'quick' history
int fmt = prp.getOutputFormat();
int siz = prp.getOutputSize();
int idx = gEqmFactory.getNextHistoryRecordIndex(getLocalName(),prpName,"#0",fmt,siz);
int cc = addLocalHistoryRecord(idx, "#0", prpName, siz, fmt);
if (cc != 0) TFecLog.log("could not add "+prpName+" to local history subsystem: "+TErrorList.getErrorString(cc));
}
}
/**
* Registers a property and assigns a handler.
*
* @param prp is the TExportProperty instance to be registered
* @param handler is the designated property dispatch handler
*
* @see TPropertyHandler, TExportProperty, TPropertyDescription
* \b example
*
* \include eg_registerproperty.java
*/
public void registerProperty(TExportProperty prp, TPropertyHandler handler)
{
if (prp == null) return;
propertyList.addProperty(this, prp, handler);
short acc = prp.getAccessMode();
String prpName = prp.getName();
if ((acc & TAccess.CA_SAVERESTORE) != 0 && validateSaveRestoreProperty(prp))
{
if (!srLst.contains(prpName)) srLst.add(prpName);
}
if ((acc & TAccess.CA_HIST) != 0)
{ // add a 'quick' history
int fmt = prp.getOutputFormat();
int siz = prp.getOutputSize();
int idx = gEqmFactory.getNextHistoryRecordIndex(getLocalName(),prpName,"#0",fmt,siz);
int cc = addLocalHistoryRecord(idx, "#0", prpName, siz, fmt);
if (cc != 0) TFecLog.log("could not add "+prpName+" to local history subsystem: "+TErrorList.getErrorString(cc));
}
String aprpnam = gEqmFactory.getAliasFromName(prp.getName());
if (aprpnam != null)
{ // register the alias as well !
TExportProperty aprp = new TExportProperty(prp);
aprp.setName(aprpnam);
propertyList.addProperty(this,aprp, handler);
}
if (prp.getName().endsWith(".NAM")) deviceList.setPropertyOriented(true);
}
public int attachPropertyHandler(String prp,TPropertyHandler handler)
{
String aprp = gEqmFactory.getAliasFromName(prp);
if (aprp != null) propertyList.setHandler(aprp,handler);
return propertyList.setHandler(prp,handler);
}
/**
* Adds a collection of device names to the module's device list.
*/
// TODO Test if sequence remains unchanged
public void registerDevices(Collection<String[]> deviceCollection)
{
// deviceList.addAll(deviceNames);
// int ndevs = deviceCollection.size();
String[] devs = (String[])deviceCollection.toArray(new String[0]);
int ndevs = devs.length;
for (int i=0; i<ndevs; i++)
{
TStrings.validateDeviceName(devs[i]);
deviceList.addDevice(devs[i],this);
}
}
public void registerDevices(String[] deviceNames)
{
if (deviceNames == null) return;
for (int i=0; i<deviceNames.length; i++)
{
TStrings.validateDeviceName(deviceNames[i]);
deviceList.addDevice(deviceNames[i],i,this);
}
}
/**
* Adds a device to the module's device list.
*
* @param device is the TDevice instance to register
*/
public void registerDevice(TDevice device)
{
if (device == null) return;
device.setEqm(this);
deviceList.addDevice(device);
}
public void registerDevices(TDevice[] devices)
{
if (devices == null) return;
for (int i=0; i<devices.length; i++)
{
devices[i].setEqm(this);
deviceList.addDevice(devices[i]);
}
}
public void registerDevices(int numberOfDevices)
{
if (numberOfDevices <= 0) return;
TDevice[] devices = new TDevice[numberOfDevices];
for (int i=0; i<numberOfDevices; i++)
{
devices[i] = new TDevice(i);
devices[i].setEqm(this);
deviceList.addDevice(devices[i]);
}
}
/**
* Adds a device name to the module's device list.
*
* This method also creates a TDevice instance for the device
* name in question, which can be retrieved via a call to
* getDevice().
*
* @param devName is the device name to be assigned
*
* @return the assigned device number
*/
public int registerDeviceName(String devName)
{
TStrings.validateDeviceName(devName);
deviceList.addDevice(devName,this);
String adev = gEqmFactory.getAliasFromName(devName);
if (adev != null)
{ // register the alias as well !
deviceList.addDevice(adev,this);
}
return deviceList.getDeviceNumber(devName);
}
public int registerDeviceName(String devName,int devNumber)
{
TStrings.validateDeviceName(devName);
deviceList.addDevice(devName,devNumber,this);
String adev = gEqmFactory.getAliasFromName(devName);
if (adev != null)
{ // register the alias as well !
deviceList.addDevice(adev,devNumber,this);
}
return devNumber;
}
/**
* Returns all property names in a linked list.
*
* @return
*/
public LinkedList<String> getPropertyNames()
{
LinkedList<String> rv = new LinkedList<String>();
rv.addAll(propertyList.getPropertyNames());
return rv;
}
private void dumpList(String text,LinkedList<String> lst)
{
TLinkFactory.dbgPrint(text);
for (Iterator<String> it = lst.iterator(); it.hasNext();)
{
TLinkFactory.dbgPrint((String) it.next());
}
TLinkFactory.dbgPrint("");
}
public void dumpProperties()
{
dumpList("Registered Properties for "+getLocalName()+" :",getPropertyNames());
}
public void dumpDevices()
{
dumpList("Registered Devices for "+getLocalName()+" :",getDeviceNames());
}
/**
* Returns all device names in a linked list.
*
* @return
*/
public LinkedList<String> getDeviceNames()
{
return deviceList.getDeviceLinkedList();
}
/**
* Returns true if this equipment module has registered a stock property of a
* given name.
*
* @param propertyName
* @return
*/
public boolean hasStockProperty(String propertyName)
{
return stockList.hasProperty(propertyName);
}
public boolean hasProperty(String propertyName)
{
return propertyList.hasProperty(propertyName);
}
/**
* Calls a stock property handler
*
* @param propertyName
* @param devName
* @param dout
* @param din
* @param devAccess
* @return
*/
public short callStockProperty(String propertyName, String devName, TDataType dout,
TDataType din, TAccess devAccess)
{
return stockList.callPropertyHandler(propertyName, devName, dout, din, devAccess);
}
/**
* Finds a property and calls the property handler. If no property handler is
* installed, the equipment function is called instead.
*
* @param propertyName
* @param devName
* @param dout
* @param din
* @param devAccess
* @return Return code of property handler/equipment function.
* TErrorList.non_existent_elem if no property handler and no
* equipment function could be found.
*/
public short callProperty(String propertyName, String devName, TDataType dout, TDataType din, TAccess devAccess)
{
try
{
if (propertyList.hasProperty(propertyName))
{
return propertyList.callPropertyHandler(propertyName, devName, dout, din, devAccess);
}
else if (eqpFcn != null)
{
if (TEquipmentModuleFactory.debugLevel > 1)
DbgLog.log("callProperty","call function handler for "+getLocalName()+"/"+devName+"["+propertyName+ "]");
return eqpFcn.call(propertyName, devName, dout, din, devAccess.toShort());
}
else
{
if (TEquipmentModuleFactory.debugLevel > 1)
DbgLog.log("callProperty","no handler for "+getLocalName()+"/"+devName+"["+propertyName+ "]");
return TErrorList.illegal_property;
}
}
catch (Exception e)
{
e.printStackTrace();
MsgLog.log("callProperty "+propertyName,"unhandled exception "+e.toString(),TErrorList.code_failure,e,0);
setCompletionString(e.getMessage());
return TErrorList.code_failure+1000;
}
}
public short callMetaProperty(String metaPropertyName, String devName, TDataType dout, TDataType din, TAccess devAccess)
{
try
{
if (!TMetaProperties.isMetaProperty(metaPropertyName)) return TErrorList.illegal_property;
int metaIndex = TMetaProperties.getIndex(metaPropertyName);
String propertyName = TMetaProperties.getTargetProperty(metaPropertyName);
if (stockList.hasProperty(propertyName))
{ // meta info for stock property ! (only .NAM is allowed)
if (metaIndex == TMetaProperties.NAM_ID)
{
String[] slst = deviceList.getDeviceNameList();
return (short)dout.putData(StringToName.stringArrayToName16(slst));
}
}
if (!propertyList.hasProperty(propertyName)) return TErrorList.illegal_property;
TExportProperty prp = propertyList.getFirstProperty(propertyName);
if (prp == null) return TErrorList.illegal_property;
TPropertyEGU egu;
int cc = 0;
float[] fv = new float[1];
switch (metaIndex)
{
case TMetaProperties.URL_ID:
return (short) dout.putData(prp.getDescription().getUrl());
case TMetaProperties.DSC_ID:
return (short) dout.putData(prp.getDescription().getText());
case TMetaProperties.MAX_ID:
case TMetaProperties.XMAX_ID:
egu = metaIndex == TMetaProperties.XMAX_ID ?
prp.getDescription().getXRange() : prp.getDescription().getYRange();
if (devAccess.isWrite())
{
if (din.dArrayLength != 1) return TErrorList.dimension_error;
if (!TFormat.isNumberFormat(din.dFormat)) return TErrorList.illegal_format;
if ((cc=din.getData(fv)) != 0) return (short)cc;
egu.setMaxValue(fv[0]);
if (dout.dArrayLength == 0) return 0;
}
if (!TFormat.isNumberFormat(dout.dFormat)) return TErrorList.illegal_format;
fv[0] = egu.getMaxValue();
return (short) dout.putData(fv);
case TMetaProperties.MIN_ID:
case TMetaProperties.XMIN_ID:
egu = metaIndex == TMetaProperties.XMIN_ID ?
prp.getDescription().getXRange() : prp.getDescription().getYRange();
if (devAccess.isWrite())
{
if (din.dArrayLength != 1) return TErrorList.dimension_error;
if (!TFormat.isNumberFormat(din.dFormat)) return TErrorList.illegal_format;
if ((cc=din.getData(fv)) != 0) return (short)cc;
egu.setMinValue(fv[0]);
if (dout.dArrayLength == 0) return 0;
}
if (!TFormat.isNumberFormat(dout.dFormat)) return TErrorList.illegal_format;
fv[0] = egu.getMinValue();
return (short) dout.putData(fv);
case TMetaProperties.XEGU_ID:
case TMetaProperties.EGU_ID: // to satisfy DOOCS calls ...
egu = metaIndex == TMetaProperties.XEGU_ID ?
prp.getDescription().getXRange() :
prp.getDescription().getYRange();
if (devAccess.isWrite())
{
switch (din.dFormat)
{
case TFormat.CF_NAME16:
case TFormat.CF_NAME32:
case TFormat.CF_NAME64:
if (din.getArrayLength() != 1) return TErrorList.dimension_error;
case TFormat.CF_TEXT:
char[] newUnits = new char[64];
cc = din.getData(newUnits);
if (cc != 0) return (short)cc;
egu.setUnits(new String(newUnits));
break;
case TFormat.CF_FLOAT:
case TFormat.CF_DOUBLE:
case TFormat.CF_DLONG:
case TFormat.CF_LONG:
case TFormat.CF_SHORT:
if (din.dArrayLength != 2) return TErrorList.dimension_error;
float[] yrng = new float[2];
cc = din.getData(yrng);
if (cc != 0) return (short)cc;
egu.setMinValue(yrng[0]);
egu.setMaxValue(yrng[1]);
break;
case TFormat.CF_USTRING:
if (din.getArrayLength() != 1) return TErrorList.dimension_error;
USTRING[] u = new USTRING[1];
cc = din.getData(u);
if (cc != 0) return (short)cc;
egu.setUnits(u[0].getString());
egu.setMinValue(u[0].f1val);
egu.setMaxValue(u[0].f2val);
egu.setGraphType((short)u[0].ival);
break;
default:
return TErrorList.illegal_format;
}
if (dout.dArrayLength == 0) return 0;
}
switch (dout.dFormat)
{
case TFormat.CF_TEXT:
case TFormat.CF_NAME16:
case TFormat.CF_NAME32:
case TFormat.CF_NAME64:
return (short) dout.putData(egu.getUnits());
case TFormat.CF_FLOAT:
case TFormat.CF_DOUBLE:
case TFormat.CF_DLONG:
case TFormat.CF_LONG:
case TFormat.CF_SHORT:
float[] yrng = new float[2];
yrng[0] = egu.getMinValue();
yrng[1] = egu.getMaxValue();
return (short) dout.putData(yrng);
case TFormat.CF_USTRING:
USTRING[] u = new USTRING[1];
u[0] = new USTRING(egu.getGraphType(),
egu.getMinValue(),
egu.getMaxValue(),
0,
egu.getUnits());
return (short) dout.putData(u);
default:
return TErrorList.illegal_format;
}
case TMetaProperties.HST_ID:
THistoryRecord hst = null;
int listsize = gLclHstList.size();
int index = 0, sample = 0;
long start = 0;
long stop = System.currentTimeMillis()-1000;
int sysstart = 0, sysstop = 0;
int cycnr = TEquipmentModuleFactory.getCycleNumber();
float lwr = 0, upr = 0;
Object data = null;
int dataSize = 0, inputDataSize = 0;
boolean isCentralArchiveRequest = false;
if (TMetaProperties.isCentralArchive(metaPropertyName))
{
isCentralArchiveRequest = true;
}
boolean isSnapshot = TMetaProperties.isHistorySnapshot(metaPropertyName);
dataSize = dout.getArrayLength();
if (dout.dFormat == TFormat.CF_HISTORY)
{ // trap this early
int hsiz = TFormat.getCarriedFormatSize(dout.getTag());
if (hsiz > 0) dataSize /= hsiz + TFormat.getHistoryHeaderSize();
}
start = stop - dataSize * 1000; // millisecond timestamps here!
// check the time range and/or filtering criteria the caller has given us ...
if (din != null && (inputDataSize=din.getArrayLength()) > 0)
{
switch (din.getFormat())
{
case TFormat.CF_LONG:
int[] ival = (int[])din.getDataObject();
switch (inputDataSize)
{
case 6: sysstop = ival[5];
if (cycnr == 0) sysstop = 0;
if (sysstop > cycnr) sysstop = cycnr;
case 5: sysstart = ival[4];
if (cycnr == 0) sysstart = 0;
case 4: sample = ival[3];
case 3: index = ival[2];
case 2: if (ival[1] < (int)(stop/1000)) stop = ((long)ival[1])*1000;
case 1: start = ((long)ival[0])*1000;
default: break;
}
if (sample < 0) sample = 0;
break;
case TFormat.CF_DLONG:
long[] lval = (long[])din.getDataObject();
switch (inputDataSize)
{
case 6: sysstop = (int)lval[5];
if (cycnr == 0) sysstop = 0;
if (sysstop > cycnr) sysstop = cycnr;
case 5: sysstart = (int)lval[4];
if (cycnr == 0) sysstart = 0;
case 4: sample = (int)lval[3];
case 3: index = (int)lval[2];
case 2: if (lval[1] < stop/1000) stop = (long)(lval[1]*1000);
case 1: start = (long)(lval[0]*1000);
default: break;
}
if (sample < 0) sample = 0;
break;
case TFormat.CF_DOUBLE:
double[] dval = (double[])din.getDataObject();
switch (inputDataSize)
{
case 6: sysstop = (int)dval[5];
if (cycnr == 0) sysstop = 0;
if (sysstop > cycnr) sysstop = cycnr;
case 5: sysstart = (int)dval[4];
if (cycnr == 0) sysstart = 0;
case 4: sample = (int)dval[3];
case 3: index = (int)dval[2];
case 2: if (dval[1] < stop/1000) stop = (long)(dval[1]*1000);
case 1: start = (long)(dval[0]*1000);
default: break;
}
if (sample < 0) sample = 0;
break;
case TFormat.CF_FWINDOW:
FWINDOW[] fw = (FWINDOW[])din.getDataObject();
start = ((FWINDOW[])fw)[0].i1val * 1000;
stop = ((FWINDOW[])fw)[0].i2val * 1000;
lwr = ((FWINDOW[])fw)[0].f1val;
upr = ((FWINDOW[])fw)[0].f2val;
if (lwr < upr) sample = -1;
break;
default:
return TErrorList.illegal_format;
}
}
else
{ // no input given
if (dataSize == 1)
{
start = stop;
isSnapshot = true;
}
}
if (isSnapshot)
{
if (start < 1) return TErrorList.argument_list_error;
if (sysstart > 0) sysstop = sysstart; else stop = start;
sample = 0;
index = 0;
lwr = upr = (float)0.0;
}
// what the caller wants returned ....
boolean literalDevice = false;
for (int i=0; i<listsize; i++)
{ // go thru the list to see if the requested device was stored literally
hst = (THistoryRecord)gLclHstList.get(i);
if (hst.getPrp().compareToIgnoreCase(prp.getName()) != 0) continue;
if (hst.getDev().compareTo(devName) != 0) continue;
literalDevice = true;
break;
}
for (int i=0; i<listsize; i++)
{
hst = (THistoryRecord)gLclHstList.get(i);
if (hst.getPrp().compareToIgnoreCase(prp.getName()) == 0)
{
if (hst.getDev().compareTo(devName) != 0)
{ // should we look for a match in the device name ?
if (index == 0 && !literalDevice)
index = getDeviceList().getDeviceNumber(devName);
else
continue;
}
if (isCentralArchiveRequest)
{
String rmtsrv = hst.getRemoteHistoryServer();
if (rmtsrv == null || rmtsrv.length() == 0)
{ // try the central archive systematics ...
rmtsrv = "/"+getContext()+"/HISTORY/"+devName+"["+getExportName()+"."+propertyName+"]";
}
return (short)gEqmFactory.setRedirectionString(rmtsrv);
}
// snapshots always have index = 0
if (start == stop && dataSize > 1) index = 0;
switch (dout.dFormat)
{
case TFormat.CF_BYTE:
data = new byte[dataSize]; break;
case TFormat.CF_SHORT:
data = new short[dataSize]; break;
case TFormat.CF_LONG:
data = new int[dataSize]; break;
case TFormat.CF_DLONG:
data = new long[dataSize]; break;
case TFormat.CF_INTINT:
data = new INTINT[dataSize]; break;
case TFormat.CF_FLOAT:
data = new float[dataSize]; break;
case TFormat.CF_FLTINT:
data = new FLTINT[dataSize]; break;
case TFormat.CF_INTFLTINT:
data = new INTFLTINT[dataSize]; break;
case TFormat.CF_DOUBLE:
data = new double[dataSize]; break;
case TFormat.CF_DBLDBL:
data = new DBLDBL[dataSize]; break;
case TFormat.CF_DBLTIME:
data = new DBLTIME[dataSize]; break;
case TFormat.CF_NAME16:
data = new NAME16[dataSize]; break;
case TFormat.CF_NAME16I:
data = new NAME16I[dataSize]; break;
case TFormat.CF_NAME32:
data = new NAME32[dataSize]; break;
case TFormat.CF_NAME32I:
data = new NAME32I[dataSize]; break;
case TFormat.CF_NAME64:
data = new NAME64[dataSize]; break;
case TFormat.CF_NAME64I:
data = new NAME64I[dataSize]; break;
case TFormat.CF_HISTORY:
data = new HISTORY[dataSize];
// create the first one so as to pass the tag along
short f = TFormat.getFormatCode(dout.getTag());
if (f == TFormat.CF_NULL) return TErrorList.illegal_format;
TDataType d = new TDataType(1,f);
((HISTORY[])data)[0] = new HISTORY(d);
break;
default:
data = TFormat.makeCompoundDataObjectArray(dout.dFormat, dout.getTag(), dataSize);
break;
}
int nr = hst.getDataFromLTS(index,start,stop,sysstart,sysstop,lwr,upr,data,dataSize,0,sample);
if (nr < 0)
{
if (nr == -TErrorList.server_redirection)
{
String rmtsrv = hst.getRemoteHistoryServer();
if (rmtsrv == null || rmtsrv.length() == 0) return TErrorList.not_implemented;
return (short)gEqmFactory.setRedirectionString(rmtsrv);
}
return (short)-nr;
}
boolean needStsData = true;
if (nr > 0)
{
if (isSnapshot || nr >= dataSize - 1)
{ // found the snapshot in or filled the buffer from LTS
dout.putData(data);
dout.setDataTimeStamp(hst.getLastReadTimestamp());
dout.setSystemDataStamp(hst.getLastReadSystemStamp());
return 0;
}
start = hst.getLastReadTimestamp() + 1;
if (start >= stop) needStsData = false; // we're finished
}
if (needStsData)
{ // still recent points to acquire
nr = hst.getDataFromSTS(index,start,stop,sysstart,sysstop,lwr,upr,data,dataSize,nr,sample);
if (nr < 0) return (short)-nr;
}
if (dataSize > 1 && nr < dataSize) dout.dArrayLength = nr;
dout.putData(data);
dout.setDataTimeStamp(hst.getLastReadTimestamp());
dout.setSystemDataStamp(hst.getLastReadSystemStamp());
return 0;
}
}
return TErrorList.not_implemented;
case TMetaProperties.NAM_ID:
// if .NAM properties are registered they are handled with the normal property handler
String[] slst = deviceList.getDeviceNameList();
ArrayList<String> lst = prp.getDeviceList();
if (lst != null && lst.size() > 0)
{
slst = new String[lst.size()];
lst.toArray(slst);
}
else
{ // devices from registered device list ...
boolean chkOn = false, chkMask = false;
int idx = -1, edx = -1, mask = 0;
if (metaPropertyName.contains(".ONLINE")) chkOn = true;
if ((idx=metaPropertyName.indexOf(".DMASK.")) > 0)
{ // fun and games with .NAMES ...
idx += 7;
edx = metaPropertyName.indexOf(".NAM");
if (edx > idx)
{
try
{
String mstr = metaPropertyName.substring(idx, edx);
int radix = 10;
if (mstr.toLowerCase().startsWith("0x"))
{
mstr = mstr.substring(2);
radix = 16;
}
mask = Integer.parseInt(mstr, radix);
chkMask = true;
}
catch (Exception ignore) {}; // then mask stays = 0
}
}
if (chkOn || chkMask)
{
TDevice dev;
LinkedList<String> dl = new LinkedList<String>();
for (int i=0; i<deviceList.getNumberOfDevices(); i++)
{
if ((dev=deviceList.getDevice(i)) == null) continue;
if (chkOn && dev.isOffline()) continue;
if (chkMask && !dev.isMaskSet(mask)) continue;
dl.add(dev.getName());
}
slst = dl.toArray(new String[0]);
}
}
return (short)dout.putData(StringToName.stringArrayToName64(slst));
default:
break;
}
return TErrorList.illegal_property;
}
catch (Exception e)
{
e.printStackTrace();
MsgLog.log("callProperty "+metaPropertyName,"unhandled exception "+e.toString(),TErrorList.code_failure,e,0);
setCompletionString(e.getMessage());
return TErrorList.code_failure + 1000;
}
}
// csv file EXPORTS handlers:
class expRowHndlr implements RowHandler
{ // the Row Handler will be called when all columns have been read in
private TExportProperty xp;
private TPropertyDescription prpDesc;
private String targetLocalName = null;
private String localName = null;
private String expName = null;
private int numDevsHint = 1;
public void setLocalName(String value) { localName = value; }
public void setExpName(String value) { expName = value; }
public void setNumDevsHint(int value) { numDevsHint = value; }
public int getNumDevsHist() { return numDevsHint; }
public TExportProperty getExportProperty() { return xp; }
public TPropertyDescription getPropertyDescription() { return prpDesc; }
expRowHndlr(String targetName)
{
xp = new TExportProperty();
prpDesc = new TPropertyDescription();
if (targetLocalName == null) targetLocalName = targetName;
}
public int process(int index)
{
if (localName == null || localName.compareTo(moduleName) != 0) return 0;
if (targetLocalName != null && targetLocalName.compareTo(moduleName) != 0) return 0;
// register this one
if (expName != null) setExportName(expName);
if ((TAccess.CA_WRITE & xp.getAccessMode()) == TAccess.CA_WRITE)
{ // a writeable property
if (xp.getInputFormat() == TFormat.CF_NULL &&
xp.getOutputFormat() != TFormat.CF_NULL)
{ // probably a quick registration: supply this
xp.setInputFormat(xp.getOutputFormat());
}
}
xp.setDescription(prpDesc);
registerProperty(xp,null);
// allocate a new one
xp = new TExportProperty();
prpDesc = new TPropertyDescription();
if (numDevsHint > numDevicesFromExportsFile)
numDevicesFromExportsFile = numDevsHint;
return 0;
}
}
class expXnHndlr implements csvHandler
{
private expRowHndlr rHndlr;
expXnHndlr(expRowHndlr rowHndlr)
{
rHndlr = rowHndlr;
}
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
String nm = (strValue.length() > TStrings.EXPORT_NAME_SIZE) ? strValue.substring(0,TStrings.EXPORT_NAME_SIZE) : strValue;
rHndlr.setExpName(nm);
return 0;
}
}
class expCtxHndlr implements csvHandler
{
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
setContext(strValue);
String fctx = gEqmFactory.getFecContext();
if (fctx == null || fctx.length() == 0)
{ // make sure the general context is set
gEqmFactory.setFecContext(strValue);
}
return 0;
}
}
class expMstrHndlr implements csvHandler
{
public int process(String strValue, int index)
{
if (strValue == null || strValue.length() == 0) return 0;
setMaster(strValue);
return 0;
}
}
class expSlavHndlr implements csvHandler
{
public int process(String strValue, int index)
{
if (strValue == null || strValue.length() == 0) return 0;
String mstr = getMaster();
if (mstr != null && mstr.length() > 0) setSlaveMaster(mstr,strValue);
return 0;
}
}
class expSubHndlr implements csvHandler
{
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
setSubsystem(strValue);
return 0;
}
}
class expGrpHndlr implements csvHandler
{
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
setGroupName(strValue);
return 0;
}
}
class expGrpPrefixHndlr implements csvHandler
{
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
setGroupDevicePrefix(strValue);
return 0;
}
}
class expGrpPostfixHndlr implements csvHandler
{
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
setGroupDevicePostfix(strValue);
return 0;
}
}
class expGrpIdxHndlr implements csvHandler
{
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
setGroupIndex(Integer.valueOf(strValue).intValue());
return 0;
}
}
class expLnHndlr implements csvHandler
{
private expRowHndlr rHndlr;
private String targetLocalName = null;
expLnHndlr(expRowHndlr rowHndlr, String targetName)
{
if (targetLocalName == null) targetLocalName = targetName;
rHndlr = rowHndlr;
//localName = targetName;
}
public int process(String strValue,int index)
{
rHndlr.setLocalName(strValue);
if (strValue == null || strValue.length() == 0) return 0;
if (targetLocalName != null && targetLocalName.compareTo(strValue) != 0) return 0;
String nm = (strValue.length() > TStrings.EQM_NAME_SHORTSIZE) ? strValue.substring(0,TStrings.EQM_NAME_SHORTSIZE) : strValue;
setLocalName(nm);
return 0;
}
}
class expPrpHndlr implements csvHandler
{
private expRowHndlr rHndlr;
expPrpHndlr(expRowHndlr rowHndlr) { rHndlr = rowHndlr; }
public int process(String strValue,int index)
{
rHndlr.getExportProperty().setName(strValue);
return 0;
}
}
class expPrpDescHndlr implements csvHandler
{
private expRowHndlr rHndlr;
expPrpDescHndlr(expRowHndlr rowHndlr) { rHndlr = rowHndlr; }
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
// parse the csv file text description according to convention
rHndlr.getPropertyDescription().parseComplexString(strValue);
return 0;
}
}
class expPrpSizeHndlr implements csvHandler
{
private expRowHndlr rHndlr;
expPrpSizeHndlr(expRowHndlr rowHndlr) { rHndlr = rowHndlr; }
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
rHndlr.getExportProperty().setOutputSize(new Integer(strValue).intValue());
return 0;
}
}
class expNumDevsHndlr implements csvHandler
{
private expRowHndlr rHndlr;
expNumDevsHndlr(expRowHndlr rowHndlr) { rHndlr = rowHndlr; }
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) strValue = "10";
rHndlr.setNumDevsHint(new Integer(strValue).intValue());
return 0;
}
}
class expPrpFmtHndlr implements csvHandler
{
private expRowHndlr rHndlr;
expPrpFmtHndlr(expRowHndlr rowHndlr) { rHndlr = rowHndlr; }
public int process(String strValue,int index)
{
// parse the format string according to convention
int stop = strValue.indexOf(".");
String fmtString = stop != -1 ? strValue.substring(0,stop) : strValue;
short fmt = TFormat.getFormatCode(fmtString);
rHndlr.getExportProperty().setOutputFormat(fmt);
if (stop != -1)
{
String fss = strValue.substring(stop+1);
if (fmt == TFormat.CF_STRUCT)
{
if (fss.endsWith(".CHANNEL") || fss.endsWith(".channel"))
{
fss = fss.substring(0, fss.length()-8);
}
rHndlr.getExportProperty().setOutputTag(fss);
}
else
{
rHndlr.getPropertyDescription().setArrayType(TArrayType.getType(fss));
}
}
return 0;
}
}
class expDbaHndlr implements csvHandler
{
private expRowHndlr rHndlr;
expDbaHndlr(expRowHndlr rowHndlr) { rHndlr = rowHndlr; }
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
try
{
TExportProperty xp = rHndlr.getExportProperty();
addPrpDbaItem(xp.getName(), xp.getAccessMode(), new Integer(strValue).intValue());
}
catch (Exception e)
{ // just dump the stack (parsing error?, xp == null ?)
e.printStackTrace();
}
return 0;
}
}
class expPrpInSizeHndlr implements csvHandler
{
private expRowHndlr rHndlr;
expPrpInSizeHndlr(expRowHndlr rowHndlr) { rHndlr = rowHndlr; }
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
rHndlr.getExportProperty().setInputSize(new Integer(strValue).intValue());
return 0;
}
}
class expPrpInFmtHndlr implements csvHandler
{
private expRowHndlr rHndlr;
expPrpInFmtHndlr(expRowHndlr rowHndlr) { rHndlr = rowHndlr; }
public int process(String strValue,int index)
{
int stop = strValue.indexOf(".");
String fmtString = stop != -1 ? strValue.substring(0,stop) : strValue;
short fmt = TFormat.getFormatCode(fmtString);
rHndlr.getExportProperty().setInputFormat(fmt);
if (fmt == TFormat.CF_STRUCT)
{
String tag = strValue.substring(stop+1);
if (tag.endsWith(".CHANNEL") || tag.endsWith(".channel"))
{
tag = tag.substring(0, tag.length()-8);
}
rHndlr.getExportProperty().setInputTag(tag);
}
return 0;
}
}
class expPrpIdHndlr implements csvHandler
{
private expRowHndlr rHndlr;
expPrpIdHndlr(expRowHndlr rowHndlr) { rHndlr = rowHndlr; }
public int process(String strValue,int index)
{
int idx = index;
try
{
if (strValue != null && strValue.length() > 0)
idx = new Integer(strValue).intValue();
}
catch (NumberFormatException e)
{
idx = index;
}
rHndlr.getExportProperty().setId(idx);
return 0;
}
}
class expPrpAccessHndlr implements csvHandler
{
private expRowHndlr rHndlr;
expPrpAccessHndlr(expRowHndlr rowHndlr) { rHndlr = rowHndlr; }
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
// parse access mode according to convention
String accessString = strValue.trim().toUpperCase();
short ta = 0;
int idx = -1;
TExportProperty txp = rHndlr.getExportProperty();
if (txp == null) return TErrorList.code_failure;
if ((idx=accessString.indexOf("XREAD")) >= 0)
{ // remove this from the accessString for further comparisons
txp.hasExclusiveRead = true;
String s = accessString.substring(0, idx);
s += accessString.substring(idx+5, accessString.length());
accessString = s;
}
if (accessString.indexOf("WRITE") >= 0) ta |= TAccess.CA_WRITE;
if (accessString.indexOf("READ") >= 0) ta |= TAccess.CA_READ;
if (accessString.indexOf("NETWORK") >= 0) ta |= TAccess.CA_READ|TAccess.CA_NETWORK;
if (accessString.indexOf("ASYNC") >= 0)
{
ta &= ~(TAccess.CA_WRITE);
ta |= TAccess.CA_READ|TAccess.CA_NOSYNC;
}
if (accessString.indexOf("SAVERESTORE") >= 0) ta |= TAccess.CA_SAVERESTORE;
if (accessString.indexOf("HIST") >= 0) ta |= TAccess.CA_HIST;
if (accessString.indexOf("FORCEOUTPUT") >= 0) ta |= TAccess.CA_FORCEOUTPUT;
txp.setAccessMode(ta);
if (txp.hasExclusiveRead && !TAccess.isRead((byte)ta))
{ // force read calls thru the security layer for this property !
txp.hasUnlockedExclusiveRead = true;
}
return 0;
}
}
class expPrpRdrHndlr implements csvHandler
{
private expRowHndlr rHndlr;
expPrpRdrHndlr(expRowHndlr rowHndlr) { rHndlr = rowHndlr; }
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
// TODO: parse the csv file redirection string according to convention
rHndlr.getPropertyDescription().setRedirection(strValue);
return 0;
}
}
class expMaxValueHndlr implements csvHandler
{
private expRowHndlr rHndlr;
private boolean isXaxis = false;
expMaxValueHndlr(expRowHndlr rowHndlr,boolean xaxis) {rHndlr = rowHndlr; isXaxis = xaxis;}
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
TExportProperty txp = rHndlr.getExportProperty();
if (txp == null) return TErrorList.code_failure;
if (isXaxis)
txp.setMaximumXValue(Float.valueOf(strValue).floatValue());
else
txp.setMaximumValue(Float.valueOf(strValue).floatValue());
return 0;
}
}
class expMinValueHndlr implements csvHandler
{
private expRowHndlr rHndlr;
private boolean isXaxis = false;
expMinValueHndlr(expRowHndlr rowHndlr,boolean xaxis) {rHndlr = rowHndlr; isXaxis = xaxis;}
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
TExportProperty txp = rHndlr.getExportProperty();
if (txp == null) return TErrorList.code_failure;
if (isXaxis)
txp.setMinimumXValue(Float.valueOf(strValue).floatValue());
else
txp.setMinimumValue(Float.valueOf(strValue).floatValue());
return 0;
}
}
class expUnitsHndlr implements csvHandler
{
private expRowHndlr rHndlr;
private boolean isXaxis = false;
expUnitsHndlr(expRowHndlr rowHndlr,boolean xaxis) {rHndlr = rowHndlr; isXaxis = xaxis;}
public int process(String strValue,int index)
{
if (strValue == null) return 0;
TExportProperty txp = rHndlr.getExportProperty();
if (txp == null) return TErrorList.code_failure;
if (isXaxis)
txp.setXUnits(strValue);
else
txp.setUnits(strValue);
return 0;
}
}
// TODO: call this from some strategic location
// (currently tested inside of SineEquipmentModule)
public int getExportInformationFromFile()
{
return getExportInformationFromFile(moduleName);
}
public int getExportInformationFromFile(String eqmName)
{
getEquipmentModuleFactory().getFecXmlDocument();
FecCfg cfg = gEqmFactory.getFecXmlCfg();
if (cfg != null)
{ // has parsed a fec.xml config file ...
LinkedList<EqmCfg> el = cfg.getEqmList();
LinkedList<String> dv = null;
float max, min;
String grp, ctx, sub, exp, mstr, slav;
String fctx = gEqmFactory.getFecContext();
for( EqmCfg ec : el )
{
if (ec.getName().compareTo(eqmName) == 0)
{
LinkedList<PropertyCfg> pl = ec.getPropertyList();
for (PropertyCfg pc : pl)
{
TExportProperty xp = new TExportProperty(
pc.getId().getValue(),pc.getName(),pc.getDescription(),
pc.getSizeOut().getValue(),(short)pc.getDTypeOut().getValue(),pc.getDTagOut(),
pc.getSizeIn().getValue(),(short)pc.getDTypeIn().getValue(),pc.getDTagIn(),
(short)pc.getAccess().getValue());
if (pc.getDeadband().getValue() > 0)
xp.setAccessDeadband(pc.getDeadband().getValue());
xp.getDescription().setArrayType((short)pc.getDArrayTypeOut());
max = pc.getXmax().getValue();
min = pc.getXmin().getValue();
if (min > max) TFecLog.log(eqmName,"x min > x max for property "+pc.getName());
xp.getDescription().setXRange(new TPropertyEGU(pc.getXEgu(),min,max));
max = pc.getMax().getValue();
min = pc.getMin().getValue();
if (min > max) TFecLog.log(eqmName,"min > max for property "+pc.getName());
xp.getDescription().setYRange(new TPropertyEGU(pc.getEgu(),min,max));
// TODO:
//expp.getDescription().setArrayNumRows(pc.getNumRows().getValue());
xp.getDescription().setRedirection(pc.getRedirection());
xp.hasExclusiveRead = pc.hasExclusiveRead;
xp.hasUnlockedExclusiveRead = pc.hasUnlockedExclusiveRead;
xp.isEnforceOutput = pc.isEnforceOutput;
registerProperty(xp,null);
dv = pc.getDevices();
if (dv != null && dv.size() > 0)
{
int nr = 0;
ArrayList<String> lst = new ArrayList<String>(dv.size());
for (String d : dv)
{
lst.add(nr++,d);
}
xp.setDeviceList(lst);
getDeviceList().setPropertyOriented(true);
}
}
grp = ec.getGroup();
if (grp != null && grp.length() > 0)
{
setGroupName(grp);
if (ec.getGroupIndex().isValid())
setGroupIndex(ec.getGroupIndex().getValue());
setGroupDevicePrefix(ec.getGroupDevicePrefix());
setGroupDevicePostfix(ec.getGroupDevicePostfix());
}
exp = ec.getServer();
if (exp != null && exp.length() > 0) setExportName(exp);
ctx = ec.getContext();
if (ctx == null || ctx.length() == 0)
{ // not specified for the eqm : use the default
ctx = cfg.getContext();
if (ctx == null || ctx.length() == 0) ctx = fctx; // hope for the best
}
if (fctx == null || fctx.length() == 0)
{ // make sure this is set
gEqmFactory.setFecContext(ctx);
fctx = ctx;
}
if (ctx != null && ctx.length() > 0) setContext(ctx);
sub = ec.getSubsystem();
if (sub == null || sub.length() == 0)
{ // not specified for the eqm : use the default
sub = cfg.getSubsystem();
}
if (sub != null && sub.length() > 0) setSubsystem(sub);
mstr = ec.getMaster();
if (mstr != null && mstr.length() > 0)
{
setMaster(mstr);
slav = ec.getSlaveMaster();
if (slav != null && slav.length() > 0) setSlaveMaster(mstr, slav);
}
break;
}
}
return 0;
}
// no fec.xml : look for exports.csv ...
TInitializer initializer = TInitializerFactory.getInstance().getInitializer();
// register the csv database structure:
csvColumn[] expCols = new csvColumn[26];
expRowHndlr expRows = new expRowHndlr(getLocalName());
expCols[0] = new csvColumn("EXPORT_NAME","",new expXnHndlr(expRows));
expCols[1] = new csvColumn("LOCAL_NAME","",new expLnHndlr(expRows,getLocalName()));
expCols[2] = new csvColumn("PROPERTY","",new expPrpHndlr(expRows));
expCols[3] = new csvColumn("DESCRIPTION","",new expPrpDescHndlr(expRows));
expCols[4] = new csvColumn("PROPERTY_SIZE","",new expPrpSizeHndlr(expRows));
expCols[5] = new csvColumn("FORMAT","",new expPrpFmtHndlr(expRows));
expCols[6] = new csvColumn("PROPERTY_INSIZE","",new expPrpInSizeHndlr(expRows));
expCols[7] = new csvColumn("INFORMAT","",new expPrpInFmtHndlr(expRows));
expCols[8] = new csvColumn("PROPERTY_ID","",new expPrpIdHndlr(expRows));
expCols[9] = new csvColumn("ACCESS","READ",new expPrpAccessHndlr(expRows));
expCols[10] = new csvColumn("REDIRECTION","",new expPrpRdrHndlr(expRows));
expCols[11] = new csvColumn("GROUP","",new expGrpHndlr());
expCols[12] = new csvColumn("GROUP_INDEX","",new expGrpIdxHndlr());
expCols[12] = new csvColumn("GROUP_DEVICE_PREFIX","",new expGrpPrefixHndlr());
expCols[13] = new csvColumn("GROUP_DEVICE_POSTFIX","",new expGrpPostfixHndlr());
expCols[14] = new csvColumn("CONTEXT","",new expCtxHndlr());
expCols[15] = new csvColumn("SUBSYSTEM","",new expCtxHndlr());
expCols[16] = new csvColumn("MASTER","",new expMstrHndlr());
expCols[17] = new csvColumn("SLAVE_MASTER","",new expSlavHndlr());
expCols[18] = new csvColumn("NUM_DEVICES","",new expNumDevsHndlr(expRows));
expCols[19] = new csvColumn("MAX_VALUE","0",new expMaxValueHndlr(expRows,false));
expCols[20] = new csvColumn("MIN_VALUE","0",new expMinValueHndlr(expRows,false));
expCols[21] = new csvColumn("UNITS","",new expUnitsHndlr(expRows,false));
expCols[22] = new csvColumn("XMAX_VALUE","0",new expMaxValueHndlr(expRows,true));
expCols[23] = new csvColumn("XMIN_VALUE","0",new expMinValueHndlr(expRows,true));
expCols[24] = new csvColumn("XUNITS","",new expUnitsHndlr(expRows,true));
expCols[25] = new csvColumn("ACCESS_DEADBAND","",new expDbaHndlr(expRows));
// open it
csv expFile = new csv(initializer.getExportsResource(eqmName));
// read it
int rc = expFile.readFile(expCols,expRows);
// close it
expFile.close();
if (rc != TErrorList.no_such_file)
TFecLog.log("get registered exports and properties from exports.csv : " + TErrorList.errorString[rc]);
return 0;
}
// csv file USERS handlers
class usrNameHndlr implements csvHandler
{
LinkedList<String> usrsLst = null;
public usrNameHndlr(LinkedList<String> lst)
{
usrsLst = lst;
}
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
addRegisteredUser(usrsLst,strValue);
return 0;
}
}
private boolean scanForUsersCalled = false;
private boolean scanForUsers = false;
private boolean scanForNetsCalled = false;
private boolean scanForNets = false;
public boolean scanForUsersFiles()
{
if (scanForUsersCalled) return scanForUsers;
String fh = TInitializerFactory.getInstance().getInitializer().getFecHome();
File dir = new File(fh);
if (dir != null && dir.list() != null)
{
for (String f : dir.list())
{
if (f.endsWith("-users.csv"))
{
scanForUsers = true;
break;
}
}
}
if (!scanForUsers)
{
dir = new File(fh+File.separator+moduleName);
if (dir != null && dir.list() != null)
{
for (String f : dir.list())
{
if (f.endsWith("-users.csv"))
{
scanForUsers = true;
break;
}
}
}
}
scanForUsersCalled = true;
return scanForUsers;
}
public boolean scanForNetsFiles()
{
if (scanForNetsCalled) return scanForNets;
String fh = TInitializerFactory.getInstance().getInitializer().getFecHome();
File dir = new File(fh);
if (dir != null && dir.list() != null)
{
for (String f : dir.list())
{
if (f.endsWith("-ipnets.csv"))
{
scanForNets = true;
break;
}
}
}
if (!scanForNets)
{
dir = new File(fh+File.separator+moduleName);
if (dir != null && dir.list() != null)
{
for (String f : dir.list())
{
if (f.endsWith("-ipnets.csv"))
{
scanForNets = true;
break;
}
}
}
}
scanForNetsCalled = true;
return scanForNets;
}
public void addGroupToACL(String grp)
{
if (gEqmFactory.gKnownGroupsList.containsKey(grp)) return;
ACLGroup g = new ACLGroup();
if (getRegisteredGroupMembersFromFile(g.members, grp))
{
gEqmFactory.gKnownGroupsList.put(grp, g);
}
}
public boolean getRegisteredStringSetFromXml(LinkedList<String> lst,String set,String prp,String dev)
{
FecCfg cfg = gEqmFactory.getFecXmlCfg();
String eqmName = getLocalName();
if (cfg == null) return false;
LinkedList<EqmCfg> el = cfg.getEqmList();
if (el == null) return false;
for( EqmCfg ec : el )
{ // run thru the list
if (ec.getName().compareTo(eqmName) == 0)
{ // found the right EQM
if (dev != null && dev.length() > 0)
{ // device specified
LinkedList<DeviceCfg> dl = ec.getDeviceList();
for (DeviceCfg dc : dl)
{ // find the device
if (dc.getName().compareToIgnoreCase(dev) != 0) continue;
LinkedList<NameCfgList> nl = dc.getNameCfgList();
for (NameCfgList nc : nl)
{ // look for users tag
if (nc.getName().compareToIgnoreCase(set) == 0)
{ // assign the names list
lst.addAll(nc.getMembers());
return true;
}
}
}
return false;
}
if (prp != null && prp.length() > 0)
{ // device specified
LinkedList<PropertyCfg> pl = ec.getPropertyList();
for (PropertyCfg pc : pl)
{ // find the device
if (pc.getName().compareToIgnoreCase(prp) != 0) continue;
LinkedList<NameCfgList> nl = pc.getNameCfgList();
for (NameCfgList nc : nl)
{ // look for users tag
if (nc.getName().compareToIgnoreCase(set) == 0)
{ // assign the names list
lst.addAll(nc.getMembers());
return true;
}
}
}
return false;
}
LinkedList<NameCfgList> nl = ec.getNameCfgList();
for (NameCfgList nc : nl)
{ // yes ! find it
if (nc.getName().compareToIgnoreCase(set) == 0)
{ // assign the names list
lst.addAll(nc.getMembers());
return true;
}
}
return false;
}
}
return false;
}
public boolean getRegisteredUsersFromCsv(LinkedList<String> usrsLst,LinkedList<String> grpsLst,String tag)
{
if (tag != null && tag.length() > 0 && !scanForUsersFiles()) return false;
TInitializer initializer = TInitializerFactory.getInstance().getInitializer();
// register the csv database structure:
csvColumn[] usrCols = new csvColumn[1];
//usrRowHndlr usrRows = new usrRowHndlr(getLocalName());
usrCols[0] = new csvColumn("USER_NAME","",new usrNameHndlr(usrsLst));
// open it
csv usrFile = new csv(initializer.getUsersResource(moduleName,tag));
// read it
int rc = usrFile.readFile(usrCols);
// close it
usrFile.close();
if (rc == 0) return true;
if (rc != TErrorList.no_such_file)
{
if (tag == null) tag = getLocalName();
TFecLog.log("get registered users for "+tag+" from users.csv : " + TErrorList.errorString[rc]);
}
return false;
}
public boolean getRegisteredUsersFromFile(LinkedList<String> usrsLst,LinkedList<String> grpsLst,String prp,String dev)
{
boolean rc = false;
String tag = prp != null ? prp : dev;
String fnam;
if (gEqmFactory.getFecXmlCfg() != null)
{
rc = getRegisteredStringSetFromXml(usrsLst,"USERS_ALLOWED",prp,dev);
fnam = "fec.xml";
}
else
{
rc = getRegisteredUsersFromCsv(usrsLst,grpsLst,tag);
fnam = "users.csv";
}
if (tag == null) tag = getLocalName();
if (rc && usrsLst != null)
{
TFecLog.log("get registered users for "+tag+" from "+fnam);
Iterator<String> it = usrsLst.iterator();
String u;
String fn =
TInitializerFactory.getInstance().getInitializer().getFecHome() +
File.separator + moduleName;
while (it.hasNext())
{
u = it.next();
if (u.startsWith("<"))
{ // a group !
int p1 = u.indexOf(':');
int p2 = u.indexOf('>');
if (p1 < 0)
{ // not found -> then start at '<'
p1 = 0;
}
else
{ // call external process to dump the members to file
try
{
String cmdstr = "group2csv "+u.subSequence(1, p2)+" "+fn;
Runtime rt = Runtime.getRuntime();
Process rtp = rt.exec(cmdstr);
rtp.waitFor();
}
catch (Exception ignore) {}; // we did our best ...
}
if (p2 < 0) p2 = u.length();
u = u.substring(p1+1,p2); // ignore the source for now
if (u != null && u.length() > 0)
{
addGroupToACL(u);
if (grpsLst != null) grpsLst.add(u);
}
it.remove(); // not a 'user'
}
}
}
return rc;
}
/**
* @deprecated
* @param usrsLst
* @param tag
* @return
*/
public boolean getRegisteredUsersFromFile(LinkedList<String> usrsLst,String tag)
{
return false;
}
/**
* @deprecated
* @param usrsLst
* @param grpsLst
* @param tag
* @return
*/
public boolean getRegisteredUsersFromFile(LinkedList<String> usrsLst,LinkedList<String> grpsLst,String tag)
{
return false;
}
public boolean getRegisteredGroupMembersFromFile(LinkedList<String> grpsLst,String grp)
{
if (grp == null || grp.length()== 0) return false;
TInitializer initializer = TInitializerFactory.getInstance().getInitializer();
// register the csv database structure:
csvColumn[] usrCols = new csvColumn[1];
//usrRowHndlr usrRows = new usrRowHndlr(getLocalName());
usrCols[0] = new csvColumn("USER_NAME","",new usrNameHndlr(grpsLst));
// open it
csv grpFile = new csv(initializer.getGroupsResource(moduleName,grp));
// read it
int rc = grpFile.readFile(usrCols);
// close it
grpFile.close();
if (rc == 0) return true;
if (rc != TErrorList.no_such_file)
TFecLog.log("get registered groups from users.csv : " + TErrorList.errorString[rc]);
return false;
}
// csv file IPNETS handlers
class subnetNameHndlr implements csvHandler
{
LinkedList<String> netLst = null;
public subnetNameHndlr(LinkedList<String> lst)
{
netLst = lst;
}
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
addRegisteredNet(netLst,strValue);
return 0;
}
}
/**
* @deprecated
* @param lst
* @param tag
* @return
*/
public boolean getRegisteredNetsFromFile(LinkedList<String> lst,String tag)
{
return getRegisteredNetsFromCsvFile(lst,tag);
}
public boolean getRegisteredNetsFromCsvFile(LinkedList<String> lst,String tag)
{
if (tag != null && tag.length() > 0 && !scanForNetsFiles()) return false;
TInitializer initializer = TInitializerFactory.getInstance().getInitializer();
// register the csv database structure:
csvColumn[] netsCols = new csvColumn[1];
//usrRowHndlr usrRows = new usrRowHndlr(getLocalName());
netsCols[0] = new csvColumn("SUBNET","",new subnetNameHndlr(lst));
// open it
csv netsFile = new csv(initializer.getNetsResource(moduleName,tag));
// read it
int rc = netsFile.readFile(netsCols);
// close it
netsFile.close();
if (rc == 0) return true;
if (rc != TErrorList.no_such_file)
{
if (tag == null) tag = moduleName;
TFecLog.log("get registered ip nets for "+tag+" from ipnets.csv : " + TErrorList.errorString[rc]);
}
return false;
}
public boolean getRegisteredNetsFromFile(LinkedList<String> lst,String prp,String dev)
{
boolean rc = false;
String tag = prp != null ? prp : dev;
String fnam;
if (gEqmFactory.getFecXmlCfg() != null)
{
rc = getRegisteredStringSetFromXml(lst,"NETS_ALLOWED",prp,dev);
fnam = "fec.xml";
}
else
{
rc = getRegisteredNetsFromCsvFile(lst,tag);
fnam = "users.csv";
}
if (tag == null) tag = getLocalName();
if (rc) TFecLog.log("get registered users for "+tag+" from "+fnam);
return rc;
}
// csv file <EQM>-alarms handlers:
class almDefRowHndlr implements RowHandler
{ // the Row Handler will be called when all columns have been read in
private TAlarmDefinition adef;
public String tag; // 16 char
public int code; // 4 bytes
public int mask; // 4 bytes
public short severity; // 2 bytes;
public short dataFormat; // 1 byte
public int dataSize; // 1 byte
public String text; // 40 chars
public String deviceText; // 38 chars
public int system; // 2 bytes;
public String dataText; // 40 chars
public String url; // 40 chars
public TAlarmDefinition getAlarmDefinition() { return adef; }
almDefRowHndlr()
{
tag = "";
text = "";
deviceText = "";
dataText = "";
url = "";
}
public int process(int index)
{
// make a new one
adef = new TAlarmDefinition(tag,text,deviceText,code,severity,system,
mask,dataFormat,dataSize,dataText,url);
// add this to the list
addAlarmDefinition(code,adef);
return 0;
}
}
public int getRegisteredAlarmDefinitionsFromFile()
{
FecCfg cfg = gEqmFactory.getFecXmlCfg();
String eqmName = getLocalName();
if (cfg != null)
{ // has parsed a fec.xml config file ...
LinkedList<EqmCfg> el = cfg.getEqmList();
for( EqmCfg ec : el )
{
if (ec.getName().compareTo(eqmName) == 0)
{
LinkedList<AlarmDefinitionCfg> al = ec.getAlarmDefinitions();
for (AlarmDefinitionCfg ac : al)
{
addAlarmDefinition(ac.getAlarmCode().getValue(),
new TAlarmDefinition(ac.getTag(),ac.getAlarmText(),ac.getDataText(),ac.getAlarmCode().getValue(),ac.getSeverity().getValue(),ac.getAlarmSystem().getValue()));
}
break;
}
}
return 0;
}
// no fec.xml : look for alarms.csv ...
TInitializer initializer = TInitializerFactory.getInstance().getInitializer();
// register the csv database structure:
csvColumn[] almCols = new csvColumn[11];
almDefRowHndlr almRows = new almDefRowHndlr();
almCols[0] = new csvColumn("ALARM_TAG","",new StringFieldHandler(almRows,"tag"));
almCols[1] = new csvColumn("ALARM_CODE","",new IntFieldHandler(almRows,"code"));
almCols[2] = new csvColumn("ALARM_MASK","",new IntFieldHandler(almRows,"mask"));
almCols[3] = new csvColumn("SEVERITY","",new ShortFieldHandler(almRows,"severity"));
almCols[4] = new csvColumn("DATA_FORMAT","",new FormatFieldHandler(almRows,"dataFormat"));
almCols[5] = new csvColumn("DATA_ARRAYSIZE","",new IntFieldHandler(almRows,"dataSize"));
almCols[6] = new csvColumn("ALARM_TEXT","READ",new StringFieldHandler(almRows,"text"));
almCols[7] = new csvColumn("DEVICE_TEXT","",new StringFieldHandler(almRows,"deviceText"));
almCols[8] = new csvColumn("DATA_TEXT","",new StringFieldHandler(almRows,"dataText"));
almCols[9] = new csvColumn("URL","",new StringFieldHandler(almRows,"url"));
almCols[10] = new csvColumn("ALARM_SYSTEM","",new IntFieldHandler(almRows,"system"));
// open it
csv almDefsFile = new csv(initializer.getAlmDefinitionResource(getLocalName()));
// read it
int rc = almDefsFile.readFile(almCols,almRows);
// close it
almDefsFile.close();
if (rc != TErrorList.no_such_file)
TFecLog.log("get alarm definitions from " + getLocalName() + "/alarms.csv : " + TErrorList.errorString[rc]);
return 0;
}
// csv file <EQM>-devices.csv and <property>-names.csv handlers:
class devNameRowHndlr implements RowHandler
{ // the Row Handler will be called when all columns have been read in
public String deviceName;
public String deviceNameAlt;
public int deviceNumber;
public int deviceNumberAlt;
public int deviceMask;
public int deviceOffline;
public float deviceZPosition;
private boolean isPrpOriented = false;
public String deviceRedirection;
public String deviceDescription;
public String deviceLocation;
private TExportProperty prp = null;
public String prpListFile = null;
devNameRowHndlr()
{
deviceNumber = 0;
deviceName = "#0";
}
devNameRowHndlr(TExportProperty property)
{
deviceNumber = 0;
deviceName = "#0";
deviceRedirection = null;
deviceDescription = null;
prp = property;
isPrpOriented = prp == null ? false : true;
}
public int process(int index)
{
TDeviceList dlst = getDeviceList();
if (dlst == null) return TErrorList.device_not_connected;
int ndevs = dlst.getNumberOfDevices();
if (ndevs == 0) return TErrorList.device_not_connected;
if (deviceNumber < 0 && deviceNumber >= ndevs) return TErrorList.illegal_equipment_number;
if (!isPrpOriented)
{
TDevice tdv = dlst.getDevice(deviceNumber);
if (tdv == null) return TErrorList.device_not_connected;
String oldName = tdv.getName();
if (deviceName.compareTo(oldName) != 0)
{
dlst.renameDevice(oldName,deviceName);
}
if (deviceRedirection != null && deviceRedirection.length() > 0)
{
tdv.setRedirection(deviceRedirection);
deviceRedirection = null; // reset this !
}
if (deviceDescription != null && deviceDescription.length() > 0)
{
tdv.setDescription(deviceDescription);
deviceDescription = null; // reset this !
}
if (prpListFile != null && prpListFile.length() > 0)
{
getRegisteredPropertyListFromFile(tdv,prpListFile);
propertyList.setDeviceOriented(true);
prpListFile = null; // reset this !
}
if (deviceLocation != null && deviceLocation.length() > 0)
{
tdv.setLocation(deviceLocation);
}
if (deviceMask != 0) tdv.setMask(deviceMask);
if (deviceOffline != 0) tdv.setOffline(true);
if (deviceZPosition != 0) tdv.setZposition(deviceZPosition);
}
else
{
if (prp != null)
{
int prplen = prp.getOutputSize();
ArrayList<String> lst = prp.getDeviceList();
if (lst == null)
{
lst = new ArrayList<String>(prplen);
prp.setDeviceList(lst);
}
if (deviceName.length() == 0)
{
deviceName = deviceNameAlt;
if (deviceNumber == 0) deviceNumber = deviceNumberAlt;
}
if (deviceNumber < prplen) lst.add(deviceNumber,deviceName);
dlst.setPropertyOriented(true);
}
}
return 0;
}
}
public int getRegisteredDevicesFromFile()
{
FecCfg cfg = gEqmFactory.getFecXmlCfg();
String eqmName = getLocalName();
if (cfg != null)
{ // has parsed a fec.xml config file ...
LinkedList<EqmCfg> el = cfg.getEqmList();
String deviceRedirection;
String deviceDescription;
String prpSet;
for( EqmCfg ec : el )
{
if (ec.getName().compareTo(eqmName) == 0)
{
LinkedList<NameCfgList> nl = ec.getNameCfgList();
TDeviceList dlst = getDeviceList();
if (dlst == null) return TErrorList.device_not_connected;
int ndevs = dlst.getNumberOfDevices();
if (ndevs == 0) return TErrorList.device_not_connected;
LinkedList<DeviceCfg> dl = ec.getDeviceList();
for (DeviceCfg dc : dl)
{
TDevice tdv = dlst.getDevice(dc.getNumber().getValue());
if (tdv == null) return TErrorList.device_not_connected;
prpSet = dc.getPropertySet();
if (prpSet != null && prpSet.length() > 0)
{ // is there a device-specific property list ?
for (NameCfgList nc : nl)
{ // yes ! find it
if (nc.getName().compareToIgnoreCase(prpSet) == 0)
{ // assign the names list
tdv.setPropertyList(nc.getMembers());
}
}
propertyList.setDeviceOriented(true);
}
String oldName = tdv.getName();
if (dc.getName().compareTo(oldName) != 0)
{
dlst.renameDevice(oldName,dc.getName());
}
deviceRedirection = dc.getRedirection();
if (deviceRedirection != null && deviceRedirection.length() > 0)
{
tdv.setRedirection(deviceRedirection);
deviceRedirection = null; // reset this !
}
deviceDescription = dc.getDescription();
if (deviceDescription != null && deviceDescription.length() > 0)
{
tdv.setDescription(deviceDescription);
deviceDescription = null; // reset this !
}
}
break;
}
}
return 0;
}
// no fec.xml : look for devices.csv ...
TInitializer initializer = TInitializerFactory.getInstance().getInitializer();
csv devNamesFile = new csv(initializer.getDevicesResource(getLocalName()));
int rc = devNamesFile == null ?
TErrorList.file_error :
getRegisteredDevicesFromFile(devNamesFile,new devNameRowHndlr());
if (rc != TErrorList.no_such_file)
TFecLog.log("get device names from " + getLocalName() + "-devices.csv : " + TErrorList.errorString[rc]);
return rc;
}
public int getRegisteredNamesFromPropertyFile(String propertyName)
{
TInitializer initializer = TInitializerFactory.getInstance().getInitializer();
TExportProperty prp = propertyList.getFirstProperty(propertyName);
String devFileName = propertyName + "-names.csv";
csv devNamesFile = new csv(initializer.getFecHome()+File.separator+getLocalName()+File.separator+devFileName);
int rc = devNamesFile == null ?
TErrorList.file_error :
getRegisteredDevicesFromFile(devNamesFile,new devNameRowHndlr(prp));
if (rc == TErrorList.no_such_file)
{
devNamesFile = new csv(initializer.getFecHome()+File.separator+devFileName);
rc = devNamesFile == null ?
TErrorList.file_error :
getRegisteredDevicesFromFile(devNamesFile,new devNameRowHndlr(prp));
}
if (rc != TErrorList.no_such_file)
TFecLog.log("get device names from " + devFileName + " : " + TErrorList.errorString[rc]);
return rc;
}
public int getRegisteredDevicesFromFile(csv csvFile,devNameRowHndlr devRows)
{
// register the csv database structure:
csvColumn[] devCols = new csvColumn[11];
devCols[0] = new csvColumn("DEVICE_NUMBER","",new IntFieldHandler(devRows,"deviceNumber"));
devCols[1] = new csvColumn("DEVICE_NAME","",new StringFieldHandler(devRows,"deviceName"));
devCols[2] = new csvColumn("MODULE_NUMBER","",new IntFieldHandler(devRows,"deviceNumberAlt")); // alias for DEVICE_NAME
devCols[3] = new csvColumn("MODULE_NAME","",new StringFieldHandler(devRows,"deviceNameAlt"));
devCols[4] = new csvColumn("REDIRECTION","",new StringFieldHandler(devRows,"deviceRedirection"));
devCols[5] = new csvColumn("PROPERTY_LIST","",new StringFieldHandler(devRows,"prpListFile"));
devCols[6] = new csvColumn("DEVICE_DESCRIPTION","",new StringFieldHandler(devRows,"deviceDescription"));
devCols[7] = new csvColumn("DEVICE_LOCATION","",new StringFieldHandler(devRows,"deviceLocation"));
devCols[8] = new csvColumn("DEVICE_MASK","0",new IntFieldHandler(devRows,"deviceMask"));
devCols[9] = new csvColumn("DEVICE_OFFLINE","0",new IntFieldHandler(devRows,"deviceOffline"));
devCols[10] = new csvColumn("DEVICE_ZPOS","0",new FloatFieldHandler(devRows,"deviceZPosition"));
// read the file
int rc = csvFile.readFile(devCols,devRows);
// close it
csvFile.close();
return rc;
}
class devPrpLstHndlr implements csvHandler
{
protected LinkedList<String> prpLst = null;
public int process(String strValue,int index)
{
if (strValue == null || strValue.length() == 0) return 0;
if (prpLst == null) prpLst = new LinkedList<String>();
prpLst.add(strValue);
return 0;
}
}
public int getRegisteredPropertyListFromFile(TDevice device, String filename)
{
TInitializer initializer = TInitializerFactory.getInstance().getInitializer();
String fn = initializer.getFecHome();
csv csvFile = null;
if (moduleName != null) csvFile = new csv(fn+File.separator+moduleName+File.separator+filename);
if (csvFile == null || !csvFile.fileAvailable())
csvFile = new csv(fn+File.separator+filename);
devPrpLstHndlr namhdlr = new devPrpLstHndlr();
csvColumn[] devCols = new csvColumn[1];
devCols[0] = new csvColumn("PROPERTY_NAME","",namhdlr);
// read the file
int rc = csvFile.readFile(devCols,null);
// close it
csvFile.close();
if (rc == 0) device.setPropertyList(namhdlr.prpLst);
return rc;
}
public boolean isDeviceSetLocal(String devName, String propertyName)
{
TExportProperty prp = propertyList.getFirstProperty(propertyName);
WildcardMatch wc = new WildcardMatch(devName);
String tgt;
TDevice[] dlst = getDeviceList().getDeviceList();
for (int i=0; i<dlst.length; i++)
{
if ((tgt=dlst[i].getRedirection()) != null)
{
if (wc.matches(tgt)) return false;
}
}
if ((tgt=prp.getDescription().getRedirection()) != null)
{
if (wc.matches(tgt)) return false;
}
return true; /* appears to be local so-far */
}
public String getSubsystem()
{
return subsystem;
}
/**
* Sets the subsystem to which the device server should belong
*
* @param subsystem is the desired subsystem.
*/
public void setSubsystem(String subsystem)
{
TStrings.validateSubSystemName(subsystem);
this.subsystem = subsystem;
}
/**
* An equipment module can schedule a property or set of properties for immediate
* execution and delivery
*
* @param devPropertyList A single string argument containing one or more
* properties to be scheduled for immediate execution. This should be a
* single string. If more than one property is to be scheduled, then the
* property list string should be a set of properties separated by commas or
* blanks
*
*
* @author duval
*/
public int scheduleProperty(String devPropertyList)
{
if (devPropertyList == null) return TErrorList.argument_list_error;
String[] prps = null;
String tok = " "; // try a space first
if (!devPropertyList.contains(tok)) tok = ";";
if (!devPropertyList.contains(tok)) tok = ",";
if ((prps = devPropertyList.split(tok)) == null) return TErrorList.code_failure;
for (int i=0; i<prps.length; i++)
{
if (propertyList.hasProperty(prps[i])) gEqmFactory.systemScheduleProperty(this,prps[i].trim());
}
return 0;
}
/**
* Sends (schedules) a 'reset_mca_property' signal to any listening client
*
* A server with registered multi-channel array properties can inform any attached
* clients that the mutli-channel array configuration has changed (e.g. array elements
* have been added, removed, or otherwise edited) by using this call.
* Any listening clients with multi-channel array links will then return to the original
* client startup conditions and 're-learn' the new array indexing now in place.
*
* @param devPropertyList is (comma separated) list of properties which are to be reset at the client
* side.
*
* \note This routine will call scheduleProperty() to assure immediate notification
* at the client side.
*
* @return 0 upon success, otherwise a TINE return code.
*/
public int resetMultiChannelProperty(String devPropertyList)
{
if (devPropertyList == null) return TErrorList.argument_list_error;
String[] prps = null;
String tok = " "; // try a space first
if (!devPropertyList.contains(tok)) tok = ";";
if (!devPropertyList.contains(tok)) tok = ",";
if ((prps = devPropertyList.split(tok)) == null) return TErrorList.code_failure;
LinkedList<TExportProperty> plst;
Iterator<TExportProperty> it;
long ts = System.currentTimeMillis();
for (int i=0; i<prps.length; i++)
{
if ((plst=propertyList.getEqualProperties(prps[i].trim())) == null) break;
it = plst.iterator();
while (it.hasNext()) it.next().setMcaValidFloor(ts);
}
TEquipmentModuleFactory.getInstance().flushContractTable();
return 0;
}
ConcurrentLinkedQueue<TEquipmentBackgroundTask> bkgTasks = new ConcurrentLinkedQueue<TEquipmentBackgroundTask>();
public int addEquipmentBackgroundTask(TEquipmentBackgroundTask tbkg)
{
if (tbkg == null) return TErrorList.invalid_parameter;
bkgTasks.add(tbkg);
return getEquipmentModuleFactory().addEquipmentBackgroundTask(tbkg);
}
private void assignContextAndSubsystem()
{
TEquipmentModuleFactory f = getEquipmentModuleFactory();
if (context == null || context.length() == 0)
{ // fill this in if it hasn't been set ...
context = f.getFecContext();
}
String subsys = System.getenv(getLocalName()+"_SUBSYSTEM");
if (subsys != null && subsys.length() > 0) subsystem = subsys;
if (subsystem == null || subsystem.length() == 0)
{ // fill this in if it hasn't been set ...
subsystem = f.getFecSubsystem();
}
}
public int startup()
{
int rc = 0;
getRegisteredDevicesFromFile();
assignContextAndSubsystem();
clearCASAlarmList();
if (getInitializationRoutine() != null)
{
try
{
rc = getInitializationRoutine().initialize();
TFecLog.log(getLocalName()+" initialization routine called : "+TErrorList.getErrorString(rc));
}
catch (Exception e)
{
TFecLog.log(getLocalName()+" initialization routine called : unhandled exception "+e.toString());
}
}
// is there a general alarm watch file ?
gEqmFactory.getAlarmWatchListFromFile(getLocalName());
// is there a local history file ?
gEqmFactory.getHistoryListFromFile(getLocalName());
return rc;
}
public int shutdown()
{
int rc = 0;
if (!hasInitialized) return TErrorList.not_initialized;
hasInitialized = false;
if (getExitRoutine() != null)
{ // there is a registered exit routine !
try
{
rc = getExitRoutine().terminate();
TFecLog.log(getLocalName()+" exit routined called : "+TErrorList.getErrorString(rc));
}
catch (Exception e)
{
TFecLog.log(getLocalName()+" exit routined called : unhandled exception "+e.toString());
}
}
alarmDefinitionList.clear();
removeAllGCastNets();
removeAllRegisteredNets();
removeAllRegisteredUsers();
return rc;
}
/**
* Registers a cycle trigger callback dispatch function
*
* If a CYCLER is running in a server's context, then the server will receive 'Cycle Number' events
* scheduled by the designated CYCLER server.
* The cycle number will make use of the 'System Data Stamp' to tag all data sets obtained from the
* server. A server can also register a trigger function dispatch routine (or routines) to be called when a 'Cycle
* Number' event occurs. The dispatch routines will be called prior to setting the 'System Stamp' to the new
* Cycle Number, which will be set following the execution of all dispatch routines. Optionally, the server can
* provide a property (or list of properties) to be scheduled following the dispatch execution. This will ensure
* that such properties will be called immediately following dispatch execution AND contain the most recent Cycle Number
* as the 'System Data Stamp'.
*
* @param trigger is a reference to the dispatch handler to be called when a new cycle number arrives.
*
* @return 0 upon success or TErrorList.already_assigned
*
* \b Example:
* @include eg_cycleTrigger.java
*/
public int registerCycleTrigger(TCycleTrigger trigger)
{
return getEquipmentModuleFactory().registerCycleTrigger(trigger);
}
/**
* Sets the trigger cycler key to the value given
*
* By default a CYCLER is a server called "CYCLER" in the same context as the
* initializing device server and produces a keyword (property) called
* "CycleNumber". This gives rise to the Cycle Key:
* "/\<context\>/CYCLER/CycleNumber". If it is known a priori, that the
* CYCLER exists in another context or uses another server name or property
* name, the cycle key can be set via this API call or via environment
* (set TINE_CYCLE_KEY=\<key\>).
*
* @param key is the desired CYCLER trigger key
*
* @see registerCycleTrigger
*/
public void setCycleNumberKey(String key)
{
getEquipmentModuleFactory().setCyclerNumberKey(key);
}
/**
* Gets the trigger cycler key
*
* By default a CYCLER is a server called "CYCLER" in the same context as the
* initializing device server and produces a keyword (property) called
* "CycleNumber". This gives rise to the Cycle Key:
* "/\<context\>/CYCLER/CycleNumber". This default value can also be
* set via the environment (set TINE_CYCLE_KEY) or via API.
*
* @return the current setting of the cycler trigger key.
*
* @see setCycleNumberKey, registerCycleTrigger
*/
public String getCycleNumberKey()
{
return getEquipmentModuleFactory().getCycleNumberKey();
}
/**
* Unregisters a previously registered cycle trigger callback dispatch function
*
* If a cycle trigger event dispatch routine is no longer required, it can be unregistered using this
* routine.
*
* @param trigger is a reference to the dispatch handler to be removed
*
* @return 0 upon success or return TErrorList.un_allocated
*/
public int unregisterCycleTrigger(TCycleTrigger trigger)
{
return getEquipmentModuleFactory().unregisterCycleTrigger(trigger);
}
private TStateChangeTrigger scTrg = null; // a registered state-change trigger function
/**
* Establishes a state-change trigger callback for this equipment module.
*
* If a GLOBLAS server is running and providing state information, then any
* detected state change will be passed to the callback function provided.
* The callback must implement the TStateChangeTrigger class. It will receive
* both the current state and previous state (as Strings).
*
* @param stateChangeTrigger is a reference to the callback instance.
*/
public void setStateChangeTrigger(TStateChangeTrigger stateChangeTrigger)
{
setStateChangeTrigger(stateChangeTrigger,null);
}
/**
* Establishes a state-change trigger callback for this equipment module.
*
* If a GLOBLAS server is running and providing state information, then any
* detected state change will be passed to the callback function provided.
* The callback must implement the TStateChangeTrigger class. It will receive
* both the current state and previous state (as Strings).
*
* @param stateChangeTrigger is a reference to the callback instance.
* @param stateChangeKey is the GLOBALS keyword providing the declared state
* for the context associated with this equipment module. If 'null' then the
* default keyword "DeclaredState" is assumed.
*/
public void setStateChangeTrigger(TStateChangeTrigger stateChangeTrigger,String stateChangeKey)
{
scTrg = stateChangeTrigger;
if (stateChangeKey != null && stateChangeKey.trim().length() != 0) scKey = stateChangeKey;
if (scTrg != null)
{
registerStateChangeCallback(scTrg);
}
}
public TStateChangeTrigger getStateChangeTrigger() { return scTrg; }
private TStateChange scMonitor = null;
private String scKey = "DeclaredState"; // default key
private int registerStateChangeCallback(TStateChangeTrigger stateChangeTrigger)
{
scMonitor = new TStateChange(getPrimaryContext(),scKey);
return scMonitor == null ? TErrorList.invalid_keyword : scMonitor.getTriggerStatus();
}
}