1) added canRead for access security
2) main documentation moved to https://mrkraimer.github.io/website/developerGuide/pvDatabase/pvDatabaseCPP.html
This commit is contained in:
@ -2,6 +2,11 @@
|
||||
|
||||
This document summarizes the changes to the module between releases.
|
||||
|
||||
## Release 4.6.0 (EPICS 7.0.5.* March 2021)
|
||||
|
||||
* Access Security is now supported.
|
||||
* Special support has been revised and extended.
|
||||
|
||||
## Release 4.5.3 (EPICS 7.0.5 Feb 2021)
|
||||
|
||||
* The previously deprecated destroy methods have been removed.
|
||||
|
@ -4,7 +4,7 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
||||
<title>pvDatabaseCPP</title>
|
||||
<title>EPICS pvDatabaseCPP</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="http://epics-pvdata.sourceforge.net/base.css" />
|
||||
<link rel="stylesheet" type="text/css"
|
||||
@ -14,62 +14,56 @@
|
||||
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
|
||||
table { margin-left: auto; margin-right: auto }
|
||||
.diagram { text-align: center; margin: 2.5em 0 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
body { margin-right: 10% }
|
||||
/*]]>*/</style>
|
||||
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
<script type="text/javascript" src="http://epics-pvdata.sourceforge.net/script/tocgen.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="head">
|
||||
<h1>pvDatabaseCPP</h1>
|
||||
<h2 class="nocount">Release ? - TBD</h2>
|
||||
Latest update 2019.09.11.
|
||||
|
||||
<h1>EPICS pvDatabaseCPP</h1>
|
||||
<h2 class="nocount">Release 4.6.0 - March 2021</h2>
|
||||
|
||||
<h2 class="nocount">Abstract</h2>
|
||||
|
||||
<p>This document describes pvDatabaseCPP,
|
||||
which is a framework for implementing a network accessible database of smart memory resident
|
||||
<p><b>pvDatabase</b> is a framework for implementing a network accessible 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 can be extended in order to create record instances that implements services.
|
||||
The minimum that an extension must provide is a top level PVStructure and a process method.
|
||||
</p>
|
||||
|
||||
<!-- last para of Abstract is boilerplate reference to EPICS -->
|
||||
<p>For more information about EPICS generally, please refer to the home page of the <a
|
||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
||||
Control System</a>.</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div id="toc">
|
||||
<h2 class="nocount">Table of Contents</h2>
|
||||
</div>
|
||||
</div> <!-- head -->
|
||||
|
||||
<div id="contents" class="contents">
|
||||
<hr />
|
||||
|
||||
<h2>Overview</h2>
|
||||
<p>
|
||||
Documentation for pvDatabaseCPP is available at:
|
||||
<a
|
||||
href="https://mrkraimer.github.io/website/developerGuide/pvDatabase/pvDatabaseCPP.html">
|
||||
pvDatabase
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
pvDatabaseCPP is one of the components of
|
||||
EPICS Version 7
|
||||
<a href="https://epics-controls.org/resources-and-support/base/epics-7/">
|
||||
EPICS-7
|
||||
</a>
|
||||
</p>
|
||||
<p>This document is only a guide to help locate code and documentation related to pvDatabaseCPP
|
||||
</p>
|
||||
<p>
|
||||
It is intended for developers that want to use pvDatabaseCPP.
|
||||
</p>
|
||||
<h2>Developer Guide</h2>
|
||||
@ -79,204 +73,28 @@ href="https://mrkraimer.github.io/website/developerGuide/developerGuide.html">
|
||||
developerGuide
|
||||
</a>
|
||||
</p>
|
||||
<p>This guide discusses all the components that are part of an <b>EPICS V4</b> release.
|
||||
<p>This guide provides an overview of the components that are part of an <b>EPICS V4</b> release.
|
||||
Some understanding of the components and how they are related is necessary in order to
|
||||
develop code that uses pvDatabaseCPP.
|
||||
In particular read everything related to pvDatabase.
|
||||
</p>
|
||||
<p>pvDatabase has plugin support, which is implemented in <b>pvCopy</b>.
|
||||
<b>pvCopy</b> was originally implemented in <b>pvDataCPP</b>,
|
||||
but pvDatabaseCPP now implements its own version and adds plugin support.
|
||||
</p>
|
||||
<p>
|
||||
See
|
||||
<a
|
||||
href="https://mrkraimer.github.io/website/pvRequest/pvRequest.html">
|
||||
pvRequest
|
||||
</a>
|
||||
for details.
|
||||
</p>
|
||||
<p>The developerGuide discusses code in a way that applies to both CPP and C++.
|
||||
For the descriptions of the CPP specific code consult the following sections.
|
||||
In particular read everything related to pvaClient.
|
||||
</p>
|
||||
|
||||
<h2>doxygen</h2>
|
||||
<p>doxygen documentation is available at
|
||||
<a
|
||||
href="./html/index.html">doxgen</a>
|
||||
href="./html/index.html">doxygen</a>
|
||||
</p>
|
||||
|
||||
<h2>pvDatabaseCPP</h2>
|
||||
<h3>include/pv</h3>
|
||||
<p>The header files that describe the various components implemented by pvDatabase.
|
||||
</p>
|
||||
<dl>
|
||||
<dt>pvDatabase.h</dt>
|
||||
<dd>
|
||||
This describes PVRecord and PVDatabase.
|
||||
</dd>
|
||||
<dt>channelProviderLocal.h </dt>
|
||||
<dd>
|
||||
This describes a channel provider for PVDatabase
|
||||
</dd>
|
||||
<dt>pvSupport.h</dt>
|
||||
<dd>
|
||||
This is the base class for support attached to a field of a record.
|
||||
</dd>
|
||||
<dt>controlSupport.h</dt>
|
||||
<dd>
|
||||
This is support that implements control limits.
|
||||
</dd>
|
||||
<dt>scalarAlarmSupport.h</dt>
|
||||
<dd>
|
||||
This is support for a alarm limits for a scalar numeric field.
|
||||
</dd>
|
||||
<dt>processRecord.h</dt>
|
||||
<dd>
|
||||
This is a PVRecord that periodical processes a set of PVRecords in the local PVDatabase.
|
||||
</dd>
|
||||
<dt>addRecord.h</dt>
|
||||
<dd>
|
||||
This is a PVRecord that adds a new PVRecord to the local PVDatabase.
|
||||
</dd>
|
||||
<dt>removeRecord.h</dt>
|
||||
<dd>
|
||||
This is a PVRecord that removes a PVRecord in the local PVDatabase.
|
||||
</dd>
|
||||
<dt>traceRecord.h</dt>
|
||||
<dd>
|
||||
This is a PVRecord that sets the trace value for another PVRecord in the local PVDatabase.
|
||||
</dd>
|
||||
<dt>pvStructureCopy.h</dt>
|
||||
<dd>
|
||||
This is a facility that allows a client to access a subfield of the fields in a PVRecord.
|
||||
It also provides record and field options an plugin support.
|
||||
</dd>
|
||||
<dt>pvPlugin.h</dt>
|
||||
<dd>
|
||||
This is the base class for a plugin attached to a record or field of PVRecord.
|
||||
</dd>
|
||||
<dt>pvArrayPlugin.h</dt>
|
||||
<dd>
|
||||
A plugin for accessing a subset of the elements in an array field.
|
||||
</dd>
|
||||
<dt>pvDeadbandPlugin.h</dt>
|
||||
<dd>
|
||||
A deadband plugin for monitors.
|
||||
</dd>
|
||||
<dt>pvTimestampPlugin.h</dt>
|
||||
<dd>
|
||||
A plugin for timeStamp.
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>src/database</h3>
|
||||
<p>This has the code that implements pvDatabase and pvRecord.</p>
|
||||
<h3>src/pvAccess</h3>
|
||||
<p>This has the code for the channel provider for pvDatabase.
|
||||
</p>
|
||||
<h3>src/support</h3>
|
||||
<p>This has the pvSupport code.</p>
|
||||
<h3>src/special</h3>
|
||||
<p>
|
||||
This has the code for processRecord, addRecord, removeRecord, and traceRecord.
|
||||
</p>
|
||||
<h3>src/copy</h3>
|
||||
<p>This has the code for pvStructureCopy and all the plugin support.
|
||||
</p>
|
||||
<h2>exampleCPP</h2>
|
||||
<p>Example code is available as part of this release.
|
||||
<p>Example code is available at
|
||||
<a
|
||||
href="https://github.com/epics-base/exampleCPP">
|
||||
exampleCPP
|
||||
</a>
|
||||
</p>
|
||||
<p>In particular look at the example code mentioned in the following sub-sections.
|
||||
<p>In particular look at database, exampleLink, and helloPutGet.
|
||||
</p>
|
||||
|
||||
<h3>database</h3>
|
||||
<p>This has many examples of how to create both soft records and records that implement
|
||||
other functionality.</p>
|
||||
<dl>
|
||||
<dt>exampleDatabase.cpp</dt>
|
||||
<dd>
|
||||
This shows how to create soft records of each pvData type.<br />
|
||||
In addition shows how to create instances of the following two records.
|
||||
</dd>
|
||||
<dt>exampleHelloRecord.cpp</dt>
|
||||
<dd>
|
||||
This is a simple "hello world" that is intentended to be used via a channelPutGet request.
|
||||
</dd>
|
||||
<dt>exampleHelloRPC.cpp</dt>
|
||||
<dd>
|
||||
This is a simple "hello world" that is intentended to be used via a channelRPC request.
|
||||
</dd>
|
||||
<dt>exampleDatabaseMain.cpp</dt>
|
||||
<dd>
|
||||
This shows how to create a standalone IOC.
|
||||
</dd>
|
||||
<dt>ioc and iocBoot</dt>
|
||||
<dd>
|
||||
This has code and examples to create a V3 IOC which also has a PVDatabase.
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>exampleLink</h3>
|
||||
<p>This shows how to implement a record that has a link to another record</p>
|
||||
<dl>
|
||||
<dt>exampleMonitorLinkRecord</dt>
|
||||
<dd>
|
||||
This creates a monitor link to another record.
|
||||
</dd>
|
||||
<dt>exampleGetLinkRecord</dt>
|
||||
<dd>
|
||||
This creates a get link to another record.
|
||||
</dd>
|
||||
<dt>examplePutLinkRecord</dt>
|
||||
<dd>
|
||||
This creates a put link to another record.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h3>support</h3>
|
||||
<p>This creates records that have the following features:</p>
|
||||
<dl>
|
||||
<dt>value</dt>
|
||||
<dd>
|
||||
Each record has a value field the is a numeric scalar field.
|
||||
In addition each has the following fields:
|
||||
alarm,timeStamp,control,scalarAlarm, and display.
|
||||
</dd>
|
||||
<dt>support</dt>
|
||||
<dd>
|
||||
Each record uses the control and scalarAlarm support provided by pvDatabaseCPP.
|
||||
</dd>
|
||||
</dl>
|
||||
<p>
|
||||
It also creates records that can be used by clients to show example of the plugin support.
|
||||
</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>
|
||||
<pre>
|
||||
pvAccessCPP
|
||||
qsrv
|
||||
pvDatabaseCPP
|
||||
</pre>
|
||||
|
||||
<p>pvDatabaseCPP provides the following iocshell command.</p>
|
||||
<dl>
|
||||
<dt>registerChannelProviderLocal</dt>
|
||||
<dd>Including <b>registerChannelProviderLocal.dbd</b> as a dbd file automatically starts provider local
|
||||
and also creates the pvdbl shell command.
|
||||
</dd>
|
||||
<dt>pvdbl</dt>
|
||||
<dd>Provides a list of all the pvRecords in database <b>master</b>
|
||||
</dd>
|
||||
</dl>
|
||||
<p>In addition any code that implements a PVRecord must implement an ioc command.
|
||||
Look at the examples in <b>exampleCPP/support</b> to see how to implement shell commands.</p>
|
||||
|
||||
</div>
|
||||
</div> <!-- class="contents" -->
|
||||
</body>
|
||||
</html>
|
||||
|
@ -362,6 +362,12 @@ public:
|
||||
* @return true if client can write
|
||||
*/
|
||||
virtual bool canWrite();
|
||||
/**
|
||||
* @brief determines if client can read
|
||||
*
|
||||
* @return true if client can read
|
||||
*/
|
||||
virtual bool canRead();
|
||||
protected:
|
||||
shared_pointer getPtrSelf()
|
||||
{
|
||||
|
@ -328,6 +328,13 @@ void ChannelGetLocal::get()
|
||||
{
|
||||
ChannelGetRequester::shared_pointer requester = channelGetRequester.lock();
|
||||
if(!requester) return;
|
||||
ChannelLocalPtr channel(channelLocal.lock());
|
||||
if(!channel) throw std::logic_error("channel is deleted");
|
||||
if(!channel->canRead()) {
|
||||
Status status = Status::error("ChannelGet::get is not allowed");
|
||||
requester->getDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
|
||||
return;
|
||||
}
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(!pvr) throw std::logic_error("pvRecord is deleted");
|
||||
try {
|
||||
@ -489,6 +496,13 @@ void ChannelPutLocal::get()
|
||||
{
|
||||
ChannelPutRequester::shared_pointer requester = channelPutRequester.lock();
|
||||
if(!requester) return;
|
||||
ChannelLocalPtr channel(channelLocal.lock());
|
||||
if(!channel) throw std::logic_error("channel is deleted");
|
||||
if(!channel->canRead()) {
|
||||
Status status = Status::error("ChannelPut::get is not allowed");
|
||||
requester->getDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
|
||||
return;
|
||||
}
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(!pvr) throw std::logic_error("pvRecord is deleted");
|
||||
try {
|
||||
@ -522,7 +536,7 @@ void ChannelPutLocal::put(
|
||||
ChannelLocalPtr channel(channelLocal.lock());
|
||||
if(!channel) throw std::logic_error("channel is deleted");
|
||||
if(!channel->canWrite()) {
|
||||
Status status = Status::error("Channel put is not allowed");
|
||||
Status status = Status::error("ChannelPut::put is not allowed");
|
||||
requester->putDone(status,getPtrSelf());
|
||||
return;
|
||||
}
|
||||
@ -689,9 +703,9 @@ void ChannelPutGetLocal::putGet(
|
||||
if(!requester) return;
|
||||
ChannelLocalPtr channel(channelLocal.lock());
|
||||
if(!channel) throw std::logic_error("channel is deleted");
|
||||
if(!channel->canWrite()) {
|
||||
Status status = Status::error("Channel putGet is not allowed");
|
||||
requester->putGetDone(status,getPtrSelf(),pvGetStructure,getBitSet);
|
||||
if(!channel->canWrite()||!channel->canRead() ) {
|
||||
Status status = Status::error("ChannelPutGet::putGet is not allowed");
|
||||
requester->putGetDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
|
||||
return;
|
||||
}
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
@ -722,6 +736,13 @@ void ChannelPutGetLocal::getPut()
|
||||
{
|
||||
ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
|
||||
if(!requester) return;
|
||||
ChannelLocalPtr channel(channelLocal.lock());
|
||||
if(!channel) throw std::logic_error("channel is deleted");
|
||||
if(!channel->canRead()) {
|
||||
Status status = Status::error("ChannelPutGet::getPut is not allowed");
|
||||
requester->getPutDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
|
||||
return;
|
||||
}
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(!pvr) throw std::logic_error("pvRecord is deleted");
|
||||
try {
|
||||
@ -749,6 +770,13 @@ void ChannelPutGetLocal::getGet()
|
||||
{
|
||||
ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
|
||||
if(!requester) return;
|
||||
ChannelLocalPtr channel(channelLocal.lock());
|
||||
if(!channel) throw std::logic_error("channel is deleted");
|
||||
if(!channel->canRead()) {
|
||||
Status status = Status::error("ChannelPutGet::getGet is not allowed");
|
||||
requester->getPutDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
|
||||
return;
|
||||
}
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(!pvr) throw std::logic_error("pvRecord is deleted");
|
||||
try {
|
||||
@ -1325,9 +1353,15 @@ bool ChannelLocal::canWrite()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChannelLocal::canRead()
|
||||
{
|
||||
if(!asActive || (asClientPvt && asCheckGet(asClientPvt))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
ChannelLocal::~ChannelLocal()
|
||||
{
|
||||
// cout << "~ChannelLocal()" << endl;
|
||||
if(asMemberPvt) {
|
||||
asRemoveMember(&asMemberPvt);
|
||||
asMemberPvt = 0;
|
||||
|
Reference in New Issue
Block a user