Compare commits
67 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b20fd4c5c5 | ||
|
|
409b045779 | ||
|
|
fda81767a5 | ||
|
|
fe1b167e23 | ||
|
|
dc0f20cc5f | ||
|
|
6e7d887e6e | ||
|
|
699a6cd8b4 | ||
|
|
70454a6006 | ||
|
|
deebe46378 | ||
|
|
18dc4279ad | ||
|
|
61e9dc0368 | ||
|
|
6b0d1ce49b | ||
|
|
81b160d7b6 | ||
|
|
4e22a056d2 | ||
|
|
4af5ba92d9 | ||
|
|
e79c70c74c | ||
|
|
c0694e2d69 | ||
|
|
36dac883f4 | ||
|
|
35dcbf35b3 | ||
|
|
30dd2ed046 | ||
|
|
e30e4f3638 | ||
|
|
15578d1647 | ||
|
|
e3e270e242 | ||
|
|
ec44251df0 | ||
|
|
3344165f19 | ||
|
|
c2ea402be0 | ||
|
|
0535ff990d | ||
|
|
18ff90e641 | ||
|
|
a781195458 | ||
|
|
1a641f0d1b | ||
|
|
0e6639c149 | ||
|
|
93ba23aeb8 | ||
|
|
7743f3e3fd | ||
|
|
e9ce6a2f0b | ||
|
|
1ed48c15f1 | ||
|
|
d27f929595 | ||
|
|
b4e17f271b | ||
|
|
79f407486a | ||
|
|
3c359728f7 | ||
|
|
7b9693562a | ||
|
|
f1c39ca5d2 | ||
|
|
16b1775b98 | ||
|
|
f6ee7333bb | ||
|
|
9f45bdfa75 | ||
|
|
03aa15b5f7 | ||
|
|
8093952ca2 | ||
|
|
2bea54e218 | ||
|
|
e81230dba5 | ||
|
|
50b8f306c3 | ||
|
|
65be8e5678 | ||
|
|
dbb9310adc | ||
|
|
50fbb396e8 | ||
|
|
ff19fe1cd8 | ||
|
|
230938220e | ||
|
|
334ed3b70a | ||
|
|
4c7e51d8ad | ||
|
|
4973a6297e | ||
|
|
f0d1481a28 | ||
|
|
d5235db54c | ||
|
|
b125035a11 | ||
|
|
9551b0e4c6 | ||
|
|
d6aa03815e | ||
|
|
ce0d62fbbc | ||
|
|
2fe3e66047 | ||
|
|
fa53d72258 | ||
|
|
b010cf0849 | ||
|
|
7fd707cb4b |
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
bin/
|
||||||
|
lib/
|
||||||
|
doc/
|
||||||
|
include/
|
||||||
|
db/
|
||||||
|
dbd/
|
||||||
|
documentation/html
|
||||||
|
documentation/*.tag
|
||||||
|
envPaths
|
||||||
|
configure/*.local
|
||||||
|
!configure/ExampleRELEASE.local
|
||||||
|
**/O.*
|
||||||
|
QtC-*
|
||||||
8
.hgflow
8
.hgflow
@@ -1,8 +0,0 @@
|
|||||||
[branchname]
|
|
||||||
master = master
|
|
||||||
develop = default
|
|
||||||
feature = feature/
|
|
||||||
release = release/
|
|
||||||
hotfix = hotfix/
|
|
||||||
support = support/
|
|
||||||
|
|
||||||
11
.hgignore
11
.hgignore
@@ -1,11 +0,0 @@
|
|||||||
^QtC-
|
|
||||||
bin/
|
|
||||||
lib/
|
|
||||||
doc/
|
|
||||||
include/
|
|
||||||
db/
|
|
||||||
dbd/
|
|
||||||
documentation/html
|
|
||||||
envPaths
|
|
||||||
configure/.*\.local
|
|
||||||
/O\..*
|
|
||||||
2
.hgtags
2
.hgtags
@@ -1,2 +0,0 @@
|
|||||||
bba6a2491bdf73681cef01caf0bd89c87d7989cd 0.9.1
|
|
||||||
abdc90bf52a0c31e24e2f9a079ef72350ee31686 before_merge_changesAfter3_0_2
|
|
||||||
2
LICENSE
2
LICENSE
@@ -2,7 +2,7 @@
|
|||||||
Copyright (c) 2008 Martin R. Kraimer
|
Copyright (c) 2008 Martin R. Kraimer
|
||||||
Copyright (c) 2006 The University of Chicago, as Operator of Argonne
|
Copyright (c) 2006 The University of Chicago, as Operator of Argonne
|
||||||
National Laboratory.
|
National Laboratory.
|
||||||
Copyright (c) 2006 Deutsches Elektronen-Synchroton,
|
Copyright (c) 2006 Deutsches Elektronen-Synchrotron,
|
||||||
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
|
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
|
||||||
Copyright (c) 2007 Control System Laboratory,
|
Copyright (c) 2007 Control System Laboratory,
|
||||||
(COSYLAB) Ljubljana Slovenia
|
(COSYLAB) Ljubljana Slovenia
|
||||||
|
|||||||
38
README.md
Normal file
38
README.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
pvaDatabaseCPP
|
||||||
|
============
|
||||||
|
|
||||||
|
|
||||||
|
A brief description of a pvDatabase is that it is a set of network accessible, smart, memory resident records. Each record has data composed of a top level PVStructure. Each record has a name which is the channelName for pvAccess. A local Channel Provider implements the complete ChannelProvider and Channel interfaces as defined by pvAccess. The local provider provides access to the records in the pvDatabase. This local provider is accessed by the remote pvAccess server. A record is smart because code can be attached to a record, which is accessed via a method named process.
|
||||||
|
pvaDatabase is a synchronous Database interface to pvAccess,
|
||||||
|
which is callback based.
|
||||||
|
pvaDatabase is thus easier to use than pvAccess itself.
|
||||||
|
|
||||||
|
See documentation/pvaDatabaseCPP.html for details.
|
||||||
|
|
||||||
|
Building
|
||||||
|
--------
|
||||||
|
|
||||||
|
If a proper RELEASE.local file exists one directory level above pvaDatabaseCPP
|
||||||
|
then just type:
|
||||||
|
|
||||||
|
make
|
||||||
|
|
||||||
|
If RELEASE.local does not exist then look at <b>configure/RELEASE</b>
|
||||||
|
for directions for how to build.
|
||||||
|
|
||||||
|
Examples
|
||||||
|
------------
|
||||||
|
|
||||||
|
The examples require the database in pvaDatabaseTestCPP.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
mrk> pwd
|
||||||
|
/home/epicsv4/pvaDatabaseTestCPP/database/iocBoot/exampleDatabase
|
||||||
|
mrk> ../../bin/linux-x86_64/exampleDatabase st.cmd
|
||||||
|
|
||||||
|
Status
|
||||||
|
------
|
||||||
|
|
||||||
|
* The API is for release 4.5.0-pre1
|
||||||
|
|
||||||
|
|
||||||
@@ -35,5 +35,5 @@
|
|||||||
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
||||||
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
||||||
|
|
||||||
-include $(TOP)/configure/CONFIG_SITE.local
|
-include $(TOP)/../../CONFIG_SITE.local
|
||||||
-include $(TOP)/../CONFIG.local
|
-include $(TOP)/../configure/CONFIG_SITE.local
|
||||||
|
|||||||
@@ -59,9 +59,9 @@ bool ArrayPerformance::init()
|
|||||||
{
|
{
|
||||||
|
|
||||||
initPVRecord();
|
initPVRecord();
|
||||||
PVScalarArrayPtr pvScalarArray = getPVStructure()->getScalarArrayField("value",pvLong);
|
PVLongArrayPtr pvLongArray = getPVStructure()->getSubField<PVLongArray>("value");
|
||||||
if(pvScalarArray==NULL) return false;
|
if(!pvLongArray) return false;
|
||||||
pvValue = static_pointer_cast<PVLongArray>(pvScalarArray);
|
pvValue = pvLongArray;
|
||||||
ArrayPerformancePtr xxx = dynamic_pointer_cast<ArrayPerformance>(getPtrSelf());
|
ArrayPerformancePtr xxx = dynamic_pointer_cast<ArrayPerformance>(getPtrSelf());
|
||||||
arrayPerformanceThread = ArrayPerformanceThreadPtr(new ArrayPerformanceThread(xxx));
|
arrayPerformanceThread = ArrayPerformanceThreadPtr(new ArrayPerformanceThread(xxx));
|
||||||
arrayPerformanceThread->init();
|
arrayPerformanceThread->init();
|
||||||
@@ -182,14 +182,18 @@ void ArrayPerformanceThread::run()
|
|||||||
nSinceLastReport = 0;
|
nSinceLastReport = 0;
|
||||||
}
|
}
|
||||||
++nSinceLastReport;
|
++nSinceLastReport;
|
||||||
shared_vector<int64> xxx(arrayPerformance->size,value++);
|
|
||||||
shared_vector<const int64> data(freeze(xxx));
|
|
||||||
arrayPerformance->lock();
|
arrayPerformance->lock();
|
||||||
try {
|
try {
|
||||||
arrayPerformance->beginGroupPut();
|
if(arrayPerformance->getTraceLevel()>1) {
|
||||||
arrayPerformance->pvValue->replace(data);
|
cout << "arrayPerformance size " << arrayPerformance->size;
|
||||||
arrayPerformance->process();
|
cout << " value " << value +1 << endl;
|
||||||
arrayPerformance->endGroupPut();
|
}
|
||||||
|
shared_vector<int64> xxx(arrayPerformance->size,value++);
|
||||||
|
shared_vector<const int64> data(freeze(xxx));
|
||||||
|
arrayPerformance->beginGroupPut();
|
||||||
|
arrayPerformance->pvValue->replace(data);
|
||||||
|
arrayPerformance->process();
|
||||||
|
arrayPerformance->endGroupPut();
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
arrayPerformance->unlock();
|
arrayPerformance->unlock();
|
||||||
throw;
|
throw;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
# undef epicsExportSharedSymbols
|
# undef epicsExportSharedSymbols
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <shareLib.h>
|
|
||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
#include <pv/standardPVField.h>
|
#include <pv/standardPVField.h>
|
||||||
#include <pv/timeStamp.h>
|
#include <pv/timeStamp.h>
|
||||||
|
|||||||
@@ -266,9 +266,9 @@ void LongArrayChannelGet::channelGetConnect(
|
|||||||
bool structureOK(true);
|
bool structureOK(true);
|
||||||
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(structure);
|
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(structure);
|
||||||
PVFieldPtr pvField = pvStructure->getSubField("timeStamp");
|
PVFieldPtr pvField = pvStructure->getSubField("timeStamp");
|
||||||
if(pvField==NULL) structureOK = false;
|
if(!pvField) structureOK = false;
|
||||||
pvField = pvStructure->getSubField("value");
|
pvField = pvStructure->getSubField("value");
|
||||||
if(pvField==NULL) {
|
if(!pvField) {
|
||||||
structureOK = false;
|
structureOK = false;
|
||||||
} else {
|
} else {
|
||||||
FieldConstPtr field = pvField->getField();
|
FieldConstPtr field = pvField->getField();
|
||||||
@@ -292,7 +292,7 @@ bool LongArrayChannelGet::init()
|
|||||||
{
|
{
|
||||||
ChannelProvider::shared_pointer channelProvider =
|
ChannelProvider::shared_pointer channelProvider =
|
||||||
getChannelProviderRegistry()->getProvider(providerName);
|
getChannelProviderRegistry()->getProvider(providerName);
|
||||||
if(channelProvider==NULL) {
|
if(!channelProvider) {
|
||||||
cout << "provider " << providerName << " not found" << endl;
|
cout << "provider " << providerName << " not found" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -305,7 +305,7 @@ bool LongArrayChannelGet::init()
|
|||||||
if(!status.isOK()) return false;
|
if(!status.isOK()) return false;
|
||||||
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
||||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||||
if(pvRequest==NULL) {
|
if(!pvRequest) {
|
||||||
cout << "request logic error " << createRequest->getMessage() << endl;
|
cout << "request logic error " << createRequest->getMessage() << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -334,10 +334,10 @@ void LongArrayChannelGet::destroy()
|
|||||||
if(runReturned) break;
|
if(runReturned) break;
|
||||||
epicsThreadSleep(.01);
|
epicsThreadSleep(.01);
|
||||||
}
|
}
|
||||||
if(longArrayChannelRequester!=NULL) {
|
if(longArrayChannelRequester) {
|
||||||
longArrayChannelRequester->destroy();
|
longArrayChannelRequester->destroy();
|
||||||
}
|
}
|
||||||
if(longArrayChannelGetRequester!=NULL) {
|
if(longArrayChannelGetRequester) {
|
||||||
longArrayChannelGetRequester->destroy();
|
longArrayChannelGetRequester->destroy();
|
||||||
}
|
}
|
||||||
thread->exitWait();
|
thread->exitWait();
|
||||||
@@ -433,7 +433,7 @@ void LongArrayChannelGet::run()
|
|||||||
CreateRequest::create();
|
CreateRequest::create();
|
||||||
PVStructurePtr pvRequest =
|
PVStructurePtr pvRequest =
|
||||||
createRequest->createRequest(request);
|
createRequest->createRequest(request);
|
||||||
if(pvRequest==NULL) {
|
if(!pvRequest) {
|
||||||
cout << "request logic error " << createRequest->getMessage() << endl;
|
cout << "request logic error " << createRequest->getMessage() << endl;
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,6 @@
|
|||||||
# undef epicsExportSharedSymbols
|
# undef epicsExportSharedSymbols
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <shareLib.h>
|
|
||||||
|
|
||||||
#include <pv/event.h>
|
#include <pv/event.h>
|
||||||
#include <pv/lock.h>
|
#include <pv/lock.h>
|
||||||
#include <pv/standardPVField.h>
|
#include <pv/standardPVField.h>
|
||||||
|
|||||||
@@ -138,9 +138,9 @@ void LAMMonitorRequester::monitorConnect(Status const & status,
|
|||||||
}
|
}
|
||||||
bool structureOK(true);
|
bool structureOK(true);
|
||||||
FieldConstPtr field = structure->getField("timeStamp");
|
FieldConstPtr field = structure->getField("timeStamp");
|
||||||
if(field==NULL) structureOK = false;
|
if(!field) structureOK = false;
|
||||||
field = structure->getField("value");
|
field = structure->getField("value");
|
||||||
if(field==NULL) {
|
if(!field) {
|
||||||
structureOK = false;
|
structureOK = false;
|
||||||
} else {
|
} else {
|
||||||
if(field->getType()!=scalarArray) {
|
if(field->getType()!=scalarArray) {
|
||||||
@@ -179,9 +179,9 @@ void LAMMonitorRequester::run()
|
|||||||
{
|
{
|
||||||
Lock xx(mutex);
|
Lock xx(mutex);
|
||||||
monitorElement = longArrayMonitor->monitor->poll();
|
monitorElement = longArrayMonitor->monitor->poll();
|
||||||
if(monitorElement!=NULL) pvStructure = monitorElement->pvStructurePtr;
|
if(monitorElement) pvStructure = monitorElement->pvStructurePtr;
|
||||||
}
|
}
|
||||||
if(monitorElement==NULL) break;
|
if(!monitorElement) break;
|
||||||
if(waitTime>0.0) epicsThreadSleep(waitTime);
|
if(waitTime>0.0) epicsThreadSleep(waitTime);
|
||||||
pvTimeStamp.attach(pvStructure->getSubField("timeStamp"));
|
pvTimeStamp.attach(pvStructure->getSubField("timeStamp"));
|
||||||
pvTimeStamp.get(timeStamp);
|
pvTimeStamp.get(timeStamp);
|
||||||
@@ -268,7 +268,7 @@ bool LongArrayMonitor::init(
|
|||||||
monitorRequester->init();
|
monitorRequester->init();
|
||||||
ChannelProvider::shared_pointer channelProvider =
|
ChannelProvider::shared_pointer channelProvider =
|
||||||
getChannelProviderRegistry()->getProvider(providerName);
|
getChannelProviderRegistry()->getProvider(providerName);
|
||||||
if(channelProvider==NULL) {
|
if(!channelProvider) {
|
||||||
cout << "provider " << providerName << " not found" << endl;
|
cout << "provider " << providerName << " not found" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -282,7 +282,7 @@ bool LongArrayMonitor::init(
|
|||||||
request += "]field(value,timeStamp,alarm)";
|
request += "]field(value,timeStamp,alarm)";
|
||||||
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
||||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||||
if(pvRequest==NULL) {
|
if(!pvRequest) {
|
||||||
cout << "request logic error " << createRequest->getMessage() << endl;
|
cout << "request logic error " << createRequest->getMessage() << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
# undef epicsExportSharedSymbols
|
# undef epicsExportSharedSymbols
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <shareLib.h>
|
|
||||||
#include <pv/event.h>
|
#include <pv/event.h>
|
||||||
#include <pv/lock.h>
|
#include <pv/lock.h>
|
||||||
#include <pv/standardPVField.h>
|
#include <pv/standardPVField.h>
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ private:
|
|||||||
bool LongArrayChannelPut::init()
|
bool LongArrayChannelPut::init()
|
||||||
{
|
{
|
||||||
ChannelProvider::shared_pointer channelProvider = getChannelProviderRegistry()->getProvider(providerName);
|
ChannelProvider::shared_pointer channelProvider = getChannelProviderRegistry()->getProvider(providerName);
|
||||||
if(channelProvider==NULL) {
|
if(!channelProvider) {
|
||||||
cout << "provider " << providerName << " not found" << endl;
|
cout << "provider " << providerName << " not found" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ bool LongArrayChannelPut::init()
|
|||||||
if(!status.isOK()) return false;
|
if(!status.isOK()) return false;
|
||||||
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
||||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||||
if(pvRequest==NULL) {
|
if(!pvRequest) {
|
||||||
cout << "request logic error " << createRequest->getMessage() << endl;
|
cout << "request logic error " << createRequest->getMessage() << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -187,7 +187,7 @@ void LongArrayChannelPut::channelPutConnect(
|
|||||||
bitSet = BitSetPtr(new BitSet(pvStructure->getNumberFields()));
|
bitSet = BitSetPtr(new BitSet(pvStructure->getNumberFields()));
|
||||||
bool structureOK(true);
|
bool structureOK(true);
|
||||||
PVFieldPtr pvField = pvStructure->getSubField("value");
|
PVFieldPtr pvField = pvStructure->getSubField("value");
|
||||||
if(pvField==NULL) {
|
if(!pvField) {
|
||||||
structureOK = false;
|
structureOK = false;
|
||||||
} else {
|
} else {
|
||||||
FieldConstPtr field = pvField->getField();
|
FieldConstPtr field = pvField->getField();
|
||||||
@@ -267,7 +267,6 @@ void LongArrayChannelPut::run()
|
|||||||
if(iterBetweenCreateChannel!=0) {
|
if(iterBetweenCreateChannel!=0) {
|
||||||
if(numChannelCreate>=iterBetweenCreateChannel) {
|
if(numChannelCreate>=iterBetweenCreateChannel) {
|
||||||
channel->destroy();
|
channel->destroy();
|
||||||
epicsThreadSleep(1.0);
|
|
||||||
ChannelProvider::shared_pointer channelProvider =
|
ChannelProvider::shared_pointer channelProvider =
|
||||||
getChannelProviderRegistry()->getProvider(providerName);
|
getChannelProviderRegistry()->getProvider(providerName);
|
||||||
channel = channelProvider->createChannel(
|
channel = channelProvider->createChannel(
|
||||||
@@ -295,7 +294,7 @@ void LongArrayChannelPut::run()
|
|||||||
channelPut->destroy();
|
channelPut->destroy();
|
||||||
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
||||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||||
if(pvRequest==NULL) {
|
if(!pvRequest) {
|
||||||
cout << "request logic error " << createRequest->getMessage() << endl;
|
cout << "request logic error " << createRequest->getMessage() << endl;
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
# undef epicsExportSharedSymbols
|
# undef epicsExportSharedSymbols
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <shareLib.h>
|
|
||||||
#include <pv/event.h>
|
#include <pv/event.h>
|
||||||
#include <pv/lock.h>
|
#include <pv/lock.h>
|
||||||
#include <pv/standardPVField.h>
|
#include <pv/standardPVField.h>
|
||||||
|
|||||||
@@ -25,4 +25,3 @@ USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
|||||||
|
|
||||||
-include $(TOP)/../CONFIG_SITE.local
|
-include $(TOP)/../CONFIG_SITE.local
|
||||||
-include $(TOP)/configure/CONFIG_SITE.local
|
-include $(TOP)/configure/CONFIG_SITE.local
|
||||||
|
|
||||||
|
|||||||
25
documentation/RELEASE_NOTES.html
Normal file
25
documentation/RELEASE_NOTES.html
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<h1>Release 4.0 IN DEVELOPMENT</h1>
|
||||||
|
<p>The main changes since release 3.0.2 are:</p>
|
||||||
|
<ul>
|
||||||
|
<li>array semantics now enforce Copy On Write.</li>
|
||||||
|
<li>String no longer defined.</li>
|
||||||
|
<li>toString replaced by stream I/O </li>
|
||||||
|
<li>union is new type.</li>
|
||||||
|
<li>copy and monitor use new code in pvDataCPP</li>
|
||||||
|
</ul>
|
||||||
|
<h2>New Semantics for Arrays</h2>
|
||||||
|
<p>pvDatabaseCPP has been changed to use the new array implementation from pvDataCPP.</p>
|
||||||
|
<h2>String no longer defined</h2>
|
||||||
|
<p>String is replaced by std::string.</p>
|
||||||
|
<h2>toString replaced by stream I/O</h2>
|
||||||
|
<p>All uses of toString have been changed to use the steam I/O that pvDataCPP implements.</p>
|
||||||
|
<h2>union is a new basic type.</h2>
|
||||||
|
<p>exampleDatabase now has example records for union and union array.
|
||||||
|
There are records for regular union and for variant union.</p>
|
||||||
|
<h2>copy</h2>
|
||||||
|
<p>The implementation of copy and monitor for pvAccess has been changed
|
||||||
|
to use the new monitor and copy support from pvDataCPP.</p>
|
||||||
|
<h2>monitorPlugin</h2>
|
||||||
|
<p>exampleDatabase now has a example plugin that implements onChange.</p>
|
||||||
|
<h1>Release 0.9.2</h1>
|
||||||
|
<p>This was the starting point for RELEASE_NOTES</p>
|
||||||
50
documentation/RELEASE_NOTES.md
Normal file
50
documentation/RELEASE_NOTES.md
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
Release 4.0 IN DEVELOPMENT
|
||||||
|
===========
|
||||||
|
|
||||||
|
The main changes since release 3.0.2 are:
|
||||||
|
|
||||||
|
* array semantics now enforce Copy On Write.
|
||||||
|
* String no longer defined.
|
||||||
|
* toString replaced by stream I/O
|
||||||
|
* union is new type.
|
||||||
|
* copy and monitor use new code in pvDataCPP
|
||||||
|
|
||||||
|
New Semantics for Arrays
|
||||||
|
--------
|
||||||
|
|
||||||
|
pvDatabaseCPP has been changed to use the new array implementation from pvDataCPP.
|
||||||
|
|
||||||
|
String no longer defined
|
||||||
|
---------
|
||||||
|
|
||||||
|
String is replaced by std::string.
|
||||||
|
|
||||||
|
|
||||||
|
toString replaced by stream I/O
|
||||||
|
---------
|
||||||
|
|
||||||
|
All uses of toString have been changed to use the steam I/O that pvDataCPP implements.
|
||||||
|
|
||||||
|
|
||||||
|
union is a new basic type.
|
||||||
|
------------
|
||||||
|
|
||||||
|
exampleDatabase now has example records for union and union array.
|
||||||
|
There are records for regular union and for variant union.
|
||||||
|
|
||||||
|
|
||||||
|
copy
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
The implementation of copy and monitor for pvAccess has been changed
|
||||||
|
to use the new monitor and copy support from pvDataCPP.
|
||||||
|
|
||||||
|
monitorPlugin
|
||||||
|
-------------
|
||||||
|
|
||||||
|
exampleDatabase now has a example plugin that implements onChange.
|
||||||
|
|
||||||
|
Release 0.9.2
|
||||||
|
==========
|
||||||
|
This was the starting point for RELEASE_NOTES
|
||||||
13
documentation/TODO.html
Normal file
13
documentation/TODO.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<h1>TODO</h1>
|
||||||
|
<h2>recordList</h2>
|
||||||
|
<p>This is putGet support that provides a list of all the records in an IOC.
|
||||||
|
Since pvAccess implements pvlist this is no longer needed.
|
||||||
|
Remove it from pvDatabaseCPP and pvIOCCPP.
|
||||||
|
Also remove channelList from swtshell.</p>
|
||||||
|
<h2>monitorPlugin</h2>
|
||||||
|
<p>A debate is on-going about what semantics should be.</p>
|
||||||
|
<h2>Must test record delete.</h2>
|
||||||
|
<p>Must test removing a record from the PVDatabase while a pvAccess client
|
||||||
|
is attached. Also why do both unlisten and detach exists?</p>
|
||||||
|
<h2>create more regression tests</h2>
|
||||||
|
<p>Currently only some simple tests exist. Most of the testing has been via the examples</p>
|
||||||
28
documentation/TODO.md
Normal file
28
documentation/TODO.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
TODO
|
||||||
|
===========
|
||||||
|
|
||||||
|
|
||||||
|
recordList
|
||||||
|
----------
|
||||||
|
|
||||||
|
This is putGet support that provides a list of all the records in an IOC.
|
||||||
|
Since pvAccess implements pvlist this is no longer needed.
|
||||||
|
Remove it from pvDatabaseCPP and pvIOCCPP.
|
||||||
|
Also remove channelList from swtshell.
|
||||||
|
|
||||||
|
monitorPlugin
|
||||||
|
-------------
|
||||||
|
|
||||||
|
A debate is on-going about what semantics should be.
|
||||||
|
|
||||||
|
Must test record delete.
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Must test removing a record from the PVDatabase while a pvAccess client
|
||||||
|
is attached. Also why do both unlisten and detach exists?
|
||||||
|
|
||||||
|
|
||||||
|
create more regression tests
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Currently only some simple tests exist. Most of the testing has been via the examples
|
||||||
File diff suppressed because it is too large
Load Diff
1940
documentation/pvDatabaseCPP_20140710.html
Normal file
1940
documentation/pvDatabaseCPP_20140710.html
Normal file
File diff suppressed because it is too large
Load Diff
2111
documentation/pvDatabaseCPP_20140811.html
Normal file
2111
documentation/pvDatabaseCPP_20140811.html
Normal file
File diff suppressed because it is too large
Load Diff
@@ -23,6 +23,5 @@ CHECK_RELEASE = WARN
|
|||||||
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
||||||
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
||||||
|
|
||||||
-include $(TOP)/../configure/CONFIG_SITE.local
|
|
||||||
-include $(TOP)/../../CONFIG_SITE.local
|
-include $(TOP)/../../CONFIG_SITE.local
|
||||||
-include $(TOP)/../CONFIG.local
|
-include $(TOP)/../configure/CONFIG_SITE.local
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ DB += dbString.db
|
|||||||
DB += dbStringArray.db
|
DB += dbStringArray.db
|
||||||
DB += dbEnum.db
|
DB += dbEnum.db
|
||||||
DB += dbCounter.db
|
DB += dbCounter.db
|
||||||
|
DB += dbDouble.db
|
||||||
|
|
||||||
#----------------------------------------------------
|
#----------------------------------------------------
|
||||||
# If <anyname>.db template is not named <anyname>*.template add
|
# If <anyname>.db template is not named <anyname>*.template add
|
||||||
|
|||||||
3
exampleDatabase/ioc/Db/dbDouble.db
Normal file
3
exampleDatabase/ioc/Db/dbDouble.db
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
record(ao, "$(name)")
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -4,4 +4,3 @@ include "registerChannelProviderLocal.dbd"
|
|||||||
include "dbPv.dbd"
|
include "dbPv.dbd"
|
||||||
include "powerSupplyRegister.dbd"
|
include "powerSupplyRegister.dbd"
|
||||||
registrar("exampleDatabaseRegister")
|
registrar("exampleDatabaseRegister")
|
||||||
registrar("exampleMonitorPluginRegister")
|
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ include $(TOP)/configure/CONFIG
|
|||||||
DIRS += $(wildcard *ioc*)
|
DIRS += $(wildcard *ioc*)
|
||||||
DIRS += $(wildcard as*)
|
DIRS += $(wildcard as*)
|
||||||
DIRS += $(wildcard example*)
|
DIRS += $(wildcard example*)
|
||||||
include $(EPICS_BASE)/configure/RULES_DIRS
|
include $(CONFIG)/RULES_DIRS
|
||||||
|
|
||||||
|
|||||||
@@ -7,15 +7,17 @@ dbLoadDatabase("dbd/exampleDatabase.dbd")
|
|||||||
exampleDatabase_registerRecordDeviceDriver(pdbbase)
|
exampleDatabase_registerRecordDeviceDriver(pdbbase)
|
||||||
|
|
||||||
## Load record instances
|
## Load record instances
|
||||||
dbLoadRecords("db/dbScalar.db","name=double00,type=ao")
|
dbLoadRecords("db/dbDouble.db","name=double00")
|
||||||
dbLoadRecords("db/dbScalar.db","name=double01,type=ao")
|
dbLoadRecords("db/dbDouble.db","name=double01")
|
||||||
dbLoadRecords("db/dbScalar.db","name=double02,type=ao")
|
dbLoadRecords("db/dbDouble.db","name=double02")
|
||||||
dbLoadRecords("db/dbScalar.db","name=double03,type=ao")
|
dbLoadRecords("db/dbDouble.db","name=double03")
|
||||||
dbLoadRecords("db/dbScalar.db","name=double04,type=ao")
|
dbLoadRecords("db/dbDouble.db","name=double04")
|
||||||
dbLoadRecords("db/dbScalar.db","name=double05,type=ao")
|
dbLoadRecords("db/dbDouble.db","name=double05")
|
||||||
dbLoadRecords("db/dbStringArray.db","name=stringArray01")
|
dbLoadRecords("db/dbStringArray.db","name=stringArray01")
|
||||||
dbLoadRecords("db/dbEnum.db","name=enum01")
|
dbLoadRecords("db/dbEnum.db","name=enum01")
|
||||||
dbLoadRecords("db/dbCounter.db","name=counter01");
|
dbLoadRecords("db/dbCounter.db","name=counter01");
|
||||||
|
dbLoadRecords("db/dbArray.db","name=doubleArray,type=DOUBLE");
|
||||||
|
|
||||||
|
|
||||||
cd ${TOP}/iocBoot/${IOC}
|
cd ${TOP}/iocBoot/${IOC}
|
||||||
iocInit()
|
iocInit()
|
||||||
|
|||||||
@@ -7,13 +7,11 @@ include $(TOP)/configure/CONFIG
|
|||||||
DBD += exampleDatabase.dbd
|
DBD += exampleDatabase.dbd
|
||||||
|
|
||||||
INC += exampleDatabase.h
|
INC += exampleDatabase.h
|
||||||
INC += exampleMonitorPlugin.h
|
|
||||||
|
|
||||||
LIBRARY += exampleDatabase
|
LIBRARY += exampleDatabase
|
||||||
exampleDatabase_SRCS += exampleDatabase.cpp
|
exampleDatabase_SRCS += exampleDatabase.cpp
|
||||||
exampleDatabase_SRCS += exampleMonitorPlugin.cpp
|
|
||||||
exampleDatabase_SRCS += exampleDatabaseRegister.cpp
|
exampleDatabase_SRCS += exampleDatabaseRegister.cpp
|
||||||
exampleDatabase_SRCS += exampleMonitorPluginRegister.cpp
|
exampleDatabase_LIBS += powerSupply
|
||||||
exampleDatabase_LIBS += pvDatabase
|
exampleDatabase_LIBS += pvDatabase
|
||||||
exampleDatabase_LIBS += pvAccess
|
exampleDatabase_LIBS += pvAccess
|
||||||
exampleDatabase_LIBS += pvData
|
exampleDatabase_LIBS += pvData
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
#include <pv/traceRecord.h>
|
#include <pv/traceRecord.h>
|
||||||
|
|
||||||
#include <pv/powerSupply.h>
|
#include <pv/powerSupply.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
#include <pv/exampleDatabase.h>
|
#include <pv/exampleDatabase.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@@ -147,17 +149,20 @@ void ExampleDatabase::create()
|
|||||||
createVariantUnionArrayRecord(master,"exampleVariantUnionArray");
|
createVariantUnionArrayRecord(master,"exampleVariantUnionArray");
|
||||||
recordName = "examplePowerSupply";
|
recordName = "examplePowerSupply";
|
||||||
PVStructurePtr pvStructure = createPowerSupply();
|
PVStructurePtr pvStructure = createPowerSupply();
|
||||||
PowerSupplyPtr psr =
|
PowerSupplyPtr psr = PowerSupply::create(recordName,pvStructure);
|
||||||
PowerSupply::create(recordName,pvStructure);
|
if(!psr) {
|
||||||
if(psr.get()==NULL) {
|
cout << "PowerSupply::create failed" << endl;
|
||||||
cout << "PowerSupply::create failed" << endl;
|
} else {
|
||||||
return;
|
result = master->addRecord(psr);
|
||||||
|
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
}
|
}
|
||||||
result = master->addRecord(psr);
|
|
||||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
|
||||||
recordName = "laptoprecordListPGRPC";
|
recordName = "laptoprecordListPGRPC";
|
||||||
pvRecord = RecordListRecord::create(recordName);
|
pvRecord = RecordListRecord::create(recordName);
|
||||||
result = master->addRecord(pvRecord);
|
if(!pvRecord) {
|
||||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
cout << "RecordListRecord::create failed" << endl;
|
||||||
|
} else {
|
||||||
|
result = master->addRecord(pvRecord);
|
||||||
|
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,15 +16,15 @@
|
|||||||
# undef epicsExportSharedSymbols
|
# undef epicsExportSharedSymbols
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <shareLib.h>
|
|
||||||
#include <pv/pvDatabase.h>
|
#include <pv/pvDatabase.h>
|
||||||
|
|
||||||
#ifdef exampledatabaseEpicsExportSharedSymbols
|
#ifdef exampledatabaseEpicsExportSharedSymbols
|
||||||
# define epicsExportSharedSymbols
|
# define epicsExportSharedSymbols
|
||||||
# undef exampledatabaseEpicsExportSharedSymbols
|
# undef exampledatabaseEpicsExportSharedSymbols
|
||||||
# include <shareLib.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <shareLib.h>
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
class epicsShareClass ExampleDatabase{
|
class epicsShareClass ExampleDatabase{
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
registrar("exampleDatabaseRegister")
|
registrar("exampleDatabaseRegister")
|
||||||
registrar("exampleMonitorPluginRegister")
|
|
||||||
|
|||||||
@@ -10,48 +10,27 @@
|
|||||||
|
|
||||||
/* Author: Marty Kraimer */
|
/* Author: Marty Kraimer */
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <string>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <pv/channelProviderLocal.h>
|
#include <pv/channelProviderLocal.h>
|
||||||
#include <pv/serverContext.h>
|
|
||||||
|
|
||||||
#include <pv/exampleDatabase.h>
|
#include <pv/exampleDatabase.h>
|
||||||
#include <pv/exampleMonitorPlugin.h>
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using std::tr1::static_pointer_cast;
|
|
||||||
using namespace epics::pvData;
|
|
||||||
using namespace epics::pvAccess;
|
|
||||||
using namespace epics::pvDatabase;
|
using namespace epics::pvDatabase;
|
||||||
|
|
||||||
|
|
||||||
int main(int argc,char *argv[])
|
int main(int argc,char *argv[])
|
||||||
{
|
{
|
||||||
PVDatabasePtr master = PVDatabase::getMaster();
|
|
||||||
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
|
|
||||||
ExampleDatabase::create();
|
ExampleDatabase::create();
|
||||||
ExampleMonitorPlugin::create();
|
|
||||||
ServerContext::shared_pointer ctx =
|
|
||||||
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
|
|
||||||
cout << "exampleDatabase\n";
|
|
||||||
PVStringArrayPtr pvNames = master->getRecordNames();
|
|
||||||
cout << "recordNames" << endl << *pvNames << endl;
|
|
||||||
string str;
|
|
||||||
while(true) {
|
|
||||||
cout << "Type exit to stop: \n";
|
|
||||||
getline(cin,str);
|
|
||||||
if(str.compare("exit")==0) break;
|
|
||||||
|
|
||||||
}
|
ContextLocal::shared_pointer contextLocal = ContextLocal::create();
|
||||||
ctx->destroy();
|
contextLocal->start();
|
||||||
epicsThreadSleep(1.0);
|
|
||||||
channelProvider->destroy();
|
cout << "pvAccess server exampleDatabase running..." << endl;
|
||||||
|
epics::pvData::PVStringArrayPtr pvNames = PVDatabase::getMaster()->getRecordNames();
|
||||||
|
cout << "Hosted records: " << endl << *pvNames << endl;
|
||||||
|
|
||||||
|
contextLocal->waitForExit();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
#include <pv/pvDatabase.h>
|
#include <pv/pvDatabase.h>
|
||||||
|
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
|
||||||
#include <pv/exampleDatabase.h>
|
#include <pv/exampleDatabase.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
/* exampleMonitorPlugin.h */
|
|
||||||
/**
|
|
||||||
* 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 2014.04.16
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <pv/convert.h>
|
|
||||||
#include <pv/monitorPlugin.h>
|
|
||||||
#include <pv/exampleMonitorPlugin.h>
|
|
||||||
|
|
||||||
using namespace epics::pvData;
|
|
||||||
using std::cout;
|
|
||||||
using std::endl;
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
|
||||||
|
|
||||||
static string pluginName("onChange");
|
|
||||||
static ConvertPtr convert(getConvert());
|
|
||||||
|
|
||||||
class OnChangePlugin;
|
|
||||||
typedef std::tr1::shared_ptr<OnChangePlugin> OnChangePluginPtr;
|
|
||||||
class OnChangePluginCreator;
|
|
||||||
typedef std::tr1::shared_ptr<OnChangePluginCreator> OnChangePluginCreatorPtr;
|
|
||||||
|
|
||||||
class OnChangePlugin : public MonitorPlugin
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~OnChangePlugin(){}
|
|
||||||
OnChangePlugin() {}
|
|
||||||
bool init(
|
|
||||||
FieldConstPtr const &field,
|
|
||||||
StructureConstPtr const &top,
|
|
||||||
PVStructurePtr const &pvFieldOptions)
|
|
||||||
{
|
|
||||||
pvField = getPVDataCreate()->createPVField(field);
|
|
||||||
raiseMonitor = true;
|
|
||||||
if(pvFieldOptions!=NULL) {
|
|
||||||
PVStringPtr pvString =
|
|
||||||
pvFieldOptions->getSubField<PVString>("raiseMonitor");
|
|
||||||
if(pvString!=NULL) {
|
|
||||||
string value = pvString->get();
|
|
||||||
if(value.compare("false")==0) raiseMonitor = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
virtual string &getName(){return pluginName;}
|
|
||||||
virtual bool causeMonitor(
|
|
||||||
PVFieldPtr const &pvNew,
|
|
||||||
PVStructurePtr const &pvTop,
|
|
||||||
MonitorElementPtr const &monitorElement)
|
|
||||||
{
|
|
||||||
bool isSame = convert->equals(pvNew,pvField);
|
|
||||||
if(isSame) return false;
|
|
||||||
convert->copy(pvNew,pvField);
|
|
||||||
return raiseMonitor;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
PVFieldPtr pvField;
|
|
||||||
bool raiseMonitor;
|
|
||||||
};
|
|
||||||
|
|
||||||
class OnChangePluginCreator : public MonitorPluginCreator
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual string &getName(){return pluginName;}
|
|
||||||
virtual MonitorPluginPtr create(
|
|
||||||
FieldConstPtr const &field,
|
|
||||||
StructureConstPtr const &top,
|
|
||||||
PVStructurePtr const &pvFieldOptions)
|
|
||||||
{
|
|
||||||
OnChangePluginPtr plugin(new OnChangePlugin());
|
|
||||||
bool result = plugin->init(field,top,pvFieldOptions);
|
|
||||||
if(!result) return MonitorPluginPtr();
|
|
||||||
return plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
void ExampleMonitorPlugin::create()
|
|
||||||
{
|
|
||||||
static OnChangePluginCreatorPtr plugin;
|
|
||||||
static Mutex mutex;
|
|
||||||
Lock xx(mutex);
|
|
||||||
if(plugin==NULL) {
|
|
||||||
plugin = OnChangePluginCreatorPtr(new OnChangePluginCreator());
|
|
||||||
MonitorPluginManager::get()->addPlugin(pluginName,plugin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
/* exampleMonitorPlugin.h */
|
|
||||||
/**
|
|
||||||
* 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 2014.04.16
|
|
||||||
*/
|
|
||||||
#ifndef EXAMPLEMONITORPLUGIN_H
|
|
||||||
#define EXAMPLEMONITORPLUGIN_H
|
|
||||||
|
|
||||||
#include <shareLib.h>
|
|
||||||
|
|
||||||
#include <pv/pvDatabase.h>
|
|
||||||
#include <pv/monitorPlugin.h>
|
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
|
||||||
|
|
||||||
class epicsShareClass ExampleMonitorPlugin{
|
|
||||||
public:
|
|
||||||
static void create();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
||||||
#endif /* EXAMPLEMONITORPLUGIN_H */
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
/*exampleMonitorPlugin.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.07.24
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Author: Marty Kraimer */
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <string>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include <cantProceed.h>
|
|
||||||
#include <epicsStdio.h>
|
|
||||||
#include <epicsMutex.h>
|
|
||||||
#include <epicsEvent.h>
|
|
||||||
#include <epicsThread.h>
|
|
||||||
#include <iocsh.h>
|
|
||||||
|
|
||||||
#include <epicsExport.h>
|
|
||||||
|
|
||||||
#include <pv/pvIntrospect.h>
|
|
||||||
#include <pv/pvData.h>
|
|
||||||
#include <pv/pvAccess.h>
|
|
||||||
#include <pv/pvDatabase.h>
|
|
||||||
#include <pv/exampleMonitorPlugin.h>
|
|
||||||
|
|
||||||
using namespace epics::pvData;
|
|
||||||
using namespace epics::pvAccess;
|
|
||||||
using namespace epics::pvDatabase;
|
|
||||||
|
|
||||||
|
|
||||||
static const iocshFuncDef exampleMonitorPluginFuncDef = {
|
|
||||||
"exampleMonitorPlugin", 0,0 };
|
|
||||||
|
|
||||||
|
|
||||||
static void exampleMonitorPluginCallFunc(const iocshArgBuf *args)
|
|
||||||
{
|
|
||||||
ExampleMonitorPlugin::create();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void exampleMonitorPluginRegister(void)
|
|
||||||
{
|
|
||||||
std::cout << "exampleMonitorPluginRegister\n";
|
|
||||||
static int firstTime = 1;
|
|
||||||
if (firstTime) {
|
|
||||||
firstTime = 0;
|
|
||||||
iocshRegister(&exampleMonitorPluginFuncDef, exampleMonitorPluginCallFunc);
|
|
||||||
}
|
|
||||||
std::cout << "exampleMonitorPluginRegister returning\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
epicsExportRegistrar(exampleMonitorPluginRegister);
|
|
||||||
}
|
|
||||||
@@ -35,5 +35,5 @@
|
|||||||
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
||||||
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
||||||
|
|
||||||
-include $(TOP)/configure/CONFIG_SITE.local
|
-include $(TOP)/../../CONFIG_SITE.local
|
||||||
-include $(TOP)/../CONFIG.local
|
-include $(TOP)/../configure/CONFIG_SITE.local
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ include $(TOP)/configure/CONFIG
|
|||||||
DIRS += $(wildcard *ioc*)
|
DIRS += $(wildcard *ioc*)
|
||||||
DIRS += $(wildcard as*)
|
DIRS += $(wildcard as*)
|
||||||
DIRS += $(wildcard example*)
|
DIRS += $(wildcard example*)
|
||||||
include $(EPICS_BASE)/configure/RULES_DIRS
|
include $(CONFIG)/RULES_DIRS
|
||||||
|
|
||||||
|
|||||||
@@ -13,4 +13,4 @@ cd ${TOP}/iocBoot/${IOC}
|
|||||||
iocInit()
|
iocInit()
|
||||||
startPVAClient
|
startPVAClient
|
||||||
startPVAServer
|
startPVAServer
|
||||||
exampleLinkCreateRecord exampleLinkRemote pvAccess doubleArray
|
exampleLinkCreateRecord exampleLink pvAccess doubleArray
|
||||||
|
|||||||
@@ -9,9 +9,10 @@
|
|||||||
* @date 2013.08.02
|
* @date 2013.08.02
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <pv/exampleLink.h>
|
|
||||||
#include <pv/standardPVField.h>
|
#include <pv/standardPVField.h>
|
||||||
#include <pv/convert.h>
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
#include <pv/exampleLink.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
@@ -44,8 +45,7 @@ ExampleLink::ExampleLink(
|
|||||||
PVStructurePtr const & pvStructure)
|
PVStructurePtr const & pvStructure)
|
||||||
: PVRecord(recordName,pvStructure),
|
: PVRecord(recordName,pvStructure),
|
||||||
providerName(providerName),
|
providerName(providerName),
|
||||||
channelName(channelName),
|
channelName(channelName)
|
||||||
convert(getConvert())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,14 +61,13 @@ bool ExampleLink::init()
|
|||||||
PVStructurePtr pvStructure = getPVRecordStructure()->getPVStructure();
|
PVStructurePtr pvStructure = getPVRecordStructure()->getPVStructure();
|
||||||
pvTimeStamp.attach(pvStructure->getSubField("timeStamp"));
|
pvTimeStamp.attach(pvStructure->getSubField("timeStamp"));
|
||||||
pvAlarm.attach(pvStructure->getSubField("alarm"));
|
pvAlarm.attach(pvStructure->getSubField("alarm"));
|
||||||
pvValue = static_pointer_cast<PVDoubleArray>(
|
pvValue = pvStructure->getSubField<PVDoubleArray>("value");
|
||||||
pvStructure->getScalarArrayField("value",pvDouble));
|
if(!pvValue) {
|
||||||
if(pvValue==NULL) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ChannelProvider::shared_pointer provider =
|
ChannelProvider::shared_pointer provider =
|
||||||
getChannelProviderRegistry()->getProvider(providerName);
|
getChannelProviderRegistry()->getProvider(providerName);
|
||||||
if(provider==NULL) {
|
if(!provider) {
|
||||||
cout << getRecordName() << " provider "
|
cout << getRecordName() << " provider "
|
||||||
<< providerName << " does not exist" << endl;
|
<< providerName << " does not exist" << endl;
|
||||||
return false;
|
return false;
|
||||||
@@ -93,9 +92,8 @@ bool ExampleLink::init()
|
|||||||
<< status.getMessage() << endl;
|
<< status.getMessage() << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
getPVValue = static_pointer_cast<PVDoubleArray>(
|
getPVValue = getPVStructure->getSubField<PVDoubleArray>("value");
|
||||||
getPVStructure->getScalarArrayField("value",pvDouble));
|
if(!getPVValue) {
|
||||||
if(getPVValue==NULL) {
|
|
||||||
cout << getRecordName() << " get value not PVDoubleArray" << endl;
|
cout << getRecordName() << " get value not PVDoubleArray" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -119,7 +117,7 @@ void ExampleLink::process()
|
|||||||
}
|
}
|
||||||
alarm.setSeverity(severity);
|
alarm.setSeverity(severity);
|
||||||
} else {
|
} else {
|
||||||
convert->copy(getPVValue,pvValue);
|
pvValue->copyUnchecked(*getPVValue);
|
||||||
}
|
}
|
||||||
alarm.setMessage(status.getMessage());
|
alarm.setMessage(status.getMessage());
|
||||||
pvAlarm.set(alarm);
|
pvAlarm.set(alarm);
|
||||||
@@ -147,6 +145,7 @@ void ExampleLink::channelGetConnect(
|
|||||||
{
|
{
|
||||||
this->status = status;
|
this->status = status;
|
||||||
this->channelGet = channelGet;
|
this->channelGet = channelGet;
|
||||||
|
getPVStructure = getPVDataCreate()->createPVStructure(structure);
|
||||||
event.signal();
|
event.signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +156,7 @@ void ExampleLink::getDone(
|
|||||||
BitSetPtr const & bitSet)
|
BitSetPtr const & bitSet)
|
||||||
{
|
{
|
||||||
this->status = status;
|
this->status = status;
|
||||||
getPVStructure = pvStructure;
|
getPVStructure->copyUnchecked(*pvStructure);
|
||||||
this->bitSet = bitSet;
|
this->bitSet = bitSet;
|
||||||
event.signal();
|
event.signal();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,10 @@
|
|||||||
#ifndef EXAMPLEPVADOUBLEARRAYGET_H
|
#ifndef EXAMPLEPVADOUBLEARRAYGET_H
|
||||||
#define EXAMPLEPVADOUBLEARRAYGET_H
|
#define EXAMPLEPVADOUBLEARRAYGET_H
|
||||||
|
|
||||||
#include <shareLib.h>
|
#ifdef epicsExportSharedSymbols
|
||||||
|
# define exampleLinkEpicsExportSharedSymbols
|
||||||
|
# undef epicsExportSharedSymbols
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <pv/timeStamp.h>
|
#include <pv/timeStamp.h>
|
||||||
#include <pv/pvTimeStamp.h>
|
#include <pv/pvTimeStamp.h>
|
||||||
@@ -22,6 +25,13 @@
|
|||||||
#include <pv/pvAccess.h>
|
#include <pv/pvAccess.h>
|
||||||
#include <pv/serverContext.h>
|
#include <pv/serverContext.h>
|
||||||
|
|
||||||
|
#ifdef exampleLinkEpicsExportSharedSymbols
|
||||||
|
# define epicsExportSharedSymbols
|
||||||
|
# undef exampleLinkEpicsExportSharedSymbols
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <shareLib.h>
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
|
|
||||||
@@ -73,7 +83,6 @@ private:
|
|||||||
epics::pvData::PVStructurePtr const & pvStructure);
|
epics::pvData::PVStructurePtr const & pvStructure);
|
||||||
std::string providerName;
|
std::string providerName;
|
||||||
std::string channelName;
|
std::string channelName;
|
||||||
epics::pvData::ConvertPtr convert;
|
|
||||||
epics::pvData::PVDoubleArrayPtr pvValue;
|
epics::pvData::PVDoubleArrayPtr pvValue;
|
||||||
epics::pvData::PVTimeStamp pvTimeStamp;
|
epics::pvData::PVTimeStamp pvTimeStamp;
|
||||||
epics::pvData::TimeStamp timeStamp;
|
epics::pvData::TimeStamp timeStamp;
|
||||||
|
|||||||
@@ -27,14 +27,14 @@
|
|||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
#include <iocsh.h>
|
#include <iocsh.h>
|
||||||
|
|
||||||
#include <epicsExport.h>
|
|
||||||
|
|
||||||
#include <pv/pvIntrospect.h>
|
#include <pv/pvIntrospect.h>
|
||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
#include <pv/standardField.h>
|
#include <pv/standardField.h>
|
||||||
#include <pv/standardPVField.h>
|
#include <pv/standardPVField.h>
|
||||||
#include <pv/pvAccess.h>
|
#include <pv/pvAccess.h>
|
||||||
#include <pv/pvDatabase.h>
|
#include <pv/pvDatabase.h>
|
||||||
|
|
||||||
|
#include <epicsExport.h>
|
||||||
#include <pv/exampleLink.h>
|
#include <pv/exampleLink.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
@@ -70,8 +70,8 @@ static void exampleLinkCallFunc(const iocshArgBuf *args)
|
|||||||
char *providerName = args[1].sval;
|
char *providerName = args[1].sval;
|
||||||
char *channelName = args[2].sval;
|
char *channelName = args[2].sval;
|
||||||
ExampleLinkPtr record = ExampleLink::create(recordName,providerName,channelName);
|
ExampleLinkPtr record = ExampleLink::create(recordName,providerName,channelName);
|
||||||
if(record!=NULL)
|
if(record)
|
||||||
result = master->addRecord(record);
|
result = master->addRecord(record);
|
||||||
if(!result) cout << "recordname" << " not added" << endl;
|
if(!result) cout << "recordname" << " not added" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,4 +86,4 @@ static void exampleLinkRegister(void)
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
epicsExportRegistrar(exampleLinkRegister);
|
epicsExportRegistrar(exampleLinkRegister);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,5 +35,5 @@
|
|||||||
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
||||||
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
||||||
|
|
||||||
-include $(TOP)/configure/CONFIG_SITE.local
|
-include $(TOP)/../../CONFIG_SITE.local
|
||||||
-include $(TOP)/../CONFIG.local
|
-include $(TOP)/../configure/CONFIG_SITE.local
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ include $(TOP)/configure/CONFIG
|
|||||||
DIRS += $(wildcard *ioc*)
|
DIRS += $(wildcard *ioc*)
|
||||||
DIRS += $(wildcard as*)
|
DIRS += $(wildcard as*)
|
||||||
DIRS += $(wildcard power*)
|
DIRS += $(wildcard power*)
|
||||||
include $(EPICS_BASE)/configure/RULES_DIRS
|
include $(CONFIG)/RULES_DIRS
|
||||||
|
|
||||||
|
|||||||
@@ -10,23 +10,15 @@
|
|||||||
|
|
||||||
/* Author: Marty Kraimer */
|
/* Author: Marty Kraimer */
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdio>
|
|
||||||
#include <memory>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <pv/standardField.h>
|
#include <pv/recordList.h>
|
||||||
#include <pv/standardPVField.h>
|
|
||||||
#include <pv/powerSupply.h>
|
#include <pv/powerSupply.h>
|
||||||
#include <pv/traceRecord.h>
|
#include <pv/traceRecord.h>
|
||||||
#include <pv/channelProviderLocal.h>
|
#include <pv/channelProviderLocal.h>
|
||||||
#include <pv/serverContext.h>
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using std::tr1::static_pointer_cast;
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace epics::pvDatabase;
|
using namespace epics::pvDatabase;
|
||||||
@@ -35,34 +27,30 @@ using namespace epics::pvDatabase;
|
|||||||
int main(int argc,char *argv[])
|
int main(int argc,char *argv[])
|
||||||
{
|
{
|
||||||
PVDatabasePtr master = PVDatabase::getMaster();
|
PVDatabasePtr master = PVDatabase::getMaster();
|
||||||
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
|
|
||||||
PVRecordPtr pvRecord;
|
PVRecordPtr pvRecord;
|
||||||
bool result(false);
|
bool result = false;
|
||||||
string recordName;
|
string recordName;
|
||||||
|
|
||||||
recordName = "powerSupply";
|
recordName = "powerSupply";
|
||||||
PVStructurePtr pv = createPowerSupply();
|
PVStructurePtr pv = createPowerSupply();
|
||||||
pvRecord = PowerSupply::create(recordName,pv);
|
pvRecord = PowerSupply::create(recordName,pv);
|
||||||
result = master->addRecord(pvRecord);
|
result = master->addRecord(pvRecord);
|
||||||
cout << "result of addRecord " << recordName << " " << result << endl;
|
cout << "result of addRecord " << recordName << " " << result << endl;
|
||||||
|
|
||||||
recordName = "traceRecordPGRPC";
|
recordName = "traceRecordPGRPC";
|
||||||
pvRecord = TraceRecord::create(recordName);
|
pvRecord = TraceRecord::create(recordName);
|
||||||
result = master->addRecord(pvRecord);
|
result = master->addRecord(pvRecord);
|
||||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
if (!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
pvRecord.reset();
|
|
||||||
ServerContext::shared_pointer pvaServer =
|
recordName = "laptoprecordListPGRPC";
|
||||||
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
|
pvRecord = RecordListRecord::create(recordName);
|
||||||
cout << "powerSupply\n";
|
result = master->addRecord(pvRecord);
|
||||||
string str;
|
if (!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
while(true) {
|
|
||||||
cout << "Type exit to stop: \n";
|
ContextLocal::shared_pointer contextLocal = ContextLocal::create();
|
||||||
getline(cin,str);
|
contextLocal->start(true);
|
||||||
if(str.compare("exit")==0) break;
|
|
||||||
|
|
||||||
}
|
|
||||||
pvaServer->shutdown();
|
|
||||||
epicsThreadSleep(1.0);
|
|
||||||
pvaServer->destroy();
|
|
||||||
channelProvider->destroy();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,5 +35,5 @@
|
|||||||
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
||||||
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
||||||
|
|
||||||
-include $(TOP)/configure/CONFIG_SITE.local
|
-include $(TOP)/../../CONFIG_SITE.local
|
||||||
-include $(TOP)/../CONFIG.local
|
-include $(TOP)/../configure/CONFIG_SITE.local
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
include "base.dbd"
|
include "base.dbd"
|
||||||
|
include "PVAClientRegister.dbd"
|
||||||
include "PVAServerRegister.dbd"
|
include "PVAServerRegister.dbd"
|
||||||
include "registerChannelProviderLocal.dbd"
|
include "registerChannelProviderLocal.dbd"
|
||||||
include "dbPv.dbd"
|
include "dbPv.dbd"
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ include $(TOP)/configure/CONFIG
|
|||||||
DIRS += $(wildcard *ioc*)
|
DIRS += $(wildcard *ioc*)
|
||||||
DIRS += $(wildcard as*)
|
DIRS += $(wildcard as*)
|
||||||
DIRS += $(wildcard example*)
|
DIRS += $(wildcard example*)
|
||||||
include $(EPICS_BASE)/configure/RULES_DIRS
|
include $(CONFIG)/RULES_DIRS
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,9 @@
|
|||||||
* @date 2013.04.02
|
* @date 2013.04.02
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <pv/standardPVField.h>
|
#include <pv/standardField.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
#include <pv/exampleServer.h>
|
#include <pv/exampleServer.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
@@ -23,19 +25,20 @@ namespace epics { namespace exampleServer {
|
|||||||
ExampleServerPtr ExampleServer::create(
|
ExampleServerPtr ExampleServer::create(
|
||||||
string const & recordName)
|
string const & recordName)
|
||||||
{
|
{
|
||||||
StandardPVFieldPtr standardPVField = getStandardPVField();
|
StandardFieldPtr standardField = getStandardField();
|
||||||
|
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
PVStructurePtr pvArgument = standardPVField->scalar(pvString,"");
|
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
||||||
PVStructurePtr pvResult = standardPVField->scalar(pvString,"timeStamp");
|
addNestedStructure("argument")->
|
||||||
StringArray names;
|
add("value",pvString)->
|
||||||
names.reserve(2);
|
endNested()->
|
||||||
PVFieldPtrArray fields;
|
addNestedStructure("result") ->
|
||||||
fields.reserve(2);
|
add("value",pvString) ->
|
||||||
names.push_back("argument");
|
add("timeStamp",standardField->timeStamp()) ->
|
||||||
fields.push_back(pvArgument);
|
endNested()->
|
||||||
names.push_back("result");
|
createStructure();
|
||||||
fields.push_back(pvResult);
|
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(names,fields);
|
|
||||||
ExampleServerPtr pvRecord(
|
ExampleServerPtr pvRecord(
|
||||||
new ExampleServer(recordName,pvStructure));
|
new ExampleServer(recordName,pvStructure));
|
||||||
if(!pvRecord->init()) pvRecord.reset();
|
if(!pvRecord->init()) pvRecord.reset();
|
||||||
@@ -63,9 +66,9 @@ bool ExampleServer::init()
|
|||||||
|
|
||||||
initPVRecord();
|
initPVRecord();
|
||||||
PVFieldPtr pvField;
|
PVFieldPtr pvField;
|
||||||
pvArgumentValue = getPVStructure()->getStringField("argument.value");
|
pvArgumentValue = getPVStructure()->getSubField<PVString>("argument.value");
|
||||||
if(pvArgumentValue.get()==NULL) return false;
|
if(pvArgumentValue.get()==NULL) return false;
|
||||||
pvResultValue = getPVStructure()->getStringField("result.value");
|
pvResultValue = getPVStructure()->getSubField<PVString>("result.value");
|
||||||
if(pvResultValue.get()==NULL) return false;
|
if(pvResultValue.get()==NULL) return false;
|
||||||
pvTimeStamp.attach(getPVStructure()->getSubField("result.timeStamp"));
|
pvTimeStamp.attach(getPVStructure()->getSubField("result.timeStamp"));
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -8,15 +8,26 @@
|
|||||||
* @author mrk
|
* @author mrk
|
||||||
* @date 2013.04.02
|
* @date 2013.04.02
|
||||||
*/
|
*/
|
||||||
#ifndef EXAMPLECOUNTER_H
|
#ifndef EXAMPLESERVER_H
|
||||||
#define EXAMPLECOUNTER_H
|
#define EXAMPLESERVER_H
|
||||||
|
|
||||||
#include <shareLib.h>
|
#ifdef epicsExportSharedSymbols
|
||||||
|
# define exampleServerEpicsExportSharedSymbols
|
||||||
|
# undef epicsExportSharedSymbols
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <pv/pvDatabase.h>
|
#include <pv/pvDatabase.h>
|
||||||
#include <pv/timeStamp.h>
|
#include <pv/timeStamp.h>
|
||||||
#include <pv/pvTimeStamp.h>
|
#include <pv/pvTimeStamp.h>
|
||||||
|
|
||||||
|
#ifdef exampleServerEpicsExportSharedSymbols
|
||||||
|
# define epicsExportSharedSymbols
|
||||||
|
# undef exampleServerEpicsExportSharedSymbols
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <shareLib.h>
|
||||||
|
|
||||||
|
|
||||||
namespace epics { namespace exampleServer {
|
namespace epics { namespace exampleServer {
|
||||||
|
|
||||||
|
|
||||||
@@ -47,4 +58,4 @@ private:
|
|||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
#endif /* EXAMPLECOUNTER_H */
|
#endif /* EXAMPLESERVER_H */
|
||||||
|
|||||||
@@ -10,23 +10,15 @@
|
|||||||
|
|
||||||
/* Author: Marty Kraimer */
|
/* Author: Marty Kraimer */
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstdio>
|
|
||||||
#include <memory>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <pv/standardField.h>
|
|
||||||
#include <pv/standardPVField.h>
|
|
||||||
#include <pv/exampleServer.h>
|
#include <pv/exampleServer.h>
|
||||||
#include <pv/traceRecord.h>
|
#include <pv/traceRecord.h>
|
||||||
|
#include <pv/recordList.h>
|
||||||
#include <pv/channelProviderLocal.h>
|
#include <pv/channelProviderLocal.h>
|
||||||
#include <pv/serverContext.h>
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using std::tr1::static_pointer_cast;
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
using namespace epics::pvDatabase;
|
using namespace epics::pvDatabase;
|
||||||
@@ -35,33 +27,35 @@ using namespace epics::exampleServer;
|
|||||||
int main(int argc,char *argv[])
|
int main(int argc,char *argv[])
|
||||||
{
|
{
|
||||||
PVDatabasePtr master = PVDatabase::getMaster();
|
PVDatabasePtr master = PVDatabase::getMaster();
|
||||||
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
|
|
||||||
PVRecordPtr pvRecord;
|
PVRecordPtr pvRecord;
|
||||||
bool result(false);
|
bool result = false;
|
||||||
string recordName;
|
string recordName;
|
||||||
|
|
||||||
recordName = "exampleServer";
|
recordName = "exampleServer";
|
||||||
pvRecord = ExampleServer::create(recordName);
|
pvRecord = ExampleServer::create(recordName);
|
||||||
result = master->addRecord(pvRecord);
|
result = master->addRecord(pvRecord);
|
||||||
cout << "result of addRecord " << recordName << " " << result << endl;
|
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
|
|
||||||
recordName = "traceRecordPGRPC";
|
recordName = "traceRecordPGRPC";
|
||||||
pvRecord = TraceRecord::create(recordName);
|
pvRecord = TraceRecord::create(recordName);
|
||||||
result = master->addRecord(pvRecord);
|
result = master->addRecord(pvRecord);
|
||||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
pvRecord.reset();
|
|
||||||
ServerContext::shared_pointer pvaServer =
|
|
||||||
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
|
|
||||||
cout << "exampleServer\n";
|
|
||||||
string str;
|
|
||||||
while(true) {
|
|
||||||
cout << "Type exit to stop: \n";
|
|
||||||
getline(cin,str);
|
|
||||||
if(str.compare("exit")==0) break;
|
|
||||||
|
|
||||||
}
|
recordName = "laptoprecordListPGRPC";
|
||||||
pvaServer->shutdown();
|
pvRecord = RecordListRecord::create(recordName);
|
||||||
epicsThreadSleep(1.0);
|
result = master->addRecord(pvRecord);
|
||||||
pvaServer->destroy();
|
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
channelProvider->destroy();
|
|
||||||
|
|
||||||
|
ContextLocal::shared_pointer contextLocal = ContextLocal::create();
|
||||||
|
contextLocal->start();
|
||||||
|
|
||||||
|
PVStringArrayPtr pvNames = master->getRecordNames();
|
||||||
|
shared_vector<const string> names = pvNames->view();
|
||||||
|
for(size_t i=0; i<names.size(); ++i) cout << names[i] << endl;
|
||||||
|
|
||||||
|
contextLocal->waitForExit();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,12 +27,13 @@
|
|||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
#include <iocsh.h>
|
#include <iocsh.h>
|
||||||
|
|
||||||
#include <epicsExport.h>
|
|
||||||
|
|
||||||
#include <pv/pvIntrospect.h>
|
#include <pv/pvIntrospect.h>
|
||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
#include <pv/pvAccess.h>
|
#include <pv/pvAccess.h>
|
||||||
#include <pv/pvDatabase.h>
|
#include <pv/pvDatabase.h>
|
||||||
|
#include <pv/recordList.h>
|
||||||
|
|
||||||
|
#include <epicsExport.h>
|
||||||
#include <pv/exampleServer.h>
|
#include <pv/exampleServer.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
@@ -50,10 +51,19 @@ static const iocshFuncDef exampleServerFuncDef = {
|
|||||||
"exampleServerCreateRecord", 1, testArgs};
|
"exampleServerCreateRecord", 1, testArgs};
|
||||||
static void exampleServerCallFunc(const iocshArgBuf *args)
|
static void exampleServerCallFunc(const iocshArgBuf *args)
|
||||||
{
|
{
|
||||||
|
PVDatabasePtr master = PVDatabase::getMaster();
|
||||||
char *recordName = args[0].sval;
|
char *recordName = args[0].sval;
|
||||||
ExampleServerPtr record = ExampleServer::create(recordName);
|
ExampleServerPtr record = ExampleServer::create(recordName);
|
||||||
bool result = PVDatabase::getMaster()->addRecord(record);
|
bool result = master->addRecord(record);
|
||||||
if(!result) cout << "recordname" << " not added" << endl;
|
if(!result) cout << "recordname" << " not added" << endl;
|
||||||
|
PVRecordPtr pvRecord = RecordListRecord::create(
|
||||||
|
"laptoprecordListPGRPC");
|
||||||
|
if(!pvRecord) {
|
||||||
|
cout << "RecordListRecord::create failed" << endl;
|
||||||
|
} else {
|
||||||
|
result = master->addRecord(pvRecord);
|
||||||
|
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void exampleServerRegister(void)
|
static void exampleServerRegister(void)
|
||||||
|
|||||||
@@ -1,13 +1,28 @@
|
|||||||
# pvDatabaseCPP
|
# pvDatabase C++ implementation
|
||||||
# Jenkins @ Cloudbees build script
|
# Jenkins @ Cloudbees build script
|
||||||
#
|
#
|
||||||
# Jenkins invokes scripts with the "-ex" option. So the build is considered a failure
|
# Jenkins invokes scripts with the "-ex" option. So the build is considered a failure
|
||||||
# if any of the commands exits with a non-zero exit code.
|
# if any of the commands exits with a non-zero exit code.
|
||||||
#
|
#
|
||||||
# Author: Ralph Lange <Ralph.Lange@gmx.de>
|
# Author: Ralph Lange <ralph.lange@gmx.de>
|
||||||
# Copyright (C) 2014 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
|
# Copyright (C) 2014 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
|
||||||
|
# Copyright (C) 2014-2015 ITER Organization.
|
||||||
# All rights reserved. Use is subject to license terms.
|
# All rights reserved. Use is subject to license terms.
|
||||||
|
|
||||||
|
###########################################
|
||||||
|
# Determine EPICS Base version
|
||||||
|
|
||||||
|
DEFAULT_BASE=3.14.12.5
|
||||||
|
|
||||||
|
BASE=${1:-${DEFAULT_BASE}}
|
||||||
|
USE_MB=${2:-"MB_NO"}
|
||||||
|
|
||||||
|
# Dependent module branches (empty = master)
|
||||||
|
PVCOMMON_BRANCH="Release-4.1-"
|
||||||
|
PVDATA_BRANCH="Release-5.0-"
|
||||||
|
PVACCESS_BRANCH="Release-4.1-"
|
||||||
|
PVASRV_BRANCH="Release-0.11-"
|
||||||
|
|
||||||
###########################################
|
###########################################
|
||||||
# Fetch and unpack dependencies
|
# Fetch and unpack dependencies
|
||||||
|
|
||||||
@@ -17,17 +32,20 @@ rm -fr ${STUFF}
|
|||||||
mkdir -p ${STUFF}
|
mkdir -p ${STUFF}
|
||||||
cd ${STUFF}
|
cd ${STUFF}
|
||||||
|
|
||||||
wget -nv https://openepics.ci.cloudbees.com/job/Base-3.14.12.3_Build/lastSuccessfulBuild/artifact/baseR3.14.12.3.CB-dist.tar.gz
|
wget -nv https://openepics.ci.cloudbees.com/job/Base-${BASE}_Build/lastSuccessfulBuild/artifact/base-${BASE}.CB-dist.tar.gz
|
||||||
wget -nv https://openepics.ci.cloudbees.com/job/Doxygen-1.8.3_Build/lastSuccessfulBuild/artifact/doxygen-1.8.3.CB-dist.tar.gz
|
wget -nv https://openepics.ci.cloudbees.com/job/pvDataCPP_${PVDATA_BRANCH}Build/BASE=${BASE},USE_MB=MB_NO/lastSuccessfulBuild/artifact/pvData.CB-dist.tar.gz
|
||||||
wget -nv https://openepics.ci.cloudbees.com/job/pvData_CPP_Build/lastSuccessfulBuild/artifact/pvData.CB-dist.tar.gz
|
wget -nv https://openepics.ci.cloudbees.com/job/pvAccessCPP_${PVACCESS_BRANCH}Build/BASE=${BASE},USE_MB=${USE_MB}/lastSuccessfulBuild/artifact/pvAccess.CB-dist.tar.gz
|
||||||
wget -nv https://openepics.ci.cloudbees.com/job/pvAccess_CPP_Build/lastSuccessfulBuild/artifact/pvAccess.CB-dist.tar.gz
|
wget -nv https://openepics.ci.cloudbees.com/job/pvaSrvCPP_${PVASRV_BRANCH}Build/BASE=${BASE},USE_MB=MB_NO/lastSuccessfulBuild/artifact/pvaSrv.CB-dist.tar.gz
|
||||||
wget -nv https://openepics.ci.cloudbees.com/job/pvaSrv_CPP_Build/lastSuccessfulBuild/artifact/pvaSrv.CB-dist.tar.gz
|
tar -xzf base-${BASE}.CB-dist.tar.gz
|
||||||
tar -xzf baseR3.14.12.3.CB-dist.tar.gz
|
|
||||||
tar -xzf doxygen-1.8.3.CB-dist.tar.gz
|
|
||||||
tar -xzf pvData.CB-dist.tar.gz
|
tar -xzf pvData.CB-dist.tar.gz
|
||||||
tar -xzf pvAccess.CB-dist.tar.gz
|
tar -xzf pvAccess.CB-dist.tar.gz
|
||||||
tar -xzf pvaSrv.CB-dist.tar.gz
|
tar -xzf pvaSrv.CB-dist.tar.gz
|
||||||
|
|
||||||
|
if [ "${USE_MB}" = "MB_YES" ]; then
|
||||||
|
wget -nv https://openepics.ci.cloudbees.com/job/pvCommonCPP_${PVCOMMON_BRANCH}Build/BASE=${BASE},USE_MB=MB_YES/lastSuccessfulBuild/artifact/pvCommon.CB-dist.tar.gz
|
||||||
|
tar -xzf pvCommon.CB-dist.tar.gz
|
||||||
|
fi
|
||||||
|
|
||||||
###########################################
|
###########################################
|
||||||
# Build
|
# Build
|
||||||
|
|
||||||
@@ -43,7 +61,6 @@ EPICS_BASE=${EPICS_BASE}
|
|||||||
EOF
|
EOF
|
||||||
|
|
||||||
make distclean all
|
make distclean all
|
||||||
doxygen
|
|
||||||
|
|
||||||
###########################################
|
###########################################
|
||||||
# Test
|
# Test
|
||||||
@@ -53,9 +70,4 @@ doxygen
|
|||||||
###########################################
|
###########################################
|
||||||
# Create distribution
|
# Create distribution
|
||||||
|
|
||||||
tar -czf pvDatabaseCPP.CB-dist.tar.gz lib include dbd COPYRIGHT LICENSE
|
tar -czf pvDatabase.CB-dist.tar.gz lib include dbd COPYRIGHT LICENSE
|
||||||
|
|
||||||
###########################################
|
|
||||||
# Publish documentation
|
|
||||||
|
|
||||||
rsync -aP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvDatabaseCPP/tip
|
|
||||||
|
|||||||
46
jenkins/cloudbees_doc
Normal file
46
jenkins/cloudbees_doc
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# pvDatabase C++ implementation
|
||||||
|
# Jenkins @ Cloudbees documentation generation and deployment
|
||||||
|
#
|
||||||
|
# Jenkins invokes scripts with the "-ex" option. So the build is considered a failure
|
||||||
|
# if any of the commands exits with a non-zero exit code.
|
||||||
|
#
|
||||||
|
# Author: Ralph Lange <ralph.lange@gmx.de>
|
||||||
|
# Copyright (C) 2014 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
|
||||||
|
# Copyright (C) 2014-2015 ITER Organization.
|
||||||
|
# All rights reserved. Use is subject to license terms.
|
||||||
|
|
||||||
|
###########################################
|
||||||
|
# Determine EPICS Base version
|
||||||
|
|
||||||
|
DEFAULT_BASE=3.14.12.5
|
||||||
|
|
||||||
|
BASE=${1:-${DEFAULT_BASE}}
|
||||||
|
|
||||||
|
###########################################
|
||||||
|
# Fetch and unpack dependencies
|
||||||
|
|
||||||
|
export STUFF=/tmp/stuff
|
||||||
|
|
||||||
|
rm -fr ${STUFF}
|
||||||
|
mkdir -p ${STUFF}
|
||||||
|
cd ${STUFF}
|
||||||
|
|
||||||
|
wget -nv https://openepics.ci.cloudbees.com/job/Doxygen-1.8.3_Build/lastSuccessfulBuild/artifact/doxygen-1.8.3.CB-dist.tar.gz
|
||||||
|
tar -xzf doxygen-1.8.3.CB-dist.tar.gz
|
||||||
|
|
||||||
|
###########################################
|
||||||
|
# Generate
|
||||||
|
|
||||||
|
cd ${WORKSPACE}
|
||||||
|
|
||||||
|
wget -nv https://openepics.ci.cloudbees.com/job/pvDatabaseCPP_Build/BASE=${BASE},USE_MB=MB_NO/lastSuccessfulBuild/artifact/pvDatabase.CB-dist.tar.gz
|
||||||
|
tar -xzf pvDatabase.CB-dist.tar.gz
|
||||||
|
|
||||||
|
export PATH=${STUFF}/bin:${PATH}
|
||||||
|
|
||||||
|
doxygen
|
||||||
|
|
||||||
|
###########################################
|
||||||
|
# Publish
|
||||||
|
|
||||||
|
rsync -aqP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvDatabaseCPP/tip
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# pvDatabaseCPP
|
|
||||||
# Jenkins @ Cloudbees hgweb sync script
|
|
||||||
#
|
|
||||||
# Jenkins invokes scripts with the "-ex" option. So the build is considered a failure
|
|
||||||
# if any of the commands exits with a non-zero exit code.
|
|
||||||
#
|
|
||||||
# Author: Ralph Lange <Ralph.Lange@gmx.de>
|
|
||||||
# Copyright (C) 2014 Helmholtz-Zentrum Berlin für Materialien und Energie GmbH
|
|
||||||
# All rights reserved. Use is subject to license terms.
|
|
||||||
|
|
||||||
###########################################
|
|
||||||
# Fetch complete repo
|
|
||||||
|
|
||||||
rm -fr hgweb
|
|
||||||
hg clone -U http://hg.code.sf.net/p/epics-pvdata/pvDatabaseCPP hgweb
|
|
||||||
|
|
||||||
###########################################
|
|
||||||
# Sync into SF webspace
|
|
||||||
|
|
||||||
rsync -aqP --delete --exclude=\.hg/hgrc -e ssh hgweb/.hg epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/repos/pvDatabaseCPP
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
// ADD PREDEFINED MACROS HERE!
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
[General]
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
arrayPerformance/src/arrayPerformance.cpp
|
|
||||||
arrayPerformance/src/arrayPerformance.h
|
|
||||||
arrayPerformance/src/arrayPerformanceMain.cpp
|
|
||||||
arrayPerformance/src/longArrayGet.cpp
|
|
||||||
arrayPerformance/src/longArrayGet.h
|
|
||||||
arrayPerformance/src/longArrayGetMain.cpp
|
|
||||||
arrayPerformance/src/longArrayMonitor.cpp
|
|
||||||
arrayPerformance/src/longArrayMonitor.h
|
|
||||||
arrayPerformance/src/longArrayMonitorMain.cpp
|
|
||||||
arrayPerformance/src/longArrayPut.cpp
|
|
||||||
arrayPerformance/src/longArrayPut.h
|
|
||||||
arrayPerformance/src/longArrayPutMain.cpp
|
|
||||||
arrayPerformance/src/vectorPerformanceMain.cpp
|
|
||||||
exampleDatabase/ioc/src/O.linux-x86_64/exampleDatabase_registerRecordDeviceDriver.cpp
|
|
||||||
exampleDatabase/ioc/src/exampleDatabaseMain.cpp
|
|
||||||
exampleDatabase/src/exampleDatabase.cpp
|
|
||||||
exampleDatabase/src/exampleDatabase.h
|
|
||||||
exampleDatabase/src/exampleDatabaseMain.cpp
|
|
||||||
exampleDatabase/src/exampleDatabaseRegister.cpp
|
|
||||||
exampleLink/ioc/src/O.linux-x86_64/exampleLink_registerRecordDeviceDriver.cpp
|
|
||||||
exampleLink/ioc/src/exampleLinkMain.cpp
|
|
||||||
exampleLink/src/exampleLink.cpp
|
|
||||||
exampleLink/src/exampleLink.h
|
|
||||||
exampleLink/src/exampleLinkRegister.cpp
|
|
||||||
examplePowerSupply/ioc/src/O.linux-x86_64/powerSupply_registerRecordDeviceDriver.cpp
|
|
||||||
examplePowerSupply/ioc/src/powerSupplyMain.cpp
|
|
||||||
examplePowerSupply/src/powerSupplyMain.cpp
|
|
||||||
exampleServer/ioc/src/O.linux-x86_64/exampleServer_registerRecordDeviceDriver.cpp
|
|
||||||
exampleServer/ioc/src/exampleServerMain.cpp
|
|
||||||
exampleServer/src/exampleServer.cpp
|
|
||||||
exampleServer/src/exampleServer.h
|
|
||||||
exampleServer/src/exampleServerMain.cpp
|
|
||||||
exampleServer/src/exampleServerRegister.cpp
|
|
||||||
src/database/pvDatabase.cpp
|
|
||||||
src/database/pvDatabase.h
|
|
||||||
src/database/pvRecord.cpp
|
|
||||||
src/pvAccess/channelLocal.cpp
|
|
||||||
src/pvAccess/channelProviderLocal.cpp
|
|
||||||
src/pvAccess/channelProviderLocal.h
|
|
||||||
src/pvAccess/monitorAlgorithm.h
|
|
||||||
src/pvAccess/monitorFactory.cpp
|
|
||||||
src/pvAccess/pvCopy.cpp
|
|
||||||
src/pvAccess/pvCopy.h
|
|
||||||
src/pvAccess/registerChannelProviderLocal.cpp
|
|
||||||
src/special/recordList.cpp
|
|
||||||
src/special/recordList.h
|
|
||||||
src/special/traceRecord.cpp
|
|
||||||
src/special/traceRecord.h
|
|
||||||
test/src/powerSupply.cpp
|
|
||||||
test/src/powerSupply.h
|
|
||||||
test/src/powerSupplyRegister.cpp
|
|
||||||
test/src/testExampleRecord.cpp
|
|
||||||
test/src/testPVCopy.cpp
|
|
||||||
test/src/testPVRecord.cpp
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
arrayPerformance/src
|
|
||||||
exampleDatabase/src
|
|
||||||
exampleLink/src
|
|
||||||
exampleServer/src
|
|
||||||
src/database
|
|
||||||
src/pvAccess
|
|
||||||
src/special
|
|
||||||
test/src
|
|
||||||
@@ -21,15 +21,16 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/pvCopy.h>
|
||||||
#include <pv/convert.h>
|
#include <pv/pvTimeStamp.h>
|
||||||
|
|
||||||
#ifdef pvdatabaseEpicsExportSharedSymbols
|
#ifdef pvdatabaseEpicsExportSharedSymbols
|
||||||
# define epicsExportSharedSymbols
|
# define epicsExportSharedSymbols
|
||||||
# undef pvdatabaseEpicsExportSharedSymbols
|
# undef pvdatabaseEpicsExportSharedSymbols
|
||||||
# include <shareLib.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <shareLib.h>
|
||||||
|
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
@@ -55,10 +56,12 @@ class PVDatabase;
|
|||||||
typedef std::tr1::shared_ptr<PVDatabase> PVDatabasePtr;
|
typedef std::tr1::shared_ptr<PVDatabase> PVDatabasePtr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base interface for a record.
|
* @brief Base interface for a record.
|
||||||
|
*
|
||||||
* @author mrk
|
* @author mrk
|
||||||
*/
|
*/
|
||||||
class epicsShareClass PVRecord :
|
class epicsShareClass PVRecord :
|
||||||
|
public epics::pvData::PVCopyTraverseMasterCallback,
|
||||||
public std::tr1::enable_shared_from_this<PVRecord>
|
public std::tr1::enable_shared_from_this<PVRecord>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -82,7 +85,7 @@ public:
|
|||||||
* If it encounters errors it should raise alarms and/or
|
* If it encounters errors it should raise alarms and/or
|
||||||
* call the <b>message</b> method provided by the base class.
|
* call the <b>message</b> method provided by the base class.
|
||||||
*/
|
*/
|
||||||
virtual void process() {}
|
virtual void process();
|
||||||
/**
|
/**
|
||||||
* Destroy the PVRecord. Release any resources used and
|
* Destroy the PVRecord. Release any resources used and
|
||||||
* get rid of listeners and requesters.
|
* get rid of listeners and requesters.
|
||||||
@@ -166,15 +169,26 @@ public:
|
|||||||
* Add a PVListener.
|
* Add a PVListener.
|
||||||
* This must be called before calling pvRecordField.addListener.
|
* This must be called before calling pvRecordField.addListener.
|
||||||
* @param pvListener The listener.
|
* @param pvListener The listener.
|
||||||
|
* @param pvCopy The pvStructure that has the client fields.
|
||||||
* @return <b>true</b> if the listener was added.
|
* @return <b>true</b> if the listener was added.
|
||||||
*/
|
*/
|
||||||
bool addListener(PVListenerPtr const & pvListener);
|
bool addListener(
|
||||||
|
PVListenerPtr const & pvListener,
|
||||||
|
epics::pvData::PVCopyPtr const & pvCopy);
|
||||||
|
/*
|
||||||
|
* PVCopyTraverseMasterCallback method
|
||||||
|
* @param pvField The next client field.
|
||||||
|
*/
|
||||||
|
void nextMasterPVField(epics::pvData::PVFieldPtr const & pvField);
|
||||||
/**
|
/**
|
||||||
* Remove a listener.
|
* Remove a listener.
|
||||||
* @param pvListener The listener.
|
* @param pvListener The listener.
|
||||||
|
* @param pvCopy The pvStructure that has the client fields.
|
||||||
* @return <b>true</b> if the listener was removed.
|
* @return <b>true</b> if the listener was removed.
|
||||||
*/
|
*/
|
||||||
bool removeListener(PVListenerPtr const & pvListener);
|
bool removeListener(
|
||||||
|
PVListenerPtr const & pvListener,
|
||||||
|
epics::pvData::PVCopyPtr const & pvCopy);
|
||||||
/**
|
/**
|
||||||
* Begins a group of puts.
|
* Begins a group of puts.
|
||||||
*/
|
*/
|
||||||
@@ -219,9 +233,9 @@ private:
|
|||||||
PVRecordFieldPtr findPVRecordField(
|
PVRecordFieldPtr findPVRecordField(
|
||||||
PVRecordStructurePtr const & pvrs,
|
PVRecordStructurePtr const & pvrs,
|
||||||
epics::pvData::PVFieldPtr const & pvField);
|
epics::pvData::PVFieldPtr const & pvField);
|
||||||
|
|
||||||
std::string recordName;
|
std::string recordName;
|
||||||
epics::pvData::PVStructurePtr pvStructure;
|
epics::pvData::PVStructurePtr pvStructure;
|
||||||
epics::pvData::ConvertPtr convert;
|
|
||||||
PVRecordStructurePtr pvRecordStructure;
|
PVRecordStructurePtr pvRecordStructure;
|
||||||
std::list<PVListenerPtr> pvListenerList;
|
std::list<PVListenerPtr> pvListenerList;
|
||||||
std::list<PVRecordClientPtr> pvRecordClientList;
|
std::list<PVRecordClientPtr> pvRecordClientList;
|
||||||
@@ -229,12 +243,20 @@ private:
|
|||||||
std::size_t depthGroupPut;
|
std::size_t depthGroupPut;
|
||||||
int traceLevel;
|
int traceLevel;
|
||||||
bool isDestroyed;
|
bool isDestroyed;
|
||||||
|
|
||||||
|
epics::pvData::PVTimeStamp pvTimeStamp;
|
||||||
|
epics::pvData::TimeStamp timeStamp;
|
||||||
|
|
||||||
|
// following only valid while addListener or removeListener is active.
|
||||||
|
bool isAddListener;
|
||||||
|
PVListenerPtr pvListener;
|
||||||
};
|
};
|
||||||
|
|
||||||
epicsShareExtern std::ostream& operator<<(std::ostream& o, const PVRecord& record);
|
epicsShareExtern std::ostream& operator<<(std::ostream& o, const PVRecord& record);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for a field of a record.
|
* @brief Interface for a field of a record.
|
||||||
|
*
|
||||||
* One exists for each field of the top level PVStructure.
|
* One exists for each field of the top level PVStructure.
|
||||||
* @author mrk
|
* @author mrk
|
||||||
*/
|
*/
|
||||||
@@ -286,21 +308,6 @@ public:
|
|||||||
* @return The shared pointer,
|
* @return The shared pointer,
|
||||||
*/
|
*/
|
||||||
PVRecordPtr getPVRecord();
|
PVRecordPtr getPVRecord();
|
||||||
/**
|
|
||||||
* Add A PVListener to this field.
|
|
||||||
* Whenever this field or any subfield if this field is modified the listener will be notified.
|
|
||||||
* PVListener is described below.
|
|
||||||
* Before a listener can call addListener it must first call PVRecord.registerListener.
|
|
||||||
* @param pvListener The listener.
|
|
||||||
* @return <b<true</b> if listener is added.
|
|
||||||
*/
|
|
||||||
bool addListener(PVListenerPtr const & pvListener);
|
|
||||||
/**
|
|
||||||
* Remove a listener.
|
|
||||||
* @param pvListener The listener.
|
|
||||||
* @return <b<true</b> if listener is removed.
|
|
||||||
*/
|
|
||||||
virtual void removeListener(PVListenerPtr const & pvListener);
|
|
||||||
/**
|
/**
|
||||||
* This is called by the code that implements the data interface.
|
* This is called by the code that implements the data interface.
|
||||||
* It is called whenever the put method is called.
|
* It is called whenever the put method is called.
|
||||||
@@ -315,6 +322,8 @@ protected:
|
|||||||
virtual void postParent(PVRecordFieldPtr const & subField);
|
virtual void postParent(PVRecordFieldPtr const & subField);
|
||||||
virtual void postSubField();
|
virtual void postSubField();
|
||||||
private:
|
private:
|
||||||
|
bool addListener(PVListenerPtr const & pvListener);
|
||||||
|
virtual void removeListener(PVListenerPtr const & pvListener);
|
||||||
void callListener();
|
void callListener();
|
||||||
|
|
||||||
std::list<PVListenerPtr> pvListenerList;
|
std::list<PVListenerPtr> pvListenerList;
|
||||||
@@ -329,7 +338,8 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for a field that is a structure.
|
* @brief Interface for a field that is a structure.
|
||||||
|
*
|
||||||
* One exists for each structure field of the top level PVStructure.
|
* One exists for each structure field of the top level PVStructure.
|
||||||
* @author mrk
|
* @author mrk
|
||||||
*/
|
*/
|
||||||
@@ -364,11 +374,6 @@ public:
|
|||||||
* @return The shared pointer.
|
* @return The shared pointer.
|
||||||
*/
|
*/
|
||||||
epics::pvData::PVStructurePtr getPVStructure();
|
epics::pvData::PVStructurePtr getPVStructure();
|
||||||
/**
|
|
||||||
* Called by PVRecord::removeListener.
|
|
||||||
* @param pvListener The listener.
|
|
||||||
*/
|
|
||||||
virtual void removeListener(PVListenerPtr const & pvListener);
|
|
||||||
/**
|
/**
|
||||||
* Called by implementation code of PVRecord.
|
* Called by implementation code of PVRecord.
|
||||||
*/
|
*/
|
||||||
@@ -379,13 +384,16 @@ protected:
|
|||||||
*/
|
*/
|
||||||
virtual void init();
|
virtual void init();
|
||||||
private:
|
private:
|
||||||
|
virtual void removeListener(PVListenerPtr const & pvListener);
|
||||||
|
|
||||||
epics::pvData::PVStructurePtr pvStructure;
|
epics::pvData::PVStructurePtr pvStructure;
|
||||||
PVRecordFieldPtrArrayPtr pvRecordFields;
|
PVRecordFieldPtrArrayPtr pvRecordFields;
|
||||||
friend class PVRecord;
|
friend class PVRecord;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An interface that must be implemented by any code that accesses the record.
|
* @brief An interface implemented by code that accesses the record.
|
||||||
|
*
|
||||||
* @author mrk
|
* @author mrk
|
||||||
*/
|
*/
|
||||||
class epicsShareClass PVRecordClient {
|
class epicsShareClass PVRecordClient {
|
||||||
@@ -403,6 +411,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @brief Listener for PVRecord::message.
|
||||||
|
*
|
||||||
* An interface that is implemented by code that traps calls to PVRecord::message.
|
* An interface that is implemented by code that traps calls to PVRecord::message.
|
||||||
* @author mrk
|
* @author mrk
|
||||||
*/
|
*/
|
||||||
@@ -447,7 +457,8 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interface to a database of PVRecords.
|
* @brief The interface for a database of PVRecords.
|
||||||
|
*
|
||||||
* @author mrk
|
* @author mrk
|
||||||
*/
|
*/
|
||||||
class epicsShareClass PVDatabase {
|
class epicsShareClass PVDatabase {
|
||||||
@@ -502,3 +513,10 @@ private:
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
#endif /* PVDATABASE_H */
|
#endif /* PVDATABASE_H */
|
||||||
|
|
||||||
|
/** @page Overview Documentation
|
||||||
|
*
|
||||||
|
* <a href = "pvDatabaseCPP.html">pvDatabase.html</a>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -39,10 +39,10 @@ PVRecord::PVRecord(
|
|||||||
PVStructurePtr const & pvStructure)
|
PVStructurePtr const & pvStructure)
|
||||||
: recordName(recordName),
|
: recordName(recordName),
|
||||||
pvStructure(pvStructure),
|
pvStructure(pvStructure),
|
||||||
convert(getConvert()),
|
|
||||||
depthGroupPut(0),
|
depthGroupPut(0),
|
||||||
traceLevel(0),
|
traceLevel(0),
|
||||||
isDestroyed(false)
|
isDestroyed(false),
|
||||||
|
isAddListener(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,6 +59,8 @@ void PVRecord::initPVRecord()
|
|||||||
pvRecordStructure = PVRecordStructurePtr(
|
pvRecordStructure = PVRecordStructurePtr(
|
||||||
new PVRecordStructure(pvStructure,parent,getPtrSelf()));
|
new PVRecordStructure(pvStructure,parent,getPtrSelf()));
|
||||||
pvRecordStructure->init();
|
pvRecordStructure->init();
|
||||||
|
PVFieldPtr pvField = pvStructure->getSubField("timeStamp");
|
||||||
|
if(pvField) pvTimeStamp.attach(pvField);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PVRecord::destroy()
|
void PVRecord::destroy()
|
||||||
@@ -73,6 +75,7 @@ void PVRecord::destroy()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isDestroyed = true;
|
isDestroyed = true;
|
||||||
|
pvTimeStamp.detach();
|
||||||
|
|
||||||
std::list<PVRecordClientPtr>::iterator clientIter;
|
std::list<PVRecordClientPtr>::iterator clientIter;
|
||||||
while(true) {
|
while(true) {
|
||||||
@@ -94,7 +97,6 @@ void PVRecord::destroy()
|
|||||||
}
|
}
|
||||||
pvRecordStructure->destroy();
|
pvRecordStructure->destroy();
|
||||||
pvRecordStructure.reset();
|
pvRecordStructure.reset();
|
||||||
convert.reset();
|
|
||||||
pvStructure.reset();
|
pvStructure.reset();
|
||||||
unlock();
|
unlock();
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
@@ -103,6 +105,17 @@ void PVRecord::destroy()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PVRecord::process()
|
||||||
|
{
|
||||||
|
if(traceLevel>2) {
|
||||||
|
cout << "PVRecord::process() " << recordName << endl;
|
||||||
|
}
|
||||||
|
if(pvTimeStamp.isAttached()) {
|
||||||
|
timeStamp.getCurrent();
|
||||||
|
pvTimeStamp.set(timeStamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string PVRecord::getRecordName() const {return recordName;}
|
string PVRecord::getRecordName() const {return recordName;}
|
||||||
|
|
||||||
PVRecordStructurePtr PVRecord::getPVRecordStructure() const {return pvRecordStructure;}
|
PVRecordStructurePtr PVRecord::getPVRecordStructure() const {return pvRecordStructure;}
|
||||||
@@ -263,7 +276,9 @@ void PVRecord::detachClients()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PVRecord::addListener(PVListenerPtr const & pvListener)
|
bool PVRecord::addListener(
|
||||||
|
PVListenerPtr const & pvListener,
|
||||||
|
PVCopyPtr const & pvCopy)
|
||||||
{
|
{
|
||||||
if(traceLevel>1) {
|
if(traceLevel>1) {
|
||||||
cout << "PVRecord::addListener() " << recordName << endl;
|
cout << "PVRecord::addListener() " << recordName << endl;
|
||||||
@@ -283,6 +298,10 @@ bool PVRecord::addListener(PVListenerPtr const & pvListener)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pvListenerList.push_back(pvListener);
|
pvListenerList.push_back(pvListener);
|
||||||
|
this->pvListener = pvListener;
|
||||||
|
isAddListener = true;
|
||||||
|
pvCopy->traverseMaster(getPtrSelf());
|
||||||
|
this->pvListener = PVListenerPtr();;
|
||||||
unlock();
|
unlock();
|
||||||
return true;
|
return true;
|
||||||
} catch(...) {
|
} catch(...) {
|
||||||
@@ -291,7 +310,19 @@ bool PVRecord::addListener(PVListenerPtr const & pvListener)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PVRecord::removeListener(PVListenerPtr const & pvListener)
|
void PVRecord::nextMasterPVField(PVFieldPtr const & pvField)
|
||||||
|
{
|
||||||
|
PVRecordFieldPtr pvRecordField = findPVRecordField(pvField);
|
||||||
|
if(isAddListener) {
|
||||||
|
pvRecordField->addListener(pvListener);
|
||||||
|
} else {
|
||||||
|
pvRecordField->removeListener(pvListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PVRecord::removeListener(
|
||||||
|
PVListenerPtr const & pvListener,
|
||||||
|
PVCopyPtr const & pvCopy)
|
||||||
{
|
{
|
||||||
if(traceLevel>1) {
|
if(traceLevel>1) {
|
||||||
cout << "PVRecord::removeListener() " << recordName << endl;
|
cout << "PVRecord::removeListener() " << recordName << endl;
|
||||||
@@ -307,7 +338,10 @@ bool PVRecord::removeListener(PVListenerPtr const & pvListener)
|
|||||||
{
|
{
|
||||||
if((*iter).get()==pvListener.get()) {
|
if((*iter).get()==pvListener.get()) {
|
||||||
pvListenerList.erase(iter);
|
pvListenerList.erase(iter);
|
||||||
pvRecordStructure->removeListener(pvListener);
|
this->pvListener = pvListener;
|
||||||
|
isAddListener = false;
|
||||||
|
pvCopy->traverseMaster(getPtrSelf());
|
||||||
|
this->pvListener = PVListenerPtr();;
|
||||||
unlock();
|
unlock();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -371,7 +405,7 @@ void PVRecordField::init()
|
|||||||
{
|
{
|
||||||
fullFieldName = pvField->getFieldName();
|
fullFieldName = pvField->getFieldName();
|
||||||
PVRecordStructurePtr pvParent = parent;
|
PVRecordStructurePtr pvParent = parent;
|
||||||
while(pvParent.get()!= NULL) {
|
while(pvParent) {
|
||||||
string parentName = pvParent->getPVField()->getFieldName();
|
string parentName = pvParent->getPVField()->getFieldName();
|
||||||
if(parentName.size()>0) {
|
if(parentName.size()>0) {
|
||||||
fullFieldName = pvParent->getPVField()->getFieldName()
|
fullFieldName = pvParent->getPVField()->getFieldName()
|
||||||
@@ -411,6 +445,9 @@ PVRecordPtr PVRecordField::getPVRecord() {return pvRecord;}
|
|||||||
|
|
||||||
bool PVRecordField::addListener(PVListenerPtr const & pvListener)
|
bool PVRecordField::addListener(PVListenerPtr const & pvListener)
|
||||||
{
|
{
|
||||||
|
if(pvRecord->getTraceLevel()>1) {
|
||||||
|
cout << "PVRecordField::addListener() " << getFullName() << endl;
|
||||||
|
}
|
||||||
std::list<PVListenerPtr>::iterator iter;
|
std::list<PVListenerPtr>::iterator iter;
|
||||||
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
|
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
|
||||||
if((*iter).get()==pvListener.get()) {
|
if((*iter).get()==pvListener.get()) {
|
||||||
@@ -423,6 +460,9 @@ bool PVRecordField::addListener(PVListenerPtr const & pvListener)
|
|||||||
|
|
||||||
void PVRecordField::removeListener(PVListenerPtr const & pvListener)
|
void PVRecordField::removeListener(PVListenerPtr const & pvListener)
|
||||||
{
|
{
|
||||||
|
if(pvRecord->getTraceLevel()>1) {
|
||||||
|
cout << "PVRecordField::removeListener() " << getFullName() << endl;
|
||||||
|
}
|
||||||
std::list<PVListenerPtr>::iterator iter;
|
std::list<PVListenerPtr>::iterator iter;
|
||||||
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
|
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
|
||||||
if((*iter).get()==pvListener.get()) {
|
if((*iter).get()==pvListener.get()) {
|
||||||
@@ -434,7 +474,7 @@ void PVRecordField::removeListener(PVListenerPtr const & pvListener)
|
|||||||
|
|
||||||
void PVRecordField::postPut()
|
void PVRecordField::postPut()
|
||||||
{
|
{
|
||||||
if(parent!=NULL) {
|
if(parent) {
|
||||||
parent->postParent(getPtrSelf());
|
parent->postParent(getPtrSelf());
|
||||||
}
|
}
|
||||||
postSubField();
|
postSubField();
|
||||||
@@ -448,7 +488,7 @@ void PVRecordField::postParent(PVRecordFieldPtr const & subField)
|
|||||||
{
|
{
|
||||||
(*iter)->dataPut(pvrs,subField);
|
(*iter)->dataPut(pvrs,subField);
|
||||||
}
|
}
|
||||||
if(parent!=NULL) parent->postParent(subField);
|
if(parent) parent->postParent(subField);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PVRecordField::postSubField()
|
void PVRecordField::postSubField()
|
||||||
|
|||||||
@@ -3,13 +3,11 @@
|
|||||||
SRC_DIRS += $(PVDATABASE_SRC)/pvAccess
|
SRC_DIRS += $(PVDATABASE_SRC)/pvAccess
|
||||||
|
|
||||||
INC += channelProviderLocal.h
|
INC += channelProviderLocal.h
|
||||||
INC += pvCopyMonitor.h
|
|
||||||
|
|
||||||
DBD += registerChannelProviderLocal.dbd
|
DBD += registerChannelProviderLocal.dbd
|
||||||
|
|
||||||
LIBSRCS += channelProviderLocal.cpp
|
LIBSRCS += channelProviderLocal.cpp
|
||||||
LIBSRCS += channelLocal.cpp
|
LIBSRCS += channelLocal.cpp
|
||||||
LIBSRCS += pvCopyMonitor.cpp
|
|
||||||
LIBSRCS += monitorFactory.cpp
|
LIBSRCS += monitorFactory.cpp
|
||||||
LIBSRCS += registerChannelProviderLocal.cpp
|
LIBSRCS += registerChannelProviderLocal.cpp
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
#include <pv/timeStamp.h>
|
#include <pv/timeStamp.h>
|
||||||
#include <pv/convert.h>
|
|
||||||
#include <pv/pvSubArrayCopy.h>
|
#include <pv/pvSubArrayCopy.h>
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
@@ -30,7 +29,6 @@ using std::string;
|
|||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
static ConvertPtr convert = getConvert();
|
|
||||||
static StructureConstPtr nullStructure;
|
static StructureConstPtr nullStructure;
|
||||||
static PVStructurePtr nullPVStructure;
|
static PVStructurePtr nullPVStructure;
|
||||||
static BitSetPtr nullBitSet;
|
static BitSetPtr nullBitSet;
|
||||||
@@ -70,7 +68,7 @@ typedef std::tr1::shared_ptr<ChannelArrayLocal> ChannelArrayLocalPtr;
|
|||||||
static bool getProcess(PVStructurePtr pvRequest,bool processDefault)
|
static bool getProcess(PVStructurePtr pvRequest,bool processDefault)
|
||||||
{
|
{
|
||||||
PVFieldPtr pvField = pvRequest->getSubField("record._options.process");
|
PVFieldPtr pvField = pvRequest->getSubField("record._options.process");
|
||||||
if(pvField==NULL || pvField->getField()->getType()!=scalar) {
|
if(!pvField || pvField->getField()->getType()!=scalar) {
|
||||||
return processDefault;
|
return processDefault;
|
||||||
}
|
}
|
||||||
ScalarConstPtr scalar = static_pointer_cast<const Scalar>(
|
ScalarConstPtr scalar = static_pointer_cast<const Scalar>(
|
||||||
@@ -109,8 +107,8 @@ public:
|
|||||||
{return channelLocal;}
|
{return channelLocal;}
|
||||||
virtual void cancel(){}
|
virtual void cancel(){}
|
||||||
virtual void lastRequest() {}
|
virtual void lastRequest() {}
|
||||||
virtual void lock() {mutex.lock();}
|
virtual void lock() {pvRecord->lock();}
|
||||||
virtual void unlock() {mutex.unlock();}
|
virtual void unlock() {pvRecord->unlock();}
|
||||||
private:
|
private:
|
||||||
shared_pointer getPtrSelf()
|
shared_pointer getPtrSelf()
|
||||||
{
|
{
|
||||||
@@ -133,8 +131,8 @@ private:
|
|||||||
ChannelLocalPtr channelLocal;
|
ChannelLocalPtr channelLocal;
|
||||||
ChannelProcessRequester::shared_pointer channelProcessRequester;
|
ChannelProcessRequester::shared_pointer channelProcessRequester;
|
||||||
PVRecordPtr pvRecord;
|
PVRecordPtr pvRecord;
|
||||||
Mutex mutex;
|
|
||||||
int nProcess;
|
int nProcess;
|
||||||
|
Mutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
ChannelProcessLocalPtr ChannelProcessLocal::create(
|
ChannelProcessLocalPtr ChannelProcessLocal::create(
|
||||||
@@ -146,13 +144,13 @@ ChannelProcessLocalPtr ChannelProcessLocal::create(
|
|||||||
PVFieldPtr pvField;
|
PVFieldPtr pvField;
|
||||||
PVStructurePtr pvOptions;
|
PVStructurePtr pvOptions;
|
||||||
int nProcess = 1;
|
int nProcess = 1;
|
||||||
if(pvRequest!=NULL) pvField = pvRequest->getSubField("record._options");
|
if(pvRequest) pvField = pvRequest->getSubField("record._options");
|
||||||
if(pvField.get()!=NULL) {
|
if(pvField) {
|
||||||
pvOptions = static_pointer_cast<PVStructure>(pvField);
|
pvOptions = static_pointer_cast<PVStructure>(pvField);
|
||||||
pvField = pvOptions->getSubField("nProcess");
|
pvField = pvOptions->getSubField("nProcess");
|
||||||
if(pvField.get()!=NULL) {
|
if(pvField) {
|
||||||
PVStringPtr pvString = pvOptions->getStringField("nProcess");
|
PVStringPtr pvString = pvOptions->getSubField<PVString>("nProcess");
|
||||||
if(pvString.get()!=NULL) {
|
if(pvString) {
|
||||||
int size;
|
int size;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << pvString->get();
|
ss << pvString->get();
|
||||||
@@ -242,8 +240,8 @@ public:
|
|||||||
{return channelLocal;}
|
{return channelLocal;}
|
||||||
virtual void cancel(){}
|
virtual void cancel(){}
|
||||||
virtual void lastRequest() {}
|
virtual void lastRequest() {}
|
||||||
virtual void lock() {mutex.lock();}
|
virtual void lock() {pvRecord->lock();}
|
||||||
virtual void unlock() {mutex.unlock();}
|
virtual void unlock() {pvRecord->unlock();}
|
||||||
private:
|
private:
|
||||||
shared_pointer getPtrSelf()
|
shared_pointer getPtrSelf()
|
||||||
{
|
{
|
||||||
@@ -291,7 +289,7 @@ ChannelGetLocalPtr ChannelGetLocal::create(
|
|||||||
pvRecord->getPVRecordStructure()->getPVStructure(),
|
pvRecord->getPVRecordStructure()->getPVStructure(),
|
||||||
pvRequest,
|
pvRequest,
|
||||||
"");
|
"");
|
||||||
if(pvCopy==NULL) {
|
if(!pvCopy) {
|
||||||
Status status(
|
Status status(
|
||||||
Status::STATUSTYPE_ERROR,
|
Status::STATUSTYPE_ERROR,
|
||||||
"invalid pvRequest");
|
"invalid pvRequest");
|
||||||
@@ -401,8 +399,8 @@ public:
|
|||||||
{return channelLocal;}
|
{return channelLocal;}
|
||||||
virtual void cancel(){}
|
virtual void cancel(){}
|
||||||
virtual void lastRequest() {}
|
virtual void lastRequest() {}
|
||||||
virtual void lock() {mutex.lock();}
|
virtual void lock() {pvRecord->lock();}
|
||||||
virtual void unlock() {mutex.unlock();}
|
virtual void unlock() {pvRecord->unlock();}
|
||||||
private:
|
private:
|
||||||
shared_pointer getPtrSelf()
|
shared_pointer getPtrSelf()
|
||||||
{
|
{
|
||||||
@@ -442,7 +440,7 @@ ChannelPutLocalPtr ChannelPutLocal::create(
|
|||||||
pvRecord->getPVRecordStructure()->getPVStructure(),
|
pvRecord->getPVRecordStructure()->getPVStructure(),
|
||||||
pvRequest,
|
pvRequest,
|
||||||
"");
|
"");
|
||||||
if(pvCopy==NULL) {
|
if(!pvCopy) {
|
||||||
Status status(
|
Status status(
|
||||||
Status::STATUSTYPE_ERROR,
|
Status::STATUSTYPE_ERROR,
|
||||||
"invalid pvRequest");
|
"invalid pvRequest");
|
||||||
@@ -570,8 +568,8 @@ public:
|
|||||||
{return channelLocal;}
|
{return channelLocal;}
|
||||||
virtual void cancel(){}
|
virtual void cancel(){}
|
||||||
virtual void lastRequest() {}
|
virtual void lastRequest() {}
|
||||||
virtual void lock() {mutex.lock();}
|
virtual void lock() {pvRecord->lock();}
|
||||||
virtual void unlock() {mutex.unlock();}
|
virtual void unlock() {pvRecord->unlock();}
|
||||||
private:
|
private:
|
||||||
shared_pointer getPtrSelf()
|
shared_pointer getPtrSelf()
|
||||||
{
|
{
|
||||||
@@ -624,7 +622,7 @@ ChannelPutGetLocalPtr ChannelPutGetLocal::create(
|
|||||||
pvRecord->getPVRecordStructure()->getPVStructure(),
|
pvRecord->getPVRecordStructure()->getPVStructure(),
|
||||||
pvRequest,
|
pvRequest,
|
||||||
"getField");
|
"getField");
|
||||||
if(pvPutCopy==NULL || pvGetCopy==NULL) {
|
if(!pvPutCopy || !pvGetCopy) {
|
||||||
Status status(
|
Status status(
|
||||||
Status::STATUSTYPE_ERROR,
|
Status::STATUSTYPE_ERROR,
|
||||||
"invalid pvRequest");
|
"invalid pvRequest");
|
||||||
@@ -777,14 +775,14 @@ public:
|
|||||||
PVArrayPtr const &putArray,
|
PVArrayPtr const &putArray,
|
||||||
size_t offset, size_t count, size_t stride);
|
size_t offset, size_t count, size_t stride);
|
||||||
virtual void getLength();
|
virtual void getLength();
|
||||||
virtual void setLength(size_t length, size_t capacity);
|
virtual void setLength(size_t length);
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
virtual std::tr1::shared_ptr<Channel> getChannel()
|
virtual std::tr1::shared_ptr<Channel> getChannel()
|
||||||
{return channelLocal;}
|
{return channelLocal;}
|
||||||
virtual void cancel(){}
|
virtual void cancel(){}
|
||||||
virtual void lastRequest() {}
|
virtual void lastRequest() {}
|
||||||
virtual void lock() {mutex.lock();}
|
virtual void lock() {pvRecord->lock();}
|
||||||
virtual void unlock() {mutex.unlock();}
|
virtual void unlock() {pvRecord->unlock();}
|
||||||
private:
|
private:
|
||||||
shared_pointer getPtrSelf()
|
shared_pointer getPtrSelf()
|
||||||
{
|
{
|
||||||
@@ -841,8 +839,12 @@ ChannelArrayLocalPtr ChannelArrayLocal::create(
|
|||||||
if(pvfs.size()!=1) break;
|
if(pvfs.size()!=1) break;
|
||||||
pvField = pvfs[0];
|
pvField = pvfs[0];
|
||||||
}
|
}
|
||||||
|
size_t indfield = fieldName.find_first_of("field.");
|
||||||
|
if(indfield==0) {
|
||||||
|
fieldName = fieldName.substr(6);
|
||||||
|
}
|
||||||
pvField = pvRecord->getPVRecordStructure()->getPVStructure()->getSubField(fieldName);
|
pvField = pvRecord->getPVRecordStructure()->getPVStructure()->getSubField(fieldName);
|
||||||
if(pvField==NULL) {
|
if(!pvField) {
|
||||||
Status status(
|
Status status(
|
||||||
Status::STATUSTYPE_ERROR,fieldName +" not found");
|
Status::STATUSTYPE_ERROR,fieldName +" not found");
|
||||||
ChannelArrayLocalPtr channelArray;
|
ChannelArrayLocalPtr channelArray;
|
||||||
@@ -869,66 +871,29 @@ ChannelArrayLocalPtr ChannelArrayLocal::create(
|
|||||||
PVScalarArrayPtr xxx = static_pointer_cast<PVScalarArray>(pvField);
|
PVScalarArrayPtr xxx = static_pointer_cast<PVScalarArray>(pvField);
|
||||||
pvCopy = getPVDataCreate()->createPVScalarArray(
|
pvCopy = getPVDataCreate()->createPVScalarArray(
|
||||||
xxx->getScalarArray()->getElementType());
|
xxx->getScalarArray()->getElementType());
|
||||||
ChannelArrayLocalPtr array(new ChannelArrayLocal(
|
} else if(pvField->getField()->getType()==structureArray) {
|
||||||
channelLocal,
|
|
||||||
channelArrayRequester,
|
|
||||||
pvArray,
|
|
||||||
pvCopy,
|
|
||||||
pvRecord));
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "ChannelArrayLocal::create";
|
|
||||||
cout << " recordName " << pvRecord->getRecordName() << endl;
|
|
||||||
}
|
|
||||||
channelArrayRequester->channelArrayConnect(
|
|
||||||
Status::Ok, array, pvCopy->getArray());
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
if(pvField->getField()->getType()==structureArray) {
|
|
||||||
PVStructureArrayPtr xxx = static_pointer_cast<PVStructureArray>(pvField);
|
PVStructureArrayPtr xxx = static_pointer_cast<PVStructureArray>(pvField);
|
||||||
pvCopy = getPVDataCreate()->createPVStructureArray(
|
pvCopy = getPVDataCreate()->createPVStructureArray(
|
||||||
xxx->getStructureArray()->getStructure());
|
xxx->getStructureArray()->getStructure());
|
||||||
ChannelArrayLocalPtr array(new ChannelArrayLocal(
|
} else {
|
||||||
channelLocal,
|
|
||||||
channelArrayRequester,
|
|
||||||
pvArray,
|
|
||||||
pvCopy,
|
|
||||||
pvRecord));
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "ChannelArrayLocal::create";
|
|
||||||
cout << " recordName " << pvRecord->getRecordName() << endl;
|
|
||||||
}
|
|
||||||
channelArrayRequester->channelArrayConnect(
|
|
||||||
Status::Ok, array, pvCopy->getArray());
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
if(pvField->getField()->getType()==unionArray) {
|
|
||||||
PVUnionArrayPtr xxx = static_pointer_cast<PVUnionArray>(pvField);
|
PVUnionArrayPtr xxx = static_pointer_cast<PVUnionArray>(pvField);
|
||||||
pvCopy = getPVDataCreate()->createPVUnionArray(
|
pvCopy = getPVDataCreate()->createPVUnionArray(
|
||||||
xxx->getUnionArray()->getUnion());
|
xxx->getUnionArray()->getUnion());
|
||||||
ChannelArrayLocalPtr array(new ChannelArrayLocal(
|
|
||||||
channelLocal,
|
|
||||||
channelArrayRequester,
|
|
||||||
pvArray,
|
|
||||||
pvCopy,
|
|
||||||
pvRecord));
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "ChannelArrayLocal::create";
|
|
||||||
cout << " recordName " << pvRecord->getRecordName() << endl;
|
|
||||||
}
|
|
||||||
channelArrayRequester->channelArrayConnect(
|
|
||||||
Status::Ok, array, pvCopy->getArray());
|
|
||||||
return array;
|
|
||||||
}
|
}
|
||||||
|
ChannelArrayLocalPtr array(new ChannelArrayLocal(
|
||||||
Status status(Status::STATUSTYPE_ERROR,
|
channelLocal,
|
||||||
"Logic error. Should not reach this code");
|
channelArrayRequester,
|
||||||
ChannelArrayLocalPtr channelArray;
|
pvArray,
|
||||||
ArrayConstPtr array;
|
pvCopy,
|
||||||
channelArrayRequester->channelArrayConnect(status,channelArray,array);
|
pvRecord));
|
||||||
return channelArray;
|
if(pvRecord->getTraceLevel()>0)
|
||||||
|
{
|
||||||
|
cout << "ChannelArrayLocal::create";
|
||||||
|
cout << " recordName " << pvRecord->getRecordName() << endl;
|
||||||
|
}
|
||||||
|
channelArrayRequester->channelArrayConnect(
|
||||||
|
Status::Ok, array, pvCopy->getArray());
|
||||||
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1021,7 +986,7 @@ void ChannelArrayLocal::putArray(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t newLength = offset + count*stride;
|
size_t newLength = offset + count*stride;
|
||||||
pvArray->setLength(newLength);
|
if(newLength<pvArray->getLength()) pvArray->setLength(newLength);
|
||||||
const char *exceptionMessage = NULL;
|
const char *exceptionMessage = NULL;
|
||||||
pvRecord->lock();
|
pvRecord->lock();
|
||||||
try {
|
try {
|
||||||
@@ -1040,12 +1005,10 @@ void ChannelArrayLocal::putArray(
|
|||||||
void ChannelArrayLocal::getLength()
|
void ChannelArrayLocal::getLength()
|
||||||
{
|
{
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
size_t capacity = 0;
|
|
||||||
const char *exceptionMessage = NULL;
|
const char *exceptionMessage = NULL;
|
||||||
pvRecord->lock();
|
pvRecord->lock();
|
||||||
try {
|
try {
|
||||||
length = pvArray->getLength();
|
length = pvArray->getLength();
|
||||||
capacity = pvArray->getCapacity();
|
|
||||||
} catch(std::exception e) {
|
} catch(std::exception e) {
|
||||||
exceptionMessage = e.what();
|
exceptionMessage = e.what();
|
||||||
}
|
}
|
||||||
@@ -1054,10 +1017,10 @@ void ChannelArrayLocal::getLength()
|
|||||||
if(exceptionMessage!=NULL) {
|
if(exceptionMessage!=NULL) {
|
||||||
status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
|
status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
|
||||||
}
|
}
|
||||||
channelArrayRequester->getLengthDone(status,getPtrSelf(),length,capacity);
|
channelArrayRequester->getLengthDone(status,getPtrSelf(),length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelArrayLocal::setLength(size_t length, size_t capacity)
|
void ChannelArrayLocal::setLength(size_t length)
|
||||||
{
|
{
|
||||||
if(isDestroyed) {
|
if(isDestroyed) {
|
||||||
channelArrayRequester->setLengthDone(channelDestroyedStatus,getPtrSelf());
|
channelArrayRequester->setLengthDone(channelDestroyedStatus,getPtrSelf());
|
||||||
@@ -1069,17 +1032,6 @@ void ChannelArrayLocal::setLength(size_t length, size_t capacity)
|
|||||||
}
|
}
|
||||||
pvRecord->lock();
|
pvRecord->lock();
|
||||||
try {
|
try {
|
||||||
if(capacity>=0 && !pvArray->isCapacityMutable()) {
|
|
||||||
Status status(
|
|
||||||
Status::STATUSTYPE_ERROR,
|
|
||||||
"capacityImnutable");
|
|
||||||
channelArrayRequester->setLengthDone(status,getPtrSelf());
|
|
||||||
pvRecord->unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(capacity>=0) {
|
|
||||||
if(pvArray->getCapacity()!=capacity) pvArray->setCapacity(capacity);
|
|
||||||
}
|
|
||||||
if(length>=0) {
|
if(length>=0) {
|
||||||
if(pvArray->getLength()!=length) pvArray->setLength(length);
|
if(pvArray->getLength()!=length) pvArray->setLength(length);
|
||||||
}
|
}
|
||||||
@@ -1092,23 +1044,6 @@ void ChannelArrayLocal::setLength(size_t length, size_t capacity)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ChannelRPCLocal :
|
|
||||||
public ChannelRPC
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
POINTER_DEFINITIONS(ChannelRPCLocal);
|
|
||||||
virtual ~ChannelRPCLocal();
|
|
||||||
static ChannelRPC::shared_pointer create(
|
|
||||||
ChannelProviderLocalPtr const &channelProvider,
|
|
||||||
ChannelRPC::shared_pointer const & channelRPCRequester,
|
|
||||||
PVStructurePtr const & pvRequest,
|
|
||||||
PVRecordPtr const &pvRecord);
|
|
||||||
virtual void request(
|
|
||||||
PVStructurePtr const & pvArgument,
|
|
||||||
bool lastRequest);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
ChannelLocal::ChannelLocal(
|
ChannelLocal::ChannelLocal(
|
||||||
ChannelProviderLocalPtr const & provider,
|
ChannelProviderLocalPtr const & provider,
|
||||||
ChannelRequester::shared_pointer const & requester,
|
ChannelRequester::shared_pointer const & requester,
|
||||||
@@ -1170,6 +1105,8 @@ string ChannelLocal::getRemoteAddress()
|
|||||||
|
|
||||||
Channel::ConnectionState ChannelLocal::getConnectionState()
|
Channel::ConnectionState ChannelLocal::getConnectionState()
|
||||||
{
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
if(beingDestroyed) return Channel::DESTROYED;
|
||||||
return Channel::CONNECTED;
|
return Channel::CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1185,6 +1122,8 @@ ChannelRequester::shared_pointer ChannelLocal::getChannelRequester()
|
|||||||
|
|
||||||
bool ChannelLocal::isConnected()
|
bool ChannelLocal::isConnected()
|
||||||
{
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
if(beingDestroyed) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1199,7 +1138,7 @@ void ChannelLocal::getField(GetFieldRequester::shared_pointer const &requester,
|
|||||||
}
|
}
|
||||||
PVFieldPtr pvField =
|
PVFieldPtr pvField =
|
||||||
pvRecord->getPVRecordStructure()->getPVStructure()->getSubField(subField);
|
pvRecord->getPVRecordStructure()->getPVStructure()->getSubField(subField);
|
||||||
if(pvField.get()!=NULL) {
|
if(pvField) {
|
||||||
requester->getDone(Status::Ok,pvField->getField());
|
requester->getDone(Status::Ok,pvField->getField());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1308,7 +1247,7 @@ void ChannelLocal::printInfo()
|
|||||||
|
|
||||||
void ChannelLocal::printInfo(std::ostream& out)
|
void ChannelLocal::printInfo(std::ostream& out)
|
||||||
{
|
{
|
||||||
out << "ChannelLocal provides access to service";
|
out << "ChannelLocal provides access to a record in the local PVDatabase";
|
||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -71,8 +71,10 @@ ChannelProviderLocalPtr getChannelProviderLocal()
|
|||||||
if(channelProviderLocal.get()==NULL) {
|
if(channelProviderLocal.get()==NULL) {
|
||||||
channelProviderLocal = ChannelProviderLocalPtr(
|
channelProviderLocal = ChannelProviderLocalPtr(
|
||||||
new ChannelProviderLocal());
|
new ChannelProviderLocal());
|
||||||
ChannelProvider::shared_pointer xxx = dynamic_pointer_cast<ChannelProvider>(channelProviderLocal);
|
ChannelProvider::shared_pointer xxx =
|
||||||
channelProviderLocal->channelFinder = SyncChannelFind::shared_pointer(new SyncChannelFind(xxx));
|
dynamic_pointer_cast<ChannelProvider>(channelProviderLocal);
|
||||||
|
channelProviderLocal->channelFinder =
|
||||||
|
SyncChannelFind::shared_pointer(new SyncChannelFind(xxx));
|
||||||
LocalChannelProviderFactory::create(channelProviderLocal);
|
LocalChannelProviderFactory::create(channelProviderLocal);
|
||||||
}
|
}
|
||||||
return channelProviderLocal;
|
return channelProviderLocal;
|
||||||
@@ -86,12 +88,12 @@ ChannelProviderLocal::ChannelProviderLocal()
|
|||||||
|
|
||||||
ChannelProviderLocal::~ChannelProviderLocal()
|
ChannelProviderLocal::~ChannelProviderLocal()
|
||||||
{
|
{
|
||||||
cout << "~ChannelProviderLocal()" << endl;
|
// TODO should I call destroy() here
|
||||||
|
destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelProviderLocal::destroy()
|
void ChannelProviderLocal::destroy()
|
||||||
{
|
{
|
||||||
cout << "ChannelProviderLocal::destroy()" << endl;
|
|
||||||
Lock xx(mutex);
|
Lock xx(mutex);
|
||||||
if(beingDestroyed) return;
|
if(beingDestroyed) return;
|
||||||
beingDestroyed = true;
|
beingDestroyed = true;
|
||||||
@@ -170,4 +172,47 @@ Channel::shared_pointer ChannelProviderLocal::createChannel(
|
|||||||
return Channel::shared_pointer();
|
return Channel::shared_pointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ContextLocal::shared_pointer ContextLocal::create()
|
||||||
|
{
|
||||||
|
return ContextLocal::shared_pointer(new ContextLocal());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContextLocal::start(bool _waitForExit)
|
||||||
|
{
|
||||||
|
m_context = startPVAServer(
|
||||||
|
PVACCESS_ALL_PROVIDERS,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
true);
|
||||||
|
|
||||||
|
if (_waitForExit)
|
||||||
|
waitForExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContextLocal::waitForExit()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
std::cout << "Type 'exit' to stop: ";
|
||||||
|
std::string input;
|
||||||
|
std::cin >> input;
|
||||||
|
if (input == "exit")
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContextLocal::destroy()
|
||||||
|
{
|
||||||
|
if (m_context)
|
||||||
|
m_context->destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
ContextLocal::ContextLocal()
|
||||||
|
{
|
||||||
|
m_channelProvider = getChannelProviderLocal();
|
||||||
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -22,21 +22,21 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include <shareLib.h>
|
|
||||||
|
|
||||||
#include <pv/lock.h>
|
#include <pv/lock.h>
|
||||||
#include <pv/pvType.h>
|
#include <pv/pvType.h>
|
||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
#include <pv/monitorPlugin.h>
|
|
||||||
#include <pv/pvCopy.h>
|
#include <pv/pvCopy.h>
|
||||||
#include <pv/pvAccess.h>
|
#include <pv/pvAccess.h>
|
||||||
#include <pv/status.h>
|
#include <pv/status.h>
|
||||||
|
#include <pv/serverContext.h>
|
||||||
|
|
||||||
#ifdef channelProviderLocalEpicsExportSharedSymbols
|
#ifdef channelProviderLocalEpicsExportSharedSymbols
|
||||||
# define epicsExportSharedSymbols
|
# define epicsExportSharedSymbols
|
||||||
# undef channelProviderLocalEpicsExportSharedSymbols
|
# undef channelProviderLocalEpicsExportSharedSymbols
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <shareLib.h>
|
||||||
|
|
||||||
#include <pv/pvDatabase.h>
|
#include <pv/pvDatabase.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -57,12 +57,34 @@ typedef std::tr1::shared_ptr<ChannelLocal> ChannelLocalPtr;
|
|||||||
|
|
||||||
epicsShareExtern MonitorFactoryPtr getMonitorFactory();
|
epicsShareExtern MonitorFactoryPtr getMonitorFactory();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief MonitorFactory
|
||||||
|
*
|
||||||
|
* This class provides a static method to create a monitor for a PVRecord
|
||||||
|
*/
|
||||||
class epicsShareClass MonitorFactory
|
class epicsShareClass MonitorFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(MonitorFactory);
|
POINTER_DEFINITIONS(MonitorFactory);
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
virtual ~MonitorFactory();
|
virtual ~MonitorFactory();
|
||||||
|
/**
|
||||||
|
* Destroy the monitor factory.
|
||||||
|
*/
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
|
/**
|
||||||
|
* Create a monitor on a record.
|
||||||
|
* This is called by the local channel provider.
|
||||||
|
* @param pvRecord The record to monitor.
|
||||||
|
* @param monitorRequester The client callback.
|
||||||
|
* @param pvRequest Options specified by the client.
|
||||||
|
* This includes the subset of the fields in the record to monitor.
|
||||||
|
* @return A shared pointer to the newly created monitor.
|
||||||
|
* If the monitor can not be created a null monitor is returned.
|
||||||
|
* This means the pvRequest specified options that could not be satisfied.
|
||||||
|
*/
|
||||||
epics::pvData::MonitorPtr createMonitor(
|
epics::pvData::MonitorPtr createMonitor(
|
||||||
PVRecordPtr const & pvRecord,
|
PVRecordPtr const & pvRecord,
|
||||||
epics::pvData::MonitorRequester::shared_pointer const & monitorRequester,
|
epics::pvData::MonitorRequester::shared_pointer const & monitorRequester,
|
||||||
@@ -78,24 +100,81 @@ private:
|
|||||||
|
|
||||||
epicsShareExtern ChannelProviderLocalPtr getChannelProviderLocal();
|
epicsShareExtern ChannelProviderLocalPtr getChannelProviderLocal();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ChannelProvider for PVDatabase.
|
||||||
|
*
|
||||||
|
* An implementation of channelProvider that provides access to records in PVDatabase.
|
||||||
|
*/
|
||||||
class epicsShareClass ChannelProviderLocal :
|
class epicsShareClass ChannelProviderLocal :
|
||||||
public epics::pvAccess::ChannelProvider,
|
public epics::pvAccess::ChannelProvider,
|
||||||
public std::tr1::enable_shared_from_this<ChannelProviderLocal>
|
public std::tr1::enable_shared_from_this<ChannelProviderLocal>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(ChannelProviderLocal);
|
POINTER_DEFINITIONS(ChannelProviderLocal);
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
virtual ~ChannelProviderLocal();
|
virtual ~ChannelProviderLocal();
|
||||||
|
/**
|
||||||
|
* Destroy the channel provider.
|
||||||
|
* Probably never called.
|
||||||
|
*/
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
|
/**
|
||||||
|
* Returns the channel provider name.
|
||||||
|
* @return <b>local</b>
|
||||||
|
*/
|
||||||
virtual std::string getProviderName();
|
virtual std::string getProviderName();
|
||||||
|
/**
|
||||||
|
* Returns either a null channelFind or a channelFind for records in the PVDatabase.
|
||||||
|
* @param channelName The name of the channel desired.
|
||||||
|
* @param channelFindRequester The client callback.
|
||||||
|
* @return shared pointer to ChannelFind.
|
||||||
|
* This is null if the channelName is not the name of a record in the PVDatabase.
|
||||||
|
* It is an implementation of SyncChannelFind if the channelName is the name
|
||||||
|
* of a record in the PVDatabase.
|
||||||
|
* The interface for SyncChannelFind is defined by pvAccessCPP.
|
||||||
|
* The channelFindResult method of channelFindRequester is called before the
|
||||||
|
* method returns.
|
||||||
|
*/
|
||||||
virtual epics::pvAccess::ChannelFind::shared_pointer channelFind(
|
virtual epics::pvAccess::ChannelFind::shared_pointer channelFind(
|
||||||
std::string const &channelName,
|
std::string const &channelName,
|
||||||
epics::pvAccess::ChannelFindRequester::shared_pointer const & channelFindRequester);
|
epics::pvAccess::ChannelFindRequester::shared_pointer const & channelFindRequester);
|
||||||
|
/**
|
||||||
|
* Calls method channelListRequester::channelListResult which provides the
|
||||||
|
* caller with a list of the record names on the PVDatabase.
|
||||||
|
* A record name is the same as a channel name.
|
||||||
|
* @param channelListRequester The client callback.
|
||||||
|
* @return shared pointer to ChannelFind.
|
||||||
|
* The interface for SyncChannelFind is defined by pvAccessCPP.
|
||||||
|
*/
|
||||||
virtual epics::pvAccess::ChannelFind::shared_pointer channelList(
|
virtual epics::pvAccess::ChannelFind::shared_pointer channelList(
|
||||||
epics::pvAccess::ChannelListRequester::shared_pointer const & channelListRequester);
|
epics::pvAccess::ChannelListRequester::shared_pointer const & channelListRequester);
|
||||||
|
/**
|
||||||
|
* Create a channel for a record.
|
||||||
|
* This method just calls the next method with a address of "".
|
||||||
|
* @param channelName The name of the channel desired.
|
||||||
|
* @param channelRequester The client callback.
|
||||||
|
* @param priority The priority.
|
||||||
|
* @return shared pointer to Channel.
|
||||||
|
*/
|
||||||
virtual epics::pvAccess::Channel::shared_pointer createChannel(
|
virtual epics::pvAccess::Channel::shared_pointer createChannel(
|
||||||
std::string const &channelName,
|
std::string const &channelName,
|
||||||
epics::pvAccess::ChannelRequester::shared_pointer const &channelRequester,
|
epics::pvAccess::ChannelRequester::shared_pointer const &channelRequester,
|
||||||
short priority);
|
short priority);
|
||||||
|
/**
|
||||||
|
* Create a channel for a record.
|
||||||
|
* @param channelName The name of the channel desired.
|
||||||
|
* @param channelRequester The callback to call with the result.
|
||||||
|
* @param priority The priority.
|
||||||
|
* This is ignored.
|
||||||
|
* @param address The address.
|
||||||
|
* This is ignored.
|
||||||
|
* @return shared pointer to Channel.
|
||||||
|
* This is null if the channelName is not the name of a record in the PVDatabase.
|
||||||
|
* Otherwise it is a newly created channel inteface.
|
||||||
|
* ChannelRequester::channelCreated is called to give the result.
|
||||||
|
*/
|
||||||
virtual epics::pvAccess::Channel::shared_pointer createChannel(
|
virtual epics::pvAccess::Channel::shared_pointer createChannel(
|
||||||
std::string const &channelName,
|
std::string const &channelName,
|
||||||
epics::pvAccess::ChannelRequester::shared_pointer const &channelRequester,
|
epics::pvAccess::ChannelRequester::shared_pointer const &channelRequester,
|
||||||
@@ -115,6 +194,12 @@ private:
|
|||||||
friend class ChannelProviderLocalRun;
|
friend class ChannelProviderLocalRun;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Channel for accessing a PVRecord.
|
||||||
|
*
|
||||||
|
* A Channel for accessing a record in the PVDatabase.
|
||||||
|
* It is a complete implementation of Channel
|
||||||
|
*/
|
||||||
class epicsShareClass ChannelLocal :
|
class epicsShareClass ChannelLocal :
|
||||||
public epics::pvAccess::Channel,
|
public epics::pvAccess::Channel,
|
||||||
public PVRecordClient,
|
public PVRecordClient,
|
||||||
@@ -122,54 +207,185 @@ class epicsShareClass ChannelLocal :
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(ChannelLocal);
|
POINTER_DEFINITIONS(ChannelLocal);
|
||||||
|
/** Constructor
|
||||||
|
* @param channelProvider The channel provider.
|
||||||
|
* @param requester The client callback.
|
||||||
|
* @param pvRecord The record the channel will access.
|
||||||
|
*/
|
||||||
ChannelLocal(
|
ChannelLocal(
|
||||||
ChannelProviderLocalPtr const &channelProvider,
|
ChannelProviderLocalPtr const &channelProvider,
|
||||||
epics::pvAccess::ChannelRequester::shared_pointer const & requester,
|
epics::pvAccess::ChannelRequester::shared_pointer const & requester,
|
||||||
PVRecordPtr const & pvRecord
|
PVRecordPtr const & pvRecord
|
||||||
);
|
);
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
virtual ~ChannelLocal();
|
virtual ~ChannelLocal();
|
||||||
|
/**
|
||||||
|
* Destroy the channel.
|
||||||
|
* It cleans up all resources used to access the record.
|
||||||
|
* Note that this assumes that client has destroyed any objects that
|
||||||
|
* have been created for the channel like channelGet, etc.
|
||||||
|
* The remote pvAccess server does this cleanup.
|
||||||
|
*/
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
|
/**
|
||||||
|
* Get the requester name.
|
||||||
|
* @param returns the name of the channel requester.
|
||||||
|
*/
|
||||||
virtual std::string getRequesterName();
|
virtual std::string getRequesterName();
|
||||||
|
/**
|
||||||
|
* Passes the message to the channel requester.
|
||||||
|
* @param message The message.
|
||||||
|
* @param messageType The message type.
|
||||||
|
*/
|
||||||
virtual void message(
|
virtual void message(
|
||||||
std::string const & message,
|
std::string const & message,
|
||||||
epics::pvData::MessageType messageType);
|
epics::pvData::MessageType messageType);
|
||||||
|
/**
|
||||||
|
* Get the channel provider
|
||||||
|
* @return The provider.
|
||||||
|
*/
|
||||||
virtual epics::pvAccess::ChannelProvider::shared_pointer getProvider()
|
virtual epics::pvAccess::ChannelProvider::shared_pointer getProvider()
|
||||||
{
|
{
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Get the remote address
|
||||||
|
* @return <b>local</b>
|
||||||
|
*/
|
||||||
virtual std::string getRemoteAddress();
|
virtual std::string getRemoteAddress();
|
||||||
|
/**
|
||||||
|
* Get the connection state.
|
||||||
|
* @return Channel::CONNECTED.
|
||||||
|
*/
|
||||||
virtual epics::pvAccess::Channel::ConnectionState getConnectionState();
|
virtual epics::pvAccess::Channel::ConnectionState getConnectionState();
|
||||||
|
/**
|
||||||
|
* Get the channel name.
|
||||||
|
* @return the record name.
|
||||||
|
*/
|
||||||
virtual std::string getChannelName();
|
virtual std::string getChannelName();
|
||||||
|
/**
|
||||||
|
* Get the channel requester
|
||||||
|
* @return The channel requester.
|
||||||
|
*/
|
||||||
virtual epics::pvAccess::ChannelRequester::shared_pointer getChannelRequester();
|
virtual epics::pvAccess::ChannelRequester::shared_pointer getChannelRequester();
|
||||||
|
/**
|
||||||
|
* Is the channel connected?
|
||||||
|
* @return true
|
||||||
|
*/
|
||||||
virtual bool isConnected();
|
virtual bool isConnected();
|
||||||
|
/**
|
||||||
|
* Get the introspection interface for subField.
|
||||||
|
* The introspection interface is given via GetFieldRequester::getDone.
|
||||||
|
* @param requester The client callback.
|
||||||
|
* @param The subField of the record.
|
||||||
|
* If an empty string then the interface for the top level structure of
|
||||||
|
* the record is provided.
|
||||||
|
*/
|
||||||
virtual void getField(
|
virtual void getField(
|
||||||
epics::pvAccess::GetFieldRequester::shared_pointer const &requester,
|
epics::pvAccess::GetFieldRequester::shared_pointer const &requester,
|
||||||
std::string const & subField);
|
std::string const & subField);
|
||||||
|
/**
|
||||||
|
* Get the access rights for the record.
|
||||||
|
* This throws an exception because it is assumed that access rights are
|
||||||
|
* handled by a higher level.
|
||||||
|
*/
|
||||||
virtual epics::pvAccess::AccessRights getAccessRights(
|
virtual epics::pvAccess::AccessRights getAccessRights(
|
||||||
epics::pvData::PVField::shared_pointer const &pvField);
|
epics::pvData::PVField::shared_pointer const &pvField);
|
||||||
|
/**
|
||||||
|
* Create a channelProcess.
|
||||||
|
* See pvAccess.html for details.
|
||||||
|
* @param requester The client callback.
|
||||||
|
* @param pvRequest The options specified by the client.
|
||||||
|
* @return A shared pointer to the newly created implementation.
|
||||||
|
* The implementation is null if pvRequest has invalid options.
|
||||||
|
*/
|
||||||
virtual epics::pvAccess::ChannelProcess::shared_pointer createChannelProcess(
|
virtual epics::pvAccess::ChannelProcess::shared_pointer createChannelProcess(
|
||||||
epics::pvAccess::ChannelProcessRequester::shared_pointer const &requester,
|
epics::pvAccess::ChannelProcessRequester::shared_pointer const &requester,
|
||||||
epics::pvData::PVStructurePtr const &pvRequest);
|
epics::pvData::PVStructurePtr const &pvRequest);
|
||||||
|
/**
|
||||||
|
* Create a channelGet.
|
||||||
|
* See pvAccess.html for details.
|
||||||
|
* @param requester The client callback.
|
||||||
|
* @param pvRequest The options specified by the client.
|
||||||
|
* @return A shared pointer to the newly created implementation.
|
||||||
|
* The implementation is null if pvRequest has invalid options.
|
||||||
|
*/
|
||||||
virtual epics::pvAccess::ChannelGet::shared_pointer createChannelGet(
|
virtual epics::pvAccess::ChannelGet::shared_pointer createChannelGet(
|
||||||
epics::pvAccess::ChannelGetRequester::shared_pointer const &requester,
|
epics::pvAccess::ChannelGetRequester::shared_pointer const &requester,
|
||||||
epics::pvData::PVStructurePtr const &pvRequest);
|
epics::pvData::PVStructurePtr const &pvRequest);
|
||||||
|
/**
|
||||||
|
* Create a channelPut.
|
||||||
|
* See pvAccess.html for details.
|
||||||
|
* @param requester The client callback.
|
||||||
|
* @param pvRequest The options specified by the client.
|
||||||
|
* @return A shared pointer to the newly created implementation.
|
||||||
|
* The implementation is null if pvRequest has invalid options.
|
||||||
|
*/
|
||||||
virtual epics::pvAccess::ChannelPut::shared_pointer createChannelPut(
|
virtual epics::pvAccess::ChannelPut::shared_pointer createChannelPut(
|
||||||
epics::pvAccess::ChannelPutRequester::shared_pointer const &requester,
|
epics::pvAccess::ChannelPutRequester::shared_pointer const &requester,
|
||||||
epics::pvData::PVStructurePtr const &pvRequest);
|
epics::pvData::PVStructurePtr const &pvRequest);
|
||||||
|
/**
|
||||||
|
* Create a channelPutGet.
|
||||||
|
* See pvAccess.html for details.
|
||||||
|
* @param requester The client callback.
|
||||||
|
* @param pvRequest The options specified by the client.
|
||||||
|
* @return A shared pointer to the newly created implementation.
|
||||||
|
* The implementation is null if pvRequest has invalid options.
|
||||||
|
*/
|
||||||
virtual epics::pvAccess::ChannelPutGet::shared_pointer createChannelPutGet(
|
virtual epics::pvAccess::ChannelPutGet::shared_pointer createChannelPutGet(
|
||||||
epics::pvAccess::ChannelPutGetRequester::shared_pointer const &requester,
|
epics::pvAccess::ChannelPutGetRequester::shared_pointer const &requester,
|
||||||
epics::pvData::PVStructurePtr const &pvRequest);
|
epics::pvData::PVStructurePtr const &pvRequest);
|
||||||
|
/**
|
||||||
|
* Create a channelRPC.
|
||||||
|
* This is not implemented because pvAccessCPP implements channelRPC.
|
||||||
|
* The server side of remote pvAccess implements a channel provider
|
||||||
|
* just for channelRPC.
|
||||||
|
* @param requester The client callback
|
||||||
|
* @param pvRequest The options specified by the client.
|
||||||
|
* @return null.
|
||||||
|
*/
|
||||||
virtual epics::pvAccess::ChannelRPC::shared_pointer createChannelRPC(
|
virtual epics::pvAccess::ChannelRPC::shared_pointer createChannelRPC(
|
||||||
epics::pvAccess::ChannelRPCRequester::shared_pointer const &requester,
|
epics::pvAccess::ChannelRPCRequester::shared_pointer const &requester,
|
||||||
epics::pvData::PVStructurePtr const &pvRequest);
|
epics::pvData::PVStructurePtr const &pvRequest);
|
||||||
|
/**
|
||||||
|
* Create a monitor.
|
||||||
|
* See pvAccess.html for details.
|
||||||
|
* @param requester The client callback.
|
||||||
|
* @param pvRequest The options specified by the client.
|
||||||
|
* @return A shared pointer to the newly created implementation.
|
||||||
|
* The implementation is null if pvRequest has invalid options.
|
||||||
|
*/
|
||||||
virtual epics::pvData::Monitor::shared_pointer createMonitor(
|
virtual epics::pvData::Monitor::shared_pointer createMonitor(
|
||||||
epics::pvData::MonitorRequester::shared_pointer const &requester,
|
epics::pvData::MonitorRequester::shared_pointer const &requester,
|
||||||
epics::pvData::PVStructurePtr const &pvRequest);
|
epics::pvData::PVStructurePtr const &pvRequest);
|
||||||
|
/**
|
||||||
|
* Create a channelArray.
|
||||||
|
* See pvAccess.html for details.
|
||||||
|
* @param requester The client callback.
|
||||||
|
* @param pvRequest The options specified by the client.
|
||||||
|
* @return A shared pointer to the newly created implementation.
|
||||||
|
* The implementation is null if pvRequest has invalid options.
|
||||||
|
*/
|
||||||
virtual epics::pvAccess::ChannelArray::shared_pointer createChannelArray(
|
virtual epics::pvAccess::ChannelArray::shared_pointer createChannelArray(
|
||||||
epics::pvAccess::ChannelArrayRequester::shared_pointer const &requester,
|
epics::pvAccess::ChannelArrayRequester::shared_pointer const &requester,
|
||||||
epics::pvData::PVStructurePtr const &pvRequest);
|
epics::pvData::PVStructurePtr const &pvRequest);
|
||||||
|
/**
|
||||||
|
* calls printInfo(std::cout);
|
||||||
|
*/
|
||||||
virtual void printInfo();
|
virtual void printInfo();
|
||||||
|
/**
|
||||||
|
* displays a message
|
||||||
|
* "ChannelLocal provides access to a record in the local PVDatabase".
|
||||||
|
* @param out the stream on which the message is displayed.
|
||||||
|
*/
|
||||||
virtual void printInfo(std::ostream& out);
|
virtual void printInfo(std::ostream& out);
|
||||||
|
/**
|
||||||
|
* This is called when a record is being removed from the database.
|
||||||
|
* Calls destroy.
|
||||||
|
* @record The record being destroyed.
|
||||||
|
*/
|
||||||
virtual void detach(PVRecordPtr const &pvRecord);
|
virtual void detach(PVRecordPtr const &pvRecord);
|
||||||
protected:
|
protected:
|
||||||
shared_pointer getPtrSelf()
|
shared_pointer getPtrSelf()
|
||||||
@@ -184,7 +400,44 @@ private:
|
|||||||
epics::pvData::Mutex mutex;
|
epics::pvData::Mutex mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A pvAccess server context that provides
|
||||||
|
* remote access to a local channel providers (i.e. pvDatabase records).
|
||||||
|
*/
|
||||||
|
class epicsShareClass ContextLocal
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
POINTER_DEFINITIONS(ContextLocal);
|
||||||
|
|
||||||
|
static shared_pointer create();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the context thread.
|
||||||
|
* After this is called clients can connect to the server.
|
||||||
|
* @param waitForExit In true then waitForExit() method is called after the server is started.
|
||||||
|
*/
|
||||||
|
void start(bool waitForExit = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits for "exit" to be entered on standard input and calls destroy() before returning.
|
||||||
|
*/
|
||||||
|
void waitForExit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This destroys the context.
|
||||||
|
* All clients will be disconnected.
|
||||||
|
*/
|
||||||
|
void destroy();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ContextLocal();
|
||||||
|
|
||||||
|
ChannelProviderLocalPtr m_channelProvider;
|
||||||
|
epics::pvAccess::ServerContext::shared_pointer m_context;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
#endif /* CHANNELPROVIDERLOCAL_H */
|
#endif /* CHANNELPROVIDERLOCAL_H */
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
#include <pv/pvCopyMonitor.h>
|
|
||||||
#include <pv/channelProviderLocal.h>
|
#include <pv/channelProviderLocal.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
@@ -30,66 +29,27 @@ using std::string;
|
|||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
|
|
||||||
static MonitorPtr nullMonitor;
|
static MonitorPtr nullMonitor;
|
||||||
static MonitorElementPtr NULLMonitorElement;
|
static MonitorElementPtr NULLMonitorElement;
|
||||||
|
static Status failedToCreateMonitorStatus(Status::STATUSTYPE_ERROR,"failed to create monitor");
|
||||||
static Status wasDestroyedStatus(Status::STATUSTYPE_ERROR,"was destroyed");
|
static Status wasDestroyedStatus(Status::STATUSTYPE_ERROR,"was destroyed");
|
||||||
|
static Status alreadyStartedStatus(Status::STATUSTYPE_ERROR,"already started");
|
||||||
|
static Status notStartedStatus(Status::STATUSTYPE_ERROR,"not started");
|
||||||
|
|
||||||
static ConvertPtr convert = getConvert();
|
|
||||||
|
|
||||||
|
|
||||||
class ElementQueue;
|
|
||||||
typedef std::tr1::shared_ptr<ElementQueue> ElementQueuePtr;
|
|
||||||
class MultipleElementQueue;
|
|
||||||
typedef std::tr1::shared_ptr<MultipleElementQueue> MultipleElementQueuePtr;
|
|
||||||
|
|
||||||
class ElementQueue :
|
|
||||||
public Monitor,
|
|
||||||
public std::tr1::enable_shared_from_this<ElementQueue>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
POINTER_DEFINITIONS(ElementQueue);
|
|
||||||
virtual ~ElementQueue(){}
|
|
||||||
virtual bool dataChanged() = 0;
|
|
||||||
protected:
|
|
||||||
ElementQueuePtr getPtrSelf()
|
|
||||||
{
|
|
||||||
return shared_from_this();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef Queue<MonitorElement> MonitorElementQueue;
|
typedef Queue<MonitorElement> MonitorElementQueue;
|
||||||
typedef std::tr1::shared_ptr<MonitorElementQueue> MonitorElementQueuePtr;
|
typedef std::tr1::shared_ptr<MonitorElementQueue> MonitorElementQueuePtr;
|
||||||
|
|
||||||
class MultipleElementQueue :
|
|
||||||
public ElementQueue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
POINTER_DEFINITIONS(MultipleElementQueue);
|
|
||||||
virtual ~MultipleElementQueue(){}
|
|
||||||
MultipleElementQueue(
|
|
||||||
MonitorLocalPtr const &monitorLocal,
|
|
||||||
MonitorElementQueuePtr const &queue,
|
|
||||||
size_t nfields);
|
|
||||||
virtual void destroy(){}
|
|
||||||
virtual Status start();
|
|
||||||
virtual Status stop();
|
|
||||||
virtual bool dataChanged();
|
|
||||||
virtual MonitorElementPtr poll();
|
|
||||||
virtual void release(MonitorElementPtr const &monitorElement);
|
|
||||||
private:
|
|
||||||
std::tr1::weak_ptr<MonitorLocal> monitorLocal;
|
|
||||||
MonitorElementQueuePtr queue;
|
|
||||||
MonitorElementPtr activeElement;
|
|
||||||
bool queueIsFull;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class MonitorLocal :
|
class MonitorLocal :
|
||||||
public Monitor,
|
public Monitor,
|
||||||
public PVCopyMonitorRequester,
|
public PVListener,
|
||||||
public std::tr1::enable_shared_from_this<MonitorLocal>
|
public std::tr1::enable_shared_from_this<MonitorLocal>
|
||||||
{
|
{
|
||||||
|
enum MonitorState {idle,active, destroyed};
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(MonitorLocal);
|
POINTER_DEFINITIONS(MonitorLocal);
|
||||||
virtual ~MonitorLocal();
|
virtual ~MonitorLocal();
|
||||||
@@ -97,15 +57,22 @@ public:
|
|||||||
virtual Status stop();
|
virtual Status stop();
|
||||||
virtual MonitorElementPtr poll();
|
virtual MonitorElementPtr poll();
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
virtual void dataChanged();
|
virtual void detach(PVRecordPtr const & pvRecord){destroy();}
|
||||||
virtual void unlisten();
|
|
||||||
virtual void release(MonitorElementPtr const & monitorElement);
|
virtual void release(MonitorElementPtr const & monitorElement);
|
||||||
|
virtual void dataPut(PVRecordFieldPtr const & pvRecordField);
|
||||||
|
virtual void dataPut(
|
||||||
|
PVRecordStructurePtr const & requested,
|
||||||
|
PVRecordFieldPtr const & pvRecordField);
|
||||||
|
virtual void beginGroupPut(PVRecordPtr const & pvRecord);
|
||||||
|
virtual void endGroupPut(PVRecordPtr const & pvRecord);
|
||||||
|
virtual void unlisten(PVRecordPtr const & pvRecord);
|
||||||
|
MonitorElementPtr getActiveElement();
|
||||||
|
void releaseActiveElement();
|
||||||
bool init(PVStructurePtr const & pvRequest);
|
bool init(PVStructurePtr const & pvRequest);
|
||||||
MonitorLocal(
|
MonitorLocal(
|
||||||
MonitorRequester::shared_pointer const & channelMonitorRequester,
|
MonitorRequester::shared_pointer const & channelMonitorRequester,
|
||||||
PVRecordPtr const &pvRecord);
|
PVRecordPtr const &pvRecord);
|
||||||
PVCopyPtr getPVCopy() { return pvCopy;}
|
PVCopyPtr getPVCopy() { return pvCopy;}
|
||||||
PVCopyMonitorPtr getPVCopyMonitor() { return pvCopyMonitor;}
|
|
||||||
private:
|
private:
|
||||||
MonitorLocalPtr getPtrSelf()
|
MonitorLocalPtr getPtrSelf()
|
||||||
{
|
{
|
||||||
@@ -113,12 +80,14 @@ private:
|
|||||||
}
|
}
|
||||||
MonitorRequester::shared_pointer monitorRequester;
|
MonitorRequester::shared_pointer monitorRequester;
|
||||||
PVRecordPtr pvRecord;
|
PVRecordPtr pvRecord;
|
||||||
bool isDestroyed;
|
MonitorState state;
|
||||||
bool firstMonitor;
|
|
||||||
PVCopyPtr pvCopy;
|
PVCopyPtr pvCopy;
|
||||||
ElementQueuePtr queue;
|
MonitorElementQueuePtr queue;
|
||||||
PVCopyMonitorPtr pvCopyMonitor;
|
MonitorElementPtr activeElement;
|
||||||
|
bool isGroupPut;
|
||||||
|
bool dataChanged;
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
|
Mutex queueMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
MonitorLocal::MonitorLocal(
|
MonitorLocal::MonitorLocal(
|
||||||
@@ -126,8 +95,9 @@ MonitorLocal::MonitorLocal(
|
|||||||
PVRecordPtr const &pvRecord)
|
PVRecordPtr const &pvRecord)
|
||||||
: monitorRequester(channelMonitorRequester),
|
: monitorRequester(channelMonitorRequester),
|
||||||
pvRecord(pvRecord),
|
pvRecord(pvRecord),
|
||||||
isDestroyed(false),
|
state(idle),
|
||||||
firstMonitor(true)
|
isGroupPut(false),
|
||||||
|
dataChanged(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,125 +113,237 @@ void MonitorLocal::destroy()
|
|||||||
{
|
{
|
||||||
if(pvRecord->getTraceLevel()>0)
|
if(pvRecord->getTraceLevel()>0)
|
||||||
{
|
{
|
||||||
cout << "MonitorLocal::destroy " << isDestroyed << endl;
|
cout << "MonitorLocal::destroy state " << state << endl;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Lock xx(mutex);
|
Lock xx(mutex);
|
||||||
if(isDestroyed) return;
|
if(state==destroyed) return;
|
||||||
isDestroyed = true;
|
}
|
||||||
|
if(pvCopy) pvCopy->destroy();
|
||||||
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
state = destroyed;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Lock xx(queueMutex);
|
||||||
|
queue.reset();
|
||||||
}
|
}
|
||||||
unlisten();
|
|
||||||
stop();
|
|
||||||
pvCopyMonitor->destroy();
|
|
||||||
pvCopy->destroy();
|
|
||||||
pvCopyMonitor.reset();
|
|
||||||
queue.reset();
|
|
||||||
pvCopy.reset();
|
pvCopy.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
Status MonitorLocal::start()
|
Status MonitorLocal::start()
|
||||||
{
|
{
|
||||||
Lock xx(mutex);
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
if(pvRecord->getTraceLevel()>0)
|
||||||
{
|
{
|
||||||
cout << "MonitorLocal::start() " << endl;
|
cout << "MonitorLocal::start() " << endl;
|
||||||
}
|
}
|
||||||
if(isDestroyed) return wasDestroyedStatus;
|
{
|
||||||
firstMonitor = true;
|
Lock xx(mutex);
|
||||||
return queue->start();
|
if(state==destroyed) return wasDestroyedStatus;
|
||||||
|
if(state==active) return alreadyStartedStatus;
|
||||||
|
}
|
||||||
|
pvRecord->addListener(getPtrSelf(),pvCopy);
|
||||||
|
pvRecord->lock();
|
||||||
|
try {
|
||||||
|
Lock xx(mutex);
|
||||||
|
state = active;
|
||||||
|
queue->clear();
|
||||||
|
isGroupPut = false;
|
||||||
|
activeElement = queue->getFree();
|
||||||
|
activeElement->changedBitSet->clear();
|
||||||
|
activeElement->overrunBitSet->clear();
|
||||||
|
activeElement->changedBitSet->set(0);
|
||||||
|
releaseActiveElement();
|
||||||
|
pvRecord->unlock();
|
||||||
|
} catch(...) {
|
||||||
|
pvRecord->unlock();
|
||||||
|
}
|
||||||
|
return Status::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status MonitorLocal::stop()
|
Status MonitorLocal::stop()
|
||||||
{
|
{
|
||||||
pvCopyMonitor->stopMonitoring();
|
if(pvRecord->getTraceLevel()>0){
|
||||||
|
cout << "MonitorLocal::stop() " << endl;
|
||||||
|
}
|
||||||
{
|
{
|
||||||
Lock xx(mutex);
|
Lock xx(mutex);
|
||||||
if(pvRecord->getTraceLevel()>0){
|
if(state==destroyed) return wasDestroyedStatus;
|
||||||
cout << "MonitorLocal::stop() " << endl;
|
if(state==idle) return notStartedStatus;
|
||||||
}
|
state = idle;
|
||||||
if(!isDestroyed) queue->stop();
|
}
|
||||||
}
|
pvRecord->removeListener(getPtrSelf(),pvCopy);
|
||||||
return Status::Ok;
|
return Status::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
MonitorElementPtr MonitorLocal::poll()
|
MonitorElementPtr MonitorLocal::poll()
|
||||||
{
|
{
|
||||||
Lock xx(mutex);
|
|
||||||
if(pvRecord->getTraceLevel()>1)
|
if(pvRecord->getTraceLevel()>1)
|
||||||
{
|
{
|
||||||
cout << "MonitorLocal::poll() " << endl;
|
cout << "MonitorLocal::poll() " << endl;
|
||||||
}
|
}
|
||||||
if(isDestroyed) {
|
{
|
||||||
return NULLMonitorElement;
|
Lock xx(queueMutex);
|
||||||
|
if(state!=active) return NULLMonitorElement;
|
||||||
|
return queue->getUsed();
|
||||||
}
|
}
|
||||||
return queue->poll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MonitorLocal::release(MonitorElementPtr const & monitorElement)
|
void MonitorLocal::release(MonitorElementPtr const & monitorElement)
|
||||||
{
|
{
|
||||||
Lock xx(mutex);
|
|
||||||
if(pvRecord->getTraceLevel()>1)
|
if(pvRecord->getTraceLevel()>1)
|
||||||
{
|
{
|
||||||
cout << "MonitorLocal::release() " << endl;
|
cout << "MonitorLocal::release() " << endl;
|
||||||
}
|
}
|
||||||
if(isDestroyed) {
|
{
|
||||||
return;
|
Lock xx(queueMutex);
|
||||||
|
if(state!=active) return;
|
||||||
|
queue->releaseUsed(monitorElement);
|
||||||
}
|
}
|
||||||
queue->release(monitorElement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MonitorLocal::dataChanged()
|
void MonitorLocal::releaseActiveElement()
|
||||||
{
|
{
|
||||||
if(pvRecord->getTraceLevel()>1)
|
if(pvRecord->getTraceLevel()>1)
|
||||||
{
|
{
|
||||||
cout << "MonitorLocal::dataChanged() " "firstMonitor " << firstMonitor << endl;
|
cout << "MonitorLocal::releaseActiveElement() " << endl;
|
||||||
}
|
}
|
||||||
bool getMonitorEvent = false;
|
|
||||||
{
|
{
|
||||||
Lock xx(mutex);
|
Lock xx(queueMutex);
|
||||||
if(isDestroyed) return;
|
if(state!=active) return;
|
||||||
getMonitorEvent = queue->dataChanged();
|
MonitorElementPtr newActive = queue->getFree();
|
||||||
firstMonitor = false;
|
if(!newActive) return;
|
||||||
|
pvCopy->updateCopyFromBitSet(activeElement->pvStructurePtr,activeElement->changedBitSet);
|
||||||
|
BitSetUtil::compress(activeElement->changedBitSet,activeElement->pvStructurePtr);
|
||||||
|
BitSetUtil::compress(activeElement->overrunBitSet,activeElement->pvStructurePtr);
|
||||||
|
queue->setUsed(activeElement);
|
||||||
|
activeElement = newActive;
|
||||||
|
activeElement->changedBitSet->clear();
|
||||||
|
activeElement->overrunBitSet->clear();
|
||||||
}
|
}
|
||||||
if(getMonitorEvent) monitorRequester->monitorEvent(getPtrSelf());
|
monitorRequester->monitorEvent(getPtrSelf());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MonitorLocal::unlisten()
|
void MonitorLocal::dataPut(PVRecordFieldPtr const & pvRecordField)
|
||||||
{
|
{
|
||||||
if(pvRecord->getTraceLevel()>0)
|
if(pvRecord->getTraceLevel()>1)
|
||||||
{
|
{
|
||||||
cout << "MonitorLocal::unlisten() " << endl;
|
cout << "PVCopyMonitor::dataPut(pvRecordField)" << endl;
|
||||||
|
}
|
||||||
|
if(state!=active) return;
|
||||||
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
size_t offset = pvCopy->getCopyOffset(pvRecordField->getPVField());
|
||||||
|
BitSetPtr const &changedBitSet = activeElement->changedBitSet;
|
||||||
|
BitSetPtr const &overrunBitSet = activeElement->overrunBitSet;
|
||||||
|
bool isSet = changedBitSet->get(offset);
|
||||||
|
changedBitSet->set(offset);
|
||||||
|
if(isSet) overrunBitSet->set(offset);
|
||||||
|
dataChanged = true;
|
||||||
|
}
|
||||||
|
if(!isGroupPut) {
|
||||||
|
releaseActiveElement();
|
||||||
|
dataChanged = false;
|
||||||
}
|
}
|
||||||
monitorRequester->unlisten(getPtrSelf());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MonitorLocal::dataPut(
|
||||||
|
PVRecordStructurePtr const & requested,
|
||||||
|
PVRecordFieldPtr const & pvRecordField)
|
||||||
|
{
|
||||||
|
if(pvRecord->getTraceLevel()>1)
|
||||||
|
{
|
||||||
|
cout << "PVCopyMonitor::dataPut(requested,pvRecordField)" << endl;
|
||||||
|
}
|
||||||
|
if(state!=active) return;
|
||||||
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
BitSetPtr const &changedBitSet = activeElement->changedBitSet;
|
||||||
|
BitSetPtr const &overrunBitSet = activeElement->overrunBitSet;
|
||||||
|
size_t offsetCopyRequested = pvCopy->getCopyOffset(
|
||||||
|
requested->getPVField());
|
||||||
|
size_t offset = offsetCopyRequested
|
||||||
|
+ (pvRecordField->getPVField()->getFieldOffset()
|
||||||
|
- requested->getPVField()->getFieldOffset());
|
||||||
|
bool isSet = changedBitSet->get(offset);
|
||||||
|
changedBitSet->set(offset);
|
||||||
|
if(isSet) overrunBitSet->set(offset);
|
||||||
|
dataChanged = true;
|
||||||
|
}
|
||||||
|
if(!isGroupPut) {
|
||||||
|
releaseActiveElement();
|
||||||
|
dataChanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MonitorLocal::beginGroupPut(PVRecordPtr const & pvRecord)
|
||||||
|
{
|
||||||
|
if(pvRecord->getTraceLevel()>1)
|
||||||
|
{
|
||||||
|
cout << "PVCopyMonitor::beginGroupPut()" << endl;
|
||||||
|
}
|
||||||
|
if(state!=active) return;
|
||||||
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
isGroupPut = true;
|
||||||
|
dataChanged = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MonitorLocal::endGroupPut(PVRecordPtr const & pvRecord)
|
||||||
|
{
|
||||||
|
if(pvRecord->getTraceLevel()>1)
|
||||||
|
{
|
||||||
|
cout << "PVCopyMonitor::endGroupPut() dataChanged " << dataChanged << endl;
|
||||||
|
}
|
||||||
|
if(state!=active) return;
|
||||||
|
{
|
||||||
|
Lock xx(mutex);
|
||||||
|
isGroupPut = false;
|
||||||
|
}
|
||||||
|
if(dataChanged) {
|
||||||
|
dataChanged = false;
|
||||||
|
releaseActiveElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MonitorLocal::unlisten(PVRecordPtr const & pvRecord)
|
||||||
|
{
|
||||||
|
if(pvRecord->getTraceLevel()>1)
|
||||||
|
{
|
||||||
|
cout << "PVCopyMonitor::unlisten\n";
|
||||||
|
}
|
||||||
|
pvRecord->removeListener(getPtrSelf(),pvCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool MonitorLocal::init(PVStructurePtr const & pvRequest)
|
bool MonitorLocal::init(PVStructurePtr const & pvRequest)
|
||||||
{
|
{
|
||||||
PVFieldPtr pvField;
|
PVFieldPtr pvField;
|
||||||
PVStructurePtr pvOptions;
|
|
||||||
size_t queueSize = 2;
|
size_t queueSize = 2;
|
||||||
pvField = pvRequest->getSubField("record._options");
|
PVStructurePtr pvOptions = pvRequest->getSubField<PVStructure>("record._options");
|
||||||
if(pvField.get()!=NULL) {
|
if(pvOptions) {
|
||||||
pvOptions = static_pointer_cast<PVStructure>(pvField);
|
PVStringPtr pvString = pvOptions->getSubField<PVString>("queueSize");
|
||||||
pvField = pvOptions->getSubField("queueSize");
|
if(pvString) {
|
||||||
if(pvField.get()!=NULL) {
|
try {
|
||||||
PVStringPtr pvString = pvOptions->getStringField("queueSize");
|
|
||||||
if(pvString.get()!=NULL) {
|
|
||||||
int32 size;
|
int32 size;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << pvString->get();
|
ss << pvString->get();
|
||||||
ss >> size;
|
ss >> size;
|
||||||
queueSize = size;
|
queueSize = size;
|
||||||
|
} catch (...) {
|
||||||
|
monitorRequester->message("queueSize " +pvString->get() + " illegal",errorMessage);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pvField = pvRequest->getSubField("field");
|
pvField = pvRequest->getSubField("field");
|
||||||
if(pvField.get()==NULL) {
|
if(!pvField) {
|
||||||
pvCopy = PVCopy::create(
|
pvCopy = PVCopy::create(
|
||||||
pvRecord->getPVRecordStructure()->getPVStructure(),
|
pvRecord->getPVRecordStructure()->getPVStructure(),
|
||||||
pvRequest,"");
|
pvRequest,"");
|
||||||
if(pvCopy.get()==NULL) {
|
if(!pvCopy) {
|
||||||
monitorRequester->message("illegal pvRequest",errorMessage);
|
monitorRequester->message("illegal pvRequest",errorMessage);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -273,31 +355,21 @@ bool MonitorLocal::init(PVStructurePtr const & pvRequest)
|
|||||||
pvCopy = PVCopy::create(
|
pvCopy = PVCopy::create(
|
||||||
pvRecord->getPVRecordStructure()->getPVStructure(),
|
pvRecord->getPVRecordStructure()->getPVStructure(),
|
||||||
pvRequest,"field");
|
pvRequest,"field");
|
||||||
if(pvCopy.get()==NULL) {
|
if(!pvCopy) {
|
||||||
monitorRequester->message("illegal pvRequest",errorMessage);
|
monitorRequester->message("illegal pvRequest",errorMessage);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pvCopyMonitor = PVCopyMonitor::create(
|
|
||||||
getPtrSelf(),pvRecord,pvCopy);
|
|
||||||
// MARTY MUST IMPLEMENT periodic
|
|
||||||
if(queueSize<2) queueSize = 2;
|
if(queueSize<2) queueSize = 2;
|
||||||
std::vector<MonitorElementPtr> monitorElementArray;
|
std::vector<MonitorElementPtr> monitorElementArray;
|
||||||
monitorElementArray.reserve(queueSize);
|
monitorElementArray.reserve(queueSize);
|
||||||
size_t nfields = 0;
|
|
||||||
for(size_t i=0; i<queueSize; i++) {
|
for(size_t i=0; i<queueSize; i++) {
|
||||||
PVStructurePtr pvStructure = pvCopy->createPVStructure();
|
PVStructurePtr pvStructure = pvCopy->createPVStructure();
|
||||||
if(nfields==0) nfields = pvStructure->getNumberFields();
|
|
||||||
MonitorElementPtr monitorElement(
|
MonitorElementPtr monitorElement(
|
||||||
new MonitorElement(pvStructure));
|
new MonitorElement(pvStructure));
|
||||||
monitorElementArray.push_back(monitorElement);
|
monitorElementArray.push_back(monitorElement);
|
||||||
}
|
}
|
||||||
MonitorElementQueuePtr elementQueue(new MonitorElementQueue(monitorElementArray));
|
queue = MonitorElementQueuePtr(new MonitorElementQueue(monitorElementArray));
|
||||||
queue = MultipleElementQueuePtr(new MultipleElementQueue(
|
|
||||||
getPtrSelf(),
|
|
||||||
elementQueue,
|
|
||||||
nfields));
|
|
||||||
// MARTY MUST IMPLEMENT algorithm
|
|
||||||
monitorRequester->monitorConnect(
|
monitorRequester->monitorConnect(
|
||||||
Status::Ok,
|
Status::Ok,
|
||||||
getPtrSelf(),
|
getPtrSelf(),
|
||||||
@@ -318,7 +390,6 @@ MonitorFactory::~MonitorFactory()
|
|||||||
void MonitorFactory::destroy()
|
void MonitorFactory::destroy()
|
||||||
{
|
{
|
||||||
Lock lock(mutex);
|
Lock lock(mutex);
|
||||||
if(isDestroyed) return;
|
|
||||||
isDestroyed = true;
|
isDestroyed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,7 +406,12 @@ MonitorPtr MonitorFactory::createMonitor(
|
|||||||
MonitorLocalPtr monitor(new MonitorLocal(
|
MonitorLocalPtr monitor(new MonitorLocal(
|
||||||
monitorRequester,pvRecord));
|
monitorRequester,pvRecord));
|
||||||
bool result = monitor->init(pvRequest);
|
bool result = monitor->init(pvRequest);
|
||||||
if(!result) return nullMonitor;
|
if(!result) {
|
||||||
|
MonitorPtr monitor;
|
||||||
|
StructureConstPtr structure;
|
||||||
|
monitorRequester->monitorConnect(failedToCreateMonitorStatus,monitor,structure);
|
||||||
|
return nullMonitor;
|
||||||
|
}
|
||||||
if(pvRecord->getTraceLevel()>0)
|
if(pvRecord->getTraceLevel()>0)
|
||||||
{
|
{
|
||||||
cout << "MonitorFactory::createMonitor";
|
cout << "MonitorFactory::createMonitor";
|
||||||
@@ -345,75 +421,6 @@ MonitorPtr MonitorFactory::createMonitor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MultipleElementQueue::MultipleElementQueue(
|
|
||||||
MonitorLocalPtr const &monitorLocal,
|
|
||||||
MonitorElementQueuePtr const &queue,
|
|
||||||
size_t nfields)
|
|
||||||
: monitorLocal(monitorLocal),
|
|
||||||
queue(queue),
|
|
||||||
queueIsFull(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Status MultipleElementQueue::start()
|
|
||||||
{
|
|
||||||
queue->clear();
|
|
||||||
queueIsFull = false;
|
|
||||||
activeElement = queue->getFree();
|
|
||||||
activeElement->changedBitSet->clear();
|
|
||||||
activeElement->overrunBitSet->clear();
|
|
||||||
MonitorLocalPtr ml = monitorLocal.lock();
|
|
||||||
if(ml==NULL) return wasDestroyedStatus;
|
|
||||||
ml->getPVCopyMonitor()->setMonitorElement(activeElement);
|
|
||||||
ml->getPVCopyMonitor()->startMonitoring();
|
|
||||||
return Status::Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status MultipleElementQueue::stop()
|
|
||||||
{
|
|
||||||
return Status::Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MultipleElementQueue::dataChanged()
|
|
||||||
{
|
|
||||||
MonitorLocalPtr ml = monitorLocal.lock();
|
|
||||||
if(ml==NULL) return false;
|
|
||||||
if(queueIsFull) return false;
|
|
||||||
ml->getPVCopy()->updateCopyFromBitSet(
|
|
||||||
activeElement->pvStructurePtr,activeElement->changedBitSet);
|
|
||||||
BitSetUtil::compress(activeElement->changedBitSet,activeElement->pvStructurePtr);
|
|
||||||
BitSetUtil::compress(activeElement->overrunBitSet,activeElement->pvStructurePtr);
|
|
||||||
queue->setUsed(activeElement);
|
|
||||||
activeElement = queue->getFree();
|
|
||||||
if(activeElement==NULL) {
|
|
||||||
throw std::logic_error("MultipleElementQueue::dataChanged() logic error");
|
|
||||||
}
|
|
||||||
if(queue->getNumberFree()==0) queueIsFull = true;
|
|
||||||
activeElement->changedBitSet->clear();
|
|
||||||
activeElement->overrunBitSet->clear();
|
|
||||||
ml->getPVCopyMonitor()->setMonitorElement(activeElement);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MonitorElementPtr MultipleElementQueue::poll()
|
|
||||||
{
|
|
||||||
MonitorLocalPtr ml = monitorLocal.lock();
|
|
||||||
if(ml==NULL) return MonitorElementPtr();
|
|
||||||
MonitorElementPtr monitorElement = queue->getUsed();
|
|
||||||
if(monitorElement==NULL) return monitorElement;
|
|
||||||
ml->getPVCopyMonitor()->monitorDone(monitorElement);
|
|
||||||
return monitorElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MultipleElementQueue::release(MonitorElementPtr const &element)
|
|
||||||
{
|
|
||||||
queue->releaseUsed(element);
|
|
||||||
if(!queueIsFull) return;
|
|
||||||
queueIsFull = false;
|
|
||||||
if(!activeElement->changedBitSet->isEmpty()) {
|
|
||||||
dataChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MonitorFactoryPtr getMonitorFactory()
|
MonitorFactoryPtr getMonitorFactory()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,309 +0,0 @@
|
|||||||
/* pvCopyMonitor.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 Marty Kraimer
|
|
||||||
* @date 2013.04
|
|
||||||
*/
|
|
||||||
#include <string>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <memory>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <pv/thread.h>
|
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
|
|
||||||
#include <pv/channelProviderLocal.h>
|
|
||||||
#include <pv/pvCopyMonitor.h>
|
|
||||||
|
|
||||||
using namespace epics::pvData;
|
|
||||||
using std::tr1::static_pointer_cast;
|
|
||||||
using std::tr1::dynamic_pointer_cast;
|
|
||||||
using std::size_t;
|
|
||||||
using std::cout;
|
|
||||||
using std::endl;
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
|
||||||
|
|
||||||
struct PVCopyMonitorFieldNode
|
|
||||||
{
|
|
||||||
MonitorPluginPtr monitorPlugin;
|
|
||||||
size_t offset; // in pvCopy
|
|
||||||
};
|
|
||||||
|
|
||||||
PVCopyMonitorPtr PVCopyMonitor::create(
|
|
||||||
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester,
|
|
||||||
PVRecordPtr const &pvRecord,
|
|
||||||
PVCopyPtr const & pvCopy)
|
|
||||||
{
|
|
||||||
PVCopyMonitorPtr pvCopyMonitor( new PVCopyMonitor(
|
|
||||||
pvRecord,pvCopy,pvCopyMonitorRequester));
|
|
||||||
pvCopyMonitor->init(pvRecord->getPVRecordStructure()->getPVStructure());
|
|
||||||
return pvCopyMonitor;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PVCopyMonitor::PVCopyMonitor(
|
|
||||||
PVRecordPtr const &pvRecord,
|
|
||||||
PVCopyPtr const &pvCopy,
|
|
||||||
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester
|
|
||||||
)
|
|
||||||
: pvRecord(pvRecord),
|
|
||||||
pvCopy(pvCopy),
|
|
||||||
pvCopyMonitorRequester(pvCopyMonitorRequester),
|
|
||||||
isGroupPut(false),
|
|
||||||
dataChanged(false),
|
|
||||||
isMonitoring(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PVCopyMonitor::~PVCopyMonitor()
|
|
||||||
{
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "~PVCopyMonitor" << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pvField is in top level structure of PVRecord.
|
|
||||||
void PVCopyMonitor::init(PVFieldPtr const &pvField)
|
|
||||||
{
|
|
||||||
size_t offset = pvCopy->getCopyOffset(pvField);
|
|
||||||
if(offset==string::npos) return;
|
|
||||||
PVStructurePtr pvOptions = pvCopy->getOptions(offset);
|
|
||||||
if(pvOptions!=NULL) {
|
|
||||||
PVStringPtr pvName = pvOptions->getSubField<PVString>("plugin");
|
|
||||||
if(pvName!=NULL) {
|
|
||||||
string pluginName = pvName->get();
|
|
||||||
MonitorPluginManagerPtr manager = MonitorPluginManager::get();
|
|
||||||
MonitorPluginCreatorPtr pluginCreator = manager->findPlugin(pluginName);
|
|
||||||
if(pluginCreator!=NULL) {
|
|
||||||
StructureConstPtr top = pvCopy->getStructure();
|
|
||||||
FieldConstPtr field = pvField->getField();
|
|
||||||
MonitorPluginPtr monitorPlugin = pluginCreator->create(field,top,pvOptions);
|
|
||||||
if(monitorPlugin!=NULL) {
|
|
||||||
PVCopyMonitorFieldNodePtr fieldNode(new PVCopyMonitorFieldNode());
|
|
||||||
fieldNode->monitorPlugin = monitorPlugin;
|
|
||||||
fieldNode->offset = offset;
|
|
||||||
monitorFieldNodeList.push_back(fieldNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(pvField->getField()->getType()!=structure) return;
|
|
||||||
PVStructurePtr pv = static_pointer_cast<PVStructure>(pvField);
|
|
||||||
const PVFieldPtrArray &pvFields = pv->getPVFields();
|
|
||||||
for(size_t i=0; i<pvFields.size(); ++i ) init(pvFields[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
MonitorPluginPtr PVCopyMonitor::getMonitorPlugin(size_t offset)
|
|
||||||
{
|
|
||||||
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
|
|
||||||
for (iter = monitorFieldNodeList.begin();iter!=monitorFieldNodeList.end();++iter)
|
|
||||||
{
|
|
||||||
if((*iter)->offset==offset) return (*iter)->monitorPlugin;
|
|
||||||
}
|
|
||||||
return MonitorPluginPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PVCopyMonitor::destroy()
|
|
||||||
{
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "PVCopyMonitor::destroy()" << endl;
|
|
||||||
}
|
|
||||||
stopMonitoring();
|
|
||||||
pvCopyMonitorRequester.reset();
|
|
||||||
pvCopy.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PVCopyMonitor::startMonitoring()
|
|
||||||
{
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "PVCopyMonitor::startMonitoring()" << endl;
|
|
||||||
}
|
|
||||||
Lock xx(mutex);
|
|
||||||
if(isMonitoring) return;
|
|
||||||
isMonitoring = true;
|
|
||||||
isGroupPut = false;
|
|
||||||
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
|
|
||||||
for (iter = monitorFieldNodeList.begin();iter!=monitorFieldNodeList.end();++iter)
|
|
||||||
{
|
|
||||||
(*iter)->monitorPlugin->startMonitoring();
|
|
||||||
}
|
|
||||||
pvRecord->lock();
|
|
||||||
try {
|
|
||||||
pvRecord->addListener(getPtrSelf());
|
|
||||||
pvCopy->traverseMaster(getPtrSelf());
|
|
||||||
monitorElement->changedBitSet->clear();
|
|
||||||
monitorElement->overrunBitSet->clear();
|
|
||||||
monitorElement->changedBitSet->set(0);
|
|
||||||
pvCopyMonitorRequester->dataChanged();
|
|
||||||
pvRecord->unlock();
|
|
||||||
} catch(...) {
|
|
||||||
pvRecord->unlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PVCopyMonitor::nextMasterPVField(epics::pvData::PVFieldPtr const &pvField)
|
|
||||||
{
|
|
||||||
pvRecord->findPVRecordField(pvField)->addListener(getPtrSelf());
|
|
||||||
}
|
|
||||||
|
|
||||||
void PVCopyMonitor::stopMonitoring()
|
|
||||||
{
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "PVCopyMonitor::stopMonitoring()" << endl;
|
|
||||||
}
|
|
||||||
Lock xx(mutex);
|
|
||||||
if(!isMonitoring) return;
|
|
||||||
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
|
|
||||||
for (iter = monitorFieldNodeList.begin();iter!=monitorFieldNodeList.end();++iter)
|
|
||||||
{
|
|
||||||
(*iter)->monitorPlugin->stopMonitoring();
|
|
||||||
}
|
|
||||||
isMonitoring = false;
|
|
||||||
pvRecord->removeListener(getPtrSelf());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PVCopyMonitor::setMonitorElement(MonitorElementPtr const &xxx)
|
|
||||||
{
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "PVCopyMonitor::setMonitorElement()" << endl;
|
|
||||||
}
|
|
||||||
monitorElement = xxx;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PVCopyMonitor::monitorDone(MonitorElementPtr const &monitorElement)
|
|
||||||
{
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "PVCopyMonitor::monitorDone()" << endl;
|
|
||||||
}
|
|
||||||
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
|
|
||||||
for (iter = monitorFieldNodeList.begin();iter!=monitorFieldNodeList.end();++iter)
|
|
||||||
{
|
|
||||||
PVCopyMonitorFieldNodePtr fieldNode = *iter;
|
|
||||||
MonitorPluginPtr monitorPlugin = fieldNode->monitorPlugin;
|
|
||||||
monitorPlugin->monitorDone(monitorElement);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PVCopyMonitor::detach(PVRecordPtr const & pvRecord)
|
|
||||||
{
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "PVCopyMonitor::detach()" << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PVCopyMonitor::dataPut(PVRecordFieldPtr const & pvRecordField)
|
|
||||||
{
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "PVCopyMonitor::dataPut(pvRecordField)" << endl;
|
|
||||||
}
|
|
||||||
size_t offset = pvCopy->getCopyOffset(pvRecordField->getPVField());
|
|
||||||
BitSetPtr const &changedBitSet = monitorElement->changedBitSet;
|
|
||||||
BitSetPtr const &overrunBitSet = monitorElement->overrunBitSet;
|
|
||||||
bool isSet = changedBitSet->get(offset);
|
|
||||||
changedBitSet->set(offset);
|
|
||||||
if(isSet) overrunBitSet->set(offset);
|
|
||||||
MonitorPluginPtr monitorPlugin = getMonitorPlugin(offset);
|
|
||||||
bool causeMonitor = true;
|
|
||||||
if(monitorPlugin!=NULL) {
|
|
||||||
causeMonitor = monitorPlugin->causeMonitor(
|
|
||||||
pvRecordField->getPVField(),
|
|
||||||
pvRecord->getPVRecordStructure()->getPVStructure(),
|
|
||||||
monitorElement);
|
|
||||||
}
|
|
||||||
if(causeMonitor) {
|
|
||||||
if(!isGroupPut) pvCopyMonitorRequester->dataChanged();
|
|
||||||
dataChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PVCopyMonitor::dataPut(
|
|
||||||
PVRecordStructurePtr const & requested,
|
|
||||||
PVRecordFieldPtr const & pvRecordField)
|
|
||||||
{
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "PVCopyMonitor::dataPut(requested,pvRecordField)" << endl;
|
|
||||||
}
|
|
||||||
BitSetPtr const &changedBitSet = monitorElement->changedBitSet;
|
|
||||||
BitSetPtr const &overrunBitSet = monitorElement->overrunBitSet;
|
|
||||||
size_t offsetCopyRequested = pvCopy->getCopyOffset(
|
|
||||||
requested->getPVField());
|
|
||||||
size_t offset = offsetCopyRequested
|
|
||||||
+ (pvRecordField->getPVField()->getFieldOffset()
|
|
||||||
- requested->getPVField()->getFieldOffset());
|
|
||||||
bool isSet = changedBitSet->get(offset);
|
|
||||||
changedBitSet->set(offset);
|
|
||||||
if(isSet) overrunBitSet->set(offset);
|
|
||||||
MonitorPluginPtr monitorPlugin = getMonitorPlugin(offsetCopyRequested);
|
|
||||||
bool causeMonitor = true;
|
|
||||||
if(monitorPlugin!=NULL) {
|
|
||||||
causeMonitor = monitorPlugin->causeMonitor(
|
|
||||||
requested->getPVField(),
|
|
||||||
pvRecord->getPVRecordStructure()->getPVStructure(),
|
|
||||||
monitorElement);
|
|
||||||
}
|
|
||||||
if(causeMonitor) {
|
|
||||||
if(!isGroupPut) pvCopyMonitorRequester->dataChanged();
|
|
||||||
dataChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PVCopyMonitor::beginGroupPut(PVRecordPtr const & pvRecord)
|
|
||||||
{
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "PVCopyMonitor::beginGroupPut()" << endl;
|
|
||||||
}
|
|
||||||
isGroupPut = true;
|
|
||||||
dataChanged = false;
|
|
||||||
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
|
|
||||||
for (iter = monitorFieldNodeList.begin();
|
|
||||||
iter!=monitorFieldNodeList.end();
|
|
||||||
++iter)
|
|
||||||
{
|
|
||||||
(*iter)->monitorPlugin->beginGroupPut();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PVCopyMonitor::endGroupPut(PVRecordPtr const & pvRecord)
|
|
||||||
{
|
|
||||||
if(pvRecord->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "PVCopyMonitor::endGroupPut() dataChanged " << dataChanged << endl;
|
|
||||||
}
|
|
||||||
isGroupPut = false;
|
|
||||||
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
|
|
||||||
for (iter = monitorFieldNodeList.begin();iter!=monitorFieldNodeList.end();++iter)
|
|
||||||
{
|
|
||||||
(*iter)->monitorPlugin->endGroupPut();
|
|
||||||
}
|
|
||||||
if(dataChanged) {
|
|
||||||
dataChanged = false;
|
|
||||||
pvCopyMonitorRequester->dataChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PVCopyMonitor::unlisten(PVRecordPtr const & pvRecord)
|
|
||||||
{
|
|
||||||
pvCopyMonitorRequester->unlisten();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}}
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
/* pvCopyMonitor.h */
|
|
||||||
/**
|
|
||||||
* 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 Marty Kraimer
|
|
||||||
* @date 2013.04
|
|
||||||
*/
|
|
||||||
#ifndef PVCOPYMONITOR_H
|
|
||||||
#define PVCOPYMONITOR_H
|
|
||||||
|
|
||||||
#ifdef epicsExportSharedSymbols
|
|
||||||
# define pvCopyMonitorEpicsExportSharedSymbols
|
|
||||||
# undef epicsExportSharedSymbols
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <memory>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
#include <shareLib.h>
|
|
||||||
|
|
||||||
#include <pv/monitorPlugin.h>
|
|
||||||
#include <pv/pvCopy.h>
|
|
||||||
#include <pv/pvAccess.h>
|
|
||||||
|
|
||||||
#ifdef pvCopyMonitorEpicsExportSharedSymbols
|
|
||||||
# define epicsExportSharedSymbols
|
|
||||||
# undef pvCopyMonitorEpicsExportSharedSymbols
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <pv/pvDatabase.h>
|
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
|
||||||
|
|
||||||
class PVCopyMonitor;
|
|
||||||
typedef std::tr1::shared_ptr<PVCopyMonitor> PVCopyMonitorPtr;
|
|
||||||
class PVCopyMonitorRequester;
|
|
||||||
typedef std::tr1::shared_ptr<PVCopyMonitorRequester> PVCopyMonitorRequesterPtr;
|
|
||||||
|
|
||||||
struct PVCopyMonitorFieldNode;
|
|
||||||
typedef std::tr1::shared_ptr<PVCopyMonitorFieldNode> PVCopyMonitorFieldNodePtr;
|
|
||||||
|
|
||||||
|
|
||||||
class epicsShareClass PVCopyMonitor :
|
|
||||||
public PVListener,
|
|
||||||
public epics::pvData::PVCopyTraverseMasterCallback,
|
|
||||||
public std::tr1::enable_shared_from_this<PVCopyMonitor>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
POINTER_DEFINITIONS(PVCopyMonitor);
|
|
||||||
static PVCopyMonitorPtr create(
|
|
||||||
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester,
|
|
||||||
PVRecordPtr const &pvRecord,
|
|
||||||
epics::pvData::PVCopyPtr const & pvCopy);
|
|
||||||
virtual ~PVCopyMonitor();
|
|
||||||
virtual void destroy();
|
|
||||||
void startMonitoring();
|
|
||||||
void stopMonitoring();
|
|
||||||
void setMonitorElement(epics::pvData::MonitorElementPtr const &monitorElement);
|
|
||||||
void monitorDone(epics::pvData::MonitorElementPtr const &monitorElement);
|
|
||||||
// following are PVListener methods
|
|
||||||
virtual void detach(PVRecordPtr const & pvRecord);
|
|
||||||
virtual void dataPut(PVRecordFieldPtr const & pvRecordField);
|
|
||||||
virtual void dataPut(
|
|
||||||
PVRecordStructurePtr const & requested,
|
|
||||||
PVRecordFieldPtr const & pvRecordField);
|
|
||||||
virtual void beginGroupPut(PVRecordPtr const & pvRecord);
|
|
||||||
virtual void endGroupPut(PVRecordPtr const & pvRecord);
|
|
||||||
virtual void unlisten(PVRecordPtr const & pvRecord);
|
|
||||||
// following is PVCopyTraverseMasterCallback method
|
|
||||||
virtual void nextMasterPVField(epics::pvData::PVFieldPtr const &pvField);
|
|
||||||
private:
|
|
||||||
PVCopyMonitorPtr getPtrSelf()
|
|
||||||
{
|
|
||||||
return shared_from_this();
|
|
||||||
}
|
|
||||||
PVCopyMonitor(
|
|
||||||
PVRecordPtr const &pvRecord,
|
|
||||||
epics::pvData::PVCopyPtr const &pvCopy,
|
|
||||||
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester);
|
|
||||||
void init(epics::pvData::PVFieldPtr const &pvField);
|
|
||||||
epics::pvData::MonitorPluginPtr getMonitorPlugin(size_t offset);
|
|
||||||
PVRecordPtr pvRecord;
|
|
||||||
epics::pvData::PVCopyPtr pvCopy;
|
|
||||||
PVCopyMonitorRequesterPtr pvCopyMonitorRequester;
|
|
||||||
epics::pvData::MonitorElementPtr monitorElement;
|
|
||||||
bool isGroupPut;
|
|
||||||
bool dataChanged;
|
|
||||||
bool isMonitoring;
|
|
||||||
epics::pvData::Mutex mutex;
|
|
||||||
std::list<PVCopyMonitorFieldNodePtr> monitorFieldNodeList;
|
|
||||||
};
|
|
||||||
|
|
||||||
class epicsShareClass PVCopyMonitorRequester
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
POINTER_DEFINITIONS(PVCopyMonitorRequester);
|
|
||||||
virtual ~PVCopyMonitorRequester() {}
|
|
||||||
virtual void dataChanged() = 0;
|
|
||||||
virtual void unlisten() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
||||||
#endif /* PVCOPYMONITOR_H */
|
|
||||||
@@ -27,12 +27,12 @@
|
|||||||
#include <iocsh.h>
|
#include <iocsh.h>
|
||||||
#include <shareLib.h>
|
#include <shareLib.h>
|
||||||
|
|
||||||
#include <epicsExport.h>
|
|
||||||
|
|
||||||
#include <pv/pvAccess.h>
|
#include <pv/pvAccess.h>
|
||||||
#include <pv/serverContext.h>
|
#include <pv/serverContext.h>
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
// this declared epicsExportSharedSymbols
|
||||||
|
#include <epicsExport.h>
|
||||||
|
|
||||||
#include <pv/channelProviderLocal.h>
|
#include <pv/channelProviderLocal.h>
|
||||||
|
|
||||||
using std::cout;
|
using std::cout;
|
||||||
@@ -44,7 +44,7 @@ using namespace epics::pvDatabase;
|
|||||||
static const iocshFuncDef pvdblFuncDef = {
|
static const iocshFuncDef pvdblFuncDef = {
|
||||||
"pvdbl", 0, 0
|
"pvdbl", 0, 0
|
||||||
};
|
};
|
||||||
extern "C" void epicsShareAPI pvdbl(const iocshArgBuf *args)
|
extern "C" void pvdbl(const iocshArgBuf *args)
|
||||||
{
|
{
|
||||||
PVDatabasePtr master = PVDatabase::getMaster();
|
PVDatabasePtr master = PVDatabase::getMaster();
|
||||||
PVStringArrayPtr pvNames = master->getRecordNames();
|
PVStringArrayPtr pvNames = master->getRecordNames();
|
||||||
|
|||||||
@@ -24,26 +24,16 @@ RecordListRecordPtr RecordListRecord::create(
|
|||||||
{
|
{
|
||||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
StringArray argNames(2);
|
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
||||||
FieldConstPtrArray argFields(2);
|
addNestedStructure("argument")->
|
||||||
argNames[0] = "database";
|
add("database",pvString)->
|
||||||
argFields[0] = fieldCreate->createScalar(pvString);
|
add("regularExpression",pvString)->
|
||||||
argNames[1] = "regularExpression";
|
endNested()->
|
||||||
argFields[1] = fieldCreate->createScalar(pvString);
|
addNestedStructure("result") ->
|
||||||
StringArray resNames(2);
|
add("status",pvString) ->
|
||||||
FieldConstPtrArray resFields(2);
|
addArray("names",pvString) ->
|
||||||
resNames[0] = "status";
|
endNested()->
|
||||||
resFields[0] = fieldCreate->createScalar(pvString);
|
createStructure();
|
||||||
resNames[1] = "names";
|
|
||||||
resFields[1] = fieldCreate->createScalarArray(pvString);
|
|
||||||
StringArray topNames(2);
|
|
||||||
FieldConstPtrArray topFields(2);
|
|
||||||
topNames[0] = "argument";
|
|
||||||
topFields[0] = fieldCreate->createStructure(argNames,argFields);
|
|
||||||
topNames[1] = "result";
|
|
||||||
topFields[1] = fieldCreate->createStructure(resNames,resFields);
|
|
||||||
StructureConstPtr topStructure =
|
|
||||||
fieldCreate->createStructure(topNames,topFields);
|
|
||||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||||
RecordListRecordPtr pvRecord(
|
RecordListRecordPtr pvRecord(
|
||||||
new RecordListRecord(recordName,pvStructure));
|
new RecordListRecord(recordName,pvStructure));
|
||||||
@@ -71,28 +61,27 @@ bool RecordListRecord::init()
|
|||||||
{
|
{
|
||||||
initPVRecord();
|
initPVRecord();
|
||||||
PVStructurePtr pvStructure = getPVStructure();
|
PVStructurePtr pvStructure = getPVStructure();
|
||||||
database = pvStructure->getStringField("argument.database");
|
database = pvStructure->getSubField<PVString>("argument.database");
|
||||||
if(database.get()==NULL) return false;
|
if(database.get()==NULL) return false;
|
||||||
regularExpression = pvStructure->getStringField(
|
regularExpression = pvStructure->getSubField<PVString>(
|
||||||
"argument.regularExpression");
|
"argument.regularExpression");
|
||||||
if(regularExpression.get()==NULL) return false;
|
if(regularExpression.get()==NULL) return false;
|
||||||
status = pvStructure->getStringField("result.status");
|
status = pvStructure->getSubField<PVString>("result.status");
|
||||||
if(status.get()==NULL) return false;
|
if(status.get()==NULL) return false;
|
||||||
PVFieldPtr pvField = pvStructure->getSubField("result.names");
|
PVFieldPtr pvField = pvStructure->getSubField("result.names");
|
||||||
if(pvField.get()==NULL) {
|
if(pvField.get()==NULL) {
|
||||||
std::cerr << "no result.names" << std::endl;
|
std::cerr << "no result.names" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
names = static_pointer_cast<PVStringArray>(
|
name = pvStructure->getSubField<PVStringArray>("result.names");
|
||||||
pvStructure->getScalarArrayField("result.names",pvString));
|
if(name.get()==NULL) return false;
|
||||||
if(names.get()==NULL) return false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordListRecord::process()
|
void RecordListRecord::process()
|
||||||
{
|
{
|
||||||
PVStringArrayPtr pvNames = PVDatabase::getMaster()->getRecordNames();
|
PVStringArrayPtr pvNames = PVDatabase::getMaster()->getRecordNames();
|
||||||
names->replace(pvNames->view());
|
name->replace(pvNames->view());
|
||||||
string message("");
|
string message("");
|
||||||
if(database->get().compare("master")!=0) {
|
if(database->get().compare("master")!=0) {
|
||||||
message += " can only access master ";
|
message += " can only access master ";
|
||||||
|
|||||||
@@ -20,16 +20,43 @@ namespace epics { namespace pvDatabase {
|
|||||||
class RecordListRecord;
|
class RecordListRecord;
|
||||||
typedef std::tr1::shared_ptr<RecordListRecord> RecordListRecordPtr;
|
typedef std::tr1::shared_ptr<RecordListRecord> RecordListRecordPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief List records in PVDatabase.
|
||||||
|
*
|
||||||
|
* @deprecated no longer needed because of pvlist command for pvAccess.
|
||||||
|
*
|
||||||
|
* This is a record that provides a PVStringArray that
|
||||||
|
* has the record names of all records in the local PVDatabase.
|
||||||
|
* It is meant to be used by a channelPutGet request.
|
||||||
|
*/
|
||||||
class epicsShareClass RecordListRecord :
|
class epicsShareClass RecordListRecord :
|
||||||
public PVRecord
|
public PVRecord
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(RecordListRecord);
|
POINTER_DEFINITIONS(RecordListRecord);
|
||||||
|
/**
|
||||||
|
* Factory methods to create RecordListRecord.
|
||||||
|
* @param recordName The name for the RecordListRecord.
|
||||||
|
* @return A shared pointer to RecordListRecord..
|
||||||
|
*/
|
||||||
static RecordListRecordPtr create(
|
static RecordListRecordPtr create(
|
||||||
std::string const & recordName);
|
std::string const & recordName);
|
||||||
|
/**
|
||||||
|
* destructor
|
||||||
|
*/
|
||||||
virtual ~RecordListRecord();
|
virtual ~RecordListRecord();
|
||||||
|
/**
|
||||||
|
* Clean up any resources used.
|
||||||
|
*/
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
|
/**
|
||||||
|
* standard init method required by PVRecord
|
||||||
|
* @return true unless record name already exists.
|
||||||
|
*/
|
||||||
virtual bool init();
|
virtual bool init();
|
||||||
|
/*
|
||||||
|
* Generated the list of record names.
|
||||||
|
*/
|
||||||
virtual void process();
|
virtual void process();
|
||||||
private:
|
private:
|
||||||
RecordListRecord(std::string const & recordName,
|
RecordListRecord(std::string const & recordName,
|
||||||
@@ -37,7 +64,7 @@ private:
|
|||||||
epics::pvData::PVStringPtr database;
|
epics::pvData::PVStringPtr database;
|
||||||
epics::pvData::PVStringPtr regularExpression;
|
epics::pvData::PVStringPtr regularExpression;
|
||||||
epics::pvData::PVStringPtr status;
|
epics::pvData::PVStringPtr status;
|
||||||
epics::pvData::PVStringArrayPtr names;
|
epics::pvData::PVStringArrayPtr name;
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -24,24 +24,15 @@ TraceRecordPtr TraceRecord::create(
|
|||||||
{
|
{
|
||||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
StringArray topNames(2);
|
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
||||||
FieldConstPtrArray topFields(2);
|
addNestedStructure("argument")->
|
||||||
topNames[0] = "argument";
|
add("recordName",pvString)->
|
||||||
topNames[1] = "result";
|
add("level",pvInt)->
|
||||||
StringArray argNames(2);
|
endNested()->
|
||||||
FieldConstPtrArray argFields(2);
|
addNestedStructure("result") ->
|
||||||
argNames[0] = "recordName";
|
add("status",pvString) ->
|
||||||
argNames[1] = "level";
|
endNested()->
|
||||||
argFields[0] = fieldCreate->createScalar(pvString);
|
createStructure();
|
||||||
argFields[1] = fieldCreate->createScalar(pvInt);
|
|
||||||
topFields[0] = fieldCreate->createStructure(argNames,argFields);
|
|
||||||
StringArray resNames(1);
|
|
||||||
FieldConstPtrArray resFields(1);
|
|
||||||
resNames[0] = "status";
|
|
||||||
resFields[0] = fieldCreate->createScalar(pvString);
|
|
||||||
topFields[1] = fieldCreate->createStructure(resNames,resFields);
|
|
||||||
StructureConstPtr topStructure =
|
|
||||||
fieldCreate->createStructure(topNames,topFields);
|
|
||||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||||
TraceRecordPtr pvRecord(
|
TraceRecordPtr pvRecord(
|
||||||
new TraceRecord(recordName,pvStructure));
|
new TraceRecord(recordName,pvStructure));
|
||||||
@@ -71,12 +62,12 @@ bool TraceRecord::init()
|
|||||||
{
|
{
|
||||||
initPVRecord();
|
initPVRecord();
|
||||||
PVStructurePtr pvStructure = getPVStructure();
|
PVStructurePtr pvStructure = getPVStructure();
|
||||||
pvRecordName = pvStructure->getStringField("argument.recordName");
|
pvRecordName = pvStructure->getSubField<PVString>("argument.recordName");
|
||||||
if(pvRecordName==NULL) return false;
|
if(!pvRecordName) return false;
|
||||||
pvLevel = pvStructure->getIntField("argument.level");
|
pvLevel = pvStructure->getSubField<PVInt>("argument.level");
|
||||||
if(pvLevel==NULL) return false;
|
if(!pvLevel) return false;
|
||||||
pvResult = pvStructure->getStringField("result.status");
|
pvResult = pvStructure->getSubField<PVString>("result.status");
|
||||||
if(pvResult==NULL) return false;
|
if(!pvResult) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +75,7 @@ void TraceRecord::process()
|
|||||||
{
|
{
|
||||||
string name = pvRecordName->get();
|
string name = pvRecordName->get();
|
||||||
PVRecordPtr pvRecord = pvDatabase->findRecord(name);
|
PVRecordPtr pvRecord = pvDatabase->findRecord(name);
|
||||||
if(pvRecord==NULL) {
|
if(!pvRecord) {
|
||||||
pvResult->put(name + " not found");
|
pvResult->put(name + " not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,16 +21,42 @@ namespace epics { namespace pvDatabase {
|
|||||||
class TraceRecord;
|
class TraceRecord;
|
||||||
typedef std::tr1::shared_ptr<TraceRecord> TraceRecordPtr;
|
typedef std::tr1::shared_ptr<TraceRecord> TraceRecordPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Trace activity of PVRecord.
|
||||||
|
*
|
||||||
|
* A record to set the trace value for another record
|
||||||
|
* It is meant to be used via a channelPutGet request.
|
||||||
|
* The argument has two fields: recordName and level.
|
||||||
|
* The result has a field named status.
|
||||||
|
*/
|
||||||
class epicsShareClass TraceRecord :
|
class epicsShareClass TraceRecord :
|
||||||
public PVRecord
|
public PVRecord
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(TraceRecord);
|
POINTER_DEFINITIONS(TraceRecord);
|
||||||
|
/**
|
||||||
|
* Factory methods to create TraceRecord.
|
||||||
|
* @param recordName The name for the TraceRecord.
|
||||||
|
* @return A shared pointer to TraceRecord..
|
||||||
|
*/
|
||||||
static TraceRecordPtr create(
|
static TraceRecordPtr create(
|
||||||
std::string const & recordName);
|
std::string const & recordName);
|
||||||
|
/**
|
||||||
|
* destructor
|
||||||
|
*/
|
||||||
virtual ~TraceRecord();
|
virtual ~TraceRecord();
|
||||||
|
/**
|
||||||
|
* Clean up any resources used.
|
||||||
|
*/
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
|
/**
|
||||||
|
* standard init method required by PVRecord
|
||||||
|
* @return true unless record name already exists.
|
||||||
|
*/
|
||||||
virtual bool init();
|
virtual bool init();
|
||||||
|
/**
|
||||||
|
* Set the trace level.
|
||||||
|
*/
|
||||||
virtual void process();
|
virtual void process();
|
||||||
private:
|
private:
|
||||||
TraceRecord(
|
TraceRecord(
|
||||||
|
|||||||
@@ -35,5 +35,5 @@
|
|||||||
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
|
||||||
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
|
||||||
|
|
||||||
-include $(TOP)/configure/CONFIG_SITE.local
|
-include $(TOP)/../../CONFIG_SITE.local
|
||||||
-include $(TOP)/../CONFIG.local
|
-include $(TOP)/../configure/CONFIG_SITE.local
|
||||||
|
|||||||
@@ -9,12 +9,17 @@
|
|||||||
* @date 2013.04.02
|
* @date 2013.04.02
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "powerSupply.h"
|
|
||||||
#include <pv/standardField.h>
|
#include <pv/standardField.h>
|
||||||
#include <pv/standardPVField.h>
|
#include <pv/standardPVField.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
#include "powerSupply.h"
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using std::string;
|
using std::string;
|
||||||
|
using std::cout;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
@@ -24,24 +29,23 @@ PVStructurePtr createPowerSupply()
|
|||||||
StandardFieldPtr standardField = getStandardField();
|
StandardFieldPtr standardField = getStandardField();
|
||||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
|
|
||||||
size_t nfields = 5;
|
|
||||||
StringArray names;
|
|
||||||
names.reserve(nfields);
|
|
||||||
FieldConstPtrArray powerSupply;
|
|
||||||
powerSupply.reserve(nfields);
|
|
||||||
names.push_back("alarm");
|
|
||||||
powerSupply.push_back(standardField->alarm());
|
|
||||||
names.push_back("timeStamp");
|
|
||||||
powerSupply.push_back(standardField->timeStamp());
|
|
||||||
string properties("alarm,display");
|
|
||||||
names.push_back("voltage");
|
|
||||||
powerSupply.push_back(standardField->scalar(pvDouble,properties));
|
|
||||||
names.push_back("power");
|
|
||||||
powerSupply.push_back(standardField->scalar(pvDouble,properties));
|
|
||||||
names.push_back("current");
|
|
||||||
powerSupply.push_back(standardField->scalar(pvDouble,properties));
|
|
||||||
return pvDataCreate->createPVStructure(
|
return pvDataCreate->createPVStructure(
|
||||||
fieldCreate->createStructure(names,powerSupply));
|
fieldCreate->createFieldBuilder()->
|
||||||
|
add("alarm",standardField->alarm()) ->
|
||||||
|
add("timeStamp",standardField->timeStamp()) ->
|
||||||
|
addNestedStructure("power") ->
|
||||||
|
add("value",pvDouble) ->
|
||||||
|
add("alarm",standardField->alarm()) ->
|
||||||
|
endNested()->
|
||||||
|
addNestedStructure("voltage") ->
|
||||||
|
add("value",pvDouble) ->
|
||||||
|
add("alarm",standardField->alarm()) ->
|
||||||
|
endNested()->
|
||||||
|
addNestedStructure("current") ->
|
||||||
|
add("value",pvDouble) ->
|
||||||
|
add("alarm",standardField->alarm()) ->
|
||||||
|
endNested()->
|
||||||
|
createStructure());
|
||||||
}
|
}
|
||||||
|
|
||||||
PowerSupplyPtr PowerSupply::create(
|
PowerSupplyPtr PowerSupply::create(
|
||||||
@@ -77,62 +81,40 @@ bool PowerSupply::init()
|
|||||||
PVFieldPtr pvField;
|
PVFieldPtr pvField;
|
||||||
bool result;
|
bool result;
|
||||||
pvField = pvStructure->getSubField("timeStamp");
|
pvField = pvStructure->getSubField("timeStamp");
|
||||||
if(pvField.get()==NULL) {
|
if(!pvField) {
|
||||||
std::cerr << "no timeStamp" << std::endl;
|
cerr << "no timeStamp" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
result = pvTimeStamp.attach(pvField);
|
result = pvTimeStamp.attach(pvField);
|
||||||
if(!result) {
|
if(!result) {
|
||||||
std::cerr << "no timeStamp" << std::endl;
|
cerr << "no timeStamp" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pvField = pvStructure->getSubField("alarm");
|
pvField = pvStructure->getSubField("alarm");
|
||||||
if(pvField.get()==NULL) {
|
if(!pvField) {
|
||||||
std::cerr << "no alarm" << std::endl;
|
cerr << "no alarm" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
result = pvAlarm.attach(pvField);
|
result = pvAlarm.attach(pvField);
|
||||||
if(!result) {
|
if(!result) {
|
||||||
std::cerr << "no alarm" << std::endl;
|
cerr << "no alarm" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
string name;
|
pvCurrent = pvStructure->getSubField<PVDouble>("current.value");
|
||||||
name = "current.value";
|
if(!pvCurrent) {
|
||||||
pvField = pvStructure->getSubField(name);
|
cerr << "no current\n";
|
||||||
if(pvField.get()==NULL) {
|
|
||||||
name = "current";
|
|
||||||
pvField = pvStructure->getSubField(name);
|
|
||||||
}
|
|
||||||
if(pvField.get()==NULL) {
|
|
||||||
std::cerr << "no current" << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pvCurrent = pvStructure->getDoubleField(name);
|
pvVoltage = pvStructure->getSubField<PVDouble>("voltage.value");
|
||||||
if(pvCurrent.get()==NULL) return false;
|
if(!pvVoltage) {
|
||||||
name = "voltage.value";
|
cerr << "no current\n";
|
||||||
pvField = pvStructure->getSubField(name);
|
|
||||||
if(pvField.get()==NULL) {
|
|
||||||
name = "voltage";
|
|
||||||
pvField = pvStructure->getSubField(name);
|
|
||||||
}
|
|
||||||
if(pvField.get()==NULL) {
|
|
||||||
std::cerr << "no voltage" << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pvVoltage = pvStructure->getDoubleField(name);
|
pvPower = pvStructure->getSubField<PVDouble>("power.value");
|
||||||
if(pvVoltage.get()==NULL) return false;
|
if(!pvPower) {
|
||||||
name = "power.value";
|
cerr << "no powert\n";
|
||||||
pvField = pvStructure->getSubField(name);
|
|
||||||
if(pvField.get()==NULL) {
|
|
||||||
name = "power";
|
|
||||||
pvField = pvStructure->getSubField(name);
|
|
||||||
}
|
|
||||||
if(pvField.get()==NULL) {
|
|
||||||
std::cerr << "no power" << std::endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
pvPower = pvStructure->getDoubleField(name);
|
|
||||||
if(pvPower.get()==NULL) return false;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,13 +11,25 @@
|
|||||||
#ifndef POWERSUPPLY_H
|
#ifndef POWERSUPPLY_H
|
||||||
#define POWERSUPPLY_H
|
#define POWERSUPPLY_H
|
||||||
|
|
||||||
#include <shareLib.h>
|
|
||||||
|
|
||||||
#include <pv/pvDatabase.h>
|
#ifdef epicsExportSharedSymbols
|
||||||
|
# define powerSupplyEpicsExportSharedSymbols
|
||||||
|
# undef epicsExportSharedSymbols
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <pv/timeStamp.h>
|
#include <pv/timeStamp.h>
|
||||||
#include <pv/alarm.h>
|
#include <pv/alarm.h>
|
||||||
#include <pv/pvTimeStamp.h>
|
#include <pv/pvTimeStamp.h>
|
||||||
#include <pv/pvAlarm.h>
|
#include <pv/pvAlarm.h>
|
||||||
|
#include <pv/pvDatabase.h>
|
||||||
|
|
||||||
|
#ifdef powerSupplyEpicsExportSharedSymbols
|
||||||
|
# define epicsExportSharedSymbols
|
||||||
|
# undef powerSupplyEpicsExportSharedSymbols
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <shareLib.h>
|
||||||
|
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
@@ -26,7 +38,7 @@ epicsShareExtern epics::pvData::PVStructurePtr createPowerSupply();
|
|||||||
class PowerSupply;
|
class PowerSupply;
|
||||||
typedef std::tr1::shared_ptr<PowerSupply> PowerSupplyPtr;
|
typedef std::tr1::shared_ptr<PowerSupply> PowerSupplyPtr;
|
||||||
|
|
||||||
class PowerSupply :
|
class epicsShareClass PowerSupply :
|
||||||
public PVRecord
|
public PVRecord
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -27,12 +27,12 @@
|
|||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
#include <iocsh.h>
|
#include <iocsh.h>
|
||||||
|
|
||||||
#include <epicsExport.h>
|
|
||||||
|
|
||||||
#include <pv/pvIntrospect.h>
|
#include <pv/pvIntrospect.h>
|
||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
#include <pv/pvAccess.h>
|
#include <pv/pvAccess.h>
|
||||||
#include <pv/pvDatabase.h>
|
#include <pv/pvDatabase.h>
|
||||||
|
|
||||||
|
#include <epicsExport.h>
|
||||||
#include <pv/powerSupply.h>
|
#include <pv/powerSupply.h>
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
@@ -69,4 +69,4 @@ static void powerSupplyRegister(void)
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
epicsExportRegistrar(powerSupplyRegister);
|
epicsExportRegistrar(powerSupplyRegister);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,14 +23,14 @@
|
|||||||
#include <epicsEvent.h>
|
#include <epicsEvent.h>
|
||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
|
|
||||||
#include <epicsExport.h>
|
|
||||||
|
|
||||||
#include <pv/standardField.h>
|
#include <pv/standardField.h>
|
||||||
#include <pv/standardPVField.h>
|
#include <pv/standardPVField.h>
|
||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
#include <pv/pvAccess.h>
|
#include <pv/pvAccess.h>
|
||||||
#include "powerSupply.h"
|
#include "powerSupply.h"
|
||||||
|
|
||||||
|
#include <epicsExport.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using std::tr1::static_pointer_cast;
|
using std::tr1::static_pointer_cast;
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <pv/standardField.h>
|
#include <pv/standardField.h>
|
||||||
#include <pv/standardPVField.h>
|
#include <pv/standardPVField.h>
|
||||||
#include <pv/channelProviderLocal.h>
|
#include <pv/channelProviderLocal.h>
|
||||||
|
#include <pv/convert.h>
|
||||||
#include "powerSupply.h"
|
#include "powerSupply.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -143,7 +144,6 @@ static void testPVScalar(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void testPVScalarArray(
|
static void testPVScalarArray(
|
||||||
ScalarType scalarType,
|
|
||||||
string const & valueNameRecord,
|
string const & valueNameRecord,
|
||||||
string const & valueNameCopy,
|
string const & valueNameCopy,
|
||||||
PVRecordPtr const & pvRecord,
|
PVRecordPtr const & pvRecord,
|
||||||
@@ -159,14 +159,14 @@ static void testPVScalarArray(
|
|||||||
shared_vector<double> values(n);
|
shared_vector<double> values(n);
|
||||||
cout << endl;
|
cout << endl;
|
||||||
pvStructureRecord = pvRecord->getPVRecordStructure()->getPVStructure();
|
pvStructureRecord = pvRecord->getPVRecordStructure()->getPVStructure();
|
||||||
pvValueRecord = pvStructureRecord->getScalarArrayField(valueNameRecord,scalarType);
|
pvValueRecord = pvStructureRecord->getSubField<PVScalarArray>(valueNameRecord);
|
||||||
for(size_t i=0; i<n; i++) values[i] = i;
|
for(size_t i=0; i<n; i++) values[i] = i;
|
||||||
const shared_vector<const double> xxx(freeze(values));
|
const shared_vector<const double> xxx(freeze(values));
|
||||||
pvValueRecord->putFrom(xxx);
|
pvValueRecord->putFrom(xxx);
|
||||||
StructureConstPtr structure = pvCopy->getStructure();
|
StructureConstPtr structure = pvCopy->getStructure();
|
||||||
cout << "structure from copy" << endl << *structure << endl;
|
cout << "structure from copy" << endl << *structure << endl;
|
||||||
pvStructureCopy = pvCopy->createPVStructure();
|
pvStructureCopy = pvCopy->createPVStructure();
|
||||||
pvValueCopy = pvStructureCopy->getScalarArrayField(valueNameCopy,scalarType);
|
pvValueCopy = pvStructureCopy->getSubField<PVScalarArray>(valueNameCopy);
|
||||||
bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields()));
|
bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields()));
|
||||||
pvCopy->initCopy(pvStructureCopy, bitSet);
|
pvCopy->initCopy(pvStructureCopy, bitSet);
|
||||||
cout << "after initCopy pvValueCopy " << *pvValueCopy << endl;
|
cout << "after initCopy pvValueCopy " << *pvValueCopy << endl;
|
||||||
@@ -236,21 +236,21 @@ static void scalarTest()
|
|||||||
valueNameRecord = request = "value";
|
valueNameRecord = request = "value";
|
||||||
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
||||||
pvRequest = createRequest->createRequest(request);
|
pvRequest = createRequest->createRequest(request);
|
||||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
cout << "request " << request << endl << "pvRequest" << *pvRequest << endl ;
|
||||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||||
valueNameCopy = "value";
|
valueNameCopy = "value";
|
||||||
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||||
request = "";
|
request = "";
|
||||||
valueNameRecord = "value";
|
valueNameRecord = "value";
|
||||||
pvRequest = createRequest->createRequest(request);
|
pvRequest = createRequest->createRequest(request);
|
||||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
cout << "request " << request << endl << "pvRequest" << *pvRequest << endl ;
|
||||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||||
valueNameCopy = "value";
|
valueNameCopy = "value";
|
||||||
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||||
request = "alarm,timeStamp,value";
|
request = "alarm,timeStamp,value";
|
||||||
valueNameRecord = "value";
|
valueNameRecord = "value";
|
||||||
pvRequest = createRequest->createRequest(request);
|
pvRequest = createRequest->createRequest(request);
|
||||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
cout << "request " << request << endl << "pvRequest" << *pvRequest << endl ;
|
||||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||||
valueNameCopy = "value";
|
valueNameCopy = "value";
|
||||||
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||||
@@ -273,24 +273,24 @@ static void arrayTest()
|
|||||||
pvRecord = createScalarArray("doubleArrayRecord",pvDouble,"alarm,timeStamp");
|
pvRecord = createScalarArray("doubleArrayRecord",pvDouble,"alarm,timeStamp");
|
||||||
valueNameRecord = request = "value";
|
valueNameRecord = request = "value";
|
||||||
pvRequest = createRequest->createRequest(request);
|
pvRequest = createRequest->createRequest(request);
|
||||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
cout << "request " << request << endl << "pvRequest" << *pvRequest << endl ;
|
||||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||||
valueNameCopy = "value";
|
valueNameCopy = "value";
|
||||||
testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
testPVScalarArray(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||||
request = "";
|
request = "";
|
||||||
valueNameRecord = "value";
|
valueNameRecord = "value";
|
||||||
pvRequest = createRequest->createRequest(request);
|
pvRequest = createRequest->createRequest(request);
|
||||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
cout << "request " << request << endl << "pvRequest" << *pvRequest << endl ;
|
||||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||||
valueNameCopy = "value";
|
valueNameCopy = "value";
|
||||||
testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
testPVScalarArray(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||||
request = "alarm,timeStamp,value";
|
request = "alarm,timeStamp,value";
|
||||||
valueNameRecord = "value";
|
valueNameRecord = "value";
|
||||||
pvRequest = createRequest->createRequest(request);
|
pvRequest = createRequest->createRequest(request);
|
||||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
cout << "request " << request << endl << "pvRequest" << *pvRequest << endl ;
|
||||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||||
valueNameCopy = "value";
|
valueNameCopy = "value";
|
||||||
testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
testPVScalarArray(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||||
pvRecord->destroy();
|
pvRecord->destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,28 +311,28 @@ static void powerSupplyTest()
|
|||||||
pvRecord = PowerSupply::create("powerSupply",pv);
|
pvRecord = PowerSupply::create("powerSupply",pv);
|
||||||
valueNameRecord = request = "power.value";
|
valueNameRecord = request = "power.value";
|
||||||
pvRequest = createRequest->createRequest(request);
|
pvRequest = createRequest->createRequest(request);
|
||||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
cout << "request " << request << endl << "pvRequest" << *pvRequest << endl ;
|
||||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||||
valueNameCopy = "power.value";
|
valueNameCopy = "power.value";
|
||||||
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||||
request = "";
|
request = "";
|
||||||
valueNameRecord = "power.value";
|
valueNameRecord = "power.value";
|
||||||
pvRequest = createRequest->createRequest(request);
|
pvRequest = createRequest->createRequest(request);
|
||||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
cout << "request " << request << endl << "pvRequest" << *pvRequest << endl ;
|
||||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||||
valueNameCopy = "power.value";
|
valueNameCopy = "power.value";
|
||||||
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||||
request = "alarm,timeStamp,voltage.value,power.value,current.value";
|
request = "alarm,timeStamp,voltage.value,power.value,current.value";
|
||||||
valueNameRecord = "power.value";
|
valueNameRecord = "power.value";
|
||||||
pvRequest = createRequest->createRequest(request);
|
pvRequest = createRequest->createRequest(request);
|
||||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
cout << "request " << request << endl << "pvRequest" << *pvRequest << endl ;
|
||||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||||
valueNameCopy = "power.value";
|
valueNameCopy = "power.value";
|
||||||
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||||
request = "alarm,timeStamp,voltage{value,alarm},power{value,alarm,display},current.value";
|
request = "alarm,timeStamp,voltage{value,alarm},power{value,alarm,display},current.value";
|
||||||
valueNameRecord = "power.value";
|
valueNameRecord = "power.value";
|
||||||
pvRequest = createRequest->createRequest(request);
|
pvRequest = createRequest->createRequest(request);
|
||||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
cout << "request " << request << endl << "pvRequest" << *pvRequest << endl ;
|
||||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||||
valueNameCopy = "power.value";
|
valueNameCopy = "power.value";
|
||||||
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||||
|
|||||||
Reference in New Issue
Block a user