updated documentation; fixed bugs while updating documentation
This commit is contained in:
@@ -38,7 +38,7 @@
|
||||
<h1>pvDatabaseCPP</h1>
|
||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
||||
|
||||
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 19-Feb-2014</h2>
|
||||
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 10-July-2014</h2>
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
@@ -46,12 +46,12 @@
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href= "pvDatabaseCPP_20140219.html">pvDatabaseCPP20140219.html</a>
|
||||
</dd>
|
||||
href= "pvDatabaseCPP_20140710.html">pvDatabaseCPP20140710.html
|
||||
</a> </dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd><a
|
||||
href= "pvDatabaseCPP_20140207.html">pvDatabaseCPP20140207.html</a>
|
||||
</dd>
|
||||
href= "pvDatabaseCPP_20140219.html">pvDatabaseCPP20140219.html
|
||||
</a> </dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL</dd>
|
||||
</dl>
|
||||
@@ -59,7 +59,6 @@
|
||||
<p class="copyright">This product is made available subject to acceptance of the <a
|
||||
href="http://epics-pvdata.sourceforge.net/LICENSE.html">EPICS open source license.</a></p>
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
<h2 class="nocount">Abstract</h2>
|
||||
|
||||
@@ -79,54 +78,10 @@ V4 control system programming environment:<br />
|
||||
|
||||
<h2 class="nocount">Status of this Document</h2>
|
||||
|
||||
<p>This is the 19-Feb-2014 version of of pvDatabaseCPP.</p>
|
||||
<p>This is the 10-July-2014 version of of pvDatabaseCPP.</p>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Since the last version of the documentation:
|
||||
<dl>
|
||||
<dt>examples</dt>
|
||||
<dd>The examples have been moved to separate top level build areas.</dd>
|
||||
<dt>test</dt>
|
||||
<dd>The regression tests have been moved to a separate top level build area.
|
||||
It is built from the top but nothing from the tests appears in the top
|
||||
level bin directory.
|
||||
<dt>exampleServer</dt>
|
||||
<dd>This example now also includes pvaSrv, i. e. the pvAccess server for
|
||||
interfacing to iocCore V3 records.
|
||||
</dd>
|
||||
</dl>
|
||||
<p>
|
||||
This project is ready for alpha users.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
I have not had time to look at
|
||||
two unresolved problems reported in the previous version of this document:
|
||||
<dl>
|
||||
<dt>memory leak</dt>
|
||||
<dd>arrayPerformanceMain shows a slight memory leak at termination.</dd>
|
||||
<dt>channel destroy and recreate</dt>
|
||||
<dd>longArrayGet and longArrayPut fail if the channel is destroyed and
|
||||
immediately recreated.
|
||||
If epicsThreadSleep(1.0) is called between destroy and recreate then they work.
|
||||
The current version of each does wait.
|
||||
</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<p>Future enhancements in priority order:</p>
|
||||
<dl>
|
||||
<dt>channelArray</dt>
|
||||
<dd>The arguments that have type <b>int</b> should be changed to <b>size_t</b>.
|
||||
This requires changes to pvAccessCPP.
|
||||
</dd>
|
||||
<dt>Monitor Algorithms</dt>
|
||||
<dd>Monitor algorithms have not been implemented.
|
||||
Thus all monitors are onPut.</dd>
|
||||
<dt>Create more regression tests</dt>
|
||||
<dd>Currently only some simple tests exist.
|
||||
Most of the testing has been via the examples.</dd>
|
||||
</dl>
|
||||
<p>This version is a complete implementation of what is described in this manual.
|
||||
</div>
|
||||
|
||||
<div id="toc">
|
||||
<h2 class="nocount" style="page-break-before: always">Table of Contents</h2>
|
||||
@@ -343,13 +298,14 @@ completion of later phases.
|
||||
The rest of this document discusses only the first phase.</p>
|
||||
<h3>Features Required for localChannelProvider</h3>
|
||||
<dl>
|
||||
<dt>pvCopy</dt>
|
||||
<dd>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.<dd>
|
||||
<dt>monitor</dt>
|
||||
<dd>This provides the ability to monitor changes to fields of a record.</dd>
|
||||
<dt>copy and monitor</dt>
|
||||
<dd>pvDataCPP provides facilities copy and monitor.
|
||||
This facilities allow a client to access an arbitrary subset
|
||||
of the fields in the top level structure associated with a channel,
|
||||
and to monitor changes in the top level structure.
|
||||
pvDatabaseCPP uses what pvDataCPP provides and has code that
|
||||
associates these facilities with a PVRecord.
|
||||
</dd>
|
||||
<dt>PVRecord and PVDatabase</dt>
|
||||
<dd>Defined below.</dd>
|
||||
<dt>The localChannelProvider itself</dt>
|
||||
@@ -435,6 +391,22 @@ mrk> make
|
||||
<p>This builds the example.</p>
|
||||
|
||||
<h2>iocshell commands</h2>
|
||||
<p>Shell commands are made available via the standard DBD include mechanism
|
||||
provided by iocCore.
|
||||
The following provide EPICS V4 shell commands:</p>
|
||||
<dl>
|
||||
<dt>pvAccessCPP</dt>
|
||||
<dd>PVAClientRegister.dbd and PVAServerRegister.dbd</dd>
|
||||
<dt>pvaSrv</dt>
|
||||
<dd>dbPv.dbd</dd>
|
||||
<dt>pvDatabaseCPP</dt>
|
||||
<dd>registerChannelProviderLocal.dbd</dd>
|
||||
</dl>
|
||||
<p>
|
||||
Look at exampleServer/ioc/src/exampleServerInclude.dbd for an example
|
||||
of how an application can make the shell commands available.
|
||||
</p>
|
||||
<h3>Commands From pvAccessCPP</h3>
|
||||
<p>The following iocsh commands are provided for a V3IOC:</p>
|
||||
<dl>
|
||||
<dt>startPVAClient</dt>
|
||||
@@ -449,16 +421,25 @@ mrk> make
|
||||
<dd>Starts the local channel provider</p>
|
||||
<dt>stopPVAServer</dt>
|
||||
<dd>Stop the local channel provider</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<h3>Commands implemented by pvDatabaseCPP</h3>
|
||||
<p>The following iocsh commands are provided for a V3IOC:</p>
|
||||
<dl>
|
||||
<dt>pvdbl</dt>
|
||||
<dd>Provides a list of all the pvRecords in database <b>master</b>
|
||||
</dd>
|
||||
</dl>
|
||||
<p>The client commands are provided via PVAClientRegister.dbd and the other commands
|
||||
via PVAServerRegister.dbd.</p>
|
||||
<p>In addition any code that implements a PVRecord must implement an ioc command.
|
||||
The directory example has examples of how to implement the registration code.
|
||||
See example/V3IOC/exampleCounter/src/ for a simple example.</p>
|
||||
|
||||
<p>In addition any code that implements a PVRecord must implement an ioc command.</p>
|
||||
<p>Look at any of the examples to see how to implement shell commands.</p>
|
||||
<h3>Commands implemented by pvaSrv</h3>
|
||||
<p><b>pvaSrv</b> provides a pvAccess server that provides access to iocCore records.</p>
|
||||
<p>pvaSrv does not provide any shell commands but it can be part of an IOC.
|
||||
Just make sure your application configures pvaSrv and then include the following file:
|
||||
<pre>
|
||||
include "dbPv.dbd"
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
<h2>database</h2>
|
||||
<h3>src/database</h3>
|
||||
@@ -492,7 +473,12 @@ See example/V3IOC/exampleCounter/src/ for a simple example.</p>
|
||||
<pre>
|
||||
recordName = "laptoprecordListPGRPC";
|
||||
pvRecord = RecordListRecord::create(recordName);
|
||||
result = master->addRecord(pvRecord);
|
||||
if(pvRecord==NULL) {
|
||||
cout << "RecordListRecord::create failed" << endl;
|
||||
} else {
|
||||
result = master->addRecord(pvRecord);
|
||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||
}
|
||||
</pre>
|
||||
</dd>
|
||||
<dt>traceRecord.h</dt>
|
||||
@@ -571,6 +557,7 @@ public:
|
||||
POINTER_DEFINITIONS(PVRecord);
|
||||
|
||||
virtual bool init() {initPVRecord(); return true;}
|
||||
virtual void start() {}
|
||||
virtual void process() {}
|
||||
virtual void destroy();
|
||||
|
||||
@@ -582,9 +569,6 @@ public:
|
||||
PVRecordStructurePtr getPVRecordStructure();
|
||||
PVRecordFieldPtr findPVRecordField(
|
||||
epics::pvData::PVFieldPtr const & pvField);
|
||||
bool addRequester(epics::pvData::RequesterPtr const & requester);
|
||||
bool removeRequester(epics::pvData::RequesterPtr const & requester);
|
||||
inline void lock_guard() { epics::pvData::Lock theLock(mutex); }
|
||||
void lock();
|
||||
void unlock();
|
||||
bool tryLock();
|
||||
@@ -596,16 +580,6 @@ public:
|
||||
bool removeListener(PVListenerPtr const & pvListener);
|
||||
void beginGroupPut();
|
||||
void endGroupPut();
|
||||
std::string getRequesterName() {return getRecordName();}
|
||||
virtual void message(
|
||||
std::string const & message,
|
||||
epics::pvData::MessageType messageType);
|
||||
void message(
|
||||
PVRecordFieldPtr const & pvRecordField,
|
||||
std::string const & message,
|
||||
epics::pvData::MessageType messageType);
|
||||
void toString(epics::pvData::StringBuilder buf);
|
||||
void toString(epics::pvData::StringBuilder buf,int indentLevel);
|
||||
int getTraceLevel();
|
||||
void setTraceLevel(int level);
|
||||
protected:
|
||||
@@ -629,19 +603,28 @@ private:
|
||||
Derived classes must implement this method.
|
||||
This method Must call initPVRecord.
|
||||
</dd>
|
||||
<dt>start</dt>
|
||||
<dd>Virtual method.
|
||||
Optional method for derived class.
|
||||
It is called before record is added to database.
|
||||
The base method does nothing.
|
||||
</dd>
|
||||
<dt>process</dt>
|
||||
<dd>Virtual method.
|
||||
Derived classes must implement this method.
|
||||
Derived classes usually implement this method.
|
||||
It implements the semantics for the record.
|
||||
The base implementation does nothing.
|
||||
</dd>
|
||||
<dt>destroy</dt>
|
||||
<dd>This is a virtual method.
|
||||
A derived class must call the base class destroy method after it
|
||||
<dd>Virtual method.
|
||||
Optional method for derived class.
|
||||
If the derived class implements this it
|
||||
must call the base class destroy method after it
|
||||
has released any resources it uses.</dd>
|
||||
<dt>create</dt>
|
||||
<dd>Static method to create dumb records,
|
||||
i.e. records with a process method that does nothing.
|
||||
A derived class should have it';s own static create method.
|
||||
A derived class should have it's own static create method.
|
||||
</dd>
|
||||
<dt>~PVRecord</dt>
|
||||
<dd>The destructor which must be virtual. A derived class must also have
|
||||
@@ -652,13 +635,6 @@ private:
|
||||
<dd>Get the top level PVStructure.</dd>
|
||||
<dt>findPVRecordField</dt>
|
||||
<dd>Given a PVFieldPtr return the PVRecordFieldPtr for the field.</dd>
|
||||
<dt>addRequester</dt>
|
||||
<dd>Add a requester to receive messages.</dd>
|
||||
<dt>removeRequester</dt>
|
||||
<dd>Remove a message requester.</dd>
|
||||
<dt>lock_guard</dt>
|
||||
<dd>This is an inline method that locks the record. The record will automatically
|
||||
be unlocked when control leaves the block that has the call.
|
||||
<dt>lock</dt>
|
||||
<dt>unlock</dt>
|
||||
<dd>Lock and Unlock the record.
|
||||
@@ -691,14 +667,6 @@ private:
|
||||
<dt>endGroupPut</dt>
|
||||
<dd>End a group of puts.
|
||||
This results in all registered PVListeners being called.</dd>
|
||||
<dt>getRequesterName</dt>
|
||||
<dd>virtual method of Requester
|
||||
</dd>
|
||||
<dt>message</dt>
|
||||
<dd>Can be called by implementation code.
|
||||
The message will be sent to every requester.</dd>
|
||||
<dt>toString</dt>
|
||||
<dd>Just calls the top level PVStructure toString method.</dd>
|
||||
<dt>getTraceLevel</dt>
|
||||
<dd>This can be used for debugging. There are currently three
|
||||
levels that are used by existing code.
|
||||
@@ -748,9 +716,6 @@ public:
|
||||
bool addListener(PVListenerPtr const & pvListener);
|
||||
virtual void removeListener(PVListenerPtr const & pvListener);
|
||||
virtual void postPut();
|
||||
virtual void message(
|
||||
std::string const & message,
|
||||
epics::pvData::MessageType messageType);
|
||||
protected:
|
||||
PVRecordFieldPtr getPtrSelf()
|
||||
{
|
||||
@@ -794,9 +759,6 @@ that holds the data. It has the following methods:
|
||||
<dt>postPut</dt>
|
||||
<dd>This is called by the code that implements the data interface.
|
||||
It is called whenever the put method is called.</dd>
|
||||
<dt>message</dt>
|
||||
<dd>Called by implementation code. It calls PVRecord::message after prepending the full
|
||||
fieldname.</dd>
|
||||
</dl>
|
||||
<h3>class PVRecordStructure</h3>
|
||||
<pre>
|
||||
@@ -805,7 +767,8 @@ public:
|
||||
POINTER_DEFINITIONS(PVRecordStructure);
|
||||
PVRecordStructure(
|
||||
epics::pvData::PVStructurePtr const & pvStructure,
|
||||
PVRecordFieldPtrArrayPtr const & pvRecordField);
|
||||
PVRecordStructurePtr const & parent,
|
||||
PVRecordPtr const & pvRecord);
|
||||
virtual ~PVRecordStructure();
|
||||
virtual void destroy();
|
||||
PVRecordFieldPtrArrayPtr getPVRecordFields();
|
||||
@@ -901,9 +864,6 @@ public:
|
||||
epics::pvData::PVStringArrayPtr getRecordNames();
|
||||
bool removeRecord(PVRecordPtr const & record);
|
||||
virtual std::string getRequesterName();
|
||||
virtual void message(
|
||||
std::string const &message,
|
||||
epics::pvData::MessageType messageType);
|
||||
private:
|
||||
PVDatabase();
|
||||
};
|
||||
@@ -929,98 +889,14 @@ private:
|
||||
If the record was not in the database false is returned.</dd>
|
||||
<dt>getRequesterName</dt>
|
||||
<dd>Virtual method of Requester</dd>
|
||||
<dt>message</dt>
|
||||
<dd>Virtual message of Requester.</dd>
|
||||
</dl>
|
||||
<h2>pvAccess</h2>
|
||||
<p>This is code that provides an implementation of channelProvider as
|
||||
defined by pvAccess.
|
||||
It provides access to PVRecords and is access by the server side of remote pvAccess.</p>
|
||||
<h3>channelProviderLocal</h3>
|
||||
<p>This is a complete implementation of channelProvider and ,
|
||||
except for channelRPC, provides a complete implementation of Channel
|
||||
as defined by pvAccess.
|
||||
For monitors it calls the code described in the following sections.</p>
|
||||
<h3>pvCopy</h3>
|
||||
<p>This provides code that creates a top level PVStructure that is an arbitrary
|
||||
subset of the fields in the PVStructure from a PVRecord.
|
||||
In addition it provides code that monitors changes to the fields in a PVRecord.
|
||||
A client configures the desired set of subfields and monitoring options
|
||||
via a pvRequest structure.
|
||||
pvAccess provides a class CreatePVRequest that creates a pvRequest.
|
||||
The pvCopy code provides the same functionality as the pvCopy code in pvIOCJava.
|
||||
It provides access to PVRecords and is accessed by the server side of remote pvAccess.
|
||||
It uses the copy and monitor facilities from pvDataCPP and connects
|
||||
them to a PVRecord.
|
||||
</p>
|
||||
<h3>monitorAlgorithm</h3>
|
||||
<p>Currently all that is implemented is a header file.
|
||||
The only algorithm currently implemented is <b>onPut</b>
|
||||
</p>
|
||||
<h3>monitorFactory</h3>
|
||||
<h4>Overview</h4>
|
||||
<p><b>epics::pvData::monitor</b> defines the monitor interfaces
|
||||
as seen by a client.
|
||||
See
|
||||
<a href="http://epics-pvdata.sourceforge.net/docbuild/pvDatabaseCPP/tip/documentation/pvDatabaseCPP.html">pvDatabaseCPP.html</a>
|
||||
For details.</p>
|
||||
<p>
|
||||
monitorFactory implements the
|
||||
monitoring interfaces for a PVRecord.
|
||||
It implements queueSize=0 and queueSize>=2.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The implementation uses PVCopy and PVCopyMonitor which are implemented in pvCopy.
|
||||
When PVCopyMonitor tells monitor that changes
|
||||
have occurred, monitor applies the appropriate algorithm to each changed field.</p>
|
||||
|
||||
<p>Currently only algorithm <b>onPut</b> is implemented but,
|
||||
like pvIOCJava there are plans to support for the following monitor algorithms:</p>
|
||||
<dl>
|
||||
<dt>onPut</dt>
|
||||
<dd>A monitor is issued whenever a put is issued to the field. This is the
|
||||
default unless the record defines deadbands for a field. An exception is
|
||||
the top level timeStamp which by default is made onChange and monitor
|
||||
will not be raised.</dd>
|
||||
<dt>onChange</dt>
|
||||
<dd>This provides two options: 1) A monitor is raised whenever a field
|
||||
changes value, and 2) A monitor will never be raised for the field.</dd>
|
||||
<dt>deadband</dt>
|
||||
<dd>The field must be a numeric scalar. Whenever the absolute or percentage
|
||||
value of the field changes by more than a deadband a monitor is issued.
|
||||
The record instance can also define deadbands.</dd>
|
||||
<dt>periodic</dt>
|
||||
<dd>A monitor is issued at a periodic rate if a put was issued to any field
|
||||
being monitored.</dd>
|
||||
</dl>
|
||||
<h4>MonitorFactory</h4>
|
||||
<p>MonitorFactory provides the following methods:</p>
|
||||
<pre>class MonitorFactory
|
||||
{
|
||||
static MonitorPtr create(
|
||||
PVRecordPtr const & pvRecord,
|
||||
MonitorRequester::shared_pointer const & monitorRequester,
|
||||
PVStructurePtr const & pvRequest);
|
||||
static void registerMonitorAlgorithmCreater(
|
||||
MonitorAlgorithmCreatePtr const & monitorAlgorithmCreate,
|
||||
String const & algorithmName);
|
||||
}</pre>
|
||||
|
||||
<p>where</p>
|
||||
<dl>
|
||||
<dt>create</dt>
|
||||
<dd>Create a monitor. The arguments are:
|
||||
<dl>
|
||||
<dt>pvRecord</dt>
|
||||
<dd>The record being monitored.</dd>
|
||||
<dt>monitorRequester</dt>
|
||||
<dd>The monitor requester. This is the code to which monitot events
|
||||
will be delivered.</dd>
|
||||
<dt>pvRequest</dt>
|
||||
<dd>The request options</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
<dt>registerMonitorAlgorithmCreater</dt>
|
||||
<dd>Called by code that implements a monitor algorithm.</dd>
|
||||
</dl>
|
||||
<h2>special</h2>
|
||||
<p>This section provides two useful record support modules
|
||||
and one that is used for testing.</p>
|
||||
@@ -1030,7 +906,7 @@ the trace level of a record. It follows the pattern of a channelPutGet
|
||||
record:
|
||||
<pre>
|
||||
traceRecord
|
||||
structure arguments
|
||||
structure argument
|
||||
string recordName
|
||||
int level 0
|
||||
structure result
|
||||
@@ -1071,17 +947,18 @@ if(!result) cout<< "record " << recordName << " not added" <
|
||||
</pre>
|
||||
</p>
|
||||
<h3>recordList</h3>
|
||||
<p>This implements a PVRecord that allows a client to set
|
||||
the trace level of a record. It follows the pattern of a channelPutGet
|
||||
<p>This implements a PVRecord that allows a client to
|
||||
get the names of all the PVRecords in the PVDatabase.
|
||||
It follows the pattern of a channelPutGet
|
||||
record:
|
||||
<pre>
|
||||
traceRecord
|
||||
structure arguments
|
||||
structure argument
|
||||
string database master
|
||||
string regularExpression .*
|
||||
structure result
|
||||
string status
|
||||
string[] names
|
||||
string[] name
|
||||
</pre>
|
||||
where:
|
||||
<dl>
|
||||
@@ -1092,8 +969,8 @@ where:
|
||||
returned.</dd>
|
||||
<dt>status</dt>
|
||||
<dd>The status of a putGet request.</dd>
|
||||
<dt>names</dt>
|
||||
<dd>The list of record names.</dd>
|
||||
<dt>name</dt>
|
||||
<dd>The array of record names.</dd>
|
||||
</dl>
|
||||
<p>Note that swtshell, which is a Java GUI tool, has a command <b>channelList</b> that
|
||||
requires that a record of this type is present and calls it.
|
||||
@@ -1101,7 +978,7 @@ Thus user code does not have to use a channelGetPut to get the list
|
||||
of record names.</p>
|
||||
<p>testExampleServerMain.cpp has an example of how to create a traceRecord:
|
||||
<pre>
|
||||
recordName = "laptoprecordListPGRPC";
|
||||
recordName = "recordListPGRPC";
|
||||
pvRecord = RecordListRecord::create(recordName);
|
||||
result = master->addRecord(pvRecord);
|
||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||
@@ -1151,6 +1028,7 @@ exampleServer
|
||||
exampleServerInclude.dbd
|
||||
exampleServerMain.cpp
|
||||
exampleServerRegister.cpp
|
||||
exampleServerRegister.dbd
|
||||
ioc
|
||||
Db
|
||||
...
|
||||
@@ -1165,7 +1043,10 @@ exampleServer
|
||||
where
|
||||
<dl>
|
||||
<dt>ExampleRELEASE.local</dt>
|
||||
<dd>This is the file that must be copied to RELEASE.local
|
||||
<dd>
|
||||
If you make a copy of exampleServer and use it
|
||||
to create a new server,
|
||||
This is the file that must be copied to RELEASE.local
|
||||
and edited.</dd>
|
||||
<dt>exampleServer.h</dt>
|
||||
<dd>The header file for the service.</dd>
|
||||
@@ -1182,6 +1063,9 @@ where
|
||||
<dt>exampleServerRegister.cpp</dt>
|
||||
<dd>This has the code to start the service via the following iocsh
|
||||
command.
|
||||
<dt>exampleServerRegister.dbd</dt>
|
||||
<dd>This is the file that is used to create the shell command
|
||||
exampleServerCreateRecord.</dd>
|
||||
<pre>
|
||||
exampleServerCreateRecord exampleServer
|
||||
</pre>
|
||||
@@ -1273,19 +1157,20 @@ private:
|
||||
ExampleServerPtr ExampleServer::create(
|
||||
std::string const & recordName)
|
||||
{
|
||||
StandardPVFieldPtr standardPVField = getStandardPVField();
|
||||
StandardFieldPtr standardField = getStandardField();
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
PVStructurePtr pvArgument = standardPVField->scalar(pvString,"");
|
||||
PVStructurePtr pvResult = standardPVField->scalar(pvString,"timeStamp");
|
||||
StringArray names;
|
||||
names.reserve(2);
|
||||
PVFieldPtrArray fields;
|
||||
fields.reserve(2);
|
||||
names.push_back("argument");
|
||||
fields.push_back(pvArgument);
|
||||
names.push_back("result");
|
||||
fields.push_back(pvResult);
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(names,fields);
|
||||
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
||||
addNestedStructure("argument")->
|
||||
add("value",pvString)->
|
||||
endNested()->
|
||||
addNestedStructure("result") ->
|
||||
add("value",pvString) ->
|
||||
add("timeStamp",standardField->timeStamp()) ->
|
||||
endNested()->
|
||||
createStructure();
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||
|
||||
ExampleServerPtr pvRecord(
|
||||
new ExampleServer(recordName,pvStructure));
|
||||
if(!pvRecord->init()) pvRecord.reset();
|
||||
@@ -1364,15 +1249,23 @@ int main(int argc,char *argv[])
|
||||
String recordName("exampleServer");
|
||||
PVRecordPtr pvRecord = ExampleServer::create(recordName);
|
||||
bool result = master->addRecord(pvRecord);
|
||||
cout << "result of addRecord " << recordName << " " << result << endl;
|
||||
pvRecord.reset();
|
||||
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
|
||||
cout << "exampleServer\n";
|
||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||
recordName = "traceRecordPGRPC";
|
||||
pvRecord = TraceRecord::create(recordName);
|
||||
result = master->r;addRecord(pvRecord);
|
||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||
recordName = "recordListPGRPC";
|
||||
pvRecord = RecordListRecord::create(recordName);
|
||||
result = master->r;addRecord(pvRecord);
|
||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||
ServerContext::shared_pointer pvaServer =
|
||||
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
|
||||
PVStringArrayPtr pvNames = master->r;getRecordNames();
|
||||
shared_vector<const string>r; names = pvNames->r;view();
|
||||
for(size_t i=0; i<names.size(); ++i) cout << names[i] << endl;
|
||||
string str;
|
||||
while(true) {
|
||||
cout << "Type exit to stop: \n";
|
||||
getline(cin,str);
|
||||
if(str.compare("exit")==0) break;
|
||||
|
||||
}
|
||||
return 0;
|
||||
@@ -1382,9 +1275,9 @@ This:
|
||||
<ul>
|
||||
<li>Gets a pointer to the master database.</li>
|
||||
<li>Creates the local Channel Provider. This starts the pvAccess server.</li>
|
||||
<li>Creates a ExampleServer record with the name exampleServer
|
||||
</li>
|
||||
<li>Prints exampleServer on standard out.</li>
|
||||
<li>Creates record exampleServer </li>
|
||||
<li>creates records traceRecordPGRPC and recordListPGRPC</li>
|
||||
<li>lists all the records</li>
|
||||
<li>Runs forever until the user types exit on standard in.</li>
|
||||
</ul>
|
||||
<h3>V3IOC exampleServer</h3>
|
||||
@@ -1397,16 +1290,20 @@ mrk> ../../../bin/linux-x86_64/exampleServer st.cmd
|
||||
<p>You can then issue the commands dbl and pvdbl:
|
||||
<pre>
|
||||
epics> dbl
|
||||
double01
|
||||
pvdouble
|
||||
pvcounter
|
||||
pvenum
|
||||
pvdoubleArray
|
||||
pvstringArray
|
||||
epics> pvdbl
|
||||
exampleServer
|
||||
epics>
|
||||
</pre>
|
||||
double01 is a v3Record.
|
||||
exampleServer is a pvRecord.
|
||||
dbl shows the V3 records.
|
||||
pvdbl shows the pvRecords.
|
||||
</p>
|
||||
<p>
|
||||
It starts pvASrv so that the V3 records can be accessed via Channel Access
|
||||
It starts pvaSrv so that the V3 records can be accessed via Channel Access
|
||||
or via PVAccess.</p>
|
||||
|
||||
<h2>exampleDatabase</h2>
|
||||
@@ -1511,8 +1408,8 @@ Once the client and local provider code has started then the following creates a
|
||||
</p>
|
||||
<pre>
|
||||
PVDatabasePtr master = PVDatabase::getMaster();
|
||||
ChannelAccess::shared_pointer channelAccess = getChannelAccess();
|
||||
ChannelProvider::shared_pointer provider = channelAccess->getProvider(providerName);
|
||||
ChannelProvider::shared_pointer provider =
|
||||
getChannelProviderRegistry()->getProvider(providerName);
|
||||
Channel::shared_pointer channel = provider->createChannel(channelName,channelRequester);
|
||||
</pre>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user