EPICS pvDataJava
Release 5.1-DEV - 2017.03.29
- Editors:
- Marty Kraimer, BNL
- Dave Hickin, Diamond
This product is made available subject to acceptance of the EPICS open source license.
Abstract
pvDataJava is a computer software package for the efficient
storage, access, and communication, of structured data. It is specifically the
Java implementation of pvData, which is one part of the set of related products in the EPICS
V4 control system programming environment:
relatedDocumentsV4.html
Status of this Document
This is the 29-March-2017 version of the Java implementation of pvData.
RELEASE_NOTES.md provides changes since the last release. TODO.md describes things to do before the next release.
Table of Contents
Introduction
pvData is one of a set of related projects. It describes and implements data that the other projects support. Thus it is not useful by itself but understanding pvData is required in order to understand the other projects. The reader should also become familiar with project pvAccess, which is located via the same sourceforge site as this project.
developerGuide briefly describes a set of application programming interfaces (APIs) for EPICS V4. It should be read before reading this manual.
The Java and C++ implementation of pvData implement the same data model but differ in implementation because of the differences between Java and C++.
pvData is one of a set of related packages in the EPICS V4 core software. It describes and implements the data management system to which the the other projects interface.
pvData (Process Variable Data) defines and implements an efficient way to store, access, and communicate memory resident data structures.
- definition
- Package org.epics.pvdata.pv has Java interface definitions that define pvData. Although defined with Java syntax they also document what is required for implementation in other languages such as C++.
- implementation
- The set of packages provided by this project provide a complete Java implementation of pvData. Project pvAccess is the network support for pvData, i.e. it provides a channel access client and server that fully support pvData.
- efficient
- Small memory footprint, low cpu overhead, and concise code base.
- data storage
- pvData defines separate introspection and data interfaces. The introspection interfaces provide access to immutable objects, which allows introspection instances to be freely shared. The introspection interface for a process variable can be accessed without requiring access to the data.
- data access
- Client code can access pvData via the introspection and data interfaces. For "well known" data, e.g. image data, specialized interfaces can be provided without requiring any changes to the core software.
- data transfer
- The separation of introspection and data interfaces allows for efficient network data transfer. At connection time introspection information can be passed from server to client. Each side can create a data instance. The data is transferred between these instances. The data in the network buffers does not have to be self describing since each side has the introspection information.
- memory resident
- pvData only defines memory resident data.
- structured data
- pvData defines data as structures with subfields where each each subfield has a name and type. The types are defined next.
Interface Definitions
This section gives a brief description of the pvData introspection and data interfaces. In this section the methods are shown but not described. See org.epics.pvdata.pv below for a description of each method.
Types
The following are the type definitions:
enum Type { scalar, scalarArray, structure, structureArray, union_t, unionArray; }
where
- scalar
- A field that has data with one of the
ScalarType
s. - scalarArray
- A field that is an array where each element is the same
ScalarType
. - structure
- A field which has named subfields.
- structureArray
- A field that is an array of structures where each element has the same introspection interface, i.e. each element has the same structure.
- union
- A union stores a single subfield with a variable type. A variant union allows the type to be any type. A regular union allows only a fixed set of types
- unionArray
- A union array is an array of union fields where each element has the same introspection interface. Different elements can have different types but each must have a type determined by the union interface.
enum ScalarType { pvBoolean, pvByte,pvShort,pvInt,pvLong, pvUByte,pvUShort,pvUInt,pvULong, pvFloat,pvDouble, pvString; // The following are convenience methods public boolean isInteger(); public boolean isUInteger(); public boolean isNumeric(); public boolean isPrimitive(); public static ScalarType getScalarType(String type); public String toString(); }
where
- boolean
- true or false
- byte
- An 8 bit signed byte
- short
- 16 bit signed integer
- int
- 32 bit signed integer
- long
- 64 bit signed integer
- ubyte
- An 8 bit unsigned byte
- ushort
- 16 bit unsigned integer
- uint
- 32 bit unsigned integer
- ulong
- 64 bit unsigned integer
- float
- 32 bit IEEE float
- double
- 64 bit IEEE float
- string
- An immutable string. The Java implementation is String. For other implementations the network representation must be the same as for Java. Note that a string is treated like it is a scaler.
NOTE: Java does not support unsigned integers so the Java implementation of each unsigned type is implemented as the corresponding signed type. The only exception is the Convert facility. When it performs a widening operation, e.g. from ubyte to short, it performs the correct conversion.
Introspection Interfaces
Field
is the base introspection interface. It has only an ID and a type.
interface Field extends Serializable { String getId(); Type getType(); void toString(StringBuilder buf); void toString(StringBuilder buf,int indentLevel); String toString(); } interface Scalar extends Field { ScalarType getScalarType(); } interface ScalarArray extends Field { ScalarType getElementType(); } interface Structure extends Field { Field getField(String fieldName); Field getField(int fieldIndex); <T extends Field> T getField(Class<T> c, String fieldName); <T extends Field> T getField(Class<T> c, int fieldIndex); Field[] getFields(); String[] getFieldNames(); int getFieldIndex(String fieldName); String getFieldName(int fieldIndex); } interface StructureArray extends Field { Structure getStructure(); } public interface Union extends Field{ public static final String DEFAULT_ID = "union"; public static final String ANY_ID = "any"; Field getField(String fieldName); Field getField(int fieldIndex); <T extends Field> T getField(Class<T> c, String fieldName); <T extends Field> T getField(Class<T> c, int fieldIndex); Field[] getFields(); String[] getFieldNames(); int getFieldIndex(String fieldName); String getFieldName(int fieldIndex); boolean isVariant(); } public interface UnionArray extends Field{ Union getUnion(); }
The introspection interfaces provide access to immutable objects. This allows introspection interfaces to be freely shared between data objects. For example the introspection interface for a timeStamp, which is a structure containing two fields, can be shared by every record that has a time stamp.
Data Interfaces
PVField
is the base interface for a data field:
interface PVField extends Serializable { String getFieldName(); String getFullName(); int getFieldOffset(); int getNextFieldOffset(); int getNumberFields(); boolean isImmutable(); void setImmutable(); Field getField(); PVStructure getParent(); void postPut(); void setPostHandler(PostHandler postHandler); void toString(StringBuilder buf); void toString(StringBuilder buf,int indentLevel); String toString(); // The following should go away. PVAuxInfo getPVAuxInfo(); }
Each scalar type has an associated data interface: PVBoolean
,
PVByte
, PVShort
, PVInt
, PVLong
,
PVUByte
, PVUShort
, PVUInt
, PVULong
,
PVFloat
, PVDouble
and PVString
. Each has a get
and a
put
method. For example:
interface PVDouble extends PVScalar{ double get(); void put(double value); }
PVArray
is the base class for arrays.
interface PVArray extends PVField, SerializableArray { Array getArray(); int getLength(); void setLength(int length); int getCapacity(); void setCapacity(int length); boolean isCapacityMutable(); void setCapacityMutable(boolean isMutable); }
PVScalarArray
is the base class for scalar arrays.
interface PVScalarArray extends PVArray { ScalarArray getScalarArray(); }
For each scalar type an associated array data interface is defined. Each has
a get
and put
method. For example:
public class DoubleArrayData { public double[] data; public int offset; } interface PVDoubleArray extends PVArray { int get(int offset, int len, DoubleArrayData data); int put(int offset,int len, double[] from, int fromOffset); void shareData(double[] from); }
PVStructureArray
is the interface for an array of structures where each element
has the same introspection interface.
public class StructureArrayData { public PVStructure[] data; public int offset; } interface PVStructureArray extends PVArray{ StructureArray getStructureArray(); int get(int offset, int length, StructureArrayData data); int put(int offset,int length, PVStructure[] from, int fromOffset); void shareData(PVStructure[] from); }
PVStructure
is the data interface for a structure.
interface PVStructure extends PVField , BitSetSerializable{ Structure getStructure(); PVField[] getPVFields(); PVField getSubField(String fieldName); PVField getSubField(int fieldOffset); <T extends PVField> T getSubField(Class<T> c, String fieldName); <T extends PVField> T getSubField(Class<T> c, int fieldOffset); // The following are convenience methods // Note that they are no longer needed because of above generic methods PVBoolean getBooleanField(String fieldName); PVByte getByteField(String fieldName); PVShort getShortField(String fieldName); PVInt getIntField(String fieldName); PVLong getLongField(String fieldName); PVFloat getFloatField(String fieldName); PVDouble getDoubleField(String fieldName); PVString getStringField(String fieldName); PVScalarArray getScalarArrayField(String fieldName); PVStructureArray getStructureArrayField(String fieldName); PVStructure getStructureField(String fieldName); PVArray getArrayField(String fieldName,ScalarType elementType); PVUnion getUnionField(String fieldName); PVUnionArray getUnionArrayField(String fieldName); public boolean checkValid(); }
Introspection and Data creation
The following interface creates introspection instances:
public interface FieldCreate { FieldBuilder createFieldBuilder(); Scalar createScalar(ScalarType scalarType); BoundedString createBoundedString(int maxLength); ScalarArray createScalarArray(ScalarType elementType); ScalarArray createFixedScalarArray(ScalarType elementType, int size); ScalarArray createBoundedScalarArray(ScalarType elementType, int bound); StructureArray createStructureArray(Structure elementStructure); UnionArray createUnionArray(Union elementUnion); UnionArray createVariantUnionArray(); Structure createStructure(String[] fieldNames, Field[] field); Structure createStructure(String id,String[] fieldNames, Field[] field); Structure appendField(Structure structure,String fieldName, Field field); Structure appendFields(Structure structure,String[] fieldNames, Field[] fields); Structure createStructure(Structure structToClone); Union createVariantUnion(); Union createUnion(String[] fieldNames, Field[] fields); Union createUnion(String id, String[] fieldNames, Field[] fields); Field deserialize(ByteBuffer buffer, DeserializableControl control); }
The following is a convenience class for creating introspection objects:
public interface FieldBuilder { public FieldBuilder setId(String id); public FieldBuilder add(String name, ScalarType scalarType); public FieldBuilder addBoundedString(String name, int maxLength); public FieldBuilder add(String name, Field field); public FieldBuilder addArray(String name, ScalarType scalarType); public FieldBuilder addFixedArray(String name, ScalarType scalarType, int size); public FieldBuilder addBoundedArray(String name, ScalarType scalarType, int bound); public FieldBuilder addArray(String name, Field element); public Structure createStructure(); public Union createUnion(); FieldBuilder addNestedStructure(String name); FieldBuilder addNestedUnion(String name); FieldBuilder addNestedStructureArray(String name); FieldBuilder addNestedUnionArray(String name); FieldBuilder endNested(); }
The following interface creates data instances:
public interface PVDataCreate { PVField createPVField(Field field); PVField createPVField(PVField fieldToClone); PVScalar createPVScalar(Scalar scalar); PVScalar createPVScalar(ScalarType fieldType); PVScalar createPVScalar(PVScalar scalarToClone); <T extends PVScalar, TA extends PVScalarArray> T createPVScalar( PVScalarType<T, TA> scalarType); PVScalarArray createPVScalarArray(ScalarArray array); PVScalarArray createPVScalarArray(ScalarType elementType); PVScalarArray createPVScalarArray(PVScalarArray arrayToClone; <T extends PVScalar, TA extends PVScalarArray> TA createPVScalarArray( PVScalarType<T, TA> elementType); PVStructureArray createPVStructureArray(StructureArray structureArray); PVUnionArray createPVUnionArray(UnionArray unionArray); PVUnionArray createPVVariantUnionArray(); PVStructure createPVStructure(Structure structure); PVStructure createPVStructure(String[] fieldNames,Field[] fields); PVStructure createPVStructure(PVStructure structToClone); PVUnion createPVUnion(Union union); PVUnion createPVVariantUnion(); PVUnion createPVUnion(PVUnion unionToClone); PVStructureArray createPVStructureArray(Structure structure); PVUnionArray createPVUnionArray(Union union); PVField[] flattenPVStructure(PVStructure pvStructure); }
pvData Conversion
An interface named Convert
provides all reasonable conversions to/from
pvData.
The convert utility is also used to implement the toString
methods of PVField
.
See org.epics.pvdata.pv.Convert
for details.
Package Summary
This document describes everything via Java definitions. The initial implementation is in Java but the functionality is also implemented in C++ (See pvDataCPP for details).
pvData is distributed as a sourceforge mercurial project named pvDataJava. It consists of the following Java packages:
org.epics.pvdata.pv
The Java enum, interface, and class definitions that define pvData. This section provides a complete definition of what pvData is.
org.epics.pvdata.factory
Provides everything required for creating pvData. It provides the following factories:
- FieldFactory
- Creates introspection interfaces.
- PVDataFactory
- Creates data interfaces for all of the supported data types.
- ConvertFactory
- Converts between support data types.
- StatusFactory
- Status is a class for communication status between code modules.
- StandardFieldFactory
- Creates introspection objects for "well known" data.
- StandardPVFieldFactory
- Creates data objects for "well known" data.
Although pvDataFactory can provide the implementation for all supported data types, often it is desirable to provide other implementations. To make it easy to create alternate implementations a set of abstract and base classes are supplied.
org.epics.pvdata.property
Provides a way to associated properties with a field.
The basic idea is to associate properties with any field named "value". All the fields in the structure that contains the value field are considered properties of value with the field name being the property name. See that package overview for details.
This package also provides support for "well known" field definitions like timeStamp, alarm, display,etc. Code that uses pvData can be simplified by using this support.
org.epics.pvdata.misc
This package provides support that is used by pvData factories and might also be useful to software that uses pvData.
org.epics.pvdata.monitor
Provides the ability to monitor changes to an arbitrary subset of the fields in a record.
Package org.epics.pvdata.pv
Overview
This package has the complete set of enum, interface, and class definitions that describe pvData. The implementation is provided in package org.epics.pvdata.factory.
A PVStructure
is a field that contains an array of subfields. Each field has
code for accessing the field. The interface for each field is PVField
or an
interface that extends PVField
. Each field also has an introspection interface,
which is Field
or an extension of Field
. This package overview describes the
complete set of data and introspection interfaces for pvData.
This package also describes an interface Convert, which provides a rich set of methods for converting and copying data between field.
The interface FieldCreate
creates the introspection interfaces. The
interface PVDataCreate
creates the PVField
interfaces. Between them they
provide the ability to create every type of Field
and PVField
, i.e. they
provide a complete implementation of pvData. It is also possible for other code
to provide implementations.
The interface StandardField
provides introspection objects for standard fields.
The interface StandardPVField
provides data objects for standard fields.
The interface StatusCreate
and class Status
provide status objects to pass between source
modules.
Process Variable Reflection
Given the introspection object it is possible to introspect a field without requiring access to data. The reflection and data interfaces are separate because the data may not be available. For example when a pvAccess client connects to a PV, the client library can obtain the reflection information without obtaining any data. Only when a client issues an I/O request will data be available. This separation is especially important for arrays and structures so that a client can discover the type without requiring that a large array or structure be transported over the network.
Type
The types are defined by the Java definitions:
enum Type { scalar, scalarArray, structure, structureArray, union, unionArrray; } enum ScalarType { pvBoolean, pvByte, pvShort, pvInt, pvLong, pvUByte, pvUShort, pvUInt, pvULong, pvFloat,pvDouble, pvString; //Convenience methods public boolean isInteger(); // pvByte,...,pvULong public boolean isUInteger(); // pvUByte,...,pvULong public boolean isNumeric(); // pvByte,...pvDouble public boolean isPrimitive(); // pvBoolean,...pvDouble public static ScalarType getScalarType(String type); public String toString(); }
Serializable
The following interfaces are called by pvAccess for transporting data over the network. The abstract and base classes ensure that these methods are properly implemented.
interface Serializable { void serialize(ByteBuffer buffer,SerializableControl flusher); void deserialize(ByteBuffer buffer,DeserializableControl control); }where
- serialize
- Serialize into buffer. flusher is called when buffer is full.
- deserialize
- deserialize from byte buffer. control is called when more data is required.
interface SerializableControl { void flushSerializeBuffer(); void ensureBuffer(int size); void alignBuffer(int alignment); void cachedSerialize(Field field, ByteBuffer buffer) }where
- flushSerializeBuffer
- Code that called serialize must empty the buffer. The call can block until the buffer is flushed.
- ensureBuffer
- Helper method. Ensures specified size of bytes, flushes if necessary.
- alignBuffer
- Align buffer.Note that this takes care only current buffer alignment. If streaming protocol is used, care must be taken that entire stream is aligned.
- cachedSerialize
- Serialize
Field
instance via cache.
interface DeserializableControl { void ensureData(int size); void alignData(int alignment); Field cachedDeserialize(ByteBuffer buffer) }where
- ensureData
- Helper method. Ensures specified size of bytes, provides it if necessary.
- alignData
- Align buffer.Note that this takes care only current buffer alignment. If streaming protocol is used, care must be taken that entire stream is aligned.
- cachedDeserialize
- Deserialize
Field
instance via cache.
interface SerializableArray extends Serializable { void serialize(ByteBuffer buffer, SerializableControl flusher, int offset, int count); }where
- serialize
- Serialize field into given buffer.
interface BitSetSerializable { void serialize(ByteBuffer buffer, SerializableControl flusher, BitSet bitSet); void deserialize(ByteBuffer buffer, DeserializableControl control, BitSet bitSet); }where
- serialize
- Serialize field into given buffer. The
BitSet
shows the fields to serialize. - deserialize
- Deserialize field into given buffer. The
BitSet
shows the fields to serialize.
Reflection
This section defines the complete set of Java PV reflection interfaces. Reflection consists of the following:
- Field
- A
Field
has an ID and a type. It can be converted to a string. The format is the metadata format described in the overview. - Scalar
- A
Scalar
has aScalarType
- ScalarArray
- A
ScalarArray
has aScalarType
corresponding to the element type - Structure
- Has fields that can be any of the supported types. In addition it has a name for each field.
- StructureArray
- The field holds
Structure[]
. Each element has the sameStructure
introspection interface. A client can onlyget
/put
entirePVStructure
elements NOT subfields of array elements. - Union
- A union field stores a single field. A given union field can either store a
field of any type (variant union) or any of a specified set of types
(regular union).
Union
describes which of these applies and the set of types in the case of a regular union. - UnionArray
- The field holds
Union[]
. Each element has the sameUnion
introspection interface. - FieldCreate
- This is an interface that provides methods to create introspection
interfaces. A factory is provided to create a
FieldCreate
.
Field
interface Field extends Serializable { String getID(); Type getType(); void toString(StringBuilder buf)); void toString(StringBuilder buf,int indentLevel); String toString(); }where
- getID
- Get the identification string. It can be empty. For scalar fields the ID is the metadata type, i.e. boolean, byte, etc. For scalarArray fields the ID is the metadata type, i.e. boolean[], byte[], etc. For structure fields the ID is determined by the argument specified when fieldCreate.createStructure is called. For structureArray fields the ID is XX[] where XX is the ID of the element structure.
- getType
- Get the field type.
- toString
- Create a String that shows the type. The format is the metadata syntax defined in the overview.
Scalar
interface Scalar extends Field { ScalarType getScalarType(); }where
- getScalarType
- Return the ScalarType.
ScalarArray
interface ScalarArray extends Field{ ScalarType getElementType(); }where
- getElementType
- Return the
ScalarType
for each array element.
Structure
interface Structure extends Field{ Field getField(String fieldName); Field getField(int fieldIndex); <T extends Field> T getField(Class<T> c, String fieldName); <T extends Field> T getField(Class<T> c, int fieldIndex); Field[] getFields(); String[] getFieldNames(); int getFieldIndex(String fieldName); String getFieldName(int fieldIndex); }where
- getField
- Return a field of the structure. The field can be requested by name or by index.
- getField - generic versions
- These are the methods that get a field of the structure and convert it to the proper type.
- getFields
- Return the array of sub fields.
- getFieldNames
- Return the fieldNames for the fields.
- getFieldName
- Return the
Field
for the index. - getFieldIndex
- Return the index of the field with the specified fieldName.
StructureArray
interface StructureArray extends Field{ Structure getStructure(); }where
- getStructure
- Return the introspection interface for the array elements.
Union
public interface Union extends Field{ public static final String DEFAULT_ID = "union"; public static final String ANY_ID = "any"; Field getField(String fieldName); Field getField(int fieldIndex); <T extends Field> T getField(Class<T> c, String fieldName); <T extends Field> T getField(Class<T> c, int fieldIndex); Field[] getFields(); String[] getFieldNames(); int getFieldIndex(String fieldName); String getFieldName(int fieldIndex); boolean isVariant(); }where
- getField
- Given a name or an index the type is returned. null is returned if not found.
- getFields
- Get the array of types.
- getFieldNames
- Get the array of names.
- getFieldIndex
- Get the index for name. -1 is returned if not found.
- getFieldName
- Get the name for the specified index.
- isVariant
- returns true if this is variant array and false otherwise.
UnionArray
public interface UnionArray extends Field{ Union getUnion(); }where
- getUnion
- Get the union interface for each element.
FieldCreate
Syntax for fieldName and ID.
A fieldName must begin with a letter and must be a sequence of letters and digits. A letter is defined as 'A'-'Z', 'a'-'z','_', or any Unicode character that denotes a letter in a language. Similarly digits are '0'-'9' and any Unicode character that denotes a digit in a language. Note that this is the same as the Java syntax for variable names.
The syntax for ID is the same except the '.' is also allowed after the initial letter.
public interface FieldCreate { FieldBuilder createFieldBuilder(); Scalar createScalar(ScalarType scalarType); BoundedString createBoundedString(int maxLength); ScalarArray createScalarArray(ScalarType elementType); ScalarArray createFixedScalarArray(ScalarType elementType, int size); ScalarArray createBoundedScalarArray(ScalarType elementType, int bound); StructureArray createStructureArray(Structure elementStructure); UnionArray createUnionArray(Union elementUnion); UnionArray createVariantUnionArray(); Structure createStructure(String[] fieldNames, Field[] field); Structure createStructure(String id,String[] fieldNames, Field[] field); Structure appendField(Structure structure,String fieldName, Field field); Structure appendFields(Structure structure,String[] fieldNames, Field[] fields); Structure createStructure(Structure structToClone); Union createVariantUnion(); Union createUnion(String[] fieldNames, Field[] fields); Union createUnion(String id, String[] fieldNames, Field[] fields); Field deserialize(ByteBuffer buffer, DeserializableControl control); }where
- createFieldBuilder
- Create an instance of
FieldBuilder
, which is described next. - createScalar
- Return the
Scalar
with the specifiedScalarType
. Note that the implementation creates a single instance for eachScalarType
. - createBoundedString
- Return a scalar of type
pvString
that has a bounded size for a string. - createScalarArray
- Return the
ScalarArray
with the specifiedelementType
. Note that the implementation creates a single instance for eachelementType
. - createFixedScalarArray
- Return the
ScalarArray
with the specifiedelementType
and specifies that size of element size of any object that has this introspection interface. - createBoundedScalarArray
- Return the
ScalarArray
with the specifiedelementType
and specifies that maximum element size of any object that has this introspection interface. - createStructureArray
- Return a
StructureArray
with the specified introspection interface for each array element. - createUnionArray
- Return a
UnionArray
with the specified introspection interface. - createVariantUnionArray
- Return a
UnionArray
of variant union elements. - createStructure
- Return a
Structure
. There are two methods. The first creates a structure with an empty ID which results in an ID of structure. - appendField
- Append a field to a structure.
- appendFields
- Append an array of fields to a structure.
- createVariantUnion
- Create a variant union, i.e. a union where the subfield can be any valid type.
- createUnion
- Create a union where the subfield can have any of the types an names defined by the arguments and the associated names. The default ID is union for regular unions and any for variant unions.
- deserialize
- Deserialize a field from the the buffer.
FieldBuilder
FieldBuilder
is a convenience class for creating introspection interfaces.
An example is:
FieldCreate fieldCreate = FieldFactory.getFieldCreate(); Structure s = fieldCreate.createFieldBuilder(). add("double", ScalarType.pvDouble). addNestedStructure("nested"). add("short", ScalarType.pvShort). add("long", ScalarType.pvLong). endNested(). addArray("intArray", ScalarType.pvInt). createStructure(); System.out.println(s);This produces:
structure double double structure nested short short long long int[] intArray
The Java interface is:
public interface FieldBuilder { public FieldBuilder setId(String id); public FieldBuilder add(String name, ScalarType scalarType); public FieldBuilder addBoundedString(String name, int maxLength); public FieldBuilder add(String name, Field field); public FieldBuilder addArray(String name, ScalarType scalarType); public FieldBuilder addFixedArray(String name, ScalarType scalarType, int size); public FieldBuilder addBoundedArray(String name, ScalarType scalarType, int bound); public FieldBuilder addArray(String name, Field element); public Structure createStructure(); public Union createUnion(); FieldBuilder addNestedStructure(String name); FieldBuilder addNestedUnion(String name); FieldBuilder addNestedStructureArray(String name); FieldBuilder addNestedUnionArray(String name); FieldBuilder endNested(); }
- setId
-
Specify the ID for the next
createStructure
orcreateUnion call
. - add
-
Add a name and field for then next call to
createStructure
orcreateUnion
. There are two forms: one for an existing field and the other for a scalar field. - addBoundedString
- Add a bounded string field.
- addArray
-
Add a name and array field for then next call to
createStructure
orcreateUnion
. There are two forms: one for an existing field and the other for a scalar field. Note that for an existing field this specifies the element type. - addFixedArray
- Add a scalar fixed array field.
- addBoundedArray
- Add a scalar bounded array field.
- createStructure
-
Create a
Structure
from the previousadd
andaddArray
methods. - createUnion
-
Create a
Union
from the previousadd
andaddArray
methods. - addNestedStructure
-
Start a nested structure.
This is followed by calls to other methods and ended by a call to
endNested
. - addNestedUnion
-
Start a nested union.
This is followed by calls to other methods and ended by a call to
endNested
. - addNestedStructureArray
-
Start a nested structure array.
This is followed by calls to other methods and ended by a call to
endNested
. - addNestedUnionArray
-
Start a nested union array.
This is followed by calls to other methods and ended by a call to
endNested
. - endNested
Status
Status
provides a way to pass status back to client code. It is new and not
currently used by pvData but may be in the future. It is used by code that uses
pvData.
Status
interface Status extends Serializable { public enum StatusType {OK,WARNING,ERROR,FATAL}; StatusType getType(); String getMessage(); String getStackDump(); boolean isOK(); boolean isSuccess(); }where
- StatusType
- An enum for the status type.
- getType
- Get the
StatusType
. - getMessage
- Get a message explaining the error.
- getStackDump
- Get a stack dump.
- isOK
- Is the status the singleton object for
StatusType.OK
? - isSuccess
- Is the
StatusType
either OK or WARNING?
StatusCreate
interface StatusCreate { Status getStatusOK(); Status createStatus(StatusType type, String message, Throwable cause); Status deserializeStatus(ByteBuffer buffer, DeserializableControl control); }where
- getStatusOK
- Get a singleton that returns StatusType.OK and a null message and stackDump.
- createStatus
- Create a new Status.
- deserializeStatus
- Use this method instead of Status.deserialize(), since this allows OK status optimization.
Requester
Requester is an interface that allows messages to be given to client code.
An instance of Requester
must be implemented by the client.
The definition is:
enum MessageType {info,warning,error,fatalError} interface Requester { String getRequesterName(); void message(String message, MessageType messageType); }
where
- MessageType
- Type of message.
- Requester
- The default implementation is:
- getRequesterName
This is the full field name concatenated to the record name. - message
For the default implementation,PVField
prepends the full field name to the message and callsPVRecord.message
. The default implementation forPVRecord
either displays the message on stdout or stderr or gives the message to message requesters.
- getRequesterName
PVField - Data Interfaces
This section defines the Java Interfaces for accessing the data within
a top-level PVStructure
.
PVField
PVField
is the base interface for accessing data. Every field of a
top-level PVStructure
has a PVField
associated with it.
This includes the top-level structure itself.
interface PVField Serializable { String getFieldName(); String getFullName(); int getFieldOffset(); int getNextFieldOffset(); int getNumberFields(); boolean isImmutable(); void setImmutable(); Field getField(); PVStructure getParent(); void postPut(); void setPostHandler(PostHandler postHandler); void toString(StringBuilder buf); void toString(StringBuilder buf,int indentLevel); String toString(); // The following should go away. PVAuxInfo getPVAuxInfo(); }
where
- getFieldName
- Get the field name for this field. This will be a empty string for the top-level structure.
- getFullName
- Return the path name and field name for this field.
- getFieldOffset
- Get offset of the
PVField
field within top-level structure. Every field within thePVStructure
has a unique offset. The top-level structure has an offset of 0. The first field within the structure has offset equal to 1. The other offsets are determined by recursively traversing each structure of the tree. - getNextFieldOffset
- Get the next offset. If the field is a scalar or array field then this is just offset + 1. If the field is a structure it is the offset of the next field after this structure. Thus (nextOffset - offset) is always equal to the total number of fields within the field.
- getNumberFields
- Get the total number of fields in this field. This is nextFieldOffset - fieldOffset.
- isImmutable
- Is the field immutable?
- setImmutable
- Make the field immutable. Once a field is immutable it can never be changed since there is no method to again make it mutable. This is an important design decision because it allows immutable array fields to share the internal primitive data array.
- getField
- Get the reflection interface.
- getParent
- Get the interface for the parent or null if this is the top-level
PVStructure
. - postPut
- If a
PostHandler
is registered it is called otherwise no action is taken.
NOTE: The implementation of the various data interfaces automatically callpostPut
when a field is changed. However this is not true for a subField of aPVUnion
,PVUnionArray
, orPVStructureArray
. If a subField of any of these is changed then the code that is making the modification must callpostPut
for thePVUnion
,PVUnionArray
, orPVStructureArray
field. Note also that it is not a good idea to modify a subfield of aPVUnionArray
or aPVStructureArray
since it violates the idea of Copy On Write for arrays. - setPostHandler
- Set the handler for
postPut
. At most one handler can be set. - toString
- Converts the field data to a string. This is mostly for debugging purposes. The format is the meta data format described in the pvData project overview. Note: The actual conversion is done by the Convert facility.
PVAuxInfo
NOTE: PVAuxInfo should go away.
AuxInfo (Auxiliary Information) is information about a field that is
application specific. It will not be available outside the application that
implements the database. In particular it will not be made available to Channel
Access. It is used by the database itself to override the default
implementation of fields. The JavaIOC used it for attaching support code.
Database Configuration and other tools can use it for configuration
information. Each Field
and each PVField
can have have an arbitrary number of
auxInfos. An auxInfo is a (key,PVScalar
) pair where key is a string.
public interface PVAuxInfo { PVField getPVField(); PVScalar createInfo(String key,ScalarType scalarType); Map<String,PVScalar> getInfos(); PVScalar getInfo(String key); void toString(StringBuilder buf); void toString(StringBuilder buf,int indentLevel); }
where
- getPVField
- Get the
PVField
to which thisPVAuxInfo
is attached. - createInfo
- Create a new
PVScalar
of type scalarType. - getInfos
- Get a map of all the auxInfos.
- getInfo
- Get the
PVScalar
with the specified key. - toString
- Print all the auxInfo data in metadata format.
PVScalar and extensions
interface PVScalar extends PVField { Scalar getScalar(); }
Primitive PVField
types
The interfaces for primitive data types are:
interface PVBoolean extends PVScalar { boolean get(); void put(boolean value); } interface PVByte extends PVScalar { byte get(); void put(byte value); } interface PVShort extends PVScalar { short get(); void put(short value); } interface PVInt extends PVScalar { int get(); void put(int value); } interface PVLong extends PVScalar { long get(); void put(long value); } interface PVUByte extends PVScalar { byte get(); void put(byte value); } interface PVUShort extends PVScalar { short get(); void put(short value); } interface PVUInt extends PVScalar { int get(); void put(int value); } interface PVULong extends PVScalar { long get(); void put(long value); } interface PVFloat extends PVScalar { float get(); void put(float value); } interface PVDouble extends PVScalar { double get(); void put(double value); }
NOTE: The interface for each unsigned integer is the same as for the same signed type. This is because Java does not implement unsigned primitive types.
PVString
The interface for string is:
interface PVString extends PVScalar, SerializableArray { String get(); void put(String value); }
PVArray and Extensions
PVArray
is the base interface for
all the other array interfaces. It extends PVField
and provides the
additional methods:
interface PVArray extends PVField, SerializableArray { Array getArray(); int getLength(); void setLength(int len); int getCapacity(); void setCapacity(int len); boolean isCapacityMutable(); void setCapacityMutable(boolean isMutable); }
- getArray
- Get the Array introspection interface.
- getLength
- Get the current length. This is less that or equal to the capacity.
- setLength
- Set the length. If the
PVField
is not mutable then an exception is thrown. If this is greater than the capacitysetCapacity
is called. - getCapacity
- Get the capacity, i.e. this is the sized of the underlying data array.
- setCapacity
- Set the capacity. The semantics are implementation dependent but typical semantics are as follows: If the capacity is not mutable an exception is thrown. A new data array is created and data is copied from the old array to the new array.
- isCapacityMutable
- Is the capacity mutable
- setCapacityMutable
- Specify if the capacity can be changed.
PVArray Extensions
The interface for each array type has get and put methods which have the
same arguments except for the data type. For example for PVDoubleArray
it is:
public class DoubleArrayData { public double[] data; public int offset; } interface PVDoubleArray extends PVScalarArray { int get(int offset, int len, DoubleArrayData data); int put(int offset, int len, double[]from, int fromOffset); void shareData(double[] from); }
Get "exposes" it's internal array by setting data.data and data.offset. The
caller is responsible for copying the array elements. This violates the
principle that objects should not expose their internal data but is done for
efficiency. For example it makes it possible to copy between arrays with
identical element types via a call to System.arraycopy
without requiring an
intermediate array.
Both get
and put
return the number of elements actually transferred. The
arguments are:
- offset
- The offset in the
PVArray
. - len
- The maximum number of elements to transfer. The number actually transferred will be less than or equal to this value.
- data
- Get sets
data.data
to it's internal array anddata.offset
to the offset into the array. The caller is responsible for the actual data transfer. - from
- The array from which the data is taken. This array is supplied by the caller
- fromOffset
- The offset in
from
The caller must be prepared to make multiple calls to retrieve or put an entire array. A caller should accept or put partial arrays. For example the following reads an entire array:
double[] getArray(PVDoubleArray pv) { int len = pv.getLength(); double[] storage = new double[len]; DoubleArrayData data = new DoubleArrayData(); int offset = 0; while(offset < len) { int num = pv.get(offset,(len-offset),data); System.arraycopy(data.data,data.offset,storage,offset,num); offset += num; } return storage; }
NOTE: The pvDataCPP now enforces COW (Copy on Write) for arrays.
In the future pvDataJava should have similar rules but without the concept of const
it may not be possible to enforce COW.
shareData
definitely violates COW if any code changes the shared data.
It should not used except for immutable arrays.
shareData
results in the PVArray
using the primitive array that is passed to
this method. This is most useful for immutable arrays. In this case the caller
must set the PVArray
to be immutable. If the PVArray
is not immutable then
the application is responsibility for coordinating access to the array.
This violates the principle that objects should not expose their internal data but
is important for immutable arrays. For example pvData defines
many enumerated structures where an enumerated structure has two fields: index
and choices. Choices is a PVStringArray
that holds the enumerated choices.
Index is a PVInt
that is the index of the currently selected choice. The
choices can be immutable. Allowing the choices internal String[] to be shared
between all the instances of an enumerated structure saves on storage. Another
reason for allowing shared data is so that an application which processes an
array can be separated into multiple modules that directly access the internal
data array of a PVArray
. This can be required for minimizing CPU overhead. In
this case it is the applications responsibility to coordinate access to the
array.
Complete set of PVArray Extensions
interface PVScalarArray extends PVArray { ScalarArray getScalarArray(); } public class BooleanArrayData { public boolean[] data; public int offset; } interface PVBooleanArray extends PVScalarArray { int get(int offset, int len, BooleanArrayData data); int put(int offset, int len, boolean[]from, int fromOffset); void shareData(boolean[] from); } public class ByteArrayData { public byte[] data; public int offset; } interface PVByteArray extends PVScalarArray { int get(int offset, int len, ByteArrayData data); int put(int offset, int len, byte[]from, int fromOffset); void shareData(byte[] from); } interface PVUByteArray extends PVScalarArray { int get(int offset, int len, ByteArrayData data); int put(int offset, int len, byte[]from, int fromOffset); void shareData(byte[] from); } public class ShortArrayData { public short[] data; public int offset; } interface PVShortArray extends PVScalarArray { int get(int offset, int len, ShortArrayData data); int put(int offset, int len, short[]from, int fromOffset); void shareData(short[] from); } interface PVUShortArray extends PVScalarArray { int get(int offset, int len, ShortArrayData data); int put(int offset, int len, short[]from, int fromOffset); void shareData(short[] from); } public class IntArrayData { public int[] data; public int offset; } interface PVIntArray extends PVScalarArray { int get(int offset, int len, IntArrayData data); int put(int offset, int len, int[]from, int fromOffset); void shareData(int[] from); } interface PVUIntArray extends PVScalarArray { int get(int offset, int len, IntArrayData data); int put(int offset, int len, int[]from, int fromOffset); void shareData(int[] from); } public class LongArrayData { public long[] data; public int offset; } interface PVLongArray extends PVScalarArray { int get(int offset, int len, LongArrayData data); int put(int offset, int len, long[]from, int fromOffset); void shareData(long[] from); } interface PVULongArray extends PVScalarArray { int get(int offset, int len, LongArrayData data); int put(int offset, int len, long[]from, int fromOffset); void shareData(long[] from); } public class FloatArrayData { public float[] data; public int offset; } interface PVFloatArray extends PVScalarArray { int get(int offset, int len, FloatArrayData data); int put(int offset, int len, float[]from, int fromOffset); void shareData(float[] from); } public class DoubleArrayData { public double[] data; public int offset; } interface PVDoubleArray extends PVScalarArray { int get(int offset, int len, DoubleArrayData data); int put(int offset, int len, double[]from, int fromOffset); void shareData(double[] from); } public class StringArrayData { public String[] data; public int offset; } interface PVStringArray extends PVScalarArray { int get(int offset, int len, StringArrayData data); int put(int offset, int len, String[]from, int fromOffset); void shareData(String[] from); } public class StructureArrayData { public PVStructure[] data; public int offset; } interface PVStructureArray extends PVArray { StructureArray getStructureArray(); int get(int offset, int length, StructureArrayData data); int put(int offset,int length, PVStructure[] from, int fromOffset); void shareData(PVStructure[] from); } public class UnionArrayData { public PVUnion[] data; public int offset; } interface PVUnionArray extends PVArray{ UnionArray getUnionArray(); int get(int offset, int length, UnionArrayData data); int put(int offset,int length, PVUnion[] from, int fromOffset); void shareData(PVUnion[] from); }
NOTES:
- Unsigned types
- The implementation for each unsigned integer is the same as for the same signed type. This is because Java does not implement unsigned primitive types.
- PVStructureArray and PVUnionArray
- A client can only access the data in the
elements of the array via the get and put methods, i.e. it is not possible to
access subfields indirectly.
PVStructureArray.getNumberFields()
returns 1, i.e. the field looks like a leaf field.
PVStructure
The interface for a structure is:
interface PVStructure extends PVField , BitSetSerializable{ Structure getStructure(); PVField[] getPVFields(); PVField getSubField(String fieldName); PVField getSubField(int fieldOffset); <T extends PVField> T getSubField(Class<T> c, String fieldName); <T extends PVField> T getSubField(Class<T> c, int fieldOffset); // The following are convenience methods // Note that they are no longer needed because of above generic methods PVBoolean getBooleanField(String fieldName); PVByte getByteField(String fieldName); PVShort getShortField(String fieldName); PVInt getIntField(String fieldName); PVLong getLongField(String fieldName); PVFloat getFloatField(String fieldName); PVDouble getDoubleField(String fieldName); PVString getStringField(String fieldName); PVScalarArray getScalarArrayField(String fieldName); PVStructureArray getStructureArrayField(String fieldName); PVStructure getStructureField(String fieldName); PVArray getArrayField(String fieldName,ScalarType elementType); PVUnion getUnionField(String fieldName); PVUnionArray getUnionArrayField(String fieldName); public boolean checkValid(); }
where
- getStructure
- Get the introspection interface for the structure.
- getPVFields
- Returns the array of subfields. The set of subfields must all have different field names.
- getSubField(String fieldName)
- Get a subfield of the
PVStructure
. If the field does not exist null is returned. fieldName can be the name of an immediate subfield. More generally it can be the name of the field relative to thePVStructure
. In other words it consists of one or more strings separated by periods (.s). The last of these strings is the name of the field. The other strings are the names of the structure subfields containing the requested field starting with the highest level subfield and descending to the leaf field, e.g. current.alarm.status. - getSubField(int fieldOffset)
- Get the field located a
fieldOffset
, wherefieldOffset
is relative to the top-level structure. This returns null if the specified field is not located within thisPVStructure
. - getSubField - generic versions
- These are the methods to that get a subfield and convert it to the proper type. These two methods replace all the type specific methods, which are no longer required and should not be used.
PVDataCreate
PVDataCreate
is an interface that provides methods that create PVField
interfaces. A factory is provided that creates PVDataCreate
.
interface PVDataCreate { PVField createPVField(Field field); PVField createPVField(PVField fieldToClone); PVScalar createPVScalar(Scalar scalar); PVScalar createPVScalar(ScalarType fieldType); PVScalar createPVScalar(PVScalar scalarToClone); <T extends PVScalar, TA extends PVScalarArray> T createPVScalar( PVScalarType<T, TA> scalarType); PVScalarArray createPVScalarArray(ScalarArray array); PVScalarArray createPVScalarArray(ScalarType elementType); PVScalarArray createPVScalarArray(PVScalarArray arrayToClone; <T extends PVScalar, TA extends PVScalarArray> TA createPVScalarArray( PVScalarType<T, TA> elementType); PVStructureArray createPVStructureArray(StructureArray structureArray); PVUnionArray createPVUnionArray(UnionArray unionArray); PVUnionArray createPVVariantUnionArray(); PVStructure createPVStructure(Structure structure); PVStructure createPVStructure(String[] fieldNames,Field[] fields); PVStructure createPVStructure(PVStructure structToClone); PVUnion createPVUnion(Union union); PVUnion createPVVariantUnion(); PVUnion createPVUnion(PVUnion unionToClone); PVStructureArray createPVStructureArray(Structure structure); PVUnionArray createPVUnionArray(Union union); PVField[] flattenPVStructure(PVStructure pvStructure); }where
- createPVField
- The
PVField
is created reusing theField
interface. Two methods are provided. Each calls the correspondingcreatePVScalar
, createPVArray, orcreatePVStructure
depending in the type of the argument. - createPVScalar
- Creates an instance of a
PVScalar
. Three versions are supplied. The first is passed an introspection interface. The second provides the field name and the scalarType. The third provides a field name and aPVScalar
to clone. The newly createdPVScalar
will have the same auxInfos as the original. The last is a generic version that casts to the appropriate type. An example is:PVDouble value = pvDataCeate.createPVScalar(PVScalarType.pvDouble);
- createPVScalarArray
- Create an instance of a
PVArray
. Three versions are supplied. The first is passed an introspection interface. The second provides and the elementType. The third provides an array to clone. The newly createdPVArray
will have the same values as the original. The last is a generic version that casts to the appropriate type. An example is:PVDoubleArray value = pvDataCeate.createPVScalarArray(PVScalarType.pvDouble);
- createPVStructureArray
- Create a
PVStructureArray
. It must be passed a structureToClone. This will become theStructure
interface for ALL elements of thePVStructureArray
. It MUST be used to create any new array elements. - createPVUnionArray
- Create a
PVUnionArray
. It must be passed a union. This will become the union interface for ALL elements of thePVUnionArray
. It MUST be used to create any new array elements. - createPVVariantUnionArray
- Create a variant
PVUnionArray
. Each array element can have any type. - createPVStructure
- Create an instance of a
PVStructure
. Three methods are provided. The first method uses a previously created structure introspection interface. The second called with fieldName array and aField
array. The third initializes the subfields by cloning the fields contained instructToClone
. The newly created subfields will have the same values and AuxInfos as the original. IfstructToClone
is null then the new structure is initialized to have 0 subfields. - createPVUnion
- Create a
PVUnion
. Two versions are provided. The first is passed aUnion
interface the single subfield. The second is passed aPVUnion
to clone. - createPVVariantUnion
- Create a variant
PVUnion
. The subfield can have any type. - flattenPVStructure
- Create an array of
PVField
s for the fields in thePVStructure
. The order is according tofieldOffset
.
Convert
NOTE: copying immutable array fields. If an entire immutable array
field is copied to another array that has the same elementType, both offsets
are 0, and the length is the length of the source array, then the shareData
method of the target array is called and the target array is set immutable.
Thus the source and target share the same primitive array.
This section describes the supported conversions between data types.
- All supported types can be converted to a string. If you ask for a 100 megabyte array to be converted to a string expect a lot of output.
- Conversion from a string to a scalar type.
- Conversion from an array of strings to an array of scalar types.
- Copy between the following types of scalar PVs
- Numeric type to another numeric type
- Both have the same type.
- Either is a string
- Copy between
PVArray
s that satisfy one of the following.- Numeric to numeric
- Both have the same type.
- Either is a string.
- Conversions between numeric scalar types.
- Conversions between arrays of numeric type.
- Conversion between compatible structures.
- Support for unsigned integers. Because Java does primitive unsigned
integers the only support is in "widening" operations.
For example if a
PVUByte
is converted to short then the proper conversion will be done. - A utility method the returns the full field name of a field.
interface Convert { void getFullFieldName(StringBuilder builder,PVField pvField) void getString(StringBuilder buf,PVField pv, int indentLevel); void getString(StringBuilder buf,PVField pv); void fromString(PVScalar pv,String from); void fromString(PVScalarArray pv,String from); int fromStringArray(PVScalarArray pv, int offset, int len, String[]from, int fromOffset); int toStringArray(PVScalarArray pv, int offset, int len, String[]to, int toOffset); boolean isCopyCompatible(Field from, Field to); void copy(PVField from,PVField to); boolean isCopyScalarCompatible(Field from, Field to); void copyScalar(PVField from, PVField to); boolean isCopyScalarArrayCompatible(ScalarArray from, ScalarArray to); int copyScalarArray(PVScalarArray from, int offset, PVScalarArray to, int toOffset, int len); boolean isCopyStructureCompatible(Structure from, Structure to); void copyStructure(PVStructure from, PVStructure to); boolean isCopyUnionCompatible(Union from, Union to); void copyUnion(PVUnion from, PVUnion to); boolean isCopyStructureArrayCompatible(StructureArray from, StructureArray to); void copyStructureArray(PVStructureArray from, PVStructureArray to); boolean isCopyUnionArrayCompatible(UnionArray from, UnionArray to); void copyUnionArray(PVUnionArray from, PVUnionArray to); // For the following the pv Type must be PVByte, ...., PVDouble byte toByte(PVField pv); short toShort(PVField pv); int toInt(PVField pv); long toLong(PVField pv); float toFloat(PVField pv); double toDouble(PVField pv); String toString(PVScalar pv); void fromByte(PVField pv, byte from); void fromShort(PVField pv, short from); void fromInt(PVField pv, int from); void fromLong(PVField pv, long from); void fromUByte(PVField pv, byte from); void fromUShort(PVField pv, short from); void fromUInt(PVField pv, int from); void fromULong(PVField pv, long from); void fromFloat(PVField pv, float from); void fromDouble(PVField pv, double from); // For the following the element type must be pvByte, ...., pvDouble int toByteArray(PVScalarArray pv, int offset, int len, byte[]to, int toOffset); int toShortArray(PVScalarArray pv, int offset, int len, short[]to, int toOffset); int toIntArray(PVScalarArray pv, int offset, int len, int[]to, int toOffset); int toLongArray(PVScalarArray pv, int offset, int len, long[]to, int toOffset); int toFloatArray(PVScalarArray pv, int offset, int len, float[]to, int toOffset); int toDoubleArray(PVScalarArray pv, int offset, int len, double[]to, int toOffset); int fromByteArray(PVScalarArray pv, int offset, int len, byte[]from, fromOffset); int fromShortArray(PVScalarArray pv, int offset, int len, short[]from, fromOffset); int fromIntArray(PVScalarArray pv, int offset, int len, int[]from, fromOffset); int fromLongArray(PVScalarArray pv, int offset, int len, long[]from, fromOffset); int fromUByteArray(PVScalarArray pv, int offset, int len, byte[]from, fromOffset); int fromUShortArray(PVScalarArray pv, int offset, int len, short[]from, fromOffset); int fromUIntArray(PVScalarArray pv, int offset, int len, int[]from, fromOffset); int fromULongArray(PVScalarArray pv, int offset, int len, long[]from, fromOffset); int fromFloatArray(PVScalarArray pv, int offset, int len, float[]from, fromOffset); int fromDoubleArray(PVScalarArray pv, int offset, int len, double[]from, fromOffset); void newLine(StringBuilder builder, int indentLevel); }
The array methods all return the number of elements copied or converted.
This can be less than len
if the
PVField
array contains less than len elements.
newLine
is a convenience method
for code that implements toString
It
generates a newline and inserts blanks at the beginning of the newline.
The getString methods dump the data in the metadata syntax described in the
pvData project overview. Note that the toString
methods of PVField
are
implemented by calling these convert methods.
StandardField and StandardPVField
Warning:
The concept of StandardField
is closely related to property which is described below.
The section on property provides details about alarm,
timeStamp, display, control, and enumerated.
That section should be read in conjunction with this section.
A standard field is a field that tools know how to use. pvData defines and provides support for the following standard fields.
- enumerated
- This is a structure that has two subfields: index, and choices
- value
- This is any field with the name "value". It can be any type. The other standard fields can provide "properties" for the value field.
- timeStamp
- Encodes a time stamp. It can be a standalone field or be a property if a value field, in which case it should be a subfield of the same structure as the value field.
- alarm
- Encodes an alarm. It is normally a property if a value field, in which case it should be a subfield of the same structure as the value field.
- display
- Encodes a set of information for displaying a scalar or scalarArray value. It is normally a property if a value field, in which case it should be a sub field of the same structure as the value field.
- control
- Encodes a set of information for limits for a scalar or scalarArray value. It is normally a property if a value field, in which case it should be a sub field of the same structure as the value field.
- valueAlarm
- Defines a set of values for setting alarm values for a scalar value. It has separate definitions for booleanAlarm, byteAlarm, shortAlarm, intAlarm, longAlarm, floatAlarm, and doubleAlarm. There is also an enumeratedAlarm for an enumerated value field.
StandardField
interface StandardField { Structure scalar(ScalarType scalarType,String properties); Structure scalarArray(ScalarType elementType, String properties); Structure structureArray(Structure structure,String properties); Structure enumerated(); Structure enumerated(String properties); Structure alarm(); Structure timeStamp(); Structure display(); Structure control(); Structure booleanAlarm(); Structure byteAlarm(); Structure shortAlarm(); Structure intAlarm(); Structure longAlarm(); Structure floatAlarm(); Structure doubleAlarm(); Structure enumeratedAlarm(); }where
- scalar
- Create a
Structure
that has a scalar field named value and with the specifiedScalarType
. The structure can have additional fields that are properties of the value field. properties is some combination of alarm, timeStamp, display, control, and valueAlarm. - scalarArray
- Create a
Structure
that has a scalarArray field named value and with the specified element type. The structure can have additional fields that are properties of the value field. properties is some combination of alarm, timeStamp, display, and control. - structureArray
- Create a Structure that has a structureArray field named value and with the specified structure as the introspection interface for each array element. The structure can have additional fields that are properties of the value field. properties is some combination of alarm and timeStamp.
- enumerated()
- Create an enumerated
Structure
- enumerated(String properties)
- Create a Structure that has an enumerated structure field named value. The structure can have additional fields that are properties of the value field. properties is some combination of alarm, timeStamp, and enumeratedAlarm.
- alarm
- Create an alarm
Structure
. - timeStamp
- Create a timeStamp
Structure
. - display
- Create an display
Structure
. - control
- Create a control
Structure
. - booleanAlarm
- Create a booleanAlarm
Structure
. - byteAlarm
- Create a byteAlarm
Structure
. - shortAlarm
- Create a shortAlarm
Structure
. - intAlarm
- Create a intAlarm
Structure
. - longAlarm
- Create a longAlarm
Structure
. - floatAlarm
- Create a floatAlarm
Structure
. - doubleAlarm
- Create a doubleAlarm
Structure
. - enumeratedAlarm
- Create a enumearatedAlarm
Structure
.
StandardPVField
interface StandardPVField { PVStructure scalar(ScalarType type,String properties); PVStructure scalarArray(ScalarType elementType, String properties); PVStructure structureArray(Structure structure,String properties); PVStructure enumerated(String[] choices); PVStructure enumerated(String[] choices,String properties); }where
- scalar
- Create a
PVStructure
that has a scalar field named value and with the specifiedScalarType
. The structure can have additional fields that are properties of the value field. properties is some combination of alarm, timeStamp, display, control, and valueAlarm. - scalarArray
- Create a
PVStructure
that has a scalarArray field named value and with the specified elementType. The structure can have additional fields that are properties of the value field. properties is some combination of alarm, timeStamp, display, and control. - structureArray
- Create a
PVStructure
that has a structureArray field named value and with the specified structure as the introspection interface for each array element. The structure can have additional fields that are properties of the value field. properties is some combination of alarm and timeStamp. - enumerated(String[] choices)
- Create an enumerated
PVStructure
. The choices field is initialized with choices and set immutable. - enumerated(String[] choices,String properties)
- Create a
PVStructure
that has an enumerated structure field named value. The choices field of value is initialized with choices and set immutable. The structure can have additional fields that are properties of the value field. properties is some combination of alarm, timeStamp, and enumeratedAlarm.
Examples
Accessing pvData
Assume that code wants to access two fields from a PVStructure
:
- value
- Must be a
PVDouble
. - timeStamp
- Just look for field with this name.
The following code uses introspection to get the desired information.
String getValueAndTimeStamp(PVStructure pvStructure) { PVField valuePV = pvStructure.getSubField("value"); if(valuePV==null) { return "value field not found"; } if(valuePV.getField.getType!=Type.scalar) { return "value field is not a scalar"; } Scalar scalar = (Scalar)valuePV.getField(); if(scalar.getScalarType!=ScalarType.pvDouble) { return "value field is not a double"; } PVDouble pvDouble = (PVDouble)valuePV; PVField timeStampPV = pvStructure.getSubField("timeStamp"); if(timeStampPV==null) { return "timeStamp field not found"; } double value = valuePV.get(); return value + " timeStamp " + timeStampPV.toString(); }
Creating pvData
Example of creating a scalar field.
PVDataCreate pvDataCreate = PVDataFactory.getPVDataCreate(); PVDouble pvValue = pvDataCreate.createPVScalar(ScalarType.pvDouble);
Create a structure.
FieldCreate fieldCreate = FieldFactory.getFieldCreate(); PVDataCreate pvDataCreate = PVDataFactory.getPVDataCreate(); PVStructure create() { Field[] fields = new Field[2]; String[] fieldNames = new String[2]; fields[0] = fieldCreate.createScalar(ScalarType.pvLong); fields[1] = fieldeCreate.createScalar(ScalarType.pvInt); fieldNames[0] = "a"; fieldNames[1] = "b"; PVStructure pvStructure = pvDataCreate.createPVStructure( fieldNames,fields); return(pvStructure); }
FieldBuilder provides an easier way to accomplish the previous:
PVStructure create() { return pvDataCreate.createPVStructure( fieldCreate.createFieldBuilder() .add("a",ScalarType.pvLong) .add("b",ScalarType.pvInt) .createStructure()); }
StandardPVField also provides an easy way to create fields. For example:
StandardPVField standardPVField = StandardPVFieldFactory.getStandardPVField(); PVStructure pvStructure = standardPVField.scalar( ScalarType.pvDouble, "alarm,timeStamp.display,control,valueAlarm");
Package org.epics.pvdata.factory
This package provides factories and classes to implement everything defined in package org.epics.pvdata.pv Look at the code for details.
Package org.epics.pvdata.property
Definition of Property
A field can have properties provided by other fields in the same structure. Often this field has the name value A record can have multiple value fields, which can appear in the top-level structure of a record or in a substructure. All other fields in the structure containing a value field are considered properties of the value field. The field name is also the property name. The value field can have any type, i.e. scalar, scalarArray, or structure. Typical property fields are timeStamp, alarm, display, control, and history. The timeStamp is a special case. If it appears anywhere in the structure hierarchy above a value field it is a property of the value field.
For example the following top-level structure has a single value field. The value field has properties alarm, timeStamp, and display.
structure counterOutput double value alarm_t int severity 0 int status 0 string message double value display_t double limitLow 0.0 double limitHigh 10.0 string description "Sample Description" string format "%f" string units volts
The following example has three value fields each with properties alarm and timeStamp. Voltage, Current, and Power each have a different alarms but all share the timeStamp.
structure powerSupplyValue double value alarm_t int severity 0 int status 0 string message structure powerSupplySimple alarm_t int severity 0 int status 0 string message timeStamp_t long secondsPastEpoch int nanoseconds int userTag powerSupplyValue_t voltage double value alarm_t int severity 0 int status 0 string message powerSupplyValue_t power double value alarm_t int severity 0 int status 0 string message powerSupplyValue_t current double value alarm_t int severity 0 int status 0 string message
Standard Properties
The following field names have special meaning, i.e. support properties for general purpose clients.
- value
- This is normally defined since most general purpose clients access this
field. All other fields in the structure support or describe the value
field. The type can any supported type but is usually one of the
following:
- scalar
- Any of the scalar types.
- scalarArray
- An array with
elementType
being a scalar type - enumerated structure
- A structure that includes fields named index and choices. index is an int that selects a choice. choices is an array of strings that defines the complete set of choices.
- other
- Other structure or array types can also be defined if clients and support code agree on the meaning. Some examples are: 1) A structure defining a 2D matrix, 2) A structure defining an image, 3) A structure that simulates a remote method, ...
- timeStamp
- The timeStamp. The type MUST be a timeStamp structure. Also if the pvData structure does not have a timeStamp then a search up the parent tree is made to find a timeStamp.
- alarm
- The alarm. The type MUST be an alarm structure.
- display
- A display structure as described below. It provides display characteristics for the value field.
- control
- A control structure as described below. It provides control characteristics for the value field.
- history
- Provides a history buffer for the value field. Note that currently pvData does not define history support.
- other
- Other standard properties can be defined.
In addition a structure can have additional fields that support the value field but are not recognized by most general purpose client tools. Typical examples are:
- input
- A field with support that changes the value field. This can be anything. It can be a channel access link. It can obtain a value from hardware. Etc.
- valueAlarm
- A field with support that looks for alarm conditions based on the value.
- output
- A field with support that reads the current value and sends it somewhere else. This can be anything. It can be a channel access link. It can write a value to hardware etc.
The model allows for device records. A device record has structure fields that that support the pvData data model. For example a powerSupport record can have fields power, voltage and current that each support the pvData data model.
PVProperty Interfaces and Classes
PVProperty
Interface and factory for finding a field within a structure.
interface PVProperty { PVField findProperty(PVField pvField,String fieldName); PVField findPropertyViaParent(PVField pvField,String propertyName); String[] getPropertyNames(PVField pvField); }where
- findProperty
- Find a field that is a subfield or property of this
PVField
. The fieldName is of the form name.name...pvField
must be named value or it does not have properties. - findPropertyViaParent
- Find a property by searching up the parent tree. The property name is expected to match the name of a field. The return value is the interface to the first field found that is not a null structure or null if not found.
- getPropertyNames
- Get a String array that holds the names of the properties for this field.
PVPropertyFactory
public class PVPropertyFactory { public static PVProperty getPVProperty(); }
Standard Properties
This section has structure definitions that support standard properties. These definitions are defined in project javaIOC.
timeStamp
A timeStamp is represented by the following structure
structure timeStamp long secondsPastEpoch int nanoseconds int userTag
The Epoch is the POSIX epoch, i.e. Jan 1, 1970 00:00:00 UTC. Both the seconds and nanoseconds are signed integers and thus can be negative. Since the seconds is kept as a 64 bit integer, it allows for a time much greater than the present age of the universe. Since the nanoseconds portion is kept as a 32 bit integer it is subject to overflow if a value that corresponds to a value that is greater than a little more than 2 seconds of less that about -2 seconds. The support code always adjust seconds so that the nanoSecconds part is normalized, i. e. it has is 0<=nanoseconds<nanoSecPerSec..
TimeStamp
The Java definition of a timeStamp is:
interface TimeStamp { static final long milliSecPerSec = 1000; static final long microSecPerSec = milliSecPerSec*milliSecPerSec; static final long nanoSecPerSec = milliSecPerSec*microSecPerSec; static final long posixEpochAtEpicsEpoch = 631152000; void normalize(); long getSecondsPastEpoch(); long getEpicsSecondsPastEpoch(); int getNanoseconds(); int getUserTag(); void setUserTag(int userTag); void put(long secondsPastEpoch,int nanoseconds); long getMilliSeconds(); void put(long milliSeconds); void getCurrentTime(); boolean equals(TimeStamp other); boolean lt(TimeStamp other); boolean le(TimeStamp other); void add(long seconds); void add(double seconds); double diff(TimeStamp a,TimeStamp b); }
where:
- normalize
- Adjust secondsPastEpoch and nanoseconds so that 0<=nanoseconds< nanoSecPerSec.
- getSecondsPastEpoch
- Get the seconds part of timeStamp
- getEpicsSecondsPastEpoch
- Get seconds relative to the EPICS epoch. The epics epoch starts on Jan 1 1990 00:00:00 UTC.
- getNanoseconds
- Get the nanoseconds part of timeStamp.
- getUserTag
- Get the userTag
- setUserTag
- Set the userTag
- put(long secondsPastEpoch,int nanoseconds)
- Put a value into the timeStamp.
- getMilliSeconds
- Get the number of milliseconds since the epoch.
- put(long milliSeconds);
- Put a value into the timeStamp given the number of milliSeconds since the epoch.
- getCurrentTime
- Get the current time.
- equals
- Is this time equal other?
- lt
- Is this time less than other.
- le
- Is this time less that or equal to other.
- add(long seconds)
- Add the specified number of seconds.
- add(double seconds)
- Add the specified number of seconds.
- diff
- Compute a-b. The result is in seconds.
The TimeStamp class provides arithmetic and comparison methods for time stamps. The result is always kept in normalized form, which means that the nanosecond portion is 0≤=nano<nanoSecPerSec. Note that it is OK to have timeStamps for times previous to the epoch.
TimeStampFactory
class TimeStampFactory implements TimeStamp { public static TimeStamp create(); }
PVTimeStamp
interface PVTimeStamp { boolean attach(PVField pvField); void detach(); boolean isAttached(); void get(TimeStamp timeStamp); boolean set(TimeStamp timeStamp); }where
- attach
- Attempts to attach to
pvField
It returns (false,true) if a timeStamp structure is found. It looks first atpvField
itself and if is not an appropriate pvData structure but the field name is value it looks up the parent structure tree. - detach
- Detach from the pvData structure.
- isAttached
- Is there an attachment to a time stamp structure?
- get
- Copies data from the pvData structure to a
TimeStamp
. An exception is thrown if not attached to a pvData structure. - set
- Copies data from
TimeStamp
to the pvData structure. An exception is thrown if not attached to a pvData structure.
PVTimeStampFactory
class PVTimeStampFactory implements PVTimeStamp { public static PVTimeStamp create(); }
alarm
An alarm structure is defined as follows:
structure alarm int severity int status string message
Note that severity and status are NOT defined as enumerated structures. The reason is performance, i.e. prevent passing the array of choice strings everywhere. The AlarmStatus and AlarmSeverity provide the equivalent of choices for an enumerated structure.
AlarmSeverity
Alarm Severity defines the possible alarm severities
enum AlarmSeverity { NONE,MINOR,MAJOR,INVALID,UNDEFINED; public static AlarmSeverity getSeverity(int value); private static final String[] alarmSeverityNames; public static String[] getSeverityNames() { return alarmSeverityNames;} }where
- getSeverity
- Get the alarm severity corresponding to the integer value.
- getSeverityNames
- Get the array of severity choices.
AlarmStatus
Alarm Status defines the possible alarm status conditions
enum AlarmStatus { NONE,DEVICE,DRIVER,RECORD,DB,CONF,UNDEFINED,CLIENT; public static AlarmStatus getStatus(int value); private static final String[] alarmStatusNames; public static String[] getStatusNames() { return alarmStatusNames;} }where
- getStatus
- Get the alarm status corresponding to the integer value.
- getStatusNames
- Get the array of status choices.
Alarm
class Alarm { public Alarm(); public String getMessage(); public void setMessage(String message); public AlarmSeverity getSeverity(); public void setSeverity(AlarmSeverity alarmSeverity); public AlarmStatus getStatus(); public void setStatus(AlarmStatus alarmStatus); }where
- Alarm
- The constructor. It sets the severity to no alarm and the message to "".
- getMessage
- Get the message.
- setMessage
- Set the message.
- getSeverity
- Get the severity.
- setSeverity
- Set the severity.
- getStatus
- Get the status.
- setStatus
- Set the status.
PVAlarm
interface PVAlarm { boolean attach(PVField pvField); void detach(); boolean isAttached(); void get(Alarm alarm); boolean set(Alarm alarm); }
where
- PVAlarm
- The default constructor. Attach must be called before get or set can be called.
- attach
- Attempts to attach to
pvField
It returns (false,true) if it found an appropriate pvData structure. It looks first a pvField itself and if is not an appropriate pvData structure but the field name is value it looks to see if the parent structure has an appropriate sub structure. - detach
- Just detaches from the pvData structure.
- isAttached
- Is there an attachment to an alarm structure?
- get
- Copies data from the pvData structure to an
Alarm
. An exception is thrown if not attached to a pvData structure. - set
- Copies data from
Alarm
to the pvData structure. An exception is thrown if not attached to a pvData structure.
PVAlarmFactory
class PVAlarmFactory implements PVAlarm{ public static PVAlarm create(); }
control
Control information is represented by the following structure
structure control double limitLow double limitHigh double minStep
Control
The java definition for Control is:class Control { Control(); double getLow(); double getHigh(); double getMinStep(); void setLow(double value); void setHigh(double value); void setMinStep(double value); }
where
- Control
- The default constructor.
- getLow
- Get the low limit.
- getHigh
- Get the high limit.
- getMinStep
- Get the min step.
- setLow
- Set the low limit.
- setHigh
- Set the high limit.
- setMinStep
- Set the min step.
PVControl
interface PVControl { boolean attach(PVField pvField); void detach(); boolean isAttached(); void get(Control control); boolean set(Control control); }
where
- attach
- Attempts to attach to
pvField
It returns (false,true) if it found an appropriate pvData structure. It looks firstPVField
itself and if is not an appropriate pvData structure but the field name is value it looks to see if the parent structure has an appropriate sub-structure. - detach
- Just detaches from the pvData structure.
- isAttached
- Is there an attachment to a control structure?
- get
- Copies data from the pvData structure to a
Control
. An exception is thrown if not attached to a pvData structure. - set
- Copies data from
Control
to the pvData structure. An exception is thrown if not attached to a pvData structure. - create
- Create a PVControl instance. Attach must be called before get or set can be called.
PVControlFactory
class PVControlFactory{ public static PVControl create(); }
Display
Display information is represented by the following structure
structure display double limitLow double limitHigh string description string format string units
Display
class Display { Display(); double getLow(); double getHigh(); void setLow(double value); void setHigh(double value); String getDescription(); void setDescription(String value); String getFormat(); void setFormat(String value); String getUnits(); void setUnits(String value); }
where
- Control
- The default constructor.
- getLow
- Get the low limit.
- getHigh
- Get the high limit.
- setLow
- Set the low limit.
- setHigh
- Set the high limit.
- getDescription
- Get the description.
- setDescription
- Set the description.
- getFormat
- Get the format.
- setFormat
- Set the format.
- getUnits
- Get the units.
- setUnits
- Set the units.
PVDisplay
interface PVDisplay { boolean attach(PVField pvField); void detach(); boolean isAttached(); void get(Display display); boolean set(Display display); }
where
- attach
- Attempts to attach to
pvField
It returns (false,true) if it found an appropriate pvData structure. It looks first a pvField itself and if is not an appropriate pvData structure but the field name is value it looks to see if the parent structure has an appropriate sub structure. - detach
- Just detaches from the pvData structure.
- isAttached
- Is there an attachment to a display structure?
- get
- Copies data from the pvData structure to a
Display
. An exception is thrown if not attached to a pvData structure. - set
- Copies data from a
Display
to the pvData structure. An exception is thrown if not attached to a pvData structure. - create
- Create a
PVDisplay
instance. Attach must be called before get or set can be called.
PVDisplayFactory
class PVDisplayFactory implements PVDisplay{ public static PVDisplay create() }
enumerated structure
An enumerated structure is a structure that has fields:
structure int index string[] choices
PVEnumerated
interface PVEnumerated { boolean attach(PVField pvField); void detach(); boolean isAttached(); boolean setIndex(int index); int getIndex(); String getChoice(); boolean choicesMutable(); String[] getChoices(); boolean setChoices(String[] choices); }
where
- PVEnumerated
- The default constructor. Attach must be called before any get or set method can be called.
- attach
- Attempts to attach to
pvField
It returns (false,true) if pvField (is not, is) an enumerated structure. - detach
- Just detaches from the pvData structure.
- isAttached
- Is there an attachment to an enumerated structure?
- setIndex
- Set the index field in the pvData structure. An exception is thrown if not attached to a pvData structure.
- getIndex
- Get the index field in the pvData structure.
- getChoice
- Get the String value corresponding to the current index field in the pvData structure. An exception is thrown if not attached to a pvData structure.
- choicesMutable
- Can the choices be changed? Note that this is often true. An exception is thrown if not attached to a pvData structure.
- getChoices
- Get the array of choices. An exception is thrown if not attached to a pvData structure.
- getNumberChoices
- Get the number of choices. An exception is thrown if not attached to a pvData structure.
- setChoices
- Change the choices. An exception is thrown if not attached to a pvData structure.
PVEnumeratedFactory
class PVEnumeratedFactory{ PVEnumerated create(); }
multiChoice
NOTE: This is not currently used by anything. Bob sees it as an important facility in the future.
MultiChoice is support for a multiChoice structure, which is a structure containing two fields:
- choices
- An array of strings
- bitMask
- A bitMask that selects a subset of the choices.
MultiChoice
public interface MultiChoice { interface Choices { String[] getChoices(); int getNumberChoices(); } byte[] getBitMask(); String[] getChoices(); Choices getSelectedChoices(); void setBit(int index); void clear(); int registerChoice(String choice); }
where
- getBitMask
- Returns the bitMask.
- getChoices
- Returns the complete set of choices..
- getSelectedChoices
- Returns the interface for getting the selected choices..
- setBit
- Select the choice for specified bit..
- clear
- Clear the bitMask, i.e. no choices are selected..
- registerChoice
- Register a new choice. If the choice already exists then it's index is returned. If not it is appended to the choices.
MultiChoiceFactory
public class MultiChoiceFactory{ public static MultiChoice getMultiChoice(PVField pvField); }
Package org.epics.pvdata.misc
Overview
This package provides utility code:
- BitSet
- An implementation of
BitSet
that can be serialized. - MessageQueue
- Support for queuing messages for requesters.
- Thread
ThreadCreate
andExecutor
- TimeFunction
- Time how long a function call requires.
- LinkedList
- A double linked list facility that requires the user to allocate a
node. It is more efficient that
ArrayList
and does not require the implementation to allocate storage for the nodes. - Timer
- An implementation of
Timer
that does not require an object to be created for each timer request. - Queue
- A queue implementation.
- Destroyable
- A base interface for destroy.
- Serialize
- A helper for serialization.
bitSet
BitSet
This is adapted from the java.util.BitSet. It adds serializable. See
java.util.BitSet
for a description. This implementation adds the following
additional methods:
public boolean getAndSet(int bitIndex); public void set(BitSet src); public void or_and(BitSet set1, BitSet set2);
where
- getAndSet
- gets and sets the bit at bitIndex.
- set
- fast copy operation from src to
bitSet
- or_and
- The result is the or of the current bitSet with the value of set1.and set2. The number of bits is the Math.max(set1.bitsInUse,set2.bitsInUse);
This is an implementation of BitSet
that supports serialization, which the
standard Jave implementation does not allow.
BitSetUtil
interface BitSetUtil { boolean compress(BitSet bitSet,PVStructure pvStructure); }
This provides functions that operate of a BitSet for a PVStructure
. It
currently has only one method:
- compress
- Compress the bits in a
BitSet
related to a structure.
For each structure:- If the bit for the structure is set then the bit for all subfields of the structure are cleared.
- If the bit for the structure is not set but all immediate subfields have their bit set then the bit for the structure is set and the bits for all subfields are cleared.
- Channel Access can call this before sending data. It can then pass entire structures if the structure offset bit is set.
BitSetUtilFactory
class BitSetUtilFactory { public static BitSetUtil getCompressBitSet(); }
Message Queue
MessageNode
public class MessageNode { public String message; public MessageType messageType; }
MessageQueue
public interface MessageQueue { MessageNode get(); boolean put(String message,MessageType messageType,boolean replaceLast); boolean isEmpty(); boolean isFull(); int getClearOverrun(); }
This is for use by code that wants to handle messages without blocking higher priority threads.
MessageNode
is a class with two public data members:
- message
- The message.
- messageType
- The message type.
MessageQueue
is an interface with methods:
- put
- Put a new message into the queue. False is returned if the queue was full and true otherwise.
- isEmpty
- Is the queue empty?
- isFull
- Is the queue full?
- getClearOverrun
- Get the number of times
replaceFirst
orreplaceLast
have been called since the last call togetClearOverrun
. The internal counter is reset to 0.
MessageQueueFactory
public class MessageQueueFactory { public static MessageQueue create(int size); }where
- create
- Create a
MessageQueue
and return the interface.
thread
ThreadPriority
public enum ThreadPriority { lowest, lower, low, middle, high, higher, highest; public static final int[] javaPriority; public int getJavaPriority(); public static int getJavaPriority(ThreadPriority threadPriority); }
ThreadReady
interface ThreadReady { void ready(); }
RunnableReady
interface RunnableReady { void run(ThreadReady threadReady); }
ThreadCreate
interface ThreadCreate { Thread create(String name, int priority, RunnableReady runnableReady); Thread[] getThreads(); }
ThreadCreateFactory
public class ThreadCreateFactory { public static ThreadCreate getThreadCreate(); }
ThreadCreate provides two features:
- Create does not return until
ReadyRunnable.run
callsThreadReady.ready()
. - A list of all active threads is kept. getThreads provides access to the list.
executor
An Executor
is a thread that can execute any object that implements the Java
Runnable
interface. The user can request that a single command be executed. If
the command is already in the list of commands to be executed it is NOT added
to the list when add is called.
ExecutorNode
public interface ExecutorNode {}
Executor
public interface Executor { ExecutorNode createNode(Runnable command); void execute(ExecutorNode executorNode); void stop(); }
ExecutorFactory
public class ExecutorFactory { static public Executor create(String name,ScanPriority priority); }where
- createNode
- Create a ExecutorNode that can be passed to execute.
- execute
- Request that command be executed. If it is already on the run list nothing is done.
- stop
- Stop the thread and refuse additional execute requests.
time a function call
TimeFunction is a facility that measures the average number of seconds a
function call requires. When timeCall
is called, it calls function in a loop.
It starts with a loop of one iteration. If the total elapsed time is less then
.1 seconds it increases the number of iterations by a factor of 10. It keeps
repeating until the elapsed time is greater than .1 seconds. It returns the
average number of seconds per call.
TimeFunctionRequester
public interface TimeFunctionRequester { void function(); }
TimeFunction
public interface TimeFunction { double timeCall(); }
TimeFunctionFactory
public class TimeFunctionFactory { public static TimeFunction create(TimeFunctionRequester requester); }
linked list
LinkedList implements a double linked list that requires a user to allocate
the nodes. It is more efficient that ArrayList
for implementing stacks and
queues. For lists that are traversed while new elements can be added or
removed, LinkedListArray
provides a way to get an array of the current
elements without allocating a new array each time the array is traversed.
LinkedListArray
converts a LinkedList
to an LinkNode
array. The
implementation provided by LinkedListFactory
only creates a new LinkNode
array
w.en the number of elements in the linkedList passed to setNodes is greater
than the length of the current LinkNode
array.
LinkedListNode
public interface LinkedListNode<T> { public T getObject(); boolean isOnList(); }
LinkedList
public interface LinkedList { void addTail(LinkedListNode<T> listNode); void addHead(LinkedListNode<T> listNode); void insertAfter(LinkedListNode<T> listNode,LinkedListNode<T> addNode); void insertBefore(LinkedListNode<T> listNode,LinkedListNode<T> addNode); LinkedListNode<T> removeTail(); LinkedListNode<T> removeHead(); void remove(LinkedListNode<T> listNode); void remove(T object); LinkedListNode<T> getHead(); LinkedListNode<T> getTail(); LinkedListNode<T> getNext(LinkedListNode<T> listNode); LinkedListNode<T> getPrev(LinkedListNode<T> listNode); boolean isEmpty(); boolean contains(T object); }
LinkedListArray
public interface LinkedListArray<T> { void setNodes(LinkedList<T> linkedList); LinkedListNode<T>[] getNodes(); int getLength(); void clear(); }
LinkedListCreate
public class LinkedListCreate<T> { public static LinkedList<T> create(); public static LinkedListNode<T> createNode(Object object); public static LinkedListArray<T> createArray(); }
LinkedListCreate is created as follows:
LinkedListCreate<SomeObject> linkedListCreate = new LinkedListCreate<SomeObject>();
Then a linked list can be created as follows:
LinkedList<SomeObject> linkedList = linkedListCreate.create();
The only way a node can be allocated is by calling
linkedListCreate.createNode(object)
. The object passed to createNode
is what is returned by LinkedList.getObject
. For example:
private static class SomeObject { private LinkedListNode<SomeObject> listNode = null; // other definitions private Node(/* arguments*/) { listNode = linkedListCreate.createNode(this); } LinkedListNode<SomeObject> getListNode() {return listNode}; } // then SomeObject someObject = new SomeObject(/* args */); linkedList.addTail(someObject);
A node can only be on one list at a time but can be put, at different times, on different lists as long as they all hold the same type of objects.
The class does not provide a lock but the user can synchronized via calls like:
synchronized(linkedList) { linkedList.addTail(listNode); }
The following is an example of how to use LinkedListArray.
LinkedListNode<SomeObject>[] nodes = null; int length = 0; synchronized(linkedList) { linkedListArray.setNodes(linkedList); nodes = linkedListArray.getNodes(); length = linkedListArray.getLength(); } for(int i=0; i<length; i++) { SomeObject object = nodes[i].getObject(); // do something with object }
timer
This provides a general purpose timer. It provides the following features
not provided by java.util.Timer
and java.util.TimerTask
:
- Priority
The java.util implementation does not allow the user to specify the priority of the timer thread. This implementation does. - TimerNode
A java.util.TimerTask is not reusable. Once aTimerTask
has been canceled or a delayTimerTask
has run, theTimerTask
can not be reused. Instead a newTimerTask
must be created. ATimerNode
can be reused.
Timer
interface Timer { interface TimerCallback { void callback(); void timerStopped(); } interface TimerNode { void cancel(); boolean isScheduled(); } void scheduleAfterDelay(TimerNode timerNode,double delay); void schedulePeriodic(TimerNode timerNode,double delay,double period); void stop(); }
This is the interface for scheduling a timer callback. A timer is created by
calling TimerFactory.create
. It has the methods:
- scheduleAfterDelay
- A request to schedule a callback after a delay specified in seconds. If
stop has been called then
TimerCallback.timerStopped
is called immediately. - schedulePeriodic
- Schedule a periodic callback. If stop has been called then
TimerCallback.timerStopped
is called immediately. - stop
- Stop the timer. The queue is emptied and
TimerCallback.timerStopped
is called for each element of the queue. Further schedule calls result in a call toTimerCallback.timerStopped
. Once stopped a timer is no longer useful. A new timer must be created.
TimerFactory
class TimerFactory { static public Timer create(String threadName, ThreadPriority priority); static public TimerNode createNode(TimerCallback timerCallback); }
This is the factory that implements the Timer
and TimerNode
interfaces. It
has the methods:
- create
- Create a new Timer.
- createNode
- Create a
TimerNode
. ATimerNode
can be used to schedule any timer but aTimerNode
can only be on a single timer queue and only once on a given timer queue.
TimerCallback
This is an interface that must be implemented by the user. It has the following methods:
- callback
- This is called when a timer expires. This is called with no locks held.
When called a delay timer is no longer on the queue but a periodic timer
is on a queue. Thus the callback for a delay timer can issue a new
schedule request but a periodic timer must not. Note the explanation of
TimerNode.cancel
below. - timerStopped
Timer.stop
was called when a timer request was queued. or if the timer is stopped and a schedule request is made.
TimerNode
This is an interface implemented by TimerFactory
. It is allocated by calling
TimerFactory.createNode
. It is passed as an argument when scheduling a
callback. It has the single method:
- cancel
- This is called to cancel a timer request. If a callback has been dequeued but the callback not called when cancel is called then a callback may still happen. New schedule requests can be made after a cancel request has been made.
- isScheduled
- Is this node in the timerQueue.
queue
This provides a queue which has an immutable capacity, which is specified
when the queue is created. When the queue is full the user code is expected to
keep using the current element until a new free element becomes available. This
is used by pvData.monitor
.
QueueCreate
public class QueueCreate<T> { public Queue<T> create(QueueElement<T>[] queueElements) { return new QueueImpl<T>(queueElements); } public QueueElement<T> createQueueElement(T object) { return new QueueElementImpl<T>(object); } }
QueueElement
public interface QueueElement<T> { public T getObject(); }
Queue
public interface Queue<T> { void clear(); int getNumberFree(); int capacity(); QueueElement<T> getFree(); void setUsed(QueueElement<T> queueElement); QueueElement<T> getUsed(); void releaseUsed(QueueElement<T> queueElement); }
The queue methods are:
- clear
- Make the queue empty.
- getNumberFree
- Get the number of fee elements in the queue.
- capacity
- Get the capacity, i.e. the maximum number of elements the queue can hold.
- getFree
- Get the next free element. Null is returned if no free elements are available. If a non null value is returned then the element belongs to the caller until setUsed is called.
- setUsed
- Set a queue element used. This must be the element returned by the last call to getFree.
- getUsed
- Get the next used element of null if no more used elements are available.
- releaseUsed
- Set a queue element free. This must be the element returned by the last call to getUsed.
A QueueCreate
instance is created via a call like the following:
QueueCreate<MyObject> queueCreate = new QueueCreate<MyObject>();
Once a queueCreate is available a queue instance is created via code like the following:
Queue<MyObject> queue create(MyObject[] myObjects) { QueueElement<MyObject>[] queueElements = new QueueElement[length]; for(int i=0; i<length; i++) { QueueElement<MonitorElement> queueElement = queueCreate.createQueueElement(myObjects[i); queueElements[i] = queueElement; } return queueCreate.create(queueElements); }
A producer calls getFree
and setUsed
via code like the following:
MyObject getFree() { QueueElement<MyObject> queueElement = queue.getFree(); if(queueElement==null) return null; return queueElement.getObject(); }
A consumer calls getUsed and releaseUsed via code like the following:
while(true) { QueueElement<MyObject> queueElement = queue.getUsed(); if(queueElement==null) break; MyObject myObject = queueElement.getObject(); // do something with myObject queue.releaseUsed(queueElement); }
Destroyable
This is a base interface used by many other interfaces.
interface Destroyable { void destroy(); }
where
- destroy
- Destroy the object.
SerializeHelper
This is a helper class for serialization, which is required for sending and receiving pvData over the network.
class SerializeHelper { static void writeSize(final int s, ByteBuffer buffer); static int readSize(ByteBuffer buffer); static void serializeString(final String value, ByteBuffer buffer); static void serializeSubstring(final String value, int offset, int length, ByteBuffer buffer); static String deserializeString(ByteBuffer buffer); }
where
- writeSize
- Serialize the size.
- readSize
- Deserialize the size.
- serializeString
- Serialize a String.
- serializeSubstring
- Serialize a substring.
- deserializeString
- Deserialize a string.
src/copy
copy is not used in this project. It is intended for use by pvAccess and by channel providers. It is provided with this project because the code depends only on pvData itself.
copy provides the ability to create a structure that has a copy of an arbitrary subset of the fields in an existing top level structure. In addition it allows global options and field specific options. It has two main components: createRequest and pvCopy. Given a string createRequest creates a pvRequest, which is a PVStructure that has the format expected by pvCopy.
In addition pvCopy supports filter plugins. pvData implements the following filters: array, deadband, timestamp, ignore. See the developerGuide for details.
In addition the plugin API supports implementing additional plugins.
Copy provides:
- createRequest
-
The Channel create methods in pvAccess all have an argument
PVStructure pvRequest.
Given an ascii string createRequest creates a PVStructure that provides a pvData representation of the information from the ascii string. It is this structure that can be passed to the channel create methods.
The information in a pvRequest selects an arbitrary subset of the fields in a top level structure that resides in the server. In addition options can be specified. Both global and field specific options can be specified. - pvCopy
- This is a facility used by channel providers.
It provides client specific code that manages a copy of an arbitrary
subset of the fields in a top level structure that resides in the
provider. It also allows provider access to options specified
by the client.
pvCopy also provides filter plugin support.
createRequest
This is mainly used by pvAccess clients. Given a request string it creates a pvRequest structure that can be passed to the pvAccess create methods. In turn pvAccess passes the pvRequest to a local channel provider which then passes it to pvCopy.
The definition of the public members is:
class CreateRequest { ... static CreateRequestPtr create(); virtual PVStructurePtr createRequest(String const &request); String getMessage(); };
An example of how it is used is:
CreateRequestPtr createRequest = CreateRequest::create(); PVStructurePtr pvRequest = createRequest->createRequest(request); if(pvRequest==NULL) { String error = createRequest->getMessage(); // take some action } else { //success do something }
pvCopy
The definition of the public members is:
class epicsShareClass PVCopyTraverseMasterCallback { ... virtual void nextMasterPVField(PVFieldPtr const &pvField); }; class class epicsShareClass PVCopy { ... static PVCopyPtr create( PVStructurePtr const &pvMaster, PVStructurePtr const &pvRequest, String const & structureName); PVStructurePtr getPVMaster(); void traverseMaster(PVCopyTraverseMasterCallbackPtr const & callback); StructureConstPtr getStructure(); PVStructurePtr createPVStructure(); size_t getCopyOffset(PVFieldPtr const &masterPVField); size_t getCopyOffset( PVStructurePtr const &masterPVStructure, PVFieldPtr const &masterPVField); PVFieldPtr getMasterPVField(std::size_t structureOffset); void initCopy( PVStructurePtr const ©PVStructure, BitSetPtr const &bitSet); void updateCopySetBitSet( PVStructurePtr const ©PVStructure, BitSetPtr const &bitSet); void updateCopyFromBitSet( PVStructurePtr const ©PVStructure, BitSetPtr const &bitSet); void updateMaster( PVStructurePtr const ©PVStructure, BitSetPtr const &bitSet); PVStructurePtr getOptions(std::size_t fieldOffset); ... };where
- PVCopyTraverseMasterCallback::nextMasterPVField
-
PVCopyTraverseMasterCallback is a callback which must
be implemented by the code that uses pvCopy, normally
the channel provider. It has the single method nextMasterPVField
nextMasterPVField is called for each field in the master as a result of a call to traverseMaster. - create
-
This is the method for creating a PVCopy instance.
- pvMaster
- the top-level structure managed by the server.
- pvRequest
- selects the set of subfields desired and options for each field.
- structureName
- the name for the top-level of any
PVStructure
created.
- getPVMaster
-
Gets the top-level structure from
pvMaster
. - traverseMaster
-
Traverse all fields of the top-level structure of
pvMaster
. For each field the callback is called. - getStructure
-
Get the introspection interface for a
PVStructure
for copy. - createPVStructure
- Create a copy instance.
Monitors keep a queue of monitor elements.
Since each element needs a
PVStructure
, multiple top-level structures will be created. - getCopyOffset
- Given a field in
pvMaster
. return the offset in copy for the same field. A value of String::npos means that the copy does not have this field. Two overloaded methods are provided. The first is called if the field of master is not a structure. The second is for subfields of a structure. - getMasterPVField
- Given a offset in the copy get the corresponding field in pvMaster.
- initCopy
-
Initialize the fields in
copyPVStructure
by giving each field the value from the corresponding field inpvMaster
.bitSet
will be set to show that all fields are changed. This means that bit set will have the value {0}. - updateCopySetBitSet
-
Set all fields in
copyPVStructure
to the value of the corresponding field inpvMaster
. Each field that is changed has it's corresponding bit set in bitSet. - updateCopyFromBitSet
-
For each set bit in bitSet set the field in
copyPVStructure
to the value of the corresponding field inpvMaster
. - updateMaster
-
For each set bit in bitSet set the field in
pvMaster
to the value of the corresponding field incopyPVStructure
. - getOptions
-
Get the options for the field at the specified offset.
A NULL is returned if no options were specified for the field.
If options were specified, the returned
PVStructure
is a structure with a set ofPVString
subfields that specify name,value pairs. name is the subField name and value is the subField value.
src/monitor
monitor is not used in this project. It is intended for use by pvAccess and by channelProviders. It provided with this project because the code depends only on pvData itself. It is support code for channel providers that implement channel monitor. It provides support for monitor queues.
monitor
class MonitorElement { MonitorElement(PVStructurePtr const & pvStructurePtr); PVStructurePtr pvStructurePtr; BitSetPtr changedBitSet; BitSetPtr overrunBitSet; }; class Monitor { virtual Status start() = 0; virtual Status stop() = 0; virtual MonitorElementPtr poll() = 0; virtual void release(MonitorElementPtr const & monitorElement) = 0; }; class MonitorRequester : public virtual Requester { virtual void monitorConnect(Status const & status, MonitorPtr const & monitor, StructureConstPtr const & structure) = 0; virtual void monitorEvent(MonitorPtr const & monitor) = 0; virtual void unlisten(MonitorPtr const & monitor) = 0; };
monitorElement
MonitorElement holds the data for one element of a monitor queue. It has the fields:
- pvStructurePtr
- A top-level structure with data values at the time the monitors occurs.
- changedBitSet
- Shows which fields have changed since the previous monitor.
- overrunBitSet
- Shows which fields have changed more than once since the previous monitor.
monitorElement queue
A queue of monitor elements must be implemented by any channel provider that implements Channel::createMonitor. For an example implementation look at pvDatabaseCPP. It has the following:
typedef Queue<MonitorElement> MonitorElementQueue; typedef std::tr1::shared_ptr<MonitorElementQueue> MonitorElementQueuePtr; class MultipleElementQueue : public ElementQueue { public: POINTER_DEFINITIONS(MultipleElementQueue); virtual ~MultipleElementQueue(){} MultipleElementQueue( MonitorLocalPtr const &monitorLocal, MonitorElementQueuePtr const &queue, size_t nfields); virtual void destroy(){} virtual Status start(); virtual Status stop(); virtual bool dataChanged(); virtual MonitorElementPtr poll(); virtual void release(MonitorElementPtr const &monitorElement); ... };
Monitor
Monitor must be implemented by any channel provider that implements Channel::createMonitor. Remote PVAccess also implements Monitor on the client side. Note that each client has it's own queue that is not shared with other client.
Monitor has the following methods:
- start
- Start monitoring. This will result in an initial monitor that has the current value of all fields.
- stop
- Stop monitoring.
- poll
- Called to get a monitor element. If no new elements are available then a null pointer is returned.
- release
-
Release the monitor element.
The caller owns the monitor element between the calls to
poll
andrelease
.
MonitorRequester
This must be implemented by a pvAccess client. It has the methods:
- monitorConnect
- A monitor has either connected of disconnected.
- monitorEvent
- A new monitor element is available.
- unlisten
- The channel is going away. The client cam no longer access the monitor.
Package | Description |
---|---|
org.epics.pvdata.accessSecurity |
At the present time pvDataJava does not implement Access Security.
|
org.epics.pvdata.copy |
Create a structure that has a copy of an arbitrary subset of the fields in an existing top level structure.
|
org.epics.pvdata.factory |
This package implements the interfaces defined in org.epics.pvdata.pv.
|
org.epics.pvdata.misc |
This package provides a number of utility classes that are used by pvData code.
|
org.epics.pvdata.monitor |
This package has the interface and class definitions for code to monitor
changes to fields in a pvData structure.
|
org.epics.pvdata.property |
This package contains interfaces and code for standard pvData structure fields.
|
org.epics.pvdata.pv |
This package contains the interface definitions for the Java implementation of pvData.
|
org.epics.pvdata.util.namedValues |
This package implements a system of named values in which the values may be Vectors, and is useful then for constructing and manipulating and formatting logical tables of data.
|
org.epics.pvdata.util.pvDataHelper |
This package defines utility classes to help get data out of pvData array containers.
|