Merge pull request #18 from mrkraimer/master

Compatibility with pvDatabaseJava; on-line delete; database termination
This commit is contained in:
Marty Kraimer
2016-07-01 10:36:17 -04:00
committed by GitHub
12 changed files with 89 additions and 123 deletions

View File

@ -44,21 +44,20 @@ PVDatabase::~PVDatabase()
void PVDatabase::destroy()
{
{
epicsGuard<epics::pvData::Mutex> guard(mutex);
if(isDestroyed) {
return;
}
isDestroyed = true;
PVRecordMap::iterator iter;
while(true) {
iter = recordMap.begin();
if(iter==recordMap.end()) break;
}
for(PVRecordMap::iterator iter = recordMap.begin(); iter != recordMap.end(); iter++) {
PVRecordPtr pvRecord = (*iter).second;
recordMap.erase(iter);
if(pvRecord) {
pvRecord->destroy();
}
}
recordMap.clear();
}
void PVDatabase::lock() {
@ -83,27 +82,6 @@ PVRecordPtr PVDatabase::findRecord(string const& recordName)
return xxx;
}
PVStringArrayPtr PVDatabase::getRecordNames()
{
epicsGuard<epics::pvData::Mutex> guard(mutex);
PVStringArrayPtr xxx;
if(isDestroyed) {
return xxx;
}
PVStringArrayPtr pvStringArray = static_pointer_cast<PVStringArray>
(getPVDataCreate()->createPVScalarArray(pvString));
size_t len = recordMap.size();
shared_vector<string> names(len);
PVRecordMap::iterator iter;
size_t i = 0;
for(iter = recordMap.begin(); iter!=recordMap.end(); ++iter) {
names[i++] = (*iter).first;
}
shared_vector<const string> temp(freeze(names));
pvStringArray->replace(temp);
return pvStringArray;
}
bool PVDatabase::addRecord(PVRecordPtr const & record)
{
epicsGuard<epics::pvData::Mutex> guard(mutex);
@ -131,10 +109,31 @@ bool PVDatabase::removeRecord(PVRecordPtr const & record)
if(iter!=recordMap.end()) {
PVRecordPtr pvRecord = (*iter).second;
recordMap.erase(iter);
if(pvRecord.get()!=NULL) pvRecord->destroy();
if(pvRecord) pvRecord->destroy();
return true;
}
return false;
}
PVStringArrayPtr PVDatabase::getRecordNames()
{
epicsGuard<epics::pvData::Mutex> guard(mutex);
PVStringArrayPtr xxx;
if(isDestroyed) {
return xxx;
}
PVStringArrayPtr pvStringArray = static_pointer_cast<PVStringArray>
(getPVDataCreate()->createPVScalarArray(pvString));
size_t len = recordMap.size();
shared_vector<string> names(len);
PVRecordMap::iterator iter;
size_t i = 0;
for(iter = recordMap.begin(); iter!=recordMap.end(); ++iter) {
names[i++] = (*iter).first;
}
shared_vector<const string> temp(freeze(names));
pvStringArray->replace(temp);
return pvStringArray;
}
}}

View File

@ -66,11 +66,13 @@ void PVRecord::initPVRecord()
void PVRecord::destroy()
{
if(traceLevel>0) {
cout << "PVRecord::destroy() " << recordName << endl;
}
{
epicsGuard<epics::pvData::Mutex> guard(mutex);
if(traceLevel>0) {
cout << "PVRecord::destroy() " << recordName
<< " isDestroyed " << (isDestroyed ? "true" : "false")
<< endl;
}
if(isDestroyed) {
return;
}
@ -91,9 +93,8 @@ void PVRecord::destroy()
listener->unlisten(shared_from_this());
}
pvListenerList.clear();
std::list<PVRecordClientPtr>::iterator iter;
for (iter = pvRecordClientList.begin();
iter!=pvRecordClientList.end();
for (std::list<PVRecordClientPtr>::iterator iter = clientList.begin();
iter!=clientList.end();
iter++ )
{
PVRecordClientPtr client = *iter;
@ -103,7 +104,7 @@ void PVRecord::destroy()
}
client->detach(shared_from_this());
}
pvRecordClientList.clear();
clientList.clear();
}
void PVRecord::process()
@ -117,11 +118,6 @@ void PVRecord::process()
}
}
string PVRecord::getRecordName() const {return recordName;}
PVRecordStructurePtr PVRecord::getPVRecordStructure() const {return pvRecordStructure;}
PVStructurePtr PVRecord::getPVStructure() {return pvStructure;}
PVRecordFieldPtr PVRecord::findPVRecordField(PVFieldPtr const & pvField)
{
@ -199,8 +195,8 @@ bool PVRecord::addPVRecordClient(PVRecordClientPtr const & pvRecordClient)
return false;
}
std::list<PVRecordClientPtr>::iterator iter;
for (iter = pvRecordClientList.begin();
iter!=pvRecordClientList.end();
for (iter = clientList.begin();
iter!=clientList.end();
iter++ )
{
PVRecordClientPtr client = *iter;
@ -209,9 +205,9 @@ bool PVRecord::addPVRecordClient(PVRecordClientPtr const & pvRecordClient)
}
}
if(traceLevel>1) {
cout << "PVRecord::addPVRecordClient() calling pvRecordClientList.push_back(pvRecordClient)" << recordName << endl;
cout << "PVRecord::addPVRecordClient() calling clientList.push_back(pvRecordClient)" << recordName << endl;
}
pvRecordClientList.push_back(pvRecordClient);
clientList.push_back(pvRecordClient);
return true;
}
@ -225,14 +221,14 @@ bool PVRecord::removePVRecordClient(PVRecordClientPtr const & pvRecordClient)
return false;
}
std::list<PVRecordClientPtr>::iterator iter;
for (iter = pvRecordClientList.begin();
iter!=pvRecordClientList.end();
for (iter = clientList.begin();
iter!=clientList.end();
iter++ )
{
PVRecordClientPtr client = *iter;
if(!client) continue;
if(client==pvRecordClient) {
pvRecordClientList.erase(iter);
clientList.erase(iter);
return true;
}
}
@ -517,24 +513,4 @@ PVRecordFieldPtrArrayPtr PVRecordStructure::getPVRecordFields()
PVStructurePtr PVRecordStructure::getPVStructure() {return pvStructure.lock();}
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();
}
}
}}

View File

@ -100,6 +100,7 @@ private:
epicsShareFunc ChannelProviderLocalPtr getChannelProviderLocal();
/**
* @brief ChannelProvider for PVDatabase.
*
@ -229,6 +230,12 @@ public:
* The remote pvAccess server does this cleanup.
*/
virtual void destroy();
/**
* This is called when a record is being removed from the database.
* Calls destroy.
* @param pvRecord The record being destroyed.
*/
virtual void detach(PVRecordPtr const &pvRecord);
/**
* Get the requester name.
* @return returns the name of the channel requester.
@ -381,12 +388,6 @@ public:
* @param out the stream on which the message is displayed.
*/
virtual void printInfo(std::ostream& out);
/**
* This is called when a record is being removed from the database.
* Calls destroy.
* @param pvRecord The record being destroyed.
*/
virtual void detach(PVRecordPtr const &pvRecord);
protected:
shared_pointer getPtrSelf()
{
@ -396,7 +397,7 @@ private:
epics::pvAccess::ChannelRequester::shared_pointer requester;
ChannelProviderLocalPtr provider;
PVRecordPtr pvRecord;
bool beingDestroyed;
bool isDestroyed;
epics::pvData::Mutex mutex;
};

View File

@ -115,12 +115,17 @@ public:
* Get the name of the record.
* @return The name.
*/
std::string getRecordName() const;
std::string getRecordName() const { return recordName;}
/**
* Get the top level PVRecordStructure.
* @return The shared pointer.
*/
PVRecordStructurePtr getPVRecordStructure() const;
PVRecordStructurePtr getPVRecordStructure() const { return pvRecordStructure;}
/**
* Convenience method for derived classes.
* @return The top level PVStructure.
*/
epics::pvData::PVStructurePtr getPVStructure() const { return pvStructure;}
/**
* Find the PVRecordField for the PVField.
* @param pvField The PVField.
@ -232,11 +237,6 @@ protected:
* Initializes the base class. Must be called by derived classes.
*/
void initPVRecord();
/**
* Convience method for derived classes.
* @return The shared pointer to the top level PVStructure.
*/
epics::pvData::PVStructurePtr getPVStructure();
/** Get shared pointer to self
* @return The shared pointer.
*/
@ -253,7 +253,7 @@ private:
epics::pvData::PVStructurePtr pvStructure;
PVRecordStructurePtr pvRecordStructure;
std::list<PVListenerWPtr> pvListenerList;
std::list<PVRecordClientPtr> pvRecordClientList;
std::list<PVRecordClientPtr> clientList;
epics::pvData::Mutex mutex;
std::size_t depthGroupPut;
int traceLevel;
@ -378,17 +378,12 @@ public:
* @return The shared pointer.
*/
epics::pvData::PVStructurePtr getPVStructure();
/**
* Called by implementation code of PVRecord.
*/
virtual void postPut();
protected:
/**
* Called by implementation code of PVRecord.
*/
virtual void init();
private:
virtual void removeListener(PVListenerPtr const & pvListener);
epics::pvData::PVStructure::weak_pointer pvStructure;
PVRecordFieldPtrArrayPtr pvRecordFields;
friend class PVRecord;

View File

@ -65,7 +65,6 @@ private:
PVDatabasePtr pvDatabase;
epics::pvData::PVStringPtr pvRecordName;
epics::pvData::PVStringPtr pvResult;
bool isDestroyed;
};
}}

View File

@ -66,7 +66,6 @@ private:
epics::pvData::PVStringPtr pvRecordName;
epics::pvData::PVIntPtr pvLevel;
epics::pvData::PVStringPtr pvResult;
bool isDestroyed;
};
}}

View File

@ -1309,7 +1309,7 @@ ChannelLocal::ChannelLocal(
requester(requester),
provider(provider),
pvRecord(pvRecord),
beingDestroyed(false)
isDestroyed(false)
{
if(pvRecord->getTraceLevel()>0) {
cout << "ChannelLocal::ChannelLocal()"
@ -1325,6 +1325,7 @@ ChannelLocal::~ChannelLocal()
{
cout << "~ChannelLocal()" << endl;
}
destroy();
}
void ChannelLocal::destroy()
@ -1332,16 +1333,15 @@ void ChannelLocal::destroy()
if(pvRecord->getTraceLevel()>0) {
cout << "ChannelLocal::destroy()"
<< " recordName " << pvRecord->getRecordName()
<< " beingDestroyed " << beingDestroyed
<< " isDestroyed " << isDestroyed
<< " requester exists " << (requester ? "true" : "false")
<< endl;
}
{
Lock xx(mutex);
if(beingDestroyed) return;
beingDestroyed = true;
if(isDestroyed) return;
isDestroyed = true;
}
message("being destroyed",fatalErrorMessage);
pvRecord->removePVRecordClient(getPtrSelf());
}
@ -1383,7 +1383,7 @@ void ChannelLocal::message(
}
{
Lock xx(mutex);
if(beingDestroyed) return;
if(isDestroyed) return;
}
if(requester) {
requester->message(message,messageType);
@ -1403,7 +1403,7 @@ string ChannelLocal::getRemoteAddress()
Channel::ConnectionState ChannelLocal::getConnectionState()
{
Lock xx(mutex);
if(beingDestroyed) return Channel::DESTROYED;
if(isDestroyed) return Channel::DESTROYED;
return Channel::CONNECTED;
}
@ -1420,7 +1420,7 @@ ChannelRequester::shared_pointer ChannelLocal::getChannelRequester()
bool ChannelLocal::isConnected()
{
Lock xx(mutex);
if(beingDestroyed) return false;
if(isDestroyed) return false;
return true;
}

View File

@ -53,7 +53,7 @@ public:
}
virtual ChannelProvider::shared_pointer newInstance()
{
return channelProvider;
throw std::logic_error("newInstance not Implemented");
}
private:
LocalChannelProviderFactory(
@ -76,7 +76,7 @@ ChannelProviderLocalPtr getChannelProviderLocal()
channelProviderLocal->channelFinder =
SyncChannelFind::shared_pointer(new SyncChannelFind(xxx));
LocalChannelProviderFactoryPtr factory(LocalChannelProviderFactory::create(channelProviderLocal));
registerChannelProviderFactory(factory);
}
return channelProviderLocal;
}
@ -89,7 +89,6 @@ ChannelProviderLocal::ChannelProviderLocal()
ChannelProviderLocal::~ChannelProviderLocal()
{
// TODO should I call destroy() here
destroy();
}
@ -99,6 +98,7 @@ void ChannelProviderLocal::destroy()
if(beingDestroyed) return;
beingDestroyed = true;
pvDatabase->destroy();
pvDatabase.reset();
}
string ChannelProviderLocal::getProviderName()
@ -145,15 +145,6 @@ Channel::shared_pointer ChannelProviderLocal::createChannel(
string const & channelName,
ChannelRequester::shared_pointer const &channelRequester,
short priority)
{
return createChannel(channelName,channelRequester,priority,"");
}
Channel::shared_pointer ChannelProviderLocal::createChannel(
string const & channelName,
ChannelRequester::shared_pointer const &channelRequester,
short priority,
string const &address)
{
Lock xx(mutex);
PVRecordPtr pvRecord = pvDatabase->findRecord(channelName);
@ -171,6 +162,17 @@ Channel::shared_pointer ChannelProviderLocal::createChannel(
notFoundStatus,
Channel::shared_pointer());
return Channel::shared_pointer();
}
Channel::shared_pointer ChannelProviderLocal::createChannel(
string const & channelName,
ChannelRequester::shared_pointer const &channelRequester,
short priority,
string const &address)
{
if(!address.empty()) throw std::invalid_argument("address not allowed for local implementation");
return createChannel(channelName, channelRequester, priority);
}
}}

View File

@ -109,6 +109,7 @@ MonitorLocal::~MonitorLocal()
{
cout << "MonitorLocal::~MonitorLocal()" << endl;
}
destroy();
}
void MonitorLocal::destroy()
@ -121,16 +122,11 @@ void MonitorLocal::destroy()
Lock xx(mutex);
if(state==destroyed) return;
}
if(pvCopy) pvCopy->destroy();
if(state==active) stop();
{
Lock xx(mutex);
state = destroyed;
}
{
Lock xx(queueMutex);
queue.reset();
}
pvCopy.reset();
}
Status MonitorLocal::start()

View File

@ -43,8 +43,7 @@ RemoveRecord::RemoveRecord(
std::string const & recordName,
epics::pvData::PVStructurePtr const & pvStructure)
: PVRecord(recordName,pvStructure),
pvDatabase(PVDatabase::getMaster()),
isDestroyed(false)
pvDatabase(PVDatabase::getMaster())
{
}

View File

@ -44,8 +44,7 @@ TraceRecord::TraceRecord(
std::string const & recordName,
epics::pvData::PVStructurePtr const & pvStructure)
: PVRecord(recordName,pvStructure),
pvDatabase(PVDatabase::getMaster()),
isDestroyed(false)
pvDatabase(PVDatabase::getMaster())
{
}

View File

@ -61,6 +61,7 @@ static void test()
PVRecordPtr pvRecord(PVRecord::create(recordName,pvStructure));
RecordClientPtr exampleRecordClient(RecordClient::create(pvRecord));
ListenerPtr exampleListener(Listener::create(pvRecord));
if(debug) pvRecord->setTraceLevel(3);
master->addRecord(pvRecord);
pvRecord = master->findRecord("exampleDouble");
testOk1(pvRecord.get()!=0);