more code implemented. See pvDatabaseCPP.html for details

This commit is contained in:
Marty Kraimer
2013-04-18 15:16:26 -04:00
parent 124d28d33e
commit 26c977c0ae
16 changed files with 1725 additions and 201 deletions
+2
View File
@@ -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
+20 -2
View File
@@ -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);
}
}}
+6
View File
@@ -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
View File
@@ -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()
+16 -1
View File
@@ -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
View File
@@ -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();
+111
View File
@@ -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);
}
}}
+44
View File
@@ -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
View File
@@ -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(
+15 -7
View File
@@ -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()
+5 -7
View File
@@ -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;
}