Compare commits
52 Commits
before_mer
...
4.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b9693562a | ||
|
|
f1c39ca5d2 | ||
|
|
16b1775b98 | ||
|
|
f6ee7333bb | ||
|
|
9f45bdfa75 | ||
|
|
03aa15b5f7 | ||
|
|
8093952ca2 | ||
|
|
2bea54e218 | ||
|
|
e81230dba5 | ||
|
|
50b8f306c3 | ||
|
|
65be8e5678 | ||
|
|
dbb9310adc | ||
|
|
50fbb396e8 | ||
|
|
ff19fe1cd8 | ||
|
|
230938220e | ||
|
|
334ed3b70a | ||
|
|
4c7e51d8ad | ||
|
|
4973a6297e | ||
|
|
f0d1481a28 | ||
|
|
d5235db54c | ||
|
|
b125035a11 | ||
|
|
9551b0e4c6 | ||
|
|
d6aa03815e | ||
|
|
ce0d62fbbc | ||
|
|
2fe3e66047 | ||
|
|
fa53d72258 | ||
|
|
b010cf0849 | ||
|
|
7fd707cb4b | ||
|
|
5d823307f0 | ||
|
|
d41d5726d2 | ||
|
|
723f98bc44 | ||
|
|
1544147bdd | ||
|
|
0447441cfa | ||
|
|
8ce42ebb9a | ||
|
|
c39b966121 | ||
|
|
61edf17cdf | ||
|
|
39f537d7da | ||
|
|
ba496de2d3 | ||
|
|
38574ed76f | ||
|
|
92be294bbf | ||
|
|
35429bf4df | ||
|
|
552925dfe6 | ||
|
|
d1791393ad | ||
|
|
3dbad700f7 | ||
|
|
c06e33e197 | ||
|
|
1d8f01517a | ||
|
|
8c1b142e48 | ||
|
|
ca27cb5e3c | ||
|
|
a5fa17aca7 | ||
|
|
fe62a7181f | ||
|
|
342ab45dc8 | ||
|
|
127830e3c7 |
@@ -7,5 +7,5 @@ db/
|
||||
dbd/
|
||||
documentation/html
|
||||
envPaths
|
||||
RELEASE.local
|
||||
configure/.*\.local
|
||||
/O\..*
|
||||
|
||||
5
.hgtags
5
.hgtags
@@ -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
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -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
|
||||
|
||||
32
Makefile
32
Makefile
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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 << " ";
|
||||
@@ -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,
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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 ";
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
25
documentation/RELEASE_NOTES.html
Normal file
25
documentation/RELEASE_NOTES.html
Normal file
@@ -0,0 +1,25 @@
|
||||
<h1>Release 4.0 IN DEVELOPMENT</h1>
|
||||
<p>The main changes since release 3.0.2 are:</p>
|
||||
<ul>
|
||||
<li>array semantics now enforce Copy On Write.</li>
|
||||
<li>String no longer defined.</li>
|
||||
<li>toString replaced by stream I/O </li>
|
||||
<li>union is new type.</li>
|
||||
<li>copy and monitor use new code in pvDataCPP</li>
|
||||
</ul>
|
||||
<h2>New Semantics for Arrays</h2>
|
||||
<p>pvDatabaseCPP has been changed to use the new array implementation from pvDataCPP.</p>
|
||||
<h2>String no longer defined</h2>
|
||||
<p>String is replaced by std::string.</p>
|
||||
<h2>toString replaced by stream I/O</h2>
|
||||
<p>All uses of toString have been changed to use the steam I/O that pvDataCPP implements.</p>
|
||||
<h2>union is a new basic type.</h2>
|
||||
<p>exampleDatabase now has example records for union and union array.
|
||||
There are records for regular union and for variant union.</p>
|
||||
<h2>copy</h2>
|
||||
<p>The implementation of copy and monitor for pvAccess has been changed
|
||||
to use the new monitor and copy support from pvDataCPP.</p>
|
||||
<h2>monitorPlugin</h2>
|
||||
<p>exampleDatabase now has a example plugin that implements onChange.</p>
|
||||
<h1>Release 0.9.2</h1>
|
||||
<p>This was the starting point for RELEASE_NOTES</p>
|
||||
50
documentation/RELEASE_NOTES.md
Normal file
50
documentation/RELEASE_NOTES.md
Normal file
@@ -0,0 +1,50 @@
|
||||
Release 4.0 IN DEVELOPMENT
|
||||
===========
|
||||
|
||||
The main changes since release 3.0.2 are:
|
||||
|
||||
* array semantics now enforce Copy On Write.
|
||||
* String no longer defined.
|
||||
* toString replaced by stream I/O
|
||||
* union is new type.
|
||||
* copy and monitor use new code in pvDataCPP
|
||||
|
||||
New Semantics for Arrays
|
||||
--------
|
||||
|
||||
pvDatabaseCPP has been changed to use the new array implementation from pvDataCPP.
|
||||
|
||||
String no longer defined
|
||||
---------
|
||||
|
||||
String is replaced by std::string.
|
||||
|
||||
|
||||
toString replaced by stream I/O
|
||||
---------
|
||||
|
||||
All uses of toString have been changed to use the steam I/O that pvDataCPP implements.
|
||||
|
||||
|
||||
union is a new basic type.
|
||||
------------
|
||||
|
||||
exampleDatabase now has example records for union and union array.
|
||||
There are records for regular union and for variant union.
|
||||
|
||||
|
||||
copy
|
||||
----
|
||||
|
||||
|
||||
The implementation of copy and monitor for pvAccess has been changed
|
||||
to use the new monitor and copy support from pvDataCPP.
|
||||
|
||||
monitorPlugin
|
||||
-------------
|
||||
|
||||
exampleDatabase now has a example plugin that implements onChange.
|
||||
|
||||
Release 0.9.2
|
||||
==========
|
||||
This was the starting point for RELEASE_NOTES
|
||||
8
documentation/TODO.html
Normal file
8
documentation/TODO.html
Normal 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
19
documentation/TODO.md
Normal 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
1940
documentation/pvDatabaseCPP_20140710.html
Normal file
1940
documentation/pvDatabaseCPP_20140710.html
Normal file
File diff suppressed because it is too large
Load Diff
2111
documentation/pvDatabaseCPP_20140811.html
Normal file
2111
documentation/pvDatabaseCPP_20140811.html
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
3
exampleDatabase/ioc/Db/dbDouble.db
Normal file
3
exampleDatabase/ioc/Db/dbDouble.db
Normal file
@@ -0,0 +1,3 @@
|
||||
record(ao, "$(name)")
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
7
exampleDatabase/ioc/src/exampleDatabaseInclude.dbd
Normal file
7
exampleDatabase/ioc/src/exampleDatabaseInclude.dbd
Normal file
@@ -0,0 +1,7 @@
|
||||
include "base.dbd"
|
||||
include "PVAServerRegister.dbd"
|
||||
include "registerChannelProviderLocal.dbd"
|
||||
include "dbPv.dbd"
|
||||
include "powerSupplyRegister.dbd"
|
||||
registrar("exampleDatabaseRegister")
|
||||
registrar("exampleMonitorPluginRegister")
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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{
|
||||
|
||||
2
exampleDatabase/src/exampleDatabaseInclude.dbd
Normal file
2
exampleDatabase/src/exampleDatabaseInclude.dbd
Normal file
@@ -0,0 +1,2 @@
|
||||
registrar("exampleDatabaseRegister")
|
||||
registrar("exampleMonitorPluginRegister")
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
registrar("exampleDatabaseRegister")
|
||||
101
exampleDatabase/src/exampleMonitorPlugin.cpp
Normal file
101
exampleDatabase/src/exampleMonitorPlugin.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
40
exampleDatabase/src/exampleMonitorPlugin.h
Normal file
40
exampleDatabase/src/exampleMonitorPlugin.h
Normal 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 */
|
||||
65
exampleDatabase/src/exampleMonitorPluginRegister.cpp
Normal file
65
exampleDatabase/src/exampleMonitorPluginRegister.cpp
Normal 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);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
#===========================
|
||||
|
||||
5
exampleLink/ioc/src/exampleLinkInclude.dbd
Normal file
5
exampleLink/ioc/src/exampleLinkInclude.dbd
Normal file
@@ -0,0 +1,5 @@
|
||||
include "base.dbd"
|
||||
include "PVAServerRegister.dbd"
|
||||
include "PVAClientRegister.dbd"
|
||||
include "registerChannelProviderLocal.dbd"
|
||||
registrar("exampleLinkRegister")
|
||||
@@ -13,4 +13,4 @@ cd ${TOP}/iocBoot/${IOC}
|
||||
iocInit()
|
||||
startPVAClient
|
||||
startPVAServer
|
||||
exampleLinkCreateRecord exampleLinkRemote pvAccess doubleArray
|
||||
exampleLinkCreateRecord exampleLink pvAccess doubleArray
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
1
exampleLink/src/exampleLinkInclude.dbd
Normal file
1
exampleLink/src/exampleLinkInclude.dbd
Normal file
@@ -0,0 +1 @@
|
||||
registrar("exampleLinkRegister")
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
5
examplePowerSupply/ioc/src/powerSupplyInclude.dbd
Normal file
5
examplePowerSupply/ioc/src/powerSupplyInclude.dbd
Normal file
@@ -0,0 +1,5 @@
|
||||
include "base.dbd"
|
||||
include "PVAServerRegister.dbd"
|
||||
include "registerChannelProviderLocal.dbd"
|
||||
include "dbPv.dbd"
|
||||
include "powerSupplyRegister.dbd"
|
||||
@@ -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
|
||||
|
||||
#===========================
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
6
exampleServer/ioc/src/exampleServerInclude.dbd
Normal file
6
exampleServer/ioc/src/exampleServerInclude.dbd
Normal file
@@ -0,0 +1,6 @@
|
||||
include "base.dbd"
|
||||
include "PVAClientRegister.dbd"
|
||||
include "PVAServerRegister.dbd"
|
||||
include "registerChannelProviderLocal.dbd"
|
||||
include "dbPv.dbd"
|
||||
include "exampleServer.dbd"
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
1
exampleServer/src/exampleServerInclude.dbd
Normal file
1
exampleServer/src/exampleServerInclude.dbd
Normal file
@@ -0,0 +1 @@
|
||||
registrar("exampleServerRegister")
|
||||
@@ -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";
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 */
|
||||
@@ -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 ¤tElement)
|
||||
{
|
||||
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()
|
||||
{
|
||||
|
||||
@@ -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 ©PVStructure,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 ©PVStructure,
|
||||
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 ©PVStructure,
|
||||
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 ©PVStructure,
|
||||
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 ©PVStructure,
|
||||
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;
|
||||
}
|
||||
|
||||
}}
|
||||
@@ -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 ©PVStructure,
|
||||
epics::pvData::BitSetPtr const &bitSet);
|
||||
void updateCopySetBitSet(
|
||||
epics::pvData::PVStructurePtr const ©PVStructure,
|
||||
epics::pvData::BitSetPtr const &bitSet);
|
||||
void updateCopyFromBitSet(
|
||||
epics::pvData::PVStructurePtr const ©PVStructure,
|
||||
epics::pvData::BitSetPtr const &bitSet);
|
||||
void updateRecord(
|
||||
epics::pvData::PVStructurePtr const ©PVStructure,
|
||||
epics::pvData::BitSetPtr const &bitSet);
|
||||
PVCopyMonitorPtr createPVCopyMonitor(
|
||||
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester);
|
||||
epics::pvData::PVStructurePtr getOptions(
|
||||
epics::pvData::PVStructurePtr const ©PVStructure,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 */
|
||||
318
src/pvAccess/pvCopyMonitor.cpp
Normal file
318
src/pvAccess/pvCopyMonitor.cpp
Normal 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();
|
||||
}
|
||||
|
||||
}}
|
||||
168
src/pvAccess/pvCopyMonitor.h
Normal file
168
src/pvAccess/pvCopyMonitor.h
Normal 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 */
|
||||
@@ -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
Reference in New Issue
Block a user