From 33f3145fccc8ca6e56bfbbd1f44456f1eaa7e5ae Mon Sep 17 00:00:00 2001
From: Andrew Johnson Most Soft Channel input device support routines have supported fetching the
timestamp through the INP link along with the input data. However before now
there was no guarantee that the timestamp provided by a CA link came from the
-same update as the data, since the two were read at separate times without
-maintaining a lock on the CA input buffer. This shortcoming has been fixed as
-part of the new link support code, which allows code using a link to pass a
-subroutine to the link type to be run with the link locked. The subroutine may
-make multiple requests for metadata from the link, but must not block. Device support may be written to expect hardware addresses in the new
-JSON_LINK address type. Addresses loaded from a database file will be
-checked against the JSON rules, and a strict JSON representation of the result
-is provided as a C string pointed to by link.value.json.string. Currently the device support is responsible for parsing the JSON text itself.
-An event-driven JSON parser library has been included in libCom since Base-3.15,
-YAJL (Yet Another JSON Library)
-Version 1.012, documented
-here.Device Support Address Type JSON_LINK
-
-
-FIXME text missing here...
+A major new feature introduced with this release of EPICS Base is an +Extensible Link Type mechanism, also known as Link Support or JSON Link Types. +This addition permits new kinds of link I/O to be added to an IOC in a similar +manner to the other extension points already supported (e.g. record, device and +driver support).
-Support routine changes
+A new link type must implement two related APIs, one for parsing the JSON +string which provides the link address and the other which implements the link +operations that get called at run-time to perform I/O. The link type is built +into the IOC by providing a new link entry in a DBD file.
+ + +New Link Types Added
+ +This release contains two new JSON link types, const and +calc:
+ ++ +
+ +- The const link type is almost equivalent to the old CONSTANT link +type with the updates described below to accept arrays and strings, except that +there is no need to wrap a scalar string constant inside array brackets since a +constant string will never be confused with a PV name.
+ +- The calc link type allows CALC expressions to be used to combine +values from other JSON links to produce its value. Until additional JSON link +types are created though, the calc link type has little practical +utility as it can currently only fetch inputs from other calc links or +from const links.
+ +The new link types are documented in a +separate +document +.
+ + +Device Support Addressing using JSON_LINK + +
The API to allow device support to use JSON addresses is currently +incomplete; developers are advised not to try creating device support that +specifies a JSON_LINK address type.
+ + +Support Routine Modifications for Extensible Link Types
For link fields in external record types and soft device support to be able -to use the new JSON link types properly, the following changes are -necessary:
+to use the new link types properly, various changes are required to utilize the +new Link Support API as defined in the dbLink.h header file and outlined below. +The existing built-in Database and Channel Access link types have been altered +to implement the link APIs, so will work properly after these conversions:@@ -75,69 +108,149 @@ into this: recGblInitConstantLink(&prec->siml, DBF_USHORT, &prec->simm); -Note that recGblInitConstantLink() still returns true if the field was -successfully initialized from the link. +Note that recGblInitConstantLink() still returns TRUE if the field was +successfully initialized from the link (implying the link is constant).
+This change will work properly with all Base releases currently in use. -- Code like this: +
- Code that needs to identify a constant link should be modified to use the +new routine dbLinkIsConstant() instead, which returns TRUE for constant +or undefined links, FALSE for links whose dbGetLink() routine may +return different values on different calls. For example this:
-- if ((prec->dol.type != CONSTANT) && + if (prec->dol.type != CONSTANT)-should usually become: +should become this:- if (!dbLinkIsConstant(&prec->dol) && + if (!dbLinkIsConstant(&prec->dol)) ++ +When the converted software is also required to build against older versions of +Base, this macro definition may be useful: + ++#define dbLinkIsConstant(lnk) ((lnk)->type == CONSTANT)- Other code that compares a link type with CONSTANT should be modified to -use the new routine dbLinkIsConstant(plink) instead.
- -- Any code that calls dbCa routines directly or that explicitly checks if a +
- Any code that calls dbCa routines directly, or that explicitly checks if a link has been resolved as a CA link using code such as
+will still compile and run, but will only work properly with the old CA link +type. To operate with the new extensible link types such code must be modified +to use the new generic routines defined in dbLink.h and should never attempt to +examine or modify data inside the link. After conversion the above line would +probably become: -- if (plink->type == CA_LINK) + if (prec->inp.type == CA_LINK)-should be modified to use the new generic routines defined in dbLink.h. As an -example, the calcout record has been modified to use the new dbLink API.- ...
++ if (dbLinkIsVolatile(&prec->inp)) ++ +A volatile link is one like a Channel Access link which may disconnect and +reconnect without notice at runtime. Database links and constant links are not +volatile; unless their link address is changed they will always remain in the +same state they started in. For compatibility when building against older +versions of Base, this macro definition may be useful: + ++#define dbLinkIsVolatile(lnk) ((lnk)->type == CA_LINK) ++ + +The current connection state of a volatile link can be found using the +routine dbIsLinkConnected() which will only return TRUE for a volatile +link that is currently connected. Code using the older dbCa API returning this +information used to look like this: + + + + ++ stat = dbCaIsLinkConnected(plink); ++ +which should become: ++ stat = dbIsLinkConnected(plink); ++ +Similar changes should be made for calls to the other dbCa routines.A full example can be found by looking at the changes to the calcout record +type, which has been modified in this release to use the new dbLink generic +API. -FIXME text missing here...
-
Previously a constant link (i.e. a link that does not point to another PV, -either local or over Channel Access) has only been able to provide a numeric -value; any string found in a link field that was not recognized as a number was -treated as a PV name. In this release, constant links may contain string values, -arrays, or even arrays of strings. These are indicated by ...
+Previously a constant link (i.e. a link that did not point to another PV, +either locally or over Channel Access) was only able to provide a single numeric +value to a record initialization; any string given in a link field that was not +recognized as a number was treated as a PV name. In this release, constant links +can be expressed using JSON array syntax and may provide array initialization of +values containing integers, doubles or strings. An array containing a single +string value can also be used to initialize scalar strings, so the stringin, +stringout, lsi (long string input), lso (long string output), printf, waveform, +subArray and aai (analog array input) record types and/or their soft device +supports have been modified to support this.
-FIXME text missing here...
+Some examples of constant array and string initialized records are:
+ +
+ record(stringin, "const:string") {
+ field(INP, ["Not-a-PV-name"])
+ }
+ record(waveform, "const:longs") {
+ field(FTVL, LONG)
+ field(NELM, 10)
+ field(INP, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
+ }
+ record(aai, "const:doubles") {
+ field(FTVL, DOUBLE)
+ field(NELM, 10)
+ field(INP, [0, 1, 1.6e-19, 2.718, 3.141593])
+ }
+ record(aSub, "select") {
+ field(FTA, STRING)
+ field(NOA, 4)
+ field(INPA, ["Zero", "One", "Two", "Three"])
+ field(FTB, SHORT)
+ field(NOB, 1)
+ field(FTVA, STRING)
+ field(NOVA, 1)
+ field(SNAM, "select_asub")
+ }
+
+
+Reminder: Link initialization with constant values normally only occurs at +record initialization time. The calcout and printf record types are the only +exceptions in the Base record types to this rule, so it is generally not useful +to change a const link value after iocInit.
A database file can now provide a "relaxed JSON" value for a database field value or an info tag. Only a few field types can currently accept such values, -but the capability is now available for use in other places in the future. If a -JSON-capable field is written to at run-time though only strictly compliant JSON -may be used (the dbStaticLib parser rewrites relaxed JSON values into strict -JSON before passing them to the datase for interpretation, where the strict -rules must be followed).
+but the capability is now available for use in other places in the future. When +writing to a JSON-capable field at run-time however, only strictly compliant +JSON may be used (the dbStaticLib parser rewrites relaxed JSON values into +strict JSON before passing them to the datase for interpretation, where the +strict rules must be followed)."Relaxed JSON" was developed to maximize compatibility with the previous database parser rules and reduce the number of double-quotes that would be -needed using strict JSON syntax. The parser will also accept strict JSON, which -should be used when machine-generating database files. The differences are:
+needed for strict JSON syntax. The parser does accept strict JSON too though, +which should be used when machine-generating database files. The differences +are:Note that the record, field and info-tag names do not accept JSON values, so they follows the older bareword rules for quoting where the colon : and several additional characters are legal in a bareword -string.
+string. Only the value (after the comma) is parsed as JSON. The autosave module +has not been modified to accept JSON syntax, the above is only an example of +how JSON might be used.