interim commit. pvCopy how works
This commit is contained in:
5
Makefile
5
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
|
||||
|
||||
|
||||
|
@ -1,5 +0,0 @@
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
DIRS += record
|
||||
include $(TOP)/configure/RULES_DIRS
|
||||
|
@ -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
|
||||
|
@ -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 <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#include <pv/standardPVField.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
@ -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 <string>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
|
||||
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 */
|
@ -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 <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
#include <epicsStdio.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsEvent.h>
|
||||
#include <epicsThread.h>
|
||||
|
||||
#include <epicsExport.h>
|
||||
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvAccess.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
11
src/Makefile
11
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
|
||||
|
||||
|
188
src/database/powerSupplyRecordTest.h
Normal file
188
src/database/powerSupplyRecordTest.h
Normal file
@ -0,0 +1,188 @@
|
||||
/* powerSupplyRecordTest.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2013.04.02
|
||||
*/
|
||||
#ifndef POWERSUPPLYRECORDTEST_H
|
||||
#define POWERSUPPLYRECORDTEST_H
|
||||
|
||||
#include <pv/executor.h>
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/event.h>
|
||||
#include <pv/timer.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/alarm.h>
|
||||
#include <pv/pvTimeStamp.h>
|
||||
#include <pv/pvAlarm.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
|
||||
class PowerSupplyRecordTest;
|
||||
typedef std::tr1::shared_ptr<PowerSupplyRecordTest> PowerSupplyRecordTestPtr;
|
||||
|
||||
class PowerSupplyRecordTest :
|
||||
public PVRecord
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PowerSupplyRecordTest);
|
||||
static PowerSupplyRecordTestPtr create(
|
||||
epics::pvData::String const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure);
|
||||
virtual ~PowerSupplyRecordTest();
|
||||
virtual bool init();
|
||||
virtual void process();
|
||||
void put(double power,double voltage);
|
||||
double getPower();
|
||||
double getVoltage();
|
||||
double getCurrent();
|
||||
private:
|
||||
PowerSupplyRecordTest(epics::pvData::String const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure);
|
||||
epics::pvData::PVStructurePtr pvStructure;
|
||||
epics::pvData::PVDoublePtr pvCurrent;
|
||||
epics::pvData::PVDoublePtr pvPower;
|
||||
epics::pvData::PVDoublePtr pvVoltage;
|
||||
epics::pvData::PVAlarm pvAlarm;
|
||||
epics::pvData::PVTimeStamp pvTimeStamp;
|
||||
epics::pvData::Alarm alarm;
|
||||
epics::pvData::TimeStamp timeStamp;
|
||||
};
|
||||
|
||||
PowerSupplyRecordTestPtr PowerSupplyRecordTest::create(
|
||||
epics::pvData::String const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure)
|
||||
{
|
||||
PowerSupplyRecordTestPtr pvRecord(
|
||||
new PowerSupplyRecordTest(recordName,pvStructure));
|
||||
if(!pvRecord->init()) pvRecord.reset();
|
||||
return pvRecord;
|
||||
}
|
||||
|
||||
PowerSupplyRecordTest::PowerSupplyRecordTest(
|
||||
epics::pvData::String const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure)
|
||||
: PVRecord(recordName,pvStructure),
|
||||
pvStructure(pvStructure)
|
||||
{
|
||||
}
|
||||
|
||||
PowerSupplyRecordTest::~PowerSupplyRecordTest()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
bool PowerSupplyRecordTest::init()
|
||||
{
|
||||
initPVRecord();
|
||||
epics::pvData::PVFieldPtr pvField;
|
||||
bool result;
|
||||
pvField = pvStructure->getSubField("timeStamp");
|
||||
if(pvField.get()==NULL) {
|
||||
std::cerr << "no timeStamp" << std::endl;
|
||||
return false;
|
||||
}
|
||||
result = pvTimeStamp.attach(pvField);
|
||||
if(!result) {
|
||||
std::cerr << "no timeStamp" << std::endl;
|
||||
return false;
|
||||
}
|
||||
pvField = pvStructure->getSubField("alarm");
|
||||
if(pvField.get()==NULL) {
|
||||
std::cerr << "no alarm" << std::endl;
|
||||
return false;
|
||||
}
|
||||
result = pvAlarm.attach(pvField);
|
||||
if(!result) {
|
||||
std::cerr << "no alarm" << std::endl;
|
||||
return false;
|
||||
}
|
||||
epics::pvData::String name;
|
||||
name = "current.value";
|
||||
pvField = pvStructure->getSubField(name);
|
||||
if(pvField.get()==NULL) {
|
||||
name = "current";
|
||||
pvField = pvStructure->getSubField(name);
|
||||
}
|
||||
if(pvField.get()==NULL) {
|
||||
std::cerr << "no current" << std::endl;
|
||||
return false;
|
||||
}
|
||||
pvCurrent = pvStructure->getDoubleField(name);
|
||||
if(pvCurrent.get()==NULL) return false;
|
||||
name = "voltage.value";
|
||||
pvField = pvStructure->getSubField(name);
|
||||
if(pvField.get()==NULL) {
|
||||
name = "voltage";
|
||||
pvField = pvStructure->getSubField(name);
|
||||
}
|
||||
if(pvField.get()==NULL) {
|
||||
std::cerr << "no voltage" << std::endl;
|
||||
return false;
|
||||
}
|
||||
pvVoltage = pvStructure->getDoubleField(name);
|
||||
if(pvVoltage.get()==NULL) return false;
|
||||
name = "power.value";
|
||||
pvField = pvStructure->getSubField(name);
|
||||
if(pvField.get()==NULL) {
|
||||
name = "power";
|
||||
pvField = pvStructure->getSubField(name);
|
||||
}
|
||||
if(pvField.get()==NULL) {
|
||||
std::cerr << "no power" << std::endl;
|
||||
return false;
|
||||
}
|
||||
pvPower = pvStructure->getDoubleField(name);
|
||||
if(pvPower.get()==NULL) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PowerSupplyRecordTest::process()
|
||||
{
|
||||
timeStamp.getCurrent();
|
||||
pvTimeStamp.set(timeStamp);
|
||||
double voltage = pvVoltage->get();
|
||||
double power = pvPower->get();
|
||||
if(voltage<1e-3 && voltage>-1e-3) {
|
||||
alarm.setMessage("bad voltage");
|
||||
alarm.setSeverity(epics::pvData::majorAlarm);
|
||||
pvAlarm.set(alarm);
|
||||
return;
|
||||
}
|
||||
double current = power/voltage;
|
||||
pvCurrent->put(current);
|
||||
alarm.setMessage("");
|
||||
alarm.setSeverity(epics::pvData::noAlarm);
|
||||
pvAlarm.set(alarm);
|
||||
}
|
||||
|
||||
void PowerSupplyRecordTest::put(double power,double voltage)
|
||||
{
|
||||
pvPower->put(power);
|
||||
pvVoltage->put(voltage);
|
||||
}
|
||||
|
||||
double PowerSupplyRecordTest::getPower()
|
||||
{
|
||||
return pvPower->get();
|
||||
}
|
||||
|
||||
double PowerSupplyRecordTest::getVoltage()
|
||||
{
|
||||
return pvVoltage->get();
|
||||
}
|
||||
|
||||
double PowerSupplyRecordTest::getCurrent()
|
||||
{
|
||||
return pvCurrent->get();
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif /* POWERSUPPLYRECORDTEST_H */
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @data 2012.11.20
|
||||
* @date 2012.11.20
|
||||
*/
|
||||
#ifndef PVDATABASE_H
|
||||
#define PVDATABASE_H
|
||||
@ -36,33 +36,22 @@ typedef std::tr1::shared_ptr<PVRecordClient> PVRecordClientPtr;
|
||||
class PVListener;
|
||||
typedef std::tr1::shared_ptr<PVListener> PVListenerPtr;
|
||||
|
||||
class RecordProcessRequester;
|
||||
typedef std::tr1::shared_ptr<RecordProcessRequester> RecordProcessRequesterPtr;
|
||||
|
||||
class RecordPutRequester;
|
||||
typedef std::tr1::shared_ptr<RecordPutRequester> RecordPutRequesterPtr;
|
||||
|
||||
class PVDatabase;
|
||||
typedef std::tr1::shared_ptr<PVDatabase> PVDatabasePtr;
|
||||
|
||||
|
||||
class PVRecord :
|
||||
public epics::pvData::Requester,
|
||||
public std::tr1::enable_shared_from_this<PVRecord>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVRecord);
|
||||
static PVRecordPtr create(
|
||||
epics::pvData::String const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure);
|
||||
PVRecord(
|
||||
epics::pvData::String const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure);
|
||||
virtual ~PVRecord();
|
||||
virtual void process(
|
||||
RecordProcessRequesterPtr const &recordProcessRequester,
|
||||
bool alreadyLocked) = 0;
|
||||
virtual bool isSynchronous() = 0;
|
||||
virtual bool requestImmediatePut(
|
||||
epics::pvData::PVFieldPtr const &pvField);
|
||||
virtual void immediatePutDone();
|
||||
virtual void destroy();
|
||||
epics::pvData::String getRecordName();
|
||||
PVRecordStructurePtr getPVRecordStructure();
|
||||
@ -70,6 +59,7 @@ public:
|
||||
epics::pvData::PVFieldPtr const & pvField);
|
||||
bool addRequester(epics::pvData::RequesterPtr const & requester);
|
||||
bool removeRequester(epics::pvData::RequesterPtr const & requester);
|
||||
inline void lock_guard() { epics::pvData::Lock theLock(mutex); }
|
||||
void lock();
|
||||
void unlock();
|
||||
bool tryLock();
|
||||
@ -81,15 +71,7 @@ public:
|
||||
bool removeListener(PVListenerPtr const & pvListener);
|
||||
void beginGroupPut();
|
||||
void endGroupPut();
|
||||
void queueProcessRequest(
|
||||
RecordProcessRequesterPtr const &recordProcessRequester);
|
||||
void dequeueProcessRequest(
|
||||
RecordProcessRequesterPtr const &recordProcessRequester);
|
||||
void queuePutRequest(
|
||||
RecordPutRequesterPtr const &recordPutRequester);
|
||||
void putDone(
|
||||
RecordPutRequesterPtr const &recordPutRequester);
|
||||
virtual epics::pvData::String getRequesterName() {return getRecordName();}
|
||||
epics::pvData::String getRequesterName() {return getRecordName();}
|
||||
virtual void message(
|
||||
epics::pvData::String const & message,
|
||||
epics::pvData::MessageType messageType);
|
||||
@ -99,9 +81,11 @@ public:
|
||||
epics::pvData::MessageType messageType);
|
||||
void toString(epics::pvData::StringBuilder buf);
|
||||
void toString(epics::pvData::StringBuilder buf,int indentLevel);
|
||||
//init MUST be called after derived class is constructed
|
||||
void init();
|
||||
//init MUST be called by derived class after derived class is constructed
|
||||
virtual bool init() {initPVRecord(); return true;}
|
||||
virtual void process() {}
|
||||
protected:
|
||||
void initPVRecord();
|
||||
PVRecordPtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
@ -114,16 +98,12 @@ private:
|
||||
epics::pvData::PVStructurePtr pvStructure;
|
||||
epics::pvData::ConvertPtr convert;
|
||||
PVRecordStructurePtr pvRecordStructure;
|
||||
std::deque<RecordProcessRequesterPtr> processRequesterQueue;
|
||||
std::deque<RecordPutRequesterPtr> putRequesterQueue;
|
||||
std::list<PVListenerPtr> pvListenerList;
|
||||
std::list<PVRecordClientPtr> pvRecordClientList;
|
||||
std::list<epics::pvData::RequesterPtr> requesterList;
|
||||
epics::pvData::Mutex mutex;
|
||||
epics::pvData::Lock thelock;
|
||||
int depthGroupPut;
|
||||
bool processActive;
|
||||
bool putActive;
|
||||
std::size_t depthGroupPut;
|
||||
bool isDestroyed;
|
||||
};
|
||||
|
||||
@ -209,27 +189,6 @@ public:
|
||||
virtual void endGroupPut(PVRecordPtr const & pvRecord) = 0;
|
||||
};
|
||||
|
||||
class RecordProcessRequester :
|
||||
virtual public PVRecordClient,
|
||||
virtual public epics::pvData::Requester
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(RecordProcessRequester);
|
||||
virtual ~RecordProcessRequester() {}
|
||||
virtual void recordDestroyed() = 0;
|
||||
virtual void becomeProcessor() = 0;
|
||||
virtual void recordProcessResult(epics::pvData::Status status) = 0;
|
||||
virtual void recordProcessComplete() = 0;
|
||||
};
|
||||
|
||||
class RecordPutRequester
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(RecordPutRequester);
|
||||
virtual ~RecordPutRequester() {}
|
||||
virtual void requestResult(bool result) = 0;
|
||||
};
|
||||
|
||||
class PVDatabase : virtual public epics::pvData::Requester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVDatabase);
|
||||
|
@ -17,6 +17,19 @@ using namespace epics::pvAccess;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
PVRecordPtr PVRecord::create(
|
||||
String const &recordName,
|
||||
PVStructurePtr const & pvStructure)
|
||||
{
|
||||
PVRecordPtr pvRecord(new PVRecord(recordName,pvStructure));
|
||||
if(!pvRecord->init()) {
|
||||
pvRecord->destroy();
|
||||
pvRecord.reset();
|
||||
}
|
||||
return pvRecord;
|
||||
}
|
||||
|
||||
|
||||
PVRecord::PVRecord(
|
||||
String const & recordName,
|
||||
PVStructurePtr const & pvStructure)
|
||||
@ -25,14 +38,17 @@ PVRecord::PVRecord(
|
||||
convert(getConvert()),
|
||||
thelock(mutex),
|
||||
depthGroupPut(0),
|
||||
processActive(false),
|
||||
putActive(false),
|
||||
isDestroyed(false)
|
||||
{
|
||||
thelock.unlock();
|
||||
}
|
||||
|
||||
void PVRecord::init()
|
||||
PVRecord::~PVRecord()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void PVRecord::initPVRecord()
|
||||
{
|
||||
PVRecordStructurePtr parent;
|
||||
pvRecordStructure = PVRecordStructurePtr(
|
||||
@ -41,18 +57,13 @@ void PVRecord::init()
|
||||
pvStructure->setRequester(getPtrSelf());
|
||||
}
|
||||
|
||||
PVRecord::~PVRecord() {}
|
||||
|
||||
bool PVRecord::requestImmediatePut(PVFieldPtr const &pvField)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void PVRecord::immediatePutDone() {}
|
||||
|
||||
void PVRecord::destroy()
|
||||
{
|
||||
lock();
|
||||
if(isDestroyed) {
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
isDestroyed = true;
|
||||
|
||||
std::list<RequesterPtr>::iterator requesterIter;
|
||||
@ -74,28 +85,6 @@ void PVRecord::destroy()
|
||||
pvRecordClientList.clear();
|
||||
|
||||
pvListenerList.clear();
|
||||
|
||||
std::deque<RecordProcessRequesterPtr>::iterator processRequesterIter;
|
||||
for (
|
||||
processRequesterIter = processRequesterQueue.begin();
|
||||
processRequesterIter != processRequesterQueue.end();
|
||||
processRequesterIter++ )
|
||||
{
|
||||
(*processRequesterIter)->recordDestroyed();
|
||||
}
|
||||
processRequesterQueue.clear();
|
||||
|
||||
std::deque<RecordPutRequesterPtr>::iterator putRequesterIter;
|
||||
for (
|
||||
putRequesterIter = putRequesterQueue.begin();
|
||||
putRequesterIter != putRequesterQueue.end();
|
||||
putRequesterIter++ )
|
||||
{
|
||||
(*putRequesterIter)->requestResult(false);
|
||||
}
|
||||
putRequesterQueue.clear();
|
||||
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
@ -308,100 +297,6 @@ void PVRecord::endGroupPut()
|
||||
}
|
||||
}
|
||||
|
||||
void PVRecord::queueProcessRequest(
|
||||
RecordProcessRequesterPtr const &recordProcessRequester)
|
||||
{
|
||||
lock();
|
||||
if(isDestroyed) {
|
||||
unlock();
|
||||
recordProcessRequester->recordDestroyed();
|
||||
return;
|
||||
}
|
||||
bool isFirst = false;
|
||||
processRequesterQueue.push_back(recordProcessRequester);
|
||||
if(processRequesterQueue.size()==1 && !putActive) isFirst = true;
|
||||
unlock();
|
||||
if(isFirst) recordProcessRequester->becomeProcessor();
|
||||
}
|
||||
|
||||
void PVRecord::dequeueProcessRequest(
|
||||
RecordProcessRequesterPtr const &recordProcessRequester)
|
||||
{
|
||||
lock();
|
||||
if(isDestroyed) {
|
||||
unlock();
|
||||
recordProcessRequester->recordDestroyed();
|
||||
return;
|
||||
}
|
||||
RecordProcessRequesterPtr next;
|
||||
RecordProcessRequesterPtr processRequester =
|
||||
processRequesterQueue[0];
|
||||
if(processRequester.get()!=recordProcessRequester.get()) {
|
||||
message(
|
||||
"PVRecord::dequeueProcessRequest illegal requester",
|
||||
errorMessage);
|
||||
return;
|
||||
}
|
||||
processRequesterQueue.pop_front();
|
||||
if(putRequesterQueue.size() > 0) {
|
||||
RecordPutRequesterPtr putRequester = putRequesterQueue[0];
|
||||
processActive = false;
|
||||
putActive = true;
|
||||
putRequester->requestResult(true);
|
||||
return; // WITH LOCK HELD
|
||||
}
|
||||
if(processRequesterQueue.size()>0) next = processRequesterQueue[0];
|
||||
if(next.get()!=NULL) processActive = true;
|
||||
unlock();
|
||||
if(next.get()!=NULL) next->becomeProcessor();
|
||||
}
|
||||
|
||||
|
||||
void PVRecord::queuePutRequest(
|
||||
RecordPutRequesterPtr const &recordPutRequester)
|
||||
{
|
||||
lock();
|
||||
if(isDestroyed) {
|
||||
unlock();
|
||||
recordPutRequester->requestResult(false);
|
||||
return;
|
||||
}
|
||||
if(processRequesterQueue.size()==0 && !processActive) {
|
||||
putRequesterQueue.push_back(recordPutRequester);
|
||||
putActive = true;
|
||||
recordPutRequester->requestResult(true);
|
||||
return; // WITH lock held
|
||||
}
|
||||
putRequesterQueue.push_back(recordPutRequester);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void PVRecord::putDone(
|
||||
RecordPutRequesterPtr const &recordPutRequester)
|
||||
{
|
||||
// Note that this is called with lock held
|
||||
RecordPutRequesterPtr putRequester =
|
||||
putRequesterQueue[0];
|
||||
if(putRequester.get()!=recordPutRequester.get()) {
|
||||
message(
|
||||
"PVRecord::putDone illegal requester",
|
||||
errorMessage);
|
||||
return;
|
||||
}
|
||||
putRequesterQueue.pop_front();
|
||||
if(putRequesterQueue.size()>0){
|
||||
RecordPutRequesterPtr next = putRequesterQueue[0];
|
||||
next->requestResult(true);
|
||||
return; // WITH lock held
|
||||
}
|
||||
putActive = false;
|
||||
RecordProcessRequesterPtr next = processRequesterQueue[0];
|
||||
if(next.get()!=NULL) processActive = true;
|
||||
unlock();
|
||||
if(next.get()!=NULL) next->becomeProcessor();
|
||||
}
|
||||
|
||||
|
||||
void PVRecord::message(String const & message,MessageType messageType)
|
||||
{
|
||||
if(isDestroyed) return;
|
||||
|
38
src/pvAccess/monitorAlgorithm.h
Normal file
38
src/pvAccess/monitorAlgorithm.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* monitorAlgorithm.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/* Marty Kraimer 2011.03 */
|
||||
#ifndef MONITORALGORITHM_H
|
||||
#define MONITORALGORITHM_H
|
||||
#include <string>
|
||||
|
||||
#include <pv/pvData.h>
|
||||
|
||||
namespace epics { namespace pvIOC {
|
||||
|
||||
class MonitorAlgorithm {
|
||||
public:
|
||||
MonitorAlgorithm(){}
|
||||
virtual ~MonitorAlgorithm(){}
|
||||
virtual epics::pvData::String getAlgorithmName() = 0;
|
||||
virtual bool causeMonitor() = 0;
|
||||
void monitorIssued() = 0;
|
||||
}}
|
||||
|
||||
class MonitorAlgorithmCreate {
|
||||
public:
|
||||
virtual String getAlgorithmName() = 0;
|
||||
virtual std::auto_ptr<MonitorAlgorithm> create(
|
||||
PVRecord &pvRecord;
|
||||
MonitorRequester &requester;
|
||||
PVRecordField &pvRecordField;
|
||||
PVStructure &pvStructure);
|
||||
};
|
||||
|
||||
extern MonitorAlgorithmCreate& getAlgorithmDeadband();
|
||||
extern MonitorAlgorithmCreate& getAlgorithmOnChange();
|
||||
|
||||
#endif /* MONITORALGORITHM_H */
|
973
src/pvAccess/pvCopy.cpp
Normal file
973
src/pvAccess/pvCopy.cpp
Normal file
@ -0,0 +1,973 @@
|
||||
/* pvCopy.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#include <pv/pvCopy.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
using namespace epics::pvData;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::size_t;
|
||||
|
||||
static PVCopyPtr NULLPVCopy;
|
||||
static FieldConstPtr NULLField;
|
||||
static StructureConstPtr NULLStructure;
|
||||
static PVStructurePtr NULLPVStructure;
|
||||
static CopyNodePtr NULLCopyNodePtr;
|
||||
static CopyRecordNodePtr NULLCopyRecordNodePtr;
|
||||
|
||||
struct CopyNode {
|
||||
CopyNode()
|
||||
: isStructure(false),
|
||||
structureOffset(0),
|
||||
nfields(0),
|
||||
shareData(false)
|
||||
{}
|
||||
bool isStructure;
|
||||
size_t structureOffset; // In the copy
|
||||
size_t nfields;
|
||||
bool shareData;
|
||||
PVStructurePtr options;
|
||||
};
|
||||
|
||||
struct CopyRecordNode : public CopyNode{
|
||||
PVRecordFieldPtr recordPVField;
|
||||
};
|
||||
|
||||
typedef std::vector<CopyNodePtr> CopyNodePtrArray;
|
||||
typedef std::tr1::shared_ptr<CopyNodePtrArray> CopyNodePtrArrayPtr;
|
||||
|
||||
struct CopyStructureNode : public CopyNode {
|
||||
// CopyStructureNode(size_t numNodes)
|
||||
// : nodes(CopyNodePtrArrayPtr(new CopyNodePtrArray(numNodes)))
|
||||
// {
|
||||
// }
|
||||
CopyNodePtrArrayPtr nodes;
|
||||
};
|
||||
|
||||
PVCopyPtr PVCopy::create(
|
||||
PVRecordPtr const &pvRecord,
|
||||
PVStructurePtr const &pvRequest,
|
||||
String const & structureName)
|
||||
{
|
||||
if(structureName.size()>0) {
|
||||
if(pvRequest->getStructure()->getNumberFields()>0) {
|
||||
PVStructurePtr pvStructure
|
||||
= pvRequest->getStructureField(structureName);
|
||||
if(pvStructure.get()==NULL) return NULLPVCopy;
|
||||
}
|
||||
}
|
||||
PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvRecord));
|
||||
PVStructurePtr pvStruct = pvRequest;
|
||||
if(pvRequest->getSubField("field")!=NULL) {
|
||||
pvStruct = pvRequest->getStructureField("field");
|
||||
}
|
||||
bool result = pvCopy->init(pvStruct);
|
||||
if(!result) pvCopy.reset();
|
||||
return pvCopy;
|
||||
}
|
||||
|
||||
PVCopy::PVCopy(PVRecordPtr const &pvRecord)
|
||||
: pvRecord(pvRecord)
|
||||
{
|
||||
}
|
||||
|
||||
PVRecordPtr PVCopy::getPVRecord()
|
||||
{
|
||||
return pvRecord;
|
||||
}
|
||||
|
||||
StructureConstPtr PVCopy::getStructure()
|
||||
{
|
||||
return structure;
|
||||
}
|
||||
|
||||
PVStructurePtr PVCopy::createPVStructure()
|
||||
{
|
||||
if(cacheInitStructure.get()!=NULL) return cacheInitStructure;
|
||||
PVStructurePtr pvStructure =
|
||||
getPVDataCreate()->createPVStructure(structure);
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
size_t PVCopy::getCopyOffset(PVRecordFieldPtr const &recordPVField)
|
||||
{
|
||||
if(!headNode->isStructure) {
|
||||
CopyRecordNodePtr recordNode = static_pointer_cast<CopyRecordNode>(headNode);
|
||||
if((recordNode->recordPVField.get())==recordPVField.get()) {
|
||||
return headNode->structureOffset;
|
||||
}
|
||||
return String::npos;
|
||||
}
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
CopyRecordNodePtr recordNode = getCopyOffset(node,recordPVField);
|
||||
if(recordNode.get()!=NULL) return recordNode->structureOffset;
|
||||
return String::npos;
|
||||
}
|
||||
|
||||
size_t PVCopy::getCopyOffset(
|
||||
PVRecordStructurePtr const &recordPVStructure,
|
||||
PVRecordFieldPtr const &recordPVField)
|
||||
{
|
||||
CopyRecordNodePtr recordNode;
|
||||
if(!headNode->isStructure) {
|
||||
recordNode = static_pointer_cast<CopyRecordNode>(headNode);
|
||||
if(recordNode->recordPVField.get()!=recordPVStructure.get()) return String::npos;
|
||||
} else {
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
recordNode = getCopyOffset(node,recordPVField);
|
||||
}
|
||||
if(recordNode.get()==NULL) return String::npos;
|
||||
size_t diff = recordPVField->getPVField()->getFieldOffset()
|
||||
- recordPVStructure->getPVStructure()->getFieldOffset();
|
||||
return recordNode->structureOffset + diff;
|
||||
}
|
||||
|
||||
PVRecordFieldPtr PVCopy::getRecordPVField(size_t structureOffset)
|
||||
{
|
||||
CopyRecordNodePtr recordNode;
|
||||
if(!headNode->isStructure) {
|
||||
recordNode = static_pointer_cast<CopyRecordNode>(headNode);
|
||||
} else {
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
recordNode = getRecordNode(node,structureOffset);
|
||||
}
|
||||
if(recordNode.get()==NULL) {
|
||||
throw std::invalid_argument(
|
||||
"PVCopy::getRecordPVField: setstructureOffset not valid");
|
||||
}
|
||||
size_t diff = structureOffset - recordNode->structureOffset;
|
||||
PVRecordFieldPtr pvRecordField = recordNode->recordPVField;
|
||||
if(diff==0) return pvRecordField;
|
||||
PVStructurePtr pvStructure
|
||||
= static_pointer_cast<PVStructure>(pvRecordField->getPVField());
|
||||
PVFieldPtr pvField = pvStructure->getSubField(
|
||||
pvRecordField->getPVField()->getFieldOffset() + diff);
|
||||
return pvRecord->findPVRecordField(pvField);
|
||||
}
|
||||
|
||||
void PVCopy::initCopy(
|
||||
PVStructurePtr const ©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<CopyStructureNode>(headNode);
|
||||
updateStructureNodeSetBitSet(copyPVStructure,node,bitSet);
|
||||
} else {
|
||||
CopyRecordNodePtr recordNode = static_pointer_cast<CopyRecordNode>(headNode);
|
||||
PVRecordFieldPtr pvRecordField= recordNode->recordPVField;
|
||||
PVFieldPtr copyPVField = copyPVStructure;
|
||||
PVFieldPtrArray const & pvCopyFields = copyPVStructure->getPVFields();
|
||||
if(pvCopyFields.size()==1) {
|
||||
copyPVField = pvCopyFields[0];
|
||||
}
|
||||
PVFieldPtr pvField = pvRecordField->getPVField();
|
||||
if(pvField->getField()->getType()==epics::pvData::structure) {
|
||||
updateSubFieldSetBitSet(copyPVField,pvRecordField,bitSet);
|
||||
return;
|
||||
}
|
||||
if(pvCopyFields.size()!=1) {
|
||||
throw std::logic_error("Logic error");
|
||||
}
|
||||
ConvertPtr convert = getConvert();
|
||||
bool isEqual = convert->equals(copyPVField,pvField);
|
||||
if(!isEqual) {
|
||||
convert->copy(pvField, copyPVField);
|
||||
bitSet->set(copyPVField->getFieldOffset());
|
||||
}
|
||||
}
|
||||
if(lockRecord) pvRecord->unlock();
|
||||
} catch(...) {
|
||||
if(lockRecord) pvRecord->unlock();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateCopyFromBitSet(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet,
|
||||
bool lockRecord)
|
||||
{
|
||||
bool doAll = bitSet->get(0);
|
||||
if(lockRecord) pvRecord->lock();
|
||||
try {
|
||||
if(headNode->isStructure) {
|
||||
CopyStructureNodePtr node = static_pointer_cast<CopyStructureNode>(headNode);
|
||||
updateStructureNodeFromBitSet(copyPVStructure,node,bitSet,true,doAll);
|
||||
} else {
|
||||
CopyRecordNodePtr recordNode = static_pointer_cast<CopyRecordNode>(headNode);
|
||||
PVFieldPtrArray const & pvCopyFields = copyPVStructure->getPVFields();
|
||||
if(pvCopyFields.size()==1) {
|
||||
updateSubFieldFromBitSet(
|
||||
pvCopyFields[0],
|
||||
recordNode->recordPVField,bitSet,
|
||||
true,doAll);
|
||||
} else {
|
||||
updateSubFieldFromBitSet(
|
||||
copyPVStructure,
|
||||
recordNode->recordPVField,bitSet,
|
||||
true,doAll);
|
||||
}
|
||||
}
|
||||
if(lockRecord) pvRecord->unlock();
|
||||
} catch(...) {
|
||||
if(lockRecord) pvRecord->unlock();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateRecord(
|
||||
PVStructurePtr const ©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<CopyStructureNode>(headNode);
|
||||
updateStructureNodeFromBitSet(
|
||||
copyPVStructure,node,bitSet,false,doAll);
|
||||
} else {
|
||||
CopyRecordNodePtr recordNode =
|
||||
static_pointer_cast<CopyRecordNode>(headNode);
|
||||
PVFieldPtrArray const & pvCopyFields =
|
||||
copyPVStructure->getPVFields();
|
||||
if(pvCopyFields.size()==1) {
|
||||
updateSubFieldFromBitSet(
|
||||
pvCopyFields[0],
|
||||
recordNode->recordPVField,bitSet,
|
||||
false,doAll);
|
||||
} else {
|
||||
updateSubFieldFromBitSet(
|
||||
copyPVStructure,
|
||||
recordNode->recordPVField,bitSet,
|
||||
false,doAll);
|
||||
}
|
||||
}
|
||||
pvRecord->endGroupPut();
|
||||
if(lockRecord) pvRecord->unlock();
|
||||
} catch(...) {
|
||||
if(lockRecord) pvRecord->unlock();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
PVCopyMonitorPtr PVCopy::createPVCopyMonitor(
|
||||
PVCopyMonitorRequesterPtr const &pvCopyMonitorRequester)
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
}
|
||||
|
||||
epics::pvData::String PVCopy::dump()
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
}
|
||||
|
||||
bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
|
||||
{
|
||||
PVRecordStructurePtr pvRecordStructure = pvRecord->getPVRecordStructure();
|
||||
size_t len = pvRequest->getPVFields().size();
|
||||
bool entireRecord = false;
|
||||
if(len==String::npos) entireRecord = true;
|
||||
PVStructurePtr pvOptions;
|
||||
if(len==1 && pvRequest->getSubField("_options")!=NULL) {
|
||||
pvOptions = pvRequest->getStructureField("_options");
|
||||
}
|
||||
if(entireRecord) {
|
||||
structure = pvRecordStructure->getPVStructure()->getStructure();
|
||||
CopyRecordNodePtr recordNode(new CopyRecordNode());
|
||||
headNode = recordNode;
|
||||
recordNode->options = pvOptions;
|
||||
recordNode->isStructure = false;
|
||||
recordNode->structureOffset = 0;
|
||||
recordNode->recordPVField = pvRecordStructure;
|
||||
return true;
|
||||
}
|
||||
structure = createStructure(pvRecordStructure->getPVStructure(),pvRequest);
|
||||
if(structure==NULL) return false;
|
||||
cacheInitStructure = createPVStructure();
|
||||
headNode = createStructureNodes(
|
||||
pvRecord->getPVRecordStructure(),
|
||||
pvRequest,
|
||||
cacheInitStructure);
|
||||
referenceImmutable(cacheInitStructure,headNode);
|
||||
return true;
|
||||
}
|
||||
|
||||
epics::pvData::String PVCopy::dump(
|
||||
String const &value,
|
||||
CopyNodePtr const &node,
|
||||
int indentLevel)
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
}
|
||||
|
||||
String PVCopy::getFullName(
|
||||
PVStructurePtr const &pvFromRequest,
|
||||
String const &nameFromRecord)
|
||||
{
|
||||
PVFieldPtrArray const & pvFields = pvFromRequest->getPVFields();
|
||||
String fullName = nameFromRecord;
|
||||
size_t len = pvFields.size();
|
||||
if(len==1) {
|
||||
String name = pvFields[0]->getFieldName();
|
||||
if(name.compare("_options")==0) return nameFromRecord;
|
||||
PVStructurePtr pvRequest = static_pointer_cast<PVStructure>(pvFields[0]);
|
||||
if(fullName.size()!=0) fullName += ".";
|
||||
fullName += pvRequest->getFieldName();
|
||||
return getFullName(pvRequest,fullName);
|
||||
}
|
||||
if(len==2) {
|
||||
PVFieldPtr subField;
|
||||
if((pvFields[0]->getFieldName().compare("_options"))==0) {
|
||||
subField = pvFields[1];
|
||||
} else if((pvFields[1]->getFieldName().compare("_options"))==0) {
|
||||
subField = pvFields[1];
|
||||
}
|
||||
if(subField.get()!=NULL) {
|
||||
PVStructurePtr pvRequest = static_pointer_cast<PVStructure>(subField);
|
||||
if(fullName.size()!=0) fullName += ".";
|
||||
fullName += subField->getFieldName();
|
||||
return getFullName(pvRequest,fullName);
|
||||
}
|
||||
}
|
||||
return nameFromRecord;
|
||||
}
|
||||
|
||||
PVStructurePtr PVCopy::getSubStructure(
|
||||
PVStructurePtr const &xxx,
|
||||
String const &yyy)
|
||||
{
|
||||
PVStructurePtr pvFromRequest = xxx;
|
||||
String nameFromRecord = yyy;
|
||||
PVFieldPtrArray const & pvFields = pvFromRequest->getPVFields();
|
||||
size_t len = pvFields.size();
|
||||
if(len==1) {
|
||||
pvFromRequest = static_pointer_cast<PVStructure>(pvFields[0]);
|
||||
if(pvFromRequest->getFieldName().compare("_options")==0) {
|
||||
return pvFromRequest;
|
||||
}
|
||||
if(nameFromRecord.size()!=0) nameFromRecord += ".";
|
||||
nameFromRecord += pvFromRequest->getFieldName();
|
||||
return getSubStructure(pvFromRequest,nameFromRecord);
|
||||
}
|
||||
if(len==2) {
|
||||
PVFieldPtr subField;
|
||||
if(pvFields[0]->getFieldName().compare("_options")==0) {
|
||||
subField = pvFields[1];
|
||||
} else if(pvFields[1]->getFieldName().compare("_options")==0) {
|
||||
subField = pvFields[1];
|
||||
}
|
||||
if(subField.get()!=NULL) {
|
||||
if(nameFromRecord.size()!=0) nameFromRecord += ".";
|
||||
nameFromRecord += subField->getFieldName();
|
||||
pvFromRequest = static_pointer_cast<PVStructure>(subField);
|
||||
return getSubStructure(pvFromRequest,nameFromRecord);
|
||||
}
|
||||
}
|
||||
return pvFromRequest;
|
||||
}
|
||||
|
||||
PVStructurePtr PVCopy::getOptions(
|
||||
PVStructurePtr const &xxx,
|
||||
String const &yyy)
|
||||
{
|
||||
PVStructurePtr pvFromRequest = xxx;
|
||||
String nameFromRecord = yyy;
|
||||
PVFieldPtrArray const & pvFields = pvFromRequest->getPVFields();
|
||||
size_t len = pvFields.size();
|
||||
if(len==1) {
|
||||
pvFromRequest = static_pointer_cast<PVStructure>(pvFields[0]);
|
||||
if(pvFromRequest->getFieldName().compare("_options")==0) {
|
||||
return pvFromRequest;
|
||||
}
|
||||
if(nameFromRecord.size()!=0) nameFromRecord += ".";
|
||||
nameFromRecord += pvFromRequest->getFieldName();
|
||||
return getSubStructure(pvFromRequest,nameFromRecord);
|
||||
}
|
||||
|
||||
if(len==2) {
|
||||
if(pvFields[0]->getFieldName().compare("_options")==0) {
|
||||
pvFromRequest = static_pointer_cast<PVStructure>(pvFields[0]);
|
||||
return pvFromRequest;
|
||||
} else if(pvFields[1]->getFieldName().compare("_options")==0) {
|
||||
pvFromRequest = static_pointer_cast<PVStructure>(pvFields[1]);
|
||||
return pvFromRequest;
|
||||
}
|
||||
|
||||
}
|
||||
return NULLPVStructure;
|
||||
}
|
||||
|
||||
StructureConstPtr PVCopy::createStructure(
|
||||
PVStructurePtr const &pvRecord,
|
||||
PVStructurePtr const &pvFromRequest)
|
||||
{
|
||||
if(pvFromRequest->getStructure()->getNumberFields()==0) {
|
||||
return pvRecord->getStructure();
|
||||
}
|
||||
FieldConstPtr field = createField(pvRecord,pvFromRequest);
|
||||
if(field.get()==NULL) return NULLStructure;
|
||||
if(field->getType()==epics::pvData::structure) {
|
||||
StructureConstPtr structure =
|
||||
static_pointer_cast<const Structure>(field);
|
||||
return structure;
|
||||
}
|
||||
StringArray fieldNames(1);
|
||||
FieldConstPtrArray fields(1);
|
||||
String name = getFullName(pvFromRequest,"");
|
||||
size_t ind = name.find_last_of('.');
|
||||
if(ind!=String::npos) name = String(name,ind+1);
|
||||
fieldNames[0] = name;
|
||||
fields[0] = field;
|
||||
return getFieldCreate()->createStructure(fieldNames, fields);
|
||||
}
|
||||
|
||||
FieldConstPtr PVCopy::createField(
|
||||
PVStructurePtr const &xxx,
|
||||
PVStructurePtr const &yyy)
|
||||
{
|
||||
PVStructurePtr pvRecord = xxx;
|
||||
PVStructurePtr pvFromRequest = yyy;
|
||||
PVFieldPtrArray const & pvFromRequestFields
|
||||
= pvFromRequest->getPVFields();
|
||||
StringArray const & fromRequestFieldNames
|
||||
= pvFromRequest->getStructure()->getFieldNames();
|
||||
size_t length = pvFromRequestFields.size();
|
||||
size_t number = 0;
|
||||
size_t indopt = -1;
|
||||
for(size_t i=0; i<length; i++) {
|
||||
if(fromRequestFieldNames[i].compare("_options")!=0) {
|
||||
number++;
|
||||
} else {
|
||||
indopt = i;
|
||||
}
|
||||
}
|
||||
if(number==0) return pvRecord->getStructure();
|
||||
if(number==1) {
|
||||
String nameFromRecord = "";
|
||||
nameFromRecord = getFullName(pvFromRequest,nameFromRecord);
|
||||
PVFieldPtr pvRecordField = pvRecord->getSubField(nameFromRecord);
|
||||
if(pvRecordField.get()==NULL) return NULLField;
|
||||
Type recordFieldType = pvRecordField->getField()->getType();
|
||||
if(recordFieldType!=epics::pvData::structure) {
|
||||
return pvRecordField->getField();
|
||||
}
|
||||
PVStructurePtr pvSubFrom = static_pointer_cast<PVStructure>(
|
||||
pvFromRequest->getSubField(nameFromRecord));
|
||||
PVFieldPtrArray const & pvs = pvSubFrom->getPVFields();
|
||||
length = pvs.size();
|
||||
number = 0;
|
||||
for(size_t i=0; i<length; i++) {
|
||||
if(!pvs[i]->getFieldName().compare("_options")==0) {
|
||||
number++;
|
||||
}
|
||||
}
|
||||
FieldConstPtrArray fields(1);
|
||||
StringArray fieldNames(1);
|
||||
fieldNames[0] = pvRecordField->getFieldName();
|
||||
if(number==0) {
|
||||
fields[0] = pvRecordField->getField();
|
||||
} else {
|
||||
PVStructurePtr zzz =
|
||||
static_pointer_cast<PVStructure>(pvRecordField);
|
||||
fields[0] = createField(zzz,pvSubFrom);
|
||||
}
|
||||
return getFieldCreate()->createStructure(fieldNames, fields);
|
||||
}
|
||||
FieldConstPtrArray fields; fields.reserve(number);
|
||||
StringArray fieldNames; fields.reserve(number);
|
||||
for(size_t i=0; i<length; i++) {
|
||||
if(i==indopt) continue;
|
||||
PVStructurePtr arg = static_pointer_cast<PVStructure>(
|
||||
pvFromRequestFields[i]);
|
||||
PVStructurePtr yyy = static_pointer_cast<PVStructure>(
|
||||
pvFromRequestFields[i]);
|
||||
String zzz = getFullName(yyy,"");
|
||||
String full = fromRequestFieldNames[i];
|
||||
if(zzz.size()>0) {
|
||||
full += "." + zzz;
|
||||
arg = getSubStructure(yyy,zzz);
|
||||
}
|
||||
PVFieldPtr pvRecordField = pvRecord->getSubField(full);
|
||||
if(pvRecordField.get()==NULL) continue;
|
||||
FieldConstPtr field = pvRecordField->getField();
|
||||
if(field->getType()!=epics::pvData::structure) {
|
||||
fieldNames.push_back(full);
|
||||
fields.push_back(field);
|
||||
continue;
|
||||
}
|
||||
FieldConstPtr xxx = createField(
|
||||
static_pointer_cast<PVStructure>(pvRecordField),arg);
|
||||
if(xxx.get()!=NULL) {
|
||||
fieldNames.push_back(fromRequestFieldNames[i]);
|
||||
fields.push_back(xxx);
|
||||
}
|
||||
}
|
||||
boolean makeValue = true;
|
||||
size_t indValue = String::npos;
|
||||
for(size_t i=0;i<fieldNames.size(); i++) {
|
||||
if(fieldNames[i].compare("value")==0) {
|
||||
if(indValue==String::npos) {
|
||||
indValue = i;
|
||||
} else {
|
||||
makeValue = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(size_t i=0;i<fieldNames.size(); i++) {
|
||||
if(makeValue==true&&indValue==i) {
|
||||
fieldNames[i] = "value";
|
||||
} else {
|
||||
String xxx = fieldNames[i];
|
||||
size_t ind = xxx.find_first_of('.');
|
||||
if(ind!=String::npos) fieldNames[i] = String(xxx,0, ind);
|
||||
}
|
||||
}
|
||||
return getFieldCreate()->createStructure(fieldNames, fields);
|
||||
}
|
||||
|
||||
CopyNodePtr PVCopy::createStructureNodes(
|
||||
PVRecordStructurePtr const &xxx,
|
||||
PVStructurePtr const &yyy,
|
||||
PVFieldPtr const &zzz)
|
||||
{
|
||||
PVRecordStructurePtr pvRecordStructure = xxx;
|
||||
PVStructurePtr pvFromRequest = yyy;
|
||||
PVFieldPtr pvFromField = zzz;
|
||||
|
||||
PVFieldPtrArray const & pvFromRequestFields = pvFromRequest->getPVFields();
|
||||
StringArray const & fromRequestFieldNames =
|
||||
pvFromRequest->getStructure()->getFieldNames();
|
||||
size_t length = pvFromRequestFields.size();
|
||||
size_t number = 0;
|
||||
size_t indopt = -1;
|
||||
PVStructurePtr pvOptions;
|
||||
for(size_t i=0; i<length; i++) {
|
||||
if(fromRequestFieldNames[i].compare("_options")!=0) {
|
||||
number++;
|
||||
} else {
|
||||
indopt = i;
|
||||
pvOptions = static_pointer_cast<PVStructure>(pvFromRequestFields[i]);
|
||||
}
|
||||
}
|
||||
if(number==0) {
|
||||
CopyRecordNodePtr recordNode(new CopyRecordNode());
|
||||
recordNode->options = pvOptions;
|
||||
recordNode->isStructure = false;
|
||||
recordNode->recordPVField = pvRecordStructure;
|
||||
recordNode->nfields = pvFromField->getNumberFields();
|
||||
recordNode->structureOffset = pvFromField->getFieldOffset();
|
||||
return recordNode;
|
||||
}
|
||||
if(number==1) {
|
||||
String nameFromRecord = "";
|
||||
nameFromRecord = getFullName(pvFromRequest,nameFromRecord);
|
||||
PVFieldPtr pvField = pvRecordStructure->
|
||||
getPVStructure()->getSubField(nameFromRecord);
|
||||
if(pvField.get()==NULL) return NULLCopyNodePtr;
|
||||
PVRecordFieldPtr pvRecordField = pvRecordStructure->
|
||||
getPVRecord()->findPVRecordField(pvField);
|
||||
size_t structureOffset = pvFromField->getFieldOffset();
|
||||
PVStructure *pvParent = pvFromField->getParent();
|
||||
if(pvParent==NULL) {
|
||||
structureOffset++;
|
||||
}
|
||||
CopyRecordNodePtr recordNode(new CopyRecordNode());
|
||||
recordNode->options = getOptions(pvFromRequest,nameFromRecord);
|
||||
recordNode->isStructure = false;
|
||||
recordNode->recordPVField = pvRecordField;
|
||||
recordNode->nfields = pvFromField->getNumberFields();
|
||||
recordNode->structureOffset = structureOffset;
|
||||
return recordNode;
|
||||
}
|
||||
CopyNodePtrArrayPtr nodes(new CopyNodePtrArray());
|
||||
nodes->reserve(number);
|
||||
PVStructurePtr pvFromStructure =
|
||||
static_pointer_cast<PVStructure>(pvFromField);
|
||||
PVFieldPtrArray const & pvFromStructureFields =
|
||||
pvFromStructure->getPVFields();
|
||||
length = pvFromStructureFields.size();
|
||||
size_t indFromStructure = 0;
|
||||
for(size_t i= 0; i <pvFromRequestFields.size();i++) {
|
||||
if(i==indopt) continue;
|
||||
PVStructurePtr arg = static_pointer_cast<PVStructure>
|
||||
(pvFromRequestFields[i]);
|
||||
PVStructurePtr yyy = static_pointer_cast<PVStructure>
|
||||
(pvFromRequestFields[i]);
|
||||
String zzz = getFullName(yyy,"");
|
||||
String full = fromRequestFieldNames[i];
|
||||
if(zzz.size()>0) {
|
||||
full += "." + zzz;
|
||||
arg = getSubStructure(yyy,zzz);
|
||||
}
|
||||
PVFieldPtr pvField = pvRecordStructure->
|
||||
getPVStructure()->getSubField(full);
|
||||
if(pvField.get()==NULL) continue;
|
||||
PVRecordFieldPtr pvRecordField =
|
||||
pvRecordStructure->getPVRecord()->findPVRecordField(pvField);
|
||||
CopyNodePtr node;
|
||||
if(pvRecordField->getPVField()->getField()==
|
||||
pvFromStructureFields[indFromStructure]->getField()) {
|
||||
pvField = pvFromStructureFields[indFromStructure];
|
||||
CopyRecordNodePtr recordNode(new CopyRecordNode());
|
||||
recordNode->options = getOptions(yyy,zzz);
|
||||
recordNode->isStructure = false;
|
||||
recordNode->recordPVField = pvRecordField;
|
||||
recordNode->nfields = pvField->getNumberFields();
|
||||
recordNode->structureOffset = pvField->getFieldOffset();
|
||||
node = recordNode;
|
||||
} else {
|
||||
node = createStructureNodes(static_pointer_cast<PVRecordStructure>
|
||||
(pvRecordField),arg,pvFromStructureFields[indFromStructure]);
|
||||
}
|
||||
if(node.get()==NULL) continue;
|
||||
nodes->push_back(node);
|
||||
++indFromStructure;
|
||||
}
|
||||
size_t len = nodes->size();
|
||||
if(len==String::npos) return NULLCopyNodePtr;
|
||||
CopyStructureNodePtr structureNode(new CopyStructureNode());
|
||||
structureNode->isStructure = true;
|
||||
structureNode->nodes = nodes;
|
||||
structureNode->structureOffset = pvFromStructure->getFieldOffset();
|
||||
structureNode->nfields = pvFromStructure->getNumberFields();
|
||||
structureNode->options = pvOptions;
|
||||
return structureNode;
|
||||
}
|
||||
|
||||
void PVCopy::referenceImmutable(
|
||||
PVFieldPtr const &pvField,
|
||||
CopyNodePtr const & node)
|
||||
|
||||
{
|
||||
if(node->isStructure) {
|
||||
CopyStructureNodePtr structureNode =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
|
||||
for(size_t i=0; i<nodes->size(); i++) {
|
||||
CopyNodePtr nextNode = (*nodes)[i];
|
||||
referenceImmutable(
|
||||
pvStructure->getSubField(nextNode->structureOffset),
|
||||
nextNode);
|
||||
}
|
||||
} else {
|
||||
CopyRecordNodePtr recordNode =
|
||||
static_pointer_cast<CopyRecordNode>(node);
|
||||
PVRecordFieldPtr recordPVField = recordNode->recordPVField;
|
||||
bool shareData = false;
|
||||
if(node->options.get()!=NULL) {
|
||||
PVFieldPtr pv = node->options->getSubField("_options");
|
||||
if(pv.get()!=NULL) {
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pv);
|
||||
pv = xxx->getSubField("shareData");
|
||||
if(pv.get()!=NULL) {
|
||||
PVStringPtr yyy = xxx->getStringField("shareData");
|
||||
shareData = (yyy->get().compare("true")==0) ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(shareData) {
|
||||
makeShared(pvField,recordNode->recordPVField);
|
||||
} else {
|
||||
referenceImmutable(pvField,recordPVField);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::referenceImmutable(
|
||||
PVFieldPtr const ©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<PVStructure>(copyPVField);
|
||||
PVFieldPtrArray const & copyPVFields = pvStructure->getPVFields();
|
||||
PVRecordStructurePtr pvRecordStructure =
|
||||
static_pointer_cast<PVRecordStructure>(recordPVField);
|
||||
PVRecordFieldPtrArrayPtr recordPVFields =
|
||||
pvRecordStructure->getPVRecordFields();
|
||||
for(size_t i=0; i<copyPVFields.size(); i++) {
|
||||
referenceImmutable(copyPVFields[i],(*recordPVFields)[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(recordPVField->getPVField()->isImmutable()) {
|
||||
getConvert()->copy(recordPVField->getPVField(), copyPVField);
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::makeShared(
|
||||
PVFieldPtr const ©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; i<structureNode->nodes->size(); i++) {
|
||||
CopyNodePtr node = (*structureNode->nodes)[i];
|
||||
PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset);
|
||||
if(node->isStructure) {
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
|
||||
CopyStructureNodePtr yyy =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
updateStructureNodeSetBitSet(xxx,yyy,bitSet);
|
||||
} else {
|
||||
CopyRecordNodePtr recordNode =
|
||||
static_pointer_cast<CopyRecordNode>(node);
|
||||
bool shareData = false;
|
||||
if(node->options.get()!=NULL) {
|
||||
PVFieldPtr pv = node->options->getSubField("_options");
|
||||
if(pv.get()!=NULL) {
|
||||
PVStructurePtr xxx =
|
||||
static_pointer_cast<PVStructure>(pv);
|
||||
pv = xxx->getSubField("shareData");
|
||||
if(pv.get()!=NULL) {
|
||||
PVStringPtr yyy = xxx->getStringField("shareData");
|
||||
shareData = (yyy->get().compare("true")==0) ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(shareData) {
|
||||
bitSet->set(pvField->getFieldOffset());
|
||||
} else {
|
||||
updateSubFieldSetBitSet(pvField,recordNode->recordPVField,bitSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateSubFieldSetBitSet(
|
||||
PVFieldPtr const &pvCopy,
|
||||
PVRecordFieldPtr const &pvRecord,
|
||||
BitSetPtr const &bitSet)
|
||||
{
|
||||
FieldConstPtr field = pvCopy->getField();
|
||||
Type type = field->getType();
|
||||
if(type!=epics::pvData::structure) {
|
||||
ConvertPtr convert = getConvert();
|
||||
bool isEqual = convert->equals(pvCopy,pvRecord->getPVField());
|
||||
if(isEqual) {
|
||||
if(type==structureArray) {
|
||||
// always act as though a change occurred.
|
||||
// Note that array elements are shared.
|
||||
bitSet->set(pvCopy->getFieldOffset());
|
||||
}
|
||||
}
|
||||
if(isEqual) return;
|
||||
convert->copy(pvRecord->getPVField(), pvCopy);
|
||||
bitSet->set(pvCopy->getFieldOffset());
|
||||
return;
|
||||
}
|
||||
PVStructurePtr pvCopyStructure = static_pointer_cast<PVStructure>(pvCopy);
|
||||
PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
|
||||
PVRecordStructurePtr pvRecordStructure =
|
||||
static_pointer_cast<PVRecordStructure>(pvRecord);
|
||||
PVRecordFieldPtrArrayPtr pvRecordFields =
|
||||
pvRecordStructure->getPVRecordFields();
|
||||
size_t length = pvCopyFields.size();
|
||||
for(size_t i=0; i<length; i++) {
|
||||
updateSubFieldSetBitSet(pvCopyFields[i],(*pvRecordFields)[i],bitSet);
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateStructureNodeFromBitSet(
|
||||
PVStructurePtr const &pvCopy,
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
BitSetPtr const &bitSet,
|
||||
bool toCopy,
|
||||
bool doAll)
|
||||
{
|
||||
size_t offset = structureNode->structureOffset;
|
||||
if(!doAll) {
|
||||
size_t nextSet = bitSet->nextSetBit(offset);
|
||||
if(nextSet==String::npos) return;
|
||||
}
|
||||
if(offset>=pvCopy->getNextFieldOffset()) return;
|
||||
if(!doAll) doAll = bitSet->get(offset);
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
for(size_t i=0; i<nodes->size(); i++) {
|
||||
CopyNodePtr node = (*nodes)[i];
|
||||
PVFieldPtr pvField = pvCopy->getSubField(node->structureOffset);
|
||||
if(node->isStructure) {
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
|
||||
CopyStructureNodePtr subStructureNode =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
updateStructureNodeFromBitSet(
|
||||
xxx,subStructureNode,bitSet,toCopy,doAll);
|
||||
} else {
|
||||
CopyRecordNodePtr recordNode =
|
||||
static_pointer_cast<CopyRecordNode>(node);
|
||||
updateSubFieldFromBitSet(
|
||||
pvField,recordNode->recordPVField,bitSet,toCopy,doAll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::updateSubFieldFromBitSet(
|
||||
PVFieldPtr const &pvCopy,
|
||||
PVRecordFieldPtr const &pvRecordField,
|
||||
BitSetPtr const &bitSet,
|
||||
bool toCopy,
|
||||
bool doAll)
|
||||
{
|
||||
if(!doAll) {
|
||||
doAll = bitSet->get(pvCopy->getFieldOffset());
|
||||
}
|
||||
if(!doAll) {
|
||||
size_t offset = pvCopy->getFieldOffset();
|
||||
size_t nextSet = bitSet->nextSetBit(offset);
|
||||
if(nextSet==String::npos) return;
|
||||
if(nextSet>=pvCopy->getNextFieldOffset()) return;
|
||||
}
|
||||
ConvertPtr convert = getConvert();
|
||||
if(pvCopy->getField()->getType()==epics::pvData::structure) {
|
||||
PVStructurePtr pvCopyStructure =
|
||||
static_pointer_cast<PVStructure>(pvCopy);
|
||||
PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
|
||||
if(pvRecordField->getPVField()->getField()->getType()
|
||||
!=epics::pvData::structure)
|
||||
{
|
||||
if(pvCopyFields.size()!=1) {
|
||||
throw std::logic_error(String("Logic error"));
|
||||
}
|
||||
if(toCopy) {
|
||||
convert->copy(pvRecordField->getPVField(), pvCopyFields[0]);
|
||||
} else {
|
||||
convert->copy(pvCopyFields[0], pvRecordField->getPVField());
|
||||
}
|
||||
return;
|
||||
}
|
||||
PVRecordStructurePtr pvRecordStructure =
|
||||
static_pointer_cast<PVRecordStructure>(pvRecordField);
|
||||
PVRecordFieldPtrArrayPtr pvRecordFields =
|
||||
pvRecordStructure->getPVRecordFields();
|
||||
for(size_t i=0; i<pvCopyFields.size(); i++) {
|
||||
updateSubFieldFromBitSet(
|
||||
pvCopyFields[i],
|
||||
(*pvRecordFields)[i],
|
||||
bitSet,toCopy,doAll);
|
||||
}
|
||||
} else {
|
||||
if(toCopy) {
|
||||
convert->copy(pvRecordField->getPVField(), pvCopy);
|
||||
} else {
|
||||
convert->copy(pvCopy, pvRecordField->getPVField());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CopyRecordNodePtr PVCopy::getCopyOffset(
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
PVRecordFieldPtr const &recordPVField)
|
||||
{
|
||||
size_t offset = recordPVField->getPVField()->getFieldOffset();
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
for(size_t i=0; i< nodes->size(); i++) {
|
||||
CopyNodePtr node = (*nodes)[i];
|
||||
if(!node->isStructure) {
|
||||
CopyRecordNodePtr recordNode =
|
||||
static_pointer_cast<CopyRecordNode>(node);
|
||||
size_t off = recordNode->recordPVField->getPVField()->
|
||||
getFieldOffset();
|
||||
size_t nextOffset = recordNode->recordPVField->getPVField()->
|
||||
getNextFieldOffset();
|
||||
if(offset>= off && offset<nextOffset) return recordNode;
|
||||
} else {
|
||||
CopyStructureNodePtr subNode =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
CopyRecordNodePtr recordNode =
|
||||
getCopyOffset(subNode,recordPVField);
|
||||
if(recordNode.get()!=NULL) return recordNode;
|
||||
}
|
||||
}
|
||||
return NULLCopyRecordNodePtr;
|
||||
}
|
||||
|
||||
CopyRecordNodePtr PVCopy::getRecordNode(
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
std::size_t structureOffset)
|
||||
{
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
for(size_t i=0; i< nodes->size(); i++) {
|
||||
CopyNodePtr node = (*nodes)[i];
|
||||
if(structureOffset>=(node->structureOffset + node->nfields)) continue;
|
||||
if(!node->isStructure) {
|
||||
CopyRecordNodePtr recordNode =
|
||||
static_pointer_cast<CopyRecordNode>(node);
|
||||
return recordNode;
|
||||
}
|
||||
CopyStructureNodePtr subNode =
|
||||
static_pointer_cast<CopyStructureNode>(node);
|
||||
return getRecordNode(subNode,structureOffset);
|
||||
}
|
||||
return NULLCopyRecordNodePtr;
|
||||
}
|
||||
|
||||
|
||||
PVCopyMonitor::PVCopyMonitor()
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
}
|
||||
|
||||
PVCopyMonitor::~PVCopyMonitor()
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
}
|
||||
|
||||
void PVCopyMonitor::startMonitoring(
|
||||
BitSetPtr const &changeBitSet,
|
||||
BitSetPtr const &overrunBitSet)
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
}
|
||||
|
||||
void PVCopyMonitor::stopMonitoring()
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
}
|
||||
|
||||
void PVCopyMonitor::switchBitSets(
|
||||
BitSetPtr const &newChangeBitSet,
|
||||
BitSetPtr const &newOverrunBitSet, bool lockRecord)
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
}
|
||||
|
||||
}}
|
303
src/pvAccess/pvCopy.h
Normal file
303
src/pvAccess/pvCopy.h
Normal file
@ -0,0 +1,303 @@
|
||||
/* pvCopy.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2013.03.25
|
||||
*/
|
||||
#ifndef PVCOPY_H
|
||||
#define PVCOPY_H
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#include <pv/pvType.h>
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class PVCopy;
|
||||
typedef std::tr1::shared_ptr<PVCopy> PVCopyPtr;
|
||||
class PVCopyMonitor;
|
||||
typedef std::tr1::shared_ptr<PVCopyMonitor> PVCopyMonitorPtr;
|
||||
class PVCopyMonitorRequester;
|
||||
typedef std::tr1::shared_ptr<PVCopyMonitorRequester> PVCopyMonitorRequesterPtr;
|
||||
class SharePVScalarArray;
|
||||
typedef std::tr1::shared_ptr<SharePVScalarArray> SharePVScalarArrayPtr;
|
||||
class SharePVStructureArray;
|
||||
typedef std::tr1::shared_ptr<SharePVStructureArray> SharePVStructureArrayPtr;
|
||||
|
||||
struct CopyNode;
|
||||
typedef std::tr1::shared_ptr<CopyNode> CopyNodePtr;
|
||||
struct CopyRecordNode;
|
||||
typedef std::tr1::shared_ptr<CopyRecordNode> CopyRecordNodePtr;
|
||||
struct CopyStructureNode;
|
||||
typedef std::tr1::shared_ptr<CopyStructureNode> CopyStructureNodePtr;
|
||||
|
||||
|
||||
class PVCopy :
|
||||
public std::tr1::enable_shared_from_this<PVCopy>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVCopy);
|
||||
static PVCopyPtr create(
|
||||
PVRecordPtr const &pvRecord,
|
||||
epics::pvData::PVStructurePtr const &pvRequest,
|
||||
epics::pvData::String const & structureName);
|
||||
virtual ~PVCopy(){}
|
||||
PVRecordPtr getPVRecord();
|
||||
epics::pvData::StructureConstPtr getStructure();
|
||||
epics::pvData::PVStructurePtr createPVStructure();
|
||||
std::size_t getCopyOffset(PVRecordFieldPtr const &recordPVField);
|
||||
std::size_t getCopyOffset(
|
||||
PVRecordStructurePtr const &recordPVStructure,
|
||||
PVRecordFieldPtr const &recordPVField);
|
||||
PVRecordFieldPtr getRecordPVField(std::size_t structureOffset);
|
||||
void initCopy(
|
||||
epics::pvData::PVStructurePtr const ©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<PVCopyMonitor>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVCopyMonitor);
|
||||
virtual ~PVCopyMonitor();
|
||||
void startMonitoring(
|
||||
epics::pvData::BitSetPtr const &changeBitSet,
|
||||
epics::pvData::BitSetPtr const &overrunBitSet);
|
||||
void stopMonitoring();
|
||||
void switchBitSets(
|
||||
epics::pvData::BitSetPtr const &newChangeBitSet,
|
||||
epics::pvData::BitSetPtr const &newOverrunBitSet, bool lockRecord);
|
||||
private:
|
||||
PVCopyMonitorPtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
PVCopyMonitor();
|
||||
friend class PVCopy;
|
||||
// TBD
|
||||
};
|
||||
|
||||
class PVCopyMonitorRequester :
|
||||
public std::tr1::enable_shared_from_this<PVCopyMonitorRequester>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVCopyMonitorRequester);
|
||||
virtual void dataChanged() = 0;
|
||||
virtual void unlisten() = 0;
|
||||
private:
|
||||
PVCopyMonitorRequesterPtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifdef MUSTIMPLEMENT
|
||||
template<typename T>
|
||||
class SharePVScalarArray :
|
||||
public epics::pvData::PVScalarArray
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(SharePVScalarArray)
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef epics::pvData::PVArrayData<T> ArrayDataType;
|
||||
|
||||
SharePVScalarArray(
|
||||
PVRecordFieldPtr const &pvRecordField,
|
||||
epics::pvData::PVStructurePtr const &parent,
|
||||
epics::pvData::PVScalarArrayPtr const &pvShare);
|
||||
virtual ~SharePVScalarArray();
|
||||
void lockShare() const;
|
||||
void unlockShare() const;
|
||||
virtual void message(
|
||||
epics::pvData::String const & message,
|
||||
epics::pvData::MessageType messageType);
|
||||
virtual void setImmutable();
|
||||
bool isImmutable();
|
||||
virtual void setCapacity(std::size_t capacity);
|
||||
void setLength(std::size_t length);
|
||||
std::size_t getCapacity() const;
|
||||
std::size_t getLength() const;
|
||||
bool isCapacityMutable();
|
||||
void setCapacityMutable(bool isMutable);
|
||||
virtual std::size_t get(std::size_t offset, std::size_t length, ArrayDataType &data) = 0;
|
||||
virtual std::size_t put(std::size_t offset,std::size_t length, pointer from, std::size_t fromOffset) = 0;
|
||||
virtual void shareData(pointer value,std::size_t capacity,std::size_t length) = 0;
|
||||
virtual bool equals(epics::pvData::PVFieldPtr const &pv);
|
||||
virtual void serialize(
|
||||
epics::pvData::ByteBufferPtr *pbuffer,
|
||||
epics::pvData::SerializableControl *pflusher) const;
|
||||
virtual void deserialize(
|
||||
epics::pvData::ByteBuffer *pbuffer,
|
||||
epics::pvData::DeserializableControl *pflusher);
|
||||
virtual void serialize(
|
||||
epics::pvData::ByteBuffer *pbuffer,
|
||||
epics::pvData::SerializableControl *pflusher, std::size_t offset, std::size_t count) const;
|
||||
private:
|
||||
PVRecordField &pvRecordField;
|
||||
};
|
||||
|
||||
typedef SharePVScalarArray<bool> SharePVBooleanArray;
|
||||
typedef SharePVScalarArray<epics::pvData::int8> SharePVByteArray;
|
||||
typedef SharePVScalarArray<epics::pvData::int16> SharePVShortArray;
|
||||
typedef SharePVScalarArray<epics::pvData::int32> SharePVIntArray;
|
||||
typedef SharePVScalarArray<epics::pvData::int64> SharePVLongArray;
|
||||
typedef SharePVScalarArray<float> SharePVFloatArray;
|
||||
typedef SharePVScalarArray<double> SharePVDoubleArray;
|
||||
typedef SharePVScalarArray<epics::pvData::String> SharePVStringArray;
|
||||
|
||||
|
||||
class SharePVStructureArray :
|
||||
public epics::pvData::PVStructureArray
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(SharePVStructureArray)
|
||||
SharePVStructureArray(
|
||||
PVRecordFieldPtr const &pvRecordField,
|
||||
epics::pvData::PVStructurePtr const &parent,
|
||||
epics::pvData::PVStructureArrayPtr const &pvShare);
|
||||
virtual ~SharePVStructureArray();
|
||||
virtual epics::pvData::StructureArrayConstPtr getStructureArray();
|
||||
void lockShare() const;
|
||||
void unlockShare() const;
|
||||
virtual void message(
|
||||
epics::pvData::String const &message,
|
||||
epics::pvData::MessageType messageType);
|
||||
virtual void setImmutable();
|
||||
bool isImmutable();
|
||||
virtual void setCapacity(std::size_t capacity);
|
||||
void setLength(std::size_t length);
|
||||
std::size_t getCapacity() const;
|
||||
std::size_t getLength() const;
|
||||
bool isCapacityMutable();
|
||||
void setCapacityMutable(bool isMutable);
|
||||
virtual void shareData(
|
||||
epics::pvData::PVStructurePtrArrayPtr const & value,
|
||||
std::size_t capacity,std::size_t length);
|
||||
virtual std::size_t get(std::size_t offset, std::size_t length,
|
||||
epics::pvData::StructureArrayData &data);
|
||||
virtual std::size_t put(std::size_t offset,std::size_t length,
|
||||
epics::pvData::PVStructurePtrArrayPtr const & from,
|
||||
std::size_t fromOffset);
|
||||
virtual bool equals(epics::pvData::PVField & &pv);
|
||||
virtual void serialize(
|
||||
epics::pvData::ByteBuffer *pbuffer,
|
||||
epics::pvData::SerializableControl *pflusher) const;
|
||||
virtual void deserialize(
|
||||
epics::pvData::ByteBuffer *pbuffer,
|
||||
epics::pvData::DeserializableControl *pflusher);
|
||||
virtual void serialize(
|
||||
epics::pvData::ByteBuffer *pbuffer,
|
||||
epics::pvData::SerializableControl *pflusher,
|
||||
std::size_t offset, std::size_t count) const;
|
||||
private:
|
||||
PVRecordField &pvRecordField;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVCOPY_H */
|
241
src/pvAccess/pvShare.cpp
Normal file
241
src/pvAccess/pvShare.cpp
Normal file
@ -0,0 +1,241 @@
|
||||
/* pvShare.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/noDefaultMethods.h>
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/support.h>
|
||||
#include <pv/pvCopy.h>
|
||||
|
||||
namespace epics { namespace pvIOC {
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
template<typename T>
|
||||
SharePVScalarArray<T>::SharePVScalarArray(
|
||||
PVRecordField &pvRecordField,
|
||||
epics::pvData::PVStructure *parent,
|
||||
epics::pvData::PVScalarArray &pvShare)
|
||||
: PVField(parent,pvShare.getField()),
|
||||
pvRecordField(pvRecordField)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
SharePVScalarArray<T>::~SharePVScalarArray()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SharePVScalarArray<T>::lockShare() const
|
||||
{
|
||||
pvRecordField.getPVRecord().lock();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SharePVScalarArray<T>::unlockShare() const
|
||||
{
|
||||
pvRecordField.getPVRecord().unlock();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SharePVScalarArray<T>::message(String message,MessageType messageType)
|
||||
{
|
||||
pvRecordField.message(message,messageType);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SharePVScalarArray<T>::setImmutable()
|
||||
{
|
||||
lockShare();
|
||||
try {
|
||||
pvRecordField.getPVField().setImmutable();
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool SharePVScalarArray<T>::isImmutable()
|
||||
{
|
||||
return pvRecordField.getPVField().isImmutable();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SharePVScalarArray<T>::setCapacityMutable(bool isMutable)
|
||||
{
|
||||
lockShare();
|
||||
try {
|
||||
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
|
||||
pvArray.setCapacityMutable(isMutable);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool SharePVScalarArray<T>::isCapacityMutable()
|
||||
{
|
||||
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
|
||||
return pvArray.isCapacityMutable();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SharePVScalarArray<T>::setCapacity(int capacity)
|
||||
{
|
||||
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
|
||||
lockShare();
|
||||
try {
|
||||
pvArray.setCapacity(capacity);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SharePVScalarArray<T>::setLength(int length)
|
||||
{
|
||||
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
|
||||
lockShare();
|
||||
try {
|
||||
pvArray.setLength(length);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int SharePVScalarArray<T>::getCapacity() const
|
||||
{
|
||||
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
|
||||
return pvArray.getCapacity();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int SharePVScalarArray<T>::getLength() const
|
||||
{
|
||||
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
|
||||
return pvArray.getLength();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int SharePVScalarArray<T>::get(int offset, int length, ArrayDataType *data)
|
||||
{
|
||||
class PVValueArray<T> &pvArray = static_cast<PVValueArray<T> &>(
|
||||
pvRecordField.getPVField());
|
||||
lockShare();
|
||||
try {
|
||||
return pvArray.get(offset,length,data);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int SharePVScalarArray<T>::put(
|
||||
int offset,int length, pointer from, int fromOffset)
|
||||
{
|
||||
class PVValueArray<T> &pvArray = static_cast<PVValueArray<T> &>(
|
||||
pvRecordField.getPVField());
|
||||
lockShare();
|
||||
try {
|
||||
pvRecordField.getPVRecord().beginGroupPut();
|
||||
int len = pvArray.put(offset,length,from,fromOffset);
|
||||
pvRecordField.getPVRecord().endGroupPut();
|
||||
unlockShare();
|
||||
return len;
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SharePVScalarArray<T>::shareData(pointer value,int capacity,int length)
|
||||
{
|
||||
class PVValueArray<T> &pvArray = static_cast<PVValueArray<T> &>(
|
||||
pvRecordField.getPVField());
|
||||
lockShare();
|
||||
try {
|
||||
pvArray.setImmutable(value,capacity,length);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool SharePVScalarArray<T>::equals(PVField &pv)
|
||||
{
|
||||
lockShare();
|
||||
try {
|
||||
return pvRecordField.getPVField().equals(pv);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SharePVScalarArray<T>::serialize(
|
||||
ByteBuffer *pbuffer,SerializableControl *pflusher) const
|
||||
{
|
||||
serialize(pbuffer, pflusher, 0, getLength());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SharePVScalarArray<T>::deserialize(
|
||||
ByteBuffer *pbuffer,DeserializableControl *pflusher)
|
||||
{
|
||||
class PVValueArray<T> &pvArray = static_cast<PVValueArray<T> &>(
|
||||
pvRecordField.getPVField());
|
||||
lockShare();
|
||||
try {
|
||||
pvArray.deserialize(pbuffer,pflusher);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void SharePVScalarArray<T>::serialize(
|
||||
ByteBuffer *pbuffer,SerializableControl *pflusher,int offset,int count) const
|
||||
{
|
||||
class PVValueArray<T> &pvArray = static_cast<PVValueArray<T> &>(
|
||||
pvRecordField.getPVField());
|
||||
lockShare();
|
||||
try {
|
||||
pvArray.serialize(pbuffer,pflusher,offset,count);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
218
src/pvAccess/pvShareStructureArray.cpp
Normal file
218
src/pvAccess/pvShareStructureArray.cpp
Normal file
@ -0,0 +1,218 @@
|
||||
/* pvShareStructureArray.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/noDefaultMethods.h>
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/support.h>
|
||||
#include <pv/pvCopy.h>
|
||||
|
||||
namespace epics { namespace pvIOC {
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
SharePVStructureArray::SharePVStructureArray(
|
||||
PVRecordField &pvRecordField,
|
||||
PVStructure *parent,
|
||||
PVStructureArray &pvShare)
|
||||
: PVArray(parent,pvShare.getField()),
|
||||
pvRecordField(pvRecordField)
|
||||
{
|
||||
}
|
||||
|
||||
SharePVStructureArray::~SharePVStructureArray() {}
|
||||
|
||||
StructureArrayConstPtr SharePVStructureArray::getStructureArray()
|
||||
{
|
||||
PVStructureArray &pvArray = static_cast<PVStructureArray &>(
|
||||
pvRecordField.getPVField());
|
||||
return pvArray.getStructureArray();
|
||||
}
|
||||
|
||||
void SharePVStructureArray::lockShare() const
|
||||
{
|
||||
pvRecordField.getPVRecord().lock();
|
||||
}
|
||||
|
||||
void SharePVStructureArray::unlockShare() const
|
||||
{
|
||||
pvRecordField.getPVRecord().unlock();
|
||||
}
|
||||
|
||||
void SharePVStructureArray::message(String message,MessageType messageType)
|
||||
{
|
||||
pvRecordField.message(message,messageType);
|
||||
}
|
||||
|
||||
void SharePVStructureArray::setImmutable()
|
||||
{
|
||||
lockShare();
|
||||
try {
|
||||
pvRecordField.getPVField().setImmutable();
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
bool SharePVStructureArray::isImmutable()
|
||||
{
|
||||
return pvRecordField.getPVField().isImmutable();
|
||||
}
|
||||
|
||||
void SharePVStructureArray::setCapacityMutable(bool isMutable)
|
||||
{
|
||||
lockShare();
|
||||
try {
|
||||
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
|
||||
pvArray.setCapacityMutable(isMutable);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
bool SharePVStructureArray::isCapacityMutable()
|
||||
{
|
||||
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
|
||||
return pvArray.isCapacityMutable();
|
||||
}
|
||||
|
||||
void SharePVStructureArray::setCapacity(int capacity)
|
||||
{
|
||||
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
|
||||
lockShare();
|
||||
try {
|
||||
pvArray.setCapacity(capacity);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void SharePVStructureArray::setLength(int length)
|
||||
{
|
||||
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
|
||||
lockShare();
|
||||
try {
|
||||
pvArray.setLength(length);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
int SharePVStructureArray::getCapacity() const
|
||||
{
|
||||
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
|
||||
return pvArray.getCapacity();
|
||||
}
|
||||
|
||||
int SharePVStructureArray::getLength() const
|
||||
{
|
||||
PVArray &pvArray = static_cast<PVArray &>(pvRecordField.getPVField());
|
||||
return pvArray.getLength();
|
||||
}
|
||||
|
||||
int SharePVStructureArray::get(int offset, int length, StructureArrayData *data)
|
||||
{
|
||||
class PVStructureArray &pvArray = static_cast<PVStructureArray &>(
|
||||
pvRecordField.getPVField());
|
||||
lockShare();
|
||||
try {
|
||||
return pvArray.get(offset,length,data);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
int SharePVStructureArray::put(
|
||||
int offset,int length, PVStructurePtrArray from, int fromOffset)
|
||||
{
|
||||
class PVStructureArray &pvArray = static_cast<PVStructureArray &>(
|
||||
pvRecordField.getPVField());
|
||||
lockShare();
|
||||
try {
|
||||
pvRecordField.getPVRecord().beginGroupPut();
|
||||
int len = pvArray.put(offset,length,from,fromOffset);
|
||||
pvRecordField.getPVRecord().endGroupPut();
|
||||
unlockShare();
|
||||
return len;
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void SharePVStructureArray::shareData(
|
||||
PVStructurePtrArray value,int capacity,int length)
|
||||
{
|
||||
throw std::logic_error("shareData not legal in this context");
|
||||
}
|
||||
|
||||
bool SharePVStructureArray::equals(PVField &pv)
|
||||
{
|
||||
lockShare();
|
||||
try {
|
||||
return pvRecordField.getPVField().equals(pv);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void SharePVStructureArray::serialize(
|
||||
ByteBuffer *pbuffer,SerializableControl *pflusher) const
|
||||
{
|
||||
serialize(pbuffer, pflusher, 0, getLength());
|
||||
}
|
||||
|
||||
void SharePVStructureArray::deserialize(
|
||||
ByteBuffer *pbuffer,DeserializableControl *pflusher)
|
||||
{
|
||||
class PVStructureArray &pvArray = static_cast<PVStructureArray &>(
|
||||
pvRecordField.getPVField());
|
||||
lockShare();
|
||||
try {
|
||||
pvArray.deserialize(pbuffer,pflusher);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void SharePVStructureArray::serialize(
|
||||
ByteBuffer *pbuffer,SerializableControl *pflusher,int offset,int count) const
|
||||
{
|
||||
class PVStructureArray &pvArray = static_cast<PVStructureArray &>(
|
||||
pvRecordField.getPVField());
|
||||
lockShare();
|
||||
try {
|
||||
pvArray.serialize(pbuffer,pflusher,offset,count);
|
||||
unlockShare();
|
||||
} catch(...) {
|
||||
unlockShare();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
@ -1,5 +1,6 @@
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
DIRS += record
|
||||
DIRS += pvCopy
|
||||
include $(TOP)/configure/RULES_DIRS
|
||||
|
||||
|
12
test/pvCopy/Makefile
Normal file
12
test/pvCopy/Makefile
Normal file
@ -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
|
||||
|
409
test/pvCopy/testPVCopy.cpp
Normal file
409
test/pvCopy/testPVCopy.cpp
Normal file
@ -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 <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
#include <epicsStdio.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsEvent.h>
|
||||
#include <epicsThread.h>
|
||||
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/pvCopy.h>
|
||||
#include <pv/powerSupplyRecordTest.h>
|
||||
|
||||
|
||||
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<MyRequester> 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<PVScalar>(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<PVScalar>(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; i<n; i++) values[i] = i;
|
||||
convert->fromDoubleArray(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; i<n; i++) values[i] = i + .06;
|
||||
convert->fromDoubleArray(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; i<n; i++) values[i] = i + 1.0;
|
||||
convert->fromDoubleArray(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; i<n; i++) values[i] = i + 2.0;
|
||||
convert->fromDoubleArray(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;
|
||||
}
|
||||
|
@ -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
|
||||
#----------------------------------------
|
||||
|
126
test/record/testExampleRecordMain.cpp
Normal file
126
test/record/testExampleRecordMain.cpp
Normal file
@ -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 <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
#include <epicsStdio.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsEvent.h>
|
||||
#include <epicsThread.h>
|
||||
|
||||
#include <epicsExport.h>
|
||||
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/powerSupplyRecordTest.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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 <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#include <pv/standardPVField.h>
|
||||
#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();
|
||||
}
|
||||
|
||||
}}
|
||||
|
@ -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 <string>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class TestRecord;
|
||||
typedef std::tr1::shared_ptr<TestRecord> 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 */
|
@ -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 <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
#include <epicsStdio.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsEvent.h>
|
||||
#include <epicsThread.h>
|
||||
|
||||
#include <epicsExport.h>
|
||||
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/event.h>
|
||||
|
||||
#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<MyPVListener> MyPVListenerPtr;
|
||||
|
||||
class MyProcessRequester;
|
||||
typedef std::tr1::shared_ptr<MyProcessRequester> MyProcessRequesterPtr;
|
||||
|
||||
class MyPutRequester;
|
||||
typedef std::tr1::shared_ptr<MyPutRequester> MyPutRequesterPtr;
|
||||
|
||||
class MyPVListener :
|
||||
public PVListener,
|
||||
public std::tr1::enable_shared_from_this<MyPVListener>
|
||||
{
|
||||
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<MyProcessRequester>
|
||||
{
|
||||
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<MyPutRequester>
|
||||
{
|
||||
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; i<num; i++) {
|
||||
PVRecordFieldPtr pvRecordField = (*pvRecordFields.get())[i];
|
||||
if(pvRecordField->getPVField()->getField()->getType()==structure) {
|
||||
PVRecordStructurePtr xxx =
|
||||
static_pointer_cast<PVRecordStructure>(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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user