use copy and monitor from pvDataCPP; imlement example plugin; algorithm => plugin
This commit is contained in:
@ -4,3 +4,4 @@ include "registerChannelProviderLocal.dbd"
|
||||
include "dbPv.dbd"
|
||||
include "powerSupplyRegister.dbd"
|
||||
registrar("exampleDatabaseRegister")
|
||||
registrar("exampleMonitorPluginRegister")
|
||||
|
@ -17,5 +17,6 @@ iocInit()
|
||||
dbl
|
||||
epicsThreadSleep(2.0)
|
||||
exampleDatabase
|
||||
exampleMonitorPlugin
|
||||
startPVAServer
|
||||
pvdbl
|
||||
|
@ -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
|
||||
|
@ -1 +1,2 @@
|
||||
registrar("exampleDatabaseRegister")
|
||||
registrar("exampleMonitorPluginRegister")
|
||||
|
@ -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";
|
||||
|
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);
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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 */
|
@ -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 ¤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(currentElement);
|
||||
queue->releaseUsed(element);
|
||||
queueIsFull = false;
|
||||
}
|
||||
|
||||
MonitorFactoryPtr getMonitorFactory()
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user