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() void PVDatabase::destroy()
{ {
epicsGuard<epics::pvData::Mutex> guard(mutex); {
if(isDestroyed) { epicsGuard<epics::pvData::Mutex> guard(mutex);
return; if(isDestroyed) {
return;
}
isDestroyed = true;
} }
isDestroyed = true; for(PVRecordMap::iterator iter = recordMap.begin(); iter != recordMap.end(); iter++) {
PVRecordMap::iterator iter;
while(true) {
iter = recordMap.begin();
if(iter==recordMap.end()) break;
PVRecordPtr pvRecord = (*iter).second; PVRecordPtr pvRecord = (*iter).second;
recordMap.erase(iter);
if(pvRecord) { if(pvRecord) {
pvRecord->destroy(); pvRecord->destroy();
} }
} }
recordMap.clear();
} }
void PVDatabase::lock() { void PVDatabase::lock() {
@ -83,27 +82,6 @@ PVRecordPtr PVDatabase::findRecord(string const& recordName)
return xxx; 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) bool PVDatabase::addRecord(PVRecordPtr const & record)
{ {
epicsGuard<epics::pvData::Mutex> guard(mutex); epicsGuard<epics::pvData::Mutex> guard(mutex);
@ -131,10 +109,31 @@ bool PVDatabase::removeRecord(PVRecordPtr const & record)
if(iter!=recordMap.end()) { if(iter!=recordMap.end()) {
PVRecordPtr pvRecord = (*iter).second; PVRecordPtr pvRecord = (*iter).second;
recordMap.erase(iter); recordMap.erase(iter);
if(pvRecord.get()!=NULL) pvRecord->destroy(); if(pvRecord) pvRecord->destroy();
return true; return true;
} }
return false; 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() void PVRecord::destroy()
{ {
if(traceLevel>0) {
cout << "PVRecord::destroy() " << recordName << endl;
}
{ {
epicsGuard<epics::pvData::Mutex> guard(mutex); epicsGuard<epics::pvData::Mutex> guard(mutex);
if(traceLevel>0) {
cout << "PVRecord::destroy() " << recordName
<< " isDestroyed " << (isDestroyed ? "true" : "false")
<< endl;
}
if(isDestroyed) { if(isDestroyed) {
return; return;
} }
@ -78,7 +80,7 @@ void PVRecord::destroy()
} }
PVDatabasePtr pvDatabase(PVDatabase::getMaster()); PVDatabasePtr pvDatabase(PVDatabase::getMaster());
if(pvDatabase) pvDatabase->removeRecord(shared_from_this()); if(pvDatabase) pvDatabase->removeRecord(shared_from_this());
pvTimeStamp.detach(); pvTimeStamp.detach();
for(std::list<PVListenerWPtr>::iterator iter = pvListenerList.begin(); for(std::list<PVListenerWPtr>::iterator iter = pvListenerList.begin();
iter!=pvListenerList.end(); iter!=pvListenerList.end();
iter++ ) iter++ )
@ -91,9 +93,8 @@ void PVRecord::destroy()
listener->unlisten(shared_from_this()); listener->unlisten(shared_from_this());
} }
pvListenerList.clear(); pvListenerList.clear();
std::list<PVRecordClientPtr>::iterator iter; for (std::list<PVRecordClientPtr>::iterator iter = clientList.begin();
for (iter = pvRecordClientList.begin(); iter!=clientList.end();
iter!=pvRecordClientList.end();
iter++ ) iter++ )
{ {
PVRecordClientPtr client = *iter; PVRecordClientPtr client = *iter;
@ -103,7 +104,7 @@ void PVRecord::destroy()
} }
client->detach(shared_from_this()); client->detach(shared_from_this());
} }
pvRecordClientList.clear(); clientList.clear();
} }
void PVRecord::process() 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) PVRecordFieldPtr PVRecord::findPVRecordField(PVFieldPtr const & pvField)
{ {
@ -199,8 +195,8 @@ bool PVRecord::addPVRecordClient(PVRecordClientPtr const & pvRecordClient)
return false; return false;
} }
std::list<PVRecordClientPtr>::iterator iter; std::list<PVRecordClientPtr>::iterator iter;
for (iter = pvRecordClientList.begin(); for (iter = clientList.begin();
iter!=pvRecordClientList.end(); iter!=clientList.end();
iter++ ) iter++ )
{ {
PVRecordClientPtr client = *iter; PVRecordClientPtr client = *iter;
@ -209,9 +205,9 @@ bool PVRecord::addPVRecordClient(PVRecordClientPtr const & pvRecordClient)
} }
} }
if(traceLevel>1) { 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; return true;
} }
@ -225,14 +221,14 @@ bool PVRecord::removePVRecordClient(PVRecordClientPtr const & pvRecordClient)
return false; return false;
} }
std::list<PVRecordClientPtr>::iterator iter; std::list<PVRecordClientPtr>::iterator iter;
for (iter = pvRecordClientList.begin(); for (iter = clientList.begin();
iter!=pvRecordClientList.end(); iter!=clientList.end();
iter++ ) iter++ )
{ {
PVRecordClientPtr client = *iter; PVRecordClientPtr client = *iter;
if(!client) continue; if(!client) continue;
if(client==pvRecordClient) { if(client==pvRecordClient) {
pvRecordClientList.erase(iter); clientList.erase(iter);
return true; return true;
} }
} }
@ -517,24 +513,4 @@ PVRecordFieldPtrArrayPtr PVRecordStructure::getPVRecordFields()
PVStructurePtr PVRecordStructure::getPVStructure() {return pvStructure.lock();} 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(); epicsShareFunc ChannelProviderLocalPtr getChannelProviderLocal();
/** /**
* @brief ChannelProvider for PVDatabase. * @brief ChannelProvider for PVDatabase.
* *
@ -229,6 +230,12 @@ public:
* The remote pvAccess server does this cleanup. * The remote pvAccess server does this cleanup.
*/ */
virtual void destroy(); 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. * Get the requester name.
* @return returns the name of the channel requester. * @return returns the name of the channel requester.
@ -381,12 +388,6 @@ public:
* @param out the stream on which the message is displayed. * @param out the stream on which the message is displayed.
*/ */
virtual void printInfo(std::ostream& out); 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: protected:
shared_pointer getPtrSelf() shared_pointer getPtrSelf()
{ {
@ -396,7 +397,7 @@ private:
epics::pvAccess::ChannelRequester::shared_pointer requester; epics::pvAccess::ChannelRequester::shared_pointer requester;
ChannelProviderLocalPtr provider; ChannelProviderLocalPtr provider;
PVRecordPtr pvRecord; PVRecordPtr pvRecord;
bool beingDestroyed; bool isDestroyed;
epics::pvData::Mutex mutex; epics::pvData::Mutex mutex;
}; };

View File

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

View File

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

View File

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

View File

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

View File

@ -53,7 +53,7 @@ public:
} }
virtual ChannelProvider::shared_pointer newInstance() virtual ChannelProvider::shared_pointer newInstance()
{ {
return channelProvider; throw std::logic_error("newInstance not Implemented");
} }
private: private:
LocalChannelProviderFactory( LocalChannelProviderFactory(
@ -76,7 +76,7 @@ ChannelProviderLocalPtr getChannelProviderLocal()
channelProviderLocal->channelFinder = channelProviderLocal->channelFinder =
SyncChannelFind::shared_pointer(new SyncChannelFind(xxx)); SyncChannelFind::shared_pointer(new SyncChannelFind(xxx));
LocalChannelProviderFactoryPtr factory(LocalChannelProviderFactory::create(channelProviderLocal)); LocalChannelProviderFactoryPtr factory(LocalChannelProviderFactory::create(channelProviderLocal));
registerChannelProviderFactory(factory);
} }
return channelProviderLocal; return channelProviderLocal;
} }
@ -89,7 +89,6 @@ ChannelProviderLocal::ChannelProviderLocal()
ChannelProviderLocal::~ChannelProviderLocal() ChannelProviderLocal::~ChannelProviderLocal()
{ {
// TODO should I call destroy() here
destroy(); destroy();
} }
@ -99,6 +98,7 @@ void ChannelProviderLocal::destroy()
if(beingDestroyed) return; if(beingDestroyed) return;
beingDestroyed = true; beingDestroyed = true;
pvDatabase->destroy(); pvDatabase->destroy();
pvDatabase.reset();
} }
string ChannelProviderLocal::getProviderName() string ChannelProviderLocal::getProviderName()
@ -145,15 +145,6 @@ Channel::shared_pointer ChannelProviderLocal::createChannel(
string const & channelName, string const & channelName,
ChannelRequester::shared_pointer const &channelRequester, ChannelRequester::shared_pointer const &channelRequester,
short priority) 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); Lock xx(mutex);
PVRecordPtr pvRecord = pvDatabase->findRecord(channelName); PVRecordPtr pvRecord = pvDatabase->findRecord(channelName);
@ -171,6 +162,17 @@ Channel::shared_pointer ChannelProviderLocal::createChannel(
notFoundStatus, notFoundStatus,
Channel::shared_pointer()); Channel::shared_pointer());
return 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; cout << "MonitorLocal::~MonitorLocal()" << endl;
} }
destroy();
} }
void MonitorLocal::destroy() void MonitorLocal::destroy()
@ -121,16 +122,11 @@ void MonitorLocal::destroy()
Lock xx(mutex); Lock xx(mutex);
if(state==destroyed) return; if(state==destroyed) return;
} }
if(pvCopy) pvCopy->destroy(); if(state==active) stop();
{ {
Lock xx(mutex); Lock xx(mutex);
state = destroyed; state = destroyed;
} }
{
Lock xx(queueMutex);
queue.reset();
}
pvCopy.reset();
} }
Status MonitorLocal::start() Status MonitorLocal::start()

View File

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

View File

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

View File

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