interim commit. pvCopy how works

This commit is contained in:
Marty Kraimer
2013-04-04 07:21:52 -04:00
parent d96ccf3776
commit 500ecfd4ad
23 changed files with 2551 additions and 898 deletions

View File

@@ -9,15 +9,12 @@ pvDatabase_LIBS += Com pvData pvAccess
SRC_DIRS += $(DATABASE)/database
INC += pvDatabase.h
#INC += pvCopy.h
#INC += monitor.h
#LIBSRCS += pvDatabase.cpp
INC += powerSupplyRecordTest.h
LIBSRCS += pvRecord.cpp
#LIBSRCS += recordProcess.cpp
#LIBSRCS += pvCopy.cpp
#LIBSRCS += monitor.cpp
#SRC_DIRS += $(SRC)/pvAccess
SRC_DIRS += $(DATABASE)/pvAccess
INC += pvCopy.h
LIBSRCS += pvCopy.cpp
include $(TOP)/configure/RULES

View File

@@ -0,0 +1,188 @@
/* powerSupplyRecordTest.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 2013.04.02
*/
#ifndef POWERSUPPLYRECORDTEST_H
#define POWERSUPPLYRECORDTEST_H
#include <pv/executor.h>
#include <pv/pvDatabase.h>
#include <pv/event.h>
#include <pv/timer.h>
#include <pv/timeStamp.h>
#include <pv/alarm.h>
#include <pv/pvTimeStamp.h>
#include <pv/pvAlarm.h>
namespace epics { namespace pvDatabase {
class PowerSupplyRecordTest;
typedef std::tr1::shared_ptr<PowerSupplyRecordTest> PowerSupplyRecordTestPtr;
class PowerSupplyRecordTest :
public PVRecord
{
public:
POINTER_DEFINITIONS(PowerSupplyRecordTest);
static PowerSupplyRecordTestPtr create(
epics::pvData::String const & recordName,
epics::pvData::PVStructurePtr const & pvStructure);
virtual ~PowerSupplyRecordTest();
virtual bool init();
virtual void process();
void put(double power,double voltage);
double getPower();
double getVoltage();
double getCurrent();
private:
PowerSupplyRecordTest(epics::pvData::String const & recordName,
epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvStructure;
epics::pvData::PVDoublePtr pvCurrent;
epics::pvData::PVDoublePtr pvPower;
epics::pvData::PVDoublePtr pvVoltage;
epics::pvData::PVAlarm pvAlarm;
epics::pvData::PVTimeStamp pvTimeStamp;
epics::pvData::Alarm alarm;
epics::pvData::TimeStamp timeStamp;
};
PowerSupplyRecordTestPtr PowerSupplyRecordTest::create(
epics::pvData::String const & recordName,
epics::pvData::PVStructurePtr const & pvStructure)
{
PowerSupplyRecordTestPtr pvRecord(
new PowerSupplyRecordTest(recordName,pvStructure));
if(!pvRecord->init()) pvRecord.reset();
return pvRecord;
}
PowerSupplyRecordTest::PowerSupplyRecordTest(
epics::pvData::String const & recordName,
epics::pvData::PVStructurePtr const & pvStructure)
: PVRecord(recordName,pvStructure),
pvStructure(pvStructure)
{
}
PowerSupplyRecordTest::~PowerSupplyRecordTest()
{
destroy();
}
bool PowerSupplyRecordTest::init()
{
initPVRecord();
epics::pvData::PVFieldPtr pvField;
bool result;
pvField = pvStructure->getSubField("timeStamp");
if(pvField.get()==NULL) {
std::cerr << "no timeStamp" << std::endl;
return false;
}
result = pvTimeStamp.attach(pvField);
if(!result) {
std::cerr << "no timeStamp" << std::endl;
return false;
}
pvField = pvStructure->getSubField("alarm");
if(pvField.get()==NULL) {
std::cerr << "no alarm" << std::endl;
return false;
}
result = pvAlarm.attach(pvField);
if(!result) {
std::cerr << "no alarm" << std::endl;
return false;
}
epics::pvData::String name;
name = "current.value";
pvField = pvStructure->getSubField(name);
if(pvField.get()==NULL) {
name = "current";
pvField = pvStructure->getSubField(name);
}
if(pvField.get()==NULL) {
std::cerr << "no current" << std::endl;
return false;
}
pvCurrent = pvStructure->getDoubleField(name);
if(pvCurrent.get()==NULL) return false;
name = "voltage.value";
pvField = pvStructure->getSubField(name);
if(pvField.get()==NULL) {
name = "voltage";
pvField = pvStructure->getSubField(name);
}
if(pvField.get()==NULL) {
std::cerr << "no voltage" << std::endl;
return false;
}
pvVoltage = pvStructure->getDoubleField(name);
if(pvVoltage.get()==NULL) return false;
name = "power.value";
pvField = pvStructure->getSubField(name);
if(pvField.get()==NULL) {
name = "power";
pvField = pvStructure->getSubField(name);
}
if(pvField.get()==NULL) {
std::cerr << "no power" << std::endl;
return false;
}
pvPower = pvStructure->getDoubleField(name);
if(pvPower.get()==NULL) return false;
return true;
}
void PowerSupplyRecordTest::process()
{
timeStamp.getCurrent();
pvTimeStamp.set(timeStamp);
double voltage = pvVoltage->get();
double power = pvPower->get();
if(voltage<1e-3 && voltage>-1e-3) {
alarm.setMessage("bad voltage");
alarm.setSeverity(epics::pvData::majorAlarm);
pvAlarm.set(alarm);
return;
}
double current = power/voltage;
pvCurrent->put(current);
alarm.setMessage("");
alarm.setSeverity(epics::pvData::noAlarm);
pvAlarm.set(alarm);
}
void PowerSupplyRecordTest::put(double power,double voltage)
{
pvPower->put(power);
pvVoltage->put(voltage);
}
double PowerSupplyRecordTest::getPower()
{
return pvPower->get();
}
double PowerSupplyRecordTest::getVoltage()
{
return pvVoltage->get();
}
double PowerSupplyRecordTest::getCurrent()
{
return pvCurrent->get();
}
}}
#endif /* POWERSUPPLYRECORDTEST_H */

View File

@@ -6,7 +6,7 @@
*/
/**
* @author mrk
* @data 2012.11.20
* @date 2012.11.20
*/
#ifndef PVDATABASE_H
#define PVDATABASE_H
@@ -36,33 +36,22 @@ typedef std::tr1::shared_ptr<PVRecordClient> PVRecordClientPtr;
class PVListener;
typedef std::tr1::shared_ptr<PVListener> PVListenerPtr;
class RecordProcessRequester;
typedef std::tr1::shared_ptr<RecordProcessRequester> RecordProcessRequesterPtr;
class RecordPutRequester;
typedef std::tr1::shared_ptr<RecordPutRequester> RecordPutRequesterPtr;
class PVDatabase;
typedef std::tr1::shared_ptr<PVDatabase> PVDatabasePtr;
class PVRecord :
public epics::pvData::Requester,
public std::tr1::enable_shared_from_this<PVRecord>
{
public:
POINTER_DEFINITIONS(PVRecord);
static PVRecordPtr create(
epics::pvData::String const & recordName,
epics::pvData::PVStructurePtr const & pvStructure);
PVRecord(
epics::pvData::String const & recordName,
epics::pvData::PVStructurePtr const & pvStructure);
virtual ~PVRecord();
virtual void process(
RecordProcessRequesterPtr const &recordProcessRequester,
bool alreadyLocked) = 0;
virtual bool isSynchronous() = 0;
virtual bool requestImmediatePut(
epics::pvData::PVFieldPtr const &pvField);
virtual void immediatePutDone();
virtual void destroy();
epics::pvData::String getRecordName();
PVRecordStructurePtr getPVRecordStructure();
@@ -70,6 +59,7 @@ public:
epics::pvData::PVFieldPtr const & pvField);
bool addRequester(epics::pvData::RequesterPtr const & requester);
bool removeRequester(epics::pvData::RequesterPtr const & requester);
inline void lock_guard() { epics::pvData::Lock theLock(mutex); }
void lock();
void unlock();
bool tryLock();
@@ -81,15 +71,7 @@ public:
bool removeListener(PVListenerPtr const & pvListener);
void beginGroupPut();
void endGroupPut();
void queueProcessRequest(
RecordProcessRequesterPtr const &recordProcessRequester);
void dequeueProcessRequest(
RecordProcessRequesterPtr const &recordProcessRequester);
void queuePutRequest(
RecordPutRequesterPtr const &recordPutRequester);
void putDone(
RecordPutRequesterPtr const &recordPutRequester);
virtual epics::pvData::String getRequesterName() {return getRecordName();}
epics::pvData::String getRequesterName() {return getRecordName();}
virtual void message(
epics::pvData::String const & message,
epics::pvData::MessageType messageType);
@@ -99,9 +81,11 @@ public:
epics::pvData::MessageType messageType);
void toString(epics::pvData::StringBuilder buf);
void toString(epics::pvData::StringBuilder buf,int indentLevel);
//init MUST be called after derived class is constructed
void init();
//init MUST be called by derived class after derived class is constructed
virtual bool init() {initPVRecord(); return true;}
virtual void process() {}
protected:
void initPVRecord();
PVRecordPtr getPtrSelf()
{
return shared_from_this();
@@ -114,16 +98,12 @@ private:
epics::pvData::PVStructurePtr pvStructure;
epics::pvData::ConvertPtr convert;
PVRecordStructurePtr pvRecordStructure;
std::deque<RecordProcessRequesterPtr> processRequesterQueue;
std::deque<RecordPutRequesterPtr> putRequesterQueue;
std::list<PVListenerPtr> pvListenerList;
std::list<PVRecordClientPtr> pvRecordClientList;
std::list<epics::pvData::RequesterPtr> requesterList;
epics::pvData::Mutex mutex;
epics::pvData::Lock thelock;
int depthGroupPut;
bool processActive;
bool putActive;
std::size_t depthGroupPut;
bool isDestroyed;
};
@@ -209,27 +189,6 @@ public:
virtual void endGroupPut(PVRecordPtr const & pvRecord) = 0;
};
class RecordProcessRequester :
virtual public PVRecordClient,
virtual public epics::pvData::Requester
{
public:
POINTER_DEFINITIONS(RecordProcessRequester);
virtual ~RecordProcessRequester() {}
virtual void recordDestroyed() = 0;
virtual void becomeProcessor() = 0;
virtual void recordProcessResult(epics::pvData::Status status) = 0;
virtual void recordProcessComplete() = 0;
};
class RecordPutRequester
{
public:
POINTER_DEFINITIONS(RecordPutRequester);
virtual ~RecordPutRequester() {}
virtual void requestResult(bool result) = 0;
};
class PVDatabase : virtual public epics::pvData::Requester {
public:
POINTER_DEFINITIONS(PVDatabase);

View File

@@ -17,6 +17,19 @@ using namespace epics::pvAccess;
namespace epics { namespace pvDatabase {
PVRecordPtr PVRecord::create(
String const &recordName,
PVStructurePtr const & pvStructure)
{
PVRecordPtr pvRecord(new PVRecord(recordName,pvStructure));
if(!pvRecord->init()) {
pvRecord->destroy();
pvRecord.reset();
}
return pvRecord;
}
PVRecord::PVRecord(
String const & recordName,
PVStructurePtr const & pvStructure)
@@ -25,14 +38,17 @@ PVRecord::PVRecord(
convert(getConvert()),
thelock(mutex),
depthGroupPut(0),
processActive(false),
putActive(false),
isDestroyed(false)
{
thelock.unlock();
}
void PVRecord::init()
PVRecord::~PVRecord()
{
destroy();
}
void PVRecord::initPVRecord()
{
PVRecordStructurePtr parent;
pvRecordStructure = PVRecordStructurePtr(
@@ -41,18 +57,13 @@ void PVRecord::init()
pvStructure->setRequester(getPtrSelf());
}
PVRecord::~PVRecord() {}
bool PVRecord::requestImmediatePut(PVFieldPtr const &pvField)
{
return false;
}
void PVRecord::immediatePutDone() {}
void PVRecord::destroy()
{
lock();
if(isDestroyed) {
unlock();
return;
}
isDestroyed = true;
std::list<RequesterPtr>::iterator requesterIter;
@@ -74,28 +85,6 @@ void PVRecord::destroy()
pvRecordClientList.clear();
pvListenerList.clear();
std::deque<RecordProcessRequesterPtr>::iterator processRequesterIter;
for (
processRequesterIter = processRequesterQueue.begin();
processRequesterIter != processRequesterQueue.end();
processRequesterIter++ )
{
(*processRequesterIter)->recordDestroyed();
}
processRequesterQueue.clear();
std::deque<RecordPutRequesterPtr>::iterator putRequesterIter;
for (
putRequesterIter = putRequesterQueue.begin();
putRequesterIter != putRequesterQueue.end();
putRequesterIter++ )
{
(*putRequesterIter)->requestResult(false);
}
putRequesterQueue.clear();
unlock();
}
@@ -308,100 +297,6 @@ void PVRecord::endGroupPut()
}
}
void PVRecord::queueProcessRequest(
RecordProcessRequesterPtr const &recordProcessRequester)
{
lock();
if(isDestroyed) {
unlock();
recordProcessRequester->recordDestroyed();
return;
}
bool isFirst = false;
processRequesterQueue.push_back(recordProcessRequester);
if(processRequesterQueue.size()==1 && !putActive) isFirst = true;
unlock();
if(isFirst) recordProcessRequester->becomeProcessor();
}
void PVRecord::dequeueProcessRequest(
RecordProcessRequesterPtr const &recordProcessRequester)
{
lock();
if(isDestroyed) {
unlock();
recordProcessRequester->recordDestroyed();
return;
}
RecordProcessRequesterPtr next;
RecordProcessRequesterPtr processRequester =
processRequesterQueue[0];
if(processRequester.get()!=recordProcessRequester.get()) {
message(
"PVRecord::dequeueProcessRequest illegal requester",
errorMessage);
return;
}
processRequesterQueue.pop_front();
if(putRequesterQueue.size() > 0) {
RecordPutRequesterPtr putRequester = putRequesterQueue[0];
processActive = false;
putActive = true;
putRequester->requestResult(true);
return; // WITH LOCK HELD
}
if(processRequesterQueue.size()>0) next = processRequesterQueue[0];
if(next.get()!=NULL) processActive = true;
unlock();
if(next.get()!=NULL) next->becomeProcessor();
}
void PVRecord::queuePutRequest(
RecordPutRequesterPtr const &recordPutRequester)
{
lock();
if(isDestroyed) {
unlock();
recordPutRequester->requestResult(false);
return;
}
if(processRequesterQueue.size()==0 && !processActive) {
putRequesterQueue.push_back(recordPutRequester);
putActive = true;
recordPutRequester->requestResult(true);
return; // WITH lock held
}
putRequesterQueue.push_back(recordPutRequester);
unlock();
}
void PVRecord::putDone(
RecordPutRequesterPtr const &recordPutRequester)
{
// Note that this is called with lock held
RecordPutRequesterPtr putRequester =
putRequesterQueue[0];
if(putRequester.get()!=recordPutRequester.get()) {
message(
"PVRecord::putDone illegal requester",
errorMessage);
return;
}
putRequesterQueue.pop_front();
if(putRequesterQueue.size()>0){
RecordPutRequesterPtr next = putRequesterQueue[0];
next->requestResult(true);
return; // WITH lock held
}
putActive = false;
RecordProcessRequesterPtr next = processRequesterQueue[0];
if(next.get()!=NULL) processActive = true;
unlock();
if(next.get()!=NULL) next->becomeProcessor();
}
void PVRecord::message(String const & message,MessageType messageType)
{
if(isDestroyed) return;

View File

@@ -0,0 +1,38 @@
/* 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.
*/
/* Marty Kraimer 2011.03 */
#ifndef MONITORALGORITHM_H
#define MONITORALGORITHM_H
#include <string>
#include <pv/pvData.h>
namespace epics { namespace pvIOC {
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);
};
extern MonitorAlgorithmCreate& getAlgorithmDeadband();
extern MonitorAlgorithmCreate& getAlgorithmOnChange();
#endif /* MONITORALGORITHM_H */

973
src/pvAccess/pvCopy.cpp Normal file
View File

@@ -0,0 +1,973 @@
/* pvCopy.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
*/
#include <string>
#include <stdexcept>
#include <memory>
#include <pv/pvCopy.h>
namespace epics { namespace pvDatabase {
using namespace epics::pvData;
using std::tr1::static_pointer_cast;
using std::size_t;
static PVCopyPtr NULLPVCopy;
static FieldConstPtr NULLField;
static StructureConstPtr NULLStructure;
static PVStructurePtr NULLPVStructure;
static CopyNodePtr NULLCopyNodePtr;
static CopyRecordNodePtr NULLCopyRecordNodePtr;
struct CopyNode {
CopyNode()
: isStructure(false),
structureOffset(0),
nfields(0),
shareData(false)
{}
bool isStructure;
size_t structureOffset; // In the copy
size_t nfields;
bool shareData;
PVStructurePtr options;
};
struct CopyRecordNode : public CopyNode{
PVRecordFieldPtr recordPVField;
};
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;
};
PVCopyPtr PVCopy::create(
PVRecordPtr const &pvRecord,
PVStructurePtr const &pvRequest,
String const & structureName)
{
if(structureName.size()>0) {
if(pvRequest->getStructure()->getNumberFields()>0) {
PVStructurePtr pvStructure
= pvRequest->getStructureField(structureName);
if(pvStructure.get()==NULL) return NULLPVCopy;
}
}
PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvRecord));
PVStructurePtr pvStruct = pvRequest;
if(pvRequest->getSubField("field")!=NULL) {
pvStruct = pvRequest->getStructureField("field");
}
bool result = pvCopy->init(pvStruct);
if(!result) pvCopy.reset();
return pvCopy;
}
PVCopy::PVCopy(PVRecordPtr const &pvRecord)
: pvRecord(pvRecord)
{
}
PVRecordPtr PVCopy::getPVRecord()
{
return pvRecord;
}
StructureConstPtr PVCopy::getStructure()
{
return structure;
}
PVStructurePtr PVCopy::createPVStructure()
{
if(cacheInitStructure.get()!=NULL) return cacheInitStructure;
PVStructurePtr pvStructure =
getPVDataCreate()->createPVStructure(structure);
return pvStructure;
}
size_t PVCopy::getCopyOffset(PVRecordFieldPtr const &recordPVField)
{
if(!headNode->isStructure) {
CopyRecordNodePtr recordNode = static_pointer_cast<CopyRecordNode>(headNode);
if((recordNode->recordPVField.get())==recordPVField.get()) {
return headNode->structureOffset;
}
return String::npos;
}
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
CopyRecordNodePtr recordNode = getCopyOffset(node,recordPVField);
if(recordNode.get()!=NULL) return recordNode->structureOffset;
return String::npos;
}
size_t PVCopy::getCopyOffset(
PVRecordStructurePtr const &recordPVStructure,
PVRecordFieldPtr const &recordPVField)
{
CopyRecordNodePtr recordNode;
if(!headNode->isStructure) {
recordNode = static_pointer_cast<CopyRecordNode>(headNode);
if(recordNode->recordPVField.get()!=recordPVStructure.get()) return String::npos;
} else {
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
recordNode = getCopyOffset(node,recordPVField);
}
if(recordNode.get()==NULL) return String::npos;
size_t diff = recordPVField->getPVField()->getFieldOffset()
- recordPVStructure->getPVStructure()->getFieldOffset();
return recordNode->structureOffset + diff;
}
PVRecordFieldPtr PVCopy::getRecordPVField(size_t structureOffset)
{
CopyRecordNodePtr recordNode;
if(!headNode->isStructure) {
recordNode = static_pointer_cast<CopyRecordNode>(headNode);
} else {
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
recordNode = getRecordNode(node,structureOffset);
}
if(recordNode.get()==NULL) {
throw std::invalid_argument(
"PVCopy::getRecordPVField: setstructureOffset not valid");
}
size_t diff = structureOffset - recordNode->structureOffset;
PVRecordFieldPtr pvRecordField = recordNode->recordPVField;
if(diff==0) return pvRecordField;
PVStructurePtr pvStructure
= static_pointer_cast<PVStructure>(pvRecordField->getPVField());
PVFieldPtr pvField = pvStructure->getSubField(
pvRecordField->getPVField()->getFieldOffset() + diff);
return pvRecord->findPVRecordField(pvField);
}
void PVCopy::initCopy(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet,
bool lockRecord)
{
bitSet->clear();
bitSet->set(0);
updateCopyFromBitSet(copyPVStructure,bitSet,lockRecord);
}
void PVCopy::updateCopySetBitSet(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet,
bool lockRecord)
{
if(lockRecord) pvRecord->lock();
try {
if(headNode->isStructure) {
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
updateStructureNodeSetBitSet(copyPVStructure,node,bitSet);
} else {
CopyRecordNodePtr recordNode = static_pointer_cast<CopyRecordNode>(headNode);
PVRecordFieldPtr pvRecordField= recordNode->recordPVField;
PVFieldPtr copyPVField = copyPVStructure;
PVFieldPtrArray const & pvCopyFields = copyPVStructure->getPVFields();
if(pvCopyFields.size()==1) {
copyPVField = pvCopyFields[0];
}
PVFieldPtr pvField = pvRecordField->getPVField();
if(pvField->getField()->getType()==epics::pvData::structure) {
updateSubFieldSetBitSet(copyPVField,pvRecordField,bitSet);
return;
}
if(pvCopyFields.size()!=1) {
throw std::logic_error("Logic error");
}
ConvertPtr convert = getConvert();
bool isEqual = convert->equals(copyPVField,pvField);
if(!isEqual) {
convert->copy(pvField, copyPVField);
bitSet->set(copyPVField->getFieldOffset());
}
}
if(lockRecord) pvRecord->unlock();
} catch(...) {
if(lockRecord) pvRecord->unlock();
throw;
}
}
void PVCopy::updateCopyFromBitSet(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet,
bool lockRecord)
{
bool doAll = bitSet->get(0);
if(lockRecord) pvRecord->lock();
try {
if(headNode->isStructure) {
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
updateStructureNodeFromBitSet(copyPVStructure,node,bitSet,true,doAll);
} else {
CopyRecordNodePtr recordNode = static_pointer_cast<CopyRecordNode>(headNode);
PVFieldPtrArray const & pvCopyFields = copyPVStructure->getPVFields();
if(pvCopyFields.size()==1) {
updateSubFieldFromBitSet(
pvCopyFields[0],
recordNode->recordPVField,bitSet,
true,doAll);
} else {
updateSubFieldFromBitSet(
copyPVStructure,
recordNode->recordPVField,bitSet,
true,doAll);
}
}
if(lockRecord) pvRecord->unlock();
} catch(...) {
if(lockRecord) pvRecord->unlock();
throw;
}
}
void PVCopy::updateRecord(
PVStructurePtr const &copyPVStructure,
BitSetPtr const &bitSet,
bool lockRecord)
{
bool doAll = bitSet->get(0);
if(lockRecord) pvRecord->lock();
try {
pvRecord->beginGroupPut();
if(headNode->isStructure) {
CopyStructureNodePtr node =
static_pointer_cast<CopyStructureNode>(headNode);
updateStructureNodeFromBitSet(
copyPVStructure,node,bitSet,false,doAll);
} else {
CopyRecordNodePtr recordNode =
static_pointer_cast<CopyRecordNode>(headNode);
PVFieldPtrArray const & pvCopyFields =
copyPVStructure->getPVFields();
if(pvCopyFields.size()==1) {
updateSubFieldFromBitSet(
pvCopyFields[0],
recordNode->recordPVField,bitSet,
false,doAll);
} else {
updateSubFieldFromBitSet(
copyPVStructure,
recordNode->recordPVField,bitSet,
false,doAll);
}
}
pvRecord->endGroupPut();
if(lockRecord) pvRecord->unlock();
} catch(...) {
if(lockRecord) pvRecord->unlock();
throw;
}
}
PVCopyMonitorPtr PVCopy::createPVCopyMonitor(
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester)
{
throw std::logic_error(String("Not Implemented"));
}
epics::pvData::String PVCopy::dump()
{
throw std::logic_error(String("Not Implemented"));
}
bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
{
PVRecordStructurePtr pvRecordStructure = pvRecord->getPVRecordStructure();
size_t len = pvRequest->getPVFields().size();
bool entireRecord = false;
if(len==String::npos) entireRecord = true;
PVStructurePtr pvOptions;
if(len==1 && pvRequest->getSubField("_options")!=NULL) {
pvOptions = pvRequest->getStructureField("_options");
}
if(entireRecord) {
structure = pvRecordStructure->getPVStructure()->getStructure();
CopyRecordNodePtr recordNode(new CopyRecordNode());
headNode = recordNode;
recordNode->options = pvOptions;
recordNode->isStructure = false;
recordNode->structureOffset = 0;
recordNode->recordPVField = pvRecordStructure;
return true;
}
structure = createStructure(pvRecordStructure->getPVStructure(),pvRequest);
if(structure==NULL) return false;
cacheInitStructure = createPVStructure();
headNode = createStructureNodes(
pvRecord->getPVRecordStructure(),
pvRequest,
cacheInitStructure);
referenceImmutable(cacheInitStructure,headNode);
return true;
}
epics::pvData::String PVCopy::dump(
String const &value,
CopyNodePtr const &node,
int indentLevel)
{
throw std::logic_error(String("Not Implemented"));
}
String PVCopy::getFullName(
PVStructurePtr const &pvFromRequest,
String const &nameFromRecord)
{
PVFieldPtrArray const & pvFields = pvFromRequest->getPVFields();
String fullName = nameFromRecord;
size_t len = pvFields.size();
if(len==1) {
String name = pvFields[0]->getFieldName();
if(name.compare("_options")==0) return nameFromRecord;
PVStructurePtr pvRequest = static_pointer_cast<PVStructure>(pvFields[0]);
if(fullName.size()!=0) fullName += ".";
fullName += pvRequest->getFieldName();
return getFullName(pvRequest,fullName);
}
if(len==2) {
PVFieldPtr subField;
if((pvFields[0]->getFieldName().compare("_options"))==0) {
subField = pvFields[1];
} else if((pvFields[1]->getFieldName().compare("_options"))==0) {
subField = pvFields[1];
}
if(subField.get()!=NULL) {
PVStructurePtr pvRequest = static_pointer_cast<PVStructure>(subField);
if(fullName.size()!=0) fullName += ".";
fullName += subField->getFieldName();
return getFullName(pvRequest,fullName);
}
}
return nameFromRecord;
}
PVStructurePtr PVCopy::getSubStructure(
PVStructurePtr const &xxx,
String const &yyy)
{
PVStructurePtr pvFromRequest = xxx;
String nameFromRecord = yyy;
PVFieldPtrArray const & pvFields = pvFromRequest->getPVFields();
size_t len = pvFields.size();
if(len==1) {
pvFromRequest = static_pointer_cast<PVStructure>(pvFields[0]);
if(pvFromRequest->getFieldName().compare("_options")==0) {
return pvFromRequest;
}
if(nameFromRecord.size()!=0) nameFromRecord += ".";
nameFromRecord += pvFromRequest->getFieldName();
return getSubStructure(pvFromRequest,nameFromRecord);
}
if(len==2) {
PVFieldPtr subField;
if(pvFields[0]->getFieldName().compare("_options")==0) {
subField = pvFields[1];
} else if(pvFields[1]->getFieldName().compare("_options")==0) {
subField = pvFields[1];
}
if(subField.get()!=NULL) {
if(nameFromRecord.size()!=0) nameFromRecord += ".";
nameFromRecord += subField->getFieldName();
pvFromRequest = static_pointer_cast<PVStructure>(subField);
return getSubStructure(pvFromRequest,nameFromRecord);
}
}
return pvFromRequest;
}
PVStructurePtr PVCopy::getOptions(
PVStructurePtr const &xxx,
String const &yyy)
{
PVStructurePtr pvFromRequest = xxx;
String nameFromRecord = yyy;
PVFieldPtrArray const & pvFields = pvFromRequest->getPVFields();
size_t len = pvFields.size();
if(len==1) {
pvFromRequest = static_pointer_cast<PVStructure>(pvFields[0]);
if(pvFromRequest->getFieldName().compare("_options")==0) {
return pvFromRequest;
}
if(nameFromRecord.size()!=0) nameFromRecord += ".";
nameFromRecord += pvFromRequest->getFieldName();
return getSubStructure(pvFromRequest,nameFromRecord);
}
if(len==2) {
if(pvFields[0]->getFieldName().compare("_options")==0) {
pvFromRequest = static_pointer_cast<PVStructure>(pvFields[0]);
return pvFromRequest;
} else if(pvFields[1]->getFieldName().compare("_options")==0) {
pvFromRequest = static_pointer_cast<PVStructure>(pvFields[1]);
return pvFromRequest;
}
}
return NULLPVStructure;
}
StructureConstPtr PVCopy::createStructure(
PVStructurePtr const &pvRecord,
PVStructurePtr const &pvFromRequest)
{
if(pvFromRequest->getStructure()->getNumberFields()==0) {
return pvRecord->getStructure();
}
FieldConstPtr field = createField(pvRecord,pvFromRequest);
if(field.get()==NULL) return NULLStructure;
if(field->getType()==epics::pvData::structure) {
StructureConstPtr structure =
static_pointer_cast<const Structure>(field);
return structure;
}
StringArray fieldNames(1);
FieldConstPtrArray fields(1);
String name = getFullName(pvFromRequest,"");
size_t ind = name.find_last_of('.');
if(ind!=String::npos) name = String(name,ind+1);
fieldNames[0] = name;
fields[0] = field;
return getFieldCreate()->createStructure(fieldNames, fields);
}
FieldConstPtr PVCopy::createField(
PVStructurePtr const &xxx,
PVStructurePtr const &yyy)
{
PVStructurePtr pvRecord = xxx;
PVStructurePtr pvFromRequest = yyy;
PVFieldPtrArray const & pvFromRequestFields
= pvFromRequest->getPVFields();
StringArray const & fromRequestFieldNames
= pvFromRequest->getStructure()->getFieldNames();
size_t length = pvFromRequestFields.size();
size_t number = 0;
size_t indopt = -1;
for(size_t i=0; i<length; i++) {
if(fromRequestFieldNames[i].compare("_options")!=0) {
number++;
} else {
indopt = i;
}
}
if(number==0) return pvRecord->getStructure();
if(number==1) {
String nameFromRecord = "";
nameFromRecord = getFullName(pvFromRequest,nameFromRecord);
PVFieldPtr pvRecordField = pvRecord->getSubField(nameFromRecord);
if(pvRecordField.get()==NULL) return NULLField;
Type recordFieldType = pvRecordField->getField()->getType();
if(recordFieldType!=epics::pvData::structure) {
return pvRecordField->getField();
}
PVStructurePtr pvSubFrom = static_pointer_cast<PVStructure>(
pvFromRequest->getSubField(nameFromRecord));
PVFieldPtrArray const & pvs = pvSubFrom->getPVFields();
length = pvs.size();
number = 0;
for(size_t i=0; i<length; i++) {
if(!pvs[i]->getFieldName().compare("_options")==0) {
number++;
}
}
FieldConstPtrArray fields(1);
StringArray fieldNames(1);
fieldNames[0] = pvRecordField->getFieldName();
if(number==0) {
fields[0] = pvRecordField->getField();
} else {
PVStructurePtr zzz =
static_pointer_cast<PVStructure>(pvRecordField);
fields[0] = createField(zzz,pvSubFrom);
}
return getFieldCreate()->createStructure(fieldNames, fields);
}
FieldConstPtrArray fields; fields.reserve(number);
StringArray fieldNames; fields.reserve(number);
for(size_t i=0; i<length; i++) {
if(i==indopt) continue;
PVStructurePtr arg = static_pointer_cast<PVStructure>(
pvFromRequestFields[i]);
PVStructurePtr yyy = static_pointer_cast<PVStructure>(
pvFromRequestFields[i]);
String zzz = getFullName(yyy,"");
String full = fromRequestFieldNames[i];
if(zzz.size()>0) {
full += "." + zzz;
arg = getSubStructure(yyy,zzz);
}
PVFieldPtr pvRecordField = pvRecord->getSubField(full);
if(pvRecordField.get()==NULL) continue;
FieldConstPtr field = pvRecordField->getField();
if(field->getType()!=epics::pvData::structure) {
fieldNames.push_back(full);
fields.push_back(field);
continue;
}
FieldConstPtr xxx = createField(
static_pointer_cast<PVStructure>(pvRecordField),arg);
if(xxx.get()!=NULL) {
fieldNames.push_back(fromRequestFieldNames[i]);
fields.push_back(xxx);
}
}
boolean makeValue = true;
size_t indValue = String::npos;
for(size_t i=0;i<fieldNames.size(); i++) {
if(fieldNames[i].compare("value")==0) {
if(indValue==String::npos) {
indValue = i;
} else {
makeValue = false;
}
}
}
for(size_t i=0;i<fieldNames.size(); i++) {
if(makeValue==true&&indValue==i) {
fieldNames[i] = "value";
} else {
String xxx = fieldNames[i];
size_t ind = xxx.find_first_of('.');
if(ind!=String::npos) fieldNames[i] = String(xxx,0, ind);
}
}
return getFieldCreate()->createStructure(fieldNames, fields);
}
CopyNodePtr PVCopy::createStructureNodes(
PVRecordStructurePtr const &xxx,
PVStructurePtr const &yyy,
PVFieldPtr const &zzz)
{
PVRecordStructurePtr pvRecordStructure = xxx;
PVStructurePtr pvFromRequest = yyy;
PVFieldPtr pvFromField = zzz;
PVFieldPtrArray const & pvFromRequestFields = pvFromRequest->getPVFields();
StringArray const & fromRequestFieldNames =
pvFromRequest->getStructure()->getFieldNames();
size_t length = pvFromRequestFields.size();
size_t number = 0;
size_t indopt = -1;
PVStructurePtr pvOptions;
for(size_t i=0; i<length; i++) {
if(fromRequestFieldNames[i].compare("_options")!=0) {
number++;
} else {
indopt = i;
pvOptions = static_pointer_cast<PVStructure>(pvFromRequestFields[i]);
}
}
if(number==0) {
CopyRecordNodePtr recordNode(new CopyRecordNode());
recordNode->options = pvOptions;
recordNode->isStructure = false;
recordNode->recordPVField = pvRecordStructure;
recordNode->nfields = pvFromField->getNumberFields();
recordNode->structureOffset = pvFromField->getFieldOffset();
return recordNode;
}
if(number==1) {
String nameFromRecord = "";
nameFromRecord = getFullName(pvFromRequest,nameFromRecord);
PVFieldPtr pvField = pvRecordStructure->
getPVStructure()->getSubField(nameFromRecord);
if(pvField.get()==NULL) return NULLCopyNodePtr;
PVRecordFieldPtr pvRecordField = pvRecordStructure->
getPVRecord()->findPVRecordField(pvField);
size_t structureOffset = pvFromField->getFieldOffset();
PVStructure *pvParent = pvFromField->getParent();
if(pvParent==NULL) {
structureOffset++;
}
CopyRecordNodePtr recordNode(new CopyRecordNode());
recordNode->options = getOptions(pvFromRequest,nameFromRecord);
recordNode->isStructure = false;
recordNode->recordPVField = pvRecordField;
recordNode->nfields = pvFromField->getNumberFields();
recordNode->structureOffset = structureOffset;
return recordNode;
}
CopyNodePtrArrayPtr nodes(new CopyNodePtrArray());
nodes->reserve(number);
PVStructurePtr pvFromStructure =
static_pointer_cast<PVStructure>(pvFromField);
PVFieldPtrArray const & pvFromStructureFields =
pvFromStructure->getPVFields();
length = pvFromStructureFields.size();
size_t indFromStructure = 0;
for(size_t i= 0; i <pvFromRequestFields.size();i++) {
if(i==indopt) continue;
PVStructurePtr arg = static_pointer_cast<PVStructure>
(pvFromRequestFields[i]);
PVStructurePtr yyy = static_pointer_cast<PVStructure>
(pvFromRequestFields[i]);
String zzz = getFullName(yyy,"");
String full = fromRequestFieldNames[i];
if(zzz.size()>0) {
full += "." + zzz;
arg = getSubStructure(yyy,zzz);
}
PVFieldPtr pvField = pvRecordStructure->
getPVStructure()->getSubField(full);
if(pvField.get()==NULL) continue;
PVRecordFieldPtr pvRecordField =
pvRecordStructure->getPVRecord()->findPVRecordField(pvField);
CopyNodePtr node;
if(pvRecordField->getPVField()->getField()==
pvFromStructureFields[indFromStructure]->getField()) {
pvField = pvFromStructureFields[indFromStructure];
CopyRecordNodePtr recordNode(new CopyRecordNode());
recordNode->options = getOptions(yyy,zzz);
recordNode->isStructure = false;
recordNode->recordPVField = pvRecordField;
recordNode->nfields = pvField->getNumberFields();
recordNode->structureOffset = pvField->getFieldOffset();
node = recordNode;
} else {
node = createStructureNodes(static_pointer_cast<PVRecordStructure>
(pvRecordField),arg,pvFromStructureFields[indFromStructure]);
}
if(node.get()==NULL) continue;
nodes->push_back(node);
++indFromStructure;
}
size_t len = nodes->size();
if(len==String::npos) return NULLCopyNodePtr;
CopyStructureNodePtr structureNode(new CopyStructureNode());
structureNode->isStructure = true;
structureNode->nodes = nodes;
structureNode->structureOffset = pvFromStructure->getFieldOffset();
structureNode->nfields = pvFromStructure->getNumberFields();
structureNode->options = pvOptions;
return structureNode;
}
void PVCopy::referenceImmutable(
PVFieldPtr const &pvField,
CopyNodePtr const & node)
{
if(node->isStructure) {
CopyStructureNodePtr structureNode =
static_pointer_cast<CopyStructureNode>(node);
CopyNodePtrArrayPtr nodes = structureNode->nodes;
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
for(size_t i=0; i<nodes->size(); i++) {
CopyNodePtr nextNode = (*nodes)[i];
referenceImmutable(
pvStructure->getSubField(nextNode->structureOffset),
nextNode);
}
} else {
CopyRecordNodePtr recordNode =
static_pointer_cast<CopyRecordNode>(node);
PVRecordFieldPtr recordPVField = recordNode->recordPVField;
bool shareData = false;
if(node->options.get()!=NULL) {
PVFieldPtr pv = node->options->getSubField("_options");
if(pv.get()!=NULL) {
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pv);
pv = xxx->getSubField("shareData");
if(pv.get()!=NULL) {
PVStringPtr yyy = xxx->getStringField("shareData");
shareData = (yyy->get().compare("true")==0) ? true : false;
}
}
}
if(shareData) {
makeShared(pvField,recordNode->recordPVField);
} else {
referenceImmutable(pvField,recordPVField);
}
}
}
void PVCopy::referenceImmutable(
PVFieldPtr const &copyPVField,
PVRecordFieldPtr const &recordPVField)
{
if(recordPVField->getPVField()->getField()->getType()
==epics::pvData::structure) {
if(copyPVField->getField()->getType()!=epics::pvData::structure) {
throw std::logic_error(String("Logic error"));
}
PVStructurePtr pvStructure =
static_pointer_cast<PVStructure>(copyPVField);
PVFieldPtrArray const & copyPVFields = pvStructure->getPVFields();
PVRecordStructurePtr pvRecordStructure =
static_pointer_cast<PVRecordStructure>(recordPVField);
PVRecordFieldPtrArrayPtr recordPVFields =
pvRecordStructure->getPVRecordFields();
for(size_t i=0; i<copyPVFields.size(); i++) {
referenceImmutable(copyPVFields[i],(*recordPVFields)[i]);
}
return;
}
if(recordPVField->getPVField()->isImmutable()) {
getConvert()->copy(recordPVField->getPVField(), copyPVField);
}
}
void PVCopy::makeShared(
PVFieldPtr const &copyPVField,
PVRecordFieldPtr const &recordPVField)
{
throw std::logic_error(String("Not Implemented"));
}
void PVCopy::updateStructureNodeSetBitSet(
PVStructurePtr const &pvCopy,
CopyStructureNodePtr const &structureNode,
epics::pvData::BitSetPtr const &bitSet)
{
for(size_t i=0; i<structureNode->nodes->size(); i++) {
CopyNodePtr node = (*structureNode->nodes)[i];
PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset);
if(node->isStructure) {
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
CopyStructureNodePtr yyy =
static_pointer_cast<CopyStructureNode>(node);
updateStructureNodeSetBitSet(xxx,yyy,bitSet);
} else {
CopyRecordNodePtr recordNode =
static_pointer_cast<CopyRecordNode>(node);
bool shareData = false;
if(node->options.get()!=NULL) {
PVFieldPtr pv = node->options->getSubField("_options");
if(pv.get()!=NULL) {
PVStructurePtr xxx =
static_pointer_cast<PVStructure>(pv);
pv = xxx->getSubField("shareData");
if(pv.get()!=NULL) {
PVStringPtr yyy = xxx->getStringField("shareData");
shareData = (yyy->get().compare("true")==0) ? true : false;
}
}
}
if(shareData) {
bitSet->set(pvField->getFieldOffset());
} else {
updateSubFieldSetBitSet(pvField,recordNode->recordPVField,bitSet);
}
}
}
}
void PVCopy::updateSubFieldSetBitSet(
PVFieldPtr const &pvCopy,
PVRecordFieldPtr const &pvRecord,
BitSetPtr const &bitSet)
{
FieldConstPtr field = pvCopy->getField();
Type type = field->getType();
if(type!=epics::pvData::structure) {
ConvertPtr convert = getConvert();
bool isEqual = convert->equals(pvCopy,pvRecord->getPVField());
if(isEqual) {
if(type==structureArray) {
// always act as though a change occurred.
// Note that array elements are shared.
bitSet->set(pvCopy->getFieldOffset());
}
}
if(isEqual) return;
convert->copy(pvRecord->getPVField(), pvCopy);
bitSet->set(pvCopy->getFieldOffset());
return;
}
PVStructurePtr pvCopyStructure = static_pointer_cast<PVStructure>(pvCopy);
PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
PVRecordStructurePtr pvRecordStructure =
static_pointer_cast<PVRecordStructure>(pvRecord);
PVRecordFieldPtrArrayPtr pvRecordFields =
pvRecordStructure->getPVRecordFields();
size_t length = pvCopyFields.size();
for(size_t i=0; i<length; i++) {
updateSubFieldSetBitSet(pvCopyFields[i],(*pvRecordFields)[i],bitSet);
}
}
void PVCopy::updateStructureNodeFromBitSet(
PVStructurePtr const &pvCopy,
CopyStructureNodePtr const &structureNode,
BitSetPtr const &bitSet,
bool toCopy,
bool doAll)
{
size_t offset = structureNode->structureOffset;
if(!doAll) {
size_t nextSet = bitSet->nextSetBit(offset);
if(nextSet==String::npos) return;
}
if(offset>=pvCopy->getNextFieldOffset()) return;
if(!doAll) doAll = bitSet->get(offset);
CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i<nodes->size(); i++) {
CopyNodePtr node = (*nodes)[i];
PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset);
if(node->isStructure) {
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
CopyStructureNodePtr subStructureNode =
static_pointer_cast<CopyStructureNode>(node);
updateStructureNodeFromBitSet(
xxx,subStructureNode,bitSet,toCopy,doAll);
} else {
CopyRecordNodePtr recordNode =
static_pointer_cast<CopyRecordNode>(node);
updateSubFieldFromBitSet(
pvField,recordNode->recordPVField,bitSet,toCopy,doAll);
}
}
}
void PVCopy::updateSubFieldFromBitSet(
PVFieldPtr const &pvCopy,
PVRecordFieldPtr const &pvRecordField,
BitSetPtr const &bitSet,
bool toCopy,
bool doAll)
{
if(!doAll) {
doAll = bitSet->get(pvCopy->getFieldOffset());
}
if(!doAll) {
size_t offset = pvCopy->getFieldOffset();
size_t nextSet = bitSet->nextSetBit(offset);
if(nextSet==String::npos) return;
if(nextSet>=pvCopy->getNextFieldOffset()) return;
}
ConvertPtr convert = getConvert();
if(pvCopy->getField()->getType()==epics::pvData::structure) {
PVStructurePtr pvCopyStructure =
static_pointer_cast<PVStructure>(pvCopy);
PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
if(pvRecordField->getPVField()->getField()->getType()
!=epics::pvData::structure)
{
if(pvCopyFields.size()!=1) {
throw std::logic_error(String("Logic error"));
}
if(toCopy) {
convert->copy(pvRecordField->getPVField(), pvCopyFields[0]);
} else {
convert->copy(pvCopyFields[0], pvRecordField->getPVField());
}
return;
}
PVRecordStructurePtr pvRecordStructure =
static_pointer_cast<PVRecordStructure>(pvRecordField);
PVRecordFieldPtrArrayPtr pvRecordFields =
pvRecordStructure->getPVRecordFields();
for(size_t i=0; i<pvCopyFields.size(); i++) {
updateSubFieldFromBitSet(
pvCopyFields[i],
(*pvRecordFields)[i],
bitSet,toCopy,doAll);
}
} else {
if(toCopy) {
convert->copy(pvRecordField->getPVField(), pvCopy);
} else {
convert->copy(pvCopy, pvRecordField->getPVField());
}
}
}
CopyRecordNodePtr PVCopy::getCopyOffset(
CopyStructureNodePtr const &structureNode,
PVRecordFieldPtr const &recordPVField)
{
size_t offset = recordPVField->getPVField()->getFieldOffset();
CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i< nodes->size(); i++) {
CopyNodePtr node = (*nodes)[i];
if(!node->isStructure) {
CopyRecordNodePtr recordNode =
static_pointer_cast<CopyRecordNode>(node);
size_t off = recordNode->recordPVField->getPVField()->
getFieldOffset();
size_t nextOffset = recordNode->recordPVField->getPVField()->
getNextFieldOffset();
if(offset>= off && offset<nextOffset) return recordNode;
} else {
CopyStructureNodePtr subNode =
static_pointer_cast<CopyStructureNode>(node);
CopyRecordNodePtr recordNode =
getCopyOffset(subNode,recordPVField);
if(recordNode.get()!=NULL) return recordNode;
}
}
return NULLCopyRecordNodePtr;
}
CopyRecordNodePtr PVCopy::getRecordNode(
CopyStructureNodePtr const &structureNode,
std::size_t structureOffset)
{
CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i< nodes->size(); i++) {
CopyNodePtr node = (*nodes)[i];
if(structureOffset>=(node->structureOffset + node->nfields)) continue;
if(!node->isStructure) {
CopyRecordNodePtr recordNode =
static_pointer_cast<CopyRecordNode>(node);
return recordNode;
}
CopyStructureNodePtr subNode =
static_pointer_cast<CopyStructureNode>(node);
return getRecordNode(subNode,structureOffset);
}
return NULLCopyRecordNodePtr;
}
PVCopyMonitor::PVCopyMonitor()
{
throw std::logic_error(String("Not Implemented"));
}
PVCopyMonitor::~PVCopyMonitor()
{
throw std::logic_error(String("Not Implemented"));
}
void PVCopyMonitor::startMonitoring(
BitSetPtr const &changeBitSet,
BitSetPtr const &overrunBitSet)
{
throw std::logic_error(String("Not Implemented"));
}
void PVCopyMonitor::stopMonitoring()
{
throw std::logic_error(String("Not Implemented"));
}
void PVCopyMonitor::switchBitSets(
BitSetPtr const &newChangeBitSet,
BitSetPtr const &newOverrunBitSet, bool lockRecord)
{
throw std::logic_error(String("Not Implemented"));
}
}}

303
src/pvAccess/pvCopy.h Normal file
View File

@@ -0,0 +1,303 @@
/* pvCopy.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2013.03.25
*/
#ifndef PVCOPY_H
#define PVCOPY_H
#include <string>
#include <stdexcept>
#include <memory>
#include <pv/pvType.h>
#include <pv/pvIntrospect.h>
#include <pv/pvData.h>
#include <pv/pvDatabase.h>
namespace epics { namespace pvDatabase {
class PVCopy;
typedef std::tr1::shared_ptr<PVCopy> PVCopyPtr;
class PVCopyMonitor;
typedef std::tr1::shared_ptr<PVCopyMonitor> PVCopyMonitorPtr;
class PVCopyMonitorRequester;
typedef std::tr1::shared_ptr<PVCopyMonitorRequester> PVCopyMonitorRequesterPtr;
class SharePVScalarArray;
typedef std::tr1::shared_ptr<SharePVScalarArray> SharePVScalarArrayPtr;
class SharePVStructureArray;
typedef std::tr1::shared_ptr<SharePVStructureArray> SharePVStructureArrayPtr;
struct CopyNode;
typedef std::tr1::shared_ptr<CopyNode> CopyNodePtr;
struct CopyRecordNode;
typedef std::tr1::shared_ptr<CopyRecordNode> CopyRecordNodePtr;
struct CopyStructureNode;
typedef std::tr1::shared_ptr<CopyStructureNode> CopyStructureNodePtr;
class PVCopy :
public std::tr1::enable_shared_from_this<PVCopy>
{
public:
POINTER_DEFINITIONS(PVCopy);
static PVCopyPtr create(
PVRecordPtr const &pvRecord,
epics::pvData::PVStructurePtr const &pvRequest,
epics::pvData::String const & structureName);
virtual ~PVCopy(){}
PVRecordPtr getPVRecord();
epics::pvData::StructureConstPtr getStructure();
epics::pvData::PVStructurePtr createPVStructure();
std::size_t getCopyOffset(PVRecordFieldPtr const &recordPVField);
std::size_t getCopyOffset(
PVRecordStructurePtr const &recordPVStructure,
PVRecordFieldPtr const &recordPVField);
PVRecordFieldPtr getRecordPVField(std::size_t structureOffset);
void initCopy(
epics::pvData::PVStructurePtr const &copyPVStructure,
epics::pvData::BitSetPtr const &bitSet,
bool lockRecord);
void updateCopySetBitSet(
epics::pvData::PVStructurePtr const &copyPVStructure,
epics::pvData::BitSetPtr const &bitSet,
bool lockRecord);
void updateCopyFromBitSet(
epics::pvData::PVStructurePtr const &copyPVStructure,
epics::pvData::BitSetPtr const &bitSet,
bool lockRecord);
void updateRecord(
epics::pvData::PVStructurePtr const &copyPVStructure,
epics::pvData::BitSetPtr const &bitSet,
bool lockRecord);
PVCopyMonitorPtr createPVCopyMonitor(
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester);
epics::pvData::PVStructurePtr getOptions(
epics::pvData::PVStructurePtr const &copyPVStructure,std::size_t fieldOffset);
epics::pvData::String dump();
private:
PVCopyPtr getPtrSelf()
{
return shared_from_this();
}
PVRecordPtr pvRecord;
epics::pvData::StructureConstPtr structure;
CopyNodePtr headNode;
epics::pvData::PVStructurePtr cacheInitStructure;
private:
PVCopy(PVRecordPtr const &pvRecord);
bool init(epics::pvData::PVStructurePtr const &pvRequest);
epics::pvData::String dump(
epics::pvData::String const &value,
CopyNodePtr const &node,
int indentLevel);
epics::pvData::String getFullName(
epics::pvData::PVStructurePtr const &pvFromRequest,
epics::pvData::String const &nameFromRecord);
epics::pvData::PVStructurePtr getSubStructure(
epics::pvData::PVStructurePtr const &pvFromRequest,
epics::pvData::String const &nameFromRecord);
epics::pvData::PVStructurePtr getOptions(
epics::pvData::PVStructurePtr const &pvFromRequest,
epics::pvData::String const &nameFromRecord);
epics::pvData::StructureConstPtr createStructure(
epics::pvData::PVStructurePtr const &pvRecord,
epics::pvData::PVStructurePtr const &pvFromRequest);
epics::pvData::FieldConstPtr createField(
epics::pvData::PVStructurePtr const &pvRecord,
epics::pvData::PVStructurePtr const &pvFromRequest);
CopyNodePtr createStructureNodes(
PVRecordStructurePtr const &pvRecordStructure,
epics::pvData::PVStructurePtr const &pvFromRequest,
epics::pvData::PVFieldPtr const &pvFromField);
void referenceImmutable(
epics::pvData::PVFieldPtr const &pvField,
CopyNodePtr const & node);
void referenceImmutable(
epics::pvData::PVFieldPtr const &copyPVField,
PVRecordFieldPtr const &recordPVField);
void makeShared(
epics::pvData::PVFieldPtr const &copyPVField,
PVRecordFieldPtr const &recordPVField);
void updateStructureNodeSetBitSet(
epics::pvData::PVStructurePtr const &pvCopy,
CopyStructureNodePtr const &structureNode,
epics::pvData::BitSetPtr const &bitSet);
void updateSubFieldSetBitSet(
epics::pvData::PVFieldPtr const &pvCopy,
PVRecordFieldPtr const &pvRecord,
epics::pvData::BitSetPtr const &bitSet);
void updateStructureNodeFromBitSet(
epics::pvData::PVStructurePtr const &pvCopy,
CopyStructureNodePtr const &structureNode,
epics::pvData::BitSetPtr const &bitSet,
bool toCopy,
bool doAll);
void updateSubFieldFromBitSet(
epics::pvData::PVFieldPtr const &pvCopy,
PVRecordFieldPtr const &pvRecordField,
epics::pvData::BitSetPtr const &bitSet,
bool toCopy,
bool doAll);
CopyRecordNodePtr getCopyOffset(
CopyStructureNodePtr const &structureNode,
PVRecordFieldPtr const &recordPVField);
CopyRecordNodePtr getRecordNode(
CopyStructureNodePtr const &structureNode,
std::size_t structureOffset);
};
class PVCopyMonitor :
public std::tr1::enable_shared_from_this<PVCopyMonitor>
{
public:
POINTER_DEFINITIONS(PVCopyMonitor);
virtual ~PVCopyMonitor();
void startMonitoring(
epics::pvData::BitSetPtr const &changeBitSet,
epics::pvData::BitSetPtr const &overrunBitSet);
void stopMonitoring();
void switchBitSets(
epics::pvData::BitSetPtr const &newChangeBitSet,
epics::pvData::BitSetPtr const &newOverrunBitSet, bool lockRecord);
private:
PVCopyMonitorPtr getPtrSelf()
{
return shared_from_this();
}
PVCopyMonitor();
friend class PVCopy;
// TBD
};
class PVCopyMonitorRequester :
public std::tr1::enable_shared_from_this<PVCopyMonitorRequester>
{
public:
POINTER_DEFINITIONS(PVCopyMonitorRequester);
virtual void dataChanged() = 0;
virtual void unlisten() = 0;
private:
PVCopyMonitorRequesterPtr getPtrSelf()
{
return shared_from_this();
}
};
#ifdef MUSTIMPLEMENT
template<typename T>
class SharePVScalarArray :
public epics::pvData::PVScalarArray
{
public:
POINTER_DEFINITIONS(SharePVScalarArray)
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef epics::pvData::PVArrayData<T> ArrayDataType;
SharePVScalarArray(
PVRecordFieldPtr const &pvRecordField,
epics::pvData::PVStructurePtr const &parent,
epics::pvData::PVScalarArrayPtr const &pvShare);
virtual ~SharePVScalarArray();
void lockShare() const;
void unlockShare() const;
virtual void message(
epics::pvData::String const & message,
epics::pvData::MessageType messageType);
virtual void setImmutable();
bool isImmutable();
virtual void setCapacity(std::size_t capacity);
void setLength(std::size_t length);
std::size_t getCapacity() const;
std::size_t getLength() const;
bool isCapacityMutable();
void setCapacityMutable(bool isMutable);
virtual std::size_t get(std::size_t offset, std::size_t length, ArrayDataType &data) = 0;
virtual std::size_t put(std::size_t offset,std::size_t length, pointer from, std::size_t fromOffset) = 0;
virtual void shareData(pointer value,std::size_t capacity,std::size_t length) = 0;
virtual bool equals(epics::pvData::PVFieldPtr const &pv);
virtual void serialize(
epics::pvData::ByteBufferPtr *pbuffer,
epics::pvData::SerializableControl *pflusher) const;
virtual void deserialize(
epics::pvData::ByteBuffer *pbuffer,
epics::pvData::DeserializableControl *pflusher);
virtual void serialize(
epics::pvData::ByteBuffer *pbuffer,
epics::pvData::SerializableControl *pflusher, std::size_t offset, std::size_t count) const;
private:
PVRecordField &pvRecordField;
};
typedef SharePVScalarArray<bool> SharePVBooleanArray;
typedef SharePVScalarArray<epics::pvData::int8> SharePVByteArray;
typedef SharePVScalarArray<epics::pvData::int16> SharePVShortArray;
typedef SharePVScalarArray<epics::pvData::int32> SharePVIntArray;
typedef SharePVScalarArray<epics::pvData::int64> SharePVLongArray;
typedef SharePVScalarArray<float> SharePVFloatArray;
typedef SharePVScalarArray<double> SharePVDoubleArray;
typedef SharePVScalarArray<epics::pvData::String> SharePVStringArray;
class SharePVStructureArray :
public epics::pvData::PVStructureArray
{
public:
POINTER_DEFINITIONS(SharePVStructureArray)
SharePVStructureArray(
PVRecordFieldPtr const &pvRecordField,
epics::pvData::PVStructurePtr const &parent,
epics::pvData::PVStructureArrayPtr const &pvShare);
virtual ~SharePVStructureArray();
virtual epics::pvData::StructureArrayConstPtr getStructureArray();
void lockShare() const;
void unlockShare() const;
virtual void message(
epics::pvData::String const &message,
epics::pvData::MessageType messageType);
virtual void setImmutable();
bool isImmutable();
virtual void setCapacity(std::size_t capacity);
void setLength(std::size_t length);
std::size_t getCapacity() const;
std::size_t getLength() const;
bool isCapacityMutable();
void setCapacityMutable(bool isMutable);
virtual void shareData(
epics::pvData::PVStructurePtrArrayPtr const & value,
std::size_t capacity,std::size_t length);
virtual std::size_t get(std::size_t offset, std::size_t length,
epics::pvData::StructureArrayData &data);
virtual std::size_t put(std::size_t offset,std::size_t length,
epics::pvData::PVStructurePtrArrayPtr const & from,
std::size_t fromOffset);
virtual bool equals(epics::pvData::PVField & &pv);
virtual void serialize(
epics::pvData::ByteBuffer *pbuffer,
epics::pvData::SerializableControl *pflusher) const;
virtual void deserialize(
epics::pvData::ByteBuffer *pbuffer,
epics::pvData::DeserializableControl *pflusher);
virtual void serialize(
epics::pvData::ByteBuffer *pbuffer,
epics::pvData::SerializableControl *pflusher,
std::size_t offset, std::size_t count) const;
private:
PVRecordField &pvRecordField;
};
#endif
}}
#endif /* PVCOPY_H */

241
src/pvAccess/pvShare.cpp Normal file
View File

@@ -0,0 +1,241 @@
/* pvShare.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
*/
#include <string>
#include <stdexcept>
#include <memory>
#include <pv/pvData.h>
#include <pv/noDefaultMethods.h>
#include <pv/pvDatabase.h>
#include <pv/support.h>
#include <pv/pvCopy.h>
namespace epics { namespace pvIOC {
using namespace epics::pvData;
template<typename T>
SharePVScalarArray<T>::SharePVScalarArray(
PVRecordField &pvRecordField,
epics::pvData::PVStructure *parent,
epics::pvData::PVScalarArray &pvShare)
: PVField(parent,pvShare.getField()),
pvRecordField(pvRecordField)
{
}
template<typename T>
SharePVScalarArray<T>::~SharePVScalarArray()
{
}
template<typename T>
void SharePVScalarArray<T>::lockShare() const
{
pvRecordField.getPVRecord().lock();
}
template<typename T>
void SharePVScalarArray<T>::unlockShare() const
{
pvRecordField.getPVRecord().unlock();
}
template<typename T>
void SharePVScalarArray<T>::message(String message,MessageType messageType)
{
pvRecordField.message(message,messageType);
}
template<typename T>
void SharePVScalarArray<T>::setImmutable()
{
lockShare();
try {
pvRecordField.getPVField().setImmutable();
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
template<typename T>
bool SharePVScalarArray<T>::isImmutable()
{
return pvRecordField.getPVField().isImmutable();
}
template<typename T>
void SharePVScalarArray<T>::setCapacityMutable(bool isMutable)
{
lockShare();
try {
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
pvArray.setCapacityMutable(isMutable);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
template<typename T>
bool SharePVScalarArray<T>::isCapacityMutable()
{
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
return pvArray.isCapacityMutable();
}
template<typename T>
void SharePVScalarArray<T>::setCapacity(int capacity)
{
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
lockShare();
try {
pvArray.setCapacity(capacity);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
template<typename T>
void SharePVScalarArray<T>::setLength(int length)
{
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
lockShare();
try {
pvArray.setLength(length);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
template<typename T>
int SharePVScalarArray<T>::getCapacity() const
{
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
return pvArray.getCapacity();
}
template<typename T>
int SharePVScalarArray<T>::getLength() const
{
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
return pvArray.getLength();
}
template<typename T>
int SharePVScalarArray<T>::get(int offset, int length, ArrayDataType *data)
{
class PVValueArray<T> &pvArray = static_cast<PVValueArray<T> &>(
pvRecordField.getPVField());
lockShare();
try {
return pvArray.get(offset,length,data);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
template<typename T>
int SharePVScalarArray<T>::put(
int offset,int length, pointer from, int fromOffset)
{
class PVValueArray<T> &pvArray = static_cast<PVValueArray<T> &>(
pvRecordField.getPVField());
lockShare();
try {
pvRecordField.getPVRecord().beginGroupPut();
int len = pvArray.put(offset,length,from,fromOffset);
pvRecordField.getPVRecord().endGroupPut();
unlockShare();
return len;
} catch(...) {
unlockShare();
throw;
}
}
template<typename T>
void SharePVScalarArray<T>::shareData(pointer value,int capacity,int length)
{
class PVValueArray<T> &pvArray = static_cast<PVValueArray<T> &>(
pvRecordField.getPVField());
lockShare();
try {
pvArray.setImmutable(value,capacity,length);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
template<typename T>
bool SharePVScalarArray<T>::equals(PVField &pv)
{
lockShare();
try {
return pvRecordField.getPVField().equals(pv);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
template<typename T>
void SharePVScalarArray<T>::serialize(
ByteBuffer *pbuffer,SerializableControl *pflusher) const
{
serialize(pbuffer, pflusher, 0, getLength());
}
template<typename T>
void SharePVScalarArray<T>::deserialize(
ByteBuffer *pbuffer,DeserializableControl *pflusher)
{
class PVValueArray<T> &pvArray = static_cast<PVValueArray<T> &>(
pvRecordField.getPVField());
lockShare();
try {
pvArray.deserialize(pbuffer,pflusher);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
template<typename T>
void SharePVScalarArray<T>::serialize(
ByteBuffer *pbuffer,SerializableControl *pflusher,int offset,int count) const
{
class PVValueArray<T> &pvArray = static_cast<PVValueArray<T> &>(
pvRecordField.getPVField());
lockShare();
try {
pvArray.serialize(pbuffer,pflusher,offset,count);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
}}

View File

@@ -0,0 +1,218 @@
/* pvShareStructureArray.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
*/
#include <string>
#include <stdexcept>
#include <memory>
#include <pv/pvData.h>
#include <pv/noDefaultMethods.h>
#include <pv/pvDatabase.h>
#include <pv/support.h>
#include <pv/pvCopy.h>
namespace epics { namespace pvIOC {
using namespace epics::pvData;
SharePVStructureArray::SharePVStructureArray(
PVRecordField &pvRecordField,
PVStructure *parent,
PVStructureArray &pvShare)
: PVArray(parent,pvShare.getField()),
pvRecordField(pvRecordField)
{
}
SharePVStructureArray::~SharePVStructureArray() {}
StructureArrayConstPtr SharePVStructureArray::getStructureArray()
{
PVStructureArray &pvArray = static_cast<PVStructureArray &>(
pvRecordField.getPVField());
return pvArray.getStructureArray();
}
void SharePVStructureArray::lockShare() const
{
pvRecordField.getPVRecord().lock();
}
void SharePVStructureArray::unlockShare() const
{
pvRecordField.getPVRecord().unlock();
}
void SharePVStructureArray::message(String message,MessageType messageType)
{
pvRecordField.message(message,messageType);
}
void SharePVStructureArray::setImmutable()
{
lockShare();
try {
pvRecordField.getPVField().setImmutable();
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
bool SharePVStructureArray::isImmutable()
{
return pvRecordField.getPVField().isImmutable();
}
void SharePVStructureArray::setCapacityMutable(bool isMutable)
{
lockShare();
try {
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
pvArray.setCapacityMutable(isMutable);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
bool SharePVStructureArray::isCapacityMutable()
{
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
return pvArray.isCapacityMutable();
}
void SharePVStructureArray::setCapacity(int capacity)
{
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
lockShare();
try {
pvArray.setCapacity(capacity);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
void SharePVStructureArray::setLength(int length)
{
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
lockShare();
try {
pvArray.setLength(length);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
int SharePVStructureArray::getCapacity() const
{
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
return pvArray.getCapacity();
}
int SharePVStructureArray::getLength() const
{
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
return pvArray.getLength();
}
int SharePVStructureArray::get(int offset, int length, StructureArrayData *data)
{
class PVStructureArray &pvArray = static_cast<PVStructureArray &>(
pvRecordField.getPVField());
lockShare();
try {
return pvArray.get(offset,length,data);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
int SharePVStructureArray::put(
int offset,int length, PVStructurePtrArray from, int fromOffset)
{
class PVStructureArray &pvArray = static_cast<PVStructureArray &>(
pvRecordField.getPVField());
lockShare();
try {
pvRecordField.getPVRecord().beginGroupPut();
int len = pvArray.put(offset,length,from,fromOffset);
pvRecordField.getPVRecord().endGroupPut();
unlockShare();
return len;
} catch(...) {
unlockShare();
throw;
}
}
void SharePVStructureArray::shareData(
PVStructurePtrArray value,int capacity,int length)
{
throw std::logic_error("shareData not legal in this context");
}
bool SharePVStructureArray::equals(PVField &pv)
{
lockShare();
try {
return pvRecordField.getPVField().equals(pv);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
void SharePVStructureArray::serialize(
ByteBuffer *pbuffer,SerializableControl *pflusher) const
{
serialize(pbuffer, pflusher, 0, getLength());
}
void SharePVStructureArray::deserialize(
ByteBuffer *pbuffer,DeserializableControl *pflusher)
{
class PVStructureArray &pvArray = static_cast<PVStructureArray &>(
pvRecordField.getPVField());
lockShare();
try {
pvArray.deserialize(pbuffer,pflusher);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
void SharePVStructureArray::serialize(
ByteBuffer *pbuffer,SerializableControl *pflusher,int offset,int count) const
{
class PVStructureArray &pvArray = static_cast<PVStructureArray &>(
pvRecordField.getPVField());
lockShare();
try {
pvArray.serialize(pbuffer,pflusher,offset,count);
unlockShare();
} catch(...) {
unlockShare();
throw;
}
}
}}