pva2pva  1.2.2
QSRV

QSRV Configuration

By default QSRV exposes all Process Variables (fields of process database records). In addition to these "single" PVs are special "group" PVs.

Single PVs

"single" PVs are the same set of names server by the Channel Access server (RSRV). This is all accessible record fields. So all data which is accessible via Channel Access is also accessible via PVAccess.

QSRV presents all "single" PVs as Structures conforming to the Normative Types NTScalar, NTScalarArray, or NTEnum depending on the native DBF field type.

Group PV definitions

A group is defined using a JSON syntax. Groups are defined with respect to a Group Name, which is also the PV name. So unlike records, the "field" of a group have a different meaning. Group field names are not part of the PV name.

A group definition is split among several records. For example of a group including two records is:

record(ai, "rec:X") {
info(Q:group, {
"grp:name": {
"X": {+channel:"VAL"}
}
})
}
record(ai, "rec:Y") {
info(Q:group, {
"grp:name": {
"Y": {+channel:"VAL"}
}
})
}

This group, named "grp:name", has two fields "X" and "Y".

$ pvget grp:name
grp:name
structure
epics:nt/NTScalar:1.0 X
double value 0
alarm_t alarm INVALID DRIVER UDF
time_t timeStamp <undefined> 0
...
epics:nt/NTScalar:1.0 Y
double value 0
alarm_t alarm INVALID DRIVER UDF
time_t timeStamp <undefined> 0
...

Group PV reference

record(...) {
info(Q:group, {
"<group_name>":{
+id:"some/NT:1.0", # top level ID
+meta:"FLD", # map top level alarm/timeStamp
+atomic:true, # whether monitors default to multi-locking atomicity
"<field.name>":{
+type:"scalar", # controls how map VAL mapped onto <field.name>
+channel:"VAL",
+id:"some/NT:1.0",
+trigger:"*", # "*" or comma seperated list of <field.name>s
+putorder:0, # set for fields where put is allowed, processing done in increasing order
}
}
})
}

Field mapping types

The "scalar" mapping places an NTScalar or NTScalarArray as a sub-structure.

The "plain" mapping ignores all meta-data and places only the "value" as a field. The "value" is equivalent to '.value' of the equivalent NTScalar/NTScalarArray as a field.

The "any" mapping places a variant union into which the "value" is placed.

The "meta" mapping ignores the "value" and places only the alarm and time meta-data as sub-fields. The special group level tag 'meta:""' allows these meta-data fields to be placed in the top-level structure.

The "proc" mapping uses neither "value" nor meta-data. Instead the target record is processed during a put.

Field Update Triggers

The field triggers define how changes to the consitutent field are translated into a subscription update to the group.

The most use of these are "" which means that changes to the field are ignored, and do not result group update. And "*" which results in a group update containing the most recent values/meta-data of all fields.

It may be useful to specify a comma seperated list of field names so that changes may partially update the group.

QSRV Timestamp Options

QSRV has the ability to perform certain transformations on the timestamp before transporting it. The mechanism for configuring this is the "Q:time:tag" info() tag.

Nano-seconds least significant bits

Setting "Q:time:tag" to a value of "nsec:lsb:#", where # is a number between 0 and 32, will split the nanoseconds value stored in the associated record. The least significant # bits are stored in the 'timeStamp.userTag' field. While the remaining 32-# bits are stored in 'timeStamp.nanoseconds' (without shifting).

For example, in the following situation 20 bits are split off into userTag. If the nanoseconds part of the record timestamp is 0x12345678, then the PVD structure would include "timeStamp.nanoseconds=0x12300000" and "timeStamp.userTag=0x45678".

record(ai, "...") {
info(Q:time:tag, "nsec:lsb:20")
}

QSRV Display Form Option

The value of the OPI display form hint ('display.form') can be set set with the "Q:form" info() tag. This hint, along with 'display.precision', is used by some OPI clients to control how values are rendered.

The text value of the tag must be one of the following choices.

record(ai, "...") {
info(Q:form, "Default") # implied default
}

Access Security

QSRV will enforce an optional access control policy file (.acf) loaded by the usual means (cf. asSetFilename() ). This policy is applied to both Single and Group PVs. With Group PVs, restrictions are not defined for the group, but rather for the individual member records. The same policy will be applied regardess of how a record is accessed (individually, or through a group).

Policy application differs from CA (RSRV) in several ways:

Client hostname is always the numeric IP address. HAG() entries must either contained numeric IP addresses, or that asCheckClientIP=1 flag must be set to translate hostnames into IPs on ACF file load (effects CA server as well). This prevents clients from trivially forging "hostname". In additional to client usernames. UAG definitions may contained items beginning with "role/" which are matched against the list of groups of which the client username is a member. Username to group lookup is done internally to QSRV, and depends on IOC host authentication configuration. Note that this is still based on the client provided username string.

UAG(special) {
someone, "role/op"
}

The "special" UAG will match CA or PVA clients with the username "someone". It will also match a PVA client if the client provided username is a member of the "op" group (supported on POSIX targets and Windows).

PVAccess Links

When built against Base >= 3.16.1, support is enabled for PVAccess links, which are analogous to Channel Access (CA) links. However, the syntax for PVA links is quite different.

Note
The "dbjlr" and "dbpvar" IOC shell command provide information about PVA links in a running IOC.

A simple configuration using defaults is

record(longin, "tgt") {}
record(longin, "src") {
field(INP, {pva:"tgt"})
}

This is a shorthand for

record(longin, "tgt") {}
record(longin, "src") {
field(INP, {pva:{pv:"tgt"}})
}

Some additional keys (beyond "pv") may be used. Defaults are shown below:

record(longin, "tgt") {}
record(longin, "src") {
field(INP, {pva:{
pv:"tgt",
field:"", # may be a sub-field
local:false,# Require local PV
Q:4, # monitor queue depth
pipeline:false, # require that server uses monitor flow control protocol
proc:none, # Request record processing (side-effects).
sevr:false, # Maximize severity.
time:false, # set record time during getValue
monorder:0, # Order of record processing as a result of CP and CPP
retry:false,# allow Put while disconnected.
always:false,# CP/CPP input link process even when .value field hasn't changed
defer:false # Defer put
}})
}

pv: Target PV name

The PV name to search for. This is the same name which could be used with 'pvget' or other client tools.

field: Structure field name

The name of a sub-field of the remotely provided Structure. By default, an empty string "" uses the top-level Structure.

If the top level structure, or a sub-structure is selected, then it is expeccted to conform to NTScalar, NTScalarArray, or NTEnum to extract value and meta-data.

If the sub-field is an PVScalar or PVScalarArray, then a value will be taken from it, but not meta-data will be available.

Todo:
Ability to traverse through unions and into structure arrays (as with group mappings).

local: Require local PV

When true, link will not connect unless the named PV is provided by the local (QSRV) data provider.

Q: Monitor queue depth

Requests a certain monitor queue depth. The server may, or may not, take this into consideration when selecting a queue depth.

pipeline: Monitor flow control

Expect that the server supports PVA monitor flow control. If not, then the subscription will stall (ick.)

proc: Request record processing (side-effects)

The meaning of this option depends on the direction of the link.

For output links, this option allows a request for remote processing (side-effects).

For input links, this option controls whether the record containing the PVA link will be processed when subscription events are received.

sevr: Alarm propagation

This option controls whether reading a value from an input PVA link has the addition effect of propagating any alarm via the Maximize Severity process.

time: Time propagation

Somewhat analogous to sevr: applied to timestamp. When true, the record TIME field is updated when the link value is read.

Warning
TSEL must be set to -2 for time:true to have an effect.

monorder: Monitor processing order

When multiple record target the same target PV, and request processing on subscription updates. This option allows the order of processing to be specified.

Record are processed in increasing order. monorder=-1 is processed before monorder=0. Both are processed before monorder=1.

defer: Defer put

By default (defer=false) an output link will immediately start a PVA Put operation. defer=true will store the new value in an internal cache, but not start a PVA Put.

This option, in combination with field: allows a single Put to contain updates to multiple sub-fields.

retry: Put while disconnected

Allow a Put operation to be queued while the link is disconnected. The Put will be executed when the link becomes connected.

always: CP/CPP always process

By default (always:false) a subscription update will only cause a CP input link to scan if the structure field (cf. field: option) is marked as changed. Set to true to override this, and always process the link.

Link semantics/behavior

This section attempts to answer some questions about how links behave in certain situations.

Links are evaluated in three basic contexts.

An input link can bring in a Value as well as meta-data, alarm, time, and display/control info. For input links, the PVA link engine attempts to always maintain consistency between Value, alarm, and time. However, consistency between these, and the display/control info is only ensured during a CP scan.