interim commit. pvCopy how works

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

View File

@@ -0,0 +1,188 @@
/* powerSupplyRecordTest.h */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2013.04.02
*/
#ifndef POWERSUPPLYRECORDTEST_H
#define POWERSUPPLYRECORDTEST_H
#include <pv/executor.h>
#include <pv/pvDatabase.h>
#include <pv/event.h>
#include <pv/timer.h>
#include <pv/timeStamp.h>
#include <pv/alarm.h>
#include <pv/pvTimeStamp.h>
#include <pv/pvAlarm.h>
namespace epics { namespace pvDatabase {
class PowerSupplyRecordTest;
typedef std::tr1::shared_ptr<PowerSupplyRecordTest> PowerSupplyRecordTestPtr;
class PowerSupplyRecordTest :
public PVRecord
{
public:
POINTER_DEFINITIONS(PowerSupplyRecordTest);
static PowerSupplyRecordTestPtr create(
epics::pvData::String const & recordName,
epics::pvData::PVStructurePtr const & pvStructure);
virtual ~PowerSupplyRecordTest();
virtual bool init();
virtual void process();
void put(double power,double voltage);
double getPower();
double getVoltage();
double getCurrent();
private:
PowerSupplyRecordTest(epics::pvData::String const & recordName,
epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStructurePtr pvStructure;
epics::pvData::PVDoublePtr pvCurrent;
epics::pvData::PVDoublePtr pvPower;
epics::pvData::PVDoublePtr pvVoltage;
epics::pvData::PVAlarm pvAlarm;
epics::pvData::PVTimeStamp pvTimeStamp;
epics::pvData::Alarm alarm;
epics::pvData::TimeStamp timeStamp;
};
PowerSupplyRecordTestPtr PowerSupplyRecordTest::create(
epics::pvData::String const & recordName,
epics::pvData::PVStructurePtr const & pvStructure)
{
PowerSupplyRecordTestPtr pvRecord(
new PowerSupplyRecordTest(recordName,pvStructure));
if(!pvRecord->init()) pvRecord.reset();
return pvRecord;
}
PowerSupplyRecordTest::PowerSupplyRecordTest(
epics::pvData::String const & recordName,
epics::pvData::PVStructurePtr const & pvStructure)
: PVRecord(recordName,pvStructure),
pvStructure(pvStructure)
{
}
PowerSupplyRecordTest::~PowerSupplyRecordTest()
{
destroy();
}
bool PowerSupplyRecordTest::init()
{
initPVRecord();
epics::pvData::PVFieldPtr pvField;
bool result;
pvField = pvStructure->getSubField("timeStamp");
if(pvField.get()==NULL) {
std::cerr << "no timeStamp" << std::endl;
return false;
}
result = pvTimeStamp.attach(pvField);
if(!result) {
std::cerr << "no timeStamp" << std::endl;
return false;
}
pvField = pvStructure->getSubField("alarm");
if(pvField.get()==NULL) {
std::cerr << "no alarm" << std::endl;
return false;
}
result = pvAlarm.attach(pvField);
if(!result) {
std::cerr << "no alarm" << std::endl;
return false;
}
epics::pvData::String name;
name = "current.value";
pvField = pvStructure->getSubField(name);
if(pvField.get()==NULL) {
name = "current";
pvField = pvStructure->getSubField(name);
}
if(pvField.get()==NULL) {
std::cerr << "no current" << std::endl;
return false;
}
pvCurrent = pvStructure->getDoubleField(name);
if(pvCurrent.get()==NULL) return false;
name = "voltage.value";
pvField = pvStructure->getSubField(name);
if(pvField.get()==NULL) {
name = "voltage";
pvField = pvStructure->getSubField(name);
}
if(pvField.get()==NULL) {
std::cerr << "no voltage" << std::endl;
return false;
}
pvVoltage = pvStructure->getDoubleField(name);
if(pvVoltage.get()==NULL) return false;
name = "power.value";
pvField = pvStructure->getSubField(name);
if(pvField.get()==NULL) {
name = "power";
pvField = pvStructure->getSubField(name);
}
if(pvField.get()==NULL) {
std::cerr << "no power" << std::endl;
return false;
}
pvPower = pvStructure->getDoubleField(name);
if(pvPower.get()==NULL) return false;
return true;
}
void PowerSupplyRecordTest::process()
{
timeStamp.getCurrent();
pvTimeStamp.set(timeStamp);
double voltage = pvVoltage->get();
double power = pvPower->get();
if(voltage<1e-3 && voltage>-1e-3) {
alarm.setMessage("bad voltage");
alarm.setSeverity(epics::pvData::majorAlarm);
pvAlarm.set(alarm);
return;
}
double current = power/voltage;
pvCurrent->put(current);
alarm.setMessage("");
alarm.setSeverity(epics::pvData::noAlarm);
pvAlarm.set(alarm);
}
void PowerSupplyRecordTest::put(double power,double voltage)
{
pvPower->put(power);
pvVoltage->put(voltage);
}
double PowerSupplyRecordTest::getPower()
{
return pvPower->get();
}
double PowerSupplyRecordTest::getVoltage()
{
return pvVoltage->get();
}
double PowerSupplyRecordTest::getCurrent()
{
return pvCurrent->get();
}
}}
#endif /* POWERSUPPLYRECORDTEST_H */

View File

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

View File

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