add removeRecord; more work on termination issues

This commit is contained in:
mrkraimer
2016-06-15 07:21:43 -04:00
parent e025e542ea
commit fde7953de0
10 changed files with 338 additions and 44 deletions

View File

@@ -8,9 +8,13 @@ PVDATABASE_SRC = $(TOP)/src
LIBRARY += pvDatabase
# shared library ABI version.
SHRLIB_VERSION ?= 4.2-DEV
INC += pv/channelProviderLocal.h
INC += pv/pvDatabase.h
INC += pv/traceRecord.h
INC += pv/removeRecord.h
include $(PVDATABASE_SRC)/database/Makefile
include $(PVDATABASE_SRC)/pvAccess/Makefile
@@ -20,8 +24,6 @@ include $(PVDATABASE_SRC)/special/Makefile
pvDatabase_LIBS += pvAccess pvData Com
pvDatabase_LIBS += $(EPICS_BASE_IOC_LIBS)
# shared library ABI version.
SHRLIB_VERSION ?= 4.2
include $(TOP)/configure/RULES

View File

@@ -82,6 +82,9 @@ void PVRecord::destroy()
{
PVRecordClientPtr client = iter->lock();
if(client) {
if(traceLevel>1) {
cout << "PVRecord::destroy() calling client->detach " << recordName << endl;
}
epicsGuardRelease<epics::pvData::Mutex> unguard(guard);
client->detach(shared_from_this());
}
@@ -92,10 +95,15 @@ void PVRecord::destroy()
{
PVListenerPtr listener = iter->lock();
if(listener) {
if(traceLevel>1) {
cout << "PVRecord::destroy() calling listener->unlisten " << recordName << endl;
}
epicsGuardRelease<epics::pvData::Mutex> unguard(guard);
listener->unlisten(shared_from_this());
}
}
PVDatabasePtr pvDatabase(PVDatabase::getMaster());
if(pvDatabase) pvDatabase->removeRecord(shared_from_this());
}
void PVRecord::process()
@@ -232,7 +240,7 @@ bool PVRecord::removePVRecordClient(PVRecordClientPtr const & pvRecordClient)
void PVRecord::detachClients()
{
if(traceLevel>1) {
cout << "PVRecord::removePVRecordClient() " << recordName << endl;
cout << "PVRecord::detachClients() " << recordName << endl;
}
epicsGuard<epics::pvData::Mutex> guard(mutex);
if(isDestroyed) {
@@ -244,8 +252,11 @@ void PVRecord::detachClients()
iter++ )
{
PVRecordClientPtr client = iter->lock();
if(!client.get()) continue;
if(!client) continue;
epicsGuardRelease <epics::pvData::Mutex> unguard(guard);
if(traceLevel>1) {
cout << "PVRecord::detachClients() calling client->detach " << recordName << endl;
}
client->detach(shared_from_this());
}
pvRecordClientList.clear();

View File

@@ -393,8 +393,8 @@ protected:
return shared_from_this();
}
private:
ChannelProviderLocalPtr provider;
epics::pvAccess::ChannelRequester::weak_pointer requester;
ChannelProviderLocalPtr provider;
PVRecordPtr pvRecord;
bool beingDestroyed;
epics::pvData::Mutex mutex;

View File

@@ -483,6 +483,7 @@ public:
virtual ~PVDatabase();
/**
* Destroy the PVDatabase.
* For each record in the database the record is removed and it's destroy method is called.
*/
virtual void destroy();
/**

73
src/pv/removeRecord.h Normal file
View File

@@ -0,0 +1,73 @@
/* removeRecord.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 REMOVERECORD_H
#define REMOVERECORD_H
#include <shareLib.h>
#include <pv/channelProviderLocal.h>
namespace epics { namespace pvDatabase {
class RemoveRecord;
typedef std::tr1::shared_ptr<RemoveRecord> RemoveRecordPtr;
/**
* @brief Remove another record in the same database.
*
* A record to remove another record
* It is meant to be used via a channelPutGet request.
* The argument has one field: recordName.
* The result has a field named status.
*/
class epicsShareClass RemoveRecord :
public PVRecord
{
public:
POINTER_DEFINITIONS(RemoveRecord);
/**
* Factory methods to create RemoveRecord.
* @param recordName The name for the RemoveRecord.
* @return A shared pointer to RemoveRecord..
*/
static RemoveRecordPtr create(
std::string const & recordName);
/**
* destructor
*/
virtual ~RemoveRecord();
/**
* Clean up any resources used.
*/
virtual void destroy();
/**
* standard init method required by PVRecord
* @return true unless record name already exists.
*/
virtual bool init();
/**
* Set the trace level.
*/
virtual void process();
private:
RemoveRecord(
std::string const & recordName,
epics::pvData::PVStructurePtr const & pvStructure);
PVDatabasePtr pvDatabase;
epics::pvData::PVStringPtr pvRecordName;
epics::pvData::PVStringPtr pvResult;
bool isDestroyed;
};
}}
#endif /* REMOVERECORD_H */

View File

@@ -187,7 +187,6 @@ void ChannelProcessLocal::destroy()
if(isDestroyed) return;
isDestroyed = true;
}
channelLocal.reset();
}
@@ -336,7 +335,6 @@ void ChannelGetLocal::destroy()
if(isDestroyed) return;
isDestroyed = true;
}
channelLocal.reset();
}
void ChannelGetLocal::get()
@@ -488,7 +486,6 @@ void ChannelPutLocal::destroy()
if(isDestroyed) return;
isDestroyed = true;
}
channelLocal.reset();
}
void ChannelPutLocal::get()
@@ -683,7 +680,6 @@ void ChannelPutGetLocal::destroy()
if(isDestroyed) return;
isDestroyed = true;
}
channelLocal.reset();
}
void ChannelPutGetLocal::putGet(
@@ -1164,7 +1160,6 @@ void ChannelArrayLocal::destroy()
if(isDestroyed) return;
isDestroyed = true;
}
channelLocal.reset();
}
void ChannelArrayLocal::getArray(size_t offset, size_t count, size_t stride)
@@ -1310,11 +1305,18 @@ ChannelLocal::ChannelLocal(
ChannelProviderLocalPtr const & provider,
ChannelRequester::shared_pointer const & requester,
PVRecordPtr const & pvRecord)
: provider(provider),
:
requester(requester),
provider(provider),
pvRecord(pvRecord),
beingDestroyed(false)
{
if(pvRecord->getTraceLevel()>0) {
cout << "ChannelLocal::ChannelLocal()"
<< " recordName " << pvRecord->getRecordName()
<< " requester exists " << (requester ? "true" : "false")
<< endl;
}
}
ChannelLocal::~ChannelLocal()
@@ -1327,22 +1329,31 @@ ChannelLocal::~ChannelLocal()
void ChannelLocal::destroy()
{
ChannelRequester::shared_pointer requester(this->requester.lock());
if(pvRecord->getTraceLevel()>0) {
cout << "ChannelLocal::destroy() ";
cout << "beingDestroyed " << beingDestroyed << endl;
cout << "ChannelLocal::destroy()"
<< " recordName " << pvRecord->getRecordName()
<< " beingDestroyed " << beingDestroyed
<< " requester exists " << (requester ? "true" : "false")
<< endl;
}
{
Lock xx(mutex);
if(beingDestroyed) return;
beingDestroyed = true;
}
message("being destroyed",fatalErrorMessage);
pvRecord->removePVRecordClient(getPtrSelf());
}
void ChannelLocal::detach(PVRecordPtr const & pvRecord)
{
if(pvRecord->getTraceLevel()>0) {
cout << "ChannelLocal::detach() " << endl;
ChannelRequester::shared_pointer requester(this->requester.lock());
cout << "ChannelLocal::detach() "
<< " recordName " << pvRecord->getRecordName()
<< " requester exists " << (requester ? "true" : "false")
<< endl;
}
destroy();
}
@@ -1351,6 +1362,13 @@ void ChannelLocal::detach(PVRecordPtr const & pvRecord)
string ChannelLocal::getRequesterName()
{
ChannelRequester::shared_pointer req = requester.lock();
if(pvRecord->getTraceLevel()>1) {
cout << "ChannelLocal::getRequesterName() "
<< " recordName " << pvRecord->getRecordName()
<< " requester exists " << (req ? "true" : "false")
<< endl;
}
if(!req) return string();
return req->getRequesterName();
}
@@ -1360,8 +1378,20 @@ void ChannelLocal::message(
MessageType messageType)
{
ChannelRequester::shared_pointer req = requester.lock();
if(!req) return;
req->message(message,messageType);
if(pvRecord->getTraceLevel()>1) {
cout << "ChannelLocal::message() "
<< " recordName " << pvRecord->getRecordName()
<< " requester exists " << (req ? "true" : "false")
<< endl;
}
if(req) {
req->message(message,messageType);
return;
}
cout << pvRecord->getRecordName()
<< " message " << message
<< " messageType " << getMessageTypeName(messageType)
<< endl;
}
string ChannelLocal::getRemoteAddress()
@@ -1423,6 +1453,13 @@ ChannelProcess::shared_pointer ChannelLocal::createChannelProcess(
ChannelProcessRequester::shared_pointer const & channelProcessRequester,
PVStructure::shared_pointer const & pvRequest)
{
if(pvRecord->getTraceLevel()>0) {
ChannelRequester::shared_pointer requester(this->requester.lock());
cout << "ChannelLocal::createChannelProcess() "
<< " recordName " << pvRecord->getRecordName()
<< " requester exists " << (requester ? "true" : "false")
<< endl;
}
ChannelProcessLocalPtr channelProcess =
ChannelProcessLocal::create(
getPtrSelf(),
@@ -1436,6 +1473,13 @@ ChannelGet::shared_pointer ChannelLocal::createChannelGet(
ChannelGetRequester::shared_pointer const &channelGetRequester,
PVStructure::shared_pointer const &pvRequest)
{
if(pvRecord->getTraceLevel()>0) {
ChannelRequester::shared_pointer requester(this->requester.lock());
cout << "ChannelLocal::createChannelGet() "
<< " recordName " << pvRecord->getRecordName()
<< " requester exists " << (requester ? "true" : "false")
<< endl;
}
ChannelGetLocalPtr channelGet =
ChannelGetLocal::create(
getPtrSelf(),
@@ -1449,6 +1493,14 @@ ChannelPut::shared_pointer ChannelLocal::createChannelPut(
ChannelPutRequester::shared_pointer const &channelPutRequester,
PVStructure::shared_pointer const &pvRequest)
{
if(pvRecord->getTraceLevel()>0) {
ChannelRequester::shared_pointer requester(this->requester.lock());
cout << "ChannelLocal::createChannelPut() "
<< " recordName " << pvRecord->getRecordName()
<< " requester exists " << (requester ? "true" : "false")
<< endl;
}
ChannelPutLocalPtr channelPut =
ChannelPutLocal::create(
getPtrSelf(),
@@ -1462,6 +1514,14 @@ ChannelPutGet::shared_pointer ChannelLocal::createChannelPutGet(
ChannelPutGetRequester::shared_pointer const &channelPutGetRequester,
PVStructure::shared_pointer const &pvRequest)
{
if(pvRecord->getTraceLevel()>0) {
ChannelRequester::shared_pointer requester(this->requester.lock());
cout << "ChannelLocal::createChannelPutGet() "
<< " recordName " << pvRecord->getRecordName()
<< " requester exists " << (requester ? "true" : "false")
<< endl;
}
ChannelPutGetLocalPtr channelPutGet =
ChannelPutGetLocal::create(
getPtrSelf(),
@@ -1475,6 +1535,14 @@ ChannelRPC::shared_pointer ChannelLocal::createChannelRPC(
ChannelRPCRequester::shared_pointer const & channelRPCRequester,
PVStructure::shared_pointer const & pvRequest)
{
if(pvRecord->getTraceLevel()>0) {
ChannelRequester::shared_pointer requester(this->requester.lock());
cout << "ChannelLocal::createChannelRPC() "
<< " recordName " << pvRecord->getRecordName()
<< " requester exists " << (requester ? "true" : "false")
<< endl;
}
ChannelRPCLocalPtr channelRPC =
ChannelRPCLocal::create(
getPtrSelf(),
@@ -1488,6 +1556,14 @@ Monitor::shared_pointer ChannelLocal::createMonitor(
MonitorRequester::shared_pointer const &monitorRequester,
PVStructure::shared_pointer const &pvRequest)
{
if(pvRecord->getTraceLevel()>0) {
ChannelRequester::shared_pointer requester(this->requester.lock());
cout << "ChannelLocal::createMonitor() "
<< " recordName " << pvRecord->getRecordName()
<< " requester exists " << (requester ? "true" : "false")
<< endl;
}
MonitorPtr monitor =
getMonitorFactory()->createMonitor(
pvRecord,
@@ -1500,6 +1576,13 @@ ChannelArray::shared_pointer ChannelLocal::createChannelArray(
ChannelArrayRequester::shared_pointer const &channelArrayRequester,
PVStructure::shared_pointer const &pvRequest)
{
if(pvRecord->getTraceLevel()>0) {
ChannelRequester::shared_pointer requester(this->requester.lock());
cout << "ChannelLocal::createChannelArray() "
<< " recordName " << pvRecord->getRecordName()
<< " requester exists " << (requester ? "true" : "false")
<< endl;
}
ChannelArrayLocalPtr channelArray =
ChannelArrayLocal::create(
getPtrSelf(),

View File

@@ -3,3 +3,4 @@
SRC_DIRS += $(PVDATABASE_SRC)/special
LIBSRCS += traceRecord.cpp
LIBSRCS += removeRecord.cpp

View File

@@ -0,0 +1,85 @@
/* removeRecord.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
*/
#define epicsExportSharedSymbols
#include <pv/removeRecord.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace pvDatabase {
RemoveRecordPtr RemoveRecord::create(
std::string const & recordName)
{
FieldCreatePtr fieldCreate = getFieldCreate();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
addNestedStructure("argument")->
add("recordName",pvString)->
endNested()->
addNestedStructure("result") ->
add("status",pvString) ->
endNested()->
createStructure();
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
RemoveRecordPtr pvRecord(
new RemoveRecord(recordName,pvStructure));
if(!pvRecord->init()) pvRecord.reset();
return pvRecord;
}
RemoveRecord::RemoveRecord(
std::string const & recordName,
epics::pvData::PVStructurePtr const & pvStructure)
: PVRecord(recordName,pvStructure),
pvDatabase(PVDatabase::getMaster()),
isDestroyed(false)
{
}
RemoveRecord::~RemoveRecord()
{
}
void RemoveRecord::destroy()
{
PVRecord::destroy();
}
bool RemoveRecord::init()
{
initPVRecord();
PVStructurePtr pvStructure = getPVStructure();
pvRecordName = pvStructure->getSubField<PVString>("argument.recordName");
if(!pvRecordName) return false;
pvResult = pvStructure->getSubField<PVString>("result.status");
if(!pvResult) return false;
return true;
}
void RemoveRecord::process()
{
string name = pvRecordName->get();
PVRecordPtr pvRecord = pvDatabase->findRecord(name);
if(!pvRecord) {
pvResult->put(name + " not found");
return;
}
pvRecord->destroy();
pvResult->put("success");
}
}}