channelArray, trace implemented. Known memory leaks and exceptions fixed.

This commit is contained in:
Marty Kraimer
2013-06-27 10:38:05 -04:00
parent db4e10e393
commit 255f58aeb8
22 changed files with 1979 additions and 692 deletions

View File

@ -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, 23-May-2013</h2>
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 27-Jun-2013</h2>
<dl>
<dt>Latest version:</dt>
<dd><a
@ -46,11 +46,11 @@
</dd>
<dt>This version:</dt>
<dd><a
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDatabaseCPP/raw-file/tip/documentation/pvDatabaseCPP_20130523.html">pvDatabaseCPP20130523.html</a>
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDatabaseCPP/raw-file/tip/documentation/pvDatabaseCPP_20130627.html">pvDatabaseCPP20130627.html</a>
</dd>
<dt>Previous version:</dt>
<dd><a
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDatabaseCPP/raw-file/tip/documentation/pvDatabaseCPP_20130516.html">pvDatabaseCPP20130516.html</a>
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDatabaseCPP/raw-file/tip/documentation/pvDatabaseCPP_20130523.html">pvDatabaseCPP20130523.html</a>
</dd>
<dt>Editors:</dt>
<dd>Marty Kraimer, BNL</dd>
@ -74,33 +74,31 @@ The minimum that an extenson must provide is a top level PVStructure and a proce
<h2 class="nocount">Status of this Document</h2>
<p>This is the 23-May-2013 version of the definition of pvDatabaseCPP.
<p>This is the 27-Jun-2013 version of the definition of pvDatabaseCPP.
</p>
<p>The following Channel methods are implemented and working: getField,
channelProcess, channelGet, channelPut, channelPutGet, and Monitor.
But lots of work remains:</p>
channelProcess, channelGet, channelPut, channelPutGet,channelArray and Monitor.
But work remains:</p>
<dl>
<dt>Other Channel Methods</dt>
<dd>Only ChannelArray remains.
Note that pvIOCJava does not implement the pvRequest for channelArray
correctly. It uses a private convention rather than using the output
of CreateRequest. This will be fixed before pvDatabaseCPP implements ChannelArray.
<dd>channlRPC will not be implemented because pvAccess itself
provides what is required to easily implement channelRPC requests.
</dd>
<dt>Monitor Algorithms</dt>
<dd>Monitor algorithms have not been implemented.
Thus all monitors are onPut.</dd>
<dt>Lifecycle problems</dt>
<dd>Problems when channel clients disconnect.
I am asking for help from Matej</dd>
<dt>Memory leak at exit</dt>
<dd>I am asking for help from Matej</dd>
<dt>Memory leaks</dt>
<dd>I think all memory leaks have been fixed.</dd>
<dt>Scalar Arrays</dt>
<dd>Share has not been implemented.
This will wait until Michael has new implementation of ScalarArray.</dd>
This will wait for a new implementation of ScalarArray.</dd>
<dt>Structure Arrays</dt>
<dd>Has not been implemented</dd>
<dt>toString</dt>
<dd>The toString methods should be replaced by stream operator&lt;&lt;.
</dd>
<dt>Testing</dt>
<dd>Needs lots more testing</dd>
<dd>Needs more testing</dd>
</dl>
<div id="toc">
@ -142,7 +140,7 @@ A record is smart because code can be attached to a record, which is accessed vi
</dl>
<p>database provides base classes that make it easy to create record instances.
The code attached to each record must create the top
level PVStructure and the following two methods:</p>
level PVStructure and the following three methods:</p>
<dl>
<dt>init</dt>
<dd>This is a method for initializing the support.
@ -151,7 +149,67 @@ level PVStructure and the following two methods:</p>
<dt>process</dt>
<dd>This is what makes a record smart.
</dd>
<dt>destroy</dt>
<dd>This releases and resorurces used by the impplementation.</dd>
</dl>
<h3>Getting started</h3>
<p>Included with this project are two main programs that are useful for
seeing how pvDatabase can be used by clients.
The programs are:
<dl>
<dt>exampleCounterMain</dt>
<dd>This has a database consisting of two records:
The exampleCounter discussed in a following section and a record
that allows a pvAccess client to set the trace level of the
exampleCounter. This is also discussed below.
</dd>
<dt>testExamplServerMain</dt>
<dd>This has a database with several records.</dd>
</dt>
</p>
<p>To start one of the programs on linux, do the following:
<pre>
mrk&gt; pwd
/home/hg/pvDatabaseCPP
mrk&gt; bin/linux-x86_64/testExampleServer
</pre></p>
<p>The Java programs
<a
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/swtshellJava/raw-file/tip/documentation/swtshellJava.html">
swtshellJava.html</a>
can be used to access the database.</p>
<p>In particular read the sections "Getting Started" and "Simple Example".
They will work on the testExampleServer with the following differences:
<dl>
<dt>startExample.zip</dt>
<dd>Do NOT use this. Instead run testExampleServer</dd>
<dt>channelList result</dt>
<dd>The result of channelList will show the list of records that
testExampleServer has rather than the records from startExample.zip</dd>
</dl>
</p>
<p>The database has the following records:
<dl>
<dt>exampleCounter</dt>
<dd>A record that is an instance of exampleCounter described below.
The most useful channel methods are channelGet, channelProcess,
and monitor.</dd>
<dt>exampleDouble</dt>
<dd>A record that is an instance of a record with a process method
that does nothing. To test it start a channelPut and a channelGet and/or monitor.</dd>
<dt>exampleDoubleArray</dt>
<dd>An array record that is an instance of a record with a process method
that does nothing. It can be tested like exampleDouble. In addition channelArray can
also be used.</dd>
<dt>examplePowerSupply</dt>
<dd>Can be used by channelGet, channelPut, channelPutGet, and monitor.</dd>
<dt>laptoprecordListPGRPC</dt>
<dd>Implements the record expected by swtshell channelList.
It can also be used via channelPutGet but unnecessary.</dd>
<dt>traceRecordPGRPC</dt>
<dd>This can be used via channelPutGet to set the trace level of another record.</dd>
</dl>
<h3>Relationship with pvIOCJava.</h3>
<p>This document descibes a C++ implementation of some of the components in pvIOCJava,
which also implements a pvDatabase.
@ -227,7 +285,7 @@ private:
</dd>
<dt>~ExampleCounter<dt>
<dd>The destructor must be declared virtual.</dd>
<dt><destroy</dt>
<dt>destroy</dt>
<dd>Called when the record is being destroyed.
This must call the base class destroy method.
<dt>init<dt>
@ -276,12 +334,11 @@ ExampleCounter::ExampleCounter(
pvTimeStamp.attach(pvStructure->getSubField("timeStamp"));
}
</pre>
The example is very simple. It just calls the base class constructor.
The example is very simple. Note that it calls the base class constructor.
<p>The destructor and destroy methods are:</p>
<pre>
ExampleCounter::~ExampleCounter()
{
destroy();
}
void ExampleCounter::destroy()
@ -289,7 +346,7 @@ void ExampleCounter::destroy()
PVRecord::destroy();
}
</pre>
The destructor just calls destroy.
The destructor has nothing to do.
The destroy method, which is virtual, just calls the destroy method of the base class.
A more complicated example can clean up any resources it used but must call the base
class destroy method.
@ -326,8 +383,13 @@ void ExampleCounter::process()
It adds 1.0 to the current value.
It then sets the timeStamp to the current time.
<h4>exampleCounterMain.cpp</h4>
<p>This is in test/server.
The main program is:</p>
<p>This is in test/server.</p>
<p><b>NOTE:</b>
This is a shorter version of the actual code.
It shows the essential code.
The actual example shows how the create additional records.
</p>
<p>The main program is:</p>
<pre>
int main(int argc,char *argv[])
{
@ -439,14 +501,11 @@ The following are the minimium features required</p>
</dd>
<dt>pvRecord.cpp</dt>
<dd>
The implementation of the base class for PVREcord.
The implementation of the base class for PVRecord.
It can also implement record instances with a process
method does nothing.
This can be used to create a "dumb" record where all changes are
done by clients.
The complete implementation is provided in the header file.
Thus code will be generated only if other code includes the
header file and creates a record instance.
</dd>
<dt>exampleCounter.h</dt>
<dd>
@ -472,6 +531,9 @@ pvRecord = RecordListRecord::create(recordName);
result = master-&gt;addRecord(pvRecord);
</pre>
</dd>
<dt>traceRecord.h</dt>
<dd>This implements a PVRecord that can set the trace level for
another record. See below for a discussion of trace level.</dd>
</dl>
<p>The classes in pvDatabase.h describe a database of memory resident
@ -514,9 +576,6 @@ typedef std::tr1::shared_ptr&lt;PVRecordClient&gt; PVRecordClientPtr;
class PVListener;
typedef std::tr1::shared_ptr&lt;PVListener&gt; PVListenerPtr;
class RecordProcessRequester;
typedef std::tr1::shared_ptr&lt;RecordProcessRequester&gt; RecordProcessRequesterPtr;
class RecordPutRequester;
typedef std::tr1::shared_ptr&lt;RecordPutRequester&gt; RecordPutRequesterPtr;
@ -548,12 +607,12 @@ public:
virtual bool init() {initPVRecord(); return true;}
virtual void process() {}
virtual void destroy();
static PVRecordPtr create(
epics::pvData::String const &amp; recordName,
epics::pvData::PVStructurePtr const &amp; pvStructure);
virtual ~PVRecord();
virtual void destroy();
epics::pvData::String getRecordName();
PVRecordStructurePtr getPVRecordStructure();
PVRecordFieldPtr findPVRecordField(
@ -582,6 +641,8 @@ public:
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:
PVRecord(
epics::pvData::String const &amp; recordName,
@ -596,27 +657,30 @@ private:
...
}
</pre>
<p>The methods are:</h3>
<p>The methods are:</p>
<dl>
<dt>init</dt>
<dd>Virtual method.
<p>Derived classes must implement this method.
This method Must call initPVRecord.</p>
Derived classes must implement this method.
This method Must call initPVRecord.
</dd>
<dt>process</dt>
<dd>Virtual method.
<p>Derived classes must implement this method.
The base implementation does nothing.</p>
Derived classes must implement this method.
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
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.</dd>
<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.
</dd>
<dt>~PVRecord</dt>
<dd>The destructor which must be virtual. A derived class must also have
a virtual destructor.</dd>
<dt>destroy</dt>
<dd>This is a virtual method.
</dd>
<dt>getRecordName</dt>
<dd>Return the recordName.</dd>
<dt>getPVRecordStructure</dt>
@ -670,6 +734,27 @@ private:
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.
<dl>
<dt>0</dt>
<dd>Produce no trace messages.</dd>
<dt>1</dt>
<dd>Issue a message to std::cout whenever anything is created
or destroyed.</dd>
<dt>2</dt>
<dd>In addition to lifetime messages also issue a message
whenever the record is accessed by pvAccess client.</dd>
</dl>
</dd>
<dt>setTraceLevel</dt>
<dd>Set the trace level. Note that special, described below.
provides a record support that allows a pvAccess client
to set the trace level of a record.</dd>
</dl>
<p>The protected methods are:</p>
<dl>
<dt>PVRecord</dt>
<dd>The constructor. It requires a recordName and a top level PVStructure.</dd>
<dt>initPVRecord</dt>
@ -707,6 +792,8 @@ protected:
return shared_from_this();
}
virtual void init();
virtual void postParent(PVRecordFieldPtr const &amp; subField);
virtual void postSubField();
private:
...
};
@ -812,6 +899,7 @@ public:
requested,PVRecordFieldPtr const &amp; pvRecordField) = 0;
virtual void beginGroupPut(PVRecordPtr const &amp; pvRecord) = 0;
virtual void endGroupPut(PVRecordPtr const &amp; pvRecord) = 0;
virtual void unlisten(PVRecordPtr const &amp; pvRecord);
};
</pre>
<p>where</p>
@ -831,6 +919,9 @@ public:
<dd>A related set of changes is being started.</dd>
<dt>endGroupPut</dt>
<dd>A related set of changes is done.</dd>
<dt>unlisten</dt>
<dd>The record is being destroyed. The listener must release all
access to the record.</dd>
</dl>
<h3>class PVDatabase</h3>
<pre>
@ -842,6 +933,7 @@ public:
virtual void destroy();
PVRecordPtr findRecord(epics::pvData::String const&amp; recordName);
bool addRecord(PVRecordPtr const &amp; record);
epics::pvData::PVStringArrayPtr getRecordNames();
bool removeRecord(PVRecordPtr const &amp; record);
virtual epics::pvData::String getRequesterName();
virtual void message(
@ -865,6 +957,8 @@ private:
<dt>addRecord</dt>
<dd>Add a record to the database.
If the record already exists it is not modified and false is returned.</dd>
<dt>getRecordNames</dt>
<dd>Returns an array of all the record names.</dd>
<dt>removeRecord</dt>
<dd>Remove a record from the database.
If the record was not in the database false is returned.</dd>
@ -882,24 +976,6 @@ It provides access to PVRecords and is access by the server side of remote pvAcc
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>ChannelLocalDebug</h3>
<p>The channelProvider implementation provides the ability to generate
debug messages based a debug level with the following meaning:</p>
<dl>
<dt>&lt;=0</dt>
<dd>No debug messages </dd>
<dt>&gt;0</dt>
<dd>Generate a message when anything is created or destroyed</dd>
<dt>&gt;1</dt>
<dd>Also generate processing messages.</dd>
</dl>
<p>ChannelProviderLocal has a method:</p>
<pre>
void createChannelLocalDebugRecord(
String const &amp; recordName);
</pre>
<p>This method creates a PVRecord that allows a pvAccess client to set the
debug level.</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.
@ -980,17 +1056,95 @@ like pvIOCJava there are plans to support for the following monitor algorithms:<
<dt>registerMonitorAlgorithmCreater</dt>
<dd>Called by code that implements a monitor algorithm.</dd>
</dl>
<h3>channelLocalDebugRecord</h3>
<h2>special</h2>
<p>This section provides two useful record support modules
and one that is used for testing.</p>
<h3>traceRecord</h3>
<p>This implements a PVRecord that allows a client to set
a debug level for the local channel provider implementation.
The top level structure has a single integer field named value.
See ChannelProviderLocal for the meaning associated with value.</p>
<p>ChannelProviderLocal has a method:</p>
the trace level of a record. It follows the pattern of a channelPutGet
record:
<pre>
void createChannelLocalDebugRecord(String const &amp; recordName);
traceRecord
structure arguments
string recordName
int level 0
structure result
string status
</pre>
<p>This creates an instance of a ChannelLocalDebugRecord and installs it
into the PVDatabase.</p>
where:
<dl>
<dt>recordName</dt>
<dd>The name of the record to set the trace level.</dd>
<dt>level</dt>
<dd>The level to set. The meaning is:
<dl>
<dt>0</dt>
<dd>No trace messages generated</dd>
<dt>1</dt>
<dd>Lifecycle messages will be generated.
This all channel create and destroy instances will be shown.</dd>
<dt>2</dt>
<dd>In addition to lifecycle messages a message will be generted
for each get and put request.</dd>
<dt>&gt;2</dt>
<dd>Currently no definition</dd>
</dl>
</dd>
<dt>result</dt>
<dd>The result of a cannelPutGet request</dd>
</dl>
<p>testExampleServerMain.cpp has an example of how to create a traceRecord:
<pre>
PVDatabasePtr master = PVDatabase::getMaster();
PVRecordPtr pvRecord;
String recordName;
bool result(false);
recordName = "traceRecordPGRPC";
pvRecord = TraceRecord::create(recordName);
result = master-&gt;addRecord(pvRecord);
if(!result) cout&lt;&lt; "record " &lt;&lt; recordName &lt;&lt; " not added" &lt;&lt; endl;
</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
record:
<pre>
traceRecord
structure arguments
string database master
string regularExpression .*
structure result
string status
string[] names
</pre>
where:
<dl>
<dt>database</dt>
<dd>The name of the datbase. The default is "master"</dd>
<dt>regularExpression</dt>
<dd>For now this is ignored and the complete list of names is always
returned.</dd>
<dt>status</dt>
<dd>The status of a putGet request.</dd>
<dt>names</dt>
<dd>The list of record names.</dd>
</dl>
<p>Note that swtshell has a command <b>channelList</b> that
requires that a record of this type is present and calls it.
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";
pvRecord = RecordListRecord::create(recordName);
result = master-&gt;addRecord(pvRecord);
if(!result) cout&lt;&lt; "record " &lt;&lt; recordName &lt;&lt; " not added" &lt;&lt; endl;
</pre>
<h3>powerSupplyRecordTest</h3>
<p>This simulates a simple power supply record.
It is used for testing.</p>
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -9,23 +9,27 @@ pvDatabase_LIBS += Com pvData pvAccess
SRC_DIRS += $(DATABASE)/database
INC += pvDatabase.h
INC += powerSupplyRecordTest.h
INC += exampleCounter.h
INC += recordList.h
LIBSRCS += pvRecord.cpp
LIBSRCS += pvDatabase.cpp
LIBSRCS += recordList.cpp
SRC_DIRS += $(DATABASE)/pvAccess
INC += channelProviderLocal.h
INC += pvCopy.h
INC += monitorAlgorithm.h
INC += channelLocalTraceRecord.h
LIBSRCS += channelProviderLocal.cpp
LIBSRCS += channelLocal.cpp
LIBSRCS += pvCopy.cpp
LIBSRCS += monitorFactory.cpp
LIBSRCS += channelLocalTraceRecord.cpp
SRC_DIRS += $(DATABASE)/special
INC += recordList.h
INC += traceRecord.h
INC += powerSupplyRecordTest.h
LIBSRCS += recordList.cpp
LIBSRCS += traceRecord.cpp
SRC_DIRS += $(DATABASE)/example
INC += exampleCounter.h
include $(TOP)/configure/RULES

View File

@ -66,6 +66,11 @@ public:
* call the <b>message</b> method provided by the base class.
*/
virtual void process() {}
/**
* Destroy the PVRecord. Release any resources used and
* get rid of listeners and requesters.
*/
virtual void destroy();
/**
* Creates a <b>dump</b> record, i.e. a record where process does nothing.
* @param recordName The name of the record, which is also the channelName.
@ -79,11 +84,6 @@ public:
* The Destructor. Must be virtual.
*/
virtual ~PVRecord();
/**
* Destroy the PVRecord. Release any resources used and
* get rid of listeners and requesters.
*/
virtual void destroy();
/**
* Get the name of the record.
* @return The name.
@ -218,6 +218,16 @@ public:
* @param indentLevel The indentation level.
*/
void toString(epics::pvData::StringBuilder buf,int indentLevel);
/**
* get trace level (0,1,2) means (nothing,lifetime,process)
* @return the level
*/
int getTraceLevel() {return traceLevel;}
/**
* set trace level (0,1) means (lifetime,process)
* @param level The level
*/
void setTraceLevel(int level) {traceLevel = level;}
protected:
/**
* Constructor
@ -254,6 +264,7 @@ private:
epics::pvData::Mutex mutex;
epics::pvData::Lock thelock;
std::size_t depthGroupPut;
int traceLevel;
bool isDestroyed;
};

View File

@ -38,6 +38,7 @@ PVRecord::PVRecord(
convert(getConvert()),
thelock(mutex),
depthGroupPut(0),
traceLevel(0),
isDestroyed(false)
{
thelock.unlock();

File diff suppressed because it is too large Load Diff

View File

@ -1,75 +0,0 @@
/* channelListTraceRecord.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2013.04.18
*/
#include <pv/channelLocalTraceRecord.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace pvDatabase {
ChannelLocalTraceRecordPtr ChannelLocalTraceRecord::create(
ChannelLocalTracePtr const &channelLocalTrace,
epics::pvData::String const & recordName)
{
FieldCreatePtr fieldCreate = getFieldCreate();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
StringArray argNames(1);
FieldConstPtrArray argFields(1);
argNames[0] = "value";
argFields[0] = fieldCreate->createScalar(pvInt);
StructureConstPtr topStructure =
fieldCreate->createStructure(argNames,argFields);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
ChannelLocalTraceRecordPtr pvRecord(
new ChannelLocalTraceRecord(channelLocalTrace,recordName,pvStructure));
if(!pvRecord->init()) pvRecord.reset();
return pvRecord;
}
ChannelLocalTraceRecord::ChannelLocalTraceRecord(
ChannelLocalTracePtr const &channelLocalTrace,
epics::pvData::String const & recordName,
epics::pvData::PVStructurePtr const & pvStructure)
: PVRecord(recordName,pvStructure),
channelLocalTrace(channelLocalTrace)
{
}
ChannelLocalTraceRecord::~ChannelLocalTraceRecord()
{
}
void ChannelLocalTraceRecord::destroy()
{
PVRecord::destroy();
}
bool ChannelLocalTraceRecord::init()
{
initPVRecord();
PVStructurePtr pvStructure = getPVStructure();
pvValue = pvStructure->getIntField("value");
if(pvValue==NULL) return false;
return true;
}
void ChannelLocalTraceRecord::process()
{
channelLocalTrace->setLevel(pvValue->get());
}
}}

View File

@ -11,7 +11,7 @@
#include <pv/serverContext.h>
#include <pv/channelProviderLocal.h>
#include <pv/channelLocalTraceRecord.h>
#include <pv/traceRecord.h>
namespace epics { namespace pvDatabase {
@ -71,40 +71,19 @@ ChannelProviderLocalPtr getChannelProviderLocal()
ChannelProviderLocal::ChannelProviderLocal()
: pvDatabase(PVDatabase::getMaster()),
beingDestroyed(false),
channelLocalTrace(new ChannelLocalTrace())
beingDestroyed(false)
{
}
ChannelProviderLocal::~ChannelProviderLocal()
{
// if(channelLocalTrace->getLevel()>0)
{
cout << "~ChannelProviderLocal()" << endl;
}
}
void ChannelProviderLocal::destroy()
{
Lock xx(mutex);
if(channelLocalTrace->getLevel()>0)
{
cout << "ChannelProviderLocal::destroy";
cout << " destroyed " << beingDestroyed << endl;
}
if(beingDestroyed) return;
beingDestroyed = true;
ChannelLocalList::iterator iter;
while(true) {
iter = channelList.begin();
if(iter==channelList.end()) break;
if(channelLocalTrace->getLevel()>0)
{
cout << "ChannelProviderLocal destroying channel " << (*iter).get();
cout << " channelName " << (*iter)->getChannelName() << endl;
}
(*iter)->destroy();
}
pvDatabase->destroy();
}
@ -118,25 +97,6 @@ ChannelFind::shared_pointer ChannelProviderLocal::channelFind(
ChannelFindRequester::shared_pointer const &channelFindRequester)
{
Lock xx(mutex);
if(channelLocalTrace->getLevel()>2)
{
cout << "ChannelProviderLocal::channelFind" << endl;
}
bool found = false;
ChannelLocalList::iterator iter;
for(iter = channelList.begin(); iter!=channelList.end(); ++iter)
{
if((*iter)->getChannelName().compare(channelName)==0) {
found = true;
break;
}
}
if(found) {
channelFindRequester->channelFindResult(
Status::Ok,
ChannelFind::shared_pointer(),
true);
}
PVRecordPtr pvRecord = pvDatabase->findRecord(channelName);
if(pvRecord.get()!=NULL) {
channelFindRequester->channelFindResult(
@ -172,17 +132,11 @@ Channel::shared_pointer ChannelProviderLocal::createChannel(
PVRecordPtr pvRecord = pvDatabase->findRecord(channelName);
if(pvRecord.get()!=NULL) {
ChannelLocalPtr channel(new ChannelLocal(
getPtrSelf(),channelRequester,pvRecord,channelLocalTrace));
getPtrSelf(),channelRequester,pvRecord));
channelRequester->channelCreated(
Status::Ok,
channel);
if(channelLocalTrace->getLevel()>1)
{
cout << "ChannelProviderLocal::createChannel " << channel.get();
cout << " channelName " << channelName << endl;
}
pvRecord->addPVRecordClient(channel);
channelList.insert(channel);
return channel;
}
Status notFoundStatus(Status::STATUSTYPE_ERROR,String("pv not found"));
@ -192,41 +146,4 @@ Channel::shared_pointer ChannelProviderLocal::createChannel(
return Channel::shared_pointer();
}
void ChannelProviderLocal::removeChannel(
Channel::shared_pointer const & channel)
{
Lock xx(mutex);
if(channelLocalTrace->getLevel()>0)
{
cout << "ChannelProviderLocal::removeChannel " << channel.get();
cout << " destroyed " << beingDestroyed << endl;
}
if(beingDestroyed) return;
ChannelLocalList::iterator iter;
for(iter = channelList.begin(); iter!=channelList.end(); ++iter)
{
if((*iter).get()==channel.get()) {
if(channelLocalTrace->getLevel()>1)
{
cout << "ChannelProviderLocal::removeChannel " << (*iter).get();
cout << " channelName " << channel->getChannelName() << endl;
}
channelList.erase(iter);
return;
}
}
}
void ChannelProviderLocal::createChannelLocalTraceRecord(
String const &recordName)
{
ChannelLocalTraceRecordPtr pvRecord
= ChannelLocalTraceRecord::create(channelLocalTrace,recordName);
PVDatabasePtr master = PVDatabase::getMaster();
bool result = master->addRecord(pvRecord);
if(!result) {
cout << "result of addRecord " << recordName << " " << result << endl;
}
}
}}

View File

@ -22,14 +22,11 @@
#include <pv/pvAccess.h>
#include <pv/pvDatabase.h>
#include <pv/status.h>
#include <pv/pvCopy.h>
#include <pv/monitorAlgorithm.h>
namespace epics { namespace pvDatabase {
class ChannelLocalTrace;
typedef std::tr1::shared_ptr<ChannelLocalTrace> ChannelLocalTracePtr;
class MonitorFactory;
typedef std::tr1::shared_ptr<MonitorFactory> MonitorFactoryPtr;
@ -42,30 +39,8 @@ class ChannelProviderLocal;
typedef std::tr1::shared_ptr<ChannelProviderLocal> ChannelProviderLocalPtr;
class ChannelLocal;
typedef std::tr1::shared_ptr<ChannelLocal> ChannelLocalPtr;
typedef std::multiset<ChannelLocalPtr> ChannelLocalList;
extern MonitorFactoryPtr getMonitorFactory();
class MonitorLocal;
typedef std::tr1::shared_ptr<MonitorLocal> MonitorLocalPtr;
typedef std::multiset<MonitorLocalPtr> MonitorLocalList;
class ChannelLocalTrace {
public:
ChannelLocalTrace()
: channelLocalTraceLevel(3)
{}
~ChannelLocalTrace(){}
void setLevel(int level)
{
channelLocalTraceLevel = level;
}
int getLevel()
{
return channelLocalTraceLevel;
}
private:
int channelLocalTraceLevel;
};
class MonitorFactory
{
@ -76,8 +51,7 @@ public:
epics::pvData::MonitorPtr createMonitor(
PVRecordPtr const & pvRecord,
epics::pvData::MonitorRequester::shared_pointer const & monitorRequester,
epics::pvData::PVStructurePtr const & pvRequest,
ChannelLocalTracePtr const &channelLocalTrace);
epics::pvData::PVStructurePtr const & pvRequest);
void registerMonitorAlgorithmCreate(
MonitorAlgorithmCreatePtr const &monitorAlgorithmCreate);
MonitorAlgorithmCreatePtr getMonitorAlgorithmCreate(
@ -87,7 +61,6 @@ private:
friend class MonitorLocal;
friend MonitorFactoryPtr getMonitorFactory();
std::multiset<MonitorAlgorithmCreatePtr> monitorAlgorithmCreateList;
std::multiset<MonitorLocalPtr> monitorLocalList;
bool isDestroyed;
epics::pvData::Mutex mutex;
};
@ -116,10 +89,6 @@ public:
epics::pvAccess::ChannelRequester::shared_pointer const &channelRequester,
short priority,
epics::pvData::String const &address);
void removeChannel(
epics::pvAccess::Channel::shared_pointer const &channel);
void createChannelLocalTraceRecord(epics::pvData::String const &recordName);
ChannelLocalTracePtr getChannelLocalTrace() { return channelLocalTrace;}
private:
shared_pointer getPtrSelf()
{
@ -128,10 +97,8 @@ private:
ChannelProviderLocal();
friend ChannelProviderLocalPtr getChannelProviderLocal();
PVDatabasePtr pvDatabase;
ChannelLocalList channelList;
epics::pvData::Mutex mutex;
bool beingDestroyed;
ChannelLocalTracePtr channelLocalTrace;
friend class ChannelProviderLocalRun;
};
@ -145,8 +112,7 @@ public:
ChannelLocal(
ChannelProviderLocalPtr const &channelProvider,
epics::pvAccess::ChannelRequester::shared_pointer const & requester,
PVRecordPtr const & pvRecord,
ChannelLocalTracePtr const &channelLocalTrace
PVRecordPtr const & pvRecord
);
virtual ~ChannelLocal();
virtual void destroy();
@ -192,19 +158,6 @@ public:
virtual void printInfo();
virtual void printInfo(epics::pvData::StringBuilder out);
virtual void detach(PVRecordPtr const &pvRecord);
// following called by derived classes
void addChannelProcess(epics::pvAccess::ChannelProcess::shared_pointer const &);
void addChannelGet(epics::pvAccess::ChannelGet::shared_pointer const &);
void addChannelPut(epics::pvAccess::ChannelPut::shared_pointer const &);
void addChannelPutGet(epics::pvAccess::ChannelPutGet::shared_pointer const &);
void addChannelRPC(epics::pvAccess::ChannelRPC::shared_pointer const &);
void addChannelArray(epics::pvAccess::ChannelArray::shared_pointer const &);
void removeChannelProcess(epics::pvAccess::ChannelProcess::shared_pointer const &);
void removeChannelGet(epics::pvAccess::ChannelGet::shared_pointer const &);
void removeChannelPut(epics::pvAccess::ChannelPut::shared_pointer const &);
void removeChannelPutGet(epics::pvAccess::ChannelPutGet::shared_pointer const &);
void removeChannelRPC(epics::pvAccess::ChannelRPC::shared_pointer const &);
void removeChannelArray(epics::pvAccess::ChannelArray::shared_pointer const &);
protected:
shared_pointer getPtrSelf()
{
@ -214,14 +167,7 @@ private:
ChannelProviderLocalPtr provider;
epics::pvAccess::ChannelRequester::shared_pointer requester;
PVRecordPtr pvRecord;
ChannelLocalTracePtr channelLocalTrace;
bool beingDestroyed;
std::multiset<epics::pvAccess::ChannelProcess::shared_pointer> channelProcessList;
std::multiset<epics::pvAccess::ChannelGet::shared_pointer> channelGetList;
std::multiset<epics::pvAccess::ChannelPut::shared_pointer> channelPutList;
std::multiset<epics::pvAccess::ChannelPutGet::shared_pointer> channelPutGetList;
std::multiset<epics::pvAccess::ChannelRPC::shared_pointer> channelRPCList;
std::multiset<epics::pvAccess::ChannelArray::shared_pointer> channelArrayList;
epics::pvData::Mutex mutex;
};

View File

@ -20,7 +20,8 @@ namespace epics { namespace pvDatabase {
using namespace epics::pvData;
using namespace epics::pvAccess;
using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
using std::cout;
using std::endl;
static MonitorAlgorithmCreatePtr nullMonitorAlgorithmCreate;
static MonitorPtr nullMonitor;
@ -129,8 +130,7 @@ public:
bool init(PVStructurePtr const & pvRequest);
MonitorLocal(
MonitorRequester::shared_pointer const & channelMonitorRequester,
PVRecordPtr const &pvRecord,
ChannelLocalTracePtr const &channelLocalTrace);
PVRecordPtr const &pvRecord);
PVCopyPtr getPVCopy() { return pvCopy;}
PVCopyMonitorPtr getPVCopyMonitor() { return pvCopyMonitor;}
private:
@ -140,23 +140,19 @@ private:
}
MonitorRequester::shared_pointer monitorRequester;
PVRecordPtr pvRecord;
ChannelLocalTracePtr channelLocalTrace;
bool isDestroyed;
bool firstMonitor;
PVCopyPtr pvCopy;
MonitorQueuePtr queue;
PVCopyMonitorPtr pvCopyMonitor;
// std::list<MonitorFieldNodePtr> monitorFieldList;
Mutex mutex;
};
MonitorLocal::MonitorLocal(
MonitorRequester::shared_pointer const & channelMonitorRequester,
PVRecordPtr const &pvRecord,
ChannelLocalTracePtr const &channelLocalTrace)
PVRecordPtr const &pvRecord)
: monitorRequester(channelMonitorRequester),
pvRecord(pvRecord),
channelLocalTrace(channelLocalTrace),
isDestroyed(false),
firstMonitor(true)
{
@ -164,12 +160,18 @@ MonitorLocal::MonitorLocal(
MonitorLocal::~MonitorLocal()
{
std::cout << "MonitorLocal::~MonitorLocal()" << std::endl;
if(pvRecord->getTraceLevel()>0)
{
cout << "MonitorLocal::~MonitorLocal()" << endl;
}
}
void MonitorLocal::destroy()
{
std::cout << "MonitorLocal::destroy " << isDestroyed << std::endl;
if(pvRecord->getTraceLevel()>0)
{
cout << "MonitorLocal::destroy " << isDestroyed << endl;
}
{
Lock xx(mutex);
if(isDestroyed) return;
@ -177,24 +179,29 @@ std::cout << "MonitorLocal::destroy " << isDestroyed << std::endl;
}
unlisten();
stop();
// monitorFieldList.clear();
pvCopyMonitor->destroy();
pvCopy->destroy();
pvCopyMonitor.reset();
queue.reset();
pvCopy.reset();
monitorRequester.reset();
pvRecord.reset();
}
Status MonitorLocal::start()
{
//std::cout << "MonitorLocal::start" << std::endl;
if(pvRecord->getTraceLevel()>0)
{
cout << "MonitorLocal::start() " << endl;
}
firstMonitor = true;
return queue->start();
}
Status MonitorLocal::stop()
{
std::cout << "MonitorLocal::stop" << std::endl;
if(pvRecord->getTraceLevel()>0)
{
cout << "MonitorLocal::stop() " << endl;
}
pvCopyMonitor->stopMonitoring();
queue->stop();
return Status::Ok;
@ -202,13 +209,19 @@ std::cout << "MonitorLocal::stop" << std::endl;
MonitorElementPtr MonitorLocal::poll()
{
//std::cout << "MonitorLocal::poll" << std::endl;
if(pvRecord->getTraceLevel()>1)
{
cout << "MonitorLocal::poll() " << endl;
}
return queue->poll();
}
void MonitorLocal::dataChanged()
{
//std::cout << "MonitorLocal::dataChanged" << std::endl;
if(pvRecord->getTraceLevel()>1)
{
cout << "MonitorLocal::dataChanged() " << endl;
}
if(firstMonitor) {
queue->dataChanged();
firstMonitor = false;
@ -222,13 +235,19 @@ void MonitorLocal::dataChanged()
void MonitorLocal::unlisten()
{
std::cout << "MonitorLocal::unlisten" << std::endl;
if(pvRecord->getTraceLevel()>0)
{
cout << "MonitorLocal::unlisten() " << endl;
}
monitorRequester->unlisten(getPtrSelf());
}
void MonitorLocal::release(MonitorElementPtr const & monitorElement)
{
//std::cout << "MonitorLocal::release" << std::endl;
if(pvRecord->getTraceLevel()>1)
{
cout << "MonitorLocal::release() " << endl;
}
queue->release(monitorElement);
}
@ -309,26 +328,15 @@ MonitorFactory::~MonitorFactory()
void MonitorFactory::destroy()
{
std::cout << "MonitorFactory::destroy " << isDestroyed << std::endl;
Lock lock(mutex);
if(isDestroyed) return;
isDestroyed = true;
while(true) {
std::multiset<MonitorLocalPtr>::iterator it;
it = monitorLocalList.begin();
if(it==monitorLocalList.end()) break;
monitorLocalList.erase(it);
lock.unlock();
it->get()->destroy();
lock.lock();
}
}
MonitorPtr MonitorFactory::createMonitor(
PVRecordPtr const & pvRecord,
MonitorRequester::shared_pointer const & monitorRequester,
PVStructurePtr const & pvRequest,
ChannelLocalTracePtr const &channelLocalTrace)
PVStructurePtr const & pvRequest)
{
Lock xx(mutex);
if(isDestroyed) {
@ -336,15 +344,14 @@ MonitorPtr MonitorFactory::createMonitor(
return nullMonitor;
}
MonitorLocalPtr monitor(new MonitorLocal(
monitorRequester,pvRecord,channelLocalTrace));
monitorRequester,pvRecord));
bool result = monitor->init(pvRequest);
if(!result) return nullMonitor;
if(channelLocalTrace->getLevel()>0)
if(pvRecord->getTraceLevel()>0)
{
std::cout << "MonitorFactory::createMonitor";
std::cout << " recordName " << pvRecord->getRecordName() << std::endl;
cout << "MonitorFactory::createMonitor";
cout << " recordName " << pvRecord->getRecordName() << endl;
}
monitorLocalList.insert(monitor);
return monitor;
}

View File

@ -13,13 +13,16 @@
#include <memory>
#include <sstream>
#include <pv/pvCopy.h>
#include <pv/channelProviderLocal.h>
namespace epics { namespace pvDatabase {
using namespace epics::pvData;
using std::tr1::static_pointer_cast;
using std::size_t;
using std::cout;
using std::endl;
static PVCopyPtr NULLPVCopy;
static FieldConstPtr NULLField;
@ -73,11 +76,21 @@ PVCopyPtr PVCopy::create(
return pvCopy;
}
PVCopy::PVCopy(PVRecordPtr const &pvRecord)
PVCopy::PVCopy(
PVRecordPtr const &pvRecord)
: pvRecord(pvRecord)
{
}
void PVCopy::destroy()
{
if(pvRecord->getTraceLevel()>0)
{
cout << "PVCopy::destroy" << endl;
}
headNode.reset();
}
PVRecordPtr PVCopy::getPVRecord()
{
return pvRecord;
@ -990,24 +1003,41 @@ PVCopyMonitor::PVCopyMonitor(
pvCopy(pvCopy),
pvCopyMonitorRequester(pvCopyMonitorRequester),
isGroupPut(false),
dataChanged(false)
dataChanged(false),
isMonitoring(false)
{
}
PVCopyMonitor::~PVCopyMonitor()
{
pvRecord.reset();
headNode.reset();
pvCopy.reset();
pvCopyMonitorRequester.reset();
changeBitSet.reset();
overrunBitSet.reset();
if(pvRecord->getTraceLevel()>0)
{
cout << "~PVCopyMonitor" << endl;
}
}
void PVCopyMonitor::destroy()
{
if(pvRecord->getTraceLevel()>0)
{
cout << "PVCopyMonitor::destroy()" << endl;
}
stopMonitoring();
pvCopyMonitorRequester.reset();
pvCopy.reset();
}
void PVCopyMonitor::startMonitoring(
BitSetPtr const &changeBitSet,
BitSetPtr const &overrunBitSet)
{
if(pvRecord->getTraceLevel()>0)
{
cout << "PVCopyMonitor::startMonitoring()" << endl;
}
Lock xx(mutex);
if(isMonitoring) return;
isMonitoring = true;
this->changeBitSet = changeBitSet;
this->overrunBitSet = overrunBitSet;
isGroupPut = false;
@ -1027,7 +1057,13 @@ void PVCopyMonitor::startMonitoring(
void PVCopyMonitor::stopMonitoring()
{
std::cout << "PVCopyMonitor::stopMonitoring()" << std::endl;
if(pvRecord->getTraceLevel()>0)
{
cout << "PVCopyMonitor::stopMonitoring()" << endl;
}
Lock xx(mutex);
if(!isMonitoring) return;
isMonitoring = false;
pvRecord->removeListener(getPtrSelf());
}
@ -1048,6 +1084,10 @@ void PVCopyMonitor::switchBitSets(
void PVCopyMonitor::detach(PVRecordPtr const & pvRecord)
{
if(pvRecord->getTraceLevel()>0)
{
cout << "PVCopyMonitor::detach()" << endl;
}
}
void PVCopyMonitor::dataPut(PVRecordFieldPtr const & pvRecordField)

View File

@ -14,8 +14,8 @@
#include <stdexcept>
#include <memory>
#include <pv/pvDatabase.h>
#include <pv/pvAccess.h>
#include <pv/pvDatabase.h>
namespace epics { namespace pvDatabase {
@ -48,6 +48,7 @@ public:
epics::pvData::PVStructurePtr const &pvRequest,
epics::pvData::String const & structureName);
virtual ~PVCopy(){}
virtual void destroy();
PVRecordPtr getPVRecord();
epics::pvData::StructureConstPtr getStructure();
epics::pvData::PVStructurePtr createPVStructure();
@ -163,6 +164,7 @@ class PVCopyMonitor :
public:
POINTER_DEFINITIONS(PVCopyMonitor);
virtual ~PVCopyMonitor();
virtual void destroy();
void startMonitoring(
epics::pvData::BitSetPtr const &changeBitSet,
epics::pvData::BitSetPtr const &overrunBitSet);
@ -202,12 +204,15 @@ private:
epics::pvData::BitSetPtr overrunBitSet;
bool isGroupPut;
bool dataChanged;
bool isMonitoring;
epics::pvData::Mutex mutex;
};
class PVCopyMonitorRequester
{
public:
POINTER_DEFINITIONS(PVCopyMonitorRequester);
virtual ~PVCopyMonitorRequester() {}
virtual void dataChanged() = 0;
virtual void unlisten() = 0;
};

View File

@ -90,10 +90,9 @@ bool RecordListRecord::init()
void RecordListRecord::process()
{
PVStringArrayPtr pvNames = PVDatabase::getMaster()->getRecordNames();
std::vector<String> const & xxx = pvNames->getVector();
size_t n = xxx.size();
names->put(0,n,xxx,0);
// names->replace(pvNames->viewUnsafe()); for pvDataCPP-md
std::vector<String> const & xxx = pvNames->getVector();
size_t n = xxx.size();
names->put(0,n,xxx,0);
String message("");
if(database->get().compare("master")!=0) {
message += " can only access master ";

View File

@ -0,0 +1,96 @@
/* traceRecord.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2013.04.18
*/
#include <pv/traceRecord.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace pvDatabase {
TraceRecordPtr TraceRecord::create(
epics::pvData::String const & recordName)
{
FieldCreatePtr fieldCreate = getFieldCreate();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
StringArray topNames(2);
FieldConstPtrArray topFields(2);
topNames[0] = "arguments";
topNames[1] = "result";
StringArray argNames(2);
FieldConstPtrArray argFields(2);
argNames[0] = "recordName";
argNames[1] = "level";
argFields[0] = fieldCreate->createScalar(pvString);
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);
TraceRecordPtr pvRecord(
new TraceRecord(recordName,pvStructure));
if(!pvRecord->init()) pvRecord.reset();
return pvRecord;
}
TraceRecord::TraceRecord(
epics::pvData::String const & recordName,
epics::pvData::PVStructurePtr const & pvStructure)
: PVRecord(recordName,pvStructure),
pvDatabase(PVDatabase::getMaster()),
isDestroyed(false)
{
}
TraceRecord::~TraceRecord()
{
}
void TraceRecord::destroy()
{
PVRecord::destroy();
}
bool TraceRecord::init()
{
initPVRecord();
PVStructurePtr pvStructure = getPVStructure();
pvRecordName = pvStructure->getStringField("arguments.recordName");
if(pvRecordName==NULL) return false;
pvLevel = pvStructure->getIntField("arguments.level");
if(pvLevel==NULL) return false;
pvResult = pvStructure->getStringField("result.status");
if(pvResult==NULL) return false;
return true;
}
void TraceRecord::process()
{
String name = pvRecordName->get();
PVRecordPtr pvRecord = pvDatabase->findRecord(name);
if(pvRecord==NULL) {
pvResult->put(name + " not found");
return;
}
pvRecord->setTraceLevel(pvLevel->get());
pvResult->put("success");
}
}}

View File

@ -1,4 +1,4 @@
/* channelLocalTraceRecord.h */
/* traceRecord.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
@ -8,39 +8,39 @@
* @author mrk
* @date 2013.04.18
*/
#ifndef CHANNELLOCALTRACERECORD_H
#define CHANNELLOCALTRACERECORD_H
#ifndef TRACERECORD_H
#define TRACERECORD_H
#include <pv/channelProviderLocal.h>
namespace epics { namespace pvDatabase {
class ChannelLocalTraceRecord;
typedef std::tr1::shared_ptr<ChannelLocalTraceRecord> ChannelLocalTraceRecordPtr;
class TraceRecord;
typedef std::tr1::shared_ptr<TraceRecord> TraceRecordPtr;
class ChannelLocalTraceRecord :
class TraceRecord :
public PVRecord
{
public:
POINTER_DEFINITIONS(ChannelLocalTraceRecord);
static ChannelLocalTraceRecordPtr create(
ChannelLocalTracePtr const &channelLocalTrace,
POINTER_DEFINITIONS(TraceRecord);
static TraceRecordPtr create(
epics::pvData::String const & recordName);
virtual ~ChannelLocalTraceRecord();
virtual ~TraceRecord();
virtual void destroy();
virtual bool init();
virtual void process();
private:
ChannelLocalTraceRecord(
ChannelLocalTracePtr const &channelLocalTrace,
TraceRecord(
epics::pvData::String const & recordName,
epics::pvData::PVStructurePtr const & pvStructure);
ChannelLocalTracePtr channelLocalTrace;
epics::pvData::PVIntPtr pvValue;
PVDatabasePtr pvDatabase;
epics::pvData::PVStringPtr pvRecordName;
epics::pvData::PVIntPtr pvLevel;
epics::pvData::PVStringPtr pvResult;
bool isDestroyed;
};
}}
#endif /* CHANNELLOCALTRACERECORD_H */
#endif /* TRACERECORD_H */

View File

@ -2,9 +2,9 @@ TOP=../..
include $(TOP)/configure/CONFIG
#PROD_HOST += testPVCopy
#testPVCopy_SRCS += testPVCopy.cpp
#testPVCopy_LIBS += pvDatabase pvAccess pvData Com
PROD_HOST += testPVCopy
testPVCopy_SRCS += testPVCopy.cpp
testPVCopy_LIBS += pvDatabase pvAccess pvData Com
PROD_HOST += testPVRecord
testPVRecord_SRCS += testPVRecord.cpp

View File

@ -25,9 +25,7 @@
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/pvData.h>
#include <pv/pvAccess.h>
#include <pv/pvCopy.h>
#include <pv/channelProviderLocal.h>
#include <pv/powerSupplyRecordTest.h>

View File

@ -21,6 +21,7 @@
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/exampleCounter.h>
#include <pv/traceRecord.h>
#include <pv/channelProviderLocal.h>
#include <pv/serverContext.h>
@ -34,11 +35,17 @@ int main(int argc,char *argv[])
{
PVDatabasePtr master = PVDatabase::getMaster();
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
channelProvider->createChannelLocalTraceRecord("channelLocalTrace");
String recordName("exampleCounter");
PVRecordPtr pvRecord = ExampleCounter::create(recordName);
bool result = master->addRecord(pvRecord);
PVRecordPtr pvRecord;
bool result(false);
String recordName;
recordName = "exampleCounter";
pvRecord = ExampleCounter::create(recordName);
result = master->addRecord(pvRecord);
cout << "result of addRecord " << recordName << " " << result << endl;
recordName = "traceRecordPGRPC";
pvRecord = TraceRecord::create(recordName);
result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;
pvRecord.reset();
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
cout << "exampleServer\n";

View File

@ -20,10 +20,11 @@
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/exampleCounter.h>
#include <pv/powerSupplyRecordTest.h>
#include <pv/channelProviderLocal.h>
#include <pv/exampleCounter.h>
#include <pv/recordList.h>
#include <pv/traceRecord.h>
#include <pv/serverContext.h>
using namespace std;
@ -63,13 +64,16 @@ int main(int argc,char *argv[])
{
PVDatabasePtr master = PVDatabase::getMaster();
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
channelProvider->createChannelLocalTraceRecord("channelLocalTrace");
StandardPVFieldPtr standardPVField = getStandardPVField();
String properties;
ScalarType scalarType;
PVRecordPtr pvRecord;
String recordName;
bool result(false);
recordName = "traceRecordPGRPC";
pvRecord = TraceRecord::create(recordName);
result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;
StandardPVFieldPtr standardPVField = getStandardPVField();
String properties;
ScalarType scalarType;
recordName = "exampleCounter";
pvRecord = ExampleCounter::create(recordName);
result = master->addRecord(pvRecord);
@ -103,10 +107,11 @@ int main(int argc,char *argv[])
return 1;
}
result = master->addRecord(psr);
recordName = "laptoprecordListPGRPC";
if(!result) cout<< "record " << recordName << " not added" << endl;
recordName = "laptoprecordListPGRPC";
pvRecord = RecordListRecord::create(recordName);
result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;
ServerContext::shared_pointer ctx =
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
cout << "exampleServer\n";
@ -121,12 +126,9 @@ int main(int argc,char *argv[])
if(str.compare("exit")==0) break;
}
cout << "calling ctx->destroy()" << endl;
ctx->destroy();
epicsThreadSleep(1.0);
cout << "calling channelProvider->destroy()" << endl;
channelProvider->destroy();
epicsThreadSleep(1.0);
return 0;
}