All TINE servers have the following characteristics, Stock Properties, and Meta Properties:
- Unique Front End Controller Name (FEC) (up to 16 characters in length). As clients must locate the server to which they wish to speak, it is important that no two servers claim to be the same entity. One could argue that in some cases, a certain degree of load-sharing and/or redundancy could be achieved by using two (or more) servers with the same server name. Practically, this is difficult to achieve, as the relevant hardware can usually only be accessed from one station. In cases where it is nonetheless feasible to have different access paths to the same hardware, the server processes in question MUST have different names (such as "SRV1" and "SRV1-BAK"). The acronym FEC is sometimes referred to as a Front End Computer . This would be a complete misnomer in cases where two servers reside on the same computer. In such cases, each much have a unique "FEC" name, even though they are both located on the same front end computer.
- Unique Network Address (IP and/or IPX). It goes without saying that the IP address and IPX address of the server is unique on the network. Servers also listen on a specific UDP port (IP), TCP port (IP) and/or IPX socket (IPX) for requests. This listening port is also a part of the server address and must also be unique. In TINE, this is regulated by assigning offsets to a standard listening port. The default offset is 0. Thus for multi-process operating systems such as UNIX, VMS or Win32, all distinct server processes running on the same physical machine (and hence the same IP and IPX address) must have different port offsets.
- Device Servers. All FEC processes consist of one or more "Device Servers," known internally as "Equipment Modules". Device servers interface to the rest of the control system by encapsulating the hardware (or services) they are controlling by exposing and exporting "Properties" of a device type (piece of equipment). Obtaining for instance the beam positions from a Beam Position Monitor Server might be as easy as asking for the property "POSITIONS" or "ORBIT". Device Server Names are exported as a unique name which can be up to 32 characters in length. In addition, the equipment module has a "local" equipment module name used by the TINE kernel for de-referencing and managment purposes. This 'local' equipment module name is up to 6 characters in length, is hard-coded, and must be unique only within the process. So there can be two distinct device servers exporting device server names "BPM.NORTH" and "BPM.SOUTH" but running the same code, where the local equipment module name "BPMEQM" is hard-coded.
- Plug-and-play functionality. If there is a configured TINE name server, all servers register their server names and addresses upon startup. The name server guarantees that there is only one entry with a given server name. A given server can replace an existing entry only if that entry is no longer active. Specifically, if a server tries to reuse a name already present in the name server's database, the name server queries the old entry to see if it is still active. Only if it does NOT respond to this query, is the server name's address replaced. In generally, this functionality allows "painless" replacement of ethernet cards or migration of servers to other machines, activities which would otherwise involve the updating of a database by hand. Likewise the device server names from a particular server as also registered with the name server upon startup. The same guarantee for uniqueness applies to the equipment function names as well. The counterpart to this plug-and-play scenario is played by TINE clients, which we will come to shortly.
- Exported Properties. The Properties which are exported by a device server are not registered with the control system name server, but instead with the local device server. Properties of a device server are thus queriable from the device server only. Property names can be up to 64 characters in length. Properties MUST be exported (see below) in order to be accessed via other clients on the network.
- Device Names. Device servers make use of device names to identify specific "instances" of a device. A device name can be up to 64 characters in length. In cases where device numbers are preferred, a device name in the manner of "#1" is preferred. The Device names are queriable from the local device server. If no device names are registered, a query simple returns a list of "#1", "#2", etc. for the total number of devices (a quantity which must be registered).
- Synchronization. TINE servers are typically synchronized to the same designated "time" server. On several platforms, this implies an ntp daemon. Optionally, TINE servers can synchronize data timestamps making use of an external TINE time server, which multicasts (or broadcasts) the system time at regular intervals (typically at 1 Hz).
- Local Alarm Server. The TINE alarm system is such that the first layer of collecting, sorting and filtering of alarms takes place at the server level. Thus, there is a local alarm server task which exists on all TINE servers.
- Local History Server. All TINE servers can maintain both long-term and short-term histories of given properties. This can be achieved via a startup configuration file (history.csv or fec.xml) or API call, where the targeted properties are listed, along with long-term and short-term history depths, and filtering rules.
- Multi-tasking. TINE supports some form of multi-tasking on all platforms, including MSDOS. Namely, on single-threaded servers, background tasks registered along with a device server can be suspending or delayed via API call without upsetting other server operations as long as this is done in a cooperative manner. Where threads are available (Win32, POSIX) or VxWorks tasks, the registered background tasks run on individual threads and define a preemptive multi-tasking system.
- Realtime-safe, Thread-safe. The TINE server kernel is realtime-safe and thread-safe when used in realtime and/or multi-threaded environments. As mentioned above, the TINE server kernel works by default out of one thread in one process. Calls made from the client API from different threads are 'trivially' thread-safe in that re-entrancy is blocked (with an error code) if a second thread attempts to call a routine that another thread has called and the call is not completed. Where threads are available, the equipment module access can be configured to run on a separate thread from the TINE engine. This has the benefit of being able to return information to a client (operation busy, for instance) even if the equipment module is blocking access for some reason. In most cases, running equipment module access in a separate thread should be avoided, since it adds unnecessary latency to transactions.
- Security. All TINE servers support both user-specific (soft) and address-specific (hard) security features. This comes into play when server requests with WRITE access are made. If activated, a WRITE request is checked to see if the user making the request is a member of the WRITE-allowed users. Similarly a WRITE request can also be checked to see if the network node from which the WRITE request originated is a member of the WRITE-allowed nodes and networks. Targeted client application can also obtain an 'access lock' to a server, insuring that only the designated application has WRITE access to a server (see the stock property ACCESSLOCK).
- Distributed Initialization Database. TINE does not rely on a central database. Specific database support can be implemented as needed. Server initialization regarding name and address resolution, alarm information, and the like is distributed and server specific. All such information is queriable after-the-fact, and can be reassembled into a central database if desired. The lowest common denominator for a distributed database for all platforms is a standard ASCII CSV (comma separated value) file for the pertinent information.
- Stock Properties. TINE servers allow a variety of information to be queried at any time. Consequently, all TINE servers support and respond to the following standard (or stock) properties:
- "NSTOCKPROPS" (short) returns the number of stock properties for the equipment module specified.
- "STOCKPROPS" Overloaded.
- (NAME64 or NAME32) returns a list of registered properties as a list of NAME32 entities.
- (struct PropertyQueryStruct) returns a list of the stock properties plus calling and descriptive information.
- (struct PropertyQueryStructEx) returns a list of the registered properties plus extensive calling and descriptive information, including engineering units, ranges, history information, etc).
- Calls can take a target property as NAME32 input. The target property can contain wild-card characters '*', in which case only the matching set is returned. Typically, one queries the list of properties via the NAME32 format, and follows this up with a specific query according to the PropertyQueryStructEx type giving a target property as input, in order to obtain all useful information about the target property.
- "NPROPS" (short) returns the number of registered properties for the equipment module specified.
- "NPROPERTIES" identical to "NPROPS".
- "PROPS" Overloaded.
- (NAME64 or NAME32) returns a list of registered properties as a list of NAME64 or NAME32 entities.
- (struct PropertyQueryStruct) returns a list of the registered properties plus calling and descriptive information. A server can optionally register a PropertyQueryFunction (see RegisterPropertyQueryFunction()), which will be called to handle queries of this type. If no such function is registered, it is assumed that all registered properties apply to all devices serviced by the equipment module in question.
- (struct XPropertyQueryStruct) returns a list of the registered properties plus extensive calling and descriptive information, including engineering units, ranges, history information, etc). A server can optionally register a XPropertyQueryFunction (see RegisterXPropertyQueryFunction()), which will be called to handle queries of this type. If no such function is registered, it is assumed that all registered properties apply to all devices serviced by the equipment module in question.
- Calls can take a target property as NAME64 or other text input. The target property can contain wild-card characters '*', in which case only the matching set is returned. Typically, one queries the list of properties via the NAME32 format, and follows this up with a specific query according to the XPropertyQueryStruct type giving a target property as input, in order to obtain all useful information about the target property.
- "PROPERTIES" identical to "PROPS"
- "NDEVICES" (short) returns the number of registered devices for the equipment module specified.
- "DEVICES" (NAME64, NAME32, or NAME16) returns a list of the registered devices. As the caller must ask for a block of 'NAME64's it is advisable to first query "NDEVICES" to ascertain the number of "DEVICES" to query.
- "DEVDESCRIPTION" (NAME64, NAME32) gives a description for the registered device.
- "NHISTORIES" (short) returns the number of registered histories maintained by the local archive server for the equipment module specified.
- "HISTORIES" (NAME64 or NAME32) returns a list of the properties having a local history maintained by the local archive server. As the caller must ask for a block of 'NAME64's it is advisable to first query "NHISTORIES" to ascertain the number of "DEVICES" to query.
- "NALARMS" (long x 5) returns 5 long values giving a snapshot of the current alarm list (see discussion on the Local Alarm Server).
- "ALARMS" (struct AMS) returns a list of the alarms in the local alarm list. (see discussion on the Local Alarm Server).
- "ALARMSEXT" (struct AMS) returns a list of the alarms in the local alarm list. With the extended call, a data input set can specify the range of time stamps and severity of interest (see discussion on the Local Alarm Server).
- "NALARMDEFS" (short) returns the number of alarm definitions maintained by the local alarm server.
- "ALARMDEFS" (struct ADS) returns a list of the alarm definitions maintained by the local alarm server.
- "MESSAGE" (text) accepts a message and displays on the screen. This stock property is not of general use, as server console screens are seldom visible. It's primary usefulness is diagnostic and occurs at startup, where the control system name server can send an "address in use" message to the server.
- "ACTIVITY" (struct AQS) returns the Activity Query Structure containing a snapshot of the current state of the server including the number of current registered contracts and clients, useful for remote diagnostics.
- "CONTRACTS" (struct CONQS) returns the current contract list; useful for remote diagnostics.
- "CLIENTS" (struct CLNQS) returns the current client list; useful for remote diagnostics.
- "CONNECTIONS" (struct CONTBLr4) returns the current connection list; useful for remote diagnostics. Many servers (especially middle layer servers) will themselves have links to other server. This client-side link table is returned in this call.
- "NUSERS" (short) returns the number of registered users with WRITE access.
- "USERS" (NAME16) returns a list of the registered users with WRITE access. As the caller must ask for a block of 'NAME16's it is advisable to first query "NUSERS" to ascertain the number of "USERS" to query.
- "ADDUSER" (input: NAME16 or char) adds the given user to the registered users list and appends the "users.csv" file. The command itself requires WRITE access.
- "DELUSER" (input: NAME16 or char) removes the given user from the registered users list and the "users.csv" file. The command itself requires WRITE access.
- "NIPNETS" (short) returns the number of registered IP subnets with WRITE access.
- "IPNETS" (NAME32) returns a list of the registered IP subnets with WRITE access. As the caller must ask for a block of 'NAME32's it is advisable to first query "NIPNETS" to ascertain the number of "IPNETS" to query.
- "ADDIPNET" (input: NAME32 or char) adds the given ip network to the registered ip nets list and appends the "ipnets.csv" file. The command itself requires WRITE access.
- "DELIPNET" (input: NAME32 or char) removes the given ip network from the registered ip nets list and the "ipnets.csv" file. The command itself requires WRITE access.
- "NIPXNETS" (short) when IPX is supported, returns the number of registered IP subnets with WRITE access.
- "IPXNETS" (NAME16) when IPX is supported, returns a list of the registered IPX subnets with WRITE access. As the caller must ask for a block of 'NAME16's it is advisable to first query "NIPXNETS" to ascertain the number of "IPXNETS" to query.
- "DEBUGLEVEL" (short) sets or reads the current debug level.
- "LOGDEPTH" (short) sets/gives the current depth of the server's log file (if logging has not been turned off).
- "LOGCOMMANDS" (short) sets/reads current value. If non-zero, all incoming WRITE access commands are logged.
- "LOGFILE" (char) returns the current contents of the servers log file. The size of the text requested will be filled with the most recent entries in the server's log file.
- "SRVALIASLIST" (NAME32 list) gets the server alias list (if any) as a list of NAME32 doublets (real name followed by alias name).
- "ADDALIAS" (input: NAME64 array of length 2) adds the name/alias pair to the registered alias list and appends the alias.csv. The command requires WRITE access.
- "SRVOS" (NAME16 or char) returns the Operating System tag of the given server.
- "SRVLOCATION" (NAME32 or char) Returns the server's registered location.
- "SRVDESC" (NAME64) returns the registered server description.
- "SRVSUBSYSTEM" (NAME64) returns the registered server sub-system.
- "SRVINIT" is a WRITE only stock property which causes the server to reinitialize the device server addressed. Scope: device server (i.e. equipment module) accessed.
- "SRVIDLE" is a stock property which can allow the server to enter an 'idle' state. Scope: device server (i.e. equipment module) accessed.
- "SRVEXIT" Requires WRITE access and must be enabled at the server. Causes the server process to terminate. Scope: All device servers attached to the FEC process.
- "SRVRESET" Requires WRITE access and must be enabled at the server. Causes the server process to de-register all equipment modules, return server memory to the heap, and to re-initialize by calling the registered 'PostSystemInit()' routine. Note: to be effective, the PostSystemInit() routine must be registered via the SetPostSystemInitFunction() API call. Also the developer is expected to free any device server specific memory within the registered exit routines. Scope: All device servers attached to the FEC process.
- "SRVLASTACCESS" (NAME32) Returns an array of up to 5 NAME32 objects which contain information concerning the last successful WRITE access command in the following order: User name, User Address, Property accessed, Device name accessed, Timestamp of access. OR (Structure WRACCTBL) returns a list of the most recent (up to 100) WRITE commands issued to the server.
- "SRVCOMMANDS" (struct WRACCTBL) Returns an array of up to 100 of the last WRITE access commands which the server has processed. This property is complementary to "SRVLASTACCESS".
- "SRVSTATS" (long) returns a structured array of longs containing statistical counters maintained at the server.
- "SRVSETTINGS" (long) returns a structure containing the current server (and client) configuration settings.
- "SRVSTARTTIME" (long or char) Returns the server's startup time as a UTC value or a character string.
- "SRVVERSION" (NAME32 or char) returns the TINE Version Number of the given server.
- "SRVCMDLINE" (char) returns the command line used to start the server process.
- "SRVCWD" (char) returns the working directory in force when the server process started.
- "SRVPID" (long) returns the current process id of the server process.
- "STRUCTFORMAT" (input char, output NAME64DBLDBL list) accepts structure tag as input and returns the structure information as (field - size - format code) triplets. Nested fields are prefixed with "<nested structure tag>" indicating that another call to "STRUCTFORMAT" is needed to discover the embedded structure. Routines such as AcquireAndRegisterStruct() make use of this stock property.
- "BITFIELDFORMAT" (input char, output NAME16I list) accepts bitfield tag as input and returns the structure information as (field - bit mask) doublets.
- "ACCESSLOCK" (input: short x 2, output NAME32 x 2) accepts access lock type (UNLOCKED, PRE-EMPTIVE, PERSISTENT, ABORT), and lock duration (in seconds); returns user and network address of the client possessing the current lock. This property can be used to allow one and only one client WRITE privileges to a server for the specified duration.
- Meta Properties. TINE servers allow a variety of property meta information to be queried at any time. Consequently, all TINE servers support and respond to the following meta properties:
- "<property>.EGU" (USTRING) returns the engineering units of the requested property as a USTRING (fval1 is the minimum value, fval2 the maximum, ival is the graph type, and the string gives the units). This can also accept a float format, where the maximum and minumum values are returned, or a char format, where just the engineering units are returned.
- "<property>.XEGU" (USTRING) returns the engineering units for the X-axis of the requested property as a USTRING (fval1 is the minimum value, fval2 the maximum, ival is the graph type, and the string gives the units). This can also accept a float format, where the maximum and minumum values are returned, or a char format, where just the engineering units are returned. Calling this meta property will only give interesting (non-zero) results if the corresponding property is in fact a spectrum array type (i.e. a waveform or trace), where the array contents represent a 'Y vs. X' trace.
- "<property>.HIST" (input: 1 short value or 4 long values or 4 double values; output: float, FLTINT, INTFLTINT, DBLDBL, NAME32I, NAME64DBL) returns the history of the given property in the desired format. Input depends on the return format requested. If an array of simple floats in requested and no input is specified, then the output arraysize is taken as the depth in seconds from the current time. Otherwise, a single short input parameter gives the depth in seconds, and the history data are sampled to fit into the output array, or up to 4 long or double values can be input specifying : starttime, stoptime, trace index, sample flag. Of these four parameters, usually only the first two need to be input (as utc timestamps). Indeed if the second is also absent, then stoptime is taken to be the current time (hence a single long value can also be input). The trace index is only relevant if the history property keeps a trace. The sample flag, if non-zero will force the history lookups to filter the history into time bins appropriate for the specifiec output array length. This is seldom necessary.
- "<property>.HIST@" (input: 1 long or double value; output: stored data type) returns the stored data record at the designated timestamp (or nearest newer). The designated timestamp is the single input variable as a UTC long value or UTC double value.
- "<property>.HST" identical to "<property>.HIST"
- "<property>.ARCH" behaves like a call to "<property>.HIST" but redirects the call to the corresponding channel in the central archiver.
- "<property>.ARCH@" behaves like a call to "<property>.HIST@" but redirects the call to the corresponding channel in the central archiver.
- "<property>.ARC" identical to "<property>.ARCH"
- "<property>.AR" identical to "<property>.ARCH"
- "<property>.DESC" (NAME64, NAME32 or char) Returns the given property's description.
- "<property>.DSC" identical to "<property>.DESC"
- "<property>.NAM" (NAME64 or NAME32) Returns the list of device names associated with the given property. If the property is not overridden by the server developer, then this property will return the same information as a call to "DEVICES", namely a list of the registered devices. Some servers, such as archive servers, gateways, etc. may have completely different device lists according to the property requested. One can systematically handle this situation by additionally registering such "<property>.NAM" properties to handle these types of queries.
- "<property>.BIT.<#>" returns the bit settings (1 or 0) for current value of the given property (applicable only to properties returning integer values - short or long).
- "<property>.MASK.<#>" returns the boolean result (1 or 0) when masking current value of the given property against the given mask (applicable only to properties returning integer values - short or long).
- "<property>.GATE.<#>" returns the gated result when masking current value of the given property against the given mask (applicable only to properties returning integer values - short or long).