32 Commits
3.1.0 ... 4.0.1

Author SHA1 Message Date
Marty Kraimer
d27f929595 merge from default branch 2014-11-11 06:52:56 -05:00
Matej Sekoranja
b4e17f271b win32 vs2013 compilation fix 2014-11-11 09:05:25 +01:00
Marty Kraimer
79f407486a in the future remove recordList since pvAccess provides pvlist 2014-11-10 10:24:07 -05:00
Matej Sekoranja
3c359728f7 Added tag 4.0.0 for changeset 85d46a2614f9 2014-10-29 13:17:22 +01:00
Matej Sekoranja
7b9693562a merge 2014-10-29 13:15:33 +01:00
Matej Sekoranja
f1c39ca5d2 clang compilation fixes 2014-10-16 07:30:42 +02:00
Marty Kraimer
16b1775b98 Added tag 4.0.0 for changeset 42dbe8a17f85 2014-10-15 08:37:24 -04:00
Marty Kraimer
f6ee7333bb merge changes from default 2014-10-15 07:29:49 -04:00
Matej Sekoranja
9f45bdfa75 missing epicsShareClass PowerSupply 2014-10-14 21:26:07 +02:00
Matej Sekoranja
03aa15b5f7 added missing lib for win32 2014-10-14 20:41:36 +02:00
Matej Sekoranja
8093952ca2 win32 test dll linkage 2014-10-14 07:40:34 +02:00
Marty Kraimer
2bea54e218 updated pvDatabaseCPP.html and TODO 2014-10-09 09:33:13 -04:00
dhickin
e81230dba5 Corrected spelling of synchrotron in licence. 2014-10-04 02:45:53 +01:00
dhickin
50b8f306c3 Spelling and typos. 2014-10-04 01:39:14 +01:00
Marty Kraimer
65be8e5678 Added tag 4.0.0 for changeset e2e041fa7d04 2014-10-01 09:01:22 -04:00
Marty Kraimer
dbb9310adc flow: Created branch 'release/4.0'. 2014-10-01 08:58:34 -04:00
Matej Sekoranja
50fbb396e8 win32 compilation of test and examples 2014-09-13 23:40:41 +02:00
Matej Sekoranja
ff19fe1cd8 win32 linkage 2014-09-13 23:01:29 +02:00
Matej Sekoranja
230938220e win compilation 2014-09-13 00:18:25 +02:00
Matej Sekoranja
334ed3b70a hopefully fixed windows exports 2014-09-12 10:00:00 +02:00
Marty Kraimer
4c7e51d8ad prepare documentation for pre release 2014-09-03 09:13:45 -04:00
Marty Kraimer
4973a6297e fixed bug in creating implementation of channelArray 2014-08-29 09:33:42 -04:00
Marty Kraimer
f0d1481a28 nanoSecond => nanosecond 2014-08-20 06:36:40 -04:00
Marty Kraimer
d5235db54c mainly documentation changes; did much testing 2014-08-11 14:18:49 -04:00
Marty Kraimer
b125035a11 fixed connection problems 2014-08-07 14:36:35 -04:00
Marty Kraimer
9551b0e4c6 fixed bugs in implementation of montor; connection problems still exist 2014-08-07 08:02:53 -04:00
Marty Kraimer
d6aa03815e changes because of ChannelArray API change; update TODO.md; add RELEASE_NOTES.html and TODO.html 2014-07-22 08:53:32 -04:00
Marty Kraimer
ce0d62fbbc changed upcoming release number. 2014-07-10 13:38:06 -04:00
Marty Kraimer
2fe3e66047 updated documentation; fixed bugs while updating documentation 2014-07-10 13:25:58 -04:00
dhickin
fa53d72258 Corrected includes for CONFIG_SITE files. 2014-07-02 12:27:00 +01:00
Marty Kraimer
b010cf0849 add some records for testing easyPVAJava 2014-07-02 07:11:50 -04:00
Matej Sekoranja
7fd707cb4b Added tag 3.1.0 for changeset 395f48d5196d 2014-07-02 00:12:37 +02:00
63 changed files with 5365 additions and 795 deletions

View File

@@ -1,2 +1,8 @@
bba6a2491bdf73681cef01caf0bd89c87d7989cd 0.9.1
abdc90bf52a0c31e24e2f9a079ef72350ee31686 before_merge_changesAfter3_0_2
395f48d5196dde5bf7f24a1849aee3f8d92e91b8 3.1.0
e2e041fa7d04a37836a4343589077001588ae031 4.0.0
e2e041fa7d04a37836a4343589077001588ae031 4.0.0
42dbe8a17f851861a16be7d426ef1206324aa197 4.0.0
42dbe8a17f851861a16be7d426ef1206324aa197 4.0.0
85d46a2614f925ccb423d6abd5dfe20d42fb5099 4.0.0

View File

@@ -2,7 +2,7 @@
Copyright (c) 2008 Martin R. Kraimer
Copyright (c) 2006 The University of Chicago, as Operator of Argonne
National Laboratory.
Copyright (c) 2006 Deutsches Elektronen-Synchroton,
Copyright (c) 2006 Deutsches Elektronen-Synchrotron,
Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
Copyright (c) 2007 Control System Laboratory,
(COSYLAB) Ljubljana Slovenia

View File

@@ -35,5 +35,5 @@
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
-include $(TOP)/configure/CONFIG_SITE.local
-include $(TOP)/../CONFIG.local
-include $(TOP)/../configure/CONFIG_SITE.local
-include $(TOP)/../../CONFIG.local

View File

@@ -60,7 +60,7 @@ bool ArrayPerformance::init()
initPVRecord();
PVScalarArrayPtr pvScalarArray = getPVStructure()->getScalarArrayField("value",pvLong);
if(pvScalarArray==NULL) return false;
if(!pvScalarArray) return false;
pvValue = static_pointer_cast<PVLongArray>(pvScalarArray);
ArrayPerformancePtr xxx = dynamic_pointer_cast<ArrayPerformance>(getPtrSelf());
arrayPerformanceThread = ArrayPerformanceThreadPtr(new ArrayPerformanceThread(xxx));
@@ -182,14 +182,18 @@ void ArrayPerformanceThread::run()
nSinceLastReport = 0;
}
++nSinceLastReport;
shared_vector<int64> xxx(arrayPerformance->size,value++);
shared_vector<const int64> data(freeze(xxx));
arrayPerformance->lock();
try {
arrayPerformance->beginGroupPut();
arrayPerformance->pvValue->replace(data);
arrayPerformance->process();
arrayPerformance->endGroupPut();
if(arrayPerformance->getTraceLevel()>1) {
cout << "arrayPerformance size " << arrayPerformance->size;
cout << " value " << value +1 << endl;
}
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(...) {
arrayPerformance->unlock();
throw;

View File

@@ -17,7 +17,6 @@
# undef epicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <epicsThread.h>
#include <pv/standardPVField.h>
#include <pv/timeStamp.h>

View File

@@ -266,9 +266,9 @@ void LongArrayChannelGet::channelGetConnect(
bool structureOK(true);
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(structure);
PVFieldPtr pvField = pvStructure->getSubField("timeStamp");
if(pvField==NULL) structureOK = false;
if(!pvField) structureOK = false;
pvField = pvStructure->getSubField("value");
if(pvField==NULL) {
if(!pvField) {
structureOK = false;
} else {
FieldConstPtr field = pvField->getField();
@@ -292,7 +292,7 @@ bool LongArrayChannelGet::init()
{
ChannelProvider::shared_pointer channelProvider =
getChannelProviderRegistry()->getProvider(providerName);
if(channelProvider==NULL) {
if(!channelProvider) {
cout << "provider " << providerName << " not found" << endl;
return false;
}
@@ -305,7 +305,7 @@ bool LongArrayChannelGet::init()
if(!status.isOK()) return false;
CreateRequest::shared_pointer createRequest = CreateRequest::create();
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(pvRequest==NULL) {
if(!pvRequest) {
cout << "request logic error " << createRequest->getMessage() << endl;
return false;
}
@@ -334,10 +334,10 @@ void LongArrayChannelGet::destroy()
if(runReturned) break;
epicsThreadSleep(.01);
}
if(longArrayChannelRequester!=NULL) {
if(longArrayChannelRequester) {
longArrayChannelRequester->destroy();
}
if(longArrayChannelGetRequester!=NULL) {
if(longArrayChannelGetRequester) {
longArrayChannelGetRequester->destroy();
}
thread->exitWait();
@@ -433,7 +433,7 @@ void LongArrayChannelGet::run()
CreateRequest::create();
PVStructurePtr pvRequest =
createRequest->createRequest(request);
if(pvRequest==NULL) {
if(!pvRequest) {
cout << "request logic error " << createRequest->getMessage() << endl;
return ;
}

View File

@@ -17,8 +17,6 @@
# undef epicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <pv/event.h>
#include <pv/lock.h>
#include <pv/standardPVField.h>

View File

@@ -138,9 +138,9 @@ void LAMMonitorRequester::monitorConnect(Status const & status,
}
bool structureOK(true);
FieldConstPtr field = structure->getField("timeStamp");
if(field==NULL) structureOK = false;
if(!field) structureOK = false;
field = structure->getField("value");
if(field==NULL) {
if(!field) {
structureOK = false;
} else {
if(field->getType()!=scalarArray) {
@@ -179,9 +179,9 @@ void LAMMonitorRequester::run()
{
Lock xx(mutex);
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);
pvTimeStamp.attach(pvStructure->getSubField("timeStamp"));
pvTimeStamp.get(timeStamp);
@@ -268,7 +268,7 @@ bool LongArrayMonitor::init(
monitorRequester->init();
ChannelProvider::shared_pointer channelProvider =
getChannelProviderRegistry()->getProvider(providerName);
if(channelProvider==NULL) {
if(!channelProvider) {
cout << "provider " << providerName << " not found" << endl;
return false;
}
@@ -282,7 +282,7 @@ bool LongArrayMonitor::init(
request += "]field(value,timeStamp,alarm)";
CreateRequest::shared_pointer createRequest = CreateRequest::create();
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(pvRequest==NULL) {
if(!pvRequest) {
cout << "request logic error " << createRequest->getMessage() << endl;
return false;
}

View File

@@ -16,7 +16,6 @@
# undef epicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <pv/event.h>
#include <pv/lock.h>
#include <pv/standardPVField.h>

View File

@@ -110,7 +110,7 @@ private:
bool LongArrayChannelPut::init()
{
ChannelProvider::shared_pointer channelProvider = getChannelProviderRegistry()->getProvider(providerName);
if(channelProvider==NULL) {
if(!channelProvider) {
cout << "provider " << providerName << " not found" << endl;
return false;
}
@@ -119,7 +119,7 @@ bool LongArrayChannelPut::init()
if(!status.isOK()) return false;
CreateRequest::shared_pointer createRequest = CreateRequest::create();
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(pvRequest==NULL) {
if(!pvRequest) {
cout << "request logic error " << createRequest->getMessage() << endl;
return false;
}
@@ -187,7 +187,7 @@ void LongArrayChannelPut::channelPutConnect(
bitSet = BitSetPtr(new BitSet(pvStructure->getNumberFields()));
bool structureOK(true);
PVFieldPtr pvField = pvStructure->getSubField("value");
if(pvField==NULL) {
if(!pvField) {
structureOK = false;
} else {
FieldConstPtr field = pvField->getField();
@@ -267,7 +267,6 @@ void LongArrayChannelPut::run()
if(iterBetweenCreateChannel!=0) {
if(numChannelCreate>=iterBetweenCreateChannel) {
channel->destroy();
epicsThreadSleep(1.0);
ChannelProvider::shared_pointer channelProvider =
getChannelProviderRegistry()->getProvider(providerName);
channel = channelProvider->createChannel(
@@ -295,7 +294,7 @@ void LongArrayChannelPut::run()
channelPut->destroy();
CreateRequest::shared_pointer createRequest = CreateRequest::create();
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(pvRequest==NULL) {
if(!pvRequest) {
cout << "request logic error " << createRequest->getMessage() << endl;
return ;
}

View File

@@ -17,7 +17,6 @@
# undef epicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <pv/event.h>
#include <pv/lock.h>
#include <pv/standardPVField.h>

View File

@@ -23,6 +23,5 @@
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
-include $(TOP)/../CONFIG_SITE.local
-include $(TOP)/../CONFIG.local
-include $(TOP)/configure/CONFIG_SITE.local

View 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>

View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -24,5 +24,4 @@ INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
-include $(TOP)/../configure/CONFIG_SITE.local
-include $(TOP)/../../CONFIG_SITE.local
-include $(TOP)/../CONFIG.local
-include $(TOP)/../../CONFIG.local

View File

@@ -17,6 +17,7 @@ DB += dbString.db
DB += dbStringArray.db
DB += dbEnum.db
DB += dbCounter.db
DB += dbDouble.db
#----------------------------------------------------
# If <anyname>.db template is not named <anyname>*.template add

View File

@@ -0,0 +1,3 @@
record(ao, "$(name)")
{
}

View File

@@ -7,15 +7,17 @@ dbLoadDatabase("dbd/exampleDatabase.dbd")
exampleDatabase_registerRecordDeviceDriver(pdbbase)
## Load record instances
dbLoadRecords("db/dbScalar.db","name=double00,type=ao")
dbLoadRecords("db/dbScalar.db","name=double01,type=ao")
dbLoadRecords("db/dbScalar.db","name=double02,type=ao")
dbLoadRecords("db/dbScalar.db","name=double03,type=ao")
dbLoadRecords("db/dbScalar.db","name=double04,type=ao")
dbLoadRecords("db/dbScalar.db","name=double05,type=ao")
dbLoadRecords("db/dbDouble.db","name=double00")
dbLoadRecords("db/dbDouble.db","name=double01")
dbLoadRecords("db/dbDouble.db","name=double02")
dbLoadRecords("db/dbDouble.db","name=double03")
dbLoadRecords("db/dbDouble.db","name=double04")
dbLoadRecords("db/dbDouble.db","name=double05")
dbLoadRecords("db/dbStringArray.db","name=stringArray01")
dbLoadRecords("db/dbEnum.db","name=enum01")
dbLoadRecords("db/dbCounter.db","name=counter01");
dbLoadRecords("db/dbArray.db","name=doubleArray,type=DOUBLE");
cd ${TOP}/iocBoot/${IOC}
iocInit()

View File

@@ -14,6 +14,7 @@ exampleDatabase_SRCS += exampleDatabase.cpp
exampleDatabase_SRCS += exampleMonitorPlugin.cpp
exampleDatabase_SRCS += exampleDatabaseRegister.cpp
exampleDatabase_SRCS += exampleMonitorPluginRegister.cpp
exampleDatabase_LIBS += powerSupply
exampleDatabase_LIBS += pvDatabase
exampleDatabase_LIBS += pvAccess
exampleDatabase_LIBS += pvData

View File

@@ -27,6 +27,8 @@
#include <pv/traceRecord.h>
#include <pv/powerSupply.h>
#define epicsExportSharedSymbols
#include <pv/exampleDatabase.h>
using namespace std;
@@ -147,17 +149,20 @@ void ExampleDatabase::create()
createVariantUnionArrayRecord(master,"exampleVariantUnionArray");
recordName = "examplePowerSupply";
PVStructurePtr pvStructure = createPowerSupply();
PowerSupplyPtr psr =
PowerSupply::create(recordName,pvStructure);
if(psr.get()==NULL) {
cout << "PowerSupply::create failed" << endl;
return;
PowerSupplyPtr psr = PowerSupply::create(recordName,pvStructure);
if(!psr) {
cout << "PowerSupply::create failed" << endl;
} else {
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";
pvRecord = RecordListRecord::create(recordName);
result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;
if(!pvRecord) {
cout << "RecordListRecord::create failed" << endl;
} else {
result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;
}
}

View File

@@ -16,15 +16,15 @@
# undef epicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <pv/pvDatabase.h>
#ifdef exampledatabaseEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef exampledatabaseEpicsExportSharedSymbols
# include <shareLib.h>
#endif
#include <shareLib.h>
namespace epics { namespace pvDatabase {
class epicsShareClass ExampleDatabase{

View File

@@ -32,7 +32,6 @@
#include <pv/pvDatabase.h>
#include <epicsExport.h>
#include <pv/exampleDatabase.h>
using namespace epics::pvData;

View File

@@ -11,6 +11,8 @@
#include <pv/convert.h>
#include <pv/monitorPlugin.h>
#define epicsExportSharedSymbols
#include <pv/exampleMonitorPlugin.h>
using namespace epics::pvData;
@@ -40,10 +42,10 @@ public:
{
pvField = getPVDataCreate()->createPVField(field);
raiseMonitor = true;
if(pvFieldOptions!=NULL) {
if(pvFieldOptions) {
PVStringPtr pvString =
pvFieldOptions->getSubField<PVString>("raiseMonitor");
if(pvString!=NULL) {
if(pvString) {
string value = pvString->get();
if(value.compare("false")==0) raiseMonitor = false;
}
@@ -88,7 +90,7 @@ void ExampleMonitorPlugin::create()
static OnChangePluginCreatorPtr plugin;
static Mutex mutex;
Lock xx(mutex);
if(plugin==NULL) {
if(!plugin) {
plugin = OnChangePluginCreatorPtr(new OnChangePluginCreator());
MonitorPluginManager::get()->addPlugin(pluginName,plugin);
}

View File

@@ -11,11 +11,22 @@
#ifndef EXAMPLEMONITORPLUGIN_H
#define EXAMPLEMONITORPLUGIN_H
#include <shareLib.h>
#ifdef epicsExportSharedSymbols
# define examplemonitorPluginEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDatabase.h>
#include <pv/monitorPlugin.h>
#ifdef examplemonitorPluginEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef examplemonitorPluginEpicsExportSharedSymbols
#endif
#include <shareLib.h>
namespace epics { namespace pvDatabase {
class epicsShareClass ExampleMonitorPlugin{

View File

@@ -26,14 +26,15 @@
#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 <epicsExport.h>
#include <pv/exampleMonitorPlugin.h>
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvDatabase;
@@ -61,4 +62,4 @@ std::cout << "exampleMonitorPluginRegister returning\n";
extern "C" {
epicsExportRegistrar(exampleMonitorPluginRegister);
}
}

View File

@@ -35,5 +35,5 @@
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
-include $(TOP)/configure/CONFIG_SITE.local
-include $(TOP)/../CONFIG.local
-include $(TOP)/../configure/CONFIG_SITE.local
-include $(TOP)/../../CONFIG.local

View File

@@ -13,4 +13,4 @@ cd ${TOP}/iocBoot/${IOC}
iocInit()
startPVAClient
startPVAServer
exampleLinkCreateRecord exampleLinkRemote pvAccess doubleArray
exampleLinkCreateRecord exampleLink pvAccess doubleArray

View File

@@ -9,10 +9,12 @@
* @date 2013.08.02
*/
#include <pv/exampleLink.h>
#include <pv/standardPVField.h>
#include <pv/convert.h>
#define epicsExportSharedSymbols
#include <pv/exampleLink.h>
using namespace epics::pvData;
using namespace epics::pvAccess;
using std::tr1::static_pointer_cast;
@@ -63,12 +65,12 @@ bool ExampleLink::init()
pvAlarm.attach(pvStructure->getSubField("alarm"));
pvValue = static_pointer_cast<PVDoubleArray>(
pvStructure->getScalarArrayField("value",pvDouble));
if(pvValue==NULL) {
if(!pvValue) {
return false;
}
ChannelProvider::shared_pointer provider =
getChannelProviderRegistry()->getProvider(providerName);
if(provider==NULL) {
if(!provider) {
cout << getRecordName() << " provider "
<< providerName << " does not exist" << endl;
return false;
@@ -95,7 +97,7 @@ bool ExampleLink::init()
}
getPVValue = static_pointer_cast<PVDoubleArray>(
getPVStructure->getScalarArrayField("value",pvDouble));
if(getPVValue==NULL) {
if(!getPVValue) {
cout << getRecordName() << " get value not PVDoubleArray" << endl;
return false;
}
@@ -147,6 +149,7 @@ void ExampleLink::channelGetConnect(
{
this->status = status;
this->channelGet = channelGet;
getPVStructure = getPVDataCreate()->createPVStructure(structure);
event.signal();
}
@@ -157,7 +160,7 @@ void ExampleLink::getDone(
BitSetPtr const & bitSet)
{
this->status = status;
getPVStructure = pvStructure;
convert->copyStructure(pvStructure,getPVStructure);
this->bitSet = bitSet;
event.signal();
}

View File

@@ -11,7 +11,10 @@
#ifndef EXAMPLEPVADOUBLEARRAYGET_H
#define EXAMPLEPVADOUBLEARRAYGET_H
#include <shareLib.h>
#ifdef epicsExportSharedSymbols
# define exampleLinkEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/timeStamp.h>
#include <pv/pvTimeStamp.h>
@@ -22,6 +25,13 @@
#include <pv/pvAccess.h>
#include <pv/serverContext.h>
#ifdef exampleLinkEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef exampleLinkEpicsExportSharedSymbols
#endif
#include <shareLib.h>
namespace epics { namespace pvDatabase {

View File

@@ -27,14 +27,14 @@
#include <epicsThread.h>
#include <iocsh.h>
#include <epicsExport.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/pvAccess.h>
#include <pv/pvDatabase.h>
#include <epicsExport.h>
#include <pv/exampleLink.h>
using namespace epics::pvData;
@@ -70,8 +70,8 @@ static void exampleLinkCallFunc(const iocshArgBuf *args)
char *providerName = args[1].sval;
char *channelName = args[2].sval;
ExampleLinkPtr record = ExampleLink::create(recordName,providerName,channelName);
if(record!=NULL)
result = master->addRecord(record);
if(record)
result = master->addRecord(record);
if(!result) cout << "recordname" << " not added" << endl;
}
@@ -86,4 +86,4 @@ static void exampleLinkRegister(void)
extern "C" {
epicsExportRegistrar(exampleLinkRegister);
}
}

View File

@@ -35,5 +35,5 @@
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
-include $(TOP)/configure/CONFIG_SITE.local
-include $(TOP)/../CONFIG.local
-include $(TOP)/../configure/CONFIG_SITE.local
-include $(TOP)/../../CONFIG.local

View File

@@ -20,6 +20,7 @@
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/recordList.h>
#include <pv/powerSupply.h>
#include <pv/traceRecord.h>
#include <pv/channelProviderLocal.h>
@@ -48,7 +49,10 @@ int main(int argc,char *argv[])
pvRecord = TraceRecord::create(recordName);
result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;
pvRecord.reset();
recordName = "laptoprecordListPGRPC";
pvRecord = RecordListRecord::create(recordName);
result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;
ServerContext::shared_pointer pvaServer =
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
cout << "powerSupply\n";

View File

@@ -35,5 +35,5 @@
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
-include $(TOP)/configure/CONFIG_SITE.local
-include $(TOP)/../CONFIG.local
-include $(TOP)/../configure/CONFIG_SITE.local
-include $(TOP)/../../CONFIG.local

View File

@@ -1,4 +1,5 @@
include "base.dbd"
include "PVAClientRegister.dbd"
include "PVAServerRegister.dbd"
include "registerChannelProviderLocal.dbd"
include "dbPv.dbd"

View File

@@ -9,7 +9,9 @@
* @date 2013.04.02
*/
#include <pv/standardPVField.h>
#include <pv/standardField.h>
#define epicsExportSharedSymbols
#include <pv/exampleServer.h>
using namespace epics::pvData;
@@ -23,19 +25,20 @@ namespace epics { namespace exampleServer {
ExampleServerPtr ExampleServer::create(
string const & recordName)
{
StandardPVFieldPtr standardPVField = getStandardPVField();
StandardFieldPtr standardField = getStandardField();
FieldCreatePtr fieldCreate = getFieldCreate();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
PVStructurePtr pvArgument = standardPVField->scalar(pvString,"");
PVStructurePtr pvResult = standardPVField->scalar(pvString,"timeStamp");
StringArray names;
names.reserve(2);
PVFieldPtrArray fields;
fields.reserve(2);
names.push_back("argument");
fields.push_back(pvArgument);
names.push_back("result");
fields.push_back(pvResult);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(names,fields);
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
addNestedStructure("argument")->
add("value",pvString)->
endNested()->
addNestedStructure("result") ->
add("value",pvString) ->
add("timeStamp",standardField->timeStamp()) ->
endNested()->
createStructure();
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
ExampleServerPtr pvRecord(
new ExampleServer(recordName,pvStructure));
if(!pvRecord->init()) pvRecord.reset();

View File

@@ -11,12 +11,23 @@
#ifndef EXAMPLECOUNTER_H
#define EXAMPLECOUNTER_H
#include <shareLib.h>
#ifdef epicsExportSharedSymbols
# define exampleServerEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <pv/pvDatabase.h>
#include <pv/timeStamp.h>
#include <pv/pvTimeStamp.h>
#ifdef exampleServerEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef exampleServerEpicsExportSharedSymbols
#endif
#include <shareLib.h>
namespace epics { namespace exampleServer {

View File

@@ -22,6 +22,7 @@
#include <pv/standardPVField.h>
#include <pv/exampleServer.h>
#include <pv/traceRecord.h>
#include <pv/recordList.h>
#include <pv/channelProviderLocal.h>
#include <pv/serverContext.h>
@@ -42,15 +43,20 @@ int main(int argc,char *argv[])
recordName = "exampleServer";
pvRecord = ExampleServer::create(recordName);
result = master->addRecord(pvRecord);
cout << "result of addRecord " << recordName << " " << result << endl;
if(!result) cout<< "record " << recordName << " not added" << endl;
recordName = "traceRecordPGRPC";
pvRecord = TraceRecord::create(recordName);
result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;
pvRecord.reset();
recordName = "laptoprecordListPGRPC";
pvRecord = RecordListRecord::create(recordName);
result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;
ServerContext::shared_pointer pvaServer =
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
cout << "exampleServer\n";
PVStringArrayPtr pvNames = master->getRecordNames();
shared_vector<const string> names = pvNames->view();
for(size_t i=0; i<names.size(); ++i) cout << names[i] << endl;
string str;
while(true) {
cout << "Type exit to stop: \n";

View File

@@ -27,12 +27,13 @@
#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/recordList.h>
#include <epicsExport.h>
#include <pv/exampleServer.h>
using namespace epics::pvData;
@@ -50,10 +51,19 @@ static const iocshFuncDef exampleServerFuncDef = {
"exampleServerCreateRecord", 1, testArgs};
static void exampleServerCallFunc(const iocshArgBuf *args)
{
PVDatabasePtr master = PVDatabase::getMaster();
char *recordName = args[0].sval;
ExampleServerPtr record = ExampleServer::create(recordName);
bool result = PVDatabase::getMaster()->addRecord(record);
bool result = master->addRecord(record);
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)

View File

@@ -51,4 +51,74 @@ test/src/powerSupply.h
test/src/powerSupplyRegister.cpp
test/src/testExampleRecord.cpp
test/src/testPVCopy.cpp
test/src/testPVRecord.cpp
test/src/testPVRecord.cpp
arrayPerformance/include/pv/arrayPerformance.h
arrayPerformance/include/pv/longArrayGet.h
arrayPerformance/include/pv/longArrayMonitor.h
arrayPerformance/include/pv/longArrayPut.h
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/include/pv/exampleDatabase.h
exampleDatabase/include/pv/exampleMonitorPlugin.h
exampleDatabase/ioc/src/O.darwin-x86/exampleDatabase_registerRecordDeviceDriver.cpp
exampleDatabase/ioc/src/exampleDatabaseMain.cpp
exampleDatabase/src/exampleDatabase.cpp
exampleDatabase/src/exampleDatabase.h
exampleDatabase/src/exampleDatabaseMain.cpp
exampleDatabase/src/exampleDatabaseRegister.cpp
exampleDatabase/src/exampleMonitorPlugin.cpp
exampleDatabase/src/exampleMonitorPlugin.h
exampleDatabase/src/exampleMonitorPluginRegister.cpp
exampleLink/include/pv/exampleLink.h
exampleLink/ioc/src/O.darwin-x86/exampleLink_registerRecordDeviceDriver.cpp
exampleLink/ioc/src/exampleLinkMain.cpp
exampleLink/src/exampleLink.cpp
exampleLink/src/exampleLink.h
exampleLink/src/exampleLinkRegister.cpp
examplePowerSupply/ioc/src/O.darwin-x86/powerSupply_registerRecordDeviceDriver.cpp
examplePowerSupply/ioc/src/powerSupplyMain.cpp
examplePowerSupply/src/powerSupplyMain.cpp
exampleServer/include/pv/exampleServer.h
exampleServer/ioc/src/O.darwin-x86/exampleServer_registerRecordDeviceDriver.cpp
exampleServer/ioc/src/exampleServerMain.cpp
exampleServer/src/exampleServer.cpp
exampleServer/src/exampleServer.h
exampleServer/src/exampleServerMain.cpp
exampleServer/src/exampleServerRegister.cpp
include/pv/channelProviderLocal.h
include/pv/pvCopyMonitor.h
include/pv/pvDatabase.h
include/pv/recordList.h
include/pv/traceRecord.h
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/monitorFactory.cpp
src/pvAccess/pvCopyMonitor.cpp
src/pvAccess/pvCopyMonitor.h
src/pvAccess/registerChannelProviderLocal.cpp
src/special/recordList.cpp
src/special/recordList.h
src/special/traceRecord.cpp
src/special/traceRecord.h
test/include/pv/powerSupply.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

View File

@@ -27,9 +27,10 @@
#ifdef pvdatabaseEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef pvdatabaseEpicsExportSharedSymbols
# include <shareLib.h>
#endif
#include <shareLib.h>
namespace epics { namespace pvDatabase {

View File

@@ -371,7 +371,7 @@ void PVRecordField::init()
{
fullFieldName = pvField->getFieldName();
PVRecordStructurePtr pvParent = parent;
while(pvParent.get()!= NULL) {
while(pvParent) {
string parentName = pvParent->getPVField()->getFieldName();
if(parentName.size()>0) {
fullFieldName = pvParent->getPVField()->getFieldName()
@@ -434,7 +434,7 @@ void PVRecordField::removeListener(PVListenerPtr const & pvListener)
void PVRecordField::postPut()
{
if(parent!=NULL) {
if(parent) {
parent->postParent(getPtrSelf());
}
postSubField();
@@ -448,7 +448,7 @@ void PVRecordField::postParent(PVRecordFieldPtr const & subField)
{
(*iter)->dataPut(pvrs,subField);
}
if(parent!=NULL) parent->postParent(subField);
if(parent) parent->postParent(subField);
}
void PVRecordField::postSubField()

View File

@@ -70,7 +70,7 @@ typedef std::tr1::shared_ptr<ChannelArrayLocal> ChannelArrayLocalPtr;
static bool getProcess(PVStructurePtr pvRequest,bool processDefault)
{
PVFieldPtr pvField = pvRequest->getSubField("record._options.process");
if(pvField==NULL || pvField->getField()->getType()!=scalar) {
if(!pvField || pvField->getField()->getType()!=scalar) {
return processDefault;
}
ScalarConstPtr scalar = static_pointer_cast<const Scalar>(
@@ -146,13 +146,13 @@ ChannelProcessLocalPtr ChannelProcessLocal::create(
PVFieldPtr pvField;
PVStructurePtr pvOptions;
int nProcess = 1;
if(pvRequest!=NULL) pvField = pvRequest->getSubField("record._options");
if(pvField.get()!=NULL) {
if(pvRequest) pvField = pvRequest->getSubField("record._options");
if(pvField) {
pvOptions = static_pointer_cast<PVStructure>(pvField);
pvField = pvOptions->getSubField("nProcess");
if(pvField.get()!=NULL) {
if(pvField) {
PVStringPtr pvString = pvOptions->getStringField("nProcess");
if(pvString.get()!=NULL) {
if(pvString) {
int size;
std::stringstream ss;
ss << pvString->get();
@@ -291,7 +291,7 @@ ChannelGetLocalPtr ChannelGetLocal::create(
pvRecord->getPVRecordStructure()->getPVStructure(),
pvRequest,
"");
if(pvCopy==NULL) {
if(!pvCopy) {
Status status(
Status::STATUSTYPE_ERROR,
"invalid pvRequest");
@@ -442,7 +442,7 @@ ChannelPutLocalPtr ChannelPutLocal::create(
pvRecord->getPVRecordStructure()->getPVStructure(),
pvRequest,
"");
if(pvCopy==NULL) {
if(!pvCopy) {
Status status(
Status::STATUSTYPE_ERROR,
"invalid pvRequest");
@@ -624,7 +624,7 @@ ChannelPutGetLocalPtr ChannelPutGetLocal::create(
pvRecord->getPVRecordStructure()->getPVStructure(),
pvRequest,
"getField");
if(pvPutCopy==NULL || pvGetCopy==NULL) {
if(!pvPutCopy || !pvGetCopy) {
Status status(
Status::STATUSTYPE_ERROR,
"invalid pvRequest");
@@ -777,7 +777,7 @@ public:
PVArrayPtr const &putArray,
size_t offset, size_t count, size_t stride);
virtual void getLength();
virtual void setLength(size_t length, size_t capacity);
virtual void setLength(size_t length);
virtual void destroy();
virtual std::tr1::shared_ptr<Channel> getChannel()
{return channelLocal;}
@@ -841,8 +841,12 @@ ChannelArrayLocalPtr ChannelArrayLocal::create(
if(pvfs.size()!=1) break;
pvField = pvfs[0];
}
size_t indfield = fieldName.find_first_of("field.");
if(indfield==0) {
fieldName = fieldName.substr(6);
}
pvField = pvRecord->getPVRecordStructure()->getPVStructure()->getSubField(fieldName);
if(pvField==NULL) {
if(!pvField) {
Status status(
Status::STATUSTYPE_ERROR,fieldName +" not found");
ChannelArrayLocalPtr channelArray;
@@ -1021,7 +1025,7 @@ void ChannelArrayLocal::putArray(
return;
}
size_t newLength = offset + count*stride;
pvArray->setLength(newLength);
if(newLength<pvArray->getLength()) pvArray->setLength(newLength);
const char *exceptionMessage = NULL;
pvRecord->lock();
try {
@@ -1040,12 +1044,10 @@ void ChannelArrayLocal::putArray(
void ChannelArrayLocal::getLength()
{
size_t length = 0;
size_t capacity = 0;
const char *exceptionMessage = NULL;
pvRecord->lock();
try {
length = pvArray->getLength();
capacity = pvArray->getCapacity();
} catch(std::exception e) {
exceptionMessage = e.what();
}
@@ -1054,10 +1056,10 @@ void ChannelArrayLocal::getLength()
if(exceptionMessage!=NULL) {
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) {
channelArrayRequester->setLengthDone(channelDestroyedStatus,getPtrSelf());
@@ -1069,17 +1071,6 @@ void ChannelArrayLocal::setLength(size_t length, size_t capacity)
}
pvRecord->lock();
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(pvArray->getLength()!=length) pvArray->setLength(length);
}
@@ -1199,7 +1190,7 @@ void ChannelLocal::getField(GetFieldRequester::shared_pointer const &requester,
}
PVFieldPtr pvField =
pvRecord->getPVRecordStructure()->getPVStructure()->getSubField(subField);
if(pvField.get()!=NULL) {
if(pvField) {
requester->getDone(Status::Ok,pvField->getField());
return;
}
@@ -1308,7 +1299,7 @@ void ChannelLocal::printInfo()
void ChannelLocal::printInfo(std::ostream& out)
{
out << "ChannelLocal provides access to service";
out << "ChannelLocal provides access to a record in the local PVDatabase";
}
}}

View File

@@ -71,8 +71,10 @@ ChannelProviderLocalPtr getChannelProviderLocal()
if(channelProviderLocal.get()==NULL) {
channelProviderLocal = ChannelProviderLocalPtr(
new ChannelProviderLocal());
ChannelProvider::shared_pointer xxx = dynamic_pointer_cast<ChannelProvider>(channelProviderLocal);
channelProviderLocal->channelFinder = SyncChannelFind::shared_pointer(new SyncChannelFind(xxx));
ChannelProvider::shared_pointer xxx =
dynamic_pointer_cast<ChannelProvider>(channelProviderLocal);
channelProviderLocal->channelFinder =
SyncChannelFind::shared_pointer(new SyncChannelFind(xxx));
LocalChannelProviderFactory::create(channelProviderLocal);
}
return channelProviderLocal;

View File

@@ -22,8 +22,6 @@
#include <memory>
#include <set>
#include <shareLib.h>
#include <pv/lock.h>
#include <pv/pvType.h>
#include <pv/pvData.h>
@@ -37,6 +35,8 @@
# undef channelProviderLocalEpicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <pv/pvDatabase.h>
@@ -57,12 +57,32 @@ typedef std::tr1::shared_ptr<ChannelLocal> ChannelLocalPtr;
epicsShareExtern MonitorFactoryPtr getMonitorFactory();
/** MonitorFactory
* This class provides a static method to create a monitor for a PVRecord
*/
class epicsShareClass MonitorFactory
{
public:
POINTER_DEFINITIONS(MonitorFactory);
/**
* Destructor
*/
virtual ~MonitorFactory();
/**
* Destroy the monitor factory.
*/
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(
PVRecordPtr const & pvRecord,
epics::pvData::MonitorRequester::shared_pointer const & monitorRequester,
@@ -78,24 +98,79 @@ private:
epicsShareExtern ChannelProviderLocalPtr getChannelProviderLocal();
/**
* An implementation of channelProvider that provides access to records in PVDatabase.
*/
class epicsShareClass ChannelProviderLocal :
public epics::pvAccess::ChannelProvider,
public std::tr1::enable_shared_from_this<ChannelProviderLocal>
{
public:
POINTER_DEFINITIONS(ChannelProviderLocal);
/**
* Destructor
*/
virtual ~ChannelProviderLocal();
/**
* Destroy the channel provider.
* Probably never called.
*/
virtual void destroy();
/**
* Returns the channel provider name.
* @return <b>local</b>
*/
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(
std::string const &channelName,
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(
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(
std::string const &channelName,
epics::pvAccess::ChannelRequester::shared_pointer const &channelRequester,
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(
std::string const &channelName,
epics::pvAccess::ChannelRequester::shared_pointer const &channelRequester,
@@ -115,6 +190,10 @@ private:
friend class ChannelProviderLocalRun;
};
/**
* A Channel for accessing a record in the PVDatabase.
* It is a complete implementation of Channel
*/
class epicsShareClass ChannelLocal :
public epics::pvAccess::Channel,
public PVRecordClient,
@@ -122,54 +201,185 @@ class epicsShareClass ChannelLocal :
{
public:
POINTER_DEFINITIONS(ChannelLocal);
/** Constructor
* @param channelProvider The channel provider.
* @param requester The client callback.
* @param pvRecord The record the channel will access.
*/
ChannelLocal(
ChannelProviderLocalPtr const &channelProvider,
epics::pvAccess::ChannelRequester::shared_pointer const & requester,
PVRecordPtr const & pvRecord
);
/**
* Destructor
*/
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();
/**
* Get the requester name.
* @param returns the name of the channel requester.
*/
virtual std::string getRequesterName();
/**
* Passes the message to the channel requester.
* @param message The message.
* @param messageType The message type.
*/
virtual void message(
std::string const & message,
epics::pvData::MessageType messageType);
/**
* Get the channel provider
* @return The provider.
*/
virtual epics::pvAccess::ChannelProvider::shared_pointer getProvider()
{
return provider;
}
/**
* Get the remote address
* @return <b>local</b>
*/
virtual std::string getRemoteAddress();
/**
* Get the connection state.
* @return Channel::CONNECTED.
*/
virtual epics::pvAccess::Channel::ConnectionState getConnectionState();
/**
* Get the channel name.
* @return the record name.
*/
virtual std::string getChannelName();
/**
* Get the channel requester
* @return The channel requester.
*/
virtual epics::pvAccess::ChannelRequester::shared_pointer getChannelRequester();
/**
* Is the channel connected?
* @return true
*/
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(
epics::pvAccess::GetFieldRequester::shared_pointer const &requester,
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(
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(
epics::pvAccess::ChannelProcessRequester::shared_pointer const &requester,
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(
epics::pvAccess::ChannelGetRequester::shared_pointer const &requester,
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(
epics::pvAccess::ChannelPutRequester::shared_pointer const &requester,
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(
epics::pvAccess::ChannelPutGetRequester::shared_pointer const &requester,
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(
epics::pvAccess::ChannelRPCRequester::shared_pointer const &requester,
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(
epics::pvData::MonitorRequester::shared_pointer const &requester,
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(
epics::pvAccess::ChannelArrayRequester::shared_pointer const &requester,
epics::pvData::PVStructurePtr const &pvRequest);
/**
* calls printInfo(std::cout);
*/
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);
/**
* 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);
protected:
shared_pointer getPtrSelf()

View File

@@ -30,6 +30,7 @@ using std::string;
namespace epics { namespace pvDatabase {
static MonitorPtr nullMonitor;
static MonitorElementPtr NULLMonitorElement;
static Status wasDestroyedStatus(Status::STATUSTYPE_ERROR,"was destroyed");
@@ -37,52 +38,9 @@ static Status wasDestroyedStatus(Status::STATUSTYPE_ERROR,"was destroyed");
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 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 :
@@ -97,9 +55,10 @@ public:
virtual Status stop();
virtual MonitorElementPtr poll();
virtual void destroy();
virtual void dataChanged();
virtual void unlisten();
virtual void release(MonitorElementPtr const & monitorElement);
MonitorElementPtr getActiveElement();
MonitorElementPtr releaseActiveElement();
void unlisten();
bool init(PVStructurePtr const & pvRequest);
MonitorLocal(
MonitorRequester::shared_pointer const & channelMonitorRequester,
@@ -116,7 +75,8 @@ private:
bool isDestroyed;
bool firstMonitor;
PVCopyPtr pvCopy;
ElementQueuePtr queue;
MonitorElementQueuePtr queue;
MonitorElementPtr activeElement;
PVCopyMonitorPtr pvCopyMonitor;
Mutex mutex;
};
@@ -150,8 +110,6 @@ void MonitorLocal::destroy()
if(isDestroyed) return;
isDestroyed = true;
}
unlisten();
stop();
pvCopyMonitor->destroy();
pvCopy->destroy();
pvCopyMonitor.reset();
@@ -161,69 +119,76 @@ void MonitorLocal::destroy()
Status MonitorLocal::start()
{
Lock xx(mutex);
if(pvRecord->getTraceLevel()>0)
{
cout << "MonitorLocal::start() " << endl;
}
if(isDestroyed) return wasDestroyedStatus;
firstMonitor = true;
return queue->start();
{
Lock xx(mutex);
firstMonitor = true;
queue->clear();
activeElement = queue->getFree();
activeElement->changedBitSet->clear();
activeElement->overrunBitSet->clear();
}
pvCopyMonitor->startMonitoring(activeElement);
return Status::Ok;
}
Status MonitorLocal::stop()
{
pvCopyMonitor->stopMonitoring();
{
Lock xx(mutex);
if(pvRecord->getTraceLevel()>0){
cout << "MonitorLocal::stop() " << endl;
}
if(!isDestroyed) queue->stop();
if(pvRecord->getTraceLevel()>0){
cout << "MonitorLocal::stop() " << endl;
}
if(isDestroyed) return Status::Ok;
pvCopyMonitor->stopMonitoring();
return Status::Ok;
}
MonitorElementPtr MonitorLocal::poll()
{
Lock xx(mutex);
if(pvRecord->getTraceLevel()>1)
{
cout << "MonitorLocal::poll() " << endl;
}
if(isDestroyed) {
return NULLMonitorElement;
}
return queue->poll();
if(isDestroyed) return NULLMonitorElement;
Lock xx(mutex);
return queue->getUsed();
}
void MonitorLocal::release(MonitorElementPtr const & monitorElement)
{
Lock xx(mutex);
if(pvRecord->getTraceLevel()>1)
{
cout << "MonitorLocal::release() " << endl;
}
if(isDestroyed) {
return;
}
queue->release(monitorElement);
if(isDestroyed) return;
Lock xx(mutex);
queue->releaseUsed(monitorElement);
}
void MonitorLocal::dataChanged()
MonitorElementPtr MonitorLocal::releaseActiveElement()
{
if(pvRecord->getTraceLevel()>1)
{
cout << "MonitorLocal::dataChanged() " "firstMonitor " << firstMonitor << endl;
cout << "MonitorLocal::releaseActiveElement() " << endl;
}
bool getMonitorEvent = false;
if(isDestroyed) return activeElement;
{
Lock xx(mutex);
if(isDestroyed) return;
getMonitorEvent = queue->dataChanged();
firstMonitor = false;
MonitorElementPtr newActive = queue->getFree();
if(!newActive) return activeElement;
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 activeElement;
}
void MonitorLocal::unlisten()
@@ -292,11 +257,7 @@ bool MonitorLocal::init(PVStructurePtr const & pvRequest)
new MonitorElement(pvStructure));
monitorElementArray.push_back(monitorElement);
}
MonitorElementQueuePtr elementQueue(new MonitorElementQueue(monitorElementArray));
queue = MultipleElementQueuePtr(new MultipleElementQueue(
getPtrSelf(),
elementQueue,
nfields));
queue = MonitorElementQueuePtr(new MonitorElementQueue(monitorElementArray));
// MARTY MUST IMPLEMENT algorithm
monitorRequester->monitorConnect(
Status::Ok,
@@ -345,75 +306,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()
{

View File

@@ -58,7 +58,8 @@ PVCopyMonitor::PVCopyMonitor(
pvCopyMonitorRequester(pvCopyMonitorRequester),
isGroupPut(false),
dataChanged(false),
isMonitoring(false)
isMonitoring(false),
isDestroyed(false)
{
}
@@ -76,17 +77,17 @@ 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) {
if(pvOptions) {
PVStringPtr pvName = pvOptions->getSubField<PVString>("plugin");
if(pvName!=NULL) {
if(pvName) {
string pluginName = pvName->get();
MonitorPluginManagerPtr manager = MonitorPluginManager::get();
MonitorPluginCreatorPtr pluginCreator = manager->findPlugin(pluginName);
if(pluginCreator!=NULL) {
if(pluginCreator) {
StructureConstPtr top = pvCopy->getStructure();
FieldConstPtr field = pvField->getField();
MonitorPluginPtr monitorPlugin = pluginCreator->create(field,top,pvOptions);
if(monitorPlugin!=NULL) {
if(monitorPlugin) {
PVCopyMonitorFieldNodePtr fieldNode(new PVCopyMonitorFieldNode());
fieldNode->monitorPlugin = monitorPlugin;
fieldNode->offset = offset;
@@ -117,17 +118,22 @@ void PVCopyMonitor::destroy()
{
cout << "PVCopyMonitor::destroy()" << endl;
}
if(isDestroyed) return;
Lock xx(mutex);
isDestroyed = true;
stopMonitoring();
pvCopyMonitorRequester.reset();
pvCopy.reset();
}
void PVCopyMonitor::startMonitoring()
void PVCopyMonitor::startMonitoring(MonitorElementPtr const & startElement)
{
if(pvRecord->getTraceLevel()>0)
{
cout << "PVCopyMonitor::startMonitoring()" << endl;
}
if(isDestroyed) return;
monitorElement = startElement;
Lock xx(mutex);
if(isMonitoring) return;
isMonitoring = true;
@@ -137,14 +143,14 @@ void PVCopyMonitor::startMonitoring()
{
(*iter)->monitorPlugin->startMonitoring();
}
pvRecord->addListener(getPtrSelf());
pvRecord->lock();
try {
pvRecord->addListener(getPtrSelf());
pvCopy->traverseMaster(getPtrSelf());
monitorElement->changedBitSet->clear();
monitorElement->overrunBitSet->clear();
monitorElement->changedBitSet->set(0);
pvCopyMonitorRequester->dataChanged();
monitorElement = pvCopyMonitorRequester->releaseActiveElement();
pvRecord->unlock();
} catch(...) {
pvRecord->unlock();
@@ -162,41 +168,19 @@ void PVCopyMonitor::stopMonitoring()
{
cout << "PVCopyMonitor::stopMonitoring()" << endl;
}
Lock xx(mutex);
if(isDestroyed) return;
if(!isMonitoring) return;
pvRecord->removeListener(getPtrSelf());
Lock xx(mutex);
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)
{
@@ -208,27 +192,34 @@ void PVCopyMonitor::detach(PVRecordPtr const & pvRecord)
void PVCopyMonitor::dataPut(PVRecordFieldPtr const & pvRecordField)
{
if(pvRecord->getTraceLevel()>0)
if(pvRecord->getTraceLevel()>1)
{
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);
if(isDestroyed) return;
bool causeMonitor = true;
if(monitorPlugin!=NULL) {
causeMonitor = monitorPlugin->causeMonitor(
pvRecordField->getPVField(),
pvRecord->getPVRecordStructure()->getPVStructure(),
monitorElement);
{
Lock xx(mutex);
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);
if(monitorPlugin) {
causeMonitor = monitorPlugin->causeMonitor(
pvRecordField->getPVField(),
pvRecord->getPVRecordStructure()->getPVStructure(),
monitorElement);
}
if(causeMonitor) dataChanged = true;
}
if(causeMonitor) {
if(!isGroupPut) pvCopyMonitorRequester->dataChanged();
dataChanged = true;
if(!isGroupPut) {
monitorElement = pvCopyMonitorRequester->releaseActiveElement();
dataChanged = false;
}
}
}
@@ -236,42 +227,53 @@ void PVCopyMonitor::dataPut(
PVRecordStructurePtr const & requested,
PVRecordFieldPtr const & pvRecordField)
{
if(pvRecord->getTraceLevel()>0)
if(pvRecord->getTraceLevel()>1)
{
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);
if(isDestroyed) return;
bool causeMonitor = true;
if(monitorPlugin!=NULL) {
causeMonitor = monitorPlugin->causeMonitor(
requested->getPVField(),
pvRecord->getPVRecordStructure()->getPVStructure(),
monitorElement);
{
Lock xx(mutex);
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);
if(monitorPlugin) {
causeMonitor = monitorPlugin->causeMonitor(
requested->getPVField(),
pvRecord->getPVRecordStructure()->getPVStructure(),
monitorElement);
}
if(causeMonitor) dataChanged = true;
}
if(causeMonitor) {
if(!isGroupPut) pvCopyMonitorRequester->dataChanged();
dataChanged = true;
if(!isGroupPut) {
monitorElement = pvCopyMonitorRequester->releaseActiveElement();
dataChanged = false;
}
}
}
void PVCopyMonitor::beginGroupPut(PVRecordPtr const & pvRecord)
{
if(pvRecord->getTraceLevel()>0)
if(pvRecord->getTraceLevel()>1)
{
cout << "PVCopyMonitor::beginGroupPut()" << endl;
}
isGroupPut = true;
dataChanged = false;
if(isDestroyed) return;
{
Lock xx(mutex);
isGroupPut = true;
dataChanged = false;
}
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
for (iter = monitorFieldNodeList.begin();
iter!=monitorFieldNodeList.end();
@@ -283,27 +285,34 @@ void PVCopyMonitor::beginGroupPut(PVRecordPtr const & pvRecord)
void PVCopyMonitor::endGroupPut(PVRecordPtr const & pvRecord)
{
if(pvRecord->getTraceLevel()>0)
if(pvRecord->getTraceLevel()>1)
{
cout << "PVCopyMonitor::endGroupPut() dataChanged " << dataChanged << endl;
}
isGroupPut = false;
if(isDestroyed) return;
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
for (iter = monitorFieldNodeList.begin();iter!=monitorFieldNodeList.end();++iter)
{
(*iter)->monitorPlugin->endGroupPut();
}
{
Lock xx(mutex);
isGroupPut = false;
}
if(dataChanged) {
dataChanged = false;
pvCopyMonitorRequester->dataChanged();
monitorElement = pvCopyMonitorRequester->releaseActiveElement();
dataChanged = false;
}
}
void PVCopyMonitor::unlisten(PVRecordPtr const & pvRecord)
{
if(pvRecord->getTraceLevel()>1)
{
cout << "PVCopyMonitor::unlisten\n";
}
if(isDestroyed) return;
pvCopyMonitorRequester->unlisten();
}
}}

View File

@@ -21,8 +21,6 @@
#include <memory>
#include <list>
#include <shareLib.h>
#include <pv/monitorPlugin.h>
#include <pv/pvCopy.h>
#include <pv/pvAccess.h>
@@ -32,6 +30,8 @@
# undef pvCopyMonitorEpicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <pv/pvDatabase.h>
namespace epics { namespace pvDatabase {
@@ -45,6 +45,10 @@ struct PVCopyMonitorFieldNode;
typedef std::tr1::shared_ptr<PVCopyMonitorFieldNode> PVCopyMonitorFieldNodePtr;
/**
* PVCopyMonitor
* This class manages changes to fields being monitored in a PVRecord.
*/
class epicsShareClass PVCopyMonitor :
public PVListener,
public epics::pvData::PVCopyTraverseMasterCallback,
@@ -52,26 +56,80 @@ class epicsShareClass PVCopyMonitor :
{
public:
POINTER_DEFINITIONS(PVCopyMonitor);
/**
* Factory method to create a PVCopyMonoitor
* @param pvCopyMonitorRequester This is usually MonitorLocal.
* @param pvRecord The record being monitored.
* @param pvCopy An instance of pvCopy
* @return A shared pointer to a PVCopyMonitor.
*/
static PVCopyMonitorPtr create(
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester,
PVRecordPtr const &pvRecord,
epics::pvData::PVCopyPtr const & pvCopy);
/**
* Destructor
*/
virtual ~PVCopyMonitor();
/**
* Destroy the PVCopyMonitor
*/
virtual void destroy();
void startMonitoring();
/**
* Calls pvRecord methods to start monitoring for calls to postPut.
* @param monitorElement the initial monotorElement
* This holds the change and overrun bitSets that are updated
* when postPut is called.
*/
void startMonitoring(
epics::pvData::MonitorElementPtr const & monitorElement);
/**
* Calls pvRecord methods to stop monitoring for calls to postPut.
*/
void stopMonitoring();
void setMonitorElement(epics::pvData::MonitorElementPtr const &monitorElement);
void monitorDone(epics::pvData::MonitorElementPtr const &monitorElement);
// following are PVListener methods
/**
* The record is being removed from the PVDatabase.
* @param The record being removed.
*/
virtual void detach(PVRecordPtr const & pvRecord);
/**
* A postPut has been issued to a field being monitored.
* @param pvRecordField The field.
*/
virtual void dataPut(PVRecordFieldPtr const & pvRecordField);
/**
* A postPut has been issued to a subfield of a field being monitored.
* @param requested The field being monitored.
* @param pvRecordField The field being modified.
*/
virtual void dataPut(
PVRecordStructurePtr const & requested,
PVRecordFieldPtr const & pvRecordField);
/**
* A group of puts are being changed.
* No monitors should be issued until endGroupPut is called.
* @param pvRecord The record.
*/
virtual void beginGroupPut(PVRecordPtr const & pvRecord);
/**
* The end of a group of puts.
* If any fields have changed value since beginGroupPut a monitor
* can be issued.
* @param pvRecord The record.
*/
virtual void endGroupPut(PVRecordPtr const & pvRecord);
/**
* The record is being removed from the database.
* @param pvRecord The record.
*/
virtual void unlisten(PVRecordPtr const & pvRecord);
// following is PVCopyTraverseMasterCallback method
/**
* The PVCopyTraverseMasterCallback callback
* Called for every field of PVRecord that is being monoitored.
* @param pvField The field in the PVRecord.
*/
virtual void nextMasterPVField(epics::pvData::PVFieldPtr const &pvField);
private:
PVCopyMonitorPtr getPtrSelf()
@@ -91,6 +149,7 @@ private:
bool isGroupPut;
bool dataChanged;
bool isMonitoring;
bool isDestroyed;
epics::pvData::Mutex mutex;
std::list<PVCopyMonitorFieldNodePtr> monitorFieldNodeList;
};
@@ -100,7 +159,7 @@ class epicsShareClass PVCopyMonitorRequester
public:
POINTER_DEFINITIONS(PVCopyMonitorRequester);
virtual ~PVCopyMonitorRequester() {}
virtual void dataChanged() = 0;
virtual epics::pvData::MonitorElementPtr releaseActiveElement() = 0;
virtual void unlisten() = 0;
};

View File

@@ -27,12 +27,12 @@
#include <iocsh.h>
#include <shareLib.h>
#include <epicsExport.h>
#include <pv/pvAccess.h>
#include <pv/serverContext.h>
#define epicsExportSharedSymbols
// this declared epicsExportSharedSymbols
#include <epicsExport.h>
#include <pv/channelProviderLocal.h>
using std::cout;

View File

@@ -24,26 +24,16 @@ RecordListRecordPtr RecordListRecord::create(
{
FieldCreatePtr fieldCreate = getFieldCreate();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
StringArray argNames(2);
FieldConstPtrArray argFields(2);
argNames[0] = "database";
argFields[0] = fieldCreate->createScalar(pvString);
argNames[1] = "regularExpression";
argFields[1] = fieldCreate->createScalar(pvString);
StringArray resNames(2);
FieldConstPtrArray resFields(2);
resNames[0] = "status";
resFields[0] = fieldCreate->createScalar(pvString);
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);
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
addNestedStructure("argument")->
add("database",pvString)->
add("regularExpression",pvString)->
endNested()->
addNestedStructure("result") ->
add("status",pvString) ->
addArray("names",pvString) ->
endNested()->
createStructure();
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
RecordListRecordPtr pvRecord(
new RecordListRecord(recordName,pvStructure));
@@ -83,16 +73,16 @@ bool RecordListRecord::init()
std::cerr << "no result.names" << std::endl;
return false;
}
names = static_pointer_cast<PVStringArray>(
name = static_pointer_cast<PVStringArray>(
pvStructure->getScalarArrayField("result.names",pvString));
if(names.get()==NULL) return false;
if(name.get()==NULL) return false;
return true;
}
void RecordListRecord::process()
{
PVStringArrayPtr pvNames = PVDatabase::getMaster()->getRecordNames();
names->replace(pvNames->view());
name->replace(pvNames->view());
string message("");
if(database->get().compare("master")!=0) {
message += " can only access master ";

View File

@@ -20,16 +20,39 @@ namespace epics { namespace pvDatabase {
class RecordListRecord;
typedef std::tr1::shared_ptr<RecordListRecord> RecordListRecordPtr;
/**
* 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 :
public PVRecord
{
public:
POINTER_DEFINITIONS(RecordListRecord);
/**
* Factory methods to create RecordListRecord.
* @param recordName The name for the RecordListRecord.
* @return A shared pointer to RecordListRecord..
*/
static RecordListRecordPtr create(
std::string const & recordName);
/**
* destructor
*/
virtual ~RecordListRecord();
/**
* Clean up any resources used.
*/
virtual void destroy();
/**
* standard init method required by PVRecord
* @return true unless record name already exists.
*/
virtual bool init();
/*
* Generated the list of record names.
*/
virtual void process();
private:
RecordListRecord(std::string const & recordName,
@@ -37,7 +60,7 @@ private:
epics::pvData::PVStringPtr database;
epics::pvData::PVStringPtr regularExpression;
epics::pvData::PVStringPtr status;
epics::pvData::PVStringArrayPtr names;
epics::pvData::PVStringArrayPtr name;
};
}}

View File

@@ -24,24 +24,15 @@ TraceRecordPtr TraceRecord::create(
{
FieldCreatePtr fieldCreate = getFieldCreate();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
StringArray topNames(2);
FieldConstPtrArray topFields(2);
topNames[0] = "argument";
topNames[1] = "result";
StringArray argNames(2);
FieldConstPtrArray argFields(2);
argNames[0] = "recordName";
argNames[1] = "level";
argFields[0] = fieldCreate->createScalar(pvString);
argFields[1] = fieldCreate->createScalar(pvInt);
topFields[0] = fieldCreate->createStructure(argNames,argFields);
StringArray resNames(1);
FieldConstPtrArray resFields(1);
resNames[0] = "status";
resFields[0] = fieldCreate->createScalar(pvString);
topFields[1] = fieldCreate->createStructure(resNames,resFields);
StructureConstPtr topStructure =
fieldCreate->createStructure(topNames,topFields);
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
addNestedStructure("argument")->
add("recordName",pvString)->
add("level",pvInt)->
endNested()->
addNestedStructure("result") ->
add("status",pvString) ->
endNested()->
createStructure();
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
TraceRecordPtr pvRecord(
new TraceRecord(recordName,pvStructure));
@@ -72,11 +63,11 @@ bool TraceRecord::init()
initPVRecord();
PVStructurePtr pvStructure = getPVStructure();
pvRecordName = pvStructure->getStringField("argument.recordName");
if(pvRecordName==NULL) return false;
if(!pvRecordName) return false;
pvLevel = pvStructure->getIntField("argument.level");
if(pvLevel==NULL) return false;
if(!pvLevel) return false;
pvResult = pvStructure->getStringField("result.status");
if(pvResult==NULL) return false;
if(!pvResult) return false;
return true;
}
@@ -84,7 +75,7 @@ void TraceRecord::process()
{
string name = pvRecordName->get();
PVRecordPtr pvRecord = pvDatabase->findRecord(name);
if(pvRecord==NULL) {
if(!pvRecord) {
pvResult->put(name + " not found");
return;
}

View File

@@ -18,6 +18,12 @@
namespace epics { namespace pvDatabase {
/**
* 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 TraceRecord;
typedef std::tr1::shared_ptr<TraceRecord> TraceRecordPtr;
@@ -26,11 +32,29 @@ class epicsShareClass TraceRecord :
{
public:
POINTER_DEFINITIONS(TraceRecord);
/**
* Factory methods to create TraceRecord.
* @param recordName The name for the TraceRecord.
* @return A shared pointer to TraceRecord..
*/
static TraceRecordPtr create(
std::string const & recordName);
/**
* destructor
*/
virtual ~TraceRecord();
/**
* Clean up any resources used.
*/
virtual void destroy();
/**
* standard init method required by PVRecord
* @return true unless record name already exists.
*/
virtual bool init();
/**
* Set the trace level.
*/
virtual void process();
private:
TraceRecord(

View File

@@ -35,5 +35,6 @@
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
-include $(TOP)/configure/CONFIG_SITE.local
-include $(TOP)/../CONFIG.local
-include $(TOP)/../configure/CONFIG_SITE.local
-include $(TOP)/../../CONFIG.local

View File

@@ -9,12 +9,17 @@
* @date 2013.04.02
*/
#include "powerSupply.h"
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#define epicsExportSharedSymbols
#include "powerSupply.h"
using namespace epics::pvData;
using std::string;
using std::cout;
using std::cerr;
using std::endl;
namespace epics { namespace pvDatabase {
@@ -24,24 +29,23 @@ PVStructurePtr createPowerSupply()
StandardFieldPtr standardField = getStandardField();
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(
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(
@@ -77,62 +81,40 @@ bool PowerSupply::init()
PVFieldPtr pvField;
bool result;
pvField = pvStructure->getSubField("timeStamp");
if(pvField.get()==NULL) {
std::cerr << "no timeStamp" << std::endl;
if(!pvField) {
cerr << "no timeStamp" << endl;
return false;
}
result = pvTimeStamp.attach(pvField);
if(!result) {
std::cerr << "no timeStamp" << std::endl;
cerr << "no timeStamp" << endl;
return false;
}
pvField = pvStructure->getSubField("alarm");
if(pvField.get()==NULL) {
std::cerr << "no alarm" << std::endl;
if(!pvField) {
cerr << "no alarm" << endl;
return false;
}
result = pvAlarm.attach(pvField);
if(!result) {
std::cerr << "no alarm" << std::endl;
cerr << "no alarm" << endl;
return false;
}
string name;
name = "current.value";
pvField = pvStructure->getSubField(name);
if(pvField.get()==NULL) {
name = "current";
pvField = pvStructure->getSubField(name);
}
if(pvField.get()==NULL) {
std::cerr << "no current" << std::endl;
pvCurrent = pvStructure->getSubField<PVDouble>("current.value");
if(!pvCurrent) {
cerr << "no current\n";
return false;
}
pvCurrent = pvStructure->getDoubleField(name);
if(pvCurrent.get()==NULL) return false;
name = "voltage.value";
pvField = pvStructure->getSubField(name);
if(pvField.get()==NULL) {
name = "voltage";
pvField = pvStructure->getSubField(name);
}
if(pvField.get()==NULL) {
std::cerr << "no voltage" << std::endl;
pvVoltage = pvStructure->getSubField<PVDouble>("voltage.value");
if(!pvVoltage) {
cerr << "no current\n";
return false;
}
pvVoltage = pvStructure->getDoubleField(name);
if(pvVoltage.get()==NULL) return false;
name = "power.value";
pvField = pvStructure->getSubField(name);
if(pvField.get()==NULL) {
name = "power";
pvField = pvStructure->getSubField(name);
}
if(pvField.get()==NULL) {
std::cerr << "no power" << std::endl;
pvPower = pvStructure->getSubField<PVDouble>("power.value");
if(!pvPower) {
cerr << "no powert\n";
return false;
}
pvPower = pvStructure->getDoubleField(name);
if(pvPower.get()==NULL) return false;
return true;
}

View File

@@ -11,13 +11,25 @@
#ifndef 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/alarm.h>
#include <pv/pvTimeStamp.h>
#include <pv/pvAlarm.h>
#include <pv/pvDatabase.h>
#ifdef powerSupplyEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef powerSupplyEpicsExportSharedSymbols
#endif
#include <shareLib.h>
namespace epics { namespace pvDatabase {
@@ -26,7 +38,7 @@ epicsShareExtern epics::pvData::PVStructurePtr createPowerSupply();
class PowerSupply;
typedef std::tr1::shared_ptr<PowerSupply> PowerSupplyPtr;
class PowerSupply :
class epicsShareClass PowerSupply :
public PVRecord
{
public:

View File

@@ -27,12 +27,12 @@
#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 <epicsExport.h>
#include <pv/powerSupply.h>
using namespace epics::pvData;
@@ -69,4 +69,4 @@ static void powerSupplyRegister(void)
extern "C" {
epicsExportRegistrar(powerSupplyRegister);
}
}

View File

@@ -23,14 +23,14 @@
#include <epicsEvent.h>
#include <epicsThread.h>
#include <epicsExport.h>
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/pvData.h>
#include <pv/pvAccess.h>
#include "powerSupply.h"
#include <epicsExport.h>
using namespace std;
using std::tr1::static_pointer_cast;
using namespace epics::pvData;

View File

@@ -236,21 +236,21 @@ static void scalarTest()
valueNameRecord = request = "value";
CreateRequest::shared_pointer createRequest = CreateRequest::create();
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,"");
valueNameCopy = "value";
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
request = "";
valueNameRecord = "value";
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,"");
valueNameCopy = "value";
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
request = "alarm,timeStamp,value";
valueNameRecord = "value";
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,"");
valueNameCopy = "value";
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
@@ -273,21 +273,21 @@ static void arrayTest()
pvRecord = createScalarArray("doubleArrayRecord",pvDouble,"alarm,timeStamp");
valueNameRecord = request = "value";
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,"");
valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy);
request = "";
valueNameRecord = "value";
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,"");
valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy);
request = "alarm,timeStamp,value";
valueNameRecord = "value";
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,"");
valueNameCopy = "value";
testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy);
@@ -311,28 +311,28 @@ static void powerSupplyTest()
pvRecord = PowerSupply::create("powerSupply",pv);
valueNameRecord = request = "power.value";
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,"");
valueNameCopy = "power.value";
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
request = "";
valueNameRecord = "power.value";
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,"");
valueNameCopy = "power.value";
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
request = "alarm,timeStamp,voltage.value,power.value,current.value";
valueNameRecord = "power.value";
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,"");
valueNameCopy = "power.value";
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
request = "alarm,timeStamp,voltage{value,alarm},power{value,alarm,display},current.value";
valueNameRecord = "power.value";
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,"");
valueNameCopy = "power.value";
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);