use copy and monitor from pvDataCPP; imlement example plugin; algorithm => plugin

This commit is contained in:
Marty Kraimer
2014-04-23 09:25:58 -04:00
parent 342ab45dc8
commit fe62a7181f
15 changed files with 381 additions and 187 deletions

View File

@ -4,3 +4,4 @@ include "registerChannelProviderLocal.dbd"
include "dbPv.dbd"
include "powerSupplyRegister.dbd"
registrar("exampleDatabaseRegister")
registrar("exampleMonitorPluginRegister")

View File

@ -17,5 +17,6 @@ iocInit()
dbl
epicsThreadSleep(2.0)
exampleDatabase
exampleMonitorPlugin
startPVAServer
pvdbl

View File

@ -22,10 +22,13 @@ exampleDatabaseMain_LIBS += Com
DBD += exampleDatabase.dbd
INC += exampleDatabase.h
INC += exampleMonitorPlugin.h
LIBRARY_IOC += exampleDatabase
exampleDatabase_SRCS += exampleDatabase.cpp
exampleDatabase_SRCS += exampleMonitorPlugin.cpp
exampleDatabase_SRCS += exampleDatabaseRegister.cpp
exampleDatabase_SRCS += exampleMonitorPluginRegister.cpp
exampleDatabase_LIBS += pvDatabase
exampleDatabase_LIBS += pvAccess
exampleDatabase_LIBS += pvData

View File

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

View File

@ -21,6 +21,7 @@
#include <pv/channelProviderLocal.h>
#include <pv/exampleDatabase.h>
#include <pv/exampleMonitorPlugin.h>
#include <pv/serverContext.h>
using namespace std;
@ -35,6 +36,7 @@ int main(int argc,char *argv[])
PVDatabasePtr master = PVDatabase::getMaster();
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
ExampleDatabase::create();
ExampleMonitorPlugin::create();
ServerContext::shared_pointer ctx =
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
cout << "exampleDatabase\n";

View 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);
}
}
}}

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

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

View File

@ -14,7 +14,6 @@ LIBSRCS += pvDatabase.cpp
SRC_DIRS += $(DATABASE)/pvAccess
INC += channelProviderLocal.h
INC += monitorAlgorithm.h
INC += pvCopyMonitor.h
DBD += registerChannelProviderLocal.dbd
LIBSRCS += channelProviderLocal.cpp

View File

@ -66,7 +66,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.

View File

@ -21,10 +21,11 @@
#include <pv/lock.h>
#include <pv/pvType.h>
#include <pv/pvData.h>
#include <pv/monitorPlugin.h>
#include <pv/pvCopy.h>
#include <pv/pvAccess.h>
#include <pv/pvDatabase.h>
#include <pv/status.h>
#include <pv/monitorAlgorithm.h>
namespace epics { namespace pvDatabase {
@ -54,15 +55,10 @@ public:
PVRecordPtr const & pvRecord,
epics::pvData::MonitorRequester::shared_pointer const & monitorRequester,
epics::pvData::PVStructurePtr const & pvRequest);
void registerMonitorAlgorithmCreate(
MonitorAlgorithmCreatePtr const &monitorAlgorithmCreate);
MonitorAlgorithmCreatePtr getMonitorAlgorithmCreate(
epics::pvData::String algorithmName);
private:
MonitorFactory();
friend class MonitorLocal;
friend MonitorFactoryPtr getMonitorFactory();
std::multiset<MonitorAlgorithmCreatePtr> monitorAlgorithmCreateList;
bool isDestroyed;
epics::pvData::Mutex mutex;
};

View File

@ -1,60 +0,0 @@
/* monitorAlgorithm.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author Marty Kraimer
* @date 2013.04
*/
#ifndef MONITORALGORITHM_H
#define MONITORALGORITHM_H
#include <shareLib.h>
#include <pv/pvCopy.h>
namespace epics { namespace pvDatabase {
class MonitorAlgorithm;
typedef std::tr1::shared_ptr<MonitorAlgorithm> MonitorAlgorithmPtr;
class MonitorAlgorithmCreate;
typedef std::tr1::shared_ptr<MonitorAlgorithmCreate> MonitorAlgorithmCreatePtr;
class epicsShareClass MonitorAlgorithm
{
public:
POINTER_DEFINITIONS(MonitorAlgorithm);
virtual ~MonitorAlgorithm(){}
virtual epics::pvData::String getAlgorithmName(){return algorithmName;}
virtual bool causeMonitor() = 0;
virtual void monitorIssued() = 0;
protected:
MonitorAlgorithm(epics::pvData::String algorithmName)
: algorithmName(algorithmName)
{}
epics::pvData::String algorithmName;
};
class epicsShareClass MonitorAlgorithmCreate
{
public:
POINTER_DEFINITIONS(MonitorAlgorithmCreate);
virtual ~MonitorAlgorithmCreate(){}
virtual epics::pvData::String getAlgorithmName(){return algorithmName;}
virtual MonitorAlgorithmPtr create(
PVRecordPtr const &pvRecord,
epics::pvData::MonitorRequester::shared_pointer const &requester,
PVRecordFieldPtr const &fromPVRecord,
epics::pvData::PVStructurePtr const &pvOptions) = 0;
protected:
MonitorAlgorithmCreate(epics::pvData::String algorithmName)
: algorithmName(algorithmName)
{}
epics::pvData::String algorithmName;
};
}}
#endif /* MONITORALGORITHM_H */

View File

@ -26,28 +26,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::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>
@ -86,9 +76,7 @@ public:
private:
std::tr1::weak_ptr<MonitorLocal> monitorLocal;
MonitorElementQueuePtr queue;
BitSetPtr changedBitSet;
BitSetPtr overrunBitSet;
MonitorElementPtr latestMonitorElement;
MonitorElementPtr activeElement;
bool queueIsFull;
};
@ -352,29 +340,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,
@ -382,8 +347,6 @@ MultipleElementQueue::MultipleElementQueue(
size_t nfields)
: monitorLocal(monitorLocal),
queue(queue),
changedBitSet(new BitSet(nfields)),
overrunBitSet(new BitSet(nfields)),
queueIsFull(false)
{
}
@ -392,11 +355,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;
}
@ -409,55 +374,37 @@ 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 &currentElement)
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(currentElement);
queue->releaseUsed(element);
queueIsFull = false;
}
MonitorFactoryPtr getMonitorFactory()

View File

@ -28,6 +28,12 @@ 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,
@ -35,6 +41,7 @@ PVCopyMonitorPtr PVCopyMonitor::create(
{
PVCopyMonitorPtr pvCopyMonitor( new PVCopyMonitor(
pvRecord,pvCopy,pvCopyMonitorRequester));
pvCopyMonitor->init(pvRecord->getPVRecordStructure()->getPVStructure());
return pvCopyMonitor;
}
@ -61,6 +68,47 @@ PVCopyMonitor::~PVCopyMonitor()
}
}
// 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)
@ -72,9 +120,7 @@ void PVCopyMonitor::destroy()
pvCopy.reset();
}
void PVCopyMonitor::startMonitoring(
BitSetPtr const &changeBitSet,
BitSetPtr const &overrunBitSet)
void PVCopyMonitor::startMonitoring()
{
if(pvRecord->getTraceLevel()>0)
{
@ -83,16 +129,19 @@ void PVCopyMonitor::startMonitoring(
Lock xx(mutex);
if(isMonitoring) return;
isMonitoring = true;
this->changeBitSet = changeBitSet;
this->overrunBitSet = overrunBitSet;
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());
changeBitSet->clear();
overrunBitSet->clear();
changeBitSet->set(0);
monitorElement->changedBitSet->clear();
monitorElement->overrunBitSet->clear();
monitorElement->changedBitSet->set(0);
pvCopyMonitorRequester->dataChanged();
pvRecord->unlock();
} catch(...) {
@ -113,16 +162,38 @@ void PVCopyMonitor::stopMonitoring()
}
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::switchBitSets(
BitSetPtr const &newChangeBitSet,
BitSetPtr const &newOverrunBitSet)
void PVCopyMonitor::setMonitorElement(MonitorElementPtr const &xxx)
{
changeBitSet = newChangeBitSet;
overrunBitSet = newOverrunBitSet;
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)
@ -135,49 +206,91 @@ void PVCopyMonitor::detach(PVRecordPtr const & pvRecord)
void PVCopyMonitor::dataPut(PVRecordFieldPtr const & pvRecordField)
{
if(pvRecord->getTraceLevel()>0)
{
cout << "PVCopyMonitor::dataPut(pvRecordField)" << endl;
}
size_t offset = pvCopy->getCopyOffset(pvRecordField->getPVField());
bool isSet = changeBitSet->get(offset);
changeBitSet->set(offset);
BitSetPtr const &changedBitSet = monitorElement->changedBitSet;
BitSetPtr const &overrunBitSet = monitorElement->overrunBitSet;
bool isSet = changedBitSet->get(offset);
changedBitSet->set(offset);
if(isSet) overrunBitSet->set(offset);
if(!isGroupPut) pvCopyMonitorRequester->dataChanged();
dataChanged = true;
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());
#ifdef XXXXX
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());
#endif
bool isSet = changeBitSet->get(offset);
changeBitSet->set(offset);
bool isSet = changedBitSet->get(offset);
changedBitSet->set(offset);
if(isSet) overrunBitSet->set(offset);
if(!isGroupPut) pvCopyMonitorRequester->dataChanged();
dataChanged = true;
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();

View File

@ -13,6 +13,7 @@
#include <string>
#include <stdexcept>
#include <memory>
#include <list>
#include <shareLib.h>
@ -27,6 +28,10 @@ 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,
@ -40,13 +45,10 @@ public:
epics::pvData::PVCopyPtr const & pvCopy);
virtual ~PVCopyMonitor();
virtual void destroy();
void startMonitoring(
epics::pvData::BitSetPtr const &changeBitSet,
epics::pvData::BitSetPtr const &overrunBitSet);
void startMonitoring();
void stopMonitoring();
void switchBitSets(
epics::pvData::BitSetPtr const &newChangeBitSet,
epics::pvData::BitSetPtr const &newOverrunBitSet);
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);
@ -67,15 +69,17 @@ private:
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::BitSetPtr changeBitSet;
epics::pvData::BitSetPtr overrunBitSet;
epics::pvData::MonitorElementPtr monitorElement;
bool isGroupPut;
bool dataChanged;
bool isMonitoring;
epics::pvData::Mutex mutex;
std::list<PVCopyMonitorFieldNodePtr> monitorFieldNodeList;
};
class epicsShareClass PVCopyMonitorRequester