interim commit. First working version of record.
This commit is contained in:
4
Makefile
4
Makefile
@ -6,8 +6,8 @@ DIRS += configure
|
|||||||
DIRS += src
|
DIRS += src
|
||||||
src_DEPEND_DIRS = configure
|
src_DEPEND_DIRS = configure
|
||||||
|
|
||||||
#DIRS += test
|
DIRS += test
|
||||||
#test_DEPEND_DIRS = src
|
test_DEPEND_DIRS = src
|
||||||
|
|
||||||
DIRS += example
|
DIRS += example
|
||||||
example_DEPEND_DIRS = src
|
example_DEPEND_DIRS = src
|
||||||
|
@ -38,6 +38,7 @@ PVRecordPtr ExampleRecord::create(String const & recordName)
|
|||||||
PVStructurePtr pvStructure = getStandardPVField()->scalar(pvLong,properties);
|
PVStructurePtr pvStructure = getStandardPVField()->scalar(pvLong,properties);
|
||||||
PVLongPtr pvValue = pvStructure->getLongField("value");
|
PVLongPtr pvValue = pvStructure->getLongField("value");
|
||||||
PVRecordPtr pvRecord(new ExampleRecord(recordName,pvStructure,pvValue));
|
PVRecordPtr pvRecord(new ExampleRecord(recordName,pvStructure,pvValue));
|
||||||
|
pvRecord->init();
|
||||||
return pvRecord;
|
return pvRecord;
|
||||||
}
|
}
|
||||||
ExampleRecord::ExampleRecord(
|
ExampleRecord::ExampleRecord(
|
||||||
@ -51,11 +52,14 @@ PVRecordPtr ExampleRecord::create(String const & recordName)
|
|||||||
bool ExampleRecord::isSynchronous() {return true;}
|
bool ExampleRecord::isSynchronous() {return true;}
|
||||||
|
|
||||||
void ExampleRecord::process(
|
void ExampleRecord::process(
|
||||||
RecordProcessRequesterPtr const &processRequester)
|
RecordProcessRequesterPtr const &processRequester,bool alreadyLocked)
|
||||||
{
|
{
|
||||||
|
if(!alreadyLocked) lock();
|
||||||
pvValue->put(pvValue->get() + 1);
|
pvValue->put(pvValue->get() + 1);
|
||||||
processRequester->recordProcessResult(Status::Ok);
|
processRequester->recordProcessResult(Status::Ok);
|
||||||
|
unlock();
|
||||||
processRequester->recordProcessComplete();
|
processRequester->recordProcessComplete();
|
||||||
|
dequeueProcessRequest(processRequester);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,7 +29,8 @@ public:
|
|||||||
virtual ~ExampleRecord();
|
virtual ~ExampleRecord();
|
||||||
virtual bool isSynchronous();
|
virtual bool isSynchronous();
|
||||||
virtual void process(
|
virtual void process(
|
||||||
epics::pvDatabase::RecordProcessRequesterPtr const &processRequester);
|
epics::pvDatabase::RecordProcessRequesterPtr const &processRequester,
|
||||||
|
bool alreadyLocked);
|
||||||
private:
|
private:
|
||||||
ExampleRecord(epics::pvData::String const & recordName,
|
ExampleRecord(epics::pvData::String const & recordName,
|
||||||
epics::pvData::PVStructurePtr const & pvStructure,
|
epics::pvData::PVStructurePtr const & pvStructure,
|
||||||
|
@ -21,10 +21,454 @@ PVRecord::PVRecord(
|
|||||||
String const & recordName,
|
String const & recordName,
|
||||||
PVStructurePtr const & pvStructure)
|
PVStructurePtr const & pvStructure)
|
||||||
: recordName(recordName),
|
: recordName(recordName),
|
||||||
pvStructure(pvStructure)
|
pvStructure(pvStructure),
|
||||||
{}
|
convert(getConvert()),
|
||||||
|
thelock(mutex),
|
||||||
|
depthGroupPut(0)
|
||||||
|
{
|
||||||
|
thelock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecord::init()
|
||||||
|
{
|
||||||
|
PVRecordStructurePtr parent;
|
||||||
|
pvRecordStructure = PVRecordStructurePtr(
|
||||||
|
new PVRecordStructure(pvStructure,parent,getPtrSelf()));
|
||||||
|
pvRecordStructure->init();
|
||||||
|
pvStructure->setRequester(getPtrSelf());
|
||||||
|
}
|
||||||
|
|
||||||
PVRecord::~PVRecord() {}
|
PVRecord::~PVRecord() {}
|
||||||
|
|
||||||
}}
|
String PVRecord::getRecordName() {return recordName;}
|
||||||
|
|
||||||
|
PVRecordStructurePtr PVRecord::getPVRecordStructure() {return pvRecordStructure;}
|
||||||
|
|
||||||
|
PVRecordFieldPtr PVRecord::findPVRecordField(PVFieldPtr const & pvField)
|
||||||
|
{
|
||||||
|
return findPVRecordField(pvRecordStructure,pvField);
|
||||||
|
}
|
||||||
|
|
||||||
|
PVRecordFieldPtr PVRecord::findPVRecordField(
|
||||||
|
PVRecordStructurePtr const & pvrs,
|
||||||
|
PVFieldPtr const & pvField)
|
||||||
|
{
|
||||||
|
size_t desiredOffset = pvField->getFieldOffset();
|
||||||
|
PVFieldPtr pvf = pvrs->getPVField();
|
||||||
|
size_t offset = pvf->getFieldOffset();
|
||||||
|
if(offset==desiredOffset) return pvrs;
|
||||||
|
PVRecordFieldPtrArrayPtr pvrfpap = pvrs->getPVRecordFields();
|
||||||
|
PVRecordFieldPtrArray::iterator iter;
|
||||||
|
for (iter = pvrfpap.get()->begin(); iter!=pvrfpap.get()->end(); iter++ ) {
|
||||||
|
PVRecordFieldPtr pvrf = *iter;
|
||||||
|
pvf = pvrf->getPVField();
|
||||||
|
offset = pvf->getFieldOffset();
|
||||||
|
if(offset==desiredOffset) return pvrf;
|
||||||
|
size_t nextOffset = pvf->getNextFieldOffset();
|
||||||
|
if(nextOffset<=desiredOffset) continue;
|
||||||
|
return findPVRecordField(
|
||||||
|
static_pointer_cast<PVRecordStructure>(pvrf),
|
||||||
|
pvField);
|
||||||
|
}
|
||||||
|
throw std::logic_error(
|
||||||
|
recordName + " pvField "
|
||||||
|
+ pvField->getFieldName() + " not in PVRecord");
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecord::lock() {thelock.lock();}
|
||||||
|
|
||||||
|
void PVRecord::unlock() {thelock.unlock();}
|
||||||
|
|
||||||
|
bool PVRecord::tryLock() {return thelock.tryLock();}
|
||||||
|
|
||||||
|
bool PVRecord::addPVRecordClient(PVRecordClientPtr const & pvRecordClient)
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
std::list<PVRecordClientPtr>::iterator iter;
|
||||||
|
for (iter = pvRecordClientList.begin();
|
||||||
|
iter!=pvRecordClientList.end();
|
||||||
|
iter++ )
|
||||||
|
{
|
||||||
|
if((*iter).get()==pvRecordClient.get()) {
|
||||||
|
unlock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pvRecordClientList.push_back(pvRecordClient);
|
||||||
|
unlock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PVRecord::removePVRecordClient(PVRecordClientPtr const & pvRecordClient)
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
std::list<PVRecordClientPtr>::iterator iter;
|
||||||
|
for (iter = pvRecordClientList.begin();
|
||||||
|
iter!=pvRecordClientList.end();
|
||||||
|
iter++ )
|
||||||
|
{
|
||||||
|
if((*iter).get()==pvRecordClient.get()) {
|
||||||
|
pvRecordClientList.erase(iter);
|
||||||
|
unlock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unlock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecord::detachClients()
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
std::list<PVRecordClientPtr>::iterator iter;
|
||||||
|
for (iter = pvRecordClientList.begin();
|
||||||
|
iter!=pvRecordClientList.end();
|
||||||
|
iter++ )
|
||||||
|
{
|
||||||
|
(*iter)->detach(getPtrSelf());
|
||||||
|
}
|
||||||
|
pvRecordClientList.clear();
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecord::beginGroupPut()
|
||||||
|
{
|
||||||
|
if(++depthGroupPut>1) return;
|
||||||
|
std::list<PVListenerPtr>::iterator iter;
|
||||||
|
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++)
|
||||||
|
{
|
||||||
|
(*iter).get()->beginGroupPut(getPtrSelf());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecord::endGroupPut()
|
||||||
|
{
|
||||||
|
if(--depthGroupPut>0) return;
|
||||||
|
std::list<PVListenerPtr>::iterator iter;
|
||||||
|
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++)
|
||||||
|
{
|
||||||
|
(*iter).get()->endGroupPut(getPtrSelf());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PVRecord::addListener(PVListenerPtr const & pvListener)
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
std::list<PVListenerPtr>::iterator iter;
|
||||||
|
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ )
|
||||||
|
{
|
||||||
|
if((*iter).get()==pvListener.get()) {
|
||||||
|
unlock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pvListenerList.push_back(pvListener);
|
||||||
|
unlock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PVRecord::removeListener(PVListenerPtr const & pvListener)
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
std::list<PVListenerPtr>::iterator iter;
|
||||||
|
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ )
|
||||||
|
{
|
||||||
|
if((*iter).get()==pvListener.get()) {
|
||||||
|
pvListenerList.erase(iter);
|
||||||
|
unlock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unlock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecord::queueProcessRequest(
|
||||||
|
RecordProcessRequesterPtr const &recordProcessRequester)
|
||||||
|
{
|
||||||
|
bool isFirst = false;
|
||||||
|
lock();
|
||||||
|
processRequesterQueue.push_back(recordProcessRequester);
|
||||||
|
if(processRequesterQueue.size()==1) isFirst = true;
|
||||||
|
unlock();
|
||||||
|
if(isFirst) recordProcessRequester->becomeProcessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecord::dequeueProcessRequest(
|
||||||
|
RecordProcessRequesterPtr const &recordProcessRequester)
|
||||||
|
{
|
||||||
|
RecordProcessRequesterPtr next;
|
||||||
|
lock();
|
||||||
|
RecordProcessRequesterPtr processRequester =
|
||||||
|
processRequesterQueue[0];
|
||||||
|
if(processRequester.get()!=recordProcessRequester.get()) {
|
||||||
|
message(
|
||||||
|
"PVRecord::dequeueProcessRequest illegal requester",
|
||||||
|
errorMessage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
processRequesterQueue.pop_front();
|
||||||
|
if(processRequesterQueue.size()>0) next = processRequesterQueue[0];
|
||||||
|
unlock();
|
||||||
|
if(next.get()!=NULL) next->becomeProcessor();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PVRecord::addRequester(epics::pvData::RequesterPtr const & requester)
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
std::list<RequesterPtr>::iterator iter;
|
||||||
|
for (iter = requesterList.begin(); iter!=requesterList.end(); iter++ ) {
|
||||||
|
if((*iter).get()==requester.get()) {
|
||||||
|
unlock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
requesterList.push_back(requester);
|
||||||
|
unlock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PVRecord::removeRequester(epics::pvData::RequesterPtr const & requester)
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
std::list<RequesterPtr>::iterator iter;
|
||||||
|
for (iter = requesterList.begin(); iter!=requesterList.end(); iter++ ) {
|
||||||
|
if((*iter).get()==requester.get()) {
|
||||||
|
requesterList.erase(iter);
|
||||||
|
unlock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unlock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecord::message(String const & message,MessageType messageType)
|
||||||
|
{
|
||||||
|
if(requesterList.size()==0 ) {
|
||||||
|
String xxx(getMessageTypeName(messageType) + " " + message);
|
||||||
|
printf("%s\n",xxx.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::list<epics::pvData::RequesterPtr>::iterator iter;
|
||||||
|
for(iter = requesterList.begin(); iter != requesterList.end(); ++iter) {
|
||||||
|
(*iter)->message(message,messageType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecord::message(
|
||||||
|
PVRecordFieldPtr const & pvRecordField,
|
||||||
|
String const & message,
|
||||||
|
MessageType messageType)
|
||||||
|
{
|
||||||
|
this->message(pvRecordField->getFullName() + " " + message,messageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecord::toString(StringBuilder buf)
|
||||||
|
{
|
||||||
|
toString(buf,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecord::toString(StringBuilder buf,int indentLevel)
|
||||||
|
{
|
||||||
|
*buf += "\nrecord " + recordName + " ";
|
||||||
|
pvRecordStructure->getPVStructure()->toString(buf, indentLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
PVRecordField::PVRecordField(
|
||||||
|
PVFieldPtr const & pvField,
|
||||||
|
PVRecordStructurePtr const &parent,
|
||||||
|
PVRecordPtr const & pvRecord)
|
||||||
|
: pvField(pvField),
|
||||||
|
parent(parent),
|
||||||
|
pvRecord(pvRecord)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecordField::init()
|
||||||
|
{
|
||||||
|
fullFieldName = pvField->getFieldName();
|
||||||
|
PVRecordStructurePtr pvParent = parent;
|
||||||
|
while(pvParent.get()!= NULL) {
|
||||||
|
String parentName = pvParent->getPVField()->getFieldName();
|
||||||
|
if(parentName.size()>0) {
|
||||||
|
fullFieldName = pvParent->getPVField()->getFieldName()
|
||||||
|
+ '.' + fullFieldName;
|
||||||
|
}
|
||||||
|
pvParent = pvParent->getParent();
|
||||||
|
}
|
||||||
|
if(fullFieldName.size()>0) {
|
||||||
|
fullName = pvRecord->getRecordName() + '.' + fullFieldName;
|
||||||
|
} else {
|
||||||
|
fullName = pvRecord->getRecordName();
|
||||||
|
}
|
||||||
|
pvField->setPostHandler(getPtrSelf());
|
||||||
|
}
|
||||||
|
|
||||||
|
PVRecordField::~PVRecordField() {}
|
||||||
|
|
||||||
|
PVRecordStructurePtr PVRecordField::getParent() {return parent;}
|
||||||
|
|
||||||
|
PVFieldPtr PVRecordField::getPVField() {return pvField;}
|
||||||
|
|
||||||
|
String PVRecordField::getFullFieldName() {return fullFieldName; }
|
||||||
|
|
||||||
|
String PVRecordField::getFullName() {return fullName; }
|
||||||
|
|
||||||
|
PVRecordPtr PVRecordField::getPVRecord() {return pvRecord;}
|
||||||
|
|
||||||
|
bool PVRecordField::addListener(PVListenerPtr const & pvListener)
|
||||||
|
{
|
||||||
|
std::list<PVListenerPtr>::iterator iter;
|
||||||
|
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
|
||||||
|
if((*iter).get()==pvListener.get()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pvListenerList.push_back(pvListener);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecordField::removeListener(PVListenerPtr const & pvListener)
|
||||||
|
{
|
||||||
|
std::list<PVListenerPtr>::iterator iter;
|
||||||
|
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
|
||||||
|
if((*iter).get()==pvListener.get()) {
|
||||||
|
pvListenerList.erase(iter);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecordField::postPut()
|
||||||
|
{
|
||||||
|
callListener();
|
||||||
|
std::list<PVListenerPtr>::iterator iter;
|
||||||
|
PVRecordStructurePtr pvParent = getParent();
|
||||||
|
while(pvParent.get()!=NULL) {
|
||||||
|
std::list<PVListenerPtr> list = pvParent->pvListenerList;
|
||||||
|
for (iter = list.begin(); iter!=list.end(); iter++ ) {
|
||||||
|
(*iter)->dataPut(pvParent,getPtrSelf());
|
||||||
|
}
|
||||||
|
pvParent = pvParent->getParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecordField::message(String const & message,MessageType messageType)
|
||||||
|
{
|
||||||
|
pvRecord->message(getPtrSelf(),message,messageType);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecordField::callListener()
|
||||||
|
{
|
||||||
|
std::list<PVListenerPtr>::iterator iter;
|
||||||
|
for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
|
||||||
|
(*iter)->dataPut(getPtrSelf());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PVRecordStructure::PVRecordStructure(
|
||||||
|
PVStructurePtr const &pvStructure,
|
||||||
|
PVRecordStructurePtr const &parent,
|
||||||
|
PVRecordPtr const & pvRecord)
|
||||||
|
:
|
||||||
|
PVRecordField(pvStructure,parent,pvRecord),
|
||||||
|
pvStructure(pvStructure),
|
||||||
|
pvRecordFields(new PVRecordFieldPtrArray)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PVRecordStructure::~PVRecordStructure() {}
|
||||||
|
|
||||||
|
void PVRecordStructure::init()
|
||||||
|
{
|
||||||
|
PVRecordField::init();
|
||||||
|
const PVFieldPtrArray & pvFields = pvStructure->getPVFields();
|
||||||
|
size_t numFields = pvFields.size();
|
||||||
|
pvRecordFields->reserve( numFields);
|
||||||
|
PVRecordStructurePtr self =
|
||||||
|
static_pointer_cast<PVRecordStructure>(getPtrSelf());
|
||||||
|
PVRecordPtr pvRecord = getPVRecord();
|
||||||
|
for(size_t i=0; i<numFields; i++) {
|
||||||
|
PVFieldPtr pvField = pvFields[i];
|
||||||
|
if(pvField->getField()->getType()==structure) {
|
||||||
|
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
|
||||||
|
PVRecordStructurePtr pvRecordStructure(
|
||||||
|
new PVRecordStructure(xxx,self,pvRecord));
|
||||||
|
pvRecordFields->push_back(pvRecordStructure);
|
||||||
|
pvRecordStructure->init();
|
||||||
|
} else {
|
||||||
|
PVRecordFieldPtr pvRecordField(
|
||||||
|
new PVRecordField(pvField,self,pvRecord));
|
||||||
|
pvRecordFields->push_back(pvRecordField);
|
||||||
|
pvRecordField->init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PVRecordFieldPtrArrayPtr PVRecordStructure::getPVRecordFields()
|
||||||
|
{
|
||||||
|
return pvRecordFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
PVStructurePtr PVRecordStructure::getPVStructure() {return pvStructure;}
|
||||||
|
|
||||||
|
void PVRecordStructure::removeListener(PVListenerPtr const & pvListener)
|
||||||
|
{
|
||||||
|
PVRecordField::removeListener(pvListener);
|
||||||
|
size_t numFields = pvRecordFields->size();
|
||||||
|
for(size_t i=0; i<numFields; i++) {
|
||||||
|
PVRecordFieldPtr pvRecordField = (*pvRecordFields.get())[i];
|
||||||
|
pvRecordField->removeListener(pvListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVRecordStructure::postPut()
|
||||||
|
{
|
||||||
|
PVRecordField::postPut();
|
||||||
|
size_t numFields = pvRecordFields->size();
|
||||||
|
for(size_t i=0; i<numFields; i++) {
|
||||||
|
PVRecordFieldPtr pvRecordField = (*pvRecordFields.get())[i];
|
||||||
|
pvRecordField->callListener();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PVDatabase::PVDatabase()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PVDatabase::~PVDatabase() {}
|
||||||
|
|
||||||
|
PVDatabasePtr PVDatabase::getMaster()
|
||||||
|
{
|
||||||
|
PVDatabasePtr xxx;
|
||||||
|
return xxx;
|
||||||
|
}
|
||||||
|
|
||||||
|
PVRecordPtr PVDatabase::findRecord(String const& recordName)
|
||||||
|
{
|
||||||
|
PVRecordPtr xxx;
|
||||||
|
return xxx;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PVDatabase::addRecord(PVRecordPtr const & record)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PVDatabase::removeRecord(PVRecordPtr const & record)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String PVDatabase::getRequesterName()
|
||||||
|
{
|
||||||
|
String xxx;
|
||||||
|
return xxx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVDatabase::message(String const & message,MessageType messageType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
||||||
|
@ -11,7 +11,11 @@
|
|||||||
#ifndef PVDATABASE_H
|
#ifndef PVDATABASE_H
|
||||||
#define PVDATABASE_H
|
#define PVDATABASE_H
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
#include <pv/pvAccess.h>
|
#include <pv/pvAccess.h>
|
||||||
|
#include <pv/convert.h>
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
@ -39,7 +43,9 @@ class PVDatabase;
|
|||||||
typedef std::tr1::shared_ptr<PVDatabase> PVDatabasePtr;
|
typedef std::tr1::shared_ptr<PVDatabase> PVDatabasePtr;
|
||||||
|
|
||||||
|
|
||||||
class PVRecord
|
class PVRecord :
|
||||||
|
public epics::pvData::Requester,
|
||||||
|
public std::tr1::enable_shared_from_this<PVRecord>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(PVRecord);
|
POINTER_DEFINITIONS(PVRecord);
|
||||||
@ -48,7 +54,8 @@ public:
|
|||||||
epics::pvData::PVStructurePtr const & pvStructure);
|
epics::pvData::PVStructurePtr const & pvStructure);
|
||||||
virtual ~PVRecord();
|
virtual ~PVRecord();
|
||||||
virtual void process(
|
virtual void process(
|
||||||
RecordProcessRequesterPtr const &recordProcessRequester) = 0;
|
RecordProcessRequesterPtr const &recordProcessRequester,
|
||||||
|
bool alreadyLocked) = 0;
|
||||||
virtual bool isSynchronous() = 0;
|
virtual bool isSynchronous() = 0;
|
||||||
epics::pvData::String getRecordName();
|
epics::pvData::String getRecordName();
|
||||||
PVRecordStructurePtr getPVRecordStructure();
|
PVRecordStructurePtr getPVRecordStructure();
|
||||||
@ -56,34 +63,63 @@ public:
|
|||||||
epics::pvData::PVFieldPtr const & pvField);
|
epics::pvData::PVFieldPtr const & pvField);
|
||||||
void lock();
|
void lock();
|
||||||
void unlock();
|
void unlock();
|
||||||
void registerClient(PVRecordClientPtr const & pvRecordClient);
|
bool tryLock();
|
||||||
void unregisterClient(PVRecordClientPtr const & pvRecordClient);
|
bool addPVRecordClient(PVRecordClientPtr const & pvRecordClient);
|
||||||
|
bool removePVRecordClient(PVRecordClientPtr const & pvRecordClient);
|
||||||
void detachClients();
|
void detachClients();
|
||||||
void beginGroupPut();
|
void beginGroupPut();
|
||||||
void endGroupPut();
|
void endGroupPut();
|
||||||
void registerListener(PVListenerPtr const & pvListener);
|
bool addListener(PVListenerPtr const & pvListener);
|
||||||
void unregisterListener(PVListenerPtr const & pvListener);
|
bool removeListener(PVListenerPtr const & pvListener);
|
||||||
void removeEveryListener();
|
|
||||||
epics::pvData::Status processRequest();
|
|
||||||
void queueProcessRequest(
|
void queueProcessRequest(
|
||||||
RecordProcessRequesterPtr const &recordProcessRequester);
|
RecordProcessRequesterPtr const &recordProcessRequester);
|
||||||
void addRequester(epics::pvData::RequesterPtr const & requester);
|
void dequeueProcessRequest(
|
||||||
void removeRequester(epics::pvData::RequesterPtr const & requester);
|
RecordProcessRequesterPtr const &recordProcessRequester);
|
||||||
void message(
|
bool addRequester(epics::pvData::RequesterPtr const & requester);
|
||||||
|
bool removeRequester(epics::pvData::RequesterPtr const & requester);
|
||||||
|
virtual epics::pvData::String getRequesterName() {return getRecordName();}
|
||||||
|
virtual void message(
|
||||||
epics::pvData::String const & message,
|
epics::pvData::String const & message,
|
||||||
epics::pvData::MessageType messageType);
|
epics::pvData::MessageType messageType);
|
||||||
epics::pvData::String toString();
|
void message(
|
||||||
epics::pvData::String toString(int indentLevel);
|
PVRecordFieldPtr const & pvRecordField,
|
||||||
|
epics::pvData::String const & message,
|
||||||
|
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();
|
||||||
|
protected:
|
||||||
|
PVRecordPtr getPtrSelf()
|
||||||
|
{
|
||||||
|
return shared_from_this();
|
||||||
|
}
|
||||||
private:
|
private:
|
||||||
|
PVRecordFieldPtr findPVRecordField(
|
||||||
|
PVRecordStructurePtr const & pvrs,
|
||||||
|
epics::pvData::PVFieldPtr const & pvField);
|
||||||
epics::pvData::String recordName;
|
epics::pvData::String recordName;
|
||||||
epics::pvData::PVStructurePtr pvStructure;
|
epics::pvData::PVStructurePtr pvStructure;
|
||||||
|
epics::pvData::ConvertPtr convert;
|
||||||
|
PVRecordStructurePtr pvRecordStructure;
|
||||||
|
std::deque<RecordProcessRequesterPtr> processRequesterQueue;
|
||||||
|
std::list<PVListenerPtr> pvListenerList;
|
||||||
|
std::list<PVRecordClientPtr> pvRecordClientList;
|
||||||
|
std::list<epics::pvData::RequesterPtr> requesterList;
|
||||||
|
epics::pvData::Mutex mutex;
|
||||||
|
epics::pvData::Lock thelock;
|
||||||
|
int depthGroupPut;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PVRecordField {
|
class PVRecordField :
|
||||||
|
public virtual epics::pvData::PostHandler,
|
||||||
|
public std::tr1::enable_shared_from_this<PVRecordField>
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(PVRecordField);
|
POINTER_DEFINITIONS(PVRecordField);
|
||||||
PVRecordField(
|
PVRecordField(
|
||||||
epics::pvData::PVFieldPtr const & pvField,
|
epics::pvData::PVFieldPtr const & pvField,
|
||||||
|
PVRecordStructurePtr const &parent,
|
||||||
PVRecordPtr const & pvRecord);
|
PVRecordPtr const & pvRecord);
|
||||||
virtual ~PVRecordField();
|
virtual ~PVRecordField();
|
||||||
PVRecordStructurePtr getParent();
|
PVRecordStructurePtr getParent();
|
||||||
@ -92,11 +128,28 @@ public:
|
|||||||
epics::pvData::String getFullName();
|
epics::pvData::String getFullName();
|
||||||
PVRecordPtr getPVRecord();
|
PVRecordPtr getPVRecord();
|
||||||
bool addListener(PVListenerPtr const & pvListener);
|
bool addListener(PVListenerPtr const & pvListener);
|
||||||
void removeListener(PVListenerPtr const & pvListener);
|
virtual void removeListener(PVListenerPtr const & pvListener);
|
||||||
void postPut();
|
virtual void postPut();
|
||||||
virtual void message(
|
virtual void message(
|
||||||
epics::pvData::String const & message,
|
epics::pvData::String const & message,
|
||||||
epics::pvData::MessageType messageType);
|
epics::pvData::MessageType messageType);
|
||||||
|
protected:
|
||||||
|
PVRecordFieldPtr getPtrSelf()
|
||||||
|
{
|
||||||
|
return shared_from_this();
|
||||||
|
}
|
||||||
|
virtual void init();
|
||||||
|
private:
|
||||||
|
void callListener();
|
||||||
|
|
||||||
|
std::list<PVListenerPtr> pvListenerList;
|
||||||
|
epics::pvData::PVFieldPtr pvField;
|
||||||
|
PVRecordStructurePtr parent;
|
||||||
|
PVRecordPtr pvRecord;
|
||||||
|
epics::pvData::String fullName;
|
||||||
|
epics::pvData::String fullFieldName;
|
||||||
|
friend class PVRecordStructure;
|
||||||
|
friend class PVRecord;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PVRecordStructure : public PVRecordField {
|
class PVRecordStructure : public PVRecordField {
|
||||||
@ -104,19 +157,25 @@ public:
|
|||||||
POINTER_DEFINITIONS(PVRecordStructure);
|
POINTER_DEFINITIONS(PVRecordStructure);
|
||||||
PVRecordStructure(
|
PVRecordStructure(
|
||||||
epics::pvData::PVStructurePtr const &pvStructure,
|
epics::pvData::PVStructurePtr const &pvStructure,
|
||||||
PVRecordFieldPtrArrayPtr const &pvRecordField);
|
PVRecordStructurePtr const &parent,
|
||||||
|
PVRecordPtr const & pvRecord);
|
||||||
virtual ~PVRecordStructure();
|
virtual ~PVRecordStructure();
|
||||||
PVRecordFieldPtrArrayPtr getPVRecordFields();
|
PVRecordFieldPtrArrayPtr getPVRecordFields();
|
||||||
epics::pvData::PVStructurePtr getPVStructure();
|
epics::pvData::PVStructurePtr getPVStructure();
|
||||||
virtual void message(
|
virtual void removeListener(PVListenerPtr const & pvListener);
|
||||||
epics::pvData::String const & message,
|
virtual void postPut();
|
||||||
epics::pvData::MessageType messageType);
|
protected:
|
||||||
|
virtual void init();
|
||||||
|
private:
|
||||||
|
epics::pvData::PVStructurePtr pvStructure;
|
||||||
|
PVRecordFieldPtrArrayPtr pvRecordFields;
|
||||||
|
friend class PVRecord;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PVListener {
|
class PVListener {
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(PVListener);
|
POINTER_DEFINITIONS(PVListener);
|
||||||
virtual ~PVListener();
|
virtual ~PVListener() {}
|
||||||
virtual void dataPut(PVRecordFieldPtr const & pvRecordField) = 0;
|
virtual void dataPut(PVRecordFieldPtr const & pvRecordField) = 0;
|
||||||
virtual void dataPut(
|
virtual void dataPut(
|
||||||
PVRecordStructurePtr const & requested,
|
PVRecordStructurePtr const & requested,
|
||||||
@ -131,15 +190,16 @@ class RecordProcessRequester :
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(RecordProcessRequester);
|
POINTER_DEFINITIONS(RecordProcessRequester);
|
||||||
virtual ~RecordProcessRequester();
|
virtual ~RecordProcessRequester() {}
|
||||||
virtual void becomeProcessor() = 0;
|
virtual void becomeProcessor() = 0;
|
||||||
virtual void recordProcessResult(epics::pvData::Status status) = 0;
|
virtual void recordProcessResult(epics::pvData::Status status) = 0;
|
||||||
virtual void recordProcessComplete() = 0;
|
virtual void recordProcessComplete() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PVRecordClient {
|
class PVRecordClient {
|
||||||
|
public:
|
||||||
POINTER_DEFINITIONS(PVRecordClient);
|
POINTER_DEFINITIONS(PVRecordClient);
|
||||||
virtual ~PVRecordClient();
|
virtual ~PVRecordClient() {}
|
||||||
virtual void detach(PVRecordPtr const & pvRecord) = 0;
|
virtual void detach(PVRecordPtr const & pvRecord) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -151,6 +211,10 @@ public:
|
|||||||
PVRecordPtr findRecord(epics::pvData::String const& recordName);
|
PVRecordPtr findRecord(epics::pvData::String const& recordName);
|
||||||
bool addRecord(PVRecordPtr const & record);
|
bool addRecord(PVRecordPtr const & record);
|
||||||
bool removeRecord(PVRecordPtr const & record);
|
bool removeRecord(PVRecordPtr const & record);
|
||||||
|
virtual epics::pvData::String getRequesterName();
|
||||||
|
virtual void message(
|
||||||
|
epics::pvData::String const & message,
|
||||||
|
epics::pvData::MessageType messageType);
|
||||||
private:
|
private:
|
||||||
PVDatabase();
|
PVDatabase();
|
||||||
};
|
};
|
||||||
|
5
test/Makefile
Normal file
5
test/Makefile
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
TOP = ..
|
||||||
|
include $(TOP)/configure/CONFIG
|
||||||
|
DIRS += record
|
||||||
|
include $(TOP)/configure/RULES_DIRS
|
||||||
|
|
13
test/record/Makefile
Normal file
13
test/record/Makefile
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
TOP=../..
|
||||||
|
|
||||||
|
include $(TOP)/configure/CONFIG
|
||||||
|
|
||||||
|
PROD_HOST += testRecord
|
||||||
|
testRecord_SRCS += testRecord.cpp
|
||||||
|
testRecord_SRCS += testRecordMain.cpp
|
||||||
|
testRecord_LIBS += pvDatabase pvAccess pvData Com
|
||||||
|
|
||||||
|
include $(TOP)/configure/RULES
|
||||||
|
#----------------------------------------
|
||||||
|
# ADD RULES AFTER THIS LINE
|
||||||
|
|
68
test/record/testRecord.cpp
Normal file
68
test/record/testRecord.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/* 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");
|
||||||
|
PVRecordPtr pvRecord(new TestRecord(recordName,pvStructure,pvValue));
|
||||||
|
pvRecord->init();
|
||||||
|
return pvRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestRecord::TestRecord(
|
||||||
|
String const & recordName,
|
||||||
|
PVStructurePtr const & pvStructure,
|
||||||
|
PVLongPtr const &pvValue)
|
||||||
|
: PVRecord(recordName,pvStructure),
|
||||||
|
pvValue(pvValue)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool TestRecord::isSynchronous() {return true;}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
43
test/record/testRecord.h
Normal file
43
test/record/testRecord.h
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* 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;
|
||||||
|
|
||||||
|
class TestRecord :
|
||||||
|
public virtual PVRecord
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
POINTER_DEFINITIONS(TestRecord);
|
||||||
|
static PVRecordPtr create(epics::pvData::String const & recordName);
|
||||||
|
virtual ~TestRecord();
|
||||||
|
virtual bool isSynchronous();
|
||||||
|
virtual void process(
|
||||||
|
epics::pvDatabase::RecordProcessRequesterPtr const &processRequester,
|
||||||
|
bool alreadyLocked);
|
||||||
|
private:
|
||||||
|
TestRecord(epics::pvData::String const & recordName,
|
||||||
|
epics::pvData::PVStructurePtr const & pvStructure,
|
||||||
|
epics::pvData::PVLongPtr const &pvValue);
|
||||||
|
epics::pvData::PVLongPtr pvValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif /* TEST_RECORD_H */
|
296
test/record/testRecordMain.cpp
Normal file
296
test/record/testRecordMain.cpp
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
/*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 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 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->addListener(getPtrSelf());
|
||||||
|
pvRecordField->addListener(getPtrSelf());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isDetached;
|
||||||
|
String requesterName;
|
||||||
|
PVRecordPtr pvRecord;
|
||||||
|
PVRecordFieldPtr pvRecordField;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MyProcessRequester :
|
||||||
|
public virtual Requester,
|
||||||
|
public virtual RecordProcessRequester,
|
||||||
|
public PVRecordClient,
|
||||||
|
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 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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 pvValueAlarm = pvStructure->getSubField("valueAlarm");
|
||||||
|
PVRecordFieldPtr recordFieldValueAlarm =
|
||||||
|
pvRecord->findPVRecordField(pvValueAlarm);
|
||||||
|
MyPVListenerPtr listenValueAlarm = MyPVListener::create(
|
||||||
|
"listenValueAlarm", pvRecord,recordFieldValueAlarm);
|
||||||
|
PVIntPtr pvHighAlarmSeverity =
|
||||||
|
pvStructure->getIntField("valueAlarm.highAlarmSeverity");
|
||||||
|
PVRecordFieldPtr recordFieldHighAlarmSeverity =
|
||||||
|
pvRecord->findPVRecordField(pvHighAlarmSeverity);
|
||||||
|
MyPVListenerPtr listenHighAlarmSeverity = MyPVListener::create(
|
||||||
|
"listenHighAlarmSeverity", pvRecord,recordFieldHighAlarmSeverity);
|
||||||
|
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());
|
||||||
|
pvHighAlarmSeverity->put(3);
|
||||||
|
recordFieldHighAlarmSeverity->message("test message",infoMessage);
|
||||||
|
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