channelArray, trace implemented. Known memory leaks and exceptions fixed.
This commit is contained in:
@ -38,7 +38,7 @@
|
||||
<h1>pvDatabaseCPP</h1>
|
||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
||||
|
||||
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 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<<.
|
||||
</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> pwd
|
||||
/home/hg/pvDatabaseCPP
|
||||
mrk> 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->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<PVRecordClient> PVRecordClientPtr;
|
||||
class PVListener;
|
||||
typedef std::tr1::shared_ptr<PVListener> PVListenerPtr;
|
||||
|
||||
class RecordProcessRequester;
|
||||
typedef std::tr1::shared_ptr<RecordProcessRequester> RecordProcessRequesterPtr;
|
||||
|
||||
class RecordPutRequester;
|
||||
typedef std::tr1::shared_ptr<RecordPutRequester> 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 & recordName,
|
||||
epics::pvData::PVStructurePtr const & 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 & 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 & subField);
|
||||
virtual void postSubField();
|
||||
private:
|
||||
...
|
||||
};
|
||||
@ -812,6 +899,7 @@ public:
|
||||
requested,PVRecordFieldPtr const & pvRecordField) = 0;
|
||||
virtual void beginGroupPut(PVRecordPtr const & pvRecord) = 0;
|
||||
virtual void endGroupPut(PVRecordPtr const & pvRecord) = 0;
|
||||
virtual void unlisten(PVRecordPtr const & 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& recordName);
|
||||
bool addRecord(PVRecordPtr const & record);
|
||||
epics::pvData::PVStringArrayPtr getRecordNames();
|
||||
bool removeRecord(PVRecordPtr const & 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><=0</dt>
|
||||
<dd>No debug messages </dd>
|
||||
<dt>>0</dt>
|
||||
<dd>Generate a message when anything is created or destroyed</dd>
|
||||
<dt>>1</dt>
|
||||
<dd>Also generate processing messages.</dd>
|
||||
</dl>
|
||||
<p>ChannelProviderLocal has a method:</p>
|
||||
<pre>
|
||||
void createChannelLocalDebugRecord(
|
||||
String const & 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 & 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>>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->addRecord(pvRecord);
|
||||
if(!result) cout<< "record " << recordName << " not added" << 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->addRecord(pvRecord);
|
||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||
</pre>
|
||||
<h3>powerSupplyRecordTest</h3>
|
||||
<p>This simulates a simple power supply record.
|
||||
It is used for testing.</p>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
1150
documentation/pvDatabaseCPP_20130627.html
Normal file
1150
documentation/pvDatabaseCPP_20130627.html
Normal file
File diff suppressed because it is too large
Load Diff
16
src/Makefile
16
src/Makefile
@ -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
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
@ -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());
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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 ";
|
96
src/special/traceRecord.cpp
Normal file
96
src/special/traceRecord.cpp
Normal 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");
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
@ -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 */
|
@ -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
|
||||
|
@ -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>
|
||||
|
||||
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user