52 Commits

Author SHA1 Message Date
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
Marty Kraimer
5d823307f0 make records double00, ..., double04 2014-06-25 09:16:31 -04:00
Marty Kraimer
d41d5726d2 add records for testing easyPVAJava multiChannel 2014-06-24 15:05:19 -04:00
Matej Sekoranja
723f98bc44 added extern C on epicsExportRegistrar 2014-06-20 09:16:35 +02:00
Matej Sekoranja
1544147bdd win dll linkage 2014-06-20 08:56:39 +02:00
Matej Sekoranja
0447441cfa toString replaced with <<operator 2014-06-20 08:38:54 +02:00
Matej Sekoranja
8ce42ebb9a String -> std::string, toString methods removed, take 2 2014-06-19 14:55:44 +02:00
Matej Sekoranja
c39b966121 String -> std::string, toString methods removed 2014-06-19 14:30:40 +02:00
Marty Kraimer
61edf17cdf fix bug related to stride 2014-06-13 09:53:46 -04:00
Matej Sekoranja
39f537d7da win port: visibility declarations added/fixed 2014-06-13 11:43:22 +02:00
Matej Sekoranja
ba496de2d3 VxWorks fix: there is no Status::Status type 2014-06-13 11:04:29 +02:00
Marty Kraimer
38574ed76f support for ChannelArray UnionArray 2014-06-12 15:27:26 -04:00
Marty Kraimer
92be294bbf merge feature/changesAfter3_0_2; resolve conflicts 2014-06-10 15:53:37 -04:00
Marty Kraimer
35429bf4df flow: Merged <feature> 'changesAfter3_0_2' to <develop> ('default'). 2014-06-10 09:05:48 -04:00
Marty Kraimer
552925dfe6 flow: Closed <feature> 'changesAfter3_0_2'. 2014-06-10 08:55:18 -04:00
Marty Kraimer
d1791393ad Added tag before_merge_changesAfter3_0_2 for changeset abdc90bf52a0 2014-06-10 08:53:33 -04:00
Matej Sekoranja
3dbad700f7 channelList implemented 2014-06-09 22:19:52 +02:00
Marty Kraimer
c06e33e197 better implementation of ChannelArray::getLength 2014-06-09 07:55:08 -04:00
Marty Kraimer
1d8f01517a more work on stride 2014-06-06 11:28:41 -04:00
Marty Kraimer
8c1b142e48 working on support for stride for ChannelArray 2014-06-05 10:23:51 -04:00
Marty Kraimer
ca27cb5e3c changes for new pvAccess API 2014-06-04 10:48:12 -04:00
Marty Kraimer
a5fa17aca7 pvAccess added method cancel 2014-04-23 11:01:14 -04:00
Marty Kraimer
fe62a7181f use copy and monitor from pvDataCPP; imlement example plugin; algorithm => plugin 2014-04-23 09:25:58 -04:00
Marty Kraimer
342ab45dc8 changes for changesAfter3_0_2
pvCopy modified and moved to pvDataCPP
2014-04-01 14:07:43 -04:00
Marty Kraimer
127830e3c7 flow: Created branch 'feature/changesAfter3_0_2'. 2014-03-25 07:18:10 -04:00
121 changed files with 6807 additions and 2613 deletions

View File

@@ -7,5 +7,5 @@ db/
dbd/
documentation/html
envPaths
RELEASE.local
configure/.*\.local
/O\..*

View File

@@ -1 +1,6 @@
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

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

@@ -1,25 +1,27 @@
# Makefile for the EPICS V4 pvDatabase module
#Makefile at top of application tree
TOP = .
include $(TOP)/configure/CONFIG
DIRS := $(DIRS) $(filter-out $(DIRS), configure)
DIRS := $(DIRS) $(filter-out $(DIRS), src)
DIRS := $(DIRS) $(filter-out $(DIRS), test)
DIRS := $(DIRS) $(filter-out $(DIRS), arrayPerformance)
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard example*))
DIRS := configure
EMBEDDED_TOPS := $(EMBEDDED_TOPS) $(filter-out $(EMBEDDED_TOPS), test)
EMBEDDED_TOPS := $(EMBEDDED_TOPS) $(filter-out $(EMBEDDED_TOPS), arrayPerformance)
EMBEDDED_TOPS := $(EMBEDDED_TOPS) $(filter-out $(EMBEDDED_TOPS), $(wildcard example*))
DIRS += src
src_DEPEND_DIRS = configure
define DIR_template
$(1)_DEPEND_DIRS = configure
endef
$(foreach dir, $(filter-out configure,$(DIRS)),$(eval $(call DIR_template,$(dir))))
EMBEDDED_TOPS := $(wildcard *Top)
EMBEDDED_TOPS += $(wildcard example*)
DIRS += $(EMBEDDED_TOPS)
define dir_DEP
define EMB_template
$(1)_DEPEND_DIRS = src
endef
$(foreach dir, $(EMBEDDED_TOPS),$(eval $(call EMB_template,$(dir))))
$(foreach dir, $(EMBEDDED_TOPS), $(eval $(call dir_DEP,$(dir))))
exampleDatabase_DEPEND_DIRS += testTop
examplePowerSupply_DEPEND_DIRS += testTop
#exampleDatabase_DEPEND_DIRS += test
#examplePowerSupply_DEPEND_DIRS += test
include $(TOP)/configure/RULES_TOP

View File

@@ -1,8 +1,6 @@
# Makefile at top of application tree
#Makefile at top of application tree
TOP = .
include $(TOP)/configure/CONFIG
DIRS += configure
DIRS += src

View File

@@ -14,11 +14,26 @@
# Set CHECK_RELEASE to NO to disable checking completely.
# Set CHECK_RELEASE to WARN to perform consistency checking but
# continue building anyway if conflicts are found.
CHECK_RELEASE = YES
#CHECK_RELEASE = YES
# Set this when you only want to compile this application
# for a subset of the cross-compiled target architectures
# that Base is built for.
#CROSS_COMPILER_TARGET_ARCHS = vxWorks-68040
# To install files into a location other than $(TOP) define
# INSTALL_LOCATION here.
#INSTALL_LOCATION=</path/name/to/install/top>
# Set this when your IOC and the host use different paths
# to access the application. This will be needed to boot
# from a Microsoft FTP server or with some NFS mounts.
# You must rebuild in the iocBoot directory for this to
# take effect.
#IOCS_APPL_TOP = </IOC/path/to/application/top>
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
-include $(TOP)/../configure/CONFIG_SITE.local
-include $(TOP)/../../CONFIG.local

View File

@@ -1,4 +1,4 @@
# pvDatabaseCPP/arrayPerfTop RELEASE - Location of external support modules
# pvDatabaseCPP/arrayPerformance RELEASE - Location of external support modules
#
# IF YOU CHANGE this file or any file it includes you must
# subsequently do a "gnumake rebuild" in the application's
@@ -16,9 +16,8 @@
# EPICS V4 Developers: Do not edit the locations in this file!
#
# Create a file RELEASE.local pointing to your PVASRV, PVACCESS,
# PVDATA, PVCOMMON and EPICS_BASE build directories, e.g.
# PVASRV = /path/to/epics/pvaSrvCPP
# Create a file RELEASE.local pointing to your places
# for the dependencies, e.g.
# PVACCESS = /path/to/epics/pvAccessCPP
# PVDATA = /path/to/epics/pvDataCPP
# PVCOMMON = /path/to/epics/pvCommonCPP
@@ -28,14 +27,14 @@
# use the following definitions:
PVDATABASE = $(TOP)/..
-include $(TOP)/../configure/RELEASE.local
-include $(TOP)/../../RELEASE.local
-include $(TOP)/../configure/RELEASE.local
# If you copied this example from pvDatabaseCPP to be built as a
# standalone TOP, adjust and use the following definitions:
# standalone TOP, define
# PVDATABASE = /path/to/epics/pvDatabaseCPP
# in the appropriate RELEASE[.local],
# and use the following definitions instead:
#PVDATABASE = /path/to/epics/pvDatabaseCPP
#-include $(TOP)/configure/RELEASE.local
#-include $(TOP)/../RELEASE.local
#-include $(TOP)/configure/RELEASE.local

View File

@@ -26,7 +26,7 @@ using std::endl;
using std::ostringstream;
ArrayPerformancePtr ArrayPerformance::create(
epics::pvData::String const & recordName,
std::string const & recordName,
size_t size,
double delay)
{
@@ -39,7 +39,7 @@ ArrayPerformancePtr ArrayPerformance::create(
}
ArrayPerformance::ArrayPerformance(
epics::pvData::String const & recordName,
std::string const & recordName,
epics::pvData::PVStructurePtr const & pvStructure,
size_t size,
double delay)
@@ -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>
@@ -44,7 +43,7 @@ class epicsShareClass ArrayPerformance :
public:
POINTER_DEFINITIONS(ArrayPerformance);
static ArrayPerformancePtr create(
epics::pvData::String const & recordName,
std::string const & recordName,
size_t size,
double delay);
virtual ~ArrayPerformance();
@@ -53,7 +52,7 @@ public:
virtual void process();
virtual void destroy();
private:
ArrayPerformance(epics::pvData::String const & recordName,
ArrayPerformance(std::string const & recordName,
epics::pvData::PVStructurePtr const & pvStructure,
size_t size,
double delay);
@@ -81,7 +80,7 @@ private:
ArrayPerformancePtr arrayPerformance;
bool isDestroyed;
bool runReturned;
epics::pvData::String threadName;
std::string threadName;
epics::pvData::Mutex mutex;
epics::pvData::int64 value;
std::auto_ptr<epicsThread> thread;

View File

@@ -39,15 +39,15 @@ using namespace epics::pvDatabase;
int main(int argc,char *argv[])
{
bool result(false);
String recordName;
string recordName;
recordName = "arrayPerformance";
size_t size = 10000000;
double delay = .0001;
String providerName("local");
string providerName("local");
size_t nMonitor = 1;
int queueSize = 2;
double waitTime = 0.0;
if(argc==2 && String(argv[1])==String("-help")) {
if(argc==2 && string(argv[1])==string("-help")) {
cout << "arrayPerformanceMain recordName size";
cout << " delay providerName nMonitor queueSize waitTime" << endl;
cout << "default" << endl;
@@ -83,7 +83,7 @@ int main(int argc,char *argv[])
pvRecord = ArrayPerformance::create(recordName,size,delay);
result = master->addRecord(pvRecord);
PVRecordPtr arrayPreformance = pvRecord;
arrayPreformance->setTraceLevel(1);
arrayPreformance->setTraceLevel(0);
pvRecord = TraceRecord::create("traceRecordPGRPC");
result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;

View File

@@ -24,9 +24,10 @@ using std::tr1::dynamic_pointer_cast;
using std::cout;
using std::endl;
using std::ostringstream;
using std::string;
static String requesterName("longArrayGet");
static String request("value,timeStamp,alarm");
static string requesterName("longArrayGet");
static string request("value,timeStamp,alarm");
static epics::pvData::Mutex printMutex;
class LongArrayChannelRequester;
@@ -52,8 +53,8 @@ public:
isDestroyed = true;
longArrayChannelGet.reset();
}
virtual String getRequesterName() { return requesterName;}
virtual void message(String const & message, MessageType messageType)
virtual string getRequesterName() { return requesterName;}
virtual void message(string const & message, MessageType messageType)
{
Lock guard(printMutex);
cout << requesterName << " message " << message << endl;
@@ -93,18 +94,21 @@ public:
isDestroyed = true;
longArrayChannelGet.reset();
}
virtual String getRequesterName() { return requesterName;}
virtual void message(String const & message, MessageType messageType)
virtual string getRequesterName() { return requesterName;}
virtual void message(string const & message, MessageType messageType)
{
Lock guard(printMutex);
cout << requesterName << " message " << message << endl;
}
virtual void channelGetConnect(
Status const & status,
ChannelGet::shared_pointer const & channelGet,
StructureConstPtr const &structure);
virtual void getDone(
Status const & status,
ChannelGet::shared_pointer const & channelGet,
PVStructurePtr const &pvStructure,
BitSetPtr const &bitSet);
virtual void getDone(Status const & status);
BitSetPtr const & bitSet);
private:
LongArrayChannelGetRequesterPtr getPtrSelf()
{
@@ -123,8 +127,8 @@ class LongArrayChannelGet :
{
public:
LongArrayChannelGet(
String providerName,
String channelName,
string providerName,
string channelName,
int iterBetweenCreateChannel,
int iterBetweenCreateChannelGet,
double delayTime)
@@ -141,7 +145,7 @@ public:
bool init();
virtual void destroy();
virtual void run();
void message(String const & message, MessageType messageType)
void message(string const & message, MessageType messageType)
{
Lock guard(printMutex);
cout << requesterName << " message " << message << endl;
@@ -155,23 +159,26 @@ public:
virtual void channelGetConnect(
Status const & status,
ChannelGet::shared_pointer const & channelGet,
StructureConstPtr const &structure);
virtual void getDone(
Status const & status,
ChannelGet::shared_pointer channelGet,
PVStructurePtr const &pvStructure,
BitSetPtr const &bitSet);
virtual void getDone(Status const & status);
BitSetPtr const & bitSet);
private:
LongArrayChannelGetPtr getPtrSelf()
{
return shared_from_this();
}
size_t checkResult();
String providerName;
String channelName;
string providerName;
string channelName;
int iterBetweenCreateChannel;
int iterBetweenCreateChannelGet;
double delayTime;
bool isDestroyed;
bool runReturned;
epics::pvData::String threadName;
std::string threadName;
Status status;
Event event;
Mutex mutex;
@@ -197,7 +204,7 @@ void LongArrayChannelRequester::channelStateChange(
Channel::shared_pointer const & channel,
Channel::ConnectionState connectionState)
{
String mess(Channel::ConnectionStateNames[connectionState]);
string mess(Channel::ConnectionStateNames[connectionState]);
message(mess,infoMessage);
Lock guard(mutex);
if(isDestroyed) return;
@@ -206,21 +213,24 @@ void LongArrayChannelRequester::channelStateChange(
void LongArrayChannelGetRequester::channelGetConnect(
Status const & status,
ChannelGet::shared_pointer const & channelGet,
PVStructurePtr const &pvStructure,
BitSetPtr const &bitSet)
ChannelGet::shared_pointer const & channelGet,
StructureConstPtr const &structure)
{
Lock guard(mutex);
if(isDestroyed) return;
longArrayChannelGet->channelGetConnect(
status,channelGet,pvStructure,bitSet);
status,channelGet,structure);
}
void LongArrayChannelGetRequester::getDone(Status const & status)
void LongArrayChannelGetRequester::getDone(
Status const & status,
ChannelGet::shared_pointer const & channelGet,
PVStructurePtr const &pvStructure,
BitSetPtr const & bitSet)
{
Lock guard(mutex);
if(isDestroyed) return;
longArrayChannelGet->getDone(status);
longArrayChannelGet->getDone(status,channelGet,pvStructure,bitSet);
}
void LongArrayChannelGet::channelCreated(
@@ -241,12 +251,10 @@ void LongArrayChannelGet::channelStateChange(
(connectionState==Channel::CONNECTED ? infoMessage : errorMessage);
message("channelStateChange",messageType);
}
void LongArrayChannelGet::channelGetConnect(
Status const & status,
ChannelGet::shared_pointer const & channelGet,
PVStructurePtr const &pvStructure,
BitSetPtr const &bitSet)
StructureConstPtr const &structure)
{
this->status = status;
if(!status.isOK()) {
@@ -255,13 +263,12 @@ void LongArrayChannelGet::channelGetConnect(
return;
}
this->channelGet = channelGet;
this->pvStructure = pvStructure;
this->bitSet = bitSet;
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();
@@ -273,7 +280,7 @@ void LongArrayChannelGet::channelGetConnect(
}
}
if(!structureOK) {
String mess("channelGetConnect: illegal structure");
string mess("channelGetConnect: illegal structure");
message(mess,errorMessage);
this->status = Status(Status::STATUSTYPE_ERROR,mess);
}
@@ -284,8 +291,8 @@ void LongArrayChannelGet::channelGetConnect(
bool LongArrayChannelGet::init()
{
ChannelProvider::shared_pointer channelProvider =
getChannelAccess()->getProvider(providerName);
if(channelProvider==NULL) {
getChannelProviderRegistry()->getProvider(providerName);
if(!channelProvider) {
cout << "provider " << providerName << " not found" << endl;
return false;
}
@@ -298,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;
}
@@ -327,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();
@@ -355,7 +362,7 @@ void LongArrayChannelGet::run()
int numChannelCreate = 0;
size_t nElements = 0;
while(true) {
channelGet->get(false);
channelGet->get();
event.wait();
if(isDestroyed) {
runReturned = true;
@@ -398,7 +405,7 @@ void LongArrayChannelGet::run()
longArrayChannelRequester->destroy();
channel->destroy();
ChannelProvider::shared_pointer channelProvider =
getChannelAccess()->getProvider(providerName);
getChannelProviderRegistry()->getProvider(providerName);
longArrayChannelRequester.reset(new LongArrayChannelRequester(getPtrSelf()));
channel = channelProvider->createChannel(
channelName,
@@ -426,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 ;
}
@@ -445,10 +452,14 @@ void LongArrayChannelGet::run()
}
}
void LongArrayChannelGet::getDone(Status const & status)
void LongArrayChannelGet::getDone(
Status const & status,
ChannelGet::shared_pointer channelGet,
PVStructurePtr const &pvStructure,
BitSetPtr const & bitSet)
{
this->pvStructure = pvStructure;
this->bitSet = bitSet;
event.signal();
}
@@ -477,8 +488,8 @@ size_t LongArrayChannelGet::checkResult()
LongArrayGetPtr LongArrayGet::create(
String const &providerName,
String const & channelName,
string const &providerName,
string const & channelName,
int iterBetweenCreateChannel,
int iterBetweenCreateChannelGet,
double delayTime)
@@ -495,8 +506,8 @@ LongArrayGetPtr LongArrayGet::create(
}
LongArrayGet::LongArrayGet(
String const &providerName,
String const & channelName,
string const &providerName,
string const & channelName,
int iterBetweenCreateChannel,
int iterBetweenCreateChannelGet,
double delayTime)

View File

@@ -17,8 +17,6 @@
# undef epicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <pv/event.h>
#include <pv/lock.h>
#include <pv/standardPVField.h>
@@ -49,8 +47,8 @@ class epicsShareClass LongArrayGet :
public:
POINTER_DEFINITIONS(LongArrayGet);
static LongArrayGetPtr create(
epics::pvData::String const & providerName,
epics::pvData::String const & channelName,
std::string const & providerName,
std::string const & channelName,
int iterBetweenCreateChannel = 0,
int iterBetweenCreateChannelGet = 0,
double delayTime = 0.0);
@@ -62,15 +60,15 @@ private:
return shared_from_this();
}
LongArrayGet(
epics::pvData::String const & providerName,
epics::pvData::String const & channelName,
std::string const & providerName,
std::string const & channelName,
int iterBetweenCreateChannel = 0,
int iterBetweenCreateChannelGet = 0,
double delayTime = 0.0);
bool init();
epics::pvData::String providerName;
epics::pvData::String channelName;
std::string providerName;
std::string channelName;
int iterBetweenCreateChannel;
int iterBetweenCreateChannelGet;
double delayTime;

View File

@@ -38,11 +38,11 @@ using namespace epics::pvDatabase;
int main(int argc,char *argv[])
{
String channelName("arrayPerformance");
string channelName("arrayPerformance");
int iterBetweenCreateChannel = 0;
int iterBetweenCreateChannelGet = 0;
double delayTime = 1.0;
if(argc==2 && String(argv[1])==String("-help")) {
if(argc==2 && string(argv[1])==string("-help")) {
cout << "longArrayGetMain channelName ";
cout << "iterBetweenCreateChannel iterBetweenCreateChannelGet delayTime" << endl;
cout << "default" << endl;

View File

@@ -25,11 +25,12 @@ using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
using std::cout;
using std::endl;
using std::string;
using std::ostringstream;
static String requesterName("longArrayMonitor");
static string requesterName("longArrayMonitor");
static void messagePvt(String const & message, MessageType messageType)
static void messagePvt(string const & message, MessageType messageType)
{
cout << requesterName << " message " << message << endl;
}
@@ -43,8 +44,8 @@ public:
{}
virtual ~LAMChannelRequester(){}
virtual void destroy(){longArrayMonitor.reset();}
virtual String getRequesterName() { return requesterName;}
virtual void message(String const & message, MessageType messageType)
virtual string getRequesterName() { return requesterName;}
virtual void message(string const & message, MessageType messageType)
{ messagePvt(message,messageType);}
virtual void channelCreated(const Status& status, Channel::shared_pointer const & channel);
virtual void channelStateChange(Channel::shared_pointer const & channel, Channel::ConnectionState connectionState);
@@ -83,8 +84,8 @@ public:
void init();
virtual void destroy();
virtual void run();
virtual String getRequesterName() { return requesterName;}
virtual void message(String const & message, MessageType messageType)
virtual string getRequesterName() { return requesterName;}
virtual void message(string const & message, MessageType messageType)
{ messagePvt(message,messageType);}
virtual void monitorConnect(Status const & status,
MonitorPtr const & monitor, StructureConstPtr const & structure);
@@ -95,7 +96,7 @@ private:
double waitTime;
bool isDestroyed;
bool runReturned;
epics::pvData::String threadName;
std::string threadName;
Event event;
Mutex mutex;
std::auto_ptr<epicsThread> thread;
@@ -137,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) {
@@ -150,7 +151,7 @@ void LAMMonitorRequester::monitorConnect(Status const & status,
}
}
if(!structureOK) {
String message("monitorConnect: illegal structure");
string message("monitorConnect: illegal structure");
messagePvt(message,errorMessage);
longArrayMonitor->status = Status(Status::STATUSTYPE_ERROR,message);
}
@@ -178,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);
@@ -200,12 +201,8 @@ void LAMMonitorRequester::run()
out << "first " << first << " last " << last ;
BitSetPtr changed = monitorElement->changedBitSet;
BitSetPtr overrun = monitorElement->overrunBitSet;
String buffer;
changed->toString(&buffer);
out << " changed " << buffer;
buffer.clear();
overrun->toString(&buffer);
out << " overrun " << buffer;
out << " changed " << *changed;
out << " overrun " << *overrun;
double elementsPerSec = nElements;
elementsPerSec /= diff;
if(elementsPerSec>10.0e9) {
@@ -246,8 +243,8 @@ void LAMMonitorRequester::unlisten(MonitorPtr const & monitor)
LongArrayMonitorPtr LongArrayMonitor::create(
String const &providerName,
String const & channelName,
string const &providerName,
string const & channelName,
int queueSize,
double waitTime)
{
@@ -261,30 +258,31 @@ LongArrayMonitor::LongArrayMonitor() {}
LongArrayMonitor::~LongArrayMonitor() {}
bool LongArrayMonitor::init(
String const &providerName,
String const &channelName,
string const &providerName,
string const &channelName,
int queueSize,
double waitTime)
{
channelRequester = LAMChannelRequesterPtr(new LAMChannelRequester(getPtrSelf()));
monitorRequester = LAMMonitorRequesterPtr(new LAMMonitorRequester(getPtrSelf(),waitTime));
monitorRequester->init();
ChannelProvider::shared_pointer channelProvider = getChannelAccess()->getProvider(providerName);
if(channelProvider==NULL) {
ChannelProvider::shared_pointer channelProvider =
getChannelProviderRegistry()->getProvider(providerName);
if(!channelProvider) {
cout << "provider " << providerName << " not found" << endl;
return false;
}
channel = channelProvider->createChannel(channelName,channelRequester,0);
event.wait();
if(!status.isOK()) return false;
String request("record[queueSize=");
string request("record[queueSize=");
char buff[20];
sprintf(buff,"%d",queueSize);
request += buff;
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>
@@ -49,8 +48,8 @@ class epicsShareClass LongArrayMonitor :
public:
POINTER_DEFINITIONS(LongArrayMonitor);
static LongArrayMonitorPtr create(
epics::pvData::String const & providerName,
epics::pvData::String const & channelName,
std::string const & providerName,
std::string const & channelName,
int queueSize = 1,
double waitTime = 0.0);
~LongArrayMonitor();
@@ -60,8 +59,8 @@ public:
private:
static epics::pvData::Mutex printMutex;
bool init(
epics::pvData::String const & providerName,
epics::pvData::String const & channelName,
std::string const & providerName,
std::string const & channelName,
int queueSize,
double waitTime);
LongArrayMonitorPtr getPtrSelf()

View File

@@ -38,10 +38,10 @@ using namespace epics::pvDatabase;
int main(int argc,char *argv[])
{
String channelName("arrayPerformance");
string channelName("arrayPerformance");
int queueSize = 2;
double waitTime = 0.0;
if(argc==2 && String(argv[1])==String("-help")) {
if(argc==2 && string(argv[1])==string("-help")) {
cout << "longArrayMonitorMain channelName queueSize waitTime" << endl;
cout << "default" << endl;
cout << "longArrayMonitorMain " << channelName << " ";

View File

@@ -24,9 +24,10 @@ using std::tr1::dynamic_pointer_cast;
using std::cout;
using std::endl;
using std::ostringstream;
using std::string;
static String requesterName("longArrayPut");
static String request("value");
static string requesterName("longArrayPut");
static string request("value");
static epics::pvData::Mutex printMutex;
class LongArrayChannelPut :
@@ -37,8 +38,8 @@ class LongArrayChannelPut :
{
public:
LongArrayChannelPut(
String providerName,
String channelName,
string providerName,
string channelName,
size_t arraySize,
int iterBetweenCreateChannel,
int iterBetweenCreateChannelPut,
@@ -57,8 +58,8 @@ public:
bool init();
virtual void destroy();
virtual void run();
virtual String getRequesterName() { return requesterName;}
virtual void message(String const & message, MessageType messageType)
virtual string getRequesterName() { return requesterName;}
virtual void message(string const & message, MessageType messageType)
{
Lock guard(printMutex);
cout << requesterName << " message " << message << endl;
@@ -70,26 +71,31 @@ public:
Channel::shared_pointer const & channel,
Channel::ConnectionState connectionState);
virtual void channelPutConnect(
Status const & status,
ChannelPut::shared_pointer const & channelPut,
StructureConstPtr const &structure);
virtual void putDone(
Status const & status,
ChannelPut::shared_pointer const & channelPut);
virtual void getDone(
Status const & status,
ChannelPut::shared_pointer const & channelPut,
PVStructurePtr const &pvStructure,
BitSetPtr const &bitSet);
virtual void putDone(Status const & status);
virtual void getDone(Status const & status){}
BitSetPtr const & bitSet){}
private:
LongArrayChannelPutPtr getPtrSelf()
{
return shared_from_this();
}
String providerName;
String channelName;
string providerName;
string channelName;
size_t arraySize;
int iterBetweenCreateChannel;
int iterBetweenCreateChannelPut;
double delayTime;
bool isDestroyed;
bool runReturned;
epics::pvData::String threadName;
std::string threadName;
Status status;
Event event;
Mutex mutex;
@@ -103,8 +109,8 @@ private:
bool LongArrayChannelPut::init()
{
ChannelProvider::shared_pointer channelProvider = getChannelAccess()->getProvider(providerName);
if(channelProvider==NULL) {
ChannelProvider::shared_pointer channelProvider = getChannelProviderRegistry()->getProvider(providerName);
if(!channelProvider) {
cout << "provider " << providerName << " not found" << endl;
return false;
}
@@ -113,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;
}
@@ -168,8 +174,7 @@ void LongArrayChannelPut::channelStateChange(
void LongArrayChannelPut::channelPutConnect(
Status const & status,
ChannelPut::shared_pointer const & channelPut,
PVStructurePtr const &pvStructure,
BitSetPtr const &bitSet)
StructureConstPtr const &structure)
{
this->status = status;
if(!status.isOK()) {
@@ -178,11 +183,11 @@ void LongArrayChannelPut::channelPutConnect(
return;
}
this->channelPut = channelPut;
this->pvStructure = pvStructure;
this->bitSet = bitSet;
pvStructure = getPVDataCreate()->createPVStructure(structure);
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();
@@ -194,7 +199,7 @@ void LongArrayChannelPut::channelPutConnect(
}
}
if(!structureOK) {
String mess("channelPutConnect: illegal structure");
string mess("channelPutConnect: illegal structure");
message(mess,errorMessage);
this->status = Status(Status::STATUSTYPE_ERROR,mess);
}
@@ -222,7 +227,7 @@ void LongArrayChannelPut::run()
shared_vector<const int64> data(freeze(xxx));
pvLongArray->replace(data);
bitSet->set(pvLongArray->getFieldOffset());
channelPut->put(false);
channelPut->put(pvStructure,bitSet);
event.wait();
if(isDestroyed) {
runReturned = true;
@@ -262,9 +267,8 @@ void LongArrayChannelPut::run()
if(iterBetweenCreateChannel!=0) {
if(numChannelCreate>=iterBetweenCreateChannel) {
channel->destroy();
epicsThreadSleep(1.0);
ChannelProvider::shared_pointer channelProvider =
getChannelAccess()->getProvider(providerName);
getChannelProviderRegistry()->getProvider(providerName);
channel = channelProvider->createChannel(
channelName,getPtrSelf(),0);
event.wait();
@@ -290,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 ;
}
@@ -310,15 +314,17 @@ void LongArrayChannelPut::run()
}
}
void LongArrayChannelPut::putDone(Status const & status)
void LongArrayChannelPut::putDone(
Status const & status,
ChannelPut::shared_pointer const & channelPut)
{
event.signal();
}
LongArrayPutPtr LongArrayPut::create(
String const &providerName,
String const & channelName,
string const &providerName,
string const & channelName,
size_t arraySize,
int iterBetweenCreateChannel,
int iterBetweenCreateChannelPut,
@@ -337,8 +343,8 @@ LongArrayPutPtr LongArrayPut::create(
}
LongArrayPut::LongArrayPut(
String const &providerName,
String const & channelName,
string const &providerName,
string const & channelName,
size_t arraySize,
int iterBetweenCreateChannel,
int iterBetweenCreateChannelPut,

View File

@@ -17,7 +17,6 @@
# undef epicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <pv/event.h>
#include <pv/lock.h>
#include <pv/standardPVField.h>
@@ -48,8 +47,8 @@ class epicsShareClass LongArrayPut :
public:
POINTER_DEFINITIONS(LongArrayPut);
static LongArrayPutPtr create(
epics::pvData::String const & providerName,
epics::pvData::String const & channelName,
std::string const & providerName,
std::string const & channelName,
size_t arraySize = 100,
int iterBetweenCreateChannel = 0,
int iterBetweenCreateChannelPut = 0,
@@ -62,16 +61,16 @@ private:
return shared_from_this();
}
LongArrayPut(
epics::pvData::String const & providerName,
epics::pvData::String const & channelName,
std::string const & providerName,
std::string const & channelName,
size_t arraySize,
int iterBetweenCreateChannel,
int iterBetweenCreateChannelPut,
double delayTime);
bool init();
epics::pvData::String providerName;
epics::pvData::String channelName;
std::string providerName;
std::string channelName;
size_t arraySize;
int iterBetweenCreateChannel;
int iterBetweenCreateChannelPut;

View File

@@ -38,12 +38,12 @@ using namespace epics::pvDatabase;
int main(int argc,char *argv[])
{
String channelName("arrayPerformance");
string channelName("arrayPerformance");
size_t arraySize = 10;
int iterBetweenCreateChannel = 0;
int iterBetweenCreateChannelPut = 0;
double delayTime = 1.0;
if(argc==2 && String(argv[1])==String("-help")) {
if(argc==2 && string(argv[1])==string("-help")) {
cout << "longArrayPutMain channelName arraySize ";
cout << "iterBetweenCreateChannel iterBetweenCreateChannelPut delayTime" << endl;
cout << "default" << endl;

View File

@@ -140,7 +140,7 @@ int main(int argc,char *argv[])
size_t size = 50000000;
double delay = .01;
size_t nThread = 1;
if(argc==2 && String(argv[1])==String("-help")) {
if(argc==2 && string(argv[1])==string("-help")) {
cout << "vectorPerformanceMain size delay nThread" << endl;
cout << "default" << endl;
cout << "vectorPerformance ";

View File

@@ -14,11 +14,14 @@
# Set CHECK_RELEASE to NO to disable checking completely.
# Set CHECK_RELEASE to WARN to perform consistency checking but
# continue building anyway if conflicts are found.
CHECK_RELEASE = YES
#CHECK_RELEASE = YES
# To install files into a location other than $(TOP) define
# INSTALL_LOCATION here.
#INSTALL_LOCATION=</path/name/to/install/top>
-include $(TOP)/configure/CONFIG_SITE.local
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I $(INSTALL_LOCATION)/include
-include $(TOP)/../CONFIG.local
-include $(TOP)/configure/CONFIG_SITE.local

View File

@@ -1,11 +1,8 @@
# Sample RELEASE.local file
V4 = /home/install/epics/v4
PVASRV = $(V4)/pvaSrv
PVACCESS = $(V4)/pvAccessCPP
PVDATA = $(V4)/pvDataCPP
PVCOMMON = $(V4)/pvCommonCPP
EPICS_BASE = /home/install/epics/base-3.14.12.3
TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
EPICS_BASE=/home/install/epics/base
PVCOMMON=/home/hg/pvCommonCPP
PVDATA=/home/hg/pvDataCPP
PVACCESS=/home/hg/pvAccessCPP
PVASRV=/home/hg/pvaSrv

View File

@@ -24,5 +24,5 @@
# PVCOMMON = /path/to/epics/pvCommonCPP
# EPICS_BASE = /path/to/epics/base
-include $(TOP)/configure/RELEASE.local
-include $(TOP)/../RELEASE.local
-include $(TOP)/configure/RELEASE.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

8
documentation/TODO.html Normal file
View File

@@ -0,0 +1,8 @@
<h1>TODO</h1>
<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>

19
documentation/TODO.md Normal file
View File

@@ -0,0 +1,19 @@
TODO
===========
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

@@ -20,5 +20,8 @@ CHECK_RELEASE = WARN
# INSTALL_LOCATION here.
#INSTALL_LOCATION=</path/name/to/install/top>
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

View File

@@ -27,7 +27,7 @@
# If this example is built in a directory under pvDatabaseCPP,
# use the following definitions:
PVDATABASETEST = $(TOP)/../testTop
PVDATABASETEST = $(TOP)/../test
PVDATABASE = $(TOP)/..
-include $(TOP)/../configure/RELEASE.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

@@ -3,23 +3,26 @@ TOP=../..
include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================
#==================================================
# Build an IOC support library
#
DBD += exampleDatabase.dbd
exampleDatabase_DBD += base.dbd
exampleDatabase_DBD += PVAServerRegister.dbd
exampleDatabase_DBD += registerChannelProviderLocal.dbd
exampleDatabase_DBD += dbPv.dbd
exampleDatabase_DBD += powerSupplyRegister.dbd
exampleDatabase_DBD += exampleDatabaseRegister.dbd
#=============================
# build an ioc application
PROD_IOC += exampleDatabase
# <name>_registerRecordDeviceDriver.cpp will be created from <name>.dbd
exampleDatabase_SRCS += exampleDatabase_registerRecordDeviceDriver.cpp
exampleDatabase_SRCS_DEFAULT += exampleDatabaseMain.cpp
exampleDatabase_SRCS_vxWorks += -nil-
# The following adds support from base/src/vxWorks
exampleDatabase_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary

View File

@@ -0,0 +1,7 @@
include "base.dbd"
include "PVAServerRegister.dbd"
include "registerChannelProviderLocal.dbd"
include "dbPv.dbd"
include "powerSupplyRegister.dbd"
registrar("exampleDatabaseRegister")
registrar("exampleMonitorPluginRegister")

View File

@@ -7,15 +7,23 @@ dbLoadDatabase("dbd/exampleDatabase.dbd")
exampleDatabase_registerRecordDeviceDriver(pdbbase)
## Load record instances
dbLoadRecords("db/dbScalar.db","name=double01,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()
dbl
epicsThreadSleep(2.0)
exampleDatabase
exampleMonitorPlugin
startPVAServer
pvdbl

View File

@@ -4,17 +4,21 @@ include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
DBD += exampleDatabaseRegister.dbd
DBD += exampleDatabase.dbd
INC += exampleDatabase.h
INC += exampleMonitorPlugin.h
LIBRARY += exampleDatabase
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
exampleDatabase_LIBS += Com
exampleDatabase_LIBS += $(EPICS_BASE_IOC_LIBS)
PROD_HOST += exampleDatabaseMain

View File

@@ -26,8 +26,10 @@
#include <pv/recordList.h>
#include <pv/traceRecord.h>
#include <powerSupply.h>
#include <exampleDatabase.h>
#include <pv/powerSupply.h>
#define epicsExportSharedSymbols
#include <pv/exampleDatabase.h>
using namespace std;
using std::tr1::static_pointer_cast;
@@ -42,18 +44,57 @@ static StandardPVFieldPtr standardPVField = getStandardPVField();
static void createStructureArrayRecord(
PVDatabasePtr const &master,
ScalarType scalarType,
String const &recordName)
string const &recordName)
{
StructureConstPtr structure = standardField->scalar(
pvDouble,
String("value,alarm,timeStamp"));
StringArray names(2);
FieldConstPtrArray fields(2);
names[0] = "timeStamp";
names[0] = "name";
names[1] = "value";
fields[0] = standardField->timeStamp();
fields[1] = fieldCreate->createStructureArray(structure);
fields[0] = fieldCreate->createScalar(pvString);
fields[1] = fieldCreate->createScalar(pvString);
StringArray topNames(1);
FieldConstPtrArray topFields(1);
topNames[0] = "value";
topFields[0] = fieldCreate->createStructureArray(
fieldCreate->createStructure(names, fields));
StructureConstPtr top = fieldCreate->createStructure(topNames,topFields);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(top);
PVRecordPtr pvRecord = PVRecord::create(recordName,pvStructure);
bool result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;
}
static void createRegularUnionArrayRecord(
PVDatabasePtr const &master,
string const &recordName)
{
StringArray unionNames(2);
FieldConstPtrArray unionFields(2);
unionNames[0] = "string";
unionNames[1] = "stringArray";
unionFields[0] = fieldCreate->createScalar(pvString);
unionFields[1] = fieldCreate->createScalarArray(pvString);
StringArray names(1);
FieldConstPtrArray fields(1);
fields[0] = fieldCreate->createUnionArray(fieldCreate->createUnion(unionNames,unionFields));
names[0] = "value";
StructureConstPtr top = fieldCreate->createStructure(names,fields);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(top);
PVRecordPtr pvRecord = PVRecord::create(recordName,pvStructure);
bool result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;
}
static void createVariantUnionArrayRecord(
PVDatabasePtr const &master,
string const &recordName)
{
StringArray names(1);
FieldConstPtrArray fields(1);
fields[0] = fieldCreate->createVariantUnionArray();
names[0] = "value";
StructureConstPtr top = fieldCreate->createStructure(names,fields);
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(top);
PVRecordPtr pvRecord = PVRecord::create(recordName,pvStructure);
@@ -64,10 +105,10 @@ static void createStructureArrayRecord(
static void createRecords(
PVDatabasePtr const &master,
ScalarType scalarType,
String const &recordNamePrefix,
String const &properties)
string const &recordNamePrefix,
string const &properties)
{
String recordName = recordNamePrefix;
string recordName = recordNamePrefix;
PVStructurePtr pvStructure = standardPVField->scalar(scalarType,properties);
PVRecordPtr pvRecord = PVRecord::create(recordName,pvStructure);
bool result = master->addRecord(pvRecord);
@@ -82,13 +123,13 @@ void ExampleDatabase::create()
{
PVDatabasePtr master = PVDatabase::getMaster();
PVRecordPtr pvRecord;
String recordName;
string recordName;
bool result(false);
recordName = "traceRecordPGRPC";
pvRecord = TraceRecord::create(recordName);
result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;
String properties;
string properties;
properties = "alarm,timeStamp";
createRecords(master,pvBoolean,"exampleBoolean",properties);
createRecords(master,pvByte,"exampleByte",properties);
@@ -97,21 +138,31 @@ void ExampleDatabase::create()
createRecords(master,pvLong,"exampleLong",properties);
createRecords(master,pvFloat,"exampleFloat",properties);
createRecords(master,pvDouble,"exampleDouble",properties);
createRecords(master,pvDouble,"exampleDouble01",properties);
createRecords(master,pvDouble,"exampleDouble02",properties);
createRecords(master,pvDouble,"exampleDouble03",properties);
createRecords(master,pvDouble,"exampleDouble04",properties);
createRecords(master,pvDouble,"exampleDouble05",properties);
createRecords(master,pvString,"exampleString",properties);
createStructureArrayRecord(master,pvDouble,"exampleStructureArray");
createStructureArrayRecord(master,"exampleStructureArray");
createRegularUnionArrayRecord(master,"exampleRegularUnionArray");
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

@@ -0,0 +1,2 @@
registrar("exampleDatabaseRegister")
registrar("exampleMonitorPluginRegister")

View File

@@ -22,7 +22,8 @@
#include <pv/channelProviderLocal.h>
#include <pv/serverContext.h>
#include <exampleDatabase.h>
#include <pv/exampleDatabase.h>
#include <pv/exampleMonitorPlugin.h>
using namespace std;
using std::tr1::static_pointer_cast;
@@ -36,13 +37,12 @@ int main(int argc,char *argv[])
PVDatabasePtr master = PVDatabase::getMaster();
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
ExampleDatabase::create();
ExampleMonitorPlugin::create();
ServerContext::shared_pointer ctx =
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
cout << "exampleDatabase\n";
PVStringArrayPtr pvNames = master->getRecordNames();
String buffer;
pvNames->toString(&buffer);
cout << "recordNames" << endl << buffer << endl;
cout << "recordNames" << endl << *pvNames << endl;
string str;
while(true) {
cout << "Type exit to stop: \n";
@@ -55,4 +55,3 @@ int main(int argc,char *argv[])
channelProvider->destroy();
return 0;
}

View File

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

View File

@@ -1 +0,0 @@
registrar("exampleDatabaseRegister")

View File

@@ -0,0 +1,101 @@
/* 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>
#define epicsExportSharedSymbols
#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) {
PVStringPtr pvString =
pvFieldOptions->getSubField<PVString>("raiseMonitor");
if(pvString) {
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) {
plugin = OnChangePluginCreatorPtr(new OnChangePluginCreator());
MonitorPluginManager::get()->addPlugin(pluginName,plugin);
}
}
}}

View File

@@ -0,0 +1,40 @@
/* 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
#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{
public:
static void create();
};
}}
#endif /* EXAMPLEMONITORPLUGIN_H */

View File

@@ -0,0 +1,65 @@
/*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 <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;
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);
}

View File

@@ -1,8 +1,6 @@
# Makefile at top of application tree
#Makefile at top of application tree
TOP = .
include $(TOP)/configure/CONFIG
DIRS += configure
DIRS += src
@@ -12,7 +10,6 @@ DIRS += ioc
ioc_DEPEND_DIRS = src
DIRS += iocBoot
iocBoot_DEPEND_DIRS = src
include $(TOP)/configure/RULES_TOP

View File

@@ -14,11 +14,26 @@
# Set CHECK_RELEASE to NO to disable checking completely.
# Set CHECK_RELEASE to WARN to perform consistency checking but
# continue building anyway if conflicts are found.
CHECK_RELEASE = WARN
#CHECK_RELEASE = YES
# Set this when you only want to compile this application
# for a subset of the cross-compiled target architectures
# that Base is built for.
#CROSS_COMPILER_TARGET_ARCHS = vxWorks-68040
# To install files into a location other than $(TOP) define
# INSTALL_LOCATION here.
#INSTALL_LOCATION=</path/name/to/install/top>
# Set this when your IOC and the host use different paths
# to access the application. This will be needed to boot
# from a Microsoft FTP server or with some NFS mounts.
# You must rebuild in the iocBoot directory for this to
# take effect.
#IOCS_APPL_TOP = </IOC/path/to/application/top>
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

View File

@@ -16,9 +16,8 @@
# EPICS V4 Developers: Do not edit the locations in this file!
#
# Create a file RELEASE.local pointing to your PVASRV, PVACCESS,
# PVDATA, PVCOMMON and EPICS_BASE build directories, e.g.
# PVASRV = /path/to/epics/pvaSrvCPP
# Create a file RELEASE.local pointing to your places
# for the dependencies, e.g.
# PVACCESS = /path/to/epics/pvAccessCPP
# PVDATA = /path/to/epics/pvDataCPP
# PVCOMMON = /path/to/epics/pvCommonCPP
@@ -28,14 +27,14 @@
# use the following definitions:
PVDATABASE = $(TOP)/..
-include $(TOP)/../configure/RELEASE.local
-include $(TOP)/../../RELEASE.local
-include $(TOP)/../configure/RELEASE.local
# If you copied this example from pvDatabaseCPP to be built as a
# standalone TOP, adjust and use the following definitions:
# standalone TOP, define
# PVDATABASE = /path/to/epics/pvDatabaseCPP
# in the appropriate RELEASE[.local],
# and use the following definitions instead:
#PVDATABASE = /path/to/epics/pvDatabaseCPP
#-include $(TOP)/configure/RELEASE.local
#-include $(TOP)/../RELEASE.local
#-include $(TOP)/configure/RELEASE.local

View File

@@ -3,22 +3,27 @@ TOP=../..
include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================
#==================================================
# Build an IOC support library
#
#=============================
# build an ioc application
DBD += exampleLink.dbd
exampleLink_DBD += base.dbd
exampleLink_DBD += PVAServerRegister.dbd
exampleLink_DBD += PVAClientRegister.dbd
exampleLink_DBD += registerChannelProviderLocal.dbd
exampleLink_DBD += exampleLinkRegister.dbd
PROD_IOC += exampleLink
# <name>_registerRecordDeviceDriver.cpp will be created from <name>.dbd
exampleLink_SRCS += exampleLink_registerRecordDeviceDriver.cpp
exampleLink_SRCS_DEFAULT += exampleLinkMain.cpp
exampleLink_SRCS_vxWorks += -nil-
# The following adds support from base/src/vxWorks
exampleLink_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary
@@ -27,6 +32,7 @@ exampleLink_LIBS += pvDatabase
exampleLink_LIBS += pvaSrv
exampleLink_LIBS += pvAccess
exampleLink_LIBS += pvData
exampleLink_LIBS += Com
exampleLink_LIBS += $(EPICS_BASE_IOC_LIBS)
#===========================

View File

@@ -0,0 +1,5 @@
include "base.dbd"
include "PVAServerRegister.dbd"
include "PVAClientRegister.dbd"
include "registerChannelProviderLocal.dbd"
registrar("exampleLinkRegister")

View File

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

View File

@@ -3,8 +3,13 @@ TOP=..
include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================
DBD += exampleLinkRegister.dbd
#==================================================
# Build an IOC support library
#
DBD += exampleLink.dbd
INC += exampleLink.h

View File

@@ -12,22 +12,23 @@
#include <pv/standardPVField.h>
#include <pv/convert.h>
#define epicsExportSharedSymbols
#include <exampleLink.h>
#define epicsExportSharedSymbols
#include <pv/exampleLink.h>
namespace epics { namespace pvDatabase {
using namespace epics::pvData;
using namespace epics::pvAccess;
using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
using std::cout;
using std::endl;
using std::string;
namespace epics { namespace pvDatabase {
ExampleLinkPtr ExampleLink::create(
String const & recordName,
String const & providerName,
String const & channelName)
string const & recordName,
string const & providerName,
string const & channelName)
{
PVStructurePtr pvStructure = getStandardPVField()->scalarArray(
pvDouble,"alarm.timeStamp");
@@ -39,9 +40,9 @@ ExampleLinkPtr ExampleLink::create(
}
ExampleLink::ExampleLink(
String const & recordName,
String providerName,
String channelName,
string const & recordName,
string providerName,
string channelName,
PVStructurePtr const & pvStructure)
: PVRecord(recordName,pvStructure),
providerName(providerName),
@@ -64,13 +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;
}
ChannelAccess::shared_pointer channelAccess = getChannelAccess();
ChannelProvider::shared_pointer provider =
channelAccess->getProvider(providerName);
if(provider==NULL) {
getChannelProviderRegistry()->getProvider(providerName);
if(!provider) {
cout << getRecordName() << " provider "
<< providerName << " does not exist" << endl;
return false;
@@ -97,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;
}
@@ -107,7 +107,7 @@ bool ExampleLink::init()
void ExampleLink::process()
{
status = Status::Ok;
channelGet->get(false);
channelGet->get();
event.wait();
timeStamp.getCurrent();
pvTimeStamp.set(timeStamp);
@@ -145,20 +145,24 @@ void ExampleLink::channelStateChange(
void ExampleLink::channelGetConnect(
const Status& status,
ChannelGet::shared_pointer const & channelGet,
PVStructure::shared_pointer const & pvStructure,
BitSet::shared_pointer const & bitSet)
StructureConstPtr const & structure)
{
this->status = status;
this->channelGet = channelGet;
this->getPVStructure = pvStructure;
getPVStructure = getPVDataCreate()->createPVStructure(structure);
event.signal();
}
void ExampleLink::getDone(
const Status& status,
ChannelGet::shared_pointer const & channelGet,
PVStructurePtr const & pvStructure,
BitSetPtr const & bitSet)
{
this->status = status;
convert->copyStructure(pvStructure,getPVStructure);
this->bitSet = bitSet;
event.signal();
}
void ExampleLink::getDone(const Status& status)
{
this->status = status;
event.signal();
}
}}

View File

@@ -8,15 +8,14 @@
* @author mrk
* @date 2013.08.02
*/
#ifndef EXAMPLELINK_H
#define EXAMPLELINK_H
#ifndef EXAMPLEPVADOUBLEARRAYGET_H
#define EXAMPLEPVADOUBLEARRAYGET_H
#ifdef epicsExportSharedSymbols
# define examplelinkEpicsExportSharedSymbols
# define exampleLinkEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
//#include <shareLib.h>
#include <pv/timeStamp.h>
#include <pv/pvTimeStamp.h>
#include <pv/alarm.h>
@@ -26,13 +25,12 @@
#include <pv/pvAccess.h>
#include <pv/serverContext.h>
#ifdef examplelinkEpicsExportSharedSymbols
#ifdef exampleLinkEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef examplelinkEpicsExportSharedSymbols
# include <shareLib.h>
# undef exampleLinkEpicsExportSharedSymbols
#endif
#include <shareLib.h>
namespace epics { namespace pvDatabase {
@@ -48,9 +46,9 @@ class epicsShareClass ExampleLink :
public:
POINTER_DEFINITIONS(ExampleLink);
static ExampleLinkPtr create(
epics::pvData::String const & recordName,
epics::pvData::String const & providerName,
epics::pvData::String const & channelName
std::string const & recordName,
std::string const & providerName,
std::string const & channelName
);
virtual ~ExampleLink() {}
virtual void destroy();
@@ -65,23 +63,26 @@ public:
virtual void channelGetConnect(
const epics::pvData::Status& status,
epics::pvAccess::ChannelGet::shared_pointer const & channelGet,
epics::pvData::PVStructure::shared_pointer const & pvStructure,
epics::pvData::BitSet::shared_pointer const & bitSet);
virtual void getDone(const epics::pvData::Status& status);
virtual epics::pvData::String getRequesterName() {return channelName;}
epics::pvData::StructureConstPtr const & structure);
virtual void getDone(
const epics::pvData::Status& status,
epics::pvAccess::ChannelGet::shared_pointer const & channelGet,
epics::pvData::PVStructurePtr const & pvStructure,
epics::pvData::BitSetPtr const &bitSet);
virtual std::string getRequesterName() {return channelName;}
virtual void message(
epics::pvData::String const & message,
std::string const & message,
epics::pvData::MessageType messageType)
{
std::cout << "Why is ExampleLink::message called\n";
}
private:
ExampleLink(epics::pvData::String const & recordName,
epics::pvData::String providerName,
epics::pvData::String channelName,
ExampleLink(std::string const & recordName,
std::string providerName,
std::string channelName,
epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::String providerName;
epics::pvData::String channelName;
std::string providerName;
std::string channelName;
epics::pvData::ConvertPtr convert;
epics::pvData::PVDoubleArrayPtr pvValue;
epics::pvData::PVTimeStamp pvTimeStamp;
@@ -99,4 +100,4 @@ private:
}}
#endif /* EXAMPLELINK_H */
#endif /* EXAMPLEPVADOUBLEARRAYGET_H */

View File

@@ -0,0 +1 @@
registrar("exampleLinkRegister")

View File

@@ -35,14 +35,14 @@
#include <pv/pvDatabase.h>
#include <epicsExport.h>
#include <exampleLink.h>
#include <pv/exampleLink.h>
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvDatabase;
using std::cout;
using std::endl;
using std::string;
static StandardPVFieldPtr standardPVField = getStandardPVField();
@@ -59,7 +59,7 @@ static void exampleLinkCallFunc(const iocshArgBuf *args)
PVDatabasePtr master = PVDatabase::getMaster();
PVRecordPtr pvRecord;
bool result(false);
String recordName;
string recordName;
PVStructurePtr pvStructure = standardPVField->scalarArray(
pvDouble,"alarm,timeStamp");
pvRecord = PVRecord::create("doubleArray",pvStructure);
@@ -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;
}

View File

@@ -14,11 +14,26 @@
# Set CHECK_RELEASE to NO to disable checking completely.
# Set CHECK_RELEASE to WARN to perform consistency checking but
# continue building anyway if conflicts are found.
CHECK_RELEASE = WARN
#CHECK_RELEASE = YES
# Set this when you only want to compile this application
# for a subset of the cross-compiled target architectures
# that Base is built for.
#CROSS_COMPILER_TARGET_ARCHS = vxWorks-68040
# To install files into a location other than $(TOP) define
# INSTALL_LOCATION here.
#INSTALL_LOCATION=</path/name/to/install/top>
# Set this when your IOC and the host use different paths
# to access the application. This will be needed to boot
# from a Microsoft FTP server or with some NFS mounts.
# You must rebuild in the iocBoot directory for this to
# take effect.
#IOCS_APPL_TOP = </IOC/path/to/application/top>
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

View File

@@ -16,9 +16,8 @@
# EPICS V4 Developers: Do not edit the locations in this file!
#
# Create a file RELEASE.local pointing to your PVASRV, PVACCESS,
# PVDATA, PVCOMMON and EPICS_BASE build directories, e.g.
# PVASRV = /path/to/epics/pvaSrvCPP
# Create a file RELEASE.local pointing to your places
# for the dependencies, e.g.
# PVACCESS = /path/to/epics/pvAccessCPP
# PVDATA = /path/to/epics/pvDataCPP
# PVCOMMON = /path/to/epics/pvCommonCPP
@@ -27,17 +26,17 @@
# If this example is built in a directory under pvDatabaseCPP,
# use the following definitions:
PVDATABASETEST = $(TOP)/../testTop
PVDATABASE = $(TOP)/..
-include $(TOP)/../configure/RELEASE.local
PVDATABASETEST = $(TOP)/../test
-include $(TOP)/../../RELEASE.local
-include $(TOP)/../configure/RELEASE.local
# If you copied this example from pvDatabaseCPP to be built as a
# standalone TOP, adjust and use the following definitions:
#PVDATABASETEST = /path/to/epics/pvDatabaseCPP/testTop
#PVDATABASE = /path/to/epics/pvDatabaseCPP
# standalone TOP, define
# PVDATABASE = /path/to/epics/pvDatabaseCPP
# PVDATABASETEST = /path/to/epics/pvDatabaseCPP/test
# in the appropriate RELEASE[.local],
# and use the following definitions instead:
#-include $(TOP)/../RELEASE.local
#-include $(TOP)/configure/RELEASE.local

View File

@@ -3,22 +3,26 @@ TOP=../..
include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================
#==================================================
# Build an IOC support library
#
DBD += powerSupply.dbd
powerSupply_DBD += base.dbd
powerSupply_DBD += PVAServerRegister.dbd
powerSupply_DBD += registerChannelProviderLocal.dbd
powerSupply_DBD += dbPv.dbd
powerSupply_DBD += powerSupplyRegister.dbd
#=============================
# build an ioc application
PROD_IOC += powerSupply
# <name>_registerRecordDeviceDriver.cpp will be created from <name>.dbd
powerSupply_SRCS += powerSupply_registerRecordDeviceDriver.cpp
powerSupply_SRCS_DEFAULT += powerSupplyMain.cpp
powerSupply_SRCS_vxWorks += -nil-
# The following adds support from base/src/vxWorks
powerSupply_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary

View File

@@ -0,0 +1,5 @@
include "base.dbd"
include "PVAServerRegister.dbd"
include "registerChannelProviderLocal.dbd"
include "dbPv.dbd"
include "powerSupplyRegister.dbd"

View File

@@ -3,14 +3,21 @@ TOP=..
include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================
#==================================================
# Build an IOC support library
#
PROD_HOST += powerSupplyMain
powerSupplyMain_SRCS += powerSupplyMain.cpp
powerSupplyMain_LIBS += powerSupply
powerSupplyMain_LIBS += pvDatabase
powerSupplyMain_LIBS += pvAccess
powerSupplyMain_LIBS += pvData
powerSupplyMain_LIBS += Com
powerSupplyMain_LIBS += powerSupply
#===========================

View File

@@ -20,12 +20,12 @@
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/recordList.h>
#include <pv/powerSupply.h>
#include <pv/traceRecord.h>
#include <pv/channelProviderLocal.h>
#include <pv/serverContext.h>
#include <powerSupply.h>
using namespace std;
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
@@ -39,7 +39,7 @@ int main(int argc,char *argv[])
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
PVRecordPtr pvRecord;
bool result(false);
String recordName;
string recordName;
recordName = "powerSupply";
PVStructurePtr pv = createPowerSupply();
pvRecord = PowerSupply::create(recordName,pv);
@@ -49,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

@@ -1,8 +1,6 @@
# Makefile at top of application tree
#Makefile at top of application tree
TOP = .
include $(TOP)/configure/CONFIG
DIRS += configure
DIRS += src
@@ -12,7 +10,6 @@ DIRS += ioc
ioc_DEPEND_DIRS = src
DIRS += iocBoot
iocBoot_DEPEND_DIRS = src
include $(TOP)/configure/RULES_TOP

View File

@@ -14,11 +14,26 @@
# Set CHECK_RELEASE to NO to disable checking completely.
# Set CHECK_RELEASE to WARN to perform consistency checking but
# continue building anyway if conflicts are found.
CHECK_RELEASE = WARN
#CHECK_RELEASE = YES
# Set this when you only want to compile this application
# for a subset of the cross-compiled target architectures
# that Base is built for.
#CROSS_COMPILER_TARGET_ARCHS = vxWorks-68040
# To install files into a location other than $(TOP) define
# INSTALL_LOCATION here.
#INSTALL_LOCATION=</path/name/to/install/top>
# Set this when your IOC and the host use different paths
# to access the application. This will be needed to boot
# from a Microsoft FTP server or with some NFS mounts.
# You must rebuild in the iocBoot directory for this to
# take effect.
#IOCS_APPL_TOP = </IOC/path/to/application/top>
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

View File

@@ -16,9 +16,8 @@
# EPICS V4 Developers: Do not edit the locations in this file!
#
# Create a file RELEASE.local pointing to your PVASRV, PVACCESS,
# PVDATA, PVCOMMON and EPICS_BASE build directories, e.g.
# PVASRV = /path/to/epics/pvaSrvCPP
# Create a file RELEASE.local pointing to your places
# for the dependencies, e.g.
# PVACCESS = /path/to/epics/pvAccessCPP
# PVDATA = /path/to/epics/pvDataCPP
# PVCOMMON = /path/to/epics/pvCommonCPP
@@ -28,14 +27,14 @@
# use the following definitions:
PVDATABASE = $(TOP)/..
-include $(TOP)/../configure/RELEASE.local
-include $(TOP)/../../RELEASE.local
-include $(TOP)/../configure/RELEASE.local
# If you copied this example from pvDatabaseCPP to be built as a
# standalone TOP, adjust and use the following definitions:
# standalone TOP, define
# PVDATABASE = /path/to/epics/pvDatabaseCPP
# in the appropriate RELEASE[.local],
# and use the following definitions instead:
#PVDATABASE = /path/to/epics/pvDatabaseCPP
#-include $(TOP)/configure/RELEASE.local
#-include $(TOP)/../RELEASE.local
#-include $(TOP)/configure/RELEASE.local

View File

@@ -3,22 +3,26 @@ TOP=../..
include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================
#==================================================
# Build an IOC support library
#
DBD += exampleServer.dbd
exampleServer_DBD += base.dbd
exampleServer_DBD += PVAServerRegister.dbd
exampleServer_DBD += registerChannelProviderLocal.dbd
exampleServer_DBD += dbPv.dbd
exampleServer_DBD += exampleServerRegister.dbd
#=============================
# build an ioc application
PROD_IOC += exampleServer
# <name>_registerRecordDeviceDriver.cpp will be created from <name>.dbd
exampleServer_SRCS += exampleServer_registerRecordDeviceDriver.cpp
exampleServer_SRCS_DEFAULT += exampleServerMain.cpp
exampleServer_SRCS_vxWorks += -nil-
# The following adds support from base/src/vxWorks
exampleServer_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary

View File

@@ -0,0 +1,6 @@
include "base.dbd"
include "PVAClientRegister.dbd"
include "PVAServerRegister.dbd"
include "registerChannelProviderLocal.dbd"
include "dbPv.dbd"
include "exampleServer.dbd"

View File

@@ -3,8 +3,14 @@ TOP=..
include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================
DBD += exampleServerRegister.dbd
#==================================================
# Build an IOC support library
#
DBD += exampleServer.dbd
INC += exampleServer.h
@@ -14,6 +20,7 @@ exampleServer_SRCS += exampleServerRegister.cpp
exampleServer_LIBS += pvDatabase
exampleServer_LIBS += pvAccess
exampleServer_LIBS += pvData
exampleServer_LIBS += Com
exampleServer_LIBS += $(EPICS_BASE_IOC_LIBS)
PROD_HOST += exampleServerMain

View File

@@ -9,34 +9,36 @@
* @date 2013.04.02
*/
#include <pv/standardPVField.h>
#include <pv/standardField.h>
#define epicsExportSharedSymbols
#include <pv/exampleServer.h>
#include <exampleServer.h>
namespace epics { namespace exampleServer {
using namespace epics::pvData;
using namespace epics::pvDatabase;
using std::tr1::static_pointer_cast;
using std::string;
namespace epics { namespace exampleServer {
ExampleServerPtr ExampleServer::create(
String const & recordName)
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();
@@ -44,7 +46,7 @@ ExampleServerPtr ExampleServer::create(
}
ExampleServer::ExampleServer(
String const & recordName,
string const & recordName,
PVStructurePtr const & pvStructure)
: PVRecord(recordName,pvStructure)
{
@@ -74,7 +76,7 @@ bool ExampleServer::init()
void ExampleServer::process()
{
pvResultValue->put(String("Hello ") + pvArgumentValue->get());
pvResultValue->put(string("Hello ") + pvArgumentValue->get());
timeStamp.getCurrent();
pvTimeStamp.set(timeStamp);
}

View File

@@ -8,15 +8,14 @@
* @author mrk
* @date 2013.04.02
*/
#ifndef EXAMPLESERVER_H
#define EXAMPLESERVER_H
#ifndef EXAMPLECOUNTER_H
#define EXAMPLECOUNTER_H
#ifdef epicsExportSharedSymbols
# define exampleServerEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <shareLib.h>
#include <pv/pvDatabase.h>
#include <pv/timeStamp.h>
#include <pv/pvTimeStamp.h>
@@ -24,9 +23,10 @@
#ifdef exampleServerEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef exampleServerEpicsExportSharedSymbols
# include <shareLib.h>
#endif
#include <shareLib.h>
namespace epics { namespace exampleServer {
@@ -40,13 +40,13 @@ class epicsShareClass ExampleServer :
public:
POINTER_DEFINITIONS(ExampleServer);
static ExampleServerPtr create(
epics::pvData::String const & recordName);
std::string const & recordName);
virtual ~ExampleServer();
virtual void destroy();
virtual bool init();
virtual void process();
private:
ExampleServer(epics::pvData::String const & recordName,
ExampleServer(std::string const & recordName,
epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStringPtr pvArgumentValue;
@@ -58,4 +58,4 @@ private:
}}
#endif /* EXAMPLESERVER_H */
#endif /* EXAMPLECOUNTER_H */

View File

@@ -0,0 +1 @@
registrar("exampleServerRegister")

View File

@@ -20,12 +20,12 @@
#include <pv/standardField.h>
#include <pv/standardPVField.h>
#include <pv/exampleServer.h>
#include <pv/traceRecord.h>
#include <pv/recordList.h>
#include <pv/channelProviderLocal.h>
#include <pv/serverContext.h>
#include <exampleServer.h>
using namespace std;
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
@@ -39,19 +39,24 @@ int main(int argc,char *argv[])
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
PVRecordPtr pvRecord;
bool result(false);
String recordName;
string recordName;
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

@@ -31,10 +31,10 @@
#include <pv/pvData.h>
#include <pv/pvAccess.h>
#include <pv/pvDatabase.h>
#include <pv/recordList.h>
#include <epicsExport.h>
#include <exampleServer.h>
#include <pv/exampleServer.h>
using namespace epics::pvData;
using namespace epics::pvAccess;
@@ -51,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

@@ -3,9 +3,6 @@
TOP = ..
include $(TOP)/configure/CONFIG
INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
USR_INCLUDES += -I$(INSTALL_LOCATION)/include
PVDATABASE_SRC = $(TOP)/src
LIBRARY += pvDatabase

View File

@@ -70,7 +70,7 @@ void PVDatabase::unlock() {
mutex.unlock();
}
PVRecordPtr PVDatabase::findRecord(String const& recordName)
PVRecordPtr PVDatabase::findRecord(string const& recordName)
{
lock();
try {
@@ -104,13 +104,13 @@ PVStringArrayPtr PVDatabase::getRecordNames()
PVStringArrayPtr pvStringArray = static_pointer_cast<PVStringArray>
(getPVDataCreate()->createPVScalarArray(pvString));
size_t len = recordMap.size();
shared_vector<String> names(len);
shared_vector<string> names(len);
PVRecordMap::iterator iter;
size_t i = 0;
for(iter = recordMap.begin(); iter!=recordMap.end(); ++iter) {
names[i++] = (*iter).first;
}
shared_vector<const String> temp(freeze(names));
shared_vector<const string> temp(freeze(names));
pvStringArray->replace(temp);
unlock();
return pvStringArray;
@@ -128,7 +128,7 @@ bool PVDatabase::addRecord(PVRecordPtr const & record)
unlock();
return false;
}
String recordName = record->getRecordName();
string recordName = record->getRecordName();
PVRecordMap::iterator iter = recordMap.find(recordName);
if(iter!=recordMap.end()) {
unlock();
@@ -152,7 +152,7 @@ bool PVDatabase::removeRecord(PVRecordPtr const & record)
unlock();
return false;
}
String recordName = record->getRecordName();
string recordName = record->getRecordName();
PVRecordMap::iterator iter = recordMap.find(recordName);
if(iter!=recordMap.end()) {
PVRecordPtr pvRecord = (*iter).second;

View File

@@ -27,15 +27,16 @@
#ifdef pvdatabaseEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef pvdatabaseEpicsExportSharedSymbols
# include <shareLib.h>
#endif
#include <shareLib.h>
namespace epics { namespace pvDatabase {
class PVRecord;
typedef std::tr1::shared_ptr<PVRecord> PVRecordPtr;
typedef std::map<epics::pvData::String,PVRecordPtr> PVRecordMap;
typedef std::map<std::string,PVRecordPtr> PVRecordMap;
class PVRecordField;
typedef std::tr1::shared_ptr<PVRecordField> PVRecordFieldPtr;
@@ -77,7 +78,7 @@ public:
*/
virtual void start() {}
/**
* Must be implemented by derived classes.
* Optional method.
* It is the method that makes a record smart.
* If it encounters errors it should raise alarms and/or
* call the <b>message</b> method provided by the base class.
@@ -97,7 +98,7 @@ public:
* @return A shared pointer to the newly created record.
*/
static PVRecordPtr create(
epics::pvData::String const & recordName,
std::string const & recordName,
epics::pvData::PVStructurePtr const & pvStructure);
/**
* The Destructor. Must be virtual.
@@ -107,12 +108,12 @@ public:
* Get the name of the record.
* @return The name.
*/
epics::pvData::String getRecordName();
std::string getRecordName() const;
/**
* Get the top level PVStructure.
* @return The shared pointer.
*/
PVRecordStructurePtr getPVRecordStructure();
PVRecordStructurePtr getPVRecordStructure() const;
/**
* Find the PVRecordField for the PVField.
* @param pvField The PVField.
@@ -183,17 +184,6 @@ public:
* Ends a group of puts.
*/
void endGroupPut();
/**
* Calls the next method with indentLevel = 0.
* @param buf String Builder.
*/
void toString(epics::pvData::StringBuilder buf);
/**
* Dumps the data from the top level PVStructure.
* @param buf String Builder.
* @param indentLevel The indentation level.
*/
void toString(epics::pvData::StringBuilder buf,int indentLevel);
/**
* get trace level (0,1,2) means (nothing,lifetime,process)
* @return the level
@@ -211,7 +201,7 @@ protected:
* @param pvStructure The top level PVStructutre
*/
PVRecord(
epics::pvData::String const & recordName,
std::string const & recordName,
epics::pvData::PVStructurePtr const & pvStructure);
/**
* Initializes the base class. Must be called by derived classes.
@@ -230,7 +220,7 @@ private:
PVRecordFieldPtr findPVRecordField(
PVRecordStructurePtr const & pvrs,
epics::pvData::PVFieldPtr const & pvField);
epics::pvData::String recordName;
std::string recordName;
epics::pvData::PVStructurePtr pvStructure;
epics::pvData::ConvertPtr convert;
PVRecordStructurePtr pvRecordStructure;
@@ -242,6 +232,8 @@ private:
bool isDestroyed;
};
epicsShareExtern std::ostream& operator<<(std::ostream& o, const PVRecord& record);
/**
* Interface for a field of a record.
* One exists for each field of the top level PVStructure.
@@ -284,12 +276,12 @@ public:
* Get the full name of the field, i.e. field,field,..
* @return The full name.
*/
epics::pvData::String getFullFieldName();
std::string getFullFieldName();
/**
* Get the recordName plus the full name of the field, i.e. recordName.field,field,..
* @return The name.
*/
epics::pvData::String getFullName();
std::string getFullName();
/**
* Returns the PVRecord to which this field belongs.
* @return The shared pointer,
@@ -331,8 +323,8 @@ private:
bool isStructure;
PVRecordStructurePtr parent;
PVRecordPtr pvRecord;
epics::pvData::String fullName;
epics::pvData::String fullFieldName;
std::string fullName;
std::string fullFieldName;
friend class PVRecordStructure;
friend class PVRecord;
};
@@ -481,7 +473,7 @@ public:
* @param recordName The record to find.
* @return The shared pointer.
*/
PVRecordPtr findRecord(epics::pvData::String const& recordName);
PVRecordPtr findRecord(std::string const& recordName);
/**
* Add a record.
* @param The record to add.

View File

@@ -22,7 +22,7 @@ using namespace std;
namespace epics { namespace pvDatabase {
PVRecordPtr PVRecord::create(
String const &recordName,
string const &recordName,
PVStructurePtr const & pvStructure)
{
PVRecordPtr pvRecord(new PVRecord(recordName,pvStructure));
@@ -35,7 +35,7 @@ PVRecordPtr PVRecord::create(
PVRecord::PVRecord(
String const & recordName,
string const & recordName,
PVStructurePtr const & pvStructure)
: recordName(recordName),
pvStructure(pvStructure),
@@ -103,9 +103,9 @@ void PVRecord::destroy()
}
}
String PVRecord::getRecordName() {return recordName;}
string PVRecord::getRecordName() const {return recordName;}
PVRecordStructurePtr PVRecord::getPVRecordStructure() {return pvRecordStructure;}
PVRecordStructurePtr PVRecord::getPVRecordStructure() const {return pvRecordStructure;}
PVStructurePtr PVRecord::getPVStructure() {return pvStructure;}
@@ -346,15 +346,14 @@ void PVRecord::endGroupPut()
}
}
void PVRecord::toString(StringBuilder buf)
std::ostream& operator<<(std::ostream& o, const PVRecord& record)
{
toString(buf,0);
}
void PVRecord::toString(StringBuilder buf,int indentLevel)
{
*buf += "\nrecord " + recordName + " ";
pvRecordStructure->getPVStructure()->toString(buf, indentLevel);
o << format::indent() << "record " << record.getRecordName() << endl;
{
format::indent_scope s(o);
o << *record.getPVRecordStructure()->getPVStructure();
}
return o;
}
PVRecordField::PVRecordField(
@@ -372,8 +371,8 @@ void PVRecordField::init()
{
fullFieldName = pvField->getFieldName();
PVRecordStructurePtr pvParent = parent;
while(pvParent.get()!= NULL) {
String parentName = pvParent->getPVField()->getFieldName();
while(pvParent) {
string parentName = pvParent->getPVField()->getFieldName();
if(parentName.size()>0) {
fullFieldName = pvParent->getPVField()->getFieldName()
+ '.' + fullFieldName;
@@ -404,9 +403,9 @@ PVRecordStructurePtr PVRecordField::getParent() {return parent;}
PVFieldPtr PVRecordField::getPVField() {return pvField;}
String PVRecordField::getFullFieldName() {return fullFieldName; }
string PVRecordField::getFullFieldName() {return fullFieldName; }
String PVRecordField::getFullName() {return fullName; }
string PVRecordField::getFullName() {return fullName; }
PVRecordPtr PVRecordField::getPVRecord() {return pvRecord;}
@@ -435,7 +434,7 @@ void PVRecordField::removeListener(PVListenerPtr const & pvListener)
void PVRecordField::postPut()
{
if(parent!=NULL) {
if(parent) {
parent->postParent(getPtrSelf());
}
postSubField();
@@ -449,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

@@ -3,13 +3,13 @@
SRC_DIRS += $(PVDATABASE_SRC)/pvAccess
INC += channelProviderLocal.h
INC += pvCopy.h
INC += monitorAlgorithm.h
INC += pvCopyMonitor.h
DBD += registerChannelProviderLocal.dbd
LIBSRCS += channelProviderLocal.cpp
LIBSRCS += pvCopy.cpp
LIBSRCS += monitorFactory.cpp
LIBSRCS += channelLocal.cpp
LIBSRCS += pvCopyMonitor.cpp
LIBSRCS += monitorFactory.cpp
LIBSRCS += registerChannelProviderLocal.cpp

View File

@@ -12,7 +12,6 @@
#include <sstream>
#include <epicsThread.h>
#include <pv/timeStamp.h>
#include <pv/convert.h>
#include <pv/pvSubArrayCopy.h>
@@ -21,15 +20,37 @@
#include <pv/channelProviderLocal.h>
namespace epics { namespace pvDatabase {
using namespace epics::pvData;
using namespace epics::pvAccess;
using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
using std::cout;
using std::endl;
using std::string;
namespace epics { namespace pvDatabase {
static ConvertPtr convert = getConvert();
static StructureConstPtr nullStructure;
static PVStructurePtr nullPVStructure;
static BitSetPtr nullBitSet;
static Status channelDestroyedStatus(
Status::STATUSTYPE_ERROR,
"was destroyed"
);
static Status illegalOffsetStatus(
Status::STATUSTYPE_ERROR,
"count must be >0"
);
static Status illegalCountStatus(
Status::STATUSTYPE_ERROR,
"count must be >0"
);
static Status illegalStrideStatus(
Status::STATUSTYPE_ERROR,
"stride must be >0"
);
class ChannelProcessLocal;
typedef std::tr1::shared_ptr<ChannelProcessLocal> ChannelProcessLocalPtr;
@@ -49,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.get()==NULL || pvField->getField()->getType()!=scalar) {
if(!pvField || pvField->getField()->getType()!=scalar) {
return processDefault;
}
ScalarConstPtr scalar = static_pointer_cast<const Scalar>(
@@ -82,8 +103,12 @@ public:
ChannelProcessRequester::shared_pointer const & channelProcessRequester,
PVStructurePtr const & pvRequest,
PVRecordPtr const &pvRecord);
virtual void process(bool lastRequest);
virtual void process();
virtual void destroy();
virtual std::tr1::shared_ptr<Channel> getChannel()
{return channelLocal;}
virtual void cancel(){}
virtual void lastRequest() {}
virtual void lock() {mutex.lock();}
virtual void unlock() {mutex.unlock();}
private:
@@ -105,7 +130,6 @@ private:
{
}
bool isDestroyed;
bool callProcess;
ChannelLocalPtr channelLocal;
ChannelProcessRequester::shared_pointer channelProcessRequester;
PVRecordPtr pvRecord;
@@ -122,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();
@@ -167,13 +191,11 @@ void ChannelProcessLocal::destroy()
channelLocal.reset();
}
void ChannelProcessLocal::process(bool lastRequest)
void ChannelProcessLocal::process()
{
if(isDestroyed) {
Status status(
Status::STATUSTYPE_ERROR,
"was destroyed");
channelProcessRequester->processDone(status);
channelProcessRequester->processDone(channelDestroyedStatus,getPtrSelf());
return;
}
if(pvRecord->getTraceLevel()>1)
@@ -193,8 +215,7 @@ void ChannelProcessLocal::process(bool lastRequest)
}
pvRecord->unlock();
}
channelProcessRequester->processDone(Status::Ok);
if(lastRequest) destroy();
channelProcessRequester->processDone(Status::Ok,getPtrSelf());
}
class ChannelGetLocal :
@@ -215,8 +236,12 @@ public:
ChannelGetRequester::shared_pointer const & channelGetRequester,
PVStructurePtr const & pvRequest,
PVRecordPtr const &pvRecord);
virtual void get(bool lastRequest);
virtual void get();
virtual void destroy();
virtual std::tr1::shared_ptr<Channel> getChannel()
{return channelLocal;}
virtual void cancel(){}
virtual void lastRequest() {}
virtual void lock() {mutex.lock();}
virtual void unlock() {mutex.unlock();}
private:
@@ -263,21 +288,18 @@ ChannelGetLocalPtr ChannelGetLocal::create(
PVRecordPtr const &pvRecord)
{
PVCopyPtr pvCopy = PVCopy::create(
pvRecord,
pvRecord->getPVRecordStructure()->getPVStructure(),
pvRequest,
"");
if(pvCopy.get()==NULL) {
if(!pvCopy) {
Status status(
Status::STATUSTYPE_ERROR,
"invalid pvRequest");
ChannelGet::shared_pointer channelGet;
PVStructurePtr pvStructure;
BitSetPtr bitSet;
channelGetRequester->channelGetConnect(
status,
channelGet,
pvStructure,
bitSet);
nullStructure);
ChannelGetLocalPtr localGet;
return localGet;
}
@@ -296,7 +318,8 @@ ChannelGetLocalPtr ChannelGetLocal::create(
cout << "ChannelGetLocal::create";
cout << " recordName " << pvRecord->getRecordName() << endl;
}
channelGetRequester->channelGetConnect(Status::Ok, get, pvStructure,bitSet);
channelGetRequester->channelGetConnect(
Status::Ok,get,pvStructure->getStructure());
return get;
}
@@ -316,13 +339,11 @@ void ChannelGetLocal::destroy()
channelLocal.reset();
}
void ChannelGetLocal::get(bool lastRequest)
void ChannelGetLocal::get()
{
if(isDestroyed) {
Status status(
Status::STATUSTYPE_ERROR,
"was destroyed");
channelGetRequester->getDone(status);
channelGetRequester->getDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return;
}
bitSet->clear();
@@ -344,12 +365,15 @@ void ChannelGetLocal::get(bool lastRequest)
bitSet->set(0);
firstTime = false;
}
channelGetRequester->getDone(Status::Ok);
channelGetRequester->getDone(
Status::Ok,
getPtrSelf(),
pvStructure,
bitSet);
if(pvRecord->getTraceLevel()>1)
{
cout << "ChannelGetLocal::get" << endl;
}
if(lastRequest) destroy();
}
class ChannelPutLocal :
@@ -370,9 +394,13 @@ public:
ChannelPutRequester::shared_pointer const & channelPutRequester,
PVStructurePtr const & pvRequest,
PVRecordPtr const &pvRecord);
virtual void put(bool lastRequest);
virtual void put(PVStructurePtr const &pvStructure,BitSetPtr const &bitSet);
virtual void get();
virtual void destroy();
virtual std::tr1::shared_ptr<Channel> getChannel()
{return channelLocal;}
virtual void cancel(){}
virtual void lastRequest() {}
virtual void lock() {mutex.lock();}
virtual void unlock() {mutex.unlock();}
private:
@@ -385,8 +413,6 @@ private:
ChannelLocalPtr const &channelLocal,
ChannelPutRequester::shared_pointer const & channelPutRequester,
PVCopyPtr const &pvCopy,
PVStructurePtr const&pvStructure,
BitSetPtr const & bitSet,
PVRecordPtr const &pvRecord)
:
isDestroyed(false),
@@ -394,8 +420,6 @@ private:
channelLocal(channelLocal),
channelPutRequester(channelPutRequester),
pvCopy(pvCopy),
pvStructure(pvStructure),
bitSet(bitSet),
pvRecord(pvRecord)
{
}
@@ -404,8 +428,6 @@ private:
ChannelLocalPtr channelLocal;
ChannelPutRequester::shared_pointer channelPutRequester;
PVCopyPtr pvCopy;
PVStructurePtr pvStructure;
BitSetPtr bitSet;
PVRecordPtr pvRecord;
Mutex mutex;
};
@@ -417,10 +439,10 @@ ChannelPutLocalPtr ChannelPutLocal::create(
PVRecordPtr const &pvRecord)
{
PVCopyPtr pvCopy = PVCopy::create(
pvRecord,
pvRecord->getPVRecordStructure()->getPVStructure(),
pvRequest,
"");
if(pvCopy.get()==NULL) {
if(!pvCopy) {
Status status(
Status::STATUSTYPE_ERROR,
"invalid pvRequest");
@@ -430,22 +452,18 @@ ChannelPutLocalPtr ChannelPutLocal::create(
channelPutRequester->channelPutConnect(
status,
channelPut,
pvStructure,
bitSet);
nullStructure);
ChannelPutLocalPtr localPut;
return localPut;
}
PVStructurePtr pvStructure = pvCopy->createPVStructure();
BitSetPtr bitSet(new BitSet(pvStructure->getNumberFields()));
ChannelPutLocalPtr put(new ChannelPutLocal(
getProcess(pvRequest,true),
channelLocal,
channelPutRequester,
pvCopy,
pvStructure,
bitSet,
pvRecord));
channelPutRequester->channelPutConnect(Status::Ok, put, pvStructure,bitSet);
channelPutRequester->channelPutConnect(
Status::Ok, put, pvCopy->getStructure());
if(pvRecord->getTraceLevel()>0)
{
cout << "ChannelPutLocal::create";
@@ -472,12 +490,12 @@ void ChannelPutLocal::destroy()
void ChannelPutLocal::get()
{
if(isDestroyed) {
Status status(
Status::STATUSTYPE_ERROR,
"was destroyed");
channelPutRequester->getDone(status);
channelPutRequester->getDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return;
}
PVStructurePtr pvStructure = pvCopy->createPVStructure();
BitSetPtr bitSet(new BitSet(pvStructure->getNumberFields()));
bitSet->clear();
bitSet->set(0);
pvRecord->lock();
@@ -488,26 +506,25 @@ void ChannelPutLocal::get()
throw;
}
pvRecord->unlock();
channelPutRequester->getDone(Status::Ok);
channelPutRequester->getDone(
Status::Ok,getPtrSelf(),pvStructure,bitSet);
if(pvRecord->getTraceLevel()>1)
{
cout << "ChannelPutLocal::get" << endl;
}
}
void ChannelPutLocal::put(bool lastRequest)
void ChannelPutLocal::put(
PVStructurePtr const &pvStructure,BitSetPtr const &bitSet)
{
if(isDestroyed) {
Status status(
Status::STATUSTYPE_ERROR,
"was destroyed");
channelPutRequester->getDone(status);
channelPutRequester->putDone(channelDestroyedStatus,getPtrSelf());
return;
}
pvRecord->lock();
try {
pvRecord->beginGroupPut();
pvCopy->updateRecord(pvStructure, bitSet);
pvCopy->updateMaster(pvStructure, bitSet);
if(callProcess) {
pvRecord->process();
}
@@ -517,12 +534,11 @@ void ChannelPutLocal::put(bool lastRequest)
throw;
}
pvRecord->unlock();
channelPutRequester->putDone(Status::Ok);
channelPutRequester->putDone(Status::Ok,getPtrSelf());
if(pvRecord->getTraceLevel()>1)
{
cout << "ChannelPutLocal::put" << endl;
}
if(lastRequest) destroy();
}
@@ -544,10 +560,16 @@ public:
ChannelPutGetRequester::shared_pointer const & channelPutGetRequester,
PVStructurePtr const & pvRequest,
PVRecordPtr const &pvRecord);
virtual void putGet(bool lastRequest);
virtual void putGet(
PVStructurePtr const &pvPutStructure,
BitSetPtr const &putBitSet);
virtual void getPut();
virtual void getGet();
virtual void destroy();
virtual std::tr1::shared_ptr<Channel> getChannel()
{return channelLocal;}
virtual void cancel(){}
virtual void lastRequest() {}
virtual void lock() {mutex.lock();}
virtual void unlock() {mutex.unlock();}
private:
@@ -561,9 +583,7 @@ private:
ChannelPutGetRequester::shared_pointer const & channelPutGetRequester,
PVCopyPtr const &pvPutCopy,
PVCopyPtr const &pvGetCopy,
PVStructurePtr const&pvPutStructure,
PVStructurePtr const&pvGetStructure,
BitSetPtr const & putBitSet,
BitSetPtr const & getBitSet,
PVRecordPtr const &pvRecord)
:
@@ -573,9 +593,7 @@ private:
channelPutGetRequester(channelPutGetRequester),
pvPutCopy(pvPutCopy),
pvGetCopy(pvGetCopy),
pvPutStructure(pvPutStructure),
pvGetStructure(pvGetStructure),
putBitSet(putBitSet),
getBitSet(getBitSet),
pvRecord(pvRecord)
{
@@ -586,9 +604,7 @@ private:
ChannelPutGetRequester::shared_pointer channelPutGetRequester;
PVCopyPtr pvPutCopy;
PVCopyPtr pvGetCopy;
PVStructurePtr pvPutStructure;
PVStructurePtr pvGetStructure;
BitSetPtr putBitSet;
BitSetPtr getBitSet;
PVRecordPtr pvRecord;
Mutex mutex;
@@ -601,50 +617,35 @@ ChannelPutGetLocalPtr ChannelPutGetLocal::create(
PVRecordPtr const &pvRecord)
{
PVCopyPtr pvPutCopy = PVCopy::create(
pvRecord,
pvRecord->getPVRecordStructure()->getPVStructure(),
pvRequest,
"putField");
PVCopyPtr pvGetCopy = PVCopy::create(
pvRecord,
pvRecord->getPVRecordStructure()->getPVStructure(),
pvRequest,
"getField");
if(pvPutCopy.get()==NULL || pvGetCopy.get()==NULL) {
if(!pvPutCopy || !pvGetCopy) {
Status status(
Status::STATUSTYPE_ERROR,
"invalid pvRequest");
ChannelPutGet::shared_pointer channelPutGet;
PVStructurePtr pvStructure;
BitSetPtr bitSet;
channelPutGetRequester->channelPutGetConnect(
status,
channelPutGet,
pvStructure,
pvStructure);
nullStructure,
nullStructure);
ChannelPutGetLocalPtr localPutGet;
return localPutGet;
}
PVStructurePtr pvPutStructure = pvPutCopy->createPVStructure();
PVStructurePtr pvGetStructure = pvGetCopy->createPVStructure();
BitSetPtr putBitSet(new BitSet(pvPutStructure->getNumberFields()));
BitSetPtr getBitSet(new BitSet(pvGetStructure->getNumberFields()));
pvRecord->lock();
try {
pvPutCopy->initCopy(pvPutStructure,putBitSet);
pvGetCopy->initCopy(pvGetStructure,getBitSet);
} catch(...) {
pvRecord->unlock();
throw;
}
pvRecord->unlock();
ChannelPutGetLocalPtr putGet(new ChannelPutGetLocal(
getProcess(pvRequest,true),
channelLocal,
channelPutGetRequester,
pvPutCopy,
pvGetCopy,
pvPutStructure,
pvGetStructure,
putBitSet,
getBitSet,
pvRecord));
if(pvRecord->getTraceLevel()>0)
@@ -653,7 +654,7 @@ ChannelPutGetLocalPtr ChannelPutGetLocal::create(
cout << " recordName " << pvRecord->getRecordName() << endl;
}
channelPutGetRequester->channelPutGetConnect(
Status::Ok, putGet, pvPutStructure,pvGetStructure);
Status::Ok, putGet, pvPutCopy->getStructure(),pvGetCopy->getStructure());
return putGet;
}
@@ -673,22 +674,20 @@ void ChannelPutGetLocal::destroy()
channelLocal.reset();
}
void ChannelPutGetLocal::putGet(bool lastRequest)
void ChannelPutGetLocal::putGet(
PVStructurePtr const &pvPutStructure,BitSetPtr const &putBitSet)
{
if(isDestroyed) {
Status status(
Status::STATUSTYPE_ERROR,
"was destroyed");
channelPutGetRequester->putGetDone(status);
channelPutGetRequester->putGetDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return;
}
putBitSet->clear();
putBitSet->set(0);
pvRecord->lock();
try {
pvRecord->beginGroupPut();
pvPutCopy->updateRecord(pvPutStructure, putBitSet);
pvPutCopy->updateMaster(pvPutStructure, putBitSet);
if(callProcess) pvRecord->process();
getBitSet->clear();
pvGetCopy->updateCopySetBitSet(pvGetStructure, getBitSet);
pvRecord->endGroupPut();
} catch(...) {
@@ -696,36 +695,33 @@ void ChannelPutGetLocal::putGet(bool lastRequest)
throw;
}
pvRecord->unlock();
getBitSet->clear();
getBitSet->set(0);
channelPutGetRequester->putGetDone(Status::Ok);
channelPutGetRequester->putGetDone(
Status::Ok,getPtrSelf(),pvGetStructure,getBitSet);
if(pvRecord->getTraceLevel()>1)
{
cout << "ChannelPutGetLocal::putGet" << endl;
}
if(lastRequest) destroy();
}
void ChannelPutGetLocal::getPut()
{
if(isDestroyed) {
Status status(
Status::STATUSTYPE_ERROR,
"was destroyed");
channelPutGetRequester->getPutDone(status);
channelPutGetRequester->getPutDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return;
}
PVStructurePtr pvPutStructure = pvPutCopy->createPVStructure();
BitSetPtr putBitSet(new BitSet(pvPutStructure->getNumberFields()));
pvRecord->lock();
try {
pvPutCopy->updateCopySetBitSet(pvPutStructure, putBitSet);
pvPutCopy->initCopy(pvPutStructure, putBitSet);
} catch(...) {
pvRecord->unlock();
throw;
}
pvRecord->unlock();
putBitSet->clear();
putBitSet->set(0);
channelPutGetRequester->getPutDone(Status::Ok);
channelPutGetRequester->getPutDone(
Status::Ok,getPtrSelf(),pvPutStructure,putBitSet);
if(pvRecord->getTraceLevel()>1)
{
cout << "ChannelPutGetLocal::getPut" << endl;
@@ -735,12 +731,11 @@ void ChannelPutGetLocal::getPut()
void ChannelPutGetLocal::getGet()
{
if(isDestroyed) {
Status status(
Status::STATUSTYPE_ERROR,
"was destroyed");
channelPutGetRequester->getGetDone(status);
channelPutGetRequester->getGetDone(
channelDestroyedStatus,getPtrSelf(),nullPVStructure,nullBitSet);
return;
}
getBitSet->clear();
pvRecord->lock();
try {
pvGetCopy->updateCopySetBitSet(pvGetStructure, getBitSet);
@@ -749,9 +744,8 @@ void ChannelPutGetLocal::getGet()
throw;
}
pvRecord->unlock();
getBitSet->clear();
getBitSet->set(0);
channelPutGetRequester->getGetDone(Status::Ok);
channelPutGetRequester->getGetDone(
Status::Ok,getPtrSelf(),pvGetStructure,getBitSet);
if(pvRecord->getTraceLevel()>1)
{
cout << "ChannelPutGetLocal::getGet" << endl;
@@ -778,10 +772,17 @@ public:
ChannelArrayRequester::shared_pointer const & channelArrayRequester,
PVStructurePtr const & pvRequest,
PVRecordPtr const &pvRecord);
virtual void getArray(bool lastRequest,int offset, int count);
virtual void putArray(bool lastRequest,int offset, int count);
virtual void setLength(bool lastRequest,int length, int capacity);
virtual void getArray(size_t offset, size_t count, size_t stride);
virtual void putArray(
PVArrayPtr const &putArray,
size_t offset, size_t count, size_t stride);
virtual void getLength();
virtual void setLength(size_t length);
virtual void destroy();
virtual std::tr1::shared_ptr<Channel> getChannel()
{return channelLocal;}
virtual void cancel(){}
virtual void lastRequest() {}
virtual void lock() {mutex.lock();}
virtual void unlock() {mutex.unlock();}
private:
@@ -797,7 +798,6 @@ private:
PVRecordPtr const &pvRecord)
:
isDestroyed(false),
callProcess(callProcess),
channelLocal(channelLocal),
channelArrayRequester(channelArrayRequester),
pvArray(pvArray),
@@ -806,7 +806,6 @@ private:
{
}
bool isDestroyed;
bool callProcess;
ChannelLocalPtr channelLocal;
ChannelArrayRequester::shared_pointer channelArrayRequester;
PVArrayPtr pvArray;
@@ -827,14 +826,14 @@ ChannelArrayLocalPtr ChannelArrayLocal::create(
Status status(
Status::STATUSTYPE_ERROR,"invalid pvRequest");
ChannelArrayLocalPtr channelArray;
PVScalarArrayPtr pvArray;
channelArrayRequester->channelArrayConnect(status,channelArray,pvArray);
ArrayConstPtr array;
channelArrayRequester->channelArrayConnect(status,channelArray,array);
return channelArray;
}
PVFieldPtr pvField = pvFields[0];
String fieldName("");
string fieldName("");
while(true) {
String name = pvField->getFieldName();
string name = pvField->getFieldName();
if(fieldName.size()>0) fieldName += '.';
fieldName += name;
PVStructurePtr pvs = static_pointer_cast<PVStructure>(pvField);
@@ -842,22 +841,30 @@ 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;
PVScalarArrayPtr pvArray;
channelArrayRequester->channelArrayConnect(status,channelArray,pvArray);
ArrayConstPtr array;
channelArrayRequester->channelArrayConnect(
status,channelArray,array);
return channelArray;
}
if(pvField->getField()->getType()!=scalarArray && pvField->getField()->getType()!=structureArray)
if(pvField->getField()->getType()!=scalarArray
&& pvField->getField()->getType()!=structureArray
&& pvField->getField()->getType()!=unionArray)
{
Status status(
Status::STATUSTYPE_ERROR,fieldName +" not array");
ChannelArrayLocalPtr channelArray;
PVArrayPtr pvArray;
channelArrayRequester->channelArrayConnect(status,channelArray,pvArray);
ArrayConstPtr array;
channelArrayRequester->channelArrayConnect(
status,channelArray,array);
return channelArray;
}
PVArrayPtr pvArray = static_pointer_cast<PVArray>(pvField);
@@ -866,26 +873,66 @@ ChannelArrayLocalPtr ChannelArrayLocal::create(
PVScalarArrayPtr xxx = static_pointer_cast<PVScalarArray>(pvField);
pvCopy = getPVDataCreate()->createPVScalarArray(
xxx->getScalarArray()->getElementType());
} else {
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;
}
if(pvField->getField()->getType()==structureArray) {
PVStructureArrayPtr xxx = static_pointer_cast<PVStructureArray>(pvField);
pvCopy = getPVDataCreate()->createPVStructureArray(
xxx->getStructureArray());
xxx->getStructureArray()->getStructure());
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;
}
if(pvField->getField()->getType()==unionArray) {
PVUnionArrayPtr xxx = static_pointer_cast<PVUnionArray>(pvField);
pvCopy = getPVDataCreate()->createPVUnionArray(
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(
channelLocal,
channelArrayRequester,
pvArray,
pvCopy,
pvRecord));
if(pvRecord->getTraceLevel()>0)
{
cout << "ChannelArrayLocal::create";
cout << " recordName " << pvRecord->getRecordName() << endl;
}
channelArrayRequester->channelArrayConnect(
Status::Ok, array, pvCopy);
return array;
Status status(Status::STATUSTYPE_ERROR,
"Logic error. Should not reach this code");
ChannelArrayLocalPtr channelArray;
ArrayConstPtr array;
channelArrayRequester->channelArrayConnect(status,channelArray,array);
return channelArray;
}
@@ -904,72 +951,118 @@ void ChannelArrayLocal::destroy()
channelLocal.reset();
}
void ChannelArrayLocal::getArray(bool lastRequest,int offset, int count)
void ChannelArrayLocal::getArray(size_t offset, size_t count, size_t stride)
{
if(isDestroyed) {
Status status(
Status::STATUSTYPE_ERROR,
"was destroyed");
channelArrayRequester->getArrayDone(status);
channelArrayRequester->getArrayDone(channelDestroyedStatus,getPtrSelf(),pvCopy);
return;
}
if(pvRecord->getTraceLevel()>1)
{
cout << "ChannelArrayLocal::getArray" << endl;
}
if(offset<0) {
channelArrayRequester->getArrayDone(illegalOffsetStatus,getPtrSelf(),pvCopy);
return;
}
if(stride<0) {
channelArrayRequester->getArrayDone(illegalStrideStatus,getPtrSelf(),pvCopy);
return;
}
const char *exceptionMessage = NULL;
pvRecord->lock();
try {
if(count<0) count = pvArray->getLength();
size_t capacity = pvArray->getCapacity();
if(capacity!=0) {
pvCopy->setCapacity(capacity);
pvCopy->setLength(count);
copy(*pvArray.get(),offset,*pvCopy.get(),0,count);
bool ok = false;
while(true) {
size_t length = pvArray->getLength();
if(length<=0) break;
if(count<=0) {
count = (length -offset + stride -1)/stride;
if(count>0) ok = true;
break;
}
size_t maxcount = (length -offset + stride -1)/stride;
if(count>maxcount) count = maxcount;
ok = true;
break;
}
} catch(...) {
pvRecord->unlock();
throw;
if(ok) {
pvCopy->setLength(count);
copy(pvArray,offset,stride,pvCopy,0,1,count);
}
} catch(std::exception e) {
exceptionMessage = e.what();
}
pvRecord->unlock();
channelArrayRequester->getArrayDone(Status::Ok);
if(lastRequest) destroy();
Status status = Status::Ok;
if(exceptionMessage!=NULL) {
status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
}
channelArrayRequester->getArrayDone(status,getPtrSelf(),pvCopy);
}
void ChannelArrayLocal::putArray(bool lastRequest,int offset, int count)
void ChannelArrayLocal::putArray(
PVArrayPtr const & pvArray, size_t offset, size_t count, size_t stride)
{
if(isDestroyed) {
Status status(
Status::STATUSTYPE_ERROR,
"was destroyed");
channelArrayRequester->putArrayDone(status);
channelArrayRequester->putArrayDone(channelDestroyedStatus,getPtrSelf());
return;
}
if(pvRecord->getTraceLevel()>1)
{
cout << "ChannelArrayLocal::putArray" << endl;
}
if(offset<0) {
channelArrayRequester->putArrayDone(illegalOffsetStatus,getPtrSelf());
return;
}
if(count<0) {
channelArrayRequester->putArrayDone(illegalCountStatus,getPtrSelf());
return;
}
if(stride<0) {
channelArrayRequester->putArrayDone(illegalStrideStatus,getPtrSelf());
return;
}
size_t newLength = offset + count*stride;
if(newLength<pvArray->getLength()) pvArray->setLength(newLength);
const char *exceptionMessage = NULL;
pvRecord->lock();
try {
if(count<=0) count = pvCopy->getLength();
if(pvArray->getCapacity()<count) pvArray->setCapacity(count);
if(pvArray->getLength()<count) pvArray->setLength(count);
copy(*pvCopy.get(),0,*pvArray.get(),offset,count);
} catch(...) {
pvRecord->unlock();
throw;
copy(pvArray,0,1,this->pvArray,offset,stride,count);
} catch(std::exception e) {
exceptionMessage = e.what();
}
pvRecord->unlock();
channelArrayRequester->putArrayDone(Status::Ok);
if(lastRequest) destroy();
Status status = Status::Ok;
if(exceptionMessage!=NULL) {
status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
}
channelArrayRequester->putArrayDone(status,getPtrSelf());
}
void ChannelArrayLocal::setLength(bool lastRequest,int length, int capacity)
void ChannelArrayLocal::getLength()
{
size_t length = 0;
const char *exceptionMessage = NULL;
pvRecord->lock();
try {
length = pvArray->getLength();
} catch(std::exception e) {
exceptionMessage = e.what();
}
pvRecord->unlock();
Status status = Status::Ok;
if(exceptionMessage!=NULL) {
status = Status(Status::STATUSTYPE_ERROR,exceptionMessage);
}
channelArrayRequester->getLengthDone(status,getPtrSelf(),length);
}
void ChannelArrayLocal::setLength(size_t length)
{
if(isDestroyed) {
Status status(
Status::STATUSTYPE_ERROR,
"was destroyed");
channelArrayRequester->setLengthDone(status);
channelArrayRequester->setLengthDone(channelDestroyedStatus,getPtrSelf());
return;
}
if(pvRecord->getTraceLevel()>1)
@@ -978,18 +1071,7 @@ void ChannelArrayLocal::setLength(bool lastRequest,int length, int capacity)
}
pvRecord->lock();
try {
if(capacity>=0 && !pvArray->isCapacityMutable()) {
Status status(
Status::STATUSTYPE_ERROR,
"capacityImnutable");
channelArrayRequester->setLengthDone(status);
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);
}
} catch(...) {
@@ -997,7 +1079,7 @@ void ChannelArrayLocal::setLength(bool lastRequest,int length, int capacity)
throw;
}
pvRecord->unlock();
channelArrayRequester->setLengthDone(Status::Ok);
channelArrayRequester->setLengthDone(Status::Ok,getPtrSelf());
}
@@ -1060,21 +1142,21 @@ void ChannelLocal::detach(PVRecordPtr const & pvRecord)
}
String ChannelLocal::getRequesterName()
string ChannelLocal::getRequesterName()
{
return requester->getRequesterName();
}
void ChannelLocal::message(
String const &message,
string const &message,
MessageType messageType)
{
requester->message(message,messageType);
}
String ChannelLocal::getRemoteAddress()
string ChannelLocal::getRemoteAddress()
{
return String("local");
return string("local");
}
Channel::ConnectionState ChannelLocal::getConnectionState()
@@ -1082,7 +1164,7 @@ Channel::ConnectionState ChannelLocal::getConnectionState()
return Channel::CONNECTED;
}
String ChannelLocal::getChannelName()
string ChannelLocal::getChannelName()
{
return pvRecord->getRecordName();
}
@@ -1098,7 +1180,7 @@ bool ChannelLocal::isConnected()
}
void ChannelLocal::getField(GetFieldRequester::shared_pointer const &requester,
String const &subField)
string const &subField)
{
if(subField.size()<1) {
StructureConstPtr structure =
@@ -1108,19 +1190,19 @@ 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;
}
Status status(Status::STATUSTYPE_ERROR,
String("client asked for illegal field"));
"client asked for illegal field");
requester->getDone(status,FieldConstPtr());
}
AccessRights ChannelLocal::getAccessRights(
PVField::shared_pointer const &pvField)
{
throw std::logic_error(String("Not Implemented"));
throw std::logic_error("Not Implemented");
}
ChannelProcess::shared_pointer ChannelLocal::createChannelProcess(
@@ -1180,7 +1262,7 @@ ChannelRPC::shared_pointer ChannelLocal::createChannelRPC(
PVStructure::shared_pointer const & pvRequest)
{
Status status(Status::STATUSTYPE_ERROR,
String("ChannelRPC not supported"));
"ChannelRPC not supported");
channelRPCRequester->channelRPCConnect(status,ChannelRPC::shared_pointer());
return ChannelRPC::shared_pointer();
}
@@ -1212,12 +1294,12 @@ ChannelArray::shared_pointer ChannelLocal::createChannelArray(
void ChannelLocal::printInfo()
{
cout << "ChannelLocal provides access to service" << endl;
printInfo(std::cout);
}
void ChannelLocal::printInfo(StringBuilder out)
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

@@ -8,14 +8,14 @@
* @author Marty Kraimer
* @date 2013.04
*/
#define epicsExportSharedSymbols
#include <pv/serverContext.h>
#include <pv/channelProviderLocal.h>
#include <pv/traceRecord.h>
#include <pv/syncChannelFind.h>
namespace epics { namespace pvDatabase {
#define epicsExportSharedSymbols
#include <pv/channelProviderLocal.h>
#include <pv/traceRecord.h>
using namespace epics::pvData;
using namespace epics::pvAccess;
@@ -23,8 +23,11 @@ using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
using std::cout;
using std::endl;
using std::string;
static String providerName("local");
namespace epics { namespace pvDatabase {
static string providerName("local");
class LocalChannelProviderFactory;
@@ -35,7 +38,7 @@ class LocalChannelProviderFactory : public ChannelProviderFactory
public:
POINTER_DEFINITIONS(LocalChannelProviderFactory);
virtual String getFactoryName() { return providerName;}
virtual string getFactoryName() { return providerName;}
static LocalChannelProviderFactoryPtr create(
ChannelProviderLocalPtr const &channelProvider)
{
@@ -68,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;
@@ -95,13 +100,13 @@ void ChannelProviderLocal::destroy()
pvDatabase->destroy();
}
String ChannelProviderLocal::getProviderName()
string ChannelProviderLocal::getProviderName()
{
return providerName;
}
ChannelFind::shared_pointer ChannelProviderLocal::channelFind(
String const & channelName,
string const & channelName,
ChannelFindRequester::shared_pointer const &channelFindRequester)
{
Lock xx(mutex);
@@ -113,7 +118,7 @@ ChannelFind::shared_pointer ChannelProviderLocal::channelFind(
true);
} else {
Status notFoundStatus(Status::STATUSTYPE_ERROR,String("pv not found"));
Status notFoundStatus(Status::STATUSTYPE_ERROR,"pv not found");
channelFindRequester->channelFindResult(
notFoundStatus,
channelFinder,
@@ -122,8 +127,21 @@ ChannelFind::shared_pointer ChannelProviderLocal::channelFind(
return channelFinder;
}
ChannelFind::shared_pointer ChannelProviderLocal::channelList(
ChannelListRequester::shared_pointer const & channelListRequester)
{
PVStringArrayPtr records;
{
Lock guard(mutex);
records = pvDatabase->getRecordNames();
}
channelListRequester->channelListResult(Status::Ok, channelFinder, records->view(), false);
return channelFinder;
}
Channel::shared_pointer ChannelProviderLocal::createChannel(
String const & channelName,
string const & channelName,
ChannelRequester::shared_pointer const &channelRequester,
short priority)
{
@@ -131,10 +149,10 @@ Channel::shared_pointer ChannelProviderLocal::createChannel(
}
Channel::shared_pointer ChannelProviderLocal::createChannel(
String const & channelName,
string const & channelName,
ChannelRequester::shared_pointer const &channelRequester,
short priority,
String const &address)
string const &address)
{
Lock xx(mutex);
PVRecordPtr pvRecord = pvDatabase->findRecord(channelName);
@@ -147,7 +165,7 @@ Channel::shared_pointer ChannelProviderLocal::createChannel(
pvRecord->addPVRecordClient(channel);
return channel;
}
Status notFoundStatus(Status::STATUSTYPE_ERROR,String("pv not found"));
Status notFoundStatus(Status::STATUSTYPE_ERROR,"pv not found");
channelRequester->channelCreated(
notFoundStatus,
Channel::shared_pointer());

View File

@@ -11,35 +11,33 @@
#ifndef CHANNELPROVIDERLOCAL_H
#define CHANNELPROVIDERLOCAL_H
#ifdef epicsExportSharedSymbols
# define channelProviderLocalEpicsExportSharedSymbols
# undef epicsExportSharedSymbols
#endif
#include <string>
#include <cstring>
#include <stdexcept>
#include <memory>
#include <set>
#include <shareLib.h>
#include <pv/lock.h>
#include <pv/pvType.h>
#include <pv/pvData.h>
#include <pv/monitorPlugin.h>
#include <pv/pvCopy.h>
#include <pv/pvAccess.h>
#include <pv/status.h>
#ifdef channelProviderLocalEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef channelProviderLocalEpicsExportSharedSymbols
# include <shareLib.h>
#endif
#include <shareLib.h>
#include <pv/pvDatabase.h>
#include <pv/monitorAlgorithm.h>
namespace epics { namespace pvDatabase {
@@ -59,25 +57,40 @@ 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,
epics::pvData::PVStructurePtr const & pvRequest);
void registerMonitorAlgorithmCreate(
MonitorAlgorithmCreatePtr const &monitorAlgorithmCreate);
MonitorAlgorithmCreatePtr getMonitorAlgorithmCreate(
epics::pvData::String algorithmName);
private:
MonitorFactory();
friend class MonitorLocal;
friend MonitorFactoryPtr getMonitorFactory();
std::multiset<MonitorAlgorithmCreatePtr> monitorAlgorithmCreateList;
bool isDestroyed;
epics::pvData::Mutex mutex;
};
@@ -85,27 +98,84 @@ 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();
virtual epics::pvData::String getProviderName();
/**
* 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(
epics::pvData::String const &channelName,
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(
epics::pvData::String const &channelName,
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(
epics::pvData::String const &channelName,
std::string const &channelName,
epics::pvAccess::ChannelRequester::shared_pointer const &channelRequester,
short priority,
epics::pvData::String const &address);
std::string const &address);
private:
shared_pointer getPtrSelf()
{
@@ -120,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,
@@ -127,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();
virtual epics::pvData::String getRequesterName();
/**
* 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(
epics::pvData::String const & 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;
}
virtual epics::pvData::String getRemoteAddress();
/**
* 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();
virtual epics::pvData::String getChannelName();
/**
* 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,
epics::pvData::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(
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();
virtual void printInfo(epics::pvData::StringBuilder out);
/**
* 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

@@ -1,60 +0,0 @@
/* monitorAlgorithm.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 MONITORALGORITHM_H
#define MONITORALGORITHM_H
#include <shareLib.h>
#include <pv/pvCopy.h>
namespace epics { namespace pvDatabase {
class MonitorAlgorithm;
typedef std::tr1::shared_ptr<MonitorAlgorithm> MonitorAlgorithmPtr;
class MonitorAlgorithmCreate;
typedef std::tr1::shared_ptr<MonitorAlgorithmCreate> MonitorAlgorithmCreatePtr;
class epicsShareClass MonitorAlgorithm
{
public:
POINTER_DEFINITIONS(MonitorAlgorithm);
virtual ~MonitorAlgorithm(){}
virtual epics::pvData::String getAlgorithmName(){return algorithmName;}
virtual bool causeMonitor() = 0;
virtual void monitorIssued() = 0;
protected:
MonitorAlgorithm(epics::pvData::String algorithmName)
: algorithmName(algorithmName)
{}
epics::pvData::String algorithmName;
};
class epicsShareClass MonitorAlgorithmCreate
{
public:
POINTER_DEFINITIONS(MonitorAlgorithmCreate);
virtual ~MonitorAlgorithmCreate(){}
virtual epics::pvData::String getAlgorithmName(){return algorithmName;}
virtual MonitorAlgorithmPtr create(
PVRecordPtr const &pvRecord,
epics::pvData::MonitorRequester::shared_pointer const &requester,
PVRecordFieldPtr const &fromPVRecord,
epics::pvData::PVStructurePtr const &pvOptions) = 0;
protected:
MonitorAlgorithmCreate(epics::pvData::String algorithmName)
: algorithmName(algorithmName)
{}
epics::pvData::String algorithmName;
};
}}
#endif /* MONITORALGORITHM_H */

View File

@@ -18,80 +18,29 @@
#define epicsExportSharedSymbols
#include <pv/pvCopyMonitor.h>
#include <pv/channelProviderLocal.h>
namespace epics { namespace pvDatabase {
using namespace epics::pvData;
using namespace epics::pvAccess;
using std::tr1::static_pointer_cast;
using std::cout;
using std::endl;
using std::string;
namespace epics { namespace pvDatabase {
static MonitorAlgorithmCreatePtr nullMonitorAlgorithmCreate;
static MonitorPtr nullMonitor;
static MonitorElementPtr NULLMonitorElement;
static Status wasDestroyedStatus(Status::STATUSTYPE_ERROR,"was destroyed");
static ConvertPtr convert = getConvert();
//class MonitorFieldNode;
//typedef std::tr1::shared_ptr<MonitorFieldNode> MonitorFieldNodePtr;
class ElementQueue;
typedef std::tr1::shared_ptr<ElementQueue> ElementQueuePtr;
class MultipleElementQueue;
typedef std::tr1::shared_ptr<MultipleElementQueue> MultipleElementQueuePtr;
//class MonitorFieldNode
//{
//public:
// MonitorAlgorithmPtr monitorAlgorithm;
// size_t bitOffset; // pv pvCopy
//};
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;
BitSetPtr changedBitSet;
BitSetPtr overrunBitSet;
MonitorElementPtr latestMonitorElement;
bool queueIsFull;
};
class MonitorLocal :
@@ -106,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,
@@ -125,7 +75,8 @@ private:
bool isDestroyed;
bool firstMonitor;
PVCopyPtr pvCopy;
ElementQueuePtr queue;
MonitorElementQueuePtr queue;
MonitorElementPtr activeElement;
PVCopyMonitorPtr pvCopyMonitor;
Mutex mutex;
};
@@ -159,8 +110,6 @@ void MonitorLocal::destroy()
if(isDestroyed) return;
isDestroyed = true;
}
unlisten();
stop();
pvCopyMonitor->destroy();
pvCopy->destroy();
pvCopyMonitor.reset();
@@ -170,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()
@@ -267,7 +223,9 @@ bool MonitorLocal::init(PVStructurePtr const & pvRequest)
pvField = pvRequest->getSubField("field");
if(pvField.get()==NULL) {
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
pvCopy = PVCopy::create(
pvRecord->getPVRecordStructure()->getPVStructure(),
pvRequest,"");
if(pvCopy.get()==NULL) {
monitorRequester->message("illegal pvRequest",errorMessage);
return false;
@@ -277,13 +235,16 @@ bool MonitorLocal::init(PVStructurePtr const & pvRequest)
monitorRequester->message("illegal pvRequest",errorMessage);
return false;
}
pvCopy = PVCopy::create(pvRecord,pvRequest,"field");
pvCopy = PVCopy::create(
pvRecord->getPVRecordStructure()->getPVStructure(),
pvRequest,"field");
if(pvCopy.get()==NULL) {
monitorRequester->message("illegal pvRequest",errorMessage);
return false;
}
}
pvCopyMonitor = pvCopy->createPVCopyMonitor(getPtrSelf());
pvCopyMonitor = PVCopyMonitor::create(
getPtrSelf(),pvRecord,pvCopy);
// MARTY MUST IMPLEMENT periodic
if(queueSize<2) queueSize = 2;
std::vector<MonitorElementPtr> monitorElementArray;
@@ -296,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,
@@ -348,113 +305,7 @@ MonitorPtr MonitorFactory::createMonitor(
return monitor;
}
void MonitorFactory::registerMonitorAlgorithmCreate(
MonitorAlgorithmCreatePtr const &monitorAlgorithmCreate)
{
Lock xx(mutex);
if(isDestroyed) return;
// monitorAlgorithmCreateList.insert(monitorAlgorithmCreate);
}
MonitorAlgorithmCreatePtr MonitorFactory::getMonitorAlgorithmCreate(
String algorithmName)
{
Lock xx(mutex);
if(isDestroyed) return nullMonitorAlgorithmCreate;
// std::multiset<MonitorAlgorithmCreatePtr>::iterator iter;
// for(iter = monitorAlgorithmCreateList.begin();
// iter!= monitorAlgorithmCreateList.end();
// ++iter)
// {
// if((*iter)->getAlgorithmName().compare(algorithmName))
// return *iter;
// }
return nullMonitorAlgorithmCreate;
}
MultipleElementQueue::MultipleElementQueue(
MonitorLocalPtr const &monitorLocal,
MonitorElementQueuePtr const &queue,
size_t nfields)
: monitorLocal(monitorLocal),
queue(queue),
changedBitSet(new BitSet(nfields)),
overrunBitSet(new BitSet(nfields)),
queueIsFull(false)
{
}
Status MultipleElementQueue::start()
{
queue->clear();
queueIsFull = false;
changedBitSet->clear();
overrunBitSet->clear();
MonitorLocalPtr ml = monitorLocal.lock();
if(ml==NULL) return wasDestroyedStatus;
ml->getPVCopyMonitor()->startMonitoring(changedBitSet,overrunBitSet);
return Status::Ok;
}
Status MultipleElementQueue::stop()
{
return Status::Ok;
}
bool MultipleElementQueue::dataChanged()
{
MonitorLocalPtr ml = monitorLocal.lock();
if(ml==NULL) return false;
if(queueIsFull) {
MonitorElementPtr monitorElement = latestMonitorElement;
PVStructurePtr pvStructure = monitorElement->pvStructurePtr;
ml->getPVCopy()->updateCopyFromBitSet(pvStructure,changedBitSet);
(*monitorElement->changedBitSet)|= (*changedBitSet);
(*monitorElement->overrunBitSet)|= (*changedBitSet);
changedBitSet->clear();
overrunBitSet->clear();
return false;
}
MonitorElementPtr monitorElement = queue->getFree();
if(monitorElement==NULL) {
throw std::logic_error(String("MultipleElementQueue::dataChanged() logic error"));
}
if(queue->getNumberFree()==0){
queueIsFull = true;
latestMonitorElement = monitorElement;
}
PVStructurePtr pvStructure = monitorElement->pvStructurePtr;
ml->getPVCopy()->updateCopyFromBitSet(
pvStructure,changedBitSet);
BitSetUtil::compress(changedBitSet,pvStructure);
BitSetUtil::compress(overrunBitSet,pvStructure);
monitorElement->changedBitSet->clear();
(*monitorElement->changedBitSet)|=(*changedBitSet);
monitorElement->overrunBitSet->clear();
(*monitorElement->overrunBitSet)|=(*overrunBitSet);
changedBitSet->clear();
overrunBitSet->clear();
queue->setUsed(monitorElement);
return true;
}
MonitorElementPtr MultipleElementQueue::poll()
{
return queue->getUsed();
}
void MultipleElementQueue::release(MonitorElementPtr const &currentElement)
{
if(queueIsFull) {
MonitorElementPtr monitorElement = latestMonitorElement;
PVStructurePtr pvStructure = monitorElement->pvStructurePtr;
BitSetUtil::compress(monitorElement->changedBitSet,pvStructure);
BitSetUtil::compress(monitorElement->overrunBitSet,pvStructure);
queueIsFull = false;
latestMonitorElement.reset();
}
queue->releaseUsed(currentElement);
}
MonitorFactoryPtr getMonitorFactory()
{

View File

@@ -1,869 +0,0 @@
/* pvCopy.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/pvCopy.h>
namespace epics { namespace pvDatabase {
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;
static PVCopyPtr NULLPVCopy;
static FieldConstPtr NULLField;
static StructureConstPtr NULLStructure;
static PVStructurePtr NULLPVStructure;
static CopyNodePtr NULLCopyNode;
static CopyRecordNodePtr NULLCopyRecordNode;
struct CopyNode {
CopyNode()
: isStructure(false),
structureOffset(0),
nfields(0)
{}
bool isStructure;
size_t structureOffset; // In the copy
size_t nfields;
PVStructurePtr options;
};
struct CopyRecordNode : public CopyNode{
PVRecordFieldPtr recordPVField;
};
typedef std::vector<CopyNodePtr> CopyNodePtrArray;
typedef std::tr1::shared_ptr<CopyNodePtrArray> CopyNodePtrArrayPtr;
struct CopyStructureNode : public CopyNode {
CopyNodePtrArrayPtr nodes;
};
PVCopyPtr PVCopy::create(
PVRecordPtr const &pvRecord,
PVStructurePtr const &pvRequest,
String const & structureName)
{
PVStructurePtr pvStructure(pvRequest);
if(structureName.size()>0) {
if(pvRequest->getStructure()->getNumberFields()>0) {
pvStructure = pvRequest->getStructureField(structureName);
if(pvStructure.get()==NULL) return NULLPVCopy;
}
} else if(pvStructure->getSubField("field")!=NULL) {
pvStructure = pvRequest->getStructureField("field");
}
PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvRecord));
bool result = pvCopy->init(pvStructure);
if(!result) pvCopy.reset();
return pvCopy;
}
PVCopy::PVCopy(
PVRecordPtr const &pvRecord)
: pvRecord(pvRecord)
{
}
void PVCopy::destroy()
{
if(pvRecord->getTraceLevel()>0)
{
cout << "PVCopy::destroy" << endl;
}
headNode.reset();
}
PVRecordPtr PVCopy::getPVRecord()
{
return pvRecord;
}
StructureConstPtr PVCopy::getStructure()
{
return structure;
}
PVStructurePtr PVCopy::createPVStructure()
{
if(cacheInitStructure.get()!=NULL) {
PVStructurePtr save = cacheInitStructure;
cacheInitStructure.reset();
return save;
}
PVStructurePtr pvStructure =
getPVDataCreate()->createPVStructure(structure);
return pvStructure;
}
PVStructurePtr PVCopy::getOptions(
PVStructurePtr const &copyPVStructure,std::size_t fieldOffset)
{
CopyNodePtr node = headNode;
while(true) {
if(!node->isStructure) {
if(node->structureOffset==fieldOffset) return node->options;
return NULLPVStructure;
}
CopyStructureNodePtr structNode = static_pointer_cast<CopyStructureNode>(node);
CopyNodePtrArrayPtr nodes = structNode->nodes;
boolean okToContinue = false;
for(size_t i=0; i< nodes->size(); i++) {
node = (*nodes)[i];
size_t soff = node->structureOffset;
if(fieldOffset>=soff && fieldOffset<soff+node->nfields) {
if(fieldOffset==soff) return node->options;
if(!node->isStructure) {
return NULLPVStructure;
}
okToContinue = true;
break;
}
}
if(okToContinue) continue;
throw std::invalid_argument("fieldOffset not valid");
}
}
size_t PVCopy::getCopyOffset(PVRecordFieldPtr const &recordPVField)
{
if(!headNode->isStructure) {
CopyRecordNodePtr recordNode = static_pointer_cast<CopyRecordNode>(headNode);
if((recordNode->recordPVField.get())==recordPVField.get()) {
return headNode->structureOffset;
}
PVStructure * parent = recordPVField->getPVField()->getParent();
size_t offsetParent = parent->getFieldOffset();
size_t off = recordPVField->getPVField()->getFieldOffset();
size_t offdiff = off -offsetParent;
if(offdiff<recordNode->nfields) return headNode->structureOffset + offdiff;
return String::npos;
}
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
CopyRecordNodePtr recordNode = getCopyOffset(node,recordPVField);
if(recordNode.get()!=NULL) return recordNode->structureOffset;
return String::npos;
}
size_t PVCopy::getCopyOffset(
PVRecordStructurePtr const &recordPVStructure,
PVRecordFieldPtr const &recordPVField)
{
CopyRecordNodePtr recordNode;
if(!headNode->isStructure) {
recordNode = static_pointer_cast<CopyRecordNode>(headNode);
if(recordNode->recordPVField.get()!=recordPVStructure.get()) return String::npos;
} else {
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
recordNode = getCopyOffset(node,recordPVField);
}
if(recordNode.get()==NULL) return String::npos;
size_t diff = recordPVField->getPVField()->getFieldOffset()
- recordPVStructure->getPVStructure()->getFieldOffset();
return recordNode->structureOffset + diff;
}
PVRecordFieldPtr PVCopy::getRecordPVField(size_t structureOffset)
{
CopyRecordNodePtr recordNode;
if(!headNode->isStructure) {
recordNode = static_pointer_cast<CopyRecordNode>(headNode);
} else {
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
recordNode = getRecordNode(node,structureOffset);
}
if(recordNode.get()==NULL) {
throw std::invalid_argument(
"PVCopy::getRecordPVField: setstructureOffset not valid");
}
size_t diff = structureOffset - recordNode->structureOffset;
PVRecordFieldPtr pvRecordField = recordNode->recordPVField;
if(diff==0) return pvRecordField;
PVStructurePtr pvStructure
= static_pointer_cast<PVStructure>(pvRecordField->getPVField());
PVFieldPtr pvField = pvStructure->getSubField(
pvRecordField->getPVField()->getFieldOffset() + diff);
return pvRecord->findPVRecordField(pvField);
}
void PVCopy::initCopy(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet)
{
bitSet->clear();
bitSet->set(0);
pvRecord->lock();
try {
updateCopyFromBitSet(copyPVStructure,bitSet);
} catch(...) {
pvRecord->unlock();
throw;
}
pvRecord->unlock();
}
void PVCopy::updateCopySetBitSet(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet)
{
if(headNode->isStructure) {
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
updateStructureNodeSetBitSet(copyPVStructure,node,bitSet);
} else {
CopyRecordNodePtr recordNode = static_pointer_cast<CopyRecordNode>(headNode);
PVRecordFieldPtr pvRecordField= recordNode->recordPVField;
PVFieldPtr copyPVField = copyPVStructure;
PVFieldPtrArray const & pvCopyFields = copyPVStructure->getPVFields();
if(pvCopyFields.size()==1) {
copyPVField = pvCopyFields[0];
}
PVFieldPtr pvField = pvRecordField->getPVField();
if(pvField->getField()->getType()==epics::pvData::structure) {
updateSubFieldSetBitSet(copyPVField,pvRecordField,bitSet);
return;
}
if(pvCopyFields.size()!=1) {
throw std::logic_error("Logic error");
}
ConvertPtr convert = getConvert();
bool isEqual = convert->equals(copyPVField,pvField);
if(!isEqual) {
convert->copy(pvField, copyPVField);
bitSet->set(copyPVField->getFieldOffset());
}
}
}
void PVCopy::updateCopyFromBitSet(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet)
{
bool doAll = bitSet->get(0);
if(headNode->isStructure) {
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
updateStructureNodeFromBitSet(copyPVStructure,node,bitSet,true,doAll);
} else {
CopyRecordNodePtr recordNode = static_pointer_cast<CopyRecordNode>(headNode);
PVFieldPtrArray const & pvCopyFields = copyPVStructure->getPVFields();
if(pvCopyFields.size()==1) {
updateSubFieldFromBitSet(
pvCopyFields[0],
recordNode->recordPVField,bitSet,
true,doAll);
} else {
updateSubFieldFromBitSet(
copyPVStructure,
recordNode->recordPVField,bitSet,
true,doAll);
}
}
}
void PVCopy::updateRecord(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet)
{
bool doAll = bitSet->get(0);
pvRecord->beginGroupPut();
if(headNode->isStructure) {
CopyStructureNodePtr node =
static_pointer_cast<CopyStructureNode>(headNode);
updateStructureNodeFromBitSet(
copyPVStructure,node,bitSet,false,doAll);
} else {
CopyRecordNodePtr recordNode =
static_pointer_cast<CopyRecordNode>(headNode);
PVFieldPtrArray const & pvCopyFields =
copyPVStructure->getPVFields();
if(pvCopyFields.size()==1) {
updateSubFieldFromBitSet(
pvCopyFields[0],
recordNode->recordPVField,bitSet,
false,doAll);
} else {
updateSubFieldFromBitSet(
copyPVStructure,
recordNode->recordPVField,bitSet,
false,doAll);
}
}
pvRecord->endGroupPut();
}
PVCopyMonitorPtr PVCopy::createPVCopyMonitor(
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester)
{
PVCopyMonitorPtr pvCopyMonitor( new PVCopyMonitor(
pvRecord,headNode,getPtrSelf(),pvCopyMonitorRequester));
return pvCopyMonitor;
}
epics::pvData::String PVCopy::dump()
{
String builder;
dump(&builder,headNode,0);
return builder;
}
void PVCopy::dump(String *builder,CopyNodePtr const &node,int indentLevel)
{
getConvert()->newLine(builder,indentLevel);
std::stringstream ss;
ss << (node->isStructure ? "structureNode" : "recordNode");
ss << " structureOffset " << node->structureOffset;
ss << " nfields " << node->nfields;
*builder += ss.str();
PVStructurePtr options = node->options;
if(options.get()!=NULL) {
getConvert()->newLine(builder,indentLevel +1);
options->toString(builder);
getConvert()->newLine(builder,indentLevel);
}
if(!node->isStructure) {
CopyRecordNodePtr recordNode = static_pointer_cast<CopyRecordNode>(node);
String name = recordNode->recordPVField->getFullName();
*builder += " recordField " + name;
return;
}
CopyStructureNodePtr structureNode =
static_pointer_cast<CopyStructureNode>(node);
CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i<nodes->size(); ++i) {
if((*nodes)[i].get()==NULL) {
getConvert()->newLine(builder,indentLevel +1);
ss.str("");
ss << "node[" << i << "] is null";
*builder += ss.str();
continue;
}
dump(builder,(*nodes)[i],indentLevel+1);
}
}
bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
{
PVRecordStructurePtr pvRecordStructure = pvRecord->getPVRecordStructure();
size_t len = pvRequest->getPVFields().size();
bool entireRecord = false;
if(len==String::npos) entireRecord = true;
if(len==0) entireRecord = true;
PVStructurePtr pvOptions;
if(len==1 && pvRequest->getSubField("_options")!=NULL) {
pvOptions = pvRequest->getStructureField("_options");
}
if(entireRecord) {
structure = pvRecordStructure->getPVStructure()->getStructure();
CopyRecordNodePtr recordNode(new CopyRecordNode());
headNode = recordNode;
recordNode->options = pvOptions;
recordNode->isStructure = false;
recordNode->structureOffset = 0;
recordNode->recordPVField = pvRecordStructure;
recordNode->nfields = pvRecordStructure->getPVStructure()->getNumberFields();
return true;
}
structure = createStructure(pvRecordStructure->getPVStructure(),pvRequest);
if(structure==NULL) return false;
cacheInitStructure = createPVStructure();
headNode = createStructureNodes(
pvRecord->getPVRecordStructure(),
pvRequest,
cacheInitStructure);
return true;
}
epics::pvData::String PVCopy::dump(
String const &value,
CopyNodePtr const &node,
int indentLevel)
{
throw std::logic_error(String("Not Implemented"));
}
StructureConstPtr PVCopy::createStructure(
PVStructurePtr const &pvRecord,
PVStructurePtr const &pvFromRequest)
{
if(pvFromRequest->getStructure()->getNumberFields()==0) {
return pvRecord->getStructure();
}
PVFieldPtrArray const &pvFromRequestFields = pvFromRequest->getPVFields();
StringArray const &fromRequestFieldNames = pvFromRequest->getStructure()->getFieldNames();
size_t length = pvFromRequestFields.size();
if(length==0) return NULLStructure;
FieldConstPtrArray fields; fields.reserve(length);
StringArray fieldNames; fields.reserve(length);
for(size_t i=0; i<length; ++i) {
String const &fieldName = fromRequestFieldNames[i];
PVFieldPtr pvRecordField = pvRecord->getSubField(fieldName);
if(pvRecordField==NULL) continue;
FieldConstPtr field = pvRecordField->getField();
if(field->getType()==epics::pvData::structure) {
PVStructurePtr pvRequestStructure = static_pointer_cast<PVStructure>(
pvFromRequestFields[i]);
if(pvRequestStructure->getNumberFields()>0) {
StringArray const &names = pvRequestStructure->getStructure()->
getFieldNames();
size_t num = names.size();
if(num>0 && names[0].compare("_options")==0) --num;
if(num>0) {
if(pvRecordField->getField()->getType()!=epics::pvData::structure) continue;
fieldNames.push_back(fieldName);
fields.push_back(createStructure(
static_pointer_cast<PVStructure>(pvRecordField),
pvRequestStructure));
continue;
}
}
}
fieldNames.push_back(fieldName);
fields.push_back(field);
}
size_t numsubfields = fields.size();
if(numsubfields==0) return NULLStructure;
return getFieldCreate()->createStructure(fieldNames, fields);
}
CopyNodePtr PVCopy::createStructureNodes(
PVRecordStructurePtr const &pvRecordStructure,
PVStructurePtr const &pvFromRequest,
PVStructurePtr const &pvFromCopy)
{
PVFieldPtrArray const & copyPVFields = pvFromCopy->getPVFields();
PVStructurePtr pvOptions;
PVFieldPtr pvField = pvFromRequest->getSubField("_options");
if(pvField!=NULL) pvOptions = static_pointer_cast<PVStructure>(pvField);
size_t number = copyPVFields.size();
CopyNodePtrArrayPtr nodes(new CopyNodePtrArray());
nodes->reserve(number);
for(size_t i=0; i<number; i++) {
PVFieldPtr copyPVField = copyPVFields[i];
String fieldName = copyPVField->getFieldName();
PVStructurePtr requestPVStructure = static_pointer_cast<PVStructure>(
pvFromRequest->getSubField(fieldName));
PVStructurePtr pvSubFieldOptions;
PVFieldPtr pvField = requestPVStructure->getSubField("_options");
if(pvField!=NULL) pvSubFieldOptions = static_pointer_cast<PVStructure>(pvField);
PVRecordFieldPtr pvRecordField;
PVRecordFieldPtrArrayPtr pvRecordFields = pvRecordStructure->getPVRecordFields();
for(size_t j=0; i<pvRecordFields->size(); j++ ) {
if((*pvRecordFields)[j]->getPVField()->getFieldName().compare(fieldName)==0) {
pvRecordField = (*pvRecordFields)[j];
break;
}
}
size_t numberRequest = requestPVStructure->getPVFields().size();
if(pvSubFieldOptions!=NULL) numberRequest--;
if(numberRequest>0) {
nodes->push_back(createStructureNodes(
static_pointer_cast<PVRecordStructure>(pvRecordField),
requestPVStructure,
static_pointer_cast<PVStructure>(copyPVField)));
continue;
}
CopyRecordNodePtr recordNode(new CopyRecordNode());
recordNode->options = pvSubFieldOptions;
recordNode->isStructure = false;
recordNode->recordPVField = pvRecordField;
recordNode->nfields = copyPVField->getNumberFields();
recordNode->structureOffset = copyPVField->getFieldOffset();
nodes->push_back(recordNode);
}
CopyStructureNodePtr structureNode(new CopyStructureNode());
structureNode->isStructure = true;
structureNode->nodes = nodes;
structureNode->structureOffset = pvFromCopy->getFieldOffset();
structureNode->nfields = pvFromCopy->getNumberFields();
structureNode->options = pvOptions;
return structureNode;
}
void PVCopy::updateStructureNodeSetBitSet(
PVStructurePtr const &pvCopy,
CopyStructureNodePtr const &structureNode,
epics::pvData::BitSetPtr const &bitSet)
{
for(size_t i=0; i<structureNode->nodes->size(); i++) {
CopyNodePtr node = (*structureNode->nodes)[i];
PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset);
if(node->isStructure) {
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
CopyStructureNodePtr yyy =
static_pointer_cast<CopyStructureNode>(node);
updateStructureNodeSetBitSet(xxx,yyy,bitSet);
} else {
CopyRecordNodePtr recordNode =
static_pointer_cast<CopyRecordNode>(node);
updateSubFieldSetBitSet(pvField,recordNode->recordPVField,bitSet);
}
}
}
void PVCopy::updateSubFieldSetBitSet(
PVFieldPtr const &pvCopy,
PVRecordFieldPtr const &pvRecord,
BitSetPtr const &bitSet)
{
FieldConstPtr field = pvCopy->getField();
Type type = field->getType();
if(type!=epics::pvData::structure) {
ConvertPtr convert = getConvert();
bool isEqual = convert->equals(pvCopy,pvRecord->getPVField());
if(isEqual) {
if(type==structureArray) {
// always act as though a change occurred.
// Note that array elements are shared.
bitSet->set(pvCopy->getFieldOffset());
}
}
if(isEqual) return;
convert->copy(pvRecord->getPVField(), pvCopy);
bitSet->set(pvCopy->getFieldOffset());
return;
}
PVStructurePtr pvCopyStructure = static_pointer_cast<PVStructure>(pvCopy);
PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
PVRecordStructurePtr pvRecordStructure =
static_pointer_cast<PVRecordStructure>(pvRecord);
PVRecordFieldPtrArrayPtr pvRecordFields =
pvRecordStructure->getPVRecordFields();
size_t length = pvCopyFields.size();
for(size_t i=0; i<length; i++) {
updateSubFieldSetBitSet(pvCopyFields[i],(*pvRecordFields)[i],bitSet);
}
}
void PVCopy::updateStructureNodeFromBitSet(
PVStructurePtr const &pvCopy,
CopyStructureNodePtr const &structureNode,
BitSetPtr const &bitSet,
bool toCopy,
bool doAll)
{
size_t offset = structureNode->structureOffset;
if(!doAll) {
size_t nextSet = bitSet->nextSetBit(offset);
if(nextSet==String::npos) return;
}
if(offset>=pvCopy->getNextFieldOffset()) return;
if(!doAll) doAll = bitSet->get(offset);
CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i<nodes->size(); i++) {
CopyNodePtr node = (*nodes)[i];
PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset);
if(node->isStructure) {
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
CopyStructureNodePtr subStructureNode =
static_pointer_cast<CopyStructureNode>(node);
updateStructureNodeFromBitSet(
xxx,subStructureNode,bitSet,toCopy,doAll);
} else {
CopyRecordNodePtr recordNode =
static_pointer_cast<CopyRecordNode>(node);
updateSubFieldFromBitSet(
pvField,recordNode->recordPVField,bitSet,toCopy,doAll);
}
}
}
void PVCopy::updateSubFieldFromBitSet(
PVFieldPtr const &pvCopy,
PVRecordFieldPtr const &pvRecordField,
BitSetPtr const &bitSet,
bool toCopy,
bool doAll)
{
if(!doAll) {
doAll = bitSet->get(pvCopy->getFieldOffset());
}
if(!doAll) {
size_t offset = pvCopy->getFieldOffset();
size_t nextSet = bitSet->nextSetBit(offset);
if(nextSet==String::npos) return;
if(nextSet>=pvCopy->getNextFieldOffset()) return;
}
ConvertPtr convert = getConvert();
if(pvCopy->getField()->getType()==epics::pvData::structure) {
PVStructurePtr pvCopyStructure =
static_pointer_cast<PVStructure>(pvCopy);
PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
if(pvRecordField->getPVField()->getField()->getType()
!=epics::pvData::structure)
{
if(pvCopyFields.size()!=1) {
throw std::logic_error(String("Logic error"));
}
if(toCopy) {
convert->copy(pvRecordField->getPVField(), pvCopyFields[0]);
} else {
convert->copy(pvCopyFields[0], pvRecordField->getPVField());
}
return;
}
PVRecordStructurePtr pvRecordStructure =
static_pointer_cast<PVRecordStructure>(pvRecordField);
PVRecordFieldPtrArrayPtr pvRecordFields =
pvRecordStructure->getPVRecordFields();
for(size_t i=0; i<pvCopyFields.size(); i++) {
updateSubFieldFromBitSet(
pvCopyFields[i],
(*pvRecordFields)[i],
bitSet,toCopy,doAll);
}
} else {
if(toCopy) {
convert->copy(pvRecordField->getPVField(), pvCopy);
} else {
convert->copy(pvCopy, pvRecordField->getPVField());
}
}
}
CopyRecordNodePtr PVCopy::getCopyOffset(
CopyStructureNodePtr const &structureNode,
PVRecordFieldPtr const &recordPVField)
{
size_t offset = recordPVField->getPVField()->getFieldOffset();
CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i< nodes->size(); i++) {
CopyNodePtr node = (*nodes)[i];
if(!node->isStructure) {
CopyRecordNodePtr recordNode =
static_pointer_cast<CopyRecordNode>(node);
size_t off = recordNode->recordPVField->getPVField()->
getFieldOffset();
size_t nextOffset = recordNode->recordPVField->getPVField()->
getNextFieldOffset();
if(offset>= off && offset<nextOffset) return recordNode;
} else {
CopyStructureNodePtr subNode =
static_pointer_cast<CopyStructureNode>(node);
CopyRecordNodePtr recordNode =
getCopyOffset(subNode,recordPVField);
if(recordNode.get()!=NULL) return recordNode;
}
}
return NULLCopyRecordNode;
}
CopyRecordNodePtr PVCopy::getRecordNode(
CopyStructureNodePtr const &structureNode,
std::size_t structureOffset)
{
CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i< nodes->size(); i++) {
CopyNodePtr node = (*nodes)[i];
if(structureOffset>=(node->structureOffset + node->nfields)) continue;
if(!node->isStructure) {
CopyRecordNodePtr recordNode =
static_pointer_cast<CopyRecordNode>(node);
return recordNode;
}
CopyStructureNodePtr subNode =
static_pointer_cast<CopyStructureNode>(node);
return getRecordNode(subNode,structureOffset);
}
return NULLCopyRecordNode;
}
PVCopyMonitor::PVCopyMonitor(
PVRecordPtr const &pvRecord,
CopyNodePtr const &headNode,
PVCopyPtr const &pvCopy,
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester
)
: pvRecord(pvRecord),
headNode(headNode),
pvCopy(pvCopy),
pvCopyMonitorRequester(pvCopyMonitorRequester),
isGroupPut(false),
dataChanged(false),
isMonitoring(false)
{
}
PVCopyMonitor::~PVCopyMonitor()
{
if(pvRecord->getTraceLevel()>0)
{
cout << "~PVCopyMonitor" << endl;
}
}
void PVCopyMonitor::destroy()
{
if(pvRecord->getTraceLevel()>0)
{
cout << "PVCopyMonitor::destroy()" << endl;
}
stopMonitoring();
pvCopyMonitorRequester.reset();
pvCopy.reset();
}
void PVCopyMonitor::startMonitoring(
BitSetPtr const &changeBitSet,
BitSetPtr const &overrunBitSet)
{
if(pvRecord->getTraceLevel()>0)
{
cout << "PVCopyMonitor::startMonitoring()" << endl;
}
Lock xx(mutex);
if(isMonitoring) return;
isMonitoring = true;
this->changeBitSet = changeBitSet;
this->overrunBitSet = overrunBitSet;
isGroupPut = false;
pvRecord->lock();
try {
pvRecord->addListener(getPtrSelf());
addListener(headNode);
changeBitSet->clear();
overrunBitSet->clear();
changeBitSet->set(0);
pvCopyMonitorRequester->dataChanged();
pvRecord->unlock();
} catch(...) {
pvRecord->unlock();
}
}
void PVCopyMonitor::stopMonitoring()
{
if(pvRecord->getTraceLevel()>0)
{
cout << "PVCopyMonitor::stopMonitoring()" << endl;
}
Lock xx(mutex);
if(!isMonitoring) return;
isMonitoring = false;
pvRecord->removeListener(getPtrSelf());
}
void PVCopyMonitor::switchBitSets(
BitSetPtr const &newChangeBitSet,
BitSetPtr const &newOverrunBitSet)
{
changeBitSet = newChangeBitSet;
overrunBitSet = newOverrunBitSet;
}
void PVCopyMonitor::detach(PVRecordPtr const & pvRecord)
{
if(pvRecord->getTraceLevel()>0)
{
cout << "PVCopyMonitor::detach()" << endl;
}
}
void PVCopyMonitor::dataPut(PVRecordFieldPtr const & pvRecordField)
{
CopyNodePtr node = findNode(headNode,pvRecordField);
if(node.get()==NULL) {
throw std::logic_error("Logic error");
}
size_t offset = node->structureOffset;
bool isSet = changeBitSet->get(offset);
changeBitSet->set(offset);
if(isSet) overrunBitSet->set(offset);
if(!isGroupPut) pvCopyMonitorRequester->dataChanged();
dataChanged = true;
}
void PVCopyMonitor::dataPut(
PVRecordStructurePtr const & requested,
PVRecordFieldPtr const & pvRecordField)
{
CopyNodePtr node = findNode(headNode,requested);
if(node.get()==NULL || node->isStructure) {
throw std::logic_error("Logic error");
}
CopyRecordNodePtr recordNode = static_pointer_cast<CopyRecordNode>(node);
size_t offset = recordNode->structureOffset
+ (pvRecordField->getPVField()->getFieldOffset()
- recordNode->recordPVField->getPVField()->getFieldOffset());
bool isSet = changeBitSet->get(offset);
changeBitSet->set(offset);
if(isSet) overrunBitSet->set(offset);
if(!isGroupPut) pvCopyMonitorRequester->dataChanged();
dataChanged = true;
}
void PVCopyMonitor::beginGroupPut(PVRecordPtr const & pvRecord)
{
isGroupPut = true;
dataChanged = false;
}
void PVCopyMonitor::endGroupPut(PVRecordPtr const & pvRecord)
{
isGroupPut = false;
if(dataChanged) {
dataChanged = false;
pvCopyMonitorRequester->dataChanged();
}
}
void PVCopyMonitor::unlisten(PVRecordPtr const & pvRecord)
{
pvCopyMonitorRequester->unlisten();
}
void PVCopyMonitor::addListener(CopyNodePtr const & node)
{
if(!node->isStructure) {
PVRecordFieldPtr pvRecordField =
pvCopy->getRecordPVField(node->structureOffset);
pvRecordField->addListener(getPtrSelf());
return;
}
CopyStructureNodePtr structureNode =
static_pointer_cast<CopyStructureNode>(node);
for(size_t i=0; i< structureNode->nodes->size(); i++) {
addListener((*structureNode->nodes)[i]);
}
}
CopyNodePtr PVCopyMonitor::findNode(
CopyNodePtr const & node,
PVRecordFieldPtr const & pvRecordField)
{
if(!node->isStructure) {
CopyRecordNodePtr recordNode = static_pointer_cast<CopyRecordNode>(node);
if(recordNode->recordPVField==pvRecordField) return node;
return NULLCopyNode;
}
CopyStructureNodePtr structureNode = static_pointer_cast<CopyStructureNode>(node);
for(size_t i=0; i<structureNode->nodes->size(); i++) {
CopyNodePtr xxx = findNode((*structureNode->nodes)[i],pvRecordField);
if(xxx.get()!=NULL) return xxx;
}
return NULLCopyNode;
}
}}

View File

@@ -1,195 +0,0 @@
/* pvCopy.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 PVCOPY_H
#define PVCOPY_H
#include <string>
#include <stdexcept>
#include <memory>
#include <shareLib.h>
#include <pv/pvAccess.h>
#include <pv/pvDatabase.h>
namespace epics { namespace pvDatabase {
class PVCopy;
typedef std::tr1::shared_ptr<PVCopy> PVCopyPtr;
class PVCopyMonitor;
typedef std::tr1::shared_ptr<PVCopyMonitor> PVCopyMonitorPtr;
class PVCopyMonitorRequester;
typedef std::tr1::shared_ptr<PVCopyMonitorRequester> PVCopyMonitorRequesterPtr;
struct CopyNode;
typedef std::tr1::shared_ptr<CopyNode> CopyNodePtr;
struct CopyRecordNode;
typedef std::tr1::shared_ptr<CopyRecordNode> CopyRecordNodePtr;
struct CopyStructureNode;
typedef std::tr1::shared_ptr<CopyStructureNode> CopyStructureNodePtr;
class epicsShareClass PVCopy :
public std::tr1::enable_shared_from_this<PVCopy>
{
public:
POINTER_DEFINITIONS(PVCopy);
static PVCopyPtr create(
PVRecordPtr const &pvRecord,
epics::pvData::PVStructurePtr const &pvRequest,
epics::pvData::String const & structureName);
virtual ~PVCopy(){}
virtual void destroy();
PVRecordPtr getPVRecord();
epics::pvData::StructureConstPtr getStructure();
epics::pvData::PVStructurePtr createPVStructure();
std::size_t getCopyOffset(PVRecordFieldPtr const &recordPVField);
std::size_t getCopyOffset(
PVRecordStructurePtr const &recordPVStructure,
PVRecordFieldPtr const &recordPVField);
PVRecordFieldPtr getRecordPVField(std::size_t structureOffset);
void initCopy(
epics::pvData::PVStructurePtr const &copyPVStructure,
epics::pvData::BitSetPtr const &bitSet);
void updateCopySetBitSet(
epics::pvData::PVStructurePtr const &copyPVStructure,
epics::pvData::BitSetPtr const &bitSet);
void updateCopyFromBitSet(
epics::pvData::PVStructurePtr const &copyPVStructure,
epics::pvData::BitSetPtr const &bitSet);
void updateRecord(
epics::pvData::PVStructurePtr const &copyPVStructure,
epics::pvData::BitSetPtr const &bitSet);
PVCopyMonitorPtr createPVCopyMonitor(
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester);
epics::pvData::PVStructurePtr getOptions(
epics::pvData::PVStructurePtr const &copyPVStructure,std::size_t fieldOffset);
epics::pvData::String dump();
private:
void dump(
epics::pvData::String *builder,
CopyNodePtr const &node,
int indentLevel);
PVCopyPtr getPtrSelf()
{
return shared_from_this();
}
PVRecordPtr pvRecord;
epics::pvData::StructureConstPtr structure;
CopyNodePtr headNode;
epics::pvData::PVStructurePtr cacheInitStructure;
private:
PVCopy(PVRecordPtr const &pvRecord);
friend class PVCopyMonitor;
bool init(epics::pvData::PVStructurePtr const &pvRequest);
epics::pvData::String dump(
epics::pvData::String const &value,
CopyNodePtr const &node,
int indentLevel);
epics::pvData::StructureConstPtr createStructure(
epics::pvData::PVStructurePtr const &pvRecord,
epics::pvData::PVStructurePtr const &pvFromRequest);
CopyNodePtr createStructureNodes(
PVRecordStructurePtr const &pvRecordStructure,
epics::pvData::PVStructurePtr const &pvFromRequest,
epics::pvData::PVStructurePtr const &pvFromField);
void updateStructureNodeSetBitSet(
epics::pvData::PVStructurePtr const &pvCopy,
CopyStructureNodePtr const &structureNode,
epics::pvData::BitSetPtr const &bitSet);
void updateSubFieldSetBitSet(
epics::pvData::PVFieldPtr const &pvCopy,
PVRecordFieldPtr const &pvRecord,
epics::pvData::BitSetPtr const &bitSet);
void updateStructureNodeFromBitSet(
epics::pvData::PVStructurePtr const &pvCopy,
CopyStructureNodePtr const &structureNode,
epics::pvData::BitSetPtr const &bitSet,
bool toCopy,
bool doAll);
void updateSubFieldFromBitSet(
epics::pvData::PVFieldPtr const &pvCopy,
PVRecordFieldPtr const &pvRecordField,
epics::pvData::BitSetPtr const &bitSet,
bool toCopy,
bool doAll);
CopyRecordNodePtr getCopyOffset(
CopyStructureNodePtr const &structureNode,
PVRecordFieldPtr const &recordPVField);
CopyRecordNodePtr getRecordNode(
CopyStructureNodePtr const &structureNode,
std::size_t structureOffset);
};
class epicsShareClass PVCopyMonitor :
public PVListener,
public std::tr1::enable_shared_from_this<PVCopyMonitor>
{
public:
POINTER_DEFINITIONS(PVCopyMonitor);
virtual ~PVCopyMonitor();
virtual void destroy();
void startMonitoring(
epics::pvData::BitSetPtr const &changeBitSet,
epics::pvData::BitSetPtr const &overrunBitSet);
void stopMonitoring();
void switchBitSets(
epics::pvData::BitSetPtr const &newChangeBitSet,
epics::pvData::BitSetPtr const &newOverrunBitSet);
// 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);
private:
void addListener(CopyNodePtr const & node);
CopyNodePtr findNode(
CopyNodePtr const & node,
PVRecordFieldPtr const & pvRecordField);
PVCopyMonitorPtr getPtrSelf()
{
return shared_from_this();
}
PVCopyMonitor(
PVRecordPtr const &pvRecord,
CopyNodePtr const &headNode,
PVCopyPtr const &pvCopy,
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester);
friend class PVCopy;
PVRecordPtr pvRecord;
CopyNodePtr headNode;
PVCopyPtr pvCopy;
PVCopyMonitorRequesterPtr pvCopyMonitorRequester;
epics::pvData::BitSetPtr changeBitSet;
epics::pvData::BitSetPtr overrunBitSet;
bool isGroupPut;
bool dataChanged;
bool isMonitoring;
epics::pvData::Mutex mutex;
};
class epicsShareClass PVCopyMonitorRequester
{
public:
POINTER_DEFINITIONS(PVCopyMonitorRequester);
virtual ~PVCopyMonitorRequester() {}
virtual void dataChanged() = 0;
virtual void unlisten() = 0;
};
}}
#endif /* PVCOPY_H */

View File

@@ -0,0 +1,318 @@
/* 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),
isDestroyed(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) {
PVStringPtr pvName = pvOptions->getSubField<PVString>("plugin");
if(pvName) {
string pluginName = pvName->get();
MonitorPluginManagerPtr manager = MonitorPluginManager::get();
MonitorPluginCreatorPtr pluginCreator = manager->findPlugin(pluginName);
if(pluginCreator) {
StructureConstPtr top = pvCopy->getStructure();
FieldConstPtr field = pvField->getField();
MonitorPluginPtr monitorPlugin = pluginCreator->create(field,top,pvOptions);
if(monitorPlugin) {
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;
}
if(isDestroyed) return;
Lock xx(mutex);
isDestroyed = true;
stopMonitoring();
pvCopyMonitorRequester.reset();
pvCopy.reset();
}
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;
isGroupPut = false;
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
for (iter = monitorFieldNodeList.begin();iter!=monitorFieldNodeList.end();++iter)
{
(*iter)->monitorPlugin->startMonitoring();
}
pvRecord->addListener(getPtrSelf());
pvRecord->lock();
try {
pvCopy->traverseMaster(getPtrSelf());
monitorElement->changedBitSet->clear();
monitorElement->overrunBitSet->clear();
monitorElement->changedBitSet->set(0);
monitorElement = pvCopyMonitorRequester->releaseActiveElement();
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;
}
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;
}
void PVCopyMonitor::detach(PVRecordPtr const & pvRecord)
{
if(pvRecord->getTraceLevel()>0)
{
cout << "PVCopyMonitor::detach()" << endl;
}
}
void PVCopyMonitor::dataPut(PVRecordFieldPtr const & pvRecordField)
{
if(pvRecord->getTraceLevel()>1)
{
cout << "PVCopyMonitor::dataPut(pvRecordField)" << endl;
}
if(isDestroyed) return;
bool causeMonitor = true;
{
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) {
monitorElement = pvCopyMonitorRequester->releaseActiveElement();
dataChanged = false;
}
}
}
void PVCopyMonitor::dataPut(
PVRecordStructurePtr const & requested,
PVRecordFieldPtr const & pvRecordField)
{
if(pvRecord->getTraceLevel()>1)
{
cout << "PVCopyMonitor::dataPut(requested,pvRecordField)" << endl;
}
if(isDestroyed) return;
bool causeMonitor = true;
{
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) {
monitorElement = pvCopyMonitorRequester->releaseActiveElement();
dataChanged = false;
}
}
}
void PVCopyMonitor::beginGroupPut(PVRecordPtr const & pvRecord)
{
if(pvRecord->getTraceLevel()>1)
{
cout << "PVCopyMonitor::beginGroupPut()" << endl;
}
if(isDestroyed) return;
{
Lock xx(mutex);
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()>1)
{
cout << "PVCopyMonitor::endGroupPut() dataChanged " << dataChanged << endl;
}
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) {
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

@@ -0,0 +1,168 @@
/* 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 <pv/monitorPlugin.h>
#include <pv/pvCopy.h>
#include <pv/pvAccess.h>
#ifdef pvCopyMonitorEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef pvCopyMonitorEpicsExportSharedSymbols
#endif
#include <shareLib.h>
#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;
/**
* PVCopyMonitor
* This class manages changes to fields being monitored in a PVRecord.
*/
class epicsShareClass PVCopyMonitor :
public PVListener,
public epics::pvData::PVCopyTraverseMasterCallback,
public std::tr1::enable_shared_from_this<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();
/**
* 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();
// 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()
{
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;
bool isDestroyed;
epics::pvData::Mutex mutex;
std::list<PVCopyMonitorFieldNodePtr> monitorFieldNodeList;
};
class epicsShareClass PVCopyMonitorRequester
{
public:
POINTER_DEFINITIONS(PVCopyMonitorRequester);
virtual ~PVCopyMonitorRequester() {}
virtual epics::pvData::MonitorElementPtr releaseActiveElement() = 0;
virtual void unlisten() = 0;
};
}}
#endif /* PVCOPYMONITOR_H */

View File

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

Some files were not shown because too many files have changed in this diff Show More