@@ -95,12 +97,12 @@ V4 control system programming environment:
Status of this Document
-
This is the 27-Nov-2012 version of the definition of pvDatabaseCPP.
-This is the original version.
+
This is the 11-Dec-2012 version of the definition of pvDatabaseCPP.
This is the beginning of the implementation of pvDataBaseCPP.
It describes the features that will be provided.
-The class definitions for PVRecord and PVDatabase are defined but not implemented.
+The class definitions for PVRecord are implemented.
+The class definition for PVDatabase are defined but not implemented.
The classes in pvDatabase.h implement a database of memory resident
-smart records. The next subsection has the definitions for all the classes
-defined in this header file.
+smart records.
It describes the following classes:
PVRecord
This provides the methods required by localChannelProvider to implement Channel.
PVRecordField
PVRecordStructure
-
These wrap PVField and PVStructure so that pvCopy and monitor can be implemented.
+
These wrap PVField and PVStructure so that pvCopy and monitor
+ can be implemented.
+
PVRecordClient
+
This is called by anything that acceses PVRecord.
PVListener
This is implemented by anything that wants to trap calls to the PVRecord::message.
RecordProcessRequester
This is implemented by anything that calls PVRecord::queueProcessRequest.
-
PVRecordClient
-
This is called by anything that acceses PVRecord.
+
RecordPutRequester
+
This is implemented by anything that calls PVRecord::queuePutRequest.
This section uses the name record instead of "an instance of PVRecord".
+
Most clients will access a record via the local channel provider,
+ i. e. via pvAccess.
+ Thus this section is mainly of interest to
+ the local channel provider and record implementers.
The constructor. It requires a recordName and a top level PVStructure.
~PVRecord
-
The desctructor which must be virtual. A derived class must also have
+
The destructor which must be virtual. A derived class must also have
a virtual destructor.
process
-
Pure virtual method. Derived classes must implement this method.
+
Pure virtual method.
+
Derived classes must implement this method.
+
A client must only call this method when
+ RecordProcessRequester::becomeProcessor is called as a result
+ of a queueProcessRequest.
+ A client can either call lock before calling processs
+ or let process lock the record.
+ If a client wants to put data into the record it should lock, put, and then call
+ process.
+
If the record is synchronous, process will return only when all processing
+ is complete. If the record is asynchronous then process arranges for some
+ other thread to do the processing and returns.
+
When processing is done the record calls two client callbacks:
+
+
RecordProcessRequester::recordProcessResult
+
This is called with the record still locked.
+ The clients can get data from the record.
+
RecordProcessRequester::recordProcessComplete
+
This is called with the record unlocked.
+ The client can no longer access the record.
+
+
isSynchronous
Pure virtual method. Derived classes must implement this method.
+
requestImmediatePut
+
This is a virtual method.
+
The purpose is to allow the implementation to provide fields
+ that allow a client to abort process.
+ For example a motor record might provide a field stop
+
The default always returns false.
+
A record implementation can override the default and return true.
+ In it does requestImmediatePut it returns with the record locked.
+
The client can change the value of the associated field and then call
+ immediatePutDone
+
+
immediatePutDone
+
This is a virtual method.
+
The default does nothing.
+
Must be called by client as a result of a call to requestImmediatePut
+ that returns true.
+
+
destroy
+
This is a virtual method.
+
The default does nothing.
+
getRecordName
Return the recordName.
getPVRecordStructure
Get the top level PVStructure.
findPVRecordField
Given a PVFieldPtr return the PVRecordFieldPtr for the field.
+
addRequester
+
Add a requester to receive messages.
+
removeRequester
+
Remove a message requester.
lock
unlock
Lock and Unlock the record.
Any code accessing the data in the record or calling other PVRecord methods
must have the record locked.
-
registerClient
+
tryLock
+
If true then just like lock.
+ If falseclient can not access record.
+ A client can try to simultaneously hold the lock for more than two records
+ by calling this method. But must be willing to accept failure.
+
+
lockOtherRecord
+
A client that holds the lock for one record can lock one other record.
+ A client must not call this if the client already has the lock for
+ more then one record.
+
+
addPVRecordClient
Every client that accesses the record must call this so that the client can be notified when the record is deleted.
-
unregisterClient
+
removePVRecordClient
Client is no longer accessing the record.
detachClients
Ask all clients to detach from the record
+
addListener
+
Add a PVListener. This must be called before calling pvRecordField.addListener.
+
removeListener
+
Removes a listener. The listener will also be removed from all fields to which it is attached.
beginGroupPut
-
Begin a group of puts. This results in all registered PVListeners being called
+
Begin a group of puts.
+ This results in all registered PVListeners being called
endGroupPut
-
End a group of puts. This results in all registered PVListeners being called.
-
registerListener
-
Register a PVListener. This must be called before calling pvRecordField.addListener.
-
unregisterListener
-
Unregister a listener. The listener will also be removed from all fields to which it is attached.
-
removeEveryListener
-
This must be called by any code that is deleting or changing the structure of a record.
-
processRequest
-
This is a convenience method for clients that are willing to block if
- process is asynchronous. It implements RecordProcessRequester.
- If process is synchronous it just calls process and returns the result
- to the caller. If process is asynchronous it calls queueProcessRequest,
- and process and waits for completion and then returns the result to the caller.
+
End a group of puts.
+ This results in all registered PVListeners being called.
queueProcessRequest
Queue a process request.
-
addRequester
-
Add a requester to receive messages.
-
removeRequester
-
Remove a message requester.
+
dequeueProcessRequest
+
This must be called by record implementation after it has
+ completed a process request.
+
+
queuePutRequest
+
Queue a put request.
+
This is for code that wants to change data in a record without processing.
+ If RecordPutRequester::requestResult is called with result true
+ then the record is locked and the client can make changes.
+ When done the client must call putDone
+
+
putDone
+
Called by RecordPutRequester after changing values in record.
+ This method unlocks the record
+
getRequesterName
+
virtual method of Requester
+
message
Can be called by implementation code.
The message will be sent to every requester.
+
init
+
This method must be called by derived class
+ after class is completely constructed.
When PVRecord is created it creates a PVRecordStructure for every structure field in the PVStructure
@@ -550,13 +683,31 @@ that holds the data. It has the following methods:
Get the PVRecordField array for the subfields
getPVStructure
Get the PVStructure for this field.
-
message
-
Called by implementation code. It calls PVRecord::message after prepending the full
- fieldname.
+
removeListener
+
Remove a PVListener.
+
postPut
+
This is called by the code that implements the data interface.
+ It is called whenever the put method is called.
The PVLister is being removed from the record.
- This is called when the record is being destroyed or when the record structure
- (not the data values) is being changed.
The record is being removed from the master database,
+
requestResult
+
Result of a call to queuePutRequest. If requestResult is false
+ then the caller can not access the record.
+ If requestResult is true
+ then the record is locked and the caller can get and put data in the record.
+ When done the caller must call PVRecord::putDone, which will unlock the
+ record.
+
This document describes pvDatabaseCPP,
+which is a framework for implementing a network accessable database of smart memory resident
+records. Network access is via pvAccess. The data in each record is a top level PVStructure as defined by
+pvData. The framework includes a complete implementation of ChannelProvider as defined by pvAccess.
+The framework must be extended in order to create record instances.
+The minimum that an extenson must provide is a top level PVStructure and a process method
+but the framework provides for complex extensions.
+
+
EPICS version 4 is a set of related products in the EPICS
+V4 control system programming environment:
pvIOC is a software framework for building network accessable "smart" real time
+ databases, suitable for interfacing devices in a distributed control system,
+ that can exchange pvData over pvAccess.
+
Each of these products has a Java and a C++ implementation.
+
+
Status of this Document
+
+
This is the 27-Nov-2012 version of the definition of pvDatabaseCPP.
+This is the original version.
+
+
This is the beginning of the implementation of pvDataBaseCPP.
+It describes the features that will be provided.
+The class definitions for PVRecord and PVDatabase are defined but not implemented.
+
+
+
+
Table of Contents
+
+
+
+
+
Introduction
+
Overview
+
This document descibes a C++ implementation of some of the components in pvIOCJava.
+It extracts the core components required to create a network accessible database of smart
+memory resident records.
+pvDatabaseCPP does not and will not implement any of the specialized support that pvIOCJava
+provides. Instead other projects will implement the specialized support.
+It is expected that many services will be created that do not require the full features provided
+by pvIOCJava. In the future pvIOCJava should be split into multiple projects with one of
+them named pvDatabaseJava.
+
+
+
A brief description of a pvDatase is that it is a network accessible set of smart memory resident
+records. Each record has data composed of a top level PVStructure. Each record has a name which is
+the channelName for pvAccess. A local Channel Provider implements the complete ChannelProvider and
+Channel interfaces as defined by pvAccess.
+This local provider is accessed by the remote pvAccess server.
+A record is smart because code can be attached to a record.
+
This document describes components that provides the following features:
+
+
database
+
This encapsulates the concept of a database of memory resident smart records.
+ The two main components are:
+
+
pvRecord
+
This encapsulates the concept of a smart record. It can be processed.
+ Changes to field values can be trapped. A record can be locked.
+
pvDatabase
+
This is a database of pvRecords.
+ Records can be added and removed from a database.
+
+
localChannelProvider
+
This is a complete implementation of ChannelProvider and Channel as defined by pvAccess.
+ It is used by the server side of pvAccess to attach to pvRecords.
+ This component also includes the monitor and pvCopy components from pvIOCJava
+
+
database does not itself implement pvRecord instances.
+Instead it provides a base classes that make it easy to create record instances.
+What does have to be implemented is a top
+level PVStructure and the following two methods:
+
+
process
+
This is what makes a record smart.
+ What process does is up to the implementation except that it must decide if
+ it's execution model is synchronous or asynchronous.
+ Synchronous means that when process returns the processing is complete.
+ Asynchronous means that when process returns the processing is not complete.
+ Instead process invokes other threads that will complete the processing at a later time.
+
isSynchronous
+
Which execution model is being implemented.
+
+
Example PVRecord Extension
+
Directory example/record has an example PVRecord implementation.
+It implements a counter.
+The top level structure is:
+
+structure
+ long value
+
+
NOTE: The example compiles but does not build because nothing
+is implemented.
+
+
exampleRecord.h
+
This is the class description.
+The example extends PVRecord.
Creates a PVStructure with a single subfield named value.
+ It gets the interface to the value field.
+ It then creates an ExampleRecord and returns it.
+
+
~ExampleRecord
+
Does not have to do anything because of shared pointers.
+
ExampleRecord
+
Calls the base class constructor and sets pvValue.
+
isSynchronous
+
The example is synchronous.
+
process
+
Gets the curent value, increments it, and puts the new value.
+ It than calls two processRequester callbacks.
+
+
+
exampleRecordMain.cpp
+
This is a main for creating and running the example.
The main program creates an example record and adds it to the database.
+It then runs until the process is stopped by typing exit.
+
Until the process is stopped,
+pvAccess clients can put and get the value field.
+For example
+
+pvget exampleRecord
+pvput exampleRecord 5
+
+
Will both work.
+
Phased Development
+
This documentation describes the first phase of a phased implementation of pvDatabaseCPP:
+
+
pvRecord
+
Wrapper on PVStructure that implements methods required by Local Channel Provider.
+
pvDatabase
+
Database of PVRecords. Has methods find, add, and remove.
+
Local Channel Provider
+
These two features will be the first phase.
+ But only synchronous record processing will be supported.
+
+
Future phases of pvDatabaseCPP should include:
+
+
Install
+
This provides on-line add and delete.
+
Field support
+
Add ability to optionally add support to fields.
+ In addition some of the basic support defined in pvIOCJava will also be implemented.
+
XML parser
+
This provides the ability to create record instances without writing any code.
+
+
The completion of each phase provides useful features that can be used without waiting for the
+completion of later phases.
+The rest of this document discusses only the first phase.
+
Features Required for localChannelProvider
+
+
pvCopy
+
Creates a PVStructure that contains a copy of an arbitary
+ subset of the fields of another top level PVStructure.
+ It can copy data between the two and maintains a bitSet that show
+ which fields are changed.
+
monitor
+
This provides the ability to monitor changes to fields of a record.
+
PVRecord and PVDatabase
+
Defined below.
+
local ChannelProvider
+
This is the pvAccess package in pvIOCJava.
+ The localChannelProvider will access data from PVRecords.
+ It will implement all channel methods except channelRPC.
+
+
Minumum Features Required for pvRecord
+
The first phase will only implement record processing, i. e.
+the process method has to do everything itself without any generic field support.
+This will be sufficient for starting to implement services.
+The following are the minimium features required
+
+
PVDatabase
+
This holds a set of PVRecords. It has methods to find, add, and remove records.
+
PVRecord
+
This, and a set of related interfaces, provide the following:
+
+
PVStructure
+
PVRecord is a wrapper on a top level pvStructure.
+
Record locking
+
A record can be locked and unlocked.
+ A record must be locked whenever data in the pvStructure is accessed.
+
Trapping data changes
+
A client can request to be notified when data in the pvStructure is modified.
+ It can do this on a field by field basis.
+
+
+
+
The following sections provide a first attempt to describe the classes required for the first
+phase.
+
The last section gives a brief overview of the features provided by pvIOCJava.
+
+
database
+
The classes in pvDatabase.h implement a database of memory resident
+smart records. The next subsection has the definitions for all the classes
+defined in this header file.
+It describes the following classes:
+
+
PVRecord
+
This provides the methods required by localChannelProvider to implement Channel.
+
PVRecordField
+
PVRecordStructure
+
These wrap PVField and PVStructure so that pvCopy and monitor can be implemented.
+
PVListener
+
This is implemented by anything that wants to trap calls to the PVRecord::message.
+
RecordProcessRequester
+
This is implemented by anything that calls PVRecord::queueProcessRequest.
The constructor. It requires a recordName and a top level PVStructure.
+
~PVRecord
+
The desctructor which must be virtual. A derived class must also have
+ a virtual destructor.
+
process
+
Pure virtual method. Derived classes must implement this method.
+
isSynchronous
+
Pure virtual method. Derived classes must implement this method.
+
getRecordName
+
Return the recordName.
+
getPVRecordStructure
+
Get the top level PVStructure.
+
findPVRecordField
+
Given a PVFieldPtr return the PVRecordFieldPtr for the field.
+
lock
+
unlock
+
Lock and Unlock the record.
+ Any code accessing the data in the record or calling other PVRecord methods
+ must have the record locked.
+
registerClient
+
Every client that accesses the record must call this so that the client can be notified when the record is deleted.
+
unregisterClient
+
Client is no longer accessing the record.
+
detachClients
+
Ask all clients to detach from the record
+
beginGroupPut
+
Begin a group of puts. This results in all registered PVListeners being called
+
endGroupPut
+
End a group of puts. This results in all registered PVListeners being called.
+
registerListener
+
Register a PVListener. This must be called before calling pvRecordField.addListener.
+
unregisterListener
+
Unregister a listener. The listener will also be removed from all fields to which it is attached.
+
removeEveryListener
+
This must be called by any code that is deleting or changing the structure of a record.
+
processRequest
+
This is a convenience method for clients that are willing to block if
+ process is asynchronous. It implements RecordProcessRequester.
+ If process is synchronous it just calls process and returns the result
+ to the caller. If process is asynchronous it calls queueProcessRequest,
+ and process and waits for completion and then returns the result to the caller.
+
queueProcessRequest
+
Queue a process request.
+
addRequester
+
Add a requester to receive messages.
+
removeRequester
+
Remove a message requester.
+
message
+
Can be called by implementation code.
+ The message will be sent to every requester.
When PVRecord is created it creates a PVRecordField for every field in the PVStructure
+that holds the data. It has the following methods:
+
+
+
+
PVRecordField
+
The constructor.
+
~PVRecordField
+
The destructor.
+
getParent
+
Get the parent PVRecordStructure for this field.
+
getPVField
+
Get the PVField associated with this PVRecordField.
+
getFullFieldName
+
This gets the full name of the field, i.e. field,field,..
+
getFullName
+
This gets recordName plus the full name of the field, i.e. recordName.field,field,..
+
getPVRecord
+
Returns the PVRecord to which this field belongs.
+
addListener
+
Add A PVListener to this field.
+ Whenever this field or any subfield if this field is modified the listener will be notified.
+ PVListener is described below.
+ Before a listener can call addListener it must first call PVRecord.registerListener.
+
removeListener
+
Remove a PVListener.
+
postPut
+
This is called by the code that implements the data interface.
+ It is called whenever the put method is called.
+
message
+
Called by implementation code. It calls PVRecord::message after prepending the full
+ fieldname.
When PVRecord is created it creates a PVRecordStructure for every structure field in the PVStructure
+that holds the data. It has the following methods:
+
+
+
PVRecordStructure
+
The constructor.
+
~PVRecordStructure
+
The destructor.
+
getPVRecordFields
+
Get the PVRecordField array for the subfields
+
getPVStructure
+
Get the PVStructure for this field.
+
message
+
Called by implementation code. It calls PVRecord::message after prepending the full
+ fieldname.
pvField has been modified.
+ Requested is the field to which the requester issued a pvField-&addListener.
+ This is called if the listener has called PVRecordField-&addListener for requested.
+
beginGroupPut
+
A related set of changes is being started.
+
endGroupPut
+
A related set of changes is done.
+
unlisten
+
The PVLister is being removed from the record.
+ This is called when the record is being destroyed or when the record structure
+ (not the data values) is being changed.
Called as a result of queueRequeProcessst. The requester can the call process.
+
recordProcessResult
+
The results of record processing.
+ This is called with the record locked so that the process requester
+ can access data from the record.
+
recordProcessComplete
+
Processing is complete.
+ This is called with the record unlocked.
+ If the process requester called process with leaveActive true then the requester
+ must call setInactive.
Get the master database. This is the database that localChannelProvider access.
+
~PVDatabase
+
The destructor.
+
findRecord
+
Find a record. An empty pointer is returned if the record is not in the database.
+
addRecord
+
Add a record to the database.
+ If the record already exists it is not modified and false is returned.
+
removeRecord
+
Remove a record from the database.
+ If the record was not in the database false is returned.
+
+
Local Channel Provider
+
Not yet described.
+
A brief description is that it must implement the following components of pvIOCJava:
+
+
pvCopy
+
monitor
+
pvAccess
+
See the next section for a description
+
+
Summary of Packages in pvIOCJAVA
+
The following are the direct sub packages of pvIOCJava/src/org/epics/pvioc:
+
+
pvCopy
+
This provides a copy of an arbitrary subset of the fields in a PVRecord.
+ It also provides the ability to detect and report changes to fields.
+ It is required for pvAccess.
+
monitor
+
This provides the ability to monitor changes to a PVRecord. It is required for pvAccess monitors.
+
pvAccess
+
The local implementation of Channel Provider and Channel.
+ It is accessed by the remote pvAccess server and can also be accessed by code in the same IOC.
+
database
+
This defines and implements PVRecord, PVDatabase , and PVListener.
+ It supports the basic feature required the implement a local Channel Provider.
+
support
+
This provides the ability to optionally attach code to any field of a pvRecord.
+ It and several sub packages provide a set of standard support modules.
+
install
+
This provides the ability to dynamically initialize and add new PVRecords. It also provides
+ the ability to dynamicall delete PVRecords.
+
xml
+
This provides the ability to configure record instances without writing code.
+
util
+
This is misnamed since it is code related to scanning.
+
pdrv
+
This is portDriver, which is a proposed sucessor to the asynManager component of asynDriver.
+
swtshell
+
This is shell that is can either run under the same process as a JavaIOC or as a remote shell.
+ It is like a version of probe but for pvData/pvAccess.
+ Almost all of it's features work in either local or remote mode.
+ With a little more work all or it's features could work remotely.
+ This should be done and then only remote mode should be supported.
+ It can then be rewritten in a completely different language and using a complely different GUI
+ framework.
+
+
caV3
+
This has two components:
+
+
ClientFactory
+
This is a small wrapper on top of the caV3 client support implemented by pvAccess.
+ It allows code in the pvIOC to access V3Records via pvAccess.
+
ServerFactory
+
This is a caV3 server that allows a caV3 client to access a PVRecord.
+ The Java implementation uses CAJ, which does most of the work.
+ For now it will not be discussed in this document.
+
+
+
v3a
+
I do not know what this is.
+
+
In addition there is one class file JavaIOC.java.
+This is starting a IOC instance.
+This is not required for pvIOCCPP which is either a main or runs as part of a V3 IOC.