flow: Merged <feature> 'changesAfter3_0_2' to <develop> ('default').
This commit is contained in:
@ -7,5 +7,5 @@ db/
|
||||
dbd/
|
||||
documentation/html
|
||||
envPaths
|
||||
RELEASE.local
|
||||
configure/.*\.local
|
||||
/O\..*
|
||||
|
@ -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;
|
||||
|
@ -100,11 +100,14 @@ public:
|
||||
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()
|
||||
{
|
||||
@ -155,9 +158,12 @@ 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()
|
||||
{
|
||||
@ -206,21 +212,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 +250,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,9 +262,8 @@ 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;
|
||||
pvField = pvStructure->getSubField("value");
|
||||
@ -284,7 +290,7 @@ void LongArrayChannelGet::channelGetConnect(
|
||||
bool LongArrayChannelGet::init()
|
||||
{
|
||||
ChannelProvider::shared_pointer channelProvider =
|
||||
getChannelAccess()->getProvider(providerName);
|
||||
getChannelProviderRegistry()->getProvider(providerName);
|
||||
if(channelProvider==NULL) {
|
||||
cout << "provider " << providerName << " not found" << endl;
|
||||
return false;
|
||||
@ -355,7 +361,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 +404,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,
|
||||
@ -445,10 +451,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();
|
||||
}
|
||||
|
||||
|
@ -269,7 +269,8 @@ bool LongArrayMonitor::init(
|
||||
channelRequester = LAMChannelRequesterPtr(new LAMChannelRequester(getPtrSelf()));
|
||||
monitorRequester = LAMMonitorRequesterPtr(new LAMMonitorRequester(getPtrSelf(),waitTime));
|
||||
monitorRequester->init();
|
||||
ChannelProvider::shared_pointer channelProvider = getChannelAccess()->getProvider(providerName);
|
||||
ChannelProvider::shared_pointer channelProvider =
|
||||
getChannelProviderRegistry()->getProvider(providerName);
|
||||
if(channelProvider==NULL) {
|
||||
cout << "provider " << providerName << " not found" << endl;
|
||||
return false;
|
||||
|
@ -70,12 +70,17 @@ 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()
|
||||
{
|
||||
@ -103,7 +108,7 @@ private:
|
||||
|
||||
bool LongArrayChannelPut::init()
|
||||
{
|
||||
ChannelProvider::shared_pointer channelProvider = getChannelAccess()->getProvider(providerName);
|
||||
ChannelProvider::shared_pointer channelProvider = getChannelProviderRegistry()->getProvider(providerName);
|
||||
if(channelProvider==NULL) {
|
||||
cout << "provider " << providerName << " not found" << endl;
|
||||
return false;
|
||||
@ -168,8 +173,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,8 +182,8 @@ 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) {
|
||||
@ -222,7 +226,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;
|
||||
@ -264,7 +268,7 @@ void LongArrayChannelPut::run()
|
||||
channel->destroy();
|
||||
epicsThreadSleep(1.0);
|
||||
ChannelProvider::shared_pointer channelProvider =
|
||||
getChannelAccess()->getProvider(providerName);
|
||||
getChannelProviderRegistry()->getProvider(providerName);
|
||||
channel = channelProvider->createChannel(
|
||||
channelName,getPtrSelf(),0);
|
||||
event.wait();
|
||||
@ -310,7 +314,9 @@ void LongArrayChannelPut::run()
|
||||
}
|
||||
}
|
||||
|
||||
void LongArrayChannelPut::putDone(Status const & status)
|
||||
void LongArrayChannelPut::putDone(
|
||||
Status const & status,
|
||||
ChannelPut::shared_pointer const & channelPut)
|
||||
{
|
||||
event.signal();
|
||||
}
|
||||
|
@ -17,5 +17,6 @@ iocInit()
|
||||
dbl
|
||||
epicsThreadSleep(2.0)
|
||||
exampleDatabase
|
||||
exampleMonitorPlugin
|
||||
startPVAServer
|
||||
pvdbl
|
||||
|
@ -1 +1,2 @@
|
||||
registrar("exampleDatabaseRegister")
|
||||
registrar("exampleMonitorPluginRegister")
|
||||
|
97
exampleDatabase/src/exampleMonitorPlugin.cpp
Normal file
97
exampleDatabase/src/exampleMonitorPlugin.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
/* exampleMonitorPlugin.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2014.04.16
|
||||
*/
|
||||
|
||||
#include <pv/convert.h>
|
||||
#include <pv/monitorPlugin.h>
|
||||
#include <pv/exampleMonitorPlugin.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
using namespace epics::pvData;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
static String pluginName("onChange");
|
||||
static ConvertPtr convert(getConvert());
|
||||
|
||||
class OnChangePlugin;
|
||||
typedef std::tr1::shared_ptr<OnChangePlugin> OnChangePluginPtr;
|
||||
class OnChangePluginCreator;
|
||||
typedef std::tr1::shared_ptr<OnChangePluginCreator> OnChangePluginCreatorPtr;
|
||||
|
||||
class OnChangePlugin : public MonitorPlugin
|
||||
{
|
||||
public:
|
||||
virtual ~OnChangePlugin(){}
|
||||
OnChangePlugin() {}
|
||||
bool init(
|
||||
FieldConstPtr const &field,
|
||||
StructureConstPtr const &top,
|
||||
PVStructurePtr const &pvFieldOptions)
|
||||
{
|
||||
pvField = getPVDataCreate()->createPVField(field);
|
||||
raiseMonitor = true;
|
||||
if(pvFieldOptions!=NULL) {
|
||||
PVStringPtr pvString =
|
||||
pvFieldOptions->getSubField<PVString>("raiseMonitor");
|
||||
if(pvString!=NULL) {
|
||||
String value = pvString->get();
|
||||
if(value.compare("false")==0) raiseMonitor = false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
virtual String &getName(){return pluginName;}
|
||||
virtual bool causeMonitor(
|
||||
PVFieldPtr const &pvNew,
|
||||
PVStructurePtr const &pvTop,
|
||||
MonitorElementPtr const &monitorElement)
|
||||
{
|
||||
bool isSame = convert->equals(pvNew,pvField);
|
||||
if(isSame) return false;
|
||||
convert->copy(pvNew,pvField);
|
||||
return raiseMonitor;
|
||||
}
|
||||
private:
|
||||
PVFieldPtr pvField;
|
||||
bool raiseMonitor;
|
||||
};
|
||||
|
||||
class OnChangePluginCreator : public MonitorPluginCreator
|
||||
{
|
||||
public:
|
||||
virtual String &getName(){return pluginName;}
|
||||
virtual MonitorPluginPtr create(
|
||||
FieldConstPtr const &field,
|
||||
StructureConstPtr const &top,
|
||||
PVStructurePtr const &pvFieldOptions)
|
||||
{
|
||||
OnChangePluginPtr plugin(new OnChangePlugin());
|
||||
bool result = plugin->init(field,top,pvFieldOptions);
|
||||
if(!result) return MonitorPluginPtr();
|
||||
return plugin;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void ExampleMonitorPlugin::create()
|
||||
{
|
||||
static OnChangePluginCreatorPtr plugin;
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
if(plugin==NULL) {
|
||||
plugin = OnChangePluginCreatorPtr(new OnChangePluginCreator());
|
||||
MonitorPluginManager::get()->addPlugin(pluginName,plugin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
29
exampleDatabase/src/exampleMonitorPlugin.h
Normal file
29
exampleDatabase/src/exampleMonitorPlugin.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* exampleMonitorPlugin.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2014.04.16
|
||||
*/
|
||||
#ifndef EXAMPLEMONITORPLUGIN_H
|
||||
#define EXAMPLEMONITORPLUGIN_H
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/monitorPlugin.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class epicsShareClass ExampleMonitorPlugin{
|
||||
public:
|
||||
static void create();
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif /* EXAMPLEMONITORPLUGIN_H */
|
61
exampleDatabase/src/exampleMonitorPluginRegister.cpp
Normal file
61
exampleDatabase/src/exampleMonitorPluginRegister.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
/*exampleMonitorPlugin.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2013.07.24
|
||||
*/
|
||||
|
||||
|
||||
/* Author: Marty Kraimer */
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
|
||||
#include <cantProceed.h>
|
||||
#include <epicsStdio.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsEvent.h>
|
||||
#include <epicsThread.h>
|
||||
#include <iocsh.h>
|
||||
|
||||
#include <epicsExport.h>
|
||||
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/exampleMonitorPlugin.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvDatabase;
|
||||
|
||||
|
||||
static const iocshFuncDef exampleMonitorPluginFuncDef = {
|
||||
"exampleMonitorPlugin", 0,0 };
|
||||
|
||||
|
||||
static void exampleMonitorPluginCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
ExampleMonitorPlugin::create();
|
||||
}
|
||||
|
||||
static void exampleMonitorPluginRegister(void)
|
||||
{
|
||||
std::cout << "exampleMonitorPluginRegister\n";
|
||||
static int firstTime = 1;
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
iocshRegister(&exampleMonitorPluginFuncDef, exampleMonitorPluginCallFunc);
|
||||
}
|
||||
std::cout << "exampleMonitorPluginRegister returning\n";
|
||||
}
|
||||
epicsExportRegistrar(exampleMonitorPluginRegister);
|
@ -67,9 +67,8 @@ bool ExampleLink::init()
|
||||
if(pvValue==NULL) {
|
||||
return false;
|
||||
}
|
||||
ChannelAccess::shared_pointer channelAccess = getChannelAccess();
|
||||
ChannelProvider::shared_pointer provider =
|
||||
channelAccess->getProvider(providerName);
|
||||
getChannelProviderRegistry()->getProvider(providerName);
|
||||
if(provider==NULL) {
|
||||
cout << getRecordName() << " provider "
|
||||
<< providerName << " does not exist" << endl;
|
||||
@ -107,7 +106,7 @@ bool ExampleLink::init()
|
||||
void ExampleLink::process()
|
||||
{
|
||||
status = Status::Ok;
|
||||
channelGet->get(false);
|
||||
channelGet->get();
|
||||
event.wait();
|
||||
timeStamp.getCurrent();
|
||||
pvTimeStamp.set(timeStamp);
|
||||
@ -145,20 +144,23 @@ 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;
|
||||
event.signal();
|
||||
}
|
||||
|
||||
void ExampleLink::getDone(
|
||||
const Status& status,
|
||||
ChannelGet::shared_pointer const & channelGet,
|
||||
PVStructurePtr const & pvStructure,
|
||||
BitSetPtr const & bitSet)
|
||||
{
|
||||
this->status = status;
|
||||
getPVStructure = pvStructure;
|
||||
this->bitSet = bitSet;
|
||||
event.signal();
|
||||
}
|
||||
|
||||
void ExampleLink::getDone(const Status& status)
|
||||
{
|
||||
this->status = status;
|
||||
event.signal();
|
||||
}
|
||||
|
||||
}}
|
||||
|
@ -65,9 +65,12 @@ 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);
|
||||
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 epics::pvData::String getRequesterName() {return channelName;}
|
||||
virtual void message(
|
||||
epics::pvData::String const & message,
|
||||
|
@ -77,7 +77,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.
|
||||
|
@ -122,6 +122,19 @@ 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,
|
||||
ChannelRequester::shared_pointer const &channelRequester,
|
||||
|
@ -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 */
|
@ -15,6 +15,7 @@
|
||||
#include <pv/bitSetUtil.h>
|
||||
#include <pv/queue.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/pvCopyMonitor.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
|
||||
@ -27,28 +28,18 @@ using std::tr1::static_pointer_cast;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
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>
|
||||
@ -87,9 +78,7 @@ public:
|
||||
private:
|
||||
std::tr1::weak_ptr<MonitorLocal> monitorLocal;
|
||||
MonitorElementQueuePtr queue;
|
||||
BitSetPtr changedBitSet;
|
||||
BitSetPtr overrunBitSet;
|
||||
MonitorElementPtr latestMonitorElement;
|
||||
MonitorElementPtr activeElement;
|
||||
bool queueIsFull;
|
||||
};
|
||||
|
||||
@ -267,7 +256,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 +268,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;
|
||||
@ -348,29 +342,6 @@ 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,
|
||||
@ -378,8 +349,6 @@ MultipleElementQueue::MultipleElementQueue(
|
||||
size_t nfields)
|
||||
: monitorLocal(monitorLocal),
|
||||
queue(queue),
|
||||
changedBitSet(new BitSet(nfields)),
|
||||
overrunBitSet(new BitSet(nfields)),
|
||||
queueIsFull(false)
|
||||
{
|
||||
}
|
||||
@ -388,11 +357,13 @@ Status MultipleElementQueue::start()
|
||||
{
|
||||
queue->clear();
|
||||
queueIsFull = false;
|
||||
changedBitSet->clear();
|
||||
overrunBitSet->clear();
|
||||
activeElement = queue->getFree();
|
||||
activeElement->changedBitSet->clear();
|
||||
activeElement->overrunBitSet->clear();
|
||||
MonitorLocalPtr ml = monitorLocal.lock();
|
||||
if(ml==NULL) return wasDestroyedStatus;
|
||||
ml->getPVCopyMonitor()->startMonitoring(changedBitSet,overrunBitSet);
|
||||
ml->getPVCopyMonitor()->setMonitorElement(activeElement);
|
||||
ml->getPVCopyMonitor()->startMonitoring();
|
||||
return Status::Ok;
|
||||
}
|
||||
|
||||
@ -405,55 +376,41 @@ 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) {
|
||||
if(queueIsFull) return false;
|
||||
ml->getPVCopy()->updateCopyFromBitSet(
|
||||
activeElement->pvStructurePtr,activeElement->changedBitSet);
|
||||
BitSetUtil::compress(activeElement->changedBitSet,activeElement->pvStructurePtr);
|
||||
BitSetUtil::compress(activeElement->overrunBitSet,activeElement->pvStructurePtr);
|
||||
queue->setUsed(activeElement);
|
||||
activeElement = queue->getFree();
|
||||
if(activeElement==NULL) {
|
||||
throw std::logic_error(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);
|
||||
if(queue->getNumberFree()==0) queueIsFull = true;
|
||||
activeElement->changedBitSet->clear();
|
||||
activeElement->overrunBitSet->clear();
|
||||
ml->getPVCopyMonitor()->setMonitorElement(activeElement);
|
||||
return true;
|
||||
}
|
||||
|
||||
MonitorElementPtr MultipleElementQueue::poll()
|
||||
{
|
||||
return queue->getUsed();
|
||||
MonitorLocalPtr ml = monitorLocal.lock();
|
||||
if(ml==NULL) return MonitorElementPtr();
|
||||
MonitorElementPtr monitorElement = queue->getUsed();
|
||||
if(monitorElement==NULL) return monitorElement;
|
||||
ml->getPVCopyMonitor()->monitorDone(monitorElement);
|
||||
return monitorElement;
|
||||
}
|
||||
|
||||
void MultipleElementQueue::release(MonitorElementPtr const ¤tElement)
|
||||
void MultipleElementQueue::release(MonitorElementPtr const &element)
|
||||
{
|
||||
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(element);
|
||||
if(!queueIsFull) return;
|
||||
queueIsFull = false;
|
||||
if(!activeElement->changedBitSet->isEmpty()) {
|
||||
dataChanged();
|
||||
}
|
||||
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 */
|
307
src/pvAccess/pvCopyMonitor.cpp
Normal file
307
src/pvAccess/pvCopyMonitor.cpp
Normal file
@ -0,0 +1,307 @@
|
||||
/* 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>
|
||||
|
||||
#include <pv/channelProviderLocal.h>
|
||||
#include <pv/pvCopyMonitor.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;
|
||||
|
||||
struct PVCopyMonitorFieldNode
|
||||
{
|
||||
MonitorPluginPtr monitorPlugin;
|
||||
size_t offset; // in pvCopy
|
||||
};
|
||||
|
||||
PVCopyMonitorPtr PVCopyMonitor::create(
|
||||
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester,
|
||||
PVRecordPtr const &pvRecord,
|
||||
PVCopyPtr const & pvCopy)
|
||||
{
|
||||
PVCopyMonitorPtr pvCopyMonitor( new PVCopyMonitor(
|
||||
pvRecord,pvCopy,pvCopyMonitorRequester));
|
||||
pvCopyMonitor->init(pvRecord->getPVRecordStructure()->getPVStructure());
|
||||
return pvCopyMonitor;
|
||||
}
|
||||
|
||||
|
||||
PVCopyMonitor::PVCopyMonitor(
|
||||
PVRecordPtr const &pvRecord,
|
||||
PVCopyPtr const &pvCopy,
|
||||
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester
|
||||
)
|
||||
: pvRecord(pvRecord),
|
||||
pvCopy(pvCopy),
|
||||
pvCopyMonitorRequester(pvCopyMonitorRequester),
|
||||
isGroupPut(false),
|
||||
dataChanged(false),
|
||||
isMonitoring(false)
|
||||
{
|
||||
}
|
||||
|
||||
PVCopyMonitor::~PVCopyMonitor()
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>0)
|
||||
{
|
||||
cout << "~PVCopyMonitor" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// pvField is in top level structure of PVRecord.
|
||||
void PVCopyMonitor::init(PVFieldPtr const &pvField)
|
||||
{
|
||||
size_t offset = pvCopy->getCopyOffset(pvField);
|
||||
if(offset==String::npos) return;
|
||||
PVStructurePtr pvOptions = pvCopy->getOptions(offset);
|
||||
if(pvOptions!=NULL) {
|
||||
PVStringPtr pvName = pvOptions->getSubField<PVString>("plugin");
|
||||
if(pvName!=NULL) {
|
||||
String pluginName = pvName->get();
|
||||
MonitorPluginManagerPtr manager = MonitorPluginManager::get();
|
||||
MonitorPluginCreatorPtr pluginCreator = manager->findPlugin(pluginName);
|
||||
if(pluginCreator!=NULL) {
|
||||
StructureConstPtr top = pvCopy->getStructure();
|
||||
FieldConstPtr field = pvField->getField();
|
||||
MonitorPluginPtr monitorPlugin = pluginCreator->create(field,top,pvOptions);
|
||||
if(monitorPlugin!=NULL) {
|
||||
PVCopyMonitorFieldNodePtr fieldNode(new PVCopyMonitorFieldNode());
|
||||
fieldNode->monitorPlugin = monitorPlugin;
|
||||
fieldNode->offset = offset;
|
||||
monitorFieldNodeList.push_back(fieldNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(pvField->getField()->getType()!=structure) return;
|
||||
PVStructurePtr pv = static_pointer_cast<PVStructure>(pvField);
|
||||
const PVFieldPtrArray &pvFields = pv->getPVFields();
|
||||
for(size_t i=0; i<pvFields.size(); ++i ) init(pvFields[i]);
|
||||
}
|
||||
|
||||
MonitorPluginPtr PVCopyMonitor::getMonitorPlugin(size_t offset)
|
||||
{
|
||||
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
|
||||
for (iter = monitorFieldNodeList.begin();iter!=monitorFieldNodeList.end();++iter)
|
||||
{
|
||||
if((*iter)->offset==offset) return (*iter)->monitorPlugin;
|
||||
}
|
||||
return MonitorPluginPtr();
|
||||
}
|
||||
|
||||
void PVCopyMonitor::destroy()
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>0)
|
||||
{
|
||||
cout << "PVCopyMonitor::destroy()" << endl;
|
||||
}
|
||||
stopMonitoring();
|
||||
pvCopyMonitorRequester.reset();
|
||||
pvCopy.reset();
|
||||
}
|
||||
|
||||
void PVCopyMonitor::startMonitoring()
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>0)
|
||||
{
|
||||
cout << "PVCopyMonitor::startMonitoring()" << endl;
|
||||
}
|
||||
Lock xx(mutex);
|
||||
if(isMonitoring) return;
|
||||
isMonitoring = true;
|
||||
isGroupPut = false;
|
||||
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
|
||||
for (iter = monitorFieldNodeList.begin();iter!=monitorFieldNodeList.end();++iter)
|
||||
{
|
||||
(*iter)->monitorPlugin->startMonitoring();
|
||||
}
|
||||
pvRecord->lock();
|
||||
try {
|
||||
pvRecord->addListener(getPtrSelf());
|
||||
pvCopy->traverseMaster(getPtrSelf());
|
||||
monitorElement->changedBitSet->clear();
|
||||
monitorElement->overrunBitSet->clear();
|
||||
monitorElement->changedBitSet->set(0);
|
||||
pvCopyMonitorRequester->dataChanged();
|
||||
pvRecord->unlock();
|
||||
} catch(...) {
|
||||
pvRecord->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopyMonitor::nextMasterPVField(epics::pvData::PVFieldPtr const &pvField)
|
||||
{
|
||||
pvRecord->findPVRecordField(pvField)->addListener(getPtrSelf());
|
||||
}
|
||||
|
||||
void PVCopyMonitor::stopMonitoring()
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>0)
|
||||
{
|
||||
cout << "PVCopyMonitor::stopMonitoring()" << endl;
|
||||
}
|
||||
Lock xx(mutex);
|
||||
if(!isMonitoring) return;
|
||||
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
|
||||
for (iter = monitorFieldNodeList.begin();iter!=monitorFieldNodeList.end();++iter)
|
||||
{
|
||||
(*iter)->monitorPlugin->stopMonitoring();
|
||||
}
|
||||
isMonitoring = false;
|
||||
pvRecord->removeListener(getPtrSelf());
|
||||
}
|
||||
|
||||
|
||||
void PVCopyMonitor::setMonitorElement(MonitorElementPtr const &xxx)
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>0)
|
||||
{
|
||||
cout << "PVCopyMonitor::setMonitorElement()" << endl;
|
||||
}
|
||||
monitorElement = xxx;
|
||||
}
|
||||
|
||||
void PVCopyMonitor::monitorDone(MonitorElementPtr const &monitorElement)
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>0)
|
||||
{
|
||||
cout << "PVCopyMonitor::monitorDone()" << endl;
|
||||
}
|
||||
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
|
||||
for (iter = monitorFieldNodeList.begin();iter!=monitorFieldNodeList.end();++iter)
|
||||
{
|
||||
PVCopyMonitorFieldNodePtr fieldNode = *iter;
|
||||
MonitorPluginPtr monitorPlugin = fieldNode->monitorPlugin;
|
||||
monitorPlugin->monitorDone(monitorElement);
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopyMonitor::detach(PVRecordPtr const & pvRecord)
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>0)
|
||||
{
|
||||
cout << "PVCopyMonitor::detach()" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopyMonitor::dataPut(PVRecordFieldPtr const & pvRecordField)
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>0)
|
||||
{
|
||||
cout << "PVCopyMonitor::dataPut(pvRecordField)" << endl;
|
||||
}
|
||||
size_t offset = pvCopy->getCopyOffset(pvRecordField->getPVField());
|
||||
BitSetPtr const &changedBitSet = monitorElement->changedBitSet;
|
||||
BitSetPtr const &overrunBitSet = monitorElement->overrunBitSet;
|
||||
bool isSet = changedBitSet->get(offset);
|
||||
changedBitSet->set(offset);
|
||||
if(isSet) overrunBitSet->set(offset);
|
||||
MonitorPluginPtr monitorPlugin = getMonitorPlugin(offset);
|
||||
bool causeMonitor = true;
|
||||
if(monitorPlugin!=NULL) {
|
||||
causeMonitor = monitorPlugin->causeMonitor(
|
||||
pvRecordField->getPVField(),
|
||||
pvRecord->getPVRecordStructure()->getPVStructure(),
|
||||
monitorElement);
|
||||
}
|
||||
if(causeMonitor) {
|
||||
if(!isGroupPut) pvCopyMonitorRequester->dataChanged();
|
||||
dataChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopyMonitor::dataPut(
|
||||
PVRecordStructurePtr const & requested,
|
||||
PVRecordFieldPtr const & pvRecordField)
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>0)
|
||||
{
|
||||
cout << "PVCopyMonitor::dataPut(requested,pvRecordField)" << endl;
|
||||
}
|
||||
BitSetPtr const &changedBitSet = monitorElement->changedBitSet;
|
||||
BitSetPtr const &overrunBitSet = monitorElement->overrunBitSet;
|
||||
size_t offsetCopyRequested = pvCopy->getCopyOffset(
|
||||
requested->getPVField());
|
||||
size_t offset = offsetCopyRequested
|
||||
+ (pvRecordField->getPVField()->getFieldOffset()
|
||||
- requested->getPVField()->getFieldOffset());
|
||||
bool isSet = changedBitSet->get(offset);
|
||||
changedBitSet->set(offset);
|
||||
if(isSet) overrunBitSet->set(offset);
|
||||
MonitorPluginPtr monitorPlugin = getMonitorPlugin(offsetCopyRequested);
|
||||
bool causeMonitor = true;
|
||||
if(monitorPlugin!=NULL) {
|
||||
causeMonitor = monitorPlugin->causeMonitor(
|
||||
requested->getPVField(),
|
||||
pvRecord->getPVRecordStructure()->getPVStructure(),
|
||||
monitorElement);
|
||||
}
|
||||
if(causeMonitor) {
|
||||
if(!isGroupPut) pvCopyMonitorRequester->dataChanged();
|
||||
dataChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopyMonitor::beginGroupPut(PVRecordPtr const & pvRecord)
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>0)
|
||||
{
|
||||
cout << "PVCopyMonitor::beginGroupPut()" << endl;
|
||||
}
|
||||
isGroupPut = true;
|
||||
dataChanged = false;
|
||||
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
|
||||
for (iter = monitorFieldNodeList.begin();
|
||||
iter!=monitorFieldNodeList.end();
|
||||
++iter)
|
||||
{
|
||||
(*iter)->monitorPlugin->beginGroupPut();
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopyMonitor::endGroupPut(PVRecordPtr const & pvRecord)
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>0)
|
||||
{
|
||||
cout << "PVCopyMonitor::endGroupPut() dataChanged " << dataChanged << endl;
|
||||
}
|
||||
isGroupPut = false;
|
||||
std::list<PVCopyMonitorFieldNodePtr>::iterator iter;
|
||||
for (iter = monitorFieldNodeList.begin();iter!=monitorFieldNodeList.end();++iter)
|
||||
{
|
||||
(*iter)->monitorPlugin->endGroupPut();
|
||||
}
|
||||
if(dataChanged) {
|
||||
dataChanged = false;
|
||||
pvCopyMonitorRequester->dataChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopyMonitor::unlisten(PVRecordPtr const & pvRecord)
|
||||
{
|
||||
pvCopyMonitorRequester->unlisten();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}}
|
96
src/pvAccess/pvCopyMonitor.h
Normal file
96
src/pvAccess/pvCopyMonitor.h
Normal file
@ -0,0 +1,96 @@
|
||||
/* 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
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <list>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
#include <pv/pvCopy.h>
|
||||
#include <pv/pvAccess.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;
|
||||
|
||||
class PVCopyMonitorFieldNode;
|
||||
typedef std::tr1::shared_ptr<PVCopyMonitorFieldNode> PVCopyMonitorFieldNodePtr;
|
||||
|
||||
|
||||
class epicsShareClass PVCopyMonitor :
|
||||
public PVListener,
|
||||
public epics::pvData::PVCopyTraverseMasterCallback,
|
||||
public std::tr1::enable_shared_from_this<PVCopyMonitor>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVCopyMonitor);
|
||||
static PVCopyMonitorPtr create(
|
||||
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester,
|
||||
PVRecordPtr const &pvRecord,
|
||||
epics::pvData::PVCopyPtr const & pvCopy);
|
||||
virtual ~PVCopyMonitor();
|
||||
virtual void destroy();
|
||||
void startMonitoring();
|
||||
void stopMonitoring();
|
||||
void setMonitorElement(epics::pvData::MonitorElementPtr const &monitorElement);
|
||||
void monitorDone(epics::pvData::MonitorElementPtr const &monitorElement);
|
||||
// following are PVListener methods
|
||||
virtual void detach(PVRecordPtr const & pvRecord);
|
||||
virtual void dataPut(PVRecordFieldPtr const & pvRecordField);
|
||||
virtual void dataPut(
|
||||
PVRecordStructurePtr const & requested,
|
||||
PVRecordFieldPtr const & pvRecordField);
|
||||
virtual void beginGroupPut(PVRecordPtr const & pvRecord);
|
||||
virtual void endGroupPut(PVRecordPtr const & pvRecord);
|
||||
virtual void unlisten(PVRecordPtr const & pvRecord);
|
||||
// following is PVCopyTraverseMasterCallback method
|
||||
virtual void nextMasterPVField(epics::pvData::PVFieldPtr const &pvField);
|
||||
private:
|
||||
PVCopyMonitorPtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
PVCopyMonitor(
|
||||
PVRecordPtr const &pvRecord,
|
||||
epics::pvData::PVCopyPtr const &pvCopy,
|
||||
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester);
|
||||
void init(epics::pvData::PVFieldPtr const &pvField);
|
||||
epics::pvData::MonitorPluginPtr getMonitorPlugin(size_t offset);
|
||||
PVRecordPtr pvRecord;
|
||||
epics::pvData::PVCopyPtr pvCopy;
|
||||
PVCopyMonitorRequesterPtr pvCopyMonitorRequester;
|
||||
epics::pvData::MonitorElementPtr monitorElement;
|
||||
bool isGroupPut;
|
||||
bool dataChanged;
|
||||
bool isMonitoring;
|
||||
epics::pvData::Mutex mutex;
|
||||
std::list<PVCopyMonitorFieldNodePtr> monitorFieldNodeList;
|
||||
};
|
||||
|
||||
class epicsShareClass PVCopyMonitorRequester
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVCopyMonitorRequester);
|
||||
virtual ~PVCopyMonitorRequester() {}
|
||||
virtual void dataChanged() = 0;
|
||||
virtual void unlisten() = 0;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVCOPYMONITOR_H */
|
@ -79,7 +79,6 @@ static void testPVScalar(
|
||||
PVRecordPtr const & pvRecord,
|
||||
PVCopyPtr const & pvCopy)
|
||||
{
|
||||
PVRecordFieldPtr pvRecordField;
|
||||
PVStructurePtr pvStructureRecord;
|
||||
PVStructurePtr pvStructureCopy;
|
||||
PVFieldPtr pvField;
|
||||
@ -112,8 +111,7 @@ static void testPVScalar(
|
||||
bitSet->toString(&builder);
|
||||
cout << " bitSet " << builder;
|
||||
cout << endl;
|
||||
pvRecordField = pvRecord->findPVRecordField(pvValueRecord);
|
||||
offset = pvCopy->getCopyOffset(pvRecordField);
|
||||
offset = pvCopy->getCopyOffset(pvValueRecord);
|
||||
cout << "getCopyOffset() " << offset;
|
||||
cout << " pvValueCopy->getOffset() " << pvValueCopy->getFieldOffset();
|
||||
cout << " pvValueRecord->getOffset() " << pvValueRecord->getFieldOffset();
|
||||
@ -137,13 +135,13 @@ static void testPVScalar(
|
||||
cout << endl;
|
||||
convert->fromDouble(pvValueCopy,2.0);
|
||||
bitSet->set(0);
|
||||
cout << "before updateRecord";
|
||||
cout << "before updateMaster";
|
||||
cout << " recordValue " << convert->toDouble(pvValueRecord);
|
||||
cout << " copyValue " << convert->toDouble(pvValueCopy);
|
||||
cout << " bitSet " << builder;
|
||||
cout << endl;
|
||||
pvCopy->updateRecord(pvStructureCopy,bitSet);
|
||||
cout << "after updateRecord";
|
||||
pvCopy->updateMaster(pvStructureCopy,bitSet);
|
||||
cout << "after updateMaster";
|
||||
cout << " recordValue " << convert->toDouble(pvValueRecord);
|
||||
cout << " copyValue " << convert->toDouble(pvValueCopy);
|
||||
cout << " bitSet " << builder;
|
||||
@ -157,7 +155,6 @@ static void testPVScalarArray(
|
||||
PVRecordPtr const & pvRecord,
|
||||
PVCopyPtr const & pvCopy)
|
||||
{
|
||||
PVRecordFieldPtr pvRecordField;
|
||||
PVStructurePtr pvStructureRecord;
|
||||
PVStructurePtr pvStructureCopy;
|
||||
PVScalarArrayPtr pvValueRecord;
|
||||
@ -194,8 +191,7 @@ static void testPVScalarArray(
|
||||
bitSet->toString(&builder);
|
||||
cout << " bitSet " << builder;
|
||||
cout << endl;
|
||||
pvRecordField = pvRecord->findPVRecordField(pvValueRecord);
|
||||
offset = pvCopy->getCopyOffset(pvRecordField);
|
||||
offset = pvCopy->getCopyOffset(pvValueRecord);
|
||||
cout << "getCopyOffset() " << offset;
|
||||
cout << " pvValueCopy->getOffset() " << pvValueCopy->getFieldOffset();
|
||||
cout << " pvValueRecord->getOffset() " << pvValueRecord->getFieldOffset();
|
||||
@ -235,7 +231,7 @@ static void testPVScalarArray(
|
||||
const shared_vector<const double> ttt(freeze(values));
|
||||
pvValueRecord->putFrom(ttt);
|
||||
bitSet->set(0);
|
||||
cout << "before updateRecord";
|
||||
cout << "before updateMaster";
|
||||
builder.clear(); pvValueRecord->toString(&builder);
|
||||
cout << " recordValue " << builder << endl;
|
||||
builder.clear(); pvValueCopy->toString(&builder);
|
||||
@ -244,8 +240,8 @@ static void testPVScalarArray(
|
||||
bitSet->toString(&builder);
|
||||
cout << " bitSet " << builder;
|
||||
cout << endl;
|
||||
pvCopy->updateRecord(pvStructureCopy,bitSet);
|
||||
cout << "after updateRecord";
|
||||
pvCopy->updateMaster(pvStructureCopy,bitSet);
|
||||
cout << "after updateMaster";
|
||||
builder.clear(); pvValueRecord->toString(&builder);
|
||||
cout << " recordValue " << builder << endl;
|
||||
builder.clear(); pvValueCopy->toString(&builder);
|
||||
@ -263,7 +259,6 @@ static void scalarTest()
|
||||
PVRecordPtr pvRecord;
|
||||
String request;
|
||||
PVStructurePtr pvRequest;
|
||||
PVRecordFieldPtr pvRecordField;
|
||||
PVCopyPtr pvCopy;
|
||||
String builder;
|
||||
String valueNameRecord;
|
||||
@ -273,26 +268,22 @@ static void scalarTest()
|
||||
valueNameRecord = request = "value";
|
||||
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
builder.clear(); pvRequest->toString(&builder);
|
||||
cout << "request " << request << endl;
|
||||
cout << "pvRequest" << endl << builder;
|
||||
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
|
||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||
request = "";
|
||||
valueNameRecord = "value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
builder.clear(); pvRequest->toString(&builder);
|
||||
cout << "request " << request << endl << "pvRequest" << endl << builder << endl;
|
||||
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
|
||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||
request = "alarm,timeStamp,value";
|
||||
valueNameRecord = "value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
builder.clear(); pvRequest->toString(&builder);
|
||||
cout << "request " << request << endl << "pvRequest" << endl << builder << endl;
|
||||
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
|
||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||
pvRecord->destroy();
|
||||
@ -305,7 +296,6 @@ static void arrayTest()
|
||||
PVRecordPtr pvRecord;
|
||||
String request;
|
||||
PVStructurePtr pvRequest;
|
||||
PVRecordFieldPtr pvRecordField;
|
||||
PVCopyPtr pvCopy;
|
||||
String builder;
|
||||
String valueNameRecord;
|
||||
@ -315,26 +305,22 @@ static void arrayTest()
|
||||
pvRecord = createScalarArray("doubleArrayRecord",pvDouble,"alarm,timeStamp");
|
||||
valueNameRecord = request = "value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
builder.clear(); pvRequest->toString(&builder);
|
||||
cout << "request " << request << endl;
|
||||
cout << "pvRequest" << endl << builder;
|
||||
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
|
||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||
request = "";
|
||||
valueNameRecord = "value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
builder.clear(); pvRequest->toString(&builder);
|
||||
cout << "request " << request << endl << "pvRequest" << endl << builder << endl;
|
||||
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
|
||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||
request = "alarm,timeStamp,value";
|
||||
valueNameRecord = "value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
builder.clear(); pvRequest->toString(&builder);
|
||||
cout << "request " << request << endl << "pvRequest" << endl << builder << endl;
|
||||
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
|
||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||
valueNameCopy = "value";
|
||||
testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||
pvRecord->destroy();
|
||||
@ -347,7 +333,6 @@ static void powerSupplyTest()
|
||||
PowerSupplyPtr pvRecord;
|
||||
String request;
|
||||
PVStructurePtr pvRequest;
|
||||
PVRecordFieldPtr pvRecordField;
|
||||
PVCopyPtr pvCopy;
|
||||
String builder;
|
||||
String valueNameRecord;
|
||||
@ -358,34 +343,29 @@ static void powerSupplyTest()
|
||||
pvRecord = PowerSupply::create("powerSupply",pv);
|
||||
valueNameRecord = request = "power.value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
builder.clear(); pvRequest->toString(&builder);
|
||||
cout << "request " << request << endl;
|
||||
cout << "pvRequest" << endl << builder;
|
||||
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
|
||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||
valueNameCopy = "power.value";
|
||||
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||
request = "";
|
||||
valueNameRecord = "power.value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
builder.clear(); pvRequest->toString(&builder);
|
||||
cout << "request " << request << endl << "pvRequest" << endl << builder << endl;
|
||||
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
|
||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||
valueNameCopy = "power.value";
|
||||
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||
request = "alarm,timeStamp,voltage.value,power.value,current.value";
|
||||
valueNameRecord = "power.value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
builder.clear(); pvRequest->toString(&builder);
|
||||
cout << "request " << request << endl << "pvRequest" << endl << builder << endl;
|
||||
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
|
||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||
valueNameCopy = "power.value";
|
||||
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||
request = "alarm,timeStamp,voltage{value,alarm},power{value,alarm,display},current.value";
|
||||
valueNameRecord = "power.value";
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
builder.clear(); pvRequest->toString(&builder);
|
||||
cout << "request " << request << endl << "pvRequest" << endl << builder << endl;
|
||||
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
|
||||
cout << "request " << request << endl << "pvRequest" << pvRequest->dumpValue(cout) << endl ;
|
||||
pvCopy = PVCopy::create(pvRecord->getPVRecordStructure()->getPVStructure(),pvRequest,"");
|
||||
valueNameCopy = "power.value";
|
||||
testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy);
|
||||
pvRecord->destroy();
|
||||
|
Reference in New Issue
Block a user