diff --git a/Makefile b/Makefile index 695a348..f67c990 100644 --- a/Makefile +++ b/Makefile @@ -9,11 +9,6 @@ src_DEPEND_DIRS = configure DIRS += test test_DEPEND_DIRS = src -DIRS += example -example_DEPEND_DIRS = src - -#DIRS += iocBoot - include $(TOP)/configure/RULES_TOP diff --git a/example/Makefile b/example/Makefile deleted file mode 100644 index 13120fd..0000000 --- a/example/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -TOP = .. -include $(TOP)/configure/CONFIG -DIRS += record -include $(TOP)/configure/RULES_DIRS - diff --git a/example/record/Makefile b/example/record/Makefile deleted file mode 100644 index 27885e2..0000000 --- a/example/record/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -TOP=../.. - -include $(TOP)/configure/CONFIG - -PROD_HOST += exampleRecord -exampleRecord_SRCS += exampleRecord.cpp -exampleRecord_SRCS += exampleRecordMain.cpp -exampleRecord_LIBS += pvDatabase pvAccess pvData Com - -include $(TOP)/configure/RULES -#---------------------------------------- -# ADD RULES AFTER THIS LINE - diff --git a/example/record/exampleRecord.cpp b/example/record/exampleRecord.cpp deleted file mode 100644 index fd5950d..0000000 --- a/example/record/exampleRecord.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* exampleRecord.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 - */ -/* Marty Kraimer 2011.03 */ -/* This connects to a V3 record and presents the data as a PVStructure - * It provides access to value, alarm, display, and control. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include "exampleRecord.h" - - -namespace epics { namespace pvDatabase { - -using namespace epics::pvData; -using namespace epics::pvAccess; -using std::tr1::static_pointer_cast; - -ExampleRecord::~ExampleRecord(){} - -PVRecordPtr ExampleRecord::create(String const & recordName) -{ - String properties; - PVStructurePtr pvStructure = getStandardPVField()->scalar(pvLong,properties); - PVLongPtr pvValue = pvStructure->getLongField("value"); - PVRecordPtr pvRecord(new ExampleRecord(recordName,pvStructure,pvValue)); - pvRecord->init(); - return pvRecord; -} - -ExampleRecord::ExampleRecord( - String const & recordName, - PVStructurePtr const & pvStructure, - PVLongPtr const &pvValue) -: PVRecord(recordName,pvStructure), - pvValue(pvValue) -{} - -bool ExampleRecord::isSynchronous() {return true;} - -void ExampleRecord::process( - RecordProcessRequesterPtr const &processRequester,bool alreadyLocked) -{ - if(!alreadyLocked) lock(); - pvValue->put(pvValue->get() + 1); - processRequester->recordProcessResult(Status::Ok); - unlock(); - processRequester->recordProcessComplete(); - dequeueProcessRequest(processRequester); -} - - -}} - diff --git a/example/record/exampleRecord.h b/example/record/exampleRecord.h deleted file mode 100644 index 1158bfd..0000000 --- a/example/record/exampleRecord.h +++ /dev/null @@ -1,43 +0,0 @@ -/* exampleRecord.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 - */ -#ifndef EXAMPLE_RECORD_H -#define EXAMPLE_RECORD_H -#include -#include -#include -#include - -#include - -namespace epics { namespace pvDatabase { - -class ExampleRecord; - -class ExampleRecord : - public virtual PVRecord -{ -public: - POINTER_DEFINITIONS(ExampleRecord); - static PVRecordPtr create(epics::pvData::String const & recordName); - virtual ~ExampleRecord(); - virtual bool isSynchronous(); - virtual void process( - epics::pvDatabase::RecordProcessRequesterPtr const &processRequester, - bool alreadyLocked); -private: - ExampleRecord(epics::pvData::String const & recordName, - epics::pvData::PVStructurePtr const & pvStructure, - epics::pvData::PVLongPtr const &pvValue); - epics::pvData::PVLongPtr pvValue; -}; - -}} - -#endif /* EXAMPLE_RECORD_H */ diff --git a/example/record/exampleRecordMain.cpp b/example/record/exampleRecordMain.cpp deleted file mode 100644 index ed88c4a..0000000 --- a/example/record/exampleRecordMain.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/*exampleRecordMain.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 - */ - -/* Author: Marty Kraimer */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include "exampleRecord.h" - -using namespace std; -using namespace epics::pvData; -using namespace epics::pvAccess; -using namespace epics::pvDatabase; - -int main(int argc,char *argv[]) -{ - String recordName("exampleRecord"); - PVRecordPtr pvRecord = ExampleRecord::create(recordName); - PVDatabasePtr pvDatabase = PVDatabase::getMaster(); - pvDatabase->addRecord(pvRecord); - cout << recordName << "\n"; - string str; - while(true) { - cout << "Type exit to stop: \n"; - getline(cin,str); - if(str.compare("exit")==0) break; - - } - return 0; -} - diff --git a/src/Makefile b/src/Makefile index 5959855..4f8faab 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 diff --git a/src/database/powerSupplyRecordTest.h b/src/database/powerSupplyRecordTest.h new file mode 100644 index 0000000..2d1e09d --- /dev/null +++ b/src/database/powerSupplyRecordTest.h @@ -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 +#include +#include +#include +#include +#include +#include +#include + +namespace epics { namespace pvDatabase { + + +class PowerSupplyRecordTest; +typedef std::tr1::shared_ptr 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 */ diff --git a/src/database/pvDatabase.h b/src/database/pvDatabase.h index 94a5d62..95e71b8 100644 --- a/src/database/pvDatabase.h +++ b/src/database/pvDatabase.h @@ -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 PVRecordClientPtr; class PVListener; typedef std::tr1::shared_ptr PVListenerPtr; -class RecordProcessRequester; -typedef std::tr1::shared_ptr RecordProcessRequesterPtr; - -class RecordPutRequester; -typedef std::tr1::shared_ptr RecordPutRequesterPtr; - class PVDatabase; typedef std::tr1::shared_ptr PVDatabasePtr; - class PVRecord : public epics::pvData::Requester, public std::tr1::enable_shared_from_this { 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 processRequesterQueue; - std::deque putRequesterQueue; std::list pvListenerList; std::list pvRecordClientList; std::list 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); diff --git a/src/database/pvRecord.cpp b/src/database/pvRecord.cpp index dbd1899..ef32519 100644 --- a/src/database/pvRecord.cpp +++ b/src/database/pvRecord.cpp @@ -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::iterator requesterIter; @@ -74,28 +85,6 @@ void PVRecord::destroy() pvRecordClientList.clear(); pvListenerList.clear(); - - std::deque::iterator processRequesterIter; - for ( - processRequesterIter = processRequesterQueue.begin(); - processRequesterIter != processRequesterQueue.end(); - processRequesterIter++ ) - { - (*processRequesterIter)->recordDestroyed(); - } - processRequesterQueue.clear(); - - std::deque::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; diff --git a/src/pvAccess/monitorAlgorithm.h b/src/pvAccess/monitorAlgorithm.h new file mode 100644 index 0000000..420b7f6 --- /dev/null +++ b/src/pvAccess/monitorAlgorithm.h @@ -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 + +#include + +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 create( + PVRecord &pvRecord; + MonitorRequester &requester; + PVRecordField &pvRecordField; + PVStructure &pvStructure); +}; + +extern MonitorAlgorithmCreate& getAlgorithmDeadband(); +extern MonitorAlgorithmCreate& getAlgorithmOnChange(); + +#endif /* MONITORALGORITHM_H */ diff --git a/src/pvAccess/pvCopy.cpp b/src/pvAccess/pvCopy.cpp new file mode 100644 index 0000000..3513938 --- /dev/null +++ b/src/pvAccess/pvCopy.cpp @@ -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 +#include +#include + +#include + +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 CopyNodePtrArray; +typedef std::tr1::shared_ptr 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(headNode); + if((recordNode->recordPVField.get())==recordPVField.get()) { + return headNode->structureOffset; + } + return String::npos; + } + CopyStructureNodePtr node = static_pointer_cast(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(headNode); + if(recordNode->recordPVField.get()!=recordPVStructure.get()) return String::npos; + } else { + CopyStructureNodePtr node = static_pointer_cast(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(headNode); + } else { + CopyStructureNodePtr node = static_pointer_cast(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(pvRecordField->getPVField()); + PVFieldPtr pvField = pvStructure->getSubField( + pvRecordField->getPVField()->getFieldOffset() + diff); + return pvRecord->findPVRecordField(pvField); +} + +void PVCopy::initCopy( + PVStructurePtr const ©PVStructure, + BitSetPtr const &bitSet, + bool lockRecord) +{ + bitSet->clear(); + bitSet->set(0); + updateCopyFromBitSet(copyPVStructure,bitSet,lockRecord); +} + +void PVCopy::updateCopySetBitSet( + PVStructurePtr const ©PVStructure, + BitSetPtr const &bitSet, + bool lockRecord) +{ + if(lockRecord) pvRecord->lock(); + try { + if(headNode->isStructure) { + CopyStructureNodePtr node = static_pointer_cast(headNode); + updateStructureNodeSetBitSet(copyPVStructure,node,bitSet); + } else { + CopyRecordNodePtr recordNode = static_pointer_cast(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 ©PVStructure, + BitSetPtr const &bitSet, + bool lockRecord) +{ + bool doAll = bitSet->get(0); + if(lockRecord) pvRecord->lock(); + try { + if(headNode->isStructure) { + CopyStructureNodePtr node = static_pointer_cast(headNode); + updateStructureNodeFromBitSet(copyPVStructure,node,bitSet,true,doAll); + } else { + CopyRecordNodePtr recordNode = static_pointer_cast(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 ©PVStructure, + 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(headNode); + updateStructureNodeFromBitSet( + copyPVStructure,node,bitSet,false,doAll); + } else { + CopyRecordNodePtr recordNode = + static_pointer_cast(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(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(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(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(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(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(pvFields[0]); + return pvFromRequest; + } else if(pvFields[1]->getFieldName().compare("_options")==0) { + pvFromRequest = static_pointer_cast(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(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; igetStructure(); + 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( + pvFromRequest->getSubField(nameFromRecord)); + PVFieldPtrArray const & pvs = pvSubFrom->getPVFields(); + length = pvs.size(); + number = 0; + for(size_t i=0; igetFieldName().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(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( + pvFromRequestFields[i]); + PVStructurePtr yyy = static_pointer_cast( + 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(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;icreateStructure(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(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(pvFromField); + PVFieldPtrArray const & pvFromStructureFields = + pvFromStructure->getPVFields(); + length = pvFromStructureFields.size(); + size_t indFromStructure = 0; + for(size_t i= 0; i + (pvFromRequestFields[i]); + PVStructurePtr yyy = static_pointer_cast + (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 + (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(node); + CopyNodePtrArrayPtr nodes = structureNode->nodes; + PVStructurePtr pvStructure = static_pointer_cast(pvField); + for(size_t i=0; isize(); i++) { + CopyNodePtr nextNode = (*nodes)[i]; + referenceImmutable( + pvStructure->getSubField(nextNode->structureOffset), + nextNode); + } + } else { + CopyRecordNodePtr recordNode = + static_pointer_cast(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(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 ©PVField, + 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(copyPVField); + PVFieldPtrArray const & copyPVFields = pvStructure->getPVFields(); + PVRecordStructurePtr pvRecordStructure = + static_pointer_cast(recordPVField); + PVRecordFieldPtrArrayPtr recordPVFields = + pvRecordStructure->getPVRecordFields(); + for(size_t i=0; igetPVField()->isImmutable()) { + getConvert()->copy(recordPVField->getPVField(), copyPVField); + } +} + +void PVCopy::makeShared( + PVFieldPtr const ©PVField, + 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; inodes->size(); i++) { + CopyNodePtr node = (*structureNode->nodes)[i]; + PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset); + if(node->isStructure) { + PVStructurePtr xxx = static_pointer_cast(pvField); + CopyStructureNodePtr yyy = + static_pointer_cast(node); + updateStructureNodeSetBitSet(xxx,yyy,bitSet); + } else { + CopyRecordNodePtr recordNode = + static_pointer_cast(node); + bool shareData = false; + if(node->options.get()!=NULL) { + PVFieldPtr pv = node->options->getSubField("_options"); + if(pv.get()!=NULL) { + PVStructurePtr xxx = + static_pointer_cast(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(pvCopy); + PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields(); + PVRecordStructurePtr pvRecordStructure = + static_pointer_cast(pvRecord); + PVRecordFieldPtrArrayPtr pvRecordFields = + pvRecordStructure->getPVRecordFields(); + size_t length = pvCopyFields.size(); + for(size_t i=0; istructureOffset; + 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; isize(); i++) { + CopyNodePtr node = (*nodes)[i]; + PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset); + if(node->isStructure) { + PVStructurePtr xxx = static_pointer_cast(pvField); + CopyStructureNodePtr subStructureNode = + static_pointer_cast(node); + updateStructureNodeFromBitSet( + xxx,subStructureNode,bitSet,toCopy,doAll); + } else { + CopyRecordNodePtr recordNode = + static_pointer_cast(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(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(pvRecordField); + PVRecordFieldPtrArrayPtr pvRecordFields = + pvRecordStructure->getPVRecordFields(); + for(size_t i=0; icopy(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(node); + size_t off = recordNode->recordPVField->getPVField()-> + getFieldOffset(); + size_t nextOffset = recordNode->recordPVField->getPVField()-> + getNextFieldOffset(); + if(offset>= off && offset(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(node); + return recordNode; + } + CopyStructureNodePtr subNode = + static_pointer_cast(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")); +} + +}} diff --git a/src/pvAccess/pvCopy.h b/src/pvAccess/pvCopy.h new file mode 100644 index 0000000..4463c19 --- /dev/null +++ b/src/pvAccess/pvCopy.h @@ -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 +#include +#include + +#include +#include +#include + +#include + +namespace epics { namespace pvDatabase { + +class PVCopy; +typedef std::tr1::shared_ptr PVCopyPtr; +class PVCopyMonitor; +typedef std::tr1::shared_ptr PVCopyMonitorPtr; +class PVCopyMonitorRequester; +typedef std::tr1::shared_ptr PVCopyMonitorRequesterPtr; +class SharePVScalarArray; +typedef std::tr1::shared_ptr SharePVScalarArrayPtr; +class SharePVStructureArray; +typedef std::tr1::shared_ptr SharePVStructureArrayPtr; + +struct CopyNode; +typedef std::tr1::shared_ptr CopyNodePtr; +struct CopyRecordNode; +typedef std::tr1::shared_ptr CopyRecordNodePtr; +struct CopyStructureNode; +typedef std::tr1::shared_ptr CopyStructureNodePtr; + + +class PVCopy : + public std::tr1::enable_shared_from_this +{ +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 ©PVStructure, + epics::pvData::BitSetPtr const &bitSet, + bool lockRecord); + void updateCopySetBitSet( + epics::pvData::PVStructurePtr const ©PVStructure, + epics::pvData::BitSetPtr const &bitSet, + bool lockRecord); + void updateCopyFromBitSet( + epics::pvData::PVStructurePtr const ©PVStructure, + epics::pvData::BitSetPtr const &bitSet, + bool lockRecord); + void updateRecord( + epics::pvData::PVStructurePtr const ©PVStructure, + epics::pvData::BitSetPtr const &bitSet, + bool lockRecord); + PVCopyMonitorPtr createPVCopyMonitor( + PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester); + epics::pvData::PVStructurePtr getOptions( + epics::pvData::PVStructurePtr const ©PVStructure,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 ©PVField, + PVRecordFieldPtr const &recordPVField); + void makeShared( + epics::pvData::PVFieldPtr const ©PVField, + 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 +{ +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 +{ +public: + POINTER_DEFINITIONS(PVCopyMonitorRequester); + virtual void dataChanged() = 0; + virtual void unlisten() = 0; +private: + PVCopyMonitorRequesterPtr getPtrSelf() + { + return shared_from_this(); + } +}; + + +#ifdef MUSTIMPLEMENT +template +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 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 SharePVBooleanArray; +typedef SharePVScalarArray SharePVByteArray; +typedef SharePVScalarArray SharePVShortArray; +typedef SharePVScalarArray SharePVIntArray; +typedef SharePVScalarArray SharePVLongArray; +typedef SharePVScalarArray SharePVFloatArray; +typedef SharePVScalarArray SharePVDoubleArray; +typedef SharePVScalarArray 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 */ diff --git a/src/pvAccess/pvShare.cpp b/src/pvAccess/pvShare.cpp new file mode 100644 index 0000000..f24dd19 --- /dev/null +++ b/src/pvAccess/pvShare.cpp @@ -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 +#include +#include + +#include +#include + +#include +#include +#include + +namespace epics { namespace pvIOC { + +using namespace epics::pvData; + +template +SharePVScalarArray::SharePVScalarArray( + PVRecordField &pvRecordField, + epics::pvData::PVStructure *parent, + epics::pvData::PVScalarArray &pvShare) +: PVField(parent,pvShare.getField()), + pvRecordField(pvRecordField) +{ +} + +template +SharePVScalarArray::~SharePVScalarArray() +{ +} + +template +void SharePVScalarArray::lockShare() const +{ + pvRecordField.getPVRecord().lock(); +} + +template +void SharePVScalarArray::unlockShare() const +{ + pvRecordField.getPVRecord().unlock(); +} + +template +void SharePVScalarArray::message(String message,MessageType messageType) +{ + pvRecordField.message(message,messageType); +} + +template +void SharePVScalarArray::setImmutable() +{ + lockShare(); + try { + pvRecordField.getPVField().setImmutable(); + unlockShare(); + } catch(...) { + unlockShare(); + throw; + } +} + +template +bool SharePVScalarArray::isImmutable() +{ + return pvRecordField.getPVField().isImmutable(); +} + +template +void SharePVScalarArray::setCapacityMutable(bool isMutable) +{ + lockShare(); + try { + PVArray &pvArray = static_cast(pvRecordField.getPVField()); + pvArray.setCapacityMutable(isMutable); + unlockShare(); + } catch(...) { + unlockShare(); + throw; + } +} + +template +bool SharePVScalarArray::isCapacityMutable() +{ + PVArray &pvArray = static_cast(pvRecordField.getPVField()); + return pvArray.isCapacityMutable(); +} + +template +void SharePVScalarArray::setCapacity(int capacity) +{ + PVArray &pvArray = static_cast(pvRecordField.getPVField()); + lockShare(); + try { + pvArray.setCapacity(capacity); + unlockShare(); + } catch(...) { + unlockShare(); + throw; + } +} + +template +void SharePVScalarArray::setLength(int length) +{ + PVArray &pvArray = static_cast(pvRecordField.getPVField()); + lockShare(); + try { + pvArray.setLength(length); + unlockShare(); + } catch(...) { + unlockShare(); + throw; + } +} + +template +int SharePVScalarArray::getCapacity() const +{ + PVArray &pvArray = static_cast(pvRecordField.getPVField()); + return pvArray.getCapacity(); +} + +template +int SharePVScalarArray::getLength() const +{ + PVArray &pvArray = static_cast(pvRecordField.getPVField()); + return pvArray.getLength(); +} + +template +int SharePVScalarArray::get(int offset, int length, ArrayDataType *data) +{ + class PVValueArray &pvArray = static_cast &>( + pvRecordField.getPVField()); + lockShare(); + try { + return pvArray.get(offset,length,data); + unlockShare(); + } catch(...) { + unlockShare(); + throw; + } +} + +template +int SharePVScalarArray::put( + int offset,int length, pointer from, int fromOffset) +{ + class PVValueArray &pvArray = static_cast &>( + 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 +void SharePVScalarArray::shareData(pointer value,int capacity,int length) +{ + class PVValueArray &pvArray = static_cast &>( + pvRecordField.getPVField()); + lockShare(); + try { + pvArray.setImmutable(value,capacity,length); + unlockShare(); + } catch(...) { + unlockShare(); + throw; + } +} + +template +bool SharePVScalarArray::equals(PVField &pv) +{ + lockShare(); + try { + return pvRecordField.getPVField().equals(pv); + unlockShare(); + } catch(...) { + unlockShare(); + throw; + } +} + +template +void SharePVScalarArray::serialize( + ByteBuffer *pbuffer,SerializableControl *pflusher) const +{ + serialize(pbuffer, pflusher, 0, getLength()); +} + +template +void SharePVScalarArray::deserialize( + ByteBuffer *pbuffer,DeserializableControl *pflusher) +{ + class PVValueArray &pvArray = static_cast &>( + pvRecordField.getPVField()); + lockShare(); + try { + pvArray.deserialize(pbuffer,pflusher); + unlockShare(); + } catch(...) { + unlockShare(); + throw; + } +} + +template +void SharePVScalarArray::serialize( + ByteBuffer *pbuffer,SerializableControl *pflusher,int offset,int count) const +{ + class PVValueArray &pvArray = static_cast &>( + pvRecordField.getPVField()); + lockShare(); + try { + pvArray.serialize(pbuffer,pflusher,offset,count); + unlockShare(); + } catch(...) { + unlockShare(); + throw; + } +} + +}} diff --git a/src/pvAccess/pvShareStructureArray.cpp b/src/pvAccess/pvShareStructureArray.cpp new file mode 100644 index 0000000..451680f --- /dev/null +++ b/src/pvAccess/pvShareStructureArray.cpp @@ -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 +#include +#include + +#include +#include + +#include +#include +#include + +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( + 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(pvRecordField.getPVField()); + pvArray.setCapacityMutable(isMutable); + unlockShare(); + } catch(...) { + unlockShare(); + throw; + } +} + +bool SharePVStructureArray::isCapacityMutable() +{ + PVArray &pvArray = static_cast(pvRecordField.getPVField()); + return pvArray.isCapacityMutable(); +} + +void SharePVStructureArray::setCapacity(int capacity) +{ + PVArray &pvArray = static_cast(pvRecordField.getPVField()); + lockShare(); + try { + pvArray.setCapacity(capacity); + unlockShare(); + } catch(...) { + unlockShare(); + throw; + } +} + +void SharePVStructureArray::setLength(int length) +{ + PVArray &pvArray = static_cast(pvRecordField.getPVField()); + lockShare(); + try { + pvArray.setLength(length); + unlockShare(); + } catch(...) { + unlockShare(); + throw; + } +} + +int SharePVStructureArray::getCapacity() const +{ + PVArray &pvArray = static_cast(pvRecordField.getPVField()); + return pvArray.getCapacity(); +} + +int SharePVStructureArray::getLength() const +{ + PVArray &pvArray = static_cast(pvRecordField.getPVField()); + return pvArray.getLength(); +} + +int SharePVStructureArray::get(int offset, int length, StructureArrayData *data) +{ + class PVStructureArray &pvArray = static_cast( + 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( + 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( + 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( + pvRecordField.getPVField()); + lockShare(); + try { + pvArray.serialize(pbuffer,pflusher,offset,count); + unlockShare(); + } catch(...) { + unlockShare(); + throw; + } +} + +}} diff --git a/test/Makefile b/test/Makefile index 13120fd..88b61c1 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,5 +1,6 @@ TOP = .. include $(TOP)/configure/CONFIG DIRS += record +DIRS += pvCopy include $(TOP)/configure/RULES_DIRS diff --git a/test/pvCopy/Makefile b/test/pvCopy/Makefile new file mode 100644 index 0000000..de1fb0f --- /dev/null +++ b/test/pvCopy/Makefile @@ -0,0 +1,12 @@ +TOP=../.. + +include $(TOP)/configure/CONFIG + +PROD_HOST += testPVCopy +testPVCopy_SRCS += testPVCopy.cpp +testPVCopy_LIBS += pvDatabase pvAccess pvData Com + +include $(TOP)/configure/RULES +#---------------------------------------- +# ADD RULES AFTER THIS LINE + diff --git a/test/pvCopy/testPVCopy.cpp b/test/pvCopy/testPVCopy.cpp new file mode 100644 index 0000000..8d7f206 --- /dev/null +++ b/test/pvCopy/testPVCopy.cpp @@ -0,0 +1,409 @@ +/*testPVCopyMain.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 + */ + +/* Author: Marty Kraimer */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +using namespace std; +using std::tr1::static_pointer_cast; +using namespace epics::pvData; +using namespace epics::pvAccess; +using namespace epics::pvDatabase; + + +class MyRequester; +typedef std::tr1::shared_ptr MyRequesterPtr; + +class MyRequester : public Requester { +public: + POINTER_DEFINITIONS(MyRequester); + MyRequester(String const &requesterName) + : requesterName(requesterName) + {} + virtual ~MyRequester() {} + virtual String getRequesterName() { return requesterName;} + virtual void message(String const & message,MessageType messageType) + { + cout << message << endl; + } +private: + String requesterName; +}; + +static PVRecordPtr createScalar( + String const & recordName, + ScalarType scalarType, + String const & properties) +{ + PVStructurePtr pvStructure = getStandardPVField()->scalar(scalarType,properties); + return PVRecord::create(recordName,pvStructure); +} + +static PVRecordPtr createScalarArray( + String const & recordName, + ScalarType scalarType, + String const & properties) +{ + PVStructurePtr pvStructure = getStandardPVField()->scalarArray(scalarType,properties); + return PVRecord::create(recordName,pvStructure); +} + +static PowerSupplyRecordTestPtr createPowerSupply(String const & recordName) +{ + FieldCreatePtr fieldCreate = getFieldCreate(); + StandardFieldPtr standardField = getStandardField(); + PVDataCreatePtr pvDataCreate = getPVDataCreate(); + size_t nfields = 5; + StringArray names; + names.reserve(nfields); + FieldConstPtrArray powerSupply; + powerSupply.reserve(nfields); + names.push_back("alarm"); + powerSupply.push_back(standardField->alarm()); + names.push_back("timeStamp"); + powerSupply.push_back(standardField->timeStamp()); + String properties("alarm,display"); + names.push_back("voltage"); + powerSupply.push_back(standardField->scalar(pvDouble,properties)); + names.push_back("power"); + powerSupply.push_back(standardField->scalar(pvDouble,properties)); + names.push_back("current"); + powerSupply.push_back(standardField->scalar(pvDouble,properties)); + return PowerSupplyRecordTest::create(recordName, + pvDataCreate->createPVStructure( + fieldCreate->createStructure(names,powerSupply))); +} + +static void testPVScalar( + String const & valueNameRecord, + String const & valueNameCopy, + PVRecordPtr const & pvRecord, + PVCopyPtr const & pvCopy) +{ + PVRecordFieldPtr pvRecordField; + PVStructurePtr pvStructureRecord; + PVStructurePtr pvStructureCopy; + PVFieldPtr pvField; + PVScalarPtr pvValueRecord; + PVScalarPtr pvValueCopy; + BitSetPtr bitSet; + String builder; + size_t offset; + ConvertPtr convert = getConvert(); + + pvRecord->lock_guard(); + cout << endl; + pvStructureRecord = pvRecord->getPVRecordStructure()->getPVStructure(); + pvField = pvStructureRecord->getSubField(valueNameRecord); + pvValueRecord = static_pointer_cast(pvField); + convert->fromDouble(pvValueRecord,.04); + StructureConstPtr structure = pvCopy->getStructure(); + builder.clear(); structure->toString(&builder); + cout << "structure from copy" << endl << builder << endl; + pvStructureCopy = pvCopy->createPVStructure(); + pvField = pvStructureCopy->getSubField(valueNameCopy); + pvValueCopy = static_pointer_cast(pvField); + bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields())); + pvCopy->initCopy(pvStructureCopy, bitSet, true); + cout << "after initCopy pvValueCopy " << convert->toDouble(pvValueCopy); + cout << endl; + convert->fromDouble(pvValueRecord,.06); + pvCopy->updateCopySetBitSet(pvStructureCopy,bitSet,true); + cout << "after put(.06) pvValueCopy " << convert->toDouble(pvValueCopy); + builder.clear(); + bitSet->toString(&builder); + cout << " bitSet " << builder; + cout << endl; + pvRecordField = pvRecord->findPVRecordField(pvValueRecord); + offset = pvCopy->getCopyOffset(pvRecordField); + cout << "getCopyOffset() " << offset; + cout << " pvValueCopy->getOffset() " << pvValueCopy->getFieldOffset(); + cout << " pvValueRecord->getOffset() " << pvValueRecord->getFieldOffset(); + cout << " bitSet " << builder; + cout << endl; + bitSet->clear(); + convert->fromDouble(pvValueRecord,1.0); + builder.clear(); + bitSet->toString(&builder); + cout << "before updateCopyFromBitSet"; + cout << " recordValue " << convert->toDouble(pvValueRecord); + cout << " copyValue " << convert->toDouble(pvValueCopy); + cout << " bitSet " << builder; + cout << endl; + bitSet->set(0); + pvCopy->updateCopyFromBitSet(pvStructureCopy,bitSet,true); + cout << "after updateCopyFromBitSet"; + cout << " recordValue " << convert->toDouble(pvValueRecord); + cout << " copyValue " << convert->toDouble(pvValueCopy); + cout << " bitSet " << builder; + cout << endl; + convert->fromDouble(pvValueCopy,2.0); + bitSet->set(0); + cout << "before updateRecord"; + cout << " recordValue " << convert->toDouble(pvValueRecord); + cout << " copyValue " << convert->toDouble(pvValueCopy); + cout << " bitSet " << builder; + cout << endl; + pvCopy->updateRecord(pvStructureCopy,bitSet,true); + cout << "after updateRecord"; + cout << " recordValue " << convert->toDouble(pvValueRecord); + cout << " copyValue " << convert->toDouble(pvValueCopy); + cout << " bitSet " << builder; + cout << endl; +} + +static void testPVScalarArray( + ScalarType scalarType, + String const & valueNameRecord, + String const & valueNameCopy, + PVRecordPtr const & pvRecord, + PVCopyPtr const & pvCopy) +{ + PVRecordFieldPtr pvRecordField; + PVStructurePtr pvStructureRecord; + PVStructurePtr pvStructureCopy; + PVScalarArrayPtr pvValueRecord; + PVScalarArrayPtr pvValueCopy; + BitSetPtr bitSet; + String builder; + size_t offset; + ConvertPtr convert = getConvert(); + size_t n = 5; + DoubleArray values(n); + + pvRecord->lock_guard(); + cout << endl; + pvStructureRecord = pvRecord->getPVRecordStructure()->getPVStructure(); + pvValueRecord = pvStructureRecord->getScalarArrayField(valueNameRecord,scalarType); + for(size_t i=0; ifromDoubleArray(pvValueRecord,0,n,get(values),0); + StructureConstPtr structure = pvCopy->getStructure(); + builder.clear(); structure->toString(&builder); + cout << "structure from copy" << endl << builder << endl; + pvStructureCopy = pvCopy->createPVStructure(); + pvValueCopy = pvStructureCopy->getScalarArrayField(valueNameCopy,scalarType); + bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields())); + pvCopy->initCopy(pvStructureCopy, bitSet, true); + builder.clear(); pvValueCopy->toString(&builder); + cout << "after initCopy pvValueCopy " << builder << endl; + cout << endl; + for(size_t i=0; ifromDoubleArray(pvValueRecord,0,n,get(values),0); + pvCopy->updateCopySetBitSet(pvStructureCopy,bitSet,true); + builder.clear(); pvValueCopy->toString(&builder); + cout << "after put(i+ .06) pvValueCopy " << builder << endl; + builder.clear(); + bitSet->toString(&builder); + cout << " bitSet " << builder; + cout << endl; + pvRecordField = pvRecord->findPVRecordField(pvValueRecord); + offset = pvCopy->getCopyOffset(pvRecordField); + cout << "getCopyOffset() " << offset; + cout << " pvValueCopy->getOffset() " << pvValueCopy->getFieldOffset(); + cout << " pvValueRecord->getOffset() " << pvValueRecord->getFieldOffset(); + cout << " bitSet " << builder; + cout << endl; + bitSet->clear(); + for(size_t i=0; ifromDoubleArray(pvValueRecord,0,n,get(values),0); + builder.clear(); + bitSet->toString(&builder); + cout << "before updateCopyFromBitSet"; + builder.clear(); pvValueRecord->toString(&builder); + cout << " recordValue " << builder << endl; + builder.clear(); pvValueCopy->toString(&builder); + cout << " copyValue " << builder << endl; + cout << " bitSet " << builder; + cout << endl; + bitSet->set(0); + pvCopy->updateCopyFromBitSet(pvStructureCopy,bitSet,true); + cout << "after updateCopyFromBitSet"; + builder.clear(); pvValueRecord->toString(&builder); + cout << " recordValue " << builder << endl; + builder.clear(); pvValueCopy->toString(&builder); + cout << " copyValue " << builder << endl; + cout << " bitSet " << builder; + cout << endl; + for(size_t i=0; ifromDoubleArray(pvValueRecord,0,n,get(values),0); + bitSet->set(0); + cout << "before updateRecord"; + builder.clear(); pvValueRecord->toString(&builder); + cout << " recordValue " << builder << endl; + builder.clear(); pvValueCopy->toString(&builder); + cout << " copyValue " << builder << endl; + cout << " bitSet " << builder; + cout << endl; + pvCopy->updateRecord(pvStructureCopy,bitSet,true); + cout << "after updateRecord"; + builder.clear(); pvValueRecord->toString(&builder); + cout << " recordValue " << builder << endl; + builder.clear(); pvValueCopy->toString(&builder); + cout << " copyValue " << builder << endl; + cout << " bitSet " << builder; + cout << endl; +} + +static void scalarTest() +{ + cout << endl << endl << "****scalarTest****" << endl; + RequesterPtr requester(new MyRequester("exampleTest")); + PVRecordPtr pvRecord; + String request; + PVStructurePtr pvRequest; + PVRecordFieldPtr pvRecordField; + PVCopyPtr pvCopy; + String builder; + String valueNameRecord; + String valueNameCopy; + + pvRecord = createScalar("doubleRecord",pvDouble,"alarm,timeStamp,display"); + valueNameRecord = request = "value"; + pvRequest = getCreateRequest()->createRequest(request,requester); + builder.clear(); pvRequest->toString(&builder); + cout << "request " << request << endl; + cout << "pvRequest" << endl << builder; + pvCopy = PVCopy::create(pvRecord,pvRequest,""); + valueNameCopy = "value"; + testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy); + request = ""; + valueNameRecord = "value"; + pvRequest = getCreateRequest()->createRequest(request,requester); + builder.clear(); pvRequest->toString(&builder); + cout << "request " << request << endl << "pvRequest" << endl << builder << endl; + pvCopy = PVCopy::create(pvRecord,pvRequest,""); + valueNameCopy = "value"; + testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy); + request = "alarm,timeStamp,value"; + valueNameRecord = "value"; + pvRequest = getCreateRequest()->createRequest(request,requester); + builder.clear(); pvRequest->toString(&builder); + cout << "request " << request << endl << "pvRequest" << endl << builder << endl; + pvCopy = PVCopy::create(pvRecord,pvRequest,""); + valueNameCopy = "value"; + testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy); +} + +static void arrayTest() +{ + cout << endl << endl << "****arrayTest****" << endl; + RequesterPtr requester(new MyRequester("exampleTest")); + PVRecordPtr pvRecord; + String request; + PVStructurePtr pvRequest; + PVRecordFieldPtr pvRecordField; + PVCopyPtr pvCopy; + String builder; + String valueNameRecord; + String valueNameCopy; + + pvRecord = createScalarArray("doubleArrayRecord",pvDouble,"alarm,timeStamp"); + valueNameRecord = request = "value"; + pvRequest = getCreateRequest()->createRequest(request,requester); + builder.clear(); pvRequest->toString(&builder); + cout << "request " << request << endl; + cout << "pvRequest" << endl << builder; + pvCopy = PVCopy::create(pvRecord,pvRequest,""); + valueNameCopy = "value"; + testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy); + request = ""; + valueNameRecord = "value"; + pvRequest = getCreateRequest()->createRequest(request,requester); + builder.clear(); pvRequest->toString(&builder); + cout << "request " << request << endl << "pvRequest" << endl << builder << endl; + pvCopy = PVCopy::create(pvRecord,pvRequest,""); + valueNameCopy = "value"; + testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy); + request = "alarm,timeStamp,value"; + valueNameRecord = "value"; + pvRequest = getCreateRequest()->createRequest(request,requester); + builder.clear(); pvRequest->toString(&builder); + cout << "request " << request << endl << "pvRequest" << endl << builder << endl; + pvCopy = PVCopy::create(pvRecord,pvRequest,""); + valueNameCopy = "value"; + testPVScalarArray(pvDouble,valueNameRecord,valueNameCopy,pvRecord,pvCopy); +} + +static void powerSupplyTest() +{ + cout << endl << endl << "****powerSupplyTest****" << endl; + RequesterPtr requester(new MyRequester("exampleTest")); + PowerSupplyRecordTestPtr pvRecord; + String request; + PVStructurePtr pvRequest; + PVRecordFieldPtr pvRecordField; + PVCopyPtr pvCopy; + String builder; + String valueNameRecord; + String valueNameCopy; + + pvRecord = createPowerSupply("powerSupply"); + valueNameRecord = request = "power.value"; + pvRequest = getCreateRequest()->createRequest(request,requester); + builder.clear(); pvRequest->toString(&builder); + cout << "request " << request << endl; + cout << "pvRequest" << endl << builder; + pvCopy = PVCopy::create(pvRecord,pvRequest,""); + valueNameCopy = "value"; + testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy); + request = ""; + valueNameRecord = "power.value"; + pvRequest = getCreateRequest()->createRequest(request,requester); + builder.clear(); pvRequest->toString(&builder); + cout << "request " << request << endl << "pvRequest" << endl << builder << endl; + pvCopy = PVCopy::create(pvRecord,pvRequest,""); + valueNameCopy = "power.value"; + testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy); + request = "alarm,timeStamp,voltage.value,power.value,current.value"; + valueNameRecord = "power.value"; + pvRequest = getCreateRequest()->createRequest(request,requester); + builder.clear(); pvRequest->toString(&builder); + cout << "request " << request << endl << "pvRequest" << endl << builder << endl; + pvCopy = PVCopy::create(pvRecord,pvRequest,""); + valueNameCopy = "power"; + testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy); + request = "alarm,timeStamp,voltage{value,alarm},power{value,alarm,display},current.value"; + valueNameRecord = "power.value"; + pvRequest = getCreateRequest()->createRequest(request,requester); + builder.clear(); pvRequest->toString(&builder); + cout << "request " << request << endl << "pvRequest" << endl << builder << endl; + pvCopy = PVCopy::create(pvRecord,pvRequest,""); + valueNameCopy = "power.value"; + testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy); +} + +int main(int argc,char *argv[]) +{ + scalarTest(); + arrayTest(); + powerSupplyTest(); + return 0; +} + diff --git a/test/record/Makefile b/test/record/Makefile index 2082688..0ee6714 100644 --- a/test/record/Makefile +++ b/test/record/Makefile @@ -2,10 +2,10 @@ TOP=../.. include $(TOP)/configure/CONFIG -PROD_HOST += testRecord -testRecord_SRCS += testRecord.cpp -testRecord_SRCS += testRecordMain.cpp -testRecord_LIBS += pvDatabase pvAccess pvData Com +PROD_HOST += testExampleRecord +testExampleRecord_SRCS += testExampleRecordMain.cpp +testExampleRecord_LIBS += pvDatabase pvAccess pvData Com + include $(TOP)/configure/RULES #---------------------------------------- diff --git a/test/record/testExampleRecordMain.cpp b/test/record/testExampleRecordMain.cpp new file mode 100644 index 0000000..4ce0502 --- /dev/null +++ b/test/record/testExampleRecordMain.cpp @@ -0,0 +1,126 @@ +/*testExampleRecordMain.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 + */ + +/* Author: Marty Kraimer */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +using namespace std; +using std::tr1::static_pointer_cast; +using namespace epics::pvData; +using namespace epics::pvAccess; +using namespace epics::pvDatabase; + + +static PVStructurePtr createPowerSupply() +{ + FieldCreatePtr fieldCreate = getFieldCreate(); + StandardFieldPtr standardField = getStandardField(); + PVDataCreatePtr pvDataCreate = getPVDataCreate(); + size_t nfields = 5; + StringArray names; + names.reserve(nfields); + FieldConstPtrArray powerSupply; + powerSupply.reserve(nfields); + names.push_back("alarm"); + powerSupply.push_back(standardField->alarm()); + names.push_back("timeStamp"); + powerSupply.push_back(standardField->timeStamp()); + String properties("alarm,display"); + names.push_back("voltage"); + powerSupply.push_back(standardField->scalar(pvDouble,properties)); + names.push_back("power"); + powerSupply.push_back(standardField->scalar(pvDouble,properties)); + names.push_back("current"); + powerSupply.push_back(standardField->scalar(pvDouble,properties)); + return pvDataCreate->createPVStructure( + fieldCreate->createStructure(names,powerSupply)); +} + + +int main(int argc,char *argv[]) +{ + StandardPVFieldPtr standardPVField = getStandardPVField(); + String properties; + ScalarType scalarType; + String recordName; + properties = "alarm,timeStamp"; + scalarType = pvDouble; + recordName = "exampleDouble"; + PVStructurePtr pvStructure; + pvStructure = standardPVField->scalar(scalarType,properties); + PVRecordPtr pvRecord = PVRecord::create(recordName,pvStructure); + { + pvRecord->lock_guard(); + pvRecord->process(); + } + cout << "processed exampleDouble " << endl; + recordName = "powerSupplyExample"; + pvStructure.reset(); + pvStructure = createPowerSupply(); + PowerSupplyRecordTestPtr psr = + PowerSupplyRecordTest::create(recordName,pvStructure); + if(psr.get()==NULL) { + cout << "PowerSupplyRecordTest::create failed" << endl; + return 1; + } + double voltage,power,current; + { + psr->lock_guard(); + voltage = psr->getVoltage(); + power = psr->getPower(); + current = psr->getCurrent(); + } + cout << "initial "; + cout << " voltage " << voltage ; + cout << " power " << power; + cout << " current " << current; + cout << endl; + voltage = 1.0; + power = 1.0; + cout << "before put "; + cout << " voltage " << voltage ; + cout << " power " << power; + cout << endl; + { + psr->lock_guard(); + psr->put(power,voltage); + psr->process(); + } + { + psr->lock_guard(); + cout << "after put "; + cout << " voltage " << psr->getVoltage() ; + cout << " power " << psr->getPower(); + cout << " current " << psr->getCurrent(); + cout << endl; + } + return 0; +} + diff --git a/test/record/testRecord.cpp b/test/record/testRecord.cpp deleted file mode 100644 index 5db2121..0000000 --- a/test/record/testRecord.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* testRecord.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 - */ -/* Marty Kraimer 2011.03 */ -/* This connects to a V3 record and presents the data as a PVStructure - * It provides access to value, alarm, display, and control. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include "testRecord.h" - - -namespace epics { namespace pvDatabase { - -using namespace epics::pvData; -using namespace epics::pvAccess; -using std::tr1::static_pointer_cast; - -TestRecord::~TestRecord(){} - -PVRecordPtr TestRecord::create( - String const & recordName) -{ - String properties("alarm,timeStamp,display,control,valueAlarm"); - PVStructurePtr pvStructure = getStandardPVField()->scalar(pvLong,properties); - PVLongPtr pvValue = pvStructure->getLongField("value"); - TestRecordPtr pvRecord( - new TestRecord(recordName,pvStructure,pvValue)); - pvRecord->init(); - PVFieldPtr pvField = pvStructure->getSubField("display.description"); - pvRecord->immediatePutOK = pvField; - return pvRecord; -} - -TestRecord::TestRecord( - String const & recordName, - PVStructurePtr const & pvStructure, - PVLongPtr const &pvValue) -: PVRecord(recordName,pvStructure), - pvValue(pvValue) -{} - -void TestRecord::process( - RecordProcessRequesterPtr const &processRequester,bool alreadyLocked) -{ - if(!alreadyLocked) lock(); - pvValue->put(pvValue->get() + 1); - processRequester->recordProcessResult(Status::Ok); - unlock(); - processRequester->recordProcessComplete(); - dequeueProcessRequest(processRequester); -} - -bool TestRecord::isSynchronous() {return true;} - -void TestRecord::destroy() -{ - PVRecord::destroy(); - pvValue.reset(); - immediatePutOK.reset(); -} - -bool TestRecord::requestImmediatePut(PVFieldPtr const &pvField) -{ - if(pvField!=immediatePutOK) return false; - lock(); - return true; -} - -void TestRecord::immediatePutDone() -{ - unlock(); -} - -}} - diff --git a/test/record/testRecord.h b/test/record/testRecord.h deleted file mode 100644 index 2d5446f..0000000 --- a/test/record/testRecord.h +++ /dev/null @@ -1,50 +0,0 @@ -/* testRecord.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 - */ -#ifndef TEST_RECORD_H -#define TEST_RECORD_H -#include -#include -#include -#include - -#include - -namespace epics { namespace pvDatabase { - -class TestRecord; -typedef std::tr1::shared_ptr TestRecordPtr; - -class TestRecord : - public virtual PVRecord -{ -public: - POINTER_DEFINITIONS(TestRecord); - static PVRecordPtr create( - epics::pvData::String const & recordName); - virtual ~TestRecord(); - virtual void process( - epics::pvDatabase::RecordProcessRequesterPtr const &processRequester, - bool alreadyLocked); - virtual bool isSynchronous(); - virtual void destroy(); - virtual bool requestImmediatePut(epics::pvData::PVFieldPtr const &pvField); - virtual void immediatePutDone(); -private: - TestRecord(epics::pvData::String const & recordName, - epics::pvData::PVStructurePtr const & pvStructure, - epics::pvData::PVLongPtr const &pvValue); - - epics::pvData::PVLongPtr pvValue; - epics::pvData::PVFieldPtr immediatePutOK; -}; - -}} - -#endif /* TEST_RECORD_H */ diff --git a/test/record/testRecordMain.cpp b/test/record/testRecordMain.cpp deleted file mode 100644 index 550b479..0000000 --- a/test/record/testRecordMain.cpp +++ /dev/null @@ -1,378 +0,0 @@ -/*testRecordMain.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 - */ - -/* Author: Marty Kraimer */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "testRecord.h" - -using namespace std; -using std::tr1::static_pointer_cast; -using namespace epics::pvData; -using namespace epics::pvAccess; -using namespace epics::pvDatabase; - -class MyPVListener; -typedef std::tr1::shared_ptr MyPVListenerPtr; - -class MyProcessRequester; -typedef std::tr1::shared_ptr MyProcessRequesterPtr; - -class MyPutRequester; -typedef std::tr1::shared_ptr MyPutRequesterPtr; - -class MyPVListener : - public PVListener, - public std::tr1::enable_shared_from_this -{ -public: - POINTER_DEFINITIONS(PVListener); - static MyPVListenerPtr create( - String const & requesterName, - PVRecordPtr const & pvRecord, - PVRecordFieldPtr const &pvRecordField) - { - MyPVListenerPtr pvPVListener( - new MyPVListener(requesterName,pvRecord,pvRecordField)); - pvPVListener->init(); - return pvPVListener; - } - virtual ~MyPVListener() {} - virtual void detach(PVRecordPtr const & pvRecord) - { - printf("%s MyPVListener::detach\n",requesterName.c_str()); - } - virtual void dataPut(PVRecordFieldPtr const & pvRecordField) - { - String fieldName = pvRecordField->getFullFieldName(); - printf("%s dataPut(requested(%s))\n", - requesterName.c_str(), - fieldName.c_str()); - } - virtual void dataPut( - PVRecordStructurePtr const & requested, - PVRecordFieldPtr const & pvRecordField) - { - String requestedName = requested->getFullFieldName(); - String fieldName = pvRecordField->getFullFieldName(); - printf("%s dataPut(requested(%s),pvRecordField(%s))\n", - requesterName.c_str(), - requestedName.c_str(), - fieldName.c_str()); - } - virtual void beginGroupPut(PVRecordPtr const & pvRecord) - { - printf("beginGroupPut\n"); - } - virtual void endGroupPut(PVRecordPtr const & pvRecord) - { - printf("endGroupPut\n"); - } - virtual void unlisten(PVRecordPtr const & pvRecord) - { - printf("unlisten\n"); - } -private: - MyPVListenerPtr getPtrSelf() - { - return shared_from_this(); - } - - MyPVListener( - String const & requesterName, - PVRecordPtr const & pvRecord, - PVRecordFieldPtr const &pvRecordField) - : isDetached(false), - requesterName(requesterName), - pvRecord(pvRecord), - pvRecordField(pvRecordField) - {} - void init() { - pvRecord->addPVRecordClient(getPtrSelf()); - pvRecord->addListener(getPtrSelf()); - pvRecordField->addListener(getPtrSelf()); - } - - bool isDetached; - String requesterName; - PVRecordPtr pvRecord; - PVRecordFieldPtr pvRecordField; -}; - -class MyProcessRequester : - public virtual Requester, - public virtual RecordProcessRequester, - public std::tr1::enable_shared_from_this -{ -public: - static MyProcessRequesterPtr create( - String const &requesterName, - PVRecordPtr const & pvRecord) - { - MyProcessRequesterPtr pvProcessRequester( - new MyProcessRequester(requesterName,pvRecord)); - pvProcessRequester->init(); - return pvProcessRequester; - } - bool process() - { - if(isDetached) { - message("process request but detached",errorMessage); - return false; - } - pvRecord->queueProcessRequest(getPtrSelf()); - event.wait(); - return true; - } - virtual ~MyProcessRequester() {} - virtual void detach(PVRecordPtr const & pvRecord) - { - isDetached = true; - message("detached",infoMessage); - } - virtual String getRequesterName() {return requesterName;} - virtual void message( - String const & message, - MessageType messageType) - { - String messageTypeName = getMessageTypeName(messageType); - printf("%s %s %s\n", - requesterName.c_str(), - message.c_str(), - messageTypeName.c_str()); - } - virtual void recordDestroyed() - { - printf("%s MyProcessRequester::recordDestroyed\n", - requesterName.c_str()); - } - virtual void becomeProcessor() - { - pvRecord->process(getPtrSelf(),false); - } - virtual void recordProcessResult(epics::pvData::Status status) - { - String xxx("recordProcessResult "); - message( xxx + status.getMessage(),infoMessage); - } - virtual void recordProcessComplete() - { - message("recordProcessComplete",infoMessage); - event.signal(); - } -private: - MyProcessRequesterPtr getPtrSelf() - { - return shared_from_this(); - } - - MyProcessRequester( - String const &requesterName, - PVRecordPtr const & pvRecord) - : isDetached(false), - requesterName(requesterName), - pvRecord(pvRecord) - {} - void init() { - pvRecord->addPVRecordClient(getPtrSelf()); - pvRecord->addRequester(getPtrSelf()); - } - - Event event; - bool isDetached; - String requesterName; - PVRecordPtr pvRecord; -}; - -class MyPutRequester : - public virtual RecordPutRequester, - public std::tr1::enable_shared_from_this -{ -public: - MyPutRequester(PVRecordPtr const & pvRecord) - : pvRecord(pvRecord), - result(false) - {} - virtual ~MyPutRequester() {} - virtual void requestResult(bool result) - { - this->result = result; - event.signal(); - } - bool makeRequest() - { - pvRecord->queuePutRequest(getPtrSelf()); - event.wait(); - return result; - } -private: - MyPutRequesterPtr getPtrSelf() - { - return shared_from_this(); - } - Event event; - PVRecordPtr pvRecord; - bool result; -}; - - - -void dumpPVRecordField(PVRecordFieldPtr pvRecordField) -{ - PVRecordStructurePtr pvRecordStructure = pvRecordField->getParent(); - PVFieldPtr pvField = pvRecordField->getPVField(); - String fieldName = pvField->getFieldName(); - String fullFieldName = pvRecordField->getFullFieldName(); - String fullName = pvRecordField->getFullName(); - PVRecordPtr pvRecord = pvRecordField->getPVRecord(); - String recordName = pvRecord->getRecordName(); - printf("recordName %s fullName %s fullFieldName %s fieldName %s\n", - recordName.c_str(), - fullName.c_str(), - fullFieldName.c_str(), - fieldName.c_str()); -} - -void dumpPVRecordStructure(PVRecordStructurePtr pvRecordStructure) -{ - dumpPVRecordField(pvRecordStructure); - PVRecordFieldPtrArrayPtr pvRecordFields = - pvRecordStructure->getPVRecordFields(); - size_t num = pvRecordFields->size(); - for(size_t i=0; igetPVField()->getField()->getType()==structure) { - PVRecordStructurePtr xxx = - static_pointer_cast(pvRecordField); - dumpPVRecordStructure(xxx); - } else { - dumpPVRecordField(pvRecordField); - } - } -} - -int main(int argc,char *argv[]) -{ - String recordName("testRecord"); - PVRecordPtr pvRecord = TestRecord::create(recordName); - dumpPVRecordStructure(pvRecord->getPVRecordStructure()); - PVStructurePtr pvStructure = - pvRecord->getPVRecordStructure()->getPVStructure(); - PVLongPtr pvValue = pvStructure->getLongField("value"); - String builder; - pvStructure->toString(&builder); - printf("pvStructure\n%s\n",builder.c_str()); - builder.clear(); - pvValue->toString(&builder); - printf("value\n%s\n",builder.c_str()); - PVRecordFieldPtr recordFieldValue = pvRecord->findPVRecordField(pvValue); - MyPVListenerPtr listenTop = MyPVListener::create( - "listenTop", pvRecord, pvRecord->getPVRecordStructure()); - MyPVListenerPtr listenValue = MyPVListener::create( - "listenValue", pvRecord,recordFieldValue); - - PVFieldPtr pvDisplay = pvStructure->getSubField("display"); - PVRecordFieldPtr recordFieldDisplay = - pvRecord->findPVRecordField(pvDisplay); - MyPVListenerPtr listenDisplay = MyPVListener::create( - "listenDisplay", pvRecord,recordFieldDisplay); - - PVStringPtr pvDisplayDescription = - pvStructure->getStringField("display.description"); - PVRecordFieldPtr recordFieldDisplayDescription = - pvRecord->findPVRecordField(pvDisplayDescription); - MyPVListenerPtr listenDisplayDescription = MyPVListener::create( - "listenDisplayDescription", pvRecord,recordFieldDisplayDescription); - - recordFieldDisplayDescription->message("test message",infoMessage); - - MyProcessRequesterPtr process1 = - MyProcessRequester::create("process1",pvRecord); - MyProcessRequesterPtr process2 = - MyProcessRequester::create("process2",pvRecord); - process1->process(); - builder.clear(); - pvValue->toString(&builder); - printf("%s\n",builder.c_str()); - process2->process(); - builder.clear(); - pvValue->toString(&builder); - printf("%s\n",builder.c_str()); - bool requestResult; - requestResult = pvRecord->requestImmediatePut(pvValue); - if(requestResult) { - printf("error requestImmediatePut for pvValue returned true"); - pvRecord->immediatePutDone(); - } - requestResult = pvRecord->requestImmediatePut(pvDisplayDescription); - if(!requestResult) { - printf("error requestImmediatePut for pvDisplayDescription returned false"); - } else { - pvDisplayDescription->put("this is description"); - pvRecord->immediatePutDone(); - } - - MyPutRequesterPtr myPut(new MyPutRequester(pvRecord)); - requestResult = myPut->makeRequest(); - if(!requestResult) { - printf("error myPut->makeRequest() returned false"); - } else { - pvDisplayDescription->put("this is new description"); - pvValue->put(1000); - PVIntPtr pvSeverity = pvStructure->getIntField("alarm.severity"); - pvSeverity->put(3); - PVIntPtr pvStatus = pvStructure->getIntField("alarm.status"); - pvStatus->put(2); - PVStringPtr pvMessage = pvStructure->getStringField("alarm.message"); - pvMessage->put("alarmMessage"); - pvRecord->putDone(myPut); - } - - builder.clear(); - pvStructure->toString(&builder); - printf("pvStructure\n%s\n",builder.c_str()); - builder.clear(); - - pvRecord->destroy(); - printf("all done\n"); -#ifdef XXXXXX - PVDatabasePtr pvDatabase = PVDatabase::getMaster(); - pvDatabase->addRecord(pvRecord); - cout << recordName << "\n"; - string str; - while(true) { - cout << "Type exit to stop: \n"; - getline(cin,str); - if(str.compare("exit")==0) break; - - } -#endif - return 0; -} -