monitors now implemented
This commit is contained in:
@@ -19,9 +19,12 @@ LIBSRCS += recordList.cpp
|
||||
SRC_DIRS += $(DATABASE)/pvAccess
|
||||
INC += channelProviderLocal.h
|
||||
INC += pvCopy.h
|
||||
INC += monitorAlgorithm.h
|
||||
LIBSRCS += channelProviderLocal.cpp
|
||||
LIBSRCS += channelLocal.cpp
|
||||
LIBSRCS += pvCopy.cpp
|
||||
LIBSRCS += monitorFactory.cpp
|
||||
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#ifndef EXAMPLECOUNTER_H
|
||||
#define EXAMPLECOUNTER_H
|
||||
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/standardPVField.h>
|
||||
#include <pv/timeStamp.h>
|
||||
|
||||
@@ -61,9 +61,13 @@ void PVDatabase::destroy()
|
||||
}
|
||||
}
|
||||
|
||||
void PVDatabase::lock() {thelock.lock();}
|
||||
void PVDatabase::lock() {
|
||||
thelock.lock();
|
||||
}
|
||||
|
||||
void PVDatabase::unlock() {thelock.unlock();}
|
||||
void PVDatabase::unlock() {
|
||||
thelock.unlock();
|
||||
}
|
||||
|
||||
PVRecordPtr PVDatabase::findRecord(String const& recordName)
|
||||
{
|
||||
|
||||
@@ -346,11 +346,14 @@ protected:
|
||||
return shared_from_this();
|
||||
}
|
||||
virtual void init();
|
||||
virtual void postParent(PVRecordFieldPtr const & subField);
|
||||
virtual void postSubField();
|
||||
private:
|
||||
void callListener();
|
||||
|
||||
std::list<PVListenerPtr> pvListenerList;
|
||||
epics::pvData::PVFieldPtr pvField;
|
||||
bool isStructure;
|
||||
PVRecordStructurePtr parent;
|
||||
PVRecordPtr pvRecord;
|
||||
epics::pvData::String fullName;
|
||||
@@ -470,6 +473,11 @@ public:
|
||||
* @param pvRecord The record.
|
||||
*/
|
||||
virtual void endGroupPut(PVRecordPtr const & pvRecord) = 0;
|
||||
/**
|
||||
* Connection to record is being terminated.
|
||||
* @param pvRecord The record.
|
||||
*/
|
||||
virtual void unlisten(PVRecordPtr const & pvRecord) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+35
-10
@@ -169,11 +169,17 @@ PVRecordFieldPtr PVRecord::findPVRecordField(
|
||||
+ pvField->getFieldName() + " not in PVRecord");
|
||||
}
|
||||
|
||||
void PVRecord::lock() {thelock.lock();}
|
||||
void PVRecord::lock() {
|
||||
thelock.lock();
|
||||
}
|
||||
|
||||
void PVRecord::unlock() {thelock.unlock();}
|
||||
void PVRecord::unlock() {
|
||||
thelock.unlock();
|
||||
}
|
||||
|
||||
bool PVRecord::tryLock() {return thelock.tryLock();}
|
||||
bool PVRecord::tryLock() {
|
||||
return thelock.tryLock();
|
||||
}
|
||||
|
||||
void PVRecord::lockOtherRecord(PVRecordPtr const & otherRecord)
|
||||
{
|
||||
@@ -347,6 +353,7 @@ PVRecordField::PVRecordField(
|
||||
PVRecordStructurePtr const &parent,
|
||||
PVRecordPtr const & pvRecord)
|
||||
: pvField(pvField),
|
||||
isStructure(pvField->getField()->getType()==structure ? true : false),
|
||||
parent(parent),
|
||||
pvRecord(pvRecord)
|
||||
{
|
||||
@@ -419,15 +426,33 @@ void PVRecordField::removeListener(PVListenerPtr const & pvListener)
|
||||
|
||||
void PVRecordField::postPut()
|
||||
{
|
||||
callListener();
|
||||
if(parent!=NULL) {
|
||||
parent->postParent(getPtrSelf());
|
||||
}
|
||||
postSubField();
|
||||
}
|
||||
|
||||
void PVRecordField::postParent(PVRecordFieldPtr const & subField)
|
||||
{
|
||||
PVRecordStructurePtr pvrs = static_pointer_cast<PVRecordStructure>(getPtrSelf());
|
||||
std::list<PVListenerPtr>::iterator iter;
|
||||
PVRecordStructurePtr pvParent = getParent();
|
||||
while(pvParent.get()!=NULL) {
|
||||
std::list<PVListenerPtr> list = pvParent->pvListenerList;
|
||||
for (iter = list.begin(); iter!=list.end(); iter++ ) {
|
||||
(*iter)->dataPut(pvParent,getPtrSelf());
|
||||
for(iter = pvListenerList.begin(); iter != pvListenerList.end(); ++iter)
|
||||
{
|
||||
(*iter)->dataPut(pvrs,subField);
|
||||
}
|
||||
if(parent!=NULL) parent->postParent(subField);
|
||||
}
|
||||
|
||||
void PVRecordField::postSubField()
|
||||
{
|
||||
callListener();
|
||||
if(isStructure) {
|
||||
PVRecordStructurePtr pvrs = static_pointer_cast<PVRecordStructure>(getPtrSelf());
|
||||
PVRecordFieldPtrArrayPtr pvRecordFields = pvrs->getPVRecordFields();
|
||||
PVRecordFieldPtrArray::iterator iter;
|
||||
for(iter = pvRecordFields->begin() ; iter !=pvRecordFields->end(); iter++) {
|
||||
(*iter)->postSubField();
|
||||
}
|
||||
pvParent = pvParent->getParent();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,16 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @author Marty Kraimer
|
||||
* @date 2013.04
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <epicsThread.h>
|
||||
|
||||
#include <pv/channelProviderLocal.h>
|
||||
#include <pv/convert.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
using namespace epics::pvData;
|
||||
@@ -16,6 +22,8 @@ using namespace epics::pvAccess;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
|
||||
static ConvertPtr convert = getConvert();
|
||||
|
||||
class ChannelProcessLocal;
|
||||
typedef std::tr1::shared_ptr<ChannelProcessLocal> ChannelProcessLocalPtr;
|
||||
class ChannelGetLocal;
|
||||
@@ -79,13 +87,15 @@ private:
|
||||
ChannelProcessLocal(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelProcessRequester::shared_pointer const & channelProcessRequester,
|
||||
PVRecordPtr const &pvRecord)
|
||||
PVRecordPtr const &pvRecord,
|
||||
int nProcess)
|
||||
:
|
||||
isDestroyed(false),
|
||||
channelLocal(channelLocal),
|
||||
channelProcessRequester(channelProcessRequester),
|
||||
pvRecord(pvRecord),
|
||||
thelock(mutex)
|
||||
thelock(mutex),
|
||||
nProcess(nProcess)
|
||||
{
|
||||
thelock.unlock();
|
||||
}
|
||||
@@ -96,6 +106,7 @@ private:
|
||||
PVRecordPtr pvRecord;
|
||||
Mutex mutex;
|
||||
Lock thelock;
|
||||
int nProcess;
|
||||
};
|
||||
|
||||
ChannelProcessLocalPtr ChannelProcessLocal::create(
|
||||
@@ -104,10 +115,29 @@ ChannelProcessLocalPtr ChannelProcessLocal::create(
|
||||
PVStructurePtr const & pvRequest,
|
||||
PVRecordPtr const &pvRecord)
|
||||
{
|
||||
PVFieldPtr pvField;
|
||||
PVStructurePtr pvOptions;
|
||||
int nProcess = 1;
|
||||
if(pvRequest!=NULL) pvField = pvRequest->getSubField("record._options");
|
||||
if(pvField.get()!=NULL) {
|
||||
pvOptions = static_pointer_cast<PVStructure>(pvField);
|
||||
pvField = pvOptions->getSubField("nProcess");
|
||||
if(pvField.get()!=NULL) {
|
||||
PVStringPtr pvString = pvOptions->getStringField("nProcess");
|
||||
if(pvString.get()!=NULL) {
|
||||
int size;
|
||||
std::stringstream ss;
|
||||
ss << pvString->get();
|
||||
ss >> size;
|
||||
nProcess = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
ChannelProcessLocalPtr process(new ChannelProcessLocal(
|
||||
channelLocal,
|
||||
channelProcessRequester,
|
||||
pvRecord));
|
||||
pvRecord,
|
||||
nProcess));
|
||||
channelLocal->addChannelProcess(process);
|
||||
channelProcessRequester->channelProcessConnect(Status::Ok, process);
|
||||
return process;
|
||||
@@ -126,9 +156,13 @@ void ChannelProcessLocal::destroy()
|
||||
|
||||
void ChannelProcessLocal::process(bool lastRequest)
|
||||
{
|
||||
pvRecord->lock();
|
||||
pvRecord->process();
|
||||
pvRecord->unlock();
|
||||
for(int i=0; i< nProcess; i++) {
|
||||
pvRecord->lock();
|
||||
pvRecord->beginGroupPut();
|
||||
pvRecord->process();
|
||||
pvRecord->endGroupPut();
|
||||
pvRecord->unlock();
|
||||
}
|
||||
if(isDestroyed) {
|
||||
Status status(
|
||||
Status::Status::STATUSTYPE_ERROR,
|
||||
@@ -259,7 +293,11 @@ void ChannelGetLocal::get(bool lastRequest)
|
||||
}
|
||||
bitSet->clear();
|
||||
pvRecord->lock();
|
||||
if(callProcess) pvRecord->process();
|
||||
if(callProcess) {
|
||||
pvRecord->beginGroupPut();
|
||||
pvRecord->process();
|
||||
pvRecord->endGroupPut();
|
||||
}
|
||||
pvCopy->updateCopySetBitSet(pvStructure, bitSet, false);
|
||||
pvRecord->unlock();
|
||||
if(firstTime) {
|
||||
@@ -404,8 +442,12 @@ void ChannelPutLocal::put(bool lastRequest)
|
||||
channelPutRequester->getDone(status);
|
||||
}
|
||||
pvRecord->lock();
|
||||
pvRecord->beginGroupPut();
|
||||
pvCopy->updateRecord(pvStructure, bitSet, false);
|
||||
if(callProcess) pvRecord->process();
|
||||
if(callProcess) {
|
||||
pvRecord->process();
|
||||
}
|
||||
pvRecord->endGroupPut();
|
||||
pvRecord->unlock();
|
||||
channelPutRequester->getDone(Status::Ok);
|
||||
if(lastRequest) destroy();
|
||||
@@ -555,9 +597,11 @@ void ChannelPutGetLocal::putGet(bool lastRequest)
|
||||
putBitSet->clear();
|
||||
putBitSet->set(0);
|
||||
pvRecord->lock();
|
||||
pvRecord->beginGroupPut();
|
||||
pvPutCopy->updateRecord(pvPutStructure, putBitSet, false);
|
||||
if(callProcess) pvRecord->process();
|
||||
pvGetCopy->updateCopySetBitSet(pvGetStructure, getBitSet, false);
|
||||
pvRecord->endGroupPut();
|
||||
pvRecord->unlock();
|
||||
getBitSet->clear();
|
||||
getBitSet->set(0);
|
||||
@@ -597,23 +641,6 @@ void ChannelPutGetLocal::getGet()
|
||||
channelPutGetRequester->getGetDone(Status::Ok);
|
||||
}
|
||||
|
||||
class ChannelMonitorLocal :
|
||||
public Monitor
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelMonitorLocal);
|
||||
virtual ~ChannelMonitorLocal();
|
||||
static Monitor::shared_pointer create(
|
||||
ChannelProviderLocalPtr const &channelProvider,
|
||||
MonitorRequester::shared_pointer const & channelMonitorRequester,
|
||||
PVStructurePtr const & pvRequest,
|
||||
PVRecordPtr const &pvRecord);
|
||||
virtual Status start();
|
||||
virtual Status stop();
|
||||
virtual MonitorElementPtr poll();
|
||||
virtual void release(MonitorElementPtr const & monitorElement);
|
||||
};
|
||||
|
||||
class ChannelRPCLocal :
|
||||
public ChannelRPC
|
||||
{
|
||||
@@ -630,22 +657,6 @@ public:
|
||||
bool lastRequest);
|
||||
};
|
||||
|
||||
class ChannelArrayLocal :
|
||||
public ChannelArray
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelArrayLocal);
|
||||
virtual ~ChannelArrayLocal();
|
||||
static ChannelArray::shared_pointer create(
|
||||
ChannelProviderLocalPtr const &channelProvider,
|
||||
ChannelArray::shared_pointer const & channelArrayRequester,
|
||||
PVStructurePtr const & pvRequest,
|
||||
PVRecordPtr const &pvRecord);
|
||||
virtual void putArray(bool lastRequest, int offset, int count);
|
||||
virtual void getArray(bool lastRequest, int offset, int count);
|
||||
virtual void setLength(bool lastRequest, int length, int capacity);
|
||||
};
|
||||
|
||||
int ChannelLocalDebugLevel = 0;
|
||||
void ChannelLocalDebug::setLevel(int level) {ChannelLocalDebugLevel = level;}
|
||||
int ChannelLocalDebug::getLevel() {return ChannelLocalDebugLevel;}
|
||||
@@ -1009,14 +1020,9 @@ Monitor::shared_pointer ChannelLocal::createMonitor(
|
||||
MonitorRequester::shared_pointer const &monitorRequester,
|
||||
PVStructure::shared_pointer const &pvRequest)
|
||||
{
|
||||
Status status(Status::STATUSTYPE_ERROR,
|
||||
String("ChannelMonitor not supported"));
|
||||
Monitor::shared_pointer thisPointer = dynamic_pointer_cast<Monitor>(getPtrSelf());
|
||||
monitorRequester->monitorConnect(
|
||||
status,
|
||||
thisPointer,
|
||||
StructureConstPtr());
|
||||
return Monitor::shared_pointer();
|
||||
MonitorPtr monitor =
|
||||
getMonitorFactory()->createMonitor(pvRecord,monitorRequester,pvRequest);
|
||||
return monitor;
|
||||
}
|
||||
|
||||
ChannelArray::shared_pointer ChannelLocal::createChannelArray(
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @author Marty Kraimer
|
||||
* @date 2013.04
|
||||
*/
|
||||
|
||||
#include <pv/serverContext.h>
|
||||
@@ -98,11 +99,17 @@ void LocalChannelCTX::run()
|
||||
}
|
||||
|
||||
|
||||
ChannelProviderLocalPtr ChannelProviderLocal::create()
|
||||
ChannelProviderLocalPtr getChannelProviderLocal()
|
||||
{
|
||||
ChannelProviderLocalPtr channelProvider(new ChannelProviderLocal());
|
||||
LocalChannelCTX::create(channelProvider);
|
||||
return channelProvider;
|
||||
static ChannelProviderLocalPtr channelProviderLocal;
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
if(channelProviderLocal.get()==NULL) {
|
||||
channelProviderLocal = ChannelProviderLocalPtr(
|
||||
new ChannelProviderLocal());
|
||||
LocalChannelCTX::create(channelProviderLocal);
|
||||
}
|
||||
return channelProviderLocal;
|
||||
}
|
||||
|
||||
ChannelProviderLocal::ChannelProviderLocal()
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @author Marty Kraimer
|
||||
* @data 2013.04
|
||||
*/
|
||||
#ifndef CHANNELPROVIDERLOCAL_H
|
||||
#define CHANNELPROVIDERLOCAL_H
|
||||
@@ -22,10 +23,13 @@
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/status.h>
|
||||
#include <pv/pvCopy.h>
|
||||
#include <pv/monitorAlgorithm.h>
|
||||
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class MonitorFactory;
|
||||
typedef std::tr1::shared_ptr<MonitorFactory> MonitorFactoryPtr;
|
||||
|
||||
class ChannelProviderLocal;
|
||||
typedef std::tr1::shared_ptr<ChannelProviderLocal> ChannelProviderLocalPtr;
|
||||
@@ -33,14 +37,45 @@ class ChannelLocal;
|
||||
typedef std::tr1::shared_ptr<ChannelLocal> ChannelLocalPtr;
|
||||
typedef std::set<ChannelLocalPtr> ChannelLocalList;
|
||||
|
||||
extern MonitorFactoryPtr getMonitorFactory();
|
||||
class MonitorLocal;
|
||||
typedef std::tr1::shared_ptr<MonitorLocal> MonitorLocalPtr;
|
||||
typedef std::set<MonitorLocalPtr> MonitorLocalList;
|
||||
|
||||
|
||||
class MonitorFactory
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(MonitorFactory);
|
||||
virtual ~MonitorFactory();
|
||||
virtual void destroy();
|
||||
epics::pvData::MonitorPtr createMonitor(
|
||||
PVRecordPtr const & pvRecord,
|
||||
epics::pvData::MonitorRequester::shared_pointer const & monitorRequester,
|
||||
epics::pvData::PVStructurePtr const & pvRequest);
|
||||
void registerMonitorAlgorithmCreate(
|
||||
MonitorAlgorithmCreatePtr const &monitorAlgorithmCreate);
|
||||
MonitorAlgorithmCreatePtr getMonitorAlgorithmCreate(epics::pvData::String algorithmName);
|
||||
private:
|
||||
MonitorFactory();
|
||||
void removeMonitor(MonitorLocal * monitor);
|
||||
friend class MonitorLocal;
|
||||
friend MonitorFactoryPtr getMonitorFactory();
|
||||
std::set<MonitorAlgorithmCreatePtr> monitorAlgorithmCreateList;
|
||||
std::set<MonitorLocalPtr> monitorLocalList;
|
||||
bool isDestroyed;
|
||||
epics::pvData::Mutex mutex;
|
||||
};
|
||||
|
||||
|
||||
extern ChannelProviderLocalPtr getChannelProviderLocal();
|
||||
|
||||
class ChannelProviderLocal :
|
||||
public epics::pvAccess::ChannelProvider,
|
||||
public std::tr1::enable_shared_from_this<ChannelProviderLocal>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelProviderLocal);
|
||||
|
||||
static ChannelProviderLocalPtr create();
|
||||
virtual ~ChannelProviderLocal();
|
||||
virtual void destroy();
|
||||
virtual epics::pvData::String getProviderName();
|
||||
@@ -64,7 +99,7 @@ private:
|
||||
return shared_from_this();
|
||||
}
|
||||
ChannelProviderLocal();
|
||||
|
||||
friend ChannelProviderLocalPtr getChannelProviderLocal();
|
||||
PVDatabasePtr pvDatabase;
|
||||
ChannelLocalList channelList;
|
||||
epics::pvData::Mutex mutex;
|
||||
|
||||
@@ -4,35 +4,55 @@
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/* Marty Kraimer 2011.03 */
|
||||
/**
|
||||
* @author Marty Kraimer
|
||||
* @data 2013.04
|
||||
*/
|
||||
#ifndef MONITORALGORITHM_H
|
||||
#define MONITORALGORITHM_H
|
||||
#include <string>
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvCopy.h>
|
||||
|
||||
namespace epics { namespace pvIOC {
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class MonitorAlgorithm {
|
||||
class MonitorAlgorithm;
|
||||
typedef std::tr1::shared_ptr<MonitorAlgorithm> MonitorAlgorithmPtr;
|
||||
class MonitorAlgorithmCreate;
|
||||
typedef std::tr1::shared_ptr<MonitorAlgorithmCreate> MonitorAlgorithmCreatePtr;
|
||||
|
||||
class MonitorAlgorithm
|
||||
{
|
||||
public:
|
||||
MonitorAlgorithm(){}
|
||||
virtual ~MonitorAlgorithm(){}
|
||||
virtual epics::pvData::String getAlgorithmName() = 0;
|
||||
virtual bool causeMonitor() = 0;
|
||||
void monitorIssued() = 0;
|
||||
}}
|
||||
|
||||
class MonitorAlgorithmCreate {
|
||||
public:
|
||||
virtual String getAlgorithmName() = 0;
|
||||
virtual std::auto_ptr<MonitorAlgorithm> create(
|
||||
PVRecord &pvRecord;
|
||||
MonitorRequester &requester;
|
||||
PVRecordField &pvRecordField;
|
||||
PVStructure &pvStructure);
|
||||
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;
|
||||
};
|
||||
|
||||
extern MonitorAlgorithmCreate& getAlgorithmDeadband();
|
||||
extern MonitorAlgorithmCreate& getAlgorithmOnChange();
|
||||
class 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 */
|
||||
|
||||
@@ -0,0 +1,541 @@
|
||||
/* monitorFactory.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 <sstream>
|
||||
|
||||
#include <pv/channelProviderLocal.h>
|
||||
#include <pv/channelProviderLocal.h>
|
||||
#include <pv/bitSetUtil.h>
|
||||
#include <pv/queue.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
|
||||
static MonitorAlgorithmCreatePtr nullMonitorAlgorithmCreate;
|
||||
static MonitorPtr nullMonitor;
|
||||
static MonitorElementPtr NULLMonitorElement;
|
||||
|
||||
static ConvertPtr convert = getConvert();
|
||||
|
||||
//class MonitorFieldNode;
|
||||
//typedef std::tr1::shared_ptr<MonitorFieldNode> MonitorFieldNodePtr;
|
||||
|
||||
class MonitorQueue;
|
||||
typedef std::tr1::shared_ptr<MonitorQueue> MonitorQueuePtr;
|
||||
class NOQueue;
|
||||
typedef std::tr1::shared_ptr<NOQueue> NOQueuePtr;
|
||||
class RealQueue;
|
||||
typedef std::tr1::shared_ptr<RealQueue> RealQueuePtr;
|
||||
|
||||
class MonitorLocal;
|
||||
typedef std::tr1::shared_ptr<MonitorLocal> MonitorLocalPtr;
|
||||
|
||||
//class MonitorFieldNode
|
||||
//{
|
||||
//public:
|
||||
// MonitorAlgorithmPtr monitorAlgorithm;
|
||||
// size_t bitOffset; // pv pvCopy
|
||||
//};
|
||||
|
||||
class MonitorQueue :
|
||||
public std::tr1::enable_shared_from_this<MonitorQueue>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(MonitorQueue);
|
||||
virtual ~MonitorQueue(){}
|
||||
virtual Status start() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual bool dataChanged() = 0;
|
||||
virtual MonitorElementPtr poll() = 0;
|
||||
virtual void release(MonitorElementPtr const &monitorElement) = 0;
|
||||
protected:
|
||||
MonitorQueuePtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
};
|
||||
|
||||
class NOQueue :
|
||||
public MonitorQueue
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(NOQueue);
|
||||
virtual ~NOQueue(){}
|
||||
NOQueue(
|
||||
MonitorLocalPtr const &monitorLocal);
|
||||
|
||||
virtual Status start();
|
||||
virtual void stop();
|
||||
virtual bool dataChanged();
|
||||
virtual MonitorElementPtr poll();
|
||||
virtual void release(MonitorElementPtr const &monitorElement);
|
||||
private:
|
||||
MonitorLocalPtr monitorLocal;
|
||||
PVStructurePtr pvCopyStructure;
|
||||
MonitorElementPtr monitorElement;
|
||||
bool gotMonitor;
|
||||
bool wasReleased;
|
||||
BitSetPtr changedBitSet;
|
||||
BitSetPtr overrunBitSet;
|
||||
Mutex mutex;
|
||||
};
|
||||
|
||||
class RealQueue :
|
||||
public MonitorQueue
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(RealQueue);
|
||||
virtual ~RealQueue(){}
|
||||
RealQueue(
|
||||
MonitorLocalPtr const &monitorLocal,
|
||||
std::vector<MonitorElementPtr> &monitorElementArray);
|
||||
virtual Status start();
|
||||
virtual void stop();
|
||||
virtual bool dataChanged();
|
||||
virtual MonitorElementPtr poll();
|
||||
virtual void release(MonitorElementPtr const &monitorElement);
|
||||
private:
|
||||
MonitorLocalPtr monitorLocal;
|
||||
Queue<MonitorElement> queue;
|
||||
bool queueIsFull;
|
||||
MonitorElementPtr monitorElement;
|
||||
Mutex mutex;
|
||||
};
|
||||
|
||||
|
||||
class MonitorLocal :
|
||||
public Monitor,
|
||||
public PVCopyMonitorRequester,
|
||||
public std::tr1::enable_shared_from_this<MonitorLocal>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(MonitorLocal);
|
||||
virtual ~MonitorLocal();
|
||||
virtual Status start();
|
||||
virtual Status stop();
|
||||
virtual MonitorElementPtr poll();
|
||||
virtual void destroy();
|
||||
virtual void dataChanged();
|
||||
virtual void unlisten();
|
||||
virtual void release(MonitorElementPtr const & monitorElement);
|
||||
bool init(PVStructurePtr const & pvRequest);
|
||||
MonitorLocal(
|
||||
ChannelProviderLocalPtr const &channelProvider,
|
||||
MonitorRequester::shared_pointer const & channelMonitorRequester,
|
||||
PVRecordPtr const &pvRecord);
|
||||
PVCopyPtr getPVCopy() { return pvCopy;}
|
||||
PVCopyMonitorPtr getPVCopyMonitor() { return pvCopyMonitor;}
|
||||
private:
|
||||
MonitorLocalPtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
PVRecordPtr pvRecord;
|
||||
MonitorRequester::shared_pointer monitorRequester;
|
||||
bool isDestroyed;
|
||||
bool firstMonitor;
|
||||
PVCopyPtr pvCopy;
|
||||
MonitorQueuePtr queue;
|
||||
PVCopyMonitorPtr pvCopyMonitor;
|
||||
// std::list<MonitorFieldNodePtr> monitorFieldList;
|
||||
Mutex mutex;
|
||||
};
|
||||
|
||||
MonitorLocal::MonitorLocal(
|
||||
ChannelProviderLocalPtr const &channelProvider,
|
||||
MonitorRequester::shared_pointer const & channelMonitorRequester,
|
||||
PVRecordPtr const &pvRecord)
|
||||
: pvRecord(pvRecord),
|
||||
monitorRequester(channelMonitorRequester),
|
||||
isDestroyed(false),
|
||||
firstMonitor(true)
|
||||
{
|
||||
}
|
||||
|
||||
MonitorLocal::~MonitorLocal()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void MonitorLocal::destroy()
|
||||
{
|
||||
//std::cout << "MonitorLocal::destroy " << isDestroyed << std::endl;
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(isDestroyed) return;
|
||||
isDestroyed = true;
|
||||
}
|
||||
stop();
|
||||
// monitorFieldList.clear();
|
||||
pvCopyMonitor.reset();
|
||||
queue.reset();
|
||||
pvCopy.reset();
|
||||
monitorRequester.reset();
|
||||
pvRecord.reset();
|
||||
}
|
||||
|
||||
Status MonitorLocal::start()
|
||||
{
|
||||
//std::cout << "MonitorLocal::start" << std::endl;
|
||||
firstMonitor = true;
|
||||
return queue->start();
|
||||
}
|
||||
|
||||
Status MonitorLocal::stop()
|
||||
{
|
||||
//std::cout << "MonitorLocal::stop" << std::endl;
|
||||
pvCopyMonitor->stopMonitoring();
|
||||
queue->stop();
|
||||
return Status::Ok;
|
||||
}
|
||||
|
||||
MonitorElementPtr MonitorLocal::poll()
|
||||
{
|
||||
//std::cout << "MonitorLocal::poll" << std::endl;
|
||||
return queue->poll();
|
||||
}
|
||||
|
||||
void MonitorLocal::dataChanged()
|
||||
{
|
||||
//std::cout << "MonitorLocal::dataChanged" << std::endl;
|
||||
if(firstMonitor) {
|
||||
queue->dataChanged();
|
||||
firstMonitor = false;
|
||||
monitorRequester->monitorEvent(getPtrSelf());
|
||||
return;
|
||||
}
|
||||
if(queue->dataChanged()) {
|
||||
monitorRequester->monitorEvent(getPtrSelf());
|
||||
}
|
||||
}
|
||||
|
||||
void MonitorLocal::unlisten()
|
||||
{
|
||||
//std::cout << "MonitorLocal::unlisten" << std::endl;
|
||||
monitorRequester->unlisten(getPtrSelf());
|
||||
}
|
||||
|
||||
void MonitorLocal::release(MonitorElementPtr const & monitorElement)
|
||||
{
|
||||
//std::cout << "MonitorLocal::release" << std::endl;
|
||||
queue->release(monitorElement);
|
||||
}
|
||||
|
||||
bool MonitorLocal::init(PVStructurePtr const & pvRequest)
|
||||
{
|
||||
PVFieldPtr pvField;
|
||||
PVStructurePtr pvOptions;
|
||||
size_t queueSize = 2;
|
||||
pvField = pvRequest->getSubField("record._options");
|
||||
if(pvField.get()!=NULL) {
|
||||
pvOptions = static_pointer_cast<PVStructure>(pvField);
|
||||
pvField = pvOptions->getSubField("queueSize");
|
||||
if(pvField.get()!=NULL) {
|
||||
PVStringPtr pvString = pvOptions->getStringField("queueSize");
|
||||
if(pvString.get()!=NULL) {
|
||||
int32 size;
|
||||
std::stringstream ss;
|
||||
ss << pvString->get();
|
||||
ss >> size;
|
||||
queueSize = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(queueSize==1) {
|
||||
monitorRequester->message("queueSize can not be 1",errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvField = pvRequest->getSubField("field");
|
||||
if(pvField.get()==NULL) {
|
||||
pvCopy = PVCopy::create(pvRecord,pvRequest,"");
|
||||
if(pvCopy.get()==NULL) {
|
||||
monitorRequester->message("illegal pvRequest",errorMessage);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(pvField->getField()->getType()!=structure) {
|
||||
monitorRequester->message("illegal pvRequest",errorMessage);
|
||||
return false;
|
||||
}
|
||||
pvCopy = PVCopy::create(pvRecord,pvRequest,"field");
|
||||
if(pvCopy.get()==NULL) {
|
||||
monitorRequester->message("illegal pvRequest",errorMessage);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
pvCopyMonitor = pvCopy->createPVCopyMonitor(getPtrSelf());
|
||||
// MARTY MUST IMPLEMENT periodic
|
||||
if(queueSize==0) {
|
||||
queue = NOQueuePtr(new NOQueue(getPtrSelf()));
|
||||
} else {
|
||||
std::vector<MonitorElementPtr> monitorElementArray;
|
||||
monitorElementArray.reserve(queueSize);
|
||||
for(size_t i=0; i<queueSize; i++) {
|
||||
PVStructurePtr pvStructure = pvCopy->createPVStructure();
|
||||
MonitorElementPtr monitorElement(
|
||||
new MonitorElement(pvStructure));
|
||||
monitorElementArray.push_back(monitorElement);
|
||||
}
|
||||
queue = RealQueuePtr(new RealQueue(getPtrSelf(),monitorElementArray));
|
||||
}
|
||||
// MARTY MUST IMPLEMENT algorithm
|
||||
monitorRequester->monitorConnect(
|
||||
Status::Ok,
|
||||
getPtrSelf(),
|
||||
pvCopy->getStructure());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
MonitorFactory::MonitorFactory()
|
||||
: isDestroyed(false)
|
||||
{
|
||||
}
|
||||
|
||||
MonitorFactory::~MonitorFactory()
|
||||
{
|
||||
}
|
||||
|
||||
void MonitorFactory::destroy()
|
||||
{
|
||||
//std::cout << "MonitorFactory::destroy " << isDestroyed << std::endl;
|
||||
Lock lock(mutex);
|
||||
if(isDestroyed) return;
|
||||
isDestroyed = true;
|
||||
while(true) {
|
||||
std::set<MonitorLocalPtr>::iterator it;
|
||||
it = monitorLocalList.begin();
|
||||
if(it==monitorLocalList.end()) break;
|
||||
monitorLocalList.erase(it);
|
||||
lock.unlock();
|
||||
it->get()->destroy();
|
||||
lock.lock();
|
||||
}
|
||||
}
|
||||
|
||||
MonitorPtr MonitorFactory::createMonitor(
|
||||
PVRecordPtr const & pvRecord,
|
||||
MonitorRequester::shared_pointer const & monitorRequester,
|
||||
PVStructurePtr const & pvRequest)
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(isDestroyed) {
|
||||
monitorRequester->message("MonitorFactory is destroyed",errorMessage);
|
||||
return nullMonitor;
|
||||
}
|
||||
MonitorLocalPtr monitor(new MonitorLocal(
|
||||
getChannelProviderLocal(),monitorRequester,pvRecord));
|
||||
bool result = monitor->init(pvRequest);
|
||||
if(!result) return nullMonitor;
|
||||
monitorLocalList.insert(monitor);
|
||||
return monitor;
|
||||
}
|
||||
|
||||
void MonitorFactory::removeMonitor(MonitorLocal * monitor)
|
||||
{
|
||||
//std::cout << "MonitorFactory::removeMonitor" << std::endl;
|
||||
Lock xx(mutex);
|
||||
if(isDestroyed) return;
|
||||
std::set<MonitorLocalPtr>::iterator iter;
|
||||
for (iter = monitorLocalList.begin(); iter!= monitorLocalList.end(); ++iter) {
|
||||
if(iter->get()==monitor) {
|
||||
monitorLocalList.erase(iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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::set<MonitorAlgorithmCreatePtr>::iterator iter;
|
||||
// for(iter = monitorAlgorithmCreateList.begin();
|
||||
// iter!= monitorAlgorithmCreateList.end();
|
||||
// ++iter)
|
||||
// {
|
||||
// if((*iter)->getAlgorithmName().compare(algorithmName))
|
||||
// return *iter;
|
||||
// }
|
||||
return nullMonitorAlgorithmCreate;
|
||||
}
|
||||
|
||||
NOQueue::NOQueue(
|
||||
MonitorLocalPtr const &monitorLocal)
|
||||
: monitorLocal(monitorLocal),
|
||||
pvCopyStructure(monitorLocal->getPVCopy()->createPVStructure()),
|
||||
monitorElement(new MonitorElement(pvCopyStructure)),
|
||||
gotMonitor(false),
|
||||
wasReleased(false),
|
||||
changedBitSet(new BitSet(pvCopyStructure->getNumberFields())),
|
||||
overrunBitSet(new BitSet(pvCopyStructure->getNumberFields()))
|
||||
{
|
||||
monitorElement->pvStructurePtr = pvCopyStructure;
|
||||
monitorElement->changedBitSet =
|
||||
BitSetPtr(new BitSet(pvCopyStructure->getNumberFields()));
|
||||
monitorElement->overrunBitSet =
|
||||
BitSetPtr(new BitSet(pvCopyStructure->getNumberFields()));
|
||||
}
|
||||
|
||||
Status NOQueue::start()
|
||||
{
|
||||
Lock xx(mutex);
|
||||
gotMonitor = true;
|
||||
wasReleased = true;
|
||||
changedBitSet->clear();
|
||||
overrunBitSet->clear();
|
||||
monitorLocal->getPVCopyMonitor()->startMonitoring(
|
||||
monitorElement->changedBitSet,
|
||||
monitorElement->overrunBitSet);
|
||||
return Status::Ok;
|
||||
}
|
||||
|
||||
void NOQueue::stop()
|
||||
{
|
||||
}
|
||||
|
||||
bool NOQueue::dataChanged()
|
||||
{
|
||||
Lock xx(mutex);
|
||||
(*changedBitSet) |= (*monitorElement->changedBitSet);
|
||||
(*overrunBitSet) |= (*monitorElement->overrunBitSet);
|
||||
gotMonitor = true;
|
||||
return wasReleased ? true : false;
|
||||
}
|
||||
|
||||
MonitorElementPtr NOQueue::poll()
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(!gotMonitor) return NULLMonitorElement;
|
||||
BitSetPtr changed = monitorElement->changedBitSet;
|
||||
BitSetPtr overrun = monitorElement->overrunBitSet;
|
||||
(*changed) |= (*changedBitSet);
|
||||
(*overrun) |= (*overrunBitSet);
|
||||
monitorLocal->getPVCopy()->updateCopyFromBitSet(
|
||||
pvCopyStructure, changed,true);
|
||||
BitSetUtil::compress(changed,pvCopyStructure);
|
||||
BitSetUtil::compress(overrun,pvCopyStructure);
|
||||
changedBitSet->clear();
|
||||
overrunBitSet->clear();
|
||||
return monitorElement;
|
||||
}
|
||||
|
||||
void NOQueue::release(MonitorElementPtr const &monitorElement)
|
||||
{
|
||||
Lock xx(mutex);
|
||||
gotMonitor = false;
|
||||
monitorElement->changedBitSet->clear();
|
||||
monitorElement->overrunBitSet->clear();
|
||||
}
|
||||
|
||||
RealQueue::RealQueue(
|
||||
MonitorLocalPtr const &monitorLocal,
|
||||
std::vector<MonitorElementPtr> &monitorElementArray)
|
||||
: monitorLocal(monitorLocal),
|
||||
queue(monitorElementArray),
|
||||
queueIsFull(false)
|
||||
{
|
||||
}
|
||||
|
||||
Status RealQueue::start()
|
||||
{
|
||||
Lock xx(mutex);
|
||||
queue.clear();
|
||||
monitorElement = queue.getFree();
|
||||
monitorElement->changedBitSet->clear();
|
||||
monitorElement->overrunBitSet->clear();
|
||||
monitorLocal->getPVCopyMonitor()->startMonitoring(
|
||||
monitorElement->changedBitSet,
|
||||
monitorElement->overrunBitSet);
|
||||
return Status::Ok;
|
||||
}
|
||||
|
||||
void RealQueue::stop()
|
||||
{
|
||||
}
|
||||
|
||||
bool RealQueue::dataChanged()
|
||||
{
|
||||
Lock xx(mutex);
|
||||
PVStructurePtr pvStructure = monitorElement->pvStructurePtr;
|
||||
monitorLocal->getPVCopy()->updateCopyFromBitSet(
|
||||
pvStructure,monitorElement->changedBitSet,false);
|
||||
MonitorElementPtr newElement = queue.getFree();
|
||||
if(newElement==NULL) {
|
||||
queueIsFull = true;
|
||||
return true;
|
||||
}
|
||||
BitSetUtil::compress(monitorElement->changedBitSet,pvStructure);
|
||||
BitSetUtil::compress(monitorElement->overrunBitSet,pvStructure);
|
||||
convert->copy(pvStructure,newElement->pvStructurePtr);
|
||||
newElement->changedBitSet->clear();
|
||||
newElement->overrunBitSet->clear();
|
||||
monitorLocal->getPVCopyMonitor()->switchBitSets(
|
||||
newElement->changedBitSet,newElement->overrunBitSet,false);
|
||||
queue.setUsed(monitorElement);
|
||||
monitorElement = newElement;
|
||||
return true;
|
||||
}
|
||||
|
||||
MonitorElementPtr RealQueue::poll()
|
||||
{
|
||||
Lock xx(mutex);
|
||||
return queue.getUsed();
|
||||
}
|
||||
|
||||
void RealQueue::release(MonitorElementPtr const ¤tElement)
|
||||
{
|
||||
Lock xx(mutex);
|
||||
queue.releaseUsed(currentElement);
|
||||
currentElement->changedBitSet->clear();
|
||||
currentElement->overrunBitSet->clear();
|
||||
if(!queueIsFull) return;
|
||||
queueIsFull = false;
|
||||
PVStructurePtr pvStructure = monitorElement->pvStructurePtr;
|
||||
MonitorElementPtr newElement = queue.getFree();
|
||||
BitSetUtil::compress(monitorElement->changedBitSet,pvStructure);
|
||||
BitSetUtil::compress(monitorElement->overrunBitSet,pvStructure);
|
||||
convert->copy(pvStructure,newElement->pvStructurePtr);
|
||||
newElement->changedBitSet->clear();
|
||||
newElement->overrunBitSet->clear();
|
||||
monitorLocal->getPVCopyMonitor()->switchBitSets(
|
||||
newElement->changedBitSet,newElement->overrunBitSet,false);
|
||||
queue.setUsed(monitorElement);
|
||||
monitorElement = newElement;
|
||||
|
||||
}
|
||||
|
||||
MonitorFactoryPtr getMonitorFactory()
|
||||
{
|
||||
static MonitorFactoryPtr monitorFactoryPtr;
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
|
||||
if(monitorFactoryPtr.get()==NULL) {
|
||||
monitorFactoryPtr = MonitorFactoryPtr(
|
||||
new MonitorFactory());
|
||||
}
|
||||
return monitorFactoryPtr;
|
||||
}
|
||||
|
||||
}}
|
||||
+189
-22
@@ -5,11 +5,13 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @author Marty Kraimer
|
||||
* @date 2013.04
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include <pv/pvCopy.h>
|
||||
|
||||
@@ -23,8 +25,8 @@ static PVCopyPtr NULLPVCopy;
|
||||
static FieldConstPtr NULLField;
|
||||
static StructureConstPtr NULLStructure;
|
||||
static PVStructurePtr NULLPVStructure;
|
||||
static CopyNodePtr NULLCopyNodePtr;
|
||||
static CopyRecordNodePtr NULLCopyRecordNodePtr;
|
||||
static CopyNodePtr NULLCopyNode;
|
||||
static CopyRecordNodePtr NULLCopyRecordNode;
|
||||
|
||||
struct CopyNode {
|
||||
CopyNode()
|
||||
@@ -48,10 +50,6 @@ typedef std::vector<CopyNodePtr> CopyNodePtrArray;
|
||||
typedef std::tr1::shared_ptr<CopyNodePtrArray> CopyNodePtrArrayPtr;
|
||||
|
||||
struct CopyStructureNode : public CopyNode {
|
||||
// CopyStructureNode(size_t numNodes)
|
||||
// : nodes(CopyNodePtrArrayPtr(new CopyNodePtrArray(numNodes)))
|
||||
// {
|
||||
// }
|
||||
CopyNodePtrArrayPtr nodes;
|
||||
};
|
||||
|
||||
@@ -92,7 +90,11 @@ StructureConstPtr PVCopy::getStructure()
|
||||
|
||||
PVStructurePtr PVCopy::createPVStructure()
|
||||
{
|
||||
if(cacheInitStructure.get()!=NULL) return cacheInitStructure;
|
||||
if(cacheInitStructure.get()!=NULL) {
|
||||
PVStructurePtr save = cacheInitStructure;
|
||||
cacheInitStructure.reset();
|
||||
return save;
|
||||
}
|
||||
PVStructurePtr pvStructure =
|
||||
getPVDataCreate()->createPVStructure(structure);
|
||||
return pvStructure;
|
||||
@@ -279,12 +281,51 @@ void PVCopy::updateRecord(
|
||||
PVCopyMonitorPtr PVCopy::createPVCopyMonitor(
|
||||
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester)
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
PVCopyMonitorPtr pvCopyMonitor( new PVCopyMonitor(
|
||||
pvRecord,headNode,getPtrSelf(),pvCopyMonitorRequester));
|
||||
return pvCopyMonitor;
|
||||
}
|
||||
|
||||
epics::pvData::String PVCopy::dump()
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
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)
|
||||
@@ -589,7 +630,7 @@ CopyNodePtr PVCopy::createStructureNodes(
|
||||
nameFromRecord = getFullName(pvFromRequest,nameFromRecord);
|
||||
PVFieldPtr pvField = pvRecordStructure->
|
||||
getPVStructure()->getSubField(nameFromRecord);
|
||||
if(pvField.get()==NULL) return NULLCopyNodePtr;
|
||||
if(pvField.get()==NULL) return NULLCopyNode;
|
||||
PVRecordFieldPtr pvRecordField = pvRecordStructure->
|
||||
getPVRecord()->findPVRecordField(pvField);
|
||||
size_t structureOffset = pvFromField->getFieldOffset();
|
||||
@@ -650,7 +691,7 @@ CopyNodePtr PVCopy::createStructureNodes(
|
||||
++indFromStructure;
|
||||
}
|
||||
size_t len = nodes->size();
|
||||
if(len==String::npos) return NULLCopyNodePtr;
|
||||
if(len==String::npos) return NULLCopyNode;
|
||||
CopyStructureNodePtr structureNode(new CopyStructureNode());
|
||||
structureNode->isStructure = true;
|
||||
structureNode->nodes = nodes;
|
||||
@@ -915,7 +956,7 @@ CopyRecordNodePtr PVCopy::getCopyOffset(
|
||||
if(recordNode.get()!=NULL) return recordNode;
|
||||
}
|
||||
}
|
||||
return NULLCopyRecordNodePtr;
|
||||
return NULLCopyRecordNode;
|
||||
}
|
||||
|
||||
CopyRecordNodePtr PVCopy::getRecordNode(
|
||||
@@ -935,37 +976,163 @@ CopyRecordNodePtr PVCopy::getRecordNode(
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
return getRecordNode(subNode,structureOffset);
|
||||
}
|
||||
return NULLCopyRecordNodePtr;
|
||||
return NULLCopyRecordNode;
|
||||
}
|
||||
|
||||
|
||||
PVCopyMonitor::PVCopyMonitor()
|
||||
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)
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
}
|
||||
|
||||
PVCopyMonitor::~PVCopyMonitor()
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
pvRecord.reset();
|
||||
headNode.reset();
|
||||
pvCopy.reset();
|
||||
pvCopyMonitorRequester.reset();
|
||||
changeBitSet.reset();
|
||||
overrunBitSet.reset();
|
||||
}
|
||||
|
||||
void PVCopyMonitor::startMonitoring(
|
||||
BitSetPtr const &changeBitSet,
|
||||
BitSetPtr const &overrunBitSet)
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
this->changeBitSet = changeBitSet;
|
||||
this->overrunBitSet = overrunBitSet;
|
||||
isGroupPut = false;
|
||||
pvRecord->addListener(getPtrSelf());
|
||||
addListener(headNode);
|
||||
pvRecord->lock();
|
||||
try {
|
||||
changeBitSet->clear();
|
||||
overrunBitSet->clear();
|
||||
changeBitSet->set(0);
|
||||
pvCopyMonitorRequester->dataChanged();
|
||||
pvRecord->unlock();
|
||||
} catch(...) {
|
||||
pvRecord->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopyMonitor::stopMonitoring()
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
pvRecord->removeListener(getPtrSelf());
|
||||
}
|
||||
|
||||
void PVCopyMonitor::switchBitSets(
|
||||
BitSetPtr const &newChangeBitSet,
|
||||
BitSetPtr const &newOverrunBitSet, bool lockRecord)
|
||||
BitSetPtr const &newOverrunBitSet,
|
||||
bool lockRecord)
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
if(lockRecord) pvRecord->lock();
|
||||
try {
|
||||
changeBitSet = newChangeBitSet;
|
||||
overrunBitSet = newOverrunBitSet;
|
||||
if(lockRecord) pvRecord->unlock();
|
||||
} catch(...) {
|
||||
if(lockRecord) pvRecord->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopyMonitor::detach(PVRecordPtr const & pvRecord)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
+36
-12
@@ -5,8 +5,8 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2013.03.25
|
||||
* @author Marty Kraimer
|
||||
* @date 2013.04
|
||||
*/
|
||||
#ifndef PVCOPY_H
|
||||
#define PVCOPY_H
|
||||
@@ -81,6 +81,10 @@ public:
|
||||
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();
|
||||
@@ -92,6 +96,7 @@ private:
|
||||
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,
|
||||
@@ -154,7 +159,8 @@ private:
|
||||
|
||||
};
|
||||
|
||||
class PVCopyMonitor :
|
||||
class PVCopyMonitor :
|
||||
public PVListener,
|
||||
public std::tr1::enable_shared_from_this<PVCopyMonitor>
|
||||
{
|
||||
public:
|
||||
@@ -167,28 +173,46 @@ public:
|
||||
void switchBitSets(
|
||||
epics::pvData::BitSetPtr const &newChangeBitSet,
|
||||
epics::pvData::BitSetPtr const &newOverrunBitSet, bool lockRecord);
|
||||
// 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();
|
||||
PVCopyMonitor(
|
||||
PVRecordPtr const &pvRecord,
|
||||
CopyNodePtr const &headNode,
|
||||
PVCopyPtr const &pvCopy,
|
||||
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester);
|
||||
friend class PVCopy;
|
||||
// TBD
|
||||
PVRecordPtr pvRecord;
|
||||
CopyNodePtr headNode;
|
||||
PVCopyPtr pvCopy;
|
||||
PVCopyMonitorRequesterPtr pvCopyMonitorRequester;
|
||||
epics::pvData::BitSetPtr changeBitSet;
|
||||
epics::pvData::BitSetPtr overrunBitSet;
|
||||
bool isGroupPut;
|
||||
bool dataChanged;
|
||||
};
|
||||
|
||||
class PVCopyMonitorRequester :
|
||||
public std::tr1::enable_shared_from_this<PVCopyMonitorRequester>
|
||||
class PVCopyMonitorRequester
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVCopyMonitorRequester);
|
||||
virtual void dataChanged() = 0;
|
||||
virtual void unlisten() = 0;
|
||||
private:
|
||||
PVCopyMonitorRequesterPtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @author Marty Kraimer
|
||||
* @date 2013.04
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
@@ -18,7 +19,7 @@
|
||||
#include <pv/support.h>
|
||||
#include <pv/pvCopy.h>
|
||||
|
||||
namespace epics { namespace pvIOC {
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @author Marty Kraimer
|
||||
* @date 2013.04
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
@@ -18,7 +19,7 @@
|
||||
#include <pv/support.h>
|
||||
#include <pv/pvCopy.h>
|
||||
|
||||
namespace epics { namespace pvIOC {
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user