monitors now implemented

This commit is contained in:
Marty Kraimer
2013-05-16 09:32:32 -04:00
parent 26c977c0ae
commit ec7601392d
18 changed files with 1860 additions and 140 deletions
+3
View File
@@ -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
+1
View File
@@ -11,6 +11,7 @@
#ifndef EXAMPLECOUNTER_H
#define EXAMPLECOUNTER_H
#include <pv/pvDatabase.h>
#include <pv/standardPVField.h>
#include <pv/timeStamp.h>
+6 -2
View File
@@ -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)
{
+8
View File
@@ -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
View File
@@ -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();
}
}
+56 -50
View File
@@ -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(
+12 -5
View File
@@ -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()
+39 -4
View File
@@ -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;
+42 -22
View File
@@ -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 */
+541
View File
@@ -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 &currentElement)
{
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
View File
@@ -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
View File
@@ -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 &copyPVStructure,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();
}
};
+3 -2
View File
@@ -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;
+3 -2
View File
@@ -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;