updated documentation; fixed bugs while updating documentation
This commit is contained in:
50
documentation/RELEASE_NOTES.md
Normal file
50
documentation/RELEASE_NOTES.md
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
Release release/0.9.3 IN DEVELOPMENT
|
||||||
|
===========
|
||||||
|
|
||||||
|
The main changes since release 3.0.2 are:
|
||||||
|
|
||||||
|
* array semantics now enforce Copy On Write.
|
||||||
|
* String no longer defined.
|
||||||
|
* toString replaced by stream I/O
|
||||||
|
* union is new type.
|
||||||
|
* copy and monitor use new code in pvDataCPP
|
||||||
|
|
||||||
|
New Semantics for Arrays
|
||||||
|
--------
|
||||||
|
|
||||||
|
pvDatabaseCPP has been changed to use the new array implementation from pvDataCPP.
|
||||||
|
|
||||||
|
String no longer defined
|
||||||
|
---------
|
||||||
|
|
||||||
|
String is replaced by std::string.
|
||||||
|
|
||||||
|
|
||||||
|
toString replaced by stream I/O
|
||||||
|
---------
|
||||||
|
|
||||||
|
All uses of toString have been changed to use the steam I/O that pvDataCPP implements.
|
||||||
|
|
||||||
|
|
||||||
|
union is a new basic type.
|
||||||
|
------------
|
||||||
|
|
||||||
|
exampleDatabase now has example records for union and union array.
|
||||||
|
There are records for regular union and for variant union.
|
||||||
|
|
||||||
|
|
||||||
|
copy
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
The implementation of copy and monitor for pvAccess has been changed
|
||||||
|
to use the new monitor and copy support from pvDataCPP.
|
||||||
|
|
||||||
|
monitorPlugin
|
||||||
|
-------------
|
||||||
|
|
||||||
|
exampleDatabase now has a example plugin that implements onChange.
|
||||||
|
|
||||||
|
Release 0.9.2
|
||||||
|
==========
|
||||||
|
This was the starting point for RELEASE_NOTES
|
25
documentation/TODO.md
Normal file
25
documentation/TODO.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
TODO
|
||||||
|
===========
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
monitorPlugin
|
||||||
|
-------------
|
||||||
|
|
||||||
|
A debate is on-going about what semantics should be.
|
||||||
|
|
||||||
|
|
||||||
|
memory leak
|
||||||
|
--------
|
||||||
|
|
||||||
|
arrayPerformanceMain shows a slight memory leak at termination.
|
||||||
|
|
||||||
|
channel destroy and recreate
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
create more regresion tests
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Currently only some simple tests exist. Most of the testing has been via the examples
|
@ -38,7 +38,7 @@
|
|||||||
<h1>pvDatabaseCPP</h1>
|
<h1>pvDatabaseCPP</h1>
|
||||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
<!-- 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>
|
<dl>
|
||||||
<dt>Latest version:</dt>
|
<dt>Latest version:</dt>
|
||||||
<dd><a
|
<dd><a
|
||||||
@ -46,12 +46,12 @@
|
|||||||
</dd>
|
</dd>
|
||||||
<dt>This version:</dt>
|
<dt>This version:</dt>
|
||||||
<dd><a
|
<dd><a
|
||||||
href= "pvDatabaseCPP_20140219.html">pvDatabaseCPP20140219.html</a>
|
href= "pvDatabaseCPP_20140710.html">pvDatabaseCPP20140710.html
|
||||||
</dd>
|
</a> </dd>
|
||||||
<dt>Previous version:</dt>
|
<dt>Previous version:</dt>
|
||||||
<dd><a
|
<dd><a
|
||||||
href= "pvDatabaseCPP_20140207.html">pvDatabaseCPP20140207.html</a>
|
href= "pvDatabaseCPP_20140219.html">pvDatabaseCPP20140219.html
|
||||||
</dd>
|
</a> </dd>
|
||||||
<dt>Editors:</dt>
|
<dt>Editors:</dt>
|
||||||
<dd>Marty Kraimer, BNL</dd>
|
<dd>Marty Kraimer, BNL</dd>
|
||||||
</dl>
|
</dl>
|
||||||
@ -59,7 +59,6 @@
|
|||||||
<p class="copyright">This product is made available subject to acceptance of the <a
|
<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>
|
href="http://epics-pvdata.sourceforge.net/LICENSE.html">EPICS open source license.</a></p>
|
||||||
<hr />
|
<hr />
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2 class="nocount">Abstract</h2>
|
<h2 class="nocount">Abstract</h2>
|
||||||
|
|
||||||
@ -79,54 +78,10 @@ V4 control system programming environment:<br />
|
|||||||
|
|
||||||
<h2 class="nocount">Status of this Document</h2>
|
<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>
|
||||||
|
<p>This version is a complete implementation of what is described in this manual.
|
||||||
<p>
|
</div>
|
||||||
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>
|
|
||||||
|
|
||||||
<div id="toc">
|
<div id="toc">
|
||||||
<h2 class="nocount" style="page-break-before: always">Table of Contents</h2>
|
<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>
|
The rest of this document discusses only the first phase.</p>
|
||||||
<h3>Features Required for localChannelProvider</h3>
|
<h3>Features Required for localChannelProvider</h3>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>pvCopy</dt>
|
<dt>copy and monitor</dt>
|
||||||
<dd>Creates a PVStructure that contains a copy of an arbitary
|
<dd>pvDataCPP provides facilities copy and monitor.
|
||||||
subset of the fields of another top level PVStructure.
|
This facilities allow a client to access an arbitrary subset
|
||||||
It can copy data between the two and maintains a bitSet that show
|
of the fields in the top level structure associated with a channel,
|
||||||
which fields are changed.<dd>
|
and to monitor changes in the top level structure.
|
||||||
<dt>monitor</dt>
|
pvDatabaseCPP uses what pvDataCPP provides and has code that
|
||||||
<dd>This provides the ability to monitor changes to fields of a record.</dd>
|
associates these facilities with a PVRecord.
|
||||||
|
</dd>
|
||||||
<dt>PVRecord and PVDatabase</dt>
|
<dt>PVRecord and PVDatabase</dt>
|
||||||
<dd>Defined below.</dd>
|
<dd>Defined below.</dd>
|
||||||
<dt>The localChannelProvider itself</dt>
|
<dt>The localChannelProvider itself</dt>
|
||||||
@ -435,6 +391,22 @@ mrk> make
|
|||||||
<p>This builds the example.</p>
|
<p>This builds the example.</p>
|
||||||
|
|
||||||
<h2>iocshell commands</h2>
|
<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>
|
<p>The following iocsh commands are provided for a V3IOC:</p>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>startPVAClient</dt>
|
<dt>startPVAClient</dt>
|
||||||
@ -449,16 +421,25 @@ mrk> make
|
|||||||
<dd>Starts the local channel provider</p>
|
<dd>Starts the local channel provider</p>
|
||||||
<dt>stopPVAServer</dt>
|
<dt>stopPVAServer</dt>
|
||||||
<dd>Stop the local channel provider</dd>
|
<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>
|
<dt>pvdbl</dt>
|
||||||
<dd>Provides a list of all the pvRecords in database <b>master</b>
|
<dd>Provides a list of all the pvRecords in database <b>master</b>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<p>The client commands are provided via PVAClientRegister.dbd and the other commands
|
<p>In addition any code that implements a PVRecord must implement an ioc command.</p>
|
||||||
via PVAServerRegister.dbd.</p>
|
<p>Look at any of the examples to see how to implement shell commands.</p>
|
||||||
<p>In addition any code that implements a PVRecord must implement an ioc command.
|
<h3>Commands implemented by pvaSrv</h3>
|
||||||
The directory example has examples of how to implement the registration code.
|
<p><b>pvaSrv</b> provides a pvAccess server that provides access to iocCore records.</p>
|
||||||
See example/V3IOC/exampleCounter/src/ for a simple example.</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>
|
<h2>database</h2>
|
||||||
<h3>src/database</h3>
|
<h3>src/database</h3>
|
||||||
@ -492,7 +473,12 @@ See example/V3IOC/exampleCounter/src/ for a simple example.</p>
|
|||||||
<pre>
|
<pre>
|
||||||
recordName = "laptoprecordListPGRPC";
|
recordName = "laptoprecordListPGRPC";
|
||||||
pvRecord = RecordListRecord::create(recordName);
|
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>
|
</pre>
|
||||||
</dd>
|
</dd>
|
||||||
<dt>traceRecord.h</dt>
|
<dt>traceRecord.h</dt>
|
||||||
@ -571,6 +557,7 @@ public:
|
|||||||
POINTER_DEFINITIONS(PVRecord);
|
POINTER_DEFINITIONS(PVRecord);
|
||||||
|
|
||||||
virtual bool init() {initPVRecord(); return true;}
|
virtual bool init() {initPVRecord(); return true;}
|
||||||
|
virtual void start() {}
|
||||||
virtual void process() {}
|
virtual void process() {}
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
|
|
||||||
@ -582,9 +569,6 @@ public:
|
|||||||
PVRecordStructurePtr getPVRecordStructure();
|
PVRecordStructurePtr getPVRecordStructure();
|
||||||
PVRecordFieldPtr findPVRecordField(
|
PVRecordFieldPtr findPVRecordField(
|
||||||
epics::pvData::PVFieldPtr const & pvField);
|
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 lock();
|
||||||
void unlock();
|
void unlock();
|
||||||
bool tryLock();
|
bool tryLock();
|
||||||
@ -596,16 +580,6 @@ public:
|
|||||||
bool removeListener(PVListenerPtr const & pvListener);
|
bool removeListener(PVListenerPtr const & pvListener);
|
||||||
void beginGroupPut();
|
void beginGroupPut();
|
||||||
void endGroupPut();
|
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();
|
int getTraceLevel();
|
||||||
void setTraceLevel(int level);
|
void setTraceLevel(int level);
|
||||||
protected:
|
protected:
|
||||||
@ -629,19 +603,28 @@ private:
|
|||||||
Derived classes must implement this method.
|
Derived classes must implement this method.
|
||||||
This method Must call initPVRecord.
|
This method Must call initPVRecord.
|
||||||
</dd>
|
</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>
|
<dt>process</dt>
|
||||||
<dd>Virtual method.
|
<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.
|
The base implementation does nothing.
|
||||||
</dd>
|
</dd>
|
||||||
<dt>destroy</dt>
|
<dt>destroy</dt>
|
||||||
<dd>This is a virtual method.
|
<dd>Virtual method.
|
||||||
A derived class must call the base class destroy method after it
|
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>
|
has released any resources it uses.</dd>
|
||||||
<dt>create</dt>
|
<dt>create</dt>
|
||||||
<dd>Static method to create dumb records,
|
<dd>Static method to create dumb records,
|
||||||
i.e. records with a process method that does nothing.
|
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>
|
</dd>
|
||||||
<dt>~PVRecord</dt>
|
<dt>~PVRecord</dt>
|
||||||
<dd>The destructor which must be virtual. A derived class must also have
|
<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>
|
<dd>Get the top level PVStructure.</dd>
|
||||||
<dt>findPVRecordField</dt>
|
<dt>findPVRecordField</dt>
|
||||||
<dd>Given a PVFieldPtr return the PVRecordFieldPtr for the field.</dd>
|
<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>lock</dt>
|
||||||
<dt>unlock</dt>
|
<dt>unlock</dt>
|
||||||
<dd>Lock and Unlock the record.
|
<dd>Lock and Unlock the record.
|
||||||
@ -691,14 +667,6 @@ private:
|
|||||||
<dt>endGroupPut</dt>
|
<dt>endGroupPut</dt>
|
||||||
<dd>End a group of puts.
|
<dd>End a group of puts.
|
||||||
This results in all registered PVListeners being called.</dd>
|
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>
|
<dt>getTraceLevel</dt>
|
||||||
<dd>This can be used for debugging. There are currently three
|
<dd>This can be used for debugging. There are currently three
|
||||||
levels that are used by existing code.
|
levels that are used by existing code.
|
||||||
@ -748,9 +716,6 @@ public:
|
|||||||
bool addListener(PVListenerPtr const & pvListener);
|
bool addListener(PVListenerPtr const & pvListener);
|
||||||
virtual void removeListener(PVListenerPtr const & pvListener);
|
virtual void removeListener(PVListenerPtr const & pvListener);
|
||||||
virtual void postPut();
|
virtual void postPut();
|
||||||
virtual void message(
|
|
||||||
std::string const & message,
|
|
||||||
epics::pvData::MessageType messageType);
|
|
||||||
protected:
|
protected:
|
||||||
PVRecordFieldPtr getPtrSelf()
|
PVRecordFieldPtr getPtrSelf()
|
||||||
{
|
{
|
||||||
@ -794,9 +759,6 @@ that holds the data. It has the following methods:
|
|||||||
<dt>postPut</dt>
|
<dt>postPut</dt>
|
||||||
<dd>This is called by the code that implements the data interface.
|
<dd>This is called by the code that implements the data interface.
|
||||||
It is called whenever the put method is called.</dd>
|
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>
|
</dl>
|
||||||
<h3>class PVRecordStructure</h3>
|
<h3>class PVRecordStructure</h3>
|
||||||
<pre>
|
<pre>
|
||||||
@ -805,7 +767,8 @@ public:
|
|||||||
POINTER_DEFINITIONS(PVRecordStructure);
|
POINTER_DEFINITIONS(PVRecordStructure);
|
||||||
PVRecordStructure(
|
PVRecordStructure(
|
||||||
epics::pvData::PVStructurePtr const & pvStructure,
|
epics::pvData::PVStructurePtr const & pvStructure,
|
||||||
PVRecordFieldPtrArrayPtr const & pvRecordField);
|
PVRecordStructurePtr const & parent,
|
||||||
|
PVRecordPtr const & pvRecord);
|
||||||
virtual ~PVRecordStructure();
|
virtual ~PVRecordStructure();
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
PVRecordFieldPtrArrayPtr getPVRecordFields();
|
PVRecordFieldPtrArrayPtr getPVRecordFields();
|
||||||
@ -901,9 +864,6 @@ public:
|
|||||||
epics::pvData::PVStringArrayPtr getRecordNames();
|
epics::pvData::PVStringArrayPtr getRecordNames();
|
||||||
bool removeRecord(PVRecordPtr const & record);
|
bool removeRecord(PVRecordPtr const & record);
|
||||||
virtual std::string getRequesterName();
|
virtual std::string getRequesterName();
|
||||||
virtual void message(
|
|
||||||
std::string const &message,
|
|
||||||
epics::pvData::MessageType messageType);
|
|
||||||
private:
|
private:
|
||||||
PVDatabase();
|
PVDatabase();
|
||||||
};
|
};
|
||||||
@ -929,98 +889,14 @@ private:
|
|||||||
If the record was not in the database false is returned.</dd>
|
If the record was not in the database false is returned.</dd>
|
||||||
<dt>getRequesterName</dt>
|
<dt>getRequesterName</dt>
|
||||||
<dd>Virtual method of Requester</dd>
|
<dd>Virtual method of Requester</dd>
|
||||||
<dt>message</dt>
|
|
||||||
<dd>Virtual message of Requester.</dd>
|
|
||||||
</dl>
|
</dl>
|
||||||
<h2>pvAccess</h2>
|
<h2>pvAccess</h2>
|
||||||
<p>This is code that provides an implementation of channelProvider as
|
<p>This is code that provides an implementation of channelProvider as
|
||||||
defined by pvAccess.
|
defined by pvAccess.
|
||||||
It provides access to PVRecords and is access by the server side of remote pvAccess.</p>
|
It provides access to PVRecords and is accessed by the server side of remote pvAccess.
|
||||||
<h3>channelProviderLocal</h3>
|
It uses the copy and monitor facilities from pvDataCPP and connects
|
||||||
<p>This is a complete implementation of channelProvider and ,
|
them to a PVRecord.
|
||||||
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.
|
|
||||||
</p>
|
</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>
|
<h2>special</h2>
|
||||||
<p>This section provides two useful record support modules
|
<p>This section provides two useful record support modules
|
||||||
and one that is used for testing.</p>
|
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:
|
record:
|
||||||
<pre>
|
<pre>
|
||||||
traceRecord
|
traceRecord
|
||||||
structure arguments
|
structure argument
|
||||||
string recordName
|
string recordName
|
||||||
int level 0
|
int level 0
|
||||||
structure result
|
structure result
|
||||||
@ -1071,17 +947,18 @@ if(!result) cout<< "record " << recordName << " not added" <
|
|||||||
</pre>
|
</pre>
|
||||||
</p>
|
</p>
|
||||||
<h3>recordList</h3>
|
<h3>recordList</h3>
|
||||||
<p>This implements a PVRecord that allows a client to set
|
<p>This implements a PVRecord that allows a client to
|
||||||
the trace level of a record. It follows the pattern of a channelPutGet
|
get the names of all the PVRecords in the PVDatabase.
|
||||||
|
It follows the pattern of a channelPutGet
|
||||||
record:
|
record:
|
||||||
<pre>
|
<pre>
|
||||||
traceRecord
|
traceRecord
|
||||||
structure arguments
|
structure argument
|
||||||
string database master
|
string database master
|
||||||
string regularExpression .*
|
string regularExpression .*
|
||||||
structure result
|
structure result
|
||||||
string status
|
string status
|
||||||
string[] names
|
string[] name
|
||||||
</pre>
|
</pre>
|
||||||
where:
|
where:
|
||||||
<dl>
|
<dl>
|
||||||
@ -1092,8 +969,8 @@ where:
|
|||||||
returned.</dd>
|
returned.</dd>
|
||||||
<dt>status</dt>
|
<dt>status</dt>
|
||||||
<dd>The status of a putGet request.</dd>
|
<dd>The status of a putGet request.</dd>
|
||||||
<dt>names</dt>
|
<dt>name</dt>
|
||||||
<dd>The list of record names.</dd>
|
<dd>The array of record names.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<p>Note that swtshell, which is a Java GUI tool, has a command <b>channelList</b> that
|
<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.
|
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>
|
of record names.</p>
|
||||||
<p>testExampleServerMain.cpp has an example of how to create a traceRecord:
|
<p>testExampleServerMain.cpp has an example of how to create a traceRecord:
|
||||||
<pre>
|
<pre>
|
||||||
recordName = "laptoprecordListPGRPC";
|
recordName = "recordListPGRPC";
|
||||||
pvRecord = RecordListRecord::create(recordName);
|
pvRecord = RecordListRecord::create(recordName);
|
||||||
result = master->addRecord(pvRecord);
|
result = master->addRecord(pvRecord);
|
||||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
@ -1151,6 +1028,7 @@ exampleServer
|
|||||||
exampleServerInclude.dbd
|
exampleServerInclude.dbd
|
||||||
exampleServerMain.cpp
|
exampleServerMain.cpp
|
||||||
exampleServerRegister.cpp
|
exampleServerRegister.cpp
|
||||||
|
exampleServerRegister.dbd
|
||||||
ioc
|
ioc
|
||||||
Db
|
Db
|
||||||
...
|
...
|
||||||
@ -1165,7 +1043,10 @@ exampleServer
|
|||||||
where
|
where
|
||||||
<dl>
|
<dl>
|
||||||
<dt>ExampleRELEASE.local</dt>
|
<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>
|
and edited.</dd>
|
||||||
<dt>exampleServer.h</dt>
|
<dt>exampleServer.h</dt>
|
||||||
<dd>The header file for the service.</dd>
|
<dd>The header file for the service.</dd>
|
||||||
@ -1182,6 +1063,9 @@ where
|
|||||||
<dt>exampleServerRegister.cpp</dt>
|
<dt>exampleServerRegister.cpp</dt>
|
||||||
<dd>This has the code to start the service via the following iocsh
|
<dd>This has the code to start the service via the following iocsh
|
||||||
command.
|
command.
|
||||||
|
<dt>exampleServerRegister.dbd</dt>
|
||||||
|
<dd>This is the file that is used to create the shell command
|
||||||
|
exampleServerCreateRecord.</dd>
|
||||||
<pre>
|
<pre>
|
||||||
exampleServerCreateRecord exampleServer
|
exampleServerCreateRecord exampleServer
|
||||||
</pre>
|
</pre>
|
||||||
@ -1273,19 +1157,20 @@ private:
|
|||||||
ExampleServerPtr ExampleServer::create(
|
ExampleServerPtr ExampleServer::create(
|
||||||
std::string const & recordName)
|
std::string const & recordName)
|
||||||
{
|
{
|
||||||
StandardPVFieldPtr standardPVField = getStandardPVField();
|
StandardFieldPtr standardField = getStandardField();
|
||||||
|
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
PVStructurePtr pvArgument = standardPVField->scalar(pvString,"");
|
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
||||||
PVStructurePtr pvResult = standardPVField->scalar(pvString,"timeStamp");
|
addNestedStructure("argument")->
|
||||||
StringArray names;
|
add("value",pvString)->
|
||||||
names.reserve(2);
|
endNested()->
|
||||||
PVFieldPtrArray fields;
|
addNestedStructure("result") ->
|
||||||
fields.reserve(2);
|
add("value",pvString) ->
|
||||||
names.push_back("argument");
|
add("timeStamp",standardField->timeStamp()) ->
|
||||||
fields.push_back(pvArgument);
|
endNested()->
|
||||||
names.push_back("result");
|
createStructure();
|
||||||
fields.push_back(pvResult);
|
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(names,fields);
|
|
||||||
ExampleServerPtr pvRecord(
|
ExampleServerPtr pvRecord(
|
||||||
new ExampleServer(recordName,pvStructure));
|
new ExampleServer(recordName,pvStructure));
|
||||||
if(!pvRecord->init()) pvRecord.reset();
|
if(!pvRecord->init()) pvRecord.reset();
|
||||||
@ -1364,15 +1249,23 @@ int main(int argc,char *argv[])
|
|||||||
String recordName("exampleServer");
|
String recordName("exampleServer");
|
||||||
PVRecordPtr pvRecord = ExampleServer::create(recordName);
|
PVRecordPtr pvRecord = ExampleServer::create(recordName);
|
||||||
bool result = master->addRecord(pvRecord);
|
bool result = master->addRecord(pvRecord);
|
||||||
cout << "result of addRecord " << recordName << " " << result << endl;
|
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
pvRecord.reset();
|
recordName = "traceRecordPGRPC";
|
||||||
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
|
pvRecord = TraceRecord::create(recordName);
|
||||||
cout << "exampleServer\n";
|
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;
|
string str;
|
||||||
while(true) {
|
while(true) {
|
||||||
cout << "Type exit to stop: \n";
|
cout << "Type exit to stop: \n";
|
||||||
getline(cin,str);
|
|
||||||
if(str.compare("exit")==0) break;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1382,9 +1275,9 @@ This:
|
|||||||
<ul>
|
<ul>
|
||||||
<li>Gets a pointer to the master database.</li>
|
<li>Gets a pointer to the master database.</li>
|
||||||
<li>Creates the local Channel Provider. This starts the pvAccess server.</li>
|
<li>Creates the local Channel Provider. This starts the pvAccess server.</li>
|
||||||
<li>Creates a ExampleServer record with the name exampleServer
|
<li>Creates record exampleServer </li>
|
||||||
</li>
|
<li>creates records traceRecordPGRPC and recordListPGRPC</li>
|
||||||
<li>Prints exampleServer on standard out.</li>
|
<li>lists all the records</li>
|
||||||
<li>Runs forever until the user types exit on standard in.</li>
|
<li>Runs forever until the user types exit on standard in.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3>V3IOC exampleServer</h3>
|
<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:
|
<p>You can then issue the commands dbl and pvdbl:
|
||||||
<pre>
|
<pre>
|
||||||
epics> dbl
|
epics> dbl
|
||||||
double01
|
pvdouble
|
||||||
|
pvcounter
|
||||||
|
pvenum
|
||||||
|
pvdoubleArray
|
||||||
|
pvstringArray
|
||||||
epics> pvdbl
|
epics> pvdbl
|
||||||
exampleServer
|
exampleServer
|
||||||
epics>
|
epics>
|
||||||
</pre>
|
</pre>
|
||||||
double01 is a v3Record.
|
dbl shows the V3 records.
|
||||||
exampleServer is a pvRecord.
|
pvdbl shows the pvRecords.
|
||||||
</p>
|
</p>
|
||||||
<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>
|
or via PVAccess.</p>
|
||||||
|
|
||||||
<h2>exampleDatabase</h2>
|
<h2>exampleDatabase</h2>
|
||||||
@ -1511,8 +1408,8 @@ Once the client and local provider code has started then the following creates a
|
|||||||
</p>
|
</p>
|
||||||
<pre>
|
<pre>
|
||||||
PVDatabasePtr master = PVDatabase::getMaster();
|
PVDatabasePtr master = PVDatabase::getMaster();
|
||||||
ChannelAccess::shared_pointer channelAccess = getChannelAccess();
|
ChannelProvider::shared_pointer provider =
|
||||||
ChannelProvider::shared_pointer provider = channelAccess->getProvider(providerName);
|
getChannelProviderRegistry()->getProvider(providerName);
|
||||||
Channel::shared_pointer channel = provider->createChannel(channelName,channelRequester);
|
Channel::shared_pointer channel = provider->createChannel(channelName,channelRequester);
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
1940
documentation/pvDatabaseCPP_20140710.html
Normal file
1940
documentation/pvDatabaseCPP_20140710.html
Normal file
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,8 @@ dbLoadRecords("db/dbDouble.db","name=double05")
|
|||||||
dbLoadRecords("db/dbStringArray.db","name=stringArray01")
|
dbLoadRecords("db/dbStringArray.db","name=stringArray01")
|
||||||
dbLoadRecords("db/dbEnum.db","name=enum01")
|
dbLoadRecords("db/dbEnum.db","name=enum01")
|
||||||
dbLoadRecords("db/dbCounter.db","name=counter01");
|
dbLoadRecords("db/dbCounter.db","name=counter01");
|
||||||
|
dbLoadRecords("db/dbArray.db","name=doubleArray,type=DOUBLE");
|
||||||
|
|
||||||
|
|
||||||
cd ${TOP}/iocBoot/${IOC}
|
cd ${TOP}/iocBoot/${IOC}
|
||||||
iocInit()
|
iocInit()
|
||||||
|
@ -147,17 +147,20 @@ void ExampleDatabase::create()
|
|||||||
createVariantUnionArrayRecord(master,"exampleVariantUnionArray");
|
createVariantUnionArrayRecord(master,"exampleVariantUnionArray");
|
||||||
recordName = "examplePowerSupply";
|
recordName = "examplePowerSupply";
|
||||||
PVStructurePtr pvStructure = createPowerSupply();
|
PVStructurePtr pvStructure = createPowerSupply();
|
||||||
PowerSupplyPtr psr =
|
PowerSupplyPtr psr = PowerSupply::create(recordName,pvStructure);
|
||||||
PowerSupply::create(recordName,pvStructure);
|
if(psr==NULL) {
|
||||||
if(psr.get()==NULL) {
|
cout << "PowerSupply::create failed" << endl;
|
||||||
cout << "PowerSupply::create failed" << endl;
|
} else {
|
||||||
return;
|
result = master->addRecord(psr);
|
||||||
|
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
}
|
}
|
||||||
result = master->addRecord(psr);
|
|
||||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
|
||||||
recordName = "laptoprecordListPGRPC";
|
recordName = "laptoprecordListPGRPC";
|
||||||
pvRecord = RecordListRecord::create(recordName);
|
pvRecord = RecordListRecord::create(recordName);
|
||||||
result = master->addRecord(pvRecord);
|
if(pvRecord==NULL) {
|
||||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
cout << "RecordListRecord::create failed" << endl;
|
||||||
|
} else {
|
||||||
|
result = master->addRecord(pvRecord);
|
||||||
|
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
include "base.dbd"
|
include "base.dbd"
|
||||||
|
include "PVAClientRegister.dbd"
|
||||||
include "PVAServerRegister.dbd"
|
include "PVAServerRegister.dbd"
|
||||||
include "registerChannelProviderLocal.dbd"
|
include "registerChannelProviderLocal.dbd"
|
||||||
include "dbPv.dbd"
|
include "dbPv.dbd"
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
* @date 2013.04.02
|
* @date 2013.04.02
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <pv/standardPVField.h>
|
#include <pv/standardField.h>
|
||||||
#include <pv/exampleServer.h>
|
#include <pv/exampleServer.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
@ -23,19 +23,20 @@ namespace epics { namespace exampleServer {
|
|||||||
ExampleServerPtr ExampleServer::create(
|
ExampleServerPtr ExampleServer::create(
|
||||||
string const & recordName)
|
string const & recordName)
|
||||||
{
|
{
|
||||||
StandardPVFieldPtr standardPVField = getStandardPVField();
|
StandardFieldPtr standardField = getStandardField();
|
||||||
|
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
PVStructurePtr pvArgument = standardPVField->scalar(pvString,"");
|
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
||||||
PVStructurePtr pvResult = standardPVField->scalar(pvString,"timeStamp");
|
addNestedStructure("argument")->
|
||||||
StringArray names;
|
add("value",pvString)->
|
||||||
names.reserve(2);
|
endNested()->
|
||||||
PVFieldPtrArray fields;
|
addNestedStructure("result") ->
|
||||||
fields.reserve(2);
|
add("value",pvString) ->
|
||||||
names.push_back("argument");
|
add("timeStamp",standardField->timeStamp()) ->
|
||||||
fields.push_back(pvArgument);
|
endNested()->
|
||||||
names.push_back("result");
|
createStructure();
|
||||||
fields.push_back(pvResult);
|
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(names,fields);
|
|
||||||
ExampleServerPtr pvRecord(
|
ExampleServerPtr pvRecord(
|
||||||
new ExampleServer(recordName,pvStructure));
|
new ExampleServer(recordName,pvStructure));
|
||||||
if(!pvRecord->init()) pvRecord.reset();
|
if(!pvRecord->init()) pvRecord.reset();
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include <pv/standardPVField.h>
|
#include <pv/standardPVField.h>
|
||||||
#include <pv/exampleServer.h>
|
#include <pv/exampleServer.h>
|
||||||
#include <pv/traceRecord.h>
|
#include <pv/traceRecord.h>
|
||||||
|
#include <pv/recordList.h>
|
||||||
#include <pv/channelProviderLocal.h>
|
#include <pv/channelProviderLocal.h>
|
||||||
#include <pv/serverContext.h>
|
#include <pv/serverContext.h>
|
||||||
|
|
||||||
@ -42,15 +43,20 @@ int main(int argc,char *argv[])
|
|||||||
recordName = "exampleServer";
|
recordName = "exampleServer";
|
||||||
pvRecord = ExampleServer::create(recordName);
|
pvRecord = ExampleServer::create(recordName);
|
||||||
result = master->addRecord(pvRecord);
|
result = master->addRecord(pvRecord);
|
||||||
cout << "result of addRecord " << recordName << " " << result << endl;
|
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
recordName = "traceRecordPGRPC";
|
recordName = "traceRecordPGRPC";
|
||||||
pvRecord = TraceRecord::create(recordName);
|
pvRecord = TraceRecord::create(recordName);
|
||||||
result = master->addRecord(pvRecord);
|
result = master->addRecord(pvRecord);
|
||||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
pvRecord.reset();
|
recordName = "recordListPGRPC";
|
||||||
|
pvRecord = RecordListRecord::create(recordName);
|
||||||
|
result = master->addRecord(pvRecord);
|
||||||
|
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
ServerContext::shared_pointer pvaServer =
|
ServerContext::shared_pointer pvaServer =
|
||||||
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
|
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
|
||||||
cout << "exampleServer\n";
|
PVStringArrayPtr pvNames = master->getRecordNames();
|
||||||
|
shared_vector<const string> names = pvNames->view();
|
||||||
|
for(size_t i=0; i<names.size(); ++i) cout << names[i] << endl;
|
||||||
string str;
|
string str;
|
||||||
while(true) {
|
while(true) {
|
||||||
cout << "Type exit to stop: \n";
|
cout << "Type exit to stop: \n";
|
||||||
|
@ -24,26 +24,16 @@ RecordListRecordPtr RecordListRecord::create(
|
|||||||
{
|
{
|
||||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
StringArray argNames(2);
|
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
||||||
FieldConstPtrArray argFields(2);
|
addNestedStructure("argument")->
|
||||||
argNames[0] = "database";
|
add("database",pvString)->
|
||||||
argFields[0] = fieldCreate->createScalar(pvString);
|
add("regularExpression",pvString)->
|
||||||
argNames[1] = "regularExpression";
|
endNested()->
|
||||||
argFields[1] = fieldCreate->createScalar(pvString);
|
addNestedStructure("result") ->
|
||||||
StringArray resNames(2);
|
add("status",pvString) ->
|
||||||
FieldConstPtrArray resFields(2);
|
addArray("name",pvString) ->
|
||||||
resNames[0] = "status";
|
endNested()->
|
||||||
resFields[0] = fieldCreate->createScalar(pvString);
|
createStructure();
|
||||||
resNames[1] = "names";
|
|
||||||
resFields[1] = fieldCreate->createScalarArray(pvString);
|
|
||||||
StringArray topNames(2);
|
|
||||||
FieldConstPtrArray topFields(2);
|
|
||||||
topNames[0] = "argument";
|
|
||||||
topFields[0] = fieldCreate->createStructure(argNames,argFields);
|
|
||||||
topNames[1] = "result";
|
|
||||||
topFields[1] = fieldCreate->createStructure(resNames,resFields);
|
|
||||||
StructureConstPtr topStructure =
|
|
||||||
fieldCreate->createStructure(topNames,topFields);
|
|
||||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||||
RecordListRecordPtr pvRecord(
|
RecordListRecordPtr pvRecord(
|
||||||
new RecordListRecord(recordName,pvStructure));
|
new RecordListRecord(recordName,pvStructure));
|
||||||
@ -78,21 +68,21 @@ bool RecordListRecord::init()
|
|||||||
if(regularExpression.get()==NULL) return false;
|
if(regularExpression.get()==NULL) return false;
|
||||||
status = pvStructure->getStringField("result.status");
|
status = pvStructure->getStringField("result.status");
|
||||||
if(status.get()==NULL) return false;
|
if(status.get()==NULL) return false;
|
||||||
PVFieldPtr pvField = pvStructure->getSubField("result.names");
|
PVFieldPtr pvField = pvStructure->getSubField("result.name");
|
||||||
if(pvField.get()==NULL) {
|
if(pvField.get()==NULL) {
|
||||||
std::cerr << "no result.names" << std::endl;
|
std::cerr << "no result.name" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
names = static_pointer_cast<PVStringArray>(
|
name = static_pointer_cast<PVStringArray>(
|
||||||
pvStructure->getScalarArrayField("result.names",pvString));
|
pvStructure->getScalarArrayField("result.name",pvString));
|
||||||
if(names.get()==NULL) return false;
|
if(name.get()==NULL) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordListRecord::process()
|
void RecordListRecord::process()
|
||||||
{
|
{
|
||||||
PVStringArrayPtr pvNames = PVDatabase::getMaster()->getRecordNames();
|
PVStringArrayPtr pvNames = PVDatabase::getMaster()->getRecordNames();
|
||||||
names->replace(pvNames->view());
|
name->replace(pvNames->view());
|
||||||
string message("");
|
string message("");
|
||||||
if(database->get().compare("master")!=0) {
|
if(database->get().compare("master")!=0) {
|
||||||
message += " can only access master ";
|
message += " can only access master ";
|
||||||
|
@ -37,7 +37,7 @@ private:
|
|||||||
epics::pvData::PVStringPtr database;
|
epics::pvData::PVStringPtr database;
|
||||||
epics::pvData::PVStringPtr regularExpression;
|
epics::pvData::PVStringPtr regularExpression;
|
||||||
epics::pvData::PVStringPtr status;
|
epics::pvData::PVStringPtr status;
|
||||||
epics::pvData::PVStringArrayPtr names;
|
epics::pvData::PVStringArrayPtr name;
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
@ -24,24 +24,15 @@ TraceRecordPtr TraceRecord::create(
|
|||||||
{
|
{
|
||||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
StringArray topNames(2);
|
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
||||||
FieldConstPtrArray topFields(2);
|
addNestedStructure("argument")->
|
||||||
topNames[0] = "argument";
|
add("recordName",pvString)->
|
||||||
topNames[1] = "result";
|
add("level",pvInt)->
|
||||||
StringArray argNames(2);
|
endNested()->
|
||||||
FieldConstPtrArray argFields(2);
|
addNestedStructure("result") ->
|
||||||
argNames[0] = "recordName";
|
add("status",pvString) ->
|
||||||
argNames[1] = "level";
|
endNested()->
|
||||||
argFields[0] = fieldCreate->createScalar(pvString);
|
createStructure();
|
||||||
argFields[1] = fieldCreate->createScalar(pvInt);
|
|
||||||
topFields[0] = fieldCreate->createStructure(argNames,argFields);
|
|
||||||
StringArray resNames(1);
|
|
||||||
FieldConstPtrArray resFields(1);
|
|
||||||
resNames[0] = "status";
|
|
||||||
resFields[0] = fieldCreate->createScalar(pvString);
|
|
||||||
topFields[1] = fieldCreate->createStructure(resNames,resFields);
|
|
||||||
StructureConstPtr topStructure =
|
|
||||||
fieldCreate->createStructure(topNames,topFields);
|
|
||||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||||
TraceRecordPtr pvRecord(
|
TraceRecordPtr pvRecord(
|
||||||
new TraceRecord(recordName,pvStructure));
|
new TraceRecord(recordName,pvStructure));
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using std::string;
|
using std::string;
|
||||||
|
using std::cout;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
@ -24,24 +27,23 @@ PVStructurePtr createPowerSupply()
|
|||||||
StandardFieldPtr standardField = getStandardField();
|
StandardFieldPtr standardField = getStandardField();
|
||||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
|
|
||||||
size_t nfields = 5;
|
|
||||||
StringArray names;
|
|
||||||
names.reserve(nfields);
|
|
||||||
FieldConstPtrArray powerSupply;
|
|
||||||
powerSupply.reserve(nfields);
|
|
||||||
names.push_back("alarm");
|
|
||||||
powerSupply.push_back(standardField->alarm());
|
|
||||||
names.push_back("timeStamp");
|
|
||||||
powerSupply.push_back(standardField->timeStamp());
|
|
||||||
string properties("alarm,display");
|
|
||||||
names.push_back("voltage");
|
|
||||||
powerSupply.push_back(standardField->scalar(pvDouble,properties));
|
|
||||||
names.push_back("power");
|
|
||||||
powerSupply.push_back(standardField->scalar(pvDouble,properties));
|
|
||||||
names.push_back("current");
|
|
||||||
powerSupply.push_back(standardField->scalar(pvDouble,properties));
|
|
||||||
return pvDataCreate->createPVStructure(
|
return pvDataCreate->createPVStructure(
|
||||||
fieldCreate->createStructure(names,powerSupply));
|
fieldCreate->createFieldBuilder()->
|
||||||
|
add("alarm",standardField->alarm()) ->
|
||||||
|
add("timeStamp",standardField->timeStamp()) ->
|
||||||
|
addNestedStructure("power") ->
|
||||||
|
add("value",pvDouble) ->
|
||||||
|
add("alarm",standardField->alarm()) ->
|
||||||
|
endNested()->
|
||||||
|
addNestedStructure("voltage") ->
|
||||||
|
add("value",pvDouble) ->
|
||||||
|
add("alarm",standardField->alarm()) ->
|
||||||
|
endNested()->
|
||||||
|
addNestedStructure("current") ->
|
||||||
|
add("value",pvDouble) ->
|
||||||
|
add("alarm",standardField->alarm()) ->
|
||||||
|
endNested()->
|
||||||
|
createStructure());
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerSupplyPtr PowerSupply::create(
|
PowerSupplyPtr PowerSupply::create(
|
||||||
@ -77,62 +79,40 @@ bool PowerSupply::init()
|
|||||||
PVFieldPtr pvField;
|
PVFieldPtr pvField;
|
||||||
bool result;
|
bool result;
|
||||||
pvField = pvStructure->getSubField("timeStamp");
|
pvField = pvStructure->getSubField("timeStamp");
|
||||||
if(pvField.get()==NULL) {
|
if(pvField==NULL) {
|
||||||
std::cerr << "no timeStamp" << std::endl;
|
cerr << "no timeStamp" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
result = pvTimeStamp.attach(pvField);
|
result = pvTimeStamp.attach(pvField);
|
||||||
if(!result) {
|
if(!result) {
|
||||||
std::cerr << "no timeStamp" << std::endl;
|
cerr << "no timeStamp" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pvField = pvStructure->getSubField("alarm");
|
pvField = pvStructure->getSubField("alarm");
|
||||||
if(pvField.get()==NULL) {
|
if(pvField==NULL) {
|
||||||
std::cerr << "no alarm" << std::endl;
|
cerr << "no alarm" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
result = pvAlarm.attach(pvField);
|
result = pvAlarm.attach(pvField);
|
||||||
if(!result) {
|
if(!result) {
|
||||||
std::cerr << "no alarm" << std::endl;
|
cerr << "no alarm" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
string name;
|
pvCurrent = pvStructure->getSubField<PVDouble>("current.value");
|
||||||
name = "current.value";
|
if(pvCurrent==NULL) {
|
||||||
pvField = pvStructure->getSubField(name);
|
cerr << "no current\n";
|
||||||
if(pvField.get()==NULL) {
|
|
||||||
name = "current";
|
|
||||||
pvField = pvStructure->getSubField(name);
|
|
||||||
}
|
|
||||||
if(pvField.get()==NULL) {
|
|
||||||
std::cerr << "no current" << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pvCurrent = pvStructure->getDoubleField(name);
|
pvVoltage = pvStructure->getSubField<PVDouble>("voltage.value");
|
||||||
if(pvCurrent.get()==NULL) return false;
|
if(pvVoltage==NULL) {
|
||||||
name = "voltage.value";
|
cerr << "no current\n";
|
||||||
pvField = pvStructure->getSubField(name);
|
|
||||||
if(pvField.get()==NULL) {
|
|
||||||
name = "voltage";
|
|
||||||
pvField = pvStructure->getSubField(name);
|
|
||||||
}
|
|
||||||
if(pvField.get()==NULL) {
|
|
||||||
std::cerr << "no voltage" << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pvVoltage = pvStructure->getDoubleField(name);
|
pvPower = pvStructure->getSubField<PVDouble>("power.value");
|
||||||
if(pvVoltage.get()==NULL) return false;
|
if(pvPower==NULL) {
|
||||||
name = "power.value";
|
cerr << "no powert\n";
|
||||||
pvField = pvStructure->getSubField(name);
|
|
||||||
if(pvField.get()==NULL) {
|
|
||||||
name = "power";
|
|
||||||
pvField = pvStructure->getSubField(name);
|
|
||||||
}
|
|
||||||
if(pvField.get()==NULL) {
|
|
||||||
std::cerr << "no power" << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pvPower = pvStructure->getDoubleField(name);
|
|
||||||
if(pvPower.get()==NULL) return false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user