more code implemented. See pvDatabaseCPP.html for details
This commit is contained in:
@@ -11,8 +11,10 @@ SRC_DIRS += $(DATABASE)/database
|
||||
INC += pvDatabase.h
|
||||
INC += powerSupplyRecordTest.h
|
||||
INC += exampleCounter.h
|
||||
INC += recordList.h
|
||||
LIBSRCS += pvRecord.cpp
|
||||
LIBSRCS += pvDatabase.cpp
|
||||
LIBSRCS += recordList.cpp
|
||||
|
||||
SRC_DIRS += $(DATABASE)/pvAccess
|
||||
INC += channelProviderLocal.h
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/standardPVField.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/pvTimeStamp.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
@@ -27,20 +29,23 @@ public:
|
||||
POINTER_DEFINITIONS(ExampleCounter);
|
||||
static ExampleCounterPtr create(
|
||||
epics::pvData::String const & recordName);
|
||||
virtual ~ExampleCounter(){}
|
||||
virtual ~ExampleCounter();
|
||||
virtual void destroy();
|
||||
virtual bool init();
|
||||
virtual void process();
|
||||
private:
|
||||
ExampleCounter(epics::pvData::String const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure);
|
||||
epics::pvData::PVLongPtr pvValue;
|
||||
epics::pvData::PVTimeStamp pvTimeStamp;
|
||||
epics::pvData::TimeStamp timeStamp;
|
||||
};
|
||||
|
||||
ExampleCounterPtr ExampleCounter::create(
|
||||
epics::pvData::String const & recordName)
|
||||
{
|
||||
epics::pvData::PVStructurePtr pvStructure =
|
||||
epics::pvData::getStandardPVField()->scalar(epics::pvData::pvLong,"timeStamp");
|
||||
epics::pvData::getStandardPVField()->scalar(epics::pvData::pvLong,"timeStamp,alarm");
|
||||
ExampleCounterPtr pvRecord(
|
||||
new ExampleCounter(recordName,pvStructure));
|
||||
if(!pvRecord->init()) pvRecord.reset();
|
||||
@@ -52,6 +57,17 @@ ExampleCounter::ExampleCounter(
|
||||
epics::pvData::PVStructurePtr const & pvStructure)
|
||||
: PVRecord(recordName,pvStructure)
|
||||
{
|
||||
pvTimeStamp.attach(pvStructure->getSubField("timeStamp"));
|
||||
}
|
||||
|
||||
ExampleCounter::~ExampleCounter()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void ExampleCounter::destroy()
|
||||
{
|
||||
PVRecord::destroy();
|
||||
}
|
||||
|
||||
bool ExampleCounter::init()
|
||||
@@ -67,6 +83,8 @@ bool ExampleCounter::init()
|
||||
void ExampleCounter::process()
|
||||
{
|
||||
pvValue->put(pvValue->get() + 1.0);
|
||||
timeStamp.getCurrent();
|
||||
pvTimeStamp.set(timeStamp);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
epics::pvData::String const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure);
|
||||
virtual ~PowerSupplyRecordTest();
|
||||
virtual void destroy();
|
||||
virtual bool init();
|
||||
virtual void process();
|
||||
void put(double power,double voltage);
|
||||
@@ -72,6 +73,11 @@ PowerSupplyRecordTest::~PowerSupplyRecordTest()
|
||||
destroy();
|
||||
}
|
||||
|
||||
void PowerSupplyRecordTest::destroy()
|
||||
{
|
||||
PVRecord::destroy();
|
||||
}
|
||||
|
||||
bool PowerSupplyRecordTest::init()
|
||||
{
|
||||
initPVRecord();
|
||||
|
||||
+80
-20
@@ -18,8 +18,6 @@ using namespace std;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
PVDatabase::~PVDatabase() {}
|
||||
|
||||
PVDatabasePtr PVDatabase::getMaster()
|
||||
{
|
||||
static PVDatabasePtr master;
|
||||
@@ -31,36 +29,98 @@ PVDatabasePtr PVDatabase::getMaster()
|
||||
return master;
|
||||
}
|
||||
|
||||
PVDatabase::PVDatabase() {}
|
||||
PVDatabase::PVDatabase()
|
||||
: thelock(mutex),
|
||||
isDestroyed(false)
|
||||
{
|
||||
thelock.unlock();
|
||||
}
|
||||
|
||||
PVDatabase::~PVDatabase()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void PVDatabase::destroy()
|
||||
{
|
||||
lock();
|
||||
if(isDestroyed) {
|
||||
unlock();
|
||||
return;
|
||||
}
|
||||
isDestroyed = true;
|
||||
PVRecordMap::iterator iter;
|
||||
while(true) {
|
||||
iter = recordMap.begin();
|
||||
if(iter==recordMap.end()) break;
|
||||
PVRecordPtr pvRecord = (*iter).second;
|
||||
recordMap.erase(iter);
|
||||
unlock();
|
||||
if(pvRecord.get()!=NULL) pvRecord->destroy();
|
||||
lock();
|
||||
}
|
||||
}
|
||||
|
||||
void PVDatabase::lock() {thelock.lock();}
|
||||
|
||||
void PVDatabase::unlock() {thelock.unlock();}
|
||||
|
||||
PVRecordPtr PVDatabase::findRecord(String const& recordName)
|
||||
{
|
||||
PVRecordMap::iterator iter = recordMap.find(recordName);
|
||||
if(iter!=recordMap.end()) {
|
||||
lock_guard();
|
||||
PVRecordPtr xxx;
|
||||
if(isDestroyed) return xxx;
|
||||
PVRecordMap::iterator iter = recordMap.find(recordName);
|
||||
if(iter!=recordMap.end()) {
|
||||
return (*iter).second;
|
||||
}
|
||||
PVRecordPtr xxx;
|
||||
return xxx;
|
||||
}
|
||||
return xxx;
|
||||
}
|
||||
|
||||
PVStringArrayPtr PVDatabase::getRecordNames()
|
||||
{
|
||||
lock_guard();
|
||||
PVStringArrayPtr pvStringArray = static_pointer_cast<PVStringArray>
|
||||
(getPVDataCreate()->createPVScalarArray(pvString));
|
||||
size_t len = recordMap.size();
|
||||
std::vector<String> names(len);
|
||||
PVRecordMap::iterator iter;
|
||||
size_t i = 0;
|
||||
for(iter = recordMap.begin(); iter!=recordMap.end(); ++iter) {
|
||||
names[i++] = (*iter).first;
|
||||
}
|
||||
pvStringArray->put(0,len,names,0);
|
||||
return pvStringArray;
|
||||
}
|
||||
|
||||
bool PVDatabase::addRecord(PVRecordPtr const & record)
|
||||
{
|
||||
String recordName = record->getRecordName();
|
||||
PVRecordMap::iterator iter = recordMap.find(recordName);
|
||||
if(iter!=recordMap.end()) return false;
|
||||
recordMap.insert(PVRecordMap::value_type(recordName,record));
|
||||
return true;
|
||||
lock_guard();
|
||||
if(isDestroyed) return false;
|
||||
String recordName = record->getRecordName();
|
||||
PVRecordMap::iterator iter = recordMap.find(recordName);
|
||||
if(iter!=recordMap.end()) {
|
||||
return false;
|
||||
}
|
||||
recordMap.insert(PVRecordMap::value_type(recordName,record));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PVDatabase::removeRecord(PVRecordPtr const & record)
|
||||
{
|
||||
String recordName = record->getRecordName();
|
||||
PVRecordMap::iterator iter = recordMap.find(recordName);
|
||||
if(iter!=recordMap.end()) {
|
||||
recordMap.erase(iter);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
lock();
|
||||
if(isDestroyed) return false;
|
||||
String recordName = record->getRecordName();
|
||||
PVRecordMap::iterator iter = recordMap.find(recordName);
|
||||
if(iter!=recordMap.end()) {
|
||||
PVRecordPtr pvRecord = (*iter).second;
|
||||
recordMap.erase(iter);
|
||||
unlock();
|
||||
if(pvRecord.get()!=NULL) pvRecord->destroy();
|
||||
return true;
|
||||
}
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
String PVDatabase::getRequesterName()
|
||||
|
||||
@@ -118,7 +118,7 @@ public:
|
||||
* The record will automatically
|
||||
* be unlocked when control leaves the block that has the call.
|
||||
*/
|
||||
inline void lock_guard() { epics::pvData::Lock theLock(mutex); }
|
||||
inline void lock_guard() { epics::pvData::Lock thelock(mutex); }
|
||||
/**
|
||||
* Lock the record.
|
||||
* Any code must lock while accessing a record.
|
||||
@@ -488,6 +488,10 @@ public:
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~PVDatabase();
|
||||
/**
|
||||
* Destroy the PVDatabase.
|
||||
*/
|
||||
virtual void destroy();
|
||||
/**
|
||||
* Find a record.
|
||||
* An empty pointer is returned if the record is not in the database.
|
||||
@@ -507,6 +511,11 @@ public:
|
||||
* @return <b>true</b> if record was removed.
|
||||
*/
|
||||
bool removeRecord(PVRecordPtr const & record);
|
||||
/**
|
||||
* Get the names of all the records in the database.
|
||||
* @return The names.
|
||||
*/
|
||||
epics::pvData::PVStringArrayPtr getRecordNames();
|
||||
/**
|
||||
* Virtual method of Requester.
|
||||
* @return The name.
|
||||
@@ -523,7 +532,13 @@ public:
|
||||
epics::pvData::MessageType messageType);
|
||||
private:
|
||||
PVDatabase();
|
||||
void lock();
|
||||
void unlock();
|
||||
inline void lock_guard() { epics::pvData::Lock thelock(mutex); }
|
||||
PVRecordMap recordMap;
|
||||
epics::pvData::Mutex mutex;
|
||||
epics::pvData::Lock thelock;
|
||||
bool isDestroyed;
|
||||
|
||||
};
|
||||
|
||||
|
||||
+16
-12
@@ -68,29 +68,29 @@ void PVRecord::destroy()
|
||||
isDestroyed = true;
|
||||
|
||||
std::list<RequesterPtr>::iterator requesterIter;
|
||||
for (
|
||||
requesterIter = requesterList.begin();
|
||||
requesterIter!=requesterList.end();
|
||||
requesterIter++ ) {
|
||||
while(true) {
|
||||
requesterIter = requesterList.begin();
|
||||
if(requesterIter==requesterList.end()) break;
|
||||
requesterList.erase(requesterIter);
|
||||
unlock();
|
||||
(*requesterIter)->message("record destroyed",fatalErrorMessage);
|
||||
lock();
|
||||
}
|
||||
requesterList.clear();
|
||||
|
||||
std::list<PVRecordClientPtr>::iterator clientIter;
|
||||
for (clientIter = pvRecordClientList.begin();
|
||||
clientIter!=pvRecordClientList.end();
|
||||
clientIter++ )
|
||||
{
|
||||
while(true) {
|
||||
clientIter = pvRecordClientList.begin();
|
||||
if(clientIter==pvRecordClientList.end()) break;
|
||||
pvRecordClientList.erase(clientIter);
|
||||
unlock();
|
||||
(*clientIter)->detach(getPtrSelf());
|
||||
lock();
|
||||
}
|
||||
pvRecordClientList.clear();
|
||||
|
||||
pvListenerList.clear();
|
||||
pvRecordStructure->destroy();
|
||||
pvRecordStructure.reset();
|
||||
convert.reset();
|
||||
pvStructure.reset();
|
||||
|
||||
unlock();
|
||||
}
|
||||
|
||||
@@ -211,6 +211,10 @@ bool PVRecord::addPVRecordClient(PVRecordClientPtr const & pvRecordClient)
|
||||
bool PVRecord::removePVRecordClient(PVRecordClientPtr const & pvRecordClient)
|
||||
{
|
||||
lock();
|
||||
if(isDestroyed) {
|
||||
unlock();
|
||||
return false;
|
||||
}
|
||||
std::list<PVRecordClientPtr>::iterator iter;
|
||||
for (iter = pvRecordClientList.begin();
|
||||
iter!=pvRecordClientList.end();
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/* recordListTest.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
|
||||
* @date 2013.04.18
|
||||
*/
|
||||
|
||||
#include <pv/recordList.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
RecordListRecordPtr RecordListRecord::create(
|
||||
epics::pvData::String const & recordName)
|
||||
{
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
StringArray argNames(2);
|
||||
FieldConstPtrArray argFields(2);
|
||||
argNames[0] = "database";
|
||||
argFields[0] = fieldCreate->createScalar(pvString);
|
||||
argNames[1] = "regularExpression";
|
||||
argFields[1] = fieldCreate->createScalar(pvString);
|
||||
StringArray resNames(2);
|
||||
FieldConstPtrArray resFields(2);
|
||||
resNames[0] = "status";
|
||||
resFields[0] = fieldCreate->createScalar(pvString);
|
||||
resNames[1] = "names";
|
||||
resFields[1] = fieldCreate->createScalarArray(pvString);
|
||||
StringArray topNames(2);
|
||||
FieldConstPtrArray topFields(2);
|
||||
topNames[0] = "arguments";
|
||||
topFields[0] = fieldCreate->createStructure(argNames,argFields);
|
||||
topNames[1] = "result";
|
||||
topFields[1] = fieldCreate->createStructure(resNames,resFields);
|
||||
StructureConstPtr topStructure =
|
||||
fieldCreate->createStructure(topNames,topFields);
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||
RecordListRecordPtr pvRecord(
|
||||
new RecordListRecord(recordName,pvStructure));
|
||||
if(!pvRecord->init()) pvRecord.reset();
|
||||
return pvRecord;
|
||||
}
|
||||
|
||||
RecordListRecord::RecordListRecord(
|
||||
epics::pvData::String const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure)
|
||||
: PVRecord(recordName,pvStructure)
|
||||
{
|
||||
}
|
||||
|
||||
RecordListRecord::~RecordListRecord()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void RecordListRecord::destroy()
|
||||
{
|
||||
PVRecord::destroy();
|
||||
}
|
||||
|
||||
bool RecordListRecord::init()
|
||||
{
|
||||
initPVRecord();
|
||||
PVStructurePtr pvStructure = getPVStructure();
|
||||
database = pvStructure->getStringField("arguments.database");
|
||||
if(database.get()==NULL) return false;
|
||||
regularExpression = pvStructure->getStringField(
|
||||
"arguments.regularExpression");
|
||||
if(regularExpression.get()==NULL) return false;
|
||||
status = pvStructure->getStringField("result.status");
|
||||
if(status.get()==NULL) return false;
|
||||
PVFieldPtr pvField = pvStructure->getSubField("result.names");
|
||||
if(pvField.get()==NULL) {
|
||||
std::cerr << "no result.names" << std::endl;
|
||||
return false;
|
||||
}
|
||||
names = static_pointer_cast<PVStringArray>(
|
||||
pvStructure->getScalarArrayField("result.names",pvString));
|
||||
if(names.get()==NULL) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RecordListRecord::process()
|
||||
{
|
||||
PVStringArrayPtr pvNames = PVDatabase::getMaster()->getRecordNames();
|
||||
std::vector<String> const & xxx = pvNames->getVector();
|
||||
size_t n = xxx.size();
|
||||
names->put(0,n,xxx,0);
|
||||
String message("");
|
||||
if(database->get().compare("master")!=0) {
|
||||
message += " can only access master ";
|
||||
}
|
||||
String regEx = regularExpression->get();
|
||||
if(regEx.compare("")!=0 && regEx.compare(".*")!=0) {
|
||||
message += " regularExpression not implemented ";
|
||||
}
|
||||
status->put(message);
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/* recordListTest.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.18
|
||||
*/
|
||||
#ifndef RECORDLIST_H
|
||||
#define RECORDLIST_H
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
|
||||
class RecordListRecord;
|
||||
typedef std::tr1::shared_ptr<RecordListRecord> RecordListRecordPtr;
|
||||
|
||||
class RecordListRecord :
|
||||
public PVRecord
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(RecordListRecord);
|
||||
static RecordListRecordPtr create(
|
||||
epics::pvData::String const & recordName);
|
||||
virtual ~RecordListRecord();
|
||||
virtual void destroy();
|
||||
virtual bool init();
|
||||
virtual void process();
|
||||
private:
|
||||
RecordListRecord(epics::pvData::String const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure);
|
||||
epics::pvData::PVStringPtr database;
|
||||
epics::pvData::PVStringPtr regularExpression;
|
||||
epics::pvData::PVStringPtr status;
|
||||
epics::pvData::PVStringArrayPtr names;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* RECORDLIST_H */
|
||||
+419
-61
@@ -55,45 +55,97 @@ static bool getProcess(PVStructurePtr pvRequest,bool processDefault)
|
||||
return processDefault;
|
||||
}
|
||||
|
||||
/*
|
||||
class ChannelRequestLocal :
|
||||
public ChannelRequest
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelRequestLocal)
|
||||
ChannelRequestLocal() :thelock(mutex) {}
|
||||
virtual ~ChannelRequestLocal() {}
|
||||
virtual void destroy(){}
|
||||
virtual void lock() {thelock.lock();}
|
||||
virtual void unlock() {thelock.unlock();}
|
||||
private:
|
||||
Mutex mutex;
|
||||
Lock thelock;
|
||||
};
|
||||
*/
|
||||
|
||||
|
||||
class ChannelProcessLocal :
|
||||
public ChannelProcess
|
||||
public ChannelProcess,
|
||||
public std::tr1::enable_shared_from_this<ChannelProcessLocal>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelProcessLocal);
|
||||
virtual ~ChannelProcessLocal();
|
||||
static ChannelProcess::shared_pointer create(
|
||||
ChannelProviderLocalPtr const &channelProvider,
|
||||
ChannelProcess::shared_pointer const & channelProcessRequester,
|
||||
virtual ~ChannelProcessLocal() {destroy();}
|
||||
static ChannelProcessLocalPtr create(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelProcessRequester::shared_pointer const & channelProcessRequester,
|
||||
PVStructurePtr const & pvRequest,
|
||||
PVRecordPtr const &pvRecord);
|
||||
virtual void process(bool lastRequest);
|
||||
virtual void destroy();
|
||||
virtual void lock() {thelock.lock();}
|
||||
virtual void unlock() {thelock.unlock();}
|
||||
private:
|
||||
shared_pointer getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
ChannelProcessLocal(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelProcessRequester::shared_pointer const & channelProcessRequester,
|
||||
PVRecordPtr const &pvRecord)
|
||||
:
|
||||
isDestroyed(false),
|
||||
channelLocal(channelLocal),
|
||||
channelProcessRequester(channelProcessRequester),
|
||||
pvRecord(pvRecord),
|
||||
thelock(mutex)
|
||||
{
|
||||
thelock.unlock();
|
||||
}
|
||||
bool isDestroyed;
|
||||
bool callProcess;
|
||||
ChannelLocalPtr channelLocal;
|
||||
ChannelProcessRequester::shared_pointer channelProcessRequester,;
|
||||
PVRecordPtr pvRecord;
|
||||
Mutex mutex;
|
||||
Lock thelock;
|
||||
};
|
||||
|
||||
ChannelProcessLocalPtr ChannelProcessLocal::create(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelProcessRequester::shared_pointer const & channelProcessRequester,
|
||||
PVStructurePtr const & pvRequest,
|
||||
PVRecordPtr const &pvRecord)
|
||||
{
|
||||
ChannelProcessLocalPtr process(new ChannelProcessLocal(
|
||||
channelLocal,
|
||||
channelProcessRequester,
|
||||
pvRecord));
|
||||
channelLocal->addChannelProcess(process);
|
||||
channelProcessRequester->channelProcessConnect(Status::Ok, process);
|
||||
return process;
|
||||
}
|
||||
|
||||
|
||||
void ChannelProcessLocal::destroy()
|
||||
{
|
||||
if(isDestroyed) return;
|
||||
isDestroyed = true;
|
||||
channelLocal->removeChannelProcess(getPtrSelf());
|
||||
channelLocal.reset();
|
||||
channelProcessRequester.reset();
|
||||
pvRecord.reset();
|
||||
}
|
||||
|
||||
void ChannelProcessLocal::process(bool lastRequest)
|
||||
{
|
||||
pvRecord->lock();
|
||||
pvRecord->process();
|
||||
pvRecord->unlock();
|
||||
if(isDestroyed) {
|
||||
Status status(
|
||||
Status::Status::STATUSTYPE_ERROR,
|
||||
"was destroyed");
|
||||
channelProcessRequester->processDone(status);
|
||||
}
|
||||
channelProcessRequester->processDone(Status::Ok);
|
||||
if(lastRequest) destroy();
|
||||
}
|
||||
|
||||
class ChannelGetLocal :
|
||||
public ChannelGet,
|
||||
public std::tr1::enable_shared_from_this<ChannelGetLocal>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelGetLocal);
|
||||
virtual ~ChannelGetLocal(){}
|
||||
virtual ~ChannelGetLocal(){destroy();}
|
||||
static ChannelGetLocalPtr create(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelGetRequester::shared_pointer const & channelGetRequester,
|
||||
@@ -199,14 +251,17 @@ void ChannelGetLocal::destroy()
|
||||
|
||||
void ChannelGetLocal::get(bool lastRequest)
|
||||
{
|
||||
if(callProcess) pvRecord->process();
|
||||
if(isDestroyed) {
|
||||
Status status(
|
||||
Status::Status::STATUSTYPE_ERROR,
|
||||
"was destroyed");
|
||||
channelGetRequester->getDone(status);
|
||||
}
|
||||
bitSet->clear();
|
||||
pvRecord->lock();
|
||||
if(callProcess) pvRecord->process();
|
||||
pvCopy->updateCopySetBitSet(pvStructure, bitSet, false);
|
||||
pvRecord->unlock();
|
||||
if(firstTime) {
|
||||
bitSet->clear();
|
||||
bitSet->set(0);
|
||||
@@ -216,38 +271,332 @@ void ChannelGetLocal::get(bool lastRequest)
|
||||
if(lastRequest) destroy();
|
||||
}
|
||||
|
||||
|
||||
class ChannelLocalPut :
|
||||
public ChannelPut
|
||||
class ChannelPutLocal :
|
||||
public ChannelPut,
|
||||
public std::tr1::enable_shared_from_this<ChannelPutLocal>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelLocalPut);
|
||||
virtual ~ChannelLocalPut();
|
||||
static ChannelPut::shared_pointer create(
|
||||
ChannelProviderLocalPtr const &channelProvider,
|
||||
ChannelPut::shared_pointer const & channelPutRequester,
|
||||
POINTER_DEFINITIONS(ChannelPutLocal);
|
||||
virtual ~ChannelPutLocal(){destroy();}
|
||||
static ChannelPutLocalPtr create(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelPutRequester::shared_pointer const & channelPutRequester,
|
||||
PVStructurePtr const & pvRequest,
|
||||
PVRecordPtr const &pvRecord);
|
||||
virtual void put(bool lastRequest);
|
||||
virtual void get(bool lastRequest);
|
||||
virtual void get();
|
||||
virtual void destroy();
|
||||
virtual void lock() {thelock.lock();}
|
||||
virtual void unlock() {thelock.unlock();}
|
||||
private:
|
||||
shared_pointer getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
ChannelPutLocal(
|
||||
bool callProcess,
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelPutRequester::shared_pointer const & channelPutRequester,
|
||||
PVCopyPtr const &pvCopy,
|
||||
PVStructurePtr const&pvStructure,
|
||||
BitSetPtr const & bitSet,
|
||||
PVRecordPtr const &pvRecord)
|
||||
:
|
||||
isDestroyed(false),
|
||||
callProcess(callProcess),
|
||||
channelLocal(channelLocal),
|
||||
channelPutRequester(channelPutRequester),
|
||||
pvCopy(pvCopy),
|
||||
pvStructure(pvStructure),
|
||||
bitSet(bitSet),
|
||||
pvRecord(pvRecord),
|
||||
thelock(mutex)
|
||||
{
|
||||
thelock.unlock();
|
||||
}
|
||||
bool isDestroyed;
|
||||
bool callProcess;
|
||||
ChannelLocalPtr channelLocal;
|
||||
ChannelPutRequester::shared_pointer channelPutRequester,;
|
||||
PVCopyPtr pvCopy;
|
||||
PVStructurePtr pvStructure;
|
||||
BitSetPtr bitSet;
|
||||
PVRecordPtr pvRecord;
|
||||
Mutex mutex;
|
||||
Lock thelock;
|
||||
};
|
||||
|
||||
ChannelPutLocalPtr ChannelPutLocal::create(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelPutRequester::shared_pointer const & channelPutRequester,
|
||||
PVStructurePtr const & pvRequest,
|
||||
PVRecordPtr const &pvRecord)
|
||||
{
|
||||
PVCopyPtr pvCopy = PVCopy::create(
|
||||
pvRecord,
|
||||
pvRequest,
|
||||
"field");
|
||||
if(pvCopy.get()==NULL) {
|
||||
Status status(
|
||||
Status::Status::STATUSTYPE_ERROR,
|
||||
"invalid pvRequest");
|
||||
ChannelPut::shared_pointer channelPut;
|
||||
PVStructurePtr pvStructure;
|
||||
BitSetPtr bitSet;
|
||||
channelPutRequester->channelPutConnect(
|
||||
status,
|
||||
channelPut,
|
||||
pvStructure,
|
||||
bitSet);
|
||||
ChannelPutLocalPtr localPut;
|
||||
return localPut;
|
||||
}
|
||||
PVStructurePtr pvStructure = pvCopy->createPVStructure();
|
||||
BitSetPtr bitSet(new BitSet(pvStructure->getNumberFields()));
|
||||
ChannelPutLocalPtr put(new ChannelPutLocal(
|
||||
getProcess(pvRequest,true),
|
||||
channelLocal,
|
||||
channelPutRequester,
|
||||
pvCopy,
|
||||
pvStructure,
|
||||
bitSet,
|
||||
pvRecord));
|
||||
channelLocal->addChannelPut(put);
|
||||
channelPutRequester->channelPutConnect(Status::Ok, put, pvStructure,bitSet);
|
||||
return put;
|
||||
}
|
||||
|
||||
void ChannelPutLocal::destroy()
|
||||
{
|
||||
if(isDestroyed) return;
|
||||
isDestroyed = true;
|
||||
channelLocal->removeChannelPut(getPtrSelf());
|
||||
channelLocal.reset();
|
||||
channelPutRequester.reset();
|
||||
pvCopy.reset();
|
||||
pvStructure.reset();
|
||||
bitSet.reset();
|
||||
pvRecord.reset();
|
||||
}
|
||||
|
||||
void ChannelPutLocal::get()
|
||||
{
|
||||
if(isDestroyed) {
|
||||
Status status(
|
||||
Status::Status::STATUSTYPE_ERROR,
|
||||
"was destroyed");
|
||||
channelPutRequester->getDone(status);
|
||||
}
|
||||
bitSet->clear();
|
||||
bitSet->set(0);
|
||||
pvRecord->lock();
|
||||
pvCopy->updateCopyFromBitSet(pvStructure, bitSet, false);
|
||||
pvRecord->unlock();
|
||||
channelPutRequester->getDone(Status::Ok);
|
||||
}
|
||||
|
||||
void ChannelPutLocal::put(bool lastRequest)
|
||||
{
|
||||
if(isDestroyed) {
|
||||
Status status(
|
||||
Status::Status::STATUSTYPE_ERROR,
|
||||
"was destroyed");
|
||||
channelPutRequester->getDone(status);
|
||||
}
|
||||
pvRecord->lock();
|
||||
pvCopy->updateRecord(pvStructure, bitSet, false);
|
||||
if(callProcess) pvRecord->process();
|
||||
pvRecord->unlock();
|
||||
channelPutRequester->getDone(Status::Ok);
|
||||
if(lastRequest) destroy();
|
||||
}
|
||||
|
||||
|
||||
class ChannelPutGetLocal :
|
||||
public ChannelPutGet
|
||||
public ChannelPutGet,
|
||||
public std::tr1::enable_shared_from_this<ChannelPutGetLocal>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelPutGetLocal);
|
||||
virtual ~ChannelPutGetLocal();
|
||||
static ChannelPutGet::shared_pointer create(
|
||||
ChannelProviderLocalPtr const &channelProvider,
|
||||
ChannelPutGet::shared_pointer const & channelPutGetRequester,
|
||||
virtual ~ChannelPutGetLocal(){destroy();}
|
||||
static ChannelPutGetLocalPtr create(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelPutGetRequester::shared_pointer const & channelPutGetRequester,
|
||||
PVStructurePtr const & pvRequest,
|
||||
PVRecordPtr const &pvRecord);
|
||||
virtual void putGet(bool lastRequest);
|
||||
virtual void getPut();
|
||||
virtual void getGet();
|
||||
virtual void destroy();
|
||||
virtual void lock() {thelock.lock();}
|
||||
virtual void unlock() {thelock.unlock();}
|
||||
private:
|
||||
shared_pointer getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
ChannelPutGetLocal(
|
||||
bool callProcess,
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelPutGetRequester::shared_pointer const & channelPutGetRequester,
|
||||
PVCopyPtr const &pvPutCopy,
|
||||
PVCopyPtr const &pvGetCopy,
|
||||
PVStructurePtr const&pvPutStructure,
|
||||
PVStructurePtr const&pvGetStructure,
|
||||
BitSetPtr const & putBitSet,
|
||||
BitSetPtr const & getBitSet,
|
||||
PVRecordPtr const &pvRecord)
|
||||
:
|
||||
isDestroyed(false),
|
||||
callProcess(callProcess),
|
||||
channelLocal(channelLocal),
|
||||
channelPutGetRequester(channelPutGetRequester),
|
||||
pvPutCopy(pvPutCopy),
|
||||
pvGetCopy(pvGetCopy),
|
||||
pvPutStructure(pvPutStructure),
|
||||
pvGetStructure(pvGetStructure),
|
||||
putBitSet(putBitSet),
|
||||
getBitSet(getBitSet),
|
||||
pvRecord(pvRecord),
|
||||
thelock(mutex)
|
||||
{
|
||||
thelock.unlock();
|
||||
}
|
||||
bool isDestroyed;
|
||||
bool callProcess;
|
||||
ChannelLocalPtr channelLocal;
|
||||
ChannelPutGetRequester::shared_pointer channelPutGetRequester,;
|
||||
PVCopyPtr pvPutCopy;
|
||||
PVCopyPtr pvGetCopy;
|
||||
PVStructurePtr pvPutStructure;
|
||||
PVStructurePtr pvGetStructure;
|
||||
BitSetPtr putBitSet;
|
||||
BitSetPtr getBitSet;
|
||||
PVRecordPtr pvRecord;
|
||||
Mutex mutex;
|
||||
Lock thelock;
|
||||
};
|
||||
|
||||
ChannelPutGetLocalPtr ChannelPutGetLocal::create(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelPutGetRequester::shared_pointer const & channelPutGetRequester,
|
||||
PVStructurePtr const & pvRequest,
|
||||
PVRecordPtr const &pvRecord)
|
||||
{
|
||||
PVCopyPtr pvPutCopy = PVCopy::create(
|
||||
pvRecord,
|
||||
pvRequest,
|
||||
"putField");
|
||||
PVCopyPtr pvGetCopy = PVCopy::create(
|
||||
pvRecord,
|
||||
pvRequest,
|
||||
"getField");
|
||||
if(pvPutCopy.get()==NULL || pvGetCopy.get()==NULL) {
|
||||
Status status(
|
||||
Status::Status::STATUSTYPE_ERROR,
|
||||
"invalid pvRequest");
|
||||
ChannelPutGet::shared_pointer channelPutGet;
|
||||
PVStructurePtr pvStructure;
|
||||
BitSetPtr bitSet;
|
||||
channelPutGetRequester->channelPutGetConnect(
|
||||
status,
|
||||
channelPutGet,
|
||||
pvStructure,
|
||||
pvStructure);
|
||||
ChannelPutGetLocalPtr localPutGet;
|
||||
return localPutGet;
|
||||
}
|
||||
PVStructurePtr pvPutStructure = pvPutCopy->createPVStructure();
|
||||
PVStructurePtr pvGetStructure = pvGetCopy->createPVStructure();
|
||||
BitSetPtr putBitSet(new BitSet(pvPutStructure->getNumberFields()));
|
||||
BitSetPtr getBitSet(new BitSet(pvGetStructure->getNumberFields()));
|
||||
ChannelPutGetLocalPtr putGet(new ChannelPutGetLocal(
|
||||
getProcess(pvRequest,true),
|
||||
channelLocal,
|
||||
channelPutGetRequester,
|
||||
pvPutCopy,
|
||||
pvGetCopy,
|
||||
pvPutStructure,
|
||||
pvGetStructure,
|
||||
putBitSet,
|
||||
getBitSet,
|
||||
pvRecord));
|
||||
channelLocal->addChannelPutGet(putGet);
|
||||
channelPutGetRequester->channelPutGetConnect(
|
||||
Status::Ok, putGet, pvPutStructure,pvGetStructure);
|
||||
return putGet;
|
||||
}
|
||||
|
||||
|
||||
void ChannelPutGetLocal::destroy()
|
||||
{
|
||||
if(isDestroyed) return;
|
||||
isDestroyed = true;
|
||||
channelLocal->removeChannelPutGet(getPtrSelf());
|
||||
channelLocal.reset();
|
||||
channelPutGetRequester.reset();
|
||||
pvPutCopy.reset();
|
||||
pvGetCopy.reset();
|
||||
pvPutStructure.reset();
|
||||
pvGetStructure.reset();
|
||||
putBitSet.reset();
|
||||
getBitSet.reset();
|
||||
pvRecord.reset();
|
||||
}
|
||||
|
||||
void ChannelPutGetLocal::putGet(bool lastRequest)
|
||||
{
|
||||
if(isDestroyed) {
|
||||
Status status(
|
||||
Status::Status::STATUSTYPE_ERROR,
|
||||
"was destroyed");
|
||||
channelPutGetRequester->putGetDone(status);
|
||||
}
|
||||
putBitSet->clear();
|
||||
putBitSet->set(0);
|
||||
pvRecord->lock();
|
||||
pvPutCopy->updateRecord(pvPutStructure, putBitSet, false);
|
||||
if(callProcess) pvRecord->process();
|
||||
pvGetCopy->updateCopySetBitSet(pvGetStructure, getBitSet, false);
|
||||
pvRecord->unlock();
|
||||
getBitSet->clear();
|
||||
getBitSet->set(0);
|
||||
channelPutGetRequester->putGetDone(Status::Ok);
|
||||
if(lastRequest) destroy();
|
||||
}
|
||||
|
||||
void ChannelPutGetLocal::getPut()
|
||||
{
|
||||
if(isDestroyed) {
|
||||
Status status(
|
||||
Status::Status::STATUSTYPE_ERROR,
|
||||
"was destroyed");
|
||||
channelPutGetRequester->getPutDone(status);
|
||||
}
|
||||
pvRecord->lock();
|
||||
pvPutCopy->updateCopySetBitSet(pvPutStructure, putBitSet, false);
|
||||
pvRecord->unlock();
|
||||
putBitSet->clear();
|
||||
putBitSet->set(0);
|
||||
channelPutGetRequester->getPutDone(Status::Ok);
|
||||
}
|
||||
|
||||
void ChannelPutGetLocal::getGet()
|
||||
{
|
||||
if(isDestroyed) {
|
||||
Status status(
|
||||
Status::Status::STATUSTYPE_ERROR,
|
||||
"was destroyed");
|
||||
channelPutGetRequester->getGetDone(status);
|
||||
}
|
||||
pvRecord->lock();
|
||||
pvGetCopy->updateCopySetBitSet(pvGetStructure, getBitSet, false);
|
||||
pvRecord->unlock();
|
||||
getBitSet->clear();
|
||||
getBitSet->set(0);
|
||||
channelPutGetRequester->getGetDone(Status::Ok);
|
||||
}
|
||||
|
||||
class ChannelMonitorLocal :
|
||||
public Monitor
|
||||
{
|
||||
@@ -573,6 +922,16 @@ bool ChannelLocal::isConnected()
|
||||
void ChannelLocal::getField(GetFieldRequester::shared_pointer const &requester,
|
||||
String const &subField)
|
||||
{
|
||||
if(subField.size()<1) {
|
||||
StructureConstPtr structure = pvRecord->getPVRecordStructure()->getPVStructure()->getStructure();
|
||||
requester->getDone(Status::Ok,structure);
|
||||
return;
|
||||
}
|
||||
PVFieldPtr pvField = pvRecord->getPVRecordStructure()->getPVStructure()->getSubField(subField);
|
||||
if(pvField.get()!=NULL) {
|
||||
requester->getDone(Status::Ok,pvField->getField());
|
||||
return;
|
||||
}
|
||||
Status status(Status::STATUSTYPE_ERROR,
|
||||
String("client asked for illegal field"));
|
||||
requester->getDone(status,FieldConstPtr());
|
||||
@@ -588,12 +947,13 @@ ChannelProcess::shared_pointer ChannelLocal::createChannelProcess(
|
||||
ChannelProcessRequester::shared_pointer const & channelProcessRequester,
|
||||
PVStructure::shared_pointer const & pvRequest)
|
||||
{
|
||||
Status status(Status::STATUSTYPE_ERROR,
|
||||
String("ChannelProcess not supported"));
|
||||
channelProcessRequester->channelProcessConnect(
|
||||
status,
|
||||
ChannelProcess::shared_pointer());
|
||||
return ChannelProcess::shared_pointer();
|
||||
ChannelProcessLocalPtr channelProcess =
|
||||
ChannelProcessLocal::create(
|
||||
getPtrSelf(),
|
||||
channelProcessRequester,
|
||||
pvRequest,
|
||||
pvRecord);
|
||||
return channelProcess;
|
||||
}
|
||||
|
||||
ChannelGet::shared_pointer ChannelLocal::createChannelGet(
|
||||
@@ -613,28 +973,26 @@ ChannelPut::shared_pointer ChannelLocal::createChannelPut(
|
||||
ChannelPutRequester::shared_pointer const &channelPutRequester,
|
||||
PVStructure::shared_pointer const &pvRequest)
|
||||
{
|
||||
Status status(Status::STATUSTYPE_ERROR,
|
||||
String("ChannelPut not supported"));
|
||||
channelPutRequester->channelPutConnect(
|
||||
status,
|
||||
ChannelPut::shared_pointer(),
|
||||
PVStructure::shared_pointer(),
|
||||
BitSet::shared_pointer());
|
||||
return ChannelPut::shared_pointer();
|
||||
ChannelPutLocalPtr channelPut =
|
||||
ChannelPutLocal::create(
|
||||
getPtrSelf(),
|
||||
channelPutRequester,
|
||||
pvRequest,
|
||||
pvRecord);
|
||||
return channelPut;
|
||||
}
|
||||
|
||||
ChannelPutGet::shared_pointer ChannelLocal::createChannelPutGet(
|
||||
ChannelPutGetRequester::shared_pointer const &channelPutGetRequester,
|
||||
PVStructure::shared_pointer const &pvRequest)
|
||||
{
|
||||
Status status(Status::STATUSTYPE_ERROR,
|
||||
String("ChannelPutGet not supported"));
|
||||
channelPutGetRequester->channelPutGetConnect(
|
||||
status,
|
||||
ChannelPutGet::shared_pointer(),
|
||||
PVStructure::shared_pointer(),
|
||||
PVStructure::shared_pointer());
|
||||
return ChannelPutGet::shared_pointer();
|
||||
ChannelPutGetLocalPtr channelPutGet =
|
||||
ChannelPutGetLocal::create(
|
||||
getPtrSelf(),
|
||||
channelPutGetRequester,
|
||||
pvRequest,
|
||||
pvRecord);
|
||||
return channelPutGet;
|
||||
}
|
||||
|
||||
ChannelRPC::shared_pointer ChannelLocal::createChannelRPC(
|
||||
|
||||
@@ -21,6 +21,7 @@ static String providerName("local");
|
||||
|
||||
class LocalChannelCTX;
|
||||
typedef std::tr1::shared_ptr<LocalChannelCTX> LocalChannelCTXPtr;
|
||||
|
||||
class LocalChannelCTX :
|
||||
public epics::pvData::Runnable,
|
||||
public std::tr1::enable_shared_from_this<LocalChannelCTX>
|
||||
@@ -77,6 +78,7 @@ LocalChannelCTX::~LocalChannelCTX()
|
||||
// we need thead.waitForCompletion()
|
||||
event.wait();
|
||||
epicsThreadSleep(1.0);
|
||||
ctx.reset();
|
||||
delete thread;
|
||||
}
|
||||
void LocalChannelCTX::run()
|
||||
@@ -87,7 +89,11 @@ void LocalChannelCTX::run()
|
||||
ctx->initialize(getChannelAccess());
|
||||
ctx->printInfo();
|
||||
ctx->run(0);
|
||||
ctx->destroy();
|
||||
// Matej if I switch which is commented then errors when exit
|
||||
// BUT this way causes lots of memory leaks
|
||||
channelProvider->destroy();
|
||||
//ctx->destroy();
|
||||
// Matej end of comments
|
||||
event.signal();
|
||||
}
|
||||
|
||||
@@ -107,21 +113,23 @@ ChannelProviderLocal::ChannelProviderLocal()
|
||||
|
||||
ChannelProviderLocal::~ChannelProviderLocal()
|
||||
{
|
||||
pvDatabase.reset();
|
||||
destroy();
|
||||
}
|
||||
|
||||
void ChannelProviderLocal::destroy()
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(beingDestroyed) return;
|
||||
unregisterChannelProvider(getPtrSelf());
|
||||
beingDestroyed = true;
|
||||
ChannelLocalList::iterator iter;
|
||||
for(iter = channelList.begin(); iter!=channelList.end(); ++iter) {
|
||||
ChannelLocalPtr channel = *iter;
|
||||
channel->destroy();
|
||||
while(true) {
|
||||
iter = channelList.begin();
|
||||
if(iter==channelList.end()) break;
|
||||
(*iter)->destroy();
|
||||
channelList.erase(iter);
|
||||
}
|
||||
channelList.clear();
|
||||
|
||||
pvDatabase->destroy();
|
||||
}
|
||||
|
||||
String ChannelProviderLocal::getProviderName()
|
||||
|
||||
@@ -60,19 +60,17 @@ PVCopyPtr PVCopy::create(
|
||||
PVStructurePtr const &pvRequest,
|
||||
String const & structureName)
|
||||
{
|
||||
PVStructurePtr pvStructure(pvRequest);
|
||||
if(structureName.size()>0) {
|
||||
if(pvRequest->getStructure()->getNumberFields()>0) {
|
||||
PVStructurePtr pvStructure
|
||||
= pvRequest->getStructureField(structureName);
|
||||
pvStructure = pvRequest->getStructureField(structureName);
|
||||
if(pvStructure.get()==NULL) return NULLPVCopy;
|
||||
}
|
||||
} else if(pvStructure->getSubField("field")!=NULL) {
|
||||
pvStructure = pvRequest->getStructureField("field");
|
||||
}
|
||||
PVCopyPtr pvCopy = PVCopyPtr(new PVCopy(pvRecord));
|
||||
PVStructurePtr pvStruct = pvRequest;
|
||||
if(pvRequest->getSubField("field")!=NULL) {
|
||||
pvStruct = pvRequest->getStructureField("field");
|
||||
}
|
||||
bool result = pvCopy->init(pvStruct);
|
||||
bool result = pvCopy->init(pvStructure);
|
||||
if(!result) pvCopy.reset();
|
||||
return pvCopy;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user