interim commit. pvCopy how works
This commit is contained in:
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;
|
||||
|
||||
Reference in New Issue
Block a user