pvDatabase::removeRecord and pvRecord::remove changes;descructors now have at most a print statement

This commit is contained in:
mrkraimer
2020-02-10 06:15:59 -05:00
parent 42ba054e5f
commit 083dffac3c
9 changed files with 143 additions and 125 deletions

View File

@ -0,0 +1,20 @@
# pvDatabaseCPP/example/createdestroy
This is an example that:
1) Gets the master PVDatabase
2) Create ChannelProviderLocal
3) Creates a ServerContext
Then it executes a forever loop that:
1) creates a pvRecord and adds it to the pvDatabase.
2) creates a pvac::ClientProvider
3) creates a pvac::ClientChannel
4) creates a monitor on the channel
5) runs a loop 10 times that: does a put to the channel, and then gets the data for any outstanding monitors
6) removes the pvRecord from the pvDatabase
It also has options to set trace level for the pvRecord and to periodically pause by asking for input.

View File

@ -1,13 +1,15 @@
/******************************************************************************
* This is modeled after a test program created by Bertrand Bauvir from the ITER Organization
******************************************************************************/
#include <iostream>
#include <epicsGetopt.h>
#include <pv/pvData.h>
#include <pv/pvDatabase.h>
#include <pv/serverContext.h>
#include <pv/channelProviderLocal.h>
#include <pva/client.h>
#include <epicsEvent.h>
// Local header files
@ -17,12 +19,9 @@
using std::tr1::static_pointer_cast;
// Type definition
class Record : public ::epics::pvDatabase::PVRecord
{
public:
public:
std::shared_ptr<::epics::pvData::PVStructure> __pv;
static std::shared_ptr<Record> create (std::string const & name, std::shared_ptr<::epics::pvData::PVStructure> const & pvstruct);
Record (std::string const & name, std::shared_ptr<epics::pvData::PVStructure> const & pvstruct)
@ -32,14 +31,10 @@ class Record : public ::epics::pvDatabase::PVRecord
std::shared_ptr<Record> Record::create (std::string const & name, std::shared_ptr<::epics::pvData::PVStructure> const & pvstruct)
{
std::shared_ptr<Record> pvrecord (new Record (name, pvstruct));
// Need to be explicitly called .. not part of the base constructor
if(!pvrecord->init()) pvrecord.reset();
return pvrecord;
}
void Record::process (void)
@ -47,24 +42,85 @@ void Record::process (void)
PVRecord::process();
std::string name = this->getRecordName();
std::cout << this->getRecordName()
<< this->getPVStructure()
<< "\n";
<< " process\n";
}
class MyMonitor
{
private:
std::tr1::shared_ptr<::pvac::MonitorSync> monitor;
MyMonitor(std::tr1::shared_ptr<::pvac::ClientChannel> const &channel)
{
monitor = std::tr1::shared_ptr<::pvac::MonitorSync>(new ::pvac::MonitorSync(channel->monitor()));
}
public:
static std::tr1::shared_ptr<MyMonitor> create(std::tr1::shared_ptr<::pvac::ClientChannel> const &channel)
{
return std::tr1::shared_ptr<MyMonitor>(new MyMonitor(channel));
}
void getData();
};
void MyMonitor::getData()
{
while (true) {
if(!monitor->wait(.001)) break;
switch(monitor->event.event) {
case pvac::MonitorEvent::Fail:
std::cerr<<monitor->name()<<" : Error : "<<monitor->event.message<<"\n";
return;
case pvac::MonitorEvent::Cancel:
std::cout<<monitor->name()<<" <Cancel>\n";
return;
case pvac::MonitorEvent::Disconnect:
std::cout<<monitor->name()<<" <Disconnect>\n";
return;
case pvac::MonitorEvent::Data:
while(monitor->poll()) {
std::cout<<monitor->name()<<" : "<<monitor->root;
}
if(monitor->complete()) {
return;
}
}
}
}
int main (int argc, char** argv)
{
bool verbose = false;
int verbose = 0;
unsigned loopctr = 0;
unsigned pausectr = 0;
bool allowExit = false;
int opt;
while((opt = getopt(argc, argv, "v:ah")) != -1) {
switch(opt) {
case 'v':
verbose = std::stoi(optarg);
break;
case 'a' :
allowExit = true;
break;
case 'h':
std::cout << " -v level -a -h \n";
std::cout << "default\n";
std::cout << "-v " << verbose
<< " -a false"
<< "\n";
return 0;
default:
std::cerr<<"Unknown argument: "<<opt<<"\n";
return -1;
}
}
// Create PVA context
::epics::pvDatabase::PVDatabasePtr master = epics::pvDatabase::PVDatabase::getMaster();
::epics::pvDatabase::ChannelProviderLocalPtr channelProvider = epics::pvDatabase::getChannelProviderLocal();
// Start PVA server
epics::pvAccess::ServerContext::shared_pointer context = epics::pvAccess::startPVAServer(epics::pvAccess::PVACCESS_ALL_PROVIDERS, 0, true, true);
epics::pvAccess::ServerContext::shared_pointer context
= epics::pvAccess::startPVAServer(epics::pvAccess::PVACCESS_ALL_PROVIDERS, 0, true, true);
std::string startset("starting set of puts valuectr = ");
while (true) {
loopctr++;
std::string name = DEFAULT_RECORD_NAME + std::to_string(loopctr);
@ -73,22 +129,35 @@ int main (int argc, char** argv)
// Create record structure
::epics::pvData::FieldBuilderPtr builder = epics::pvData::getFieldCreate()->createFieldBuilder();
builder->add("value", ::epics::pvData::pvULong);
std::shared_ptr<::epics::pvData::PVStructure> pvstruct = ::epics::pvData::getPVDataCreate()->createPVStructure(builder->createStructure());
std::shared_ptr<::epics::pvData::PVStructure> pvstruct
= ::epics::pvData::getPVDataCreate()->createPVStructure(builder->createStructure());
std::shared_ptr<Record> pvrecord = Record::create(std::string(name), pvstruct);
master->addRecord(pvrecord);
if (verbose) pvrecord->setTraceLevel(3);
pvrecord->setTraceLevel(verbose);
// Start PVA (local) client
std::tr1::shared_ptr<::pvac::ClientProvider> provider
= std::tr1::shared_ptr<::pvac::ClientProvider>(new ::pvac::ClientProvider ("pva"));
std::tr1::shared_ptr<::pvac::ClientChannel> channel
= std::tr1::shared_ptr<::pvac::ClientChannel>(new ::pvac::ClientChannel (provider->connect(name)));
builder = epics::pvData::getFieldCreate()->createFieldBuilder();
builder->add("value", ::epics::pvData::pvULong);
std::shared_ptr<::epics::pvData::PVStructure> c_pvstruct =
::epics::pvData::getPVDataCreate()->createPVStructure(builder->createStructure());
std::tr1::shared_ptr<MyMonitor> mymonitor = MyMonitor::create(channel);
unsigned valuectr = loopctr;
for (int ind=0; ind<10; ind++) channel->put().set("value",valuectr++).exec();
master->removeRecord(pvrecord);
std::cout << startset << loopctr << "\n";
for (int ind=0; ind<10; ind++) {
channel->put().set("value",valuectr++).exec();
mymonitor->getData();
}
pausectr++;
if(allowExit && pausectr>500) {
pausectr = 0;
std::cout << "Type exit to stop: \n";
int c = std::cin.peek(); // peek character
if ( c == EOF ) continue;
std::string str;
std::getline(std::cin,str);
if(str.compare("exit")==0) break;
}
pvrecord->remove();
// master->removeRecord(pvrecord);
}
return (0);
}

View File

@ -56,14 +56,6 @@ PVDatabase::PVDatabase()
PVDatabase::~PVDatabase()
{
if(DEBUG_LEVEL>0) cout << "PVDatabase::~PVDatabase()\n";
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;
}
for(size_t i=0; i<len; ++i) removeRecord(findRecord(names[i]));
}
void PVDatabase::lock() {
@ -100,7 +92,7 @@ bool PVDatabase::addRecord(PVRecordPtr const & record)
return true;
}
bool PVDatabase::removeRecord(PVRecordPtr const & record)
bool PVDatabase::removeRecord(PVRecordPtr const & record,bool callRemove)
{
if(record->getTraceLevel()>0) {
cout << "PVDatabase::removeRecord " << record->getRecordName() << endl;
@ -110,6 +102,7 @@ bool PVDatabase::removeRecord(PVRecordPtr const & record)
PVRecordMap::iterator iter = recordMap.find(recordName);
if(iter!=recordMap.end()) {
PVRecordPtr pvRecord = (*iter).second;
if(callRemove) pvRecord->remove(false);
recordMap.erase(iter);
return true;
}

View File

@ -58,64 +58,23 @@ PVRecord::PVRecord(
{
}
void PVRecord::notifyClients()
{
{
epicsGuard<epics::pvData::Mutex> guard(mutex);
if(traceLevel>0) {
cout << "PVRecord::notifyClients() " << recordName
<< endl;
}
}
pvTimeStamp.detach();
for(std::list<PVListenerWPtr>::iterator iter = pvListenerList.begin();
iter!=pvListenerList.end();
iter++ )
{
PVListenerPtr listener = iter->lock();
if(!listener) continue;
if(traceLevel>0) {
cout << "PVRecord::notifyClients() calling listener->unlisten "
<< recordName << endl;
}
listener->unlisten(shared_from_this());
}
pvListenerList.clear();
for (std::list<PVRecordClientWPtr>::iterator iter = clientList.begin();
iter!=clientList.end();
iter++ )
{
PVRecordClientPtr client = iter->lock();
if(!client) continue;
if(traceLevel>0) {
cout << "PVRecord::notifyClients() calling client->detach "
<< recordName << endl;
}
client->detach(shared_from_this());
}
if(traceLevel>0) {
cout << "PVRecord::notifyClients() calling clientList.clear() "
<< recordName << endl;
}
clientList.clear();
if(traceLevel>0) {
cout << "PVRecord::notifyClients() returning " << recordName << endl;
}
}
PVRecord::~PVRecord()
{
if(traceLevel>0) {
cout << "~PVRecord() " << recordName << endl;
}
// notifyClients();
}
void PVRecord::remove()
void PVRecord::remove(bool callpvDatabaseRemoveRecord)
{
PVDatabasePtr pvDatabase(PVDatabase::getMaster());
notifyClients();
if(pvDatabase) pvDatabase->removeRecord(shared_from_this());
if(traceLevel>0) {
cout << "PVRecord::remove() " << recordName << endl;
}
epicsGuard<epics::pvData::Mutex> guard(mutex);
if(callpvDatabaseRemoveRecord) {
PVDatabasePtr pvDatabase(PVDatabase::getMaster());
if(pvDatabase) pvDatabase->removeRecord(shared_from_this(),false);
}
pvTimeStamp.detach();
for(std::list<PVListenerWPtr>::iterator iter = pvListenerList.begin();
iter!=pvListenerList.end();

View File

@ -97,11 +97,13 @@ public:
* get rid of listeners and requesters.
* If derived class overrides this then it must call PVRecord::remove()
* after it has destroyed any resorces it uses.
* @param callpvDatabaseRemoveRecord Should pvDatabase.removeRecord be called.
* Normally this is only set false by PVDatabase::removeRecord.
*/
virtual void remove();
virtual void remove(bool callpvDatabaseRemoveRecord = true);
/**
* @brief Optional method for derived class.
*
*
* Return a service corresponding to the specified request PVStructure.
* @param pvRequest The request PVStructure
* @return The corresponding service
@ -255,7 +257,6 @@ private:
PVRecordFieldPtr findPVRecordField(
PVRecordStructurePtr const & pvrs,
epics::pvData::PVFieldPtr const & pvField);
void notifyClients();
std::string recordName;
epics::pvData::PVStructurePtr pvStructure;
@ -499,9 +500,11 @@ public:
/**
* @brief Remove a record.
* @param record The record to remove.
* @param callRemove Call pvRecord->remove()
* Normally this is only set false by pvRecord.remove()
* @return <b>true</b> if record was removed.
*/
bool removeRecord(PVRecordPtr const & record);
bool removeRecord(PVRecordPtr const & record,bool callRemove = true);
/**
* @brief Get the names of all the records in the database.
* @return The names.

View File

@ -156,10 +156,7 @@ ChannelProcessLocalPtr ChannelProcessLocal::create(
ChannelProcessLocal::~ChannelProcessLocal()
{
PVRecordPtr pvr(pvRecord.lock());
if(pvr && pvr->getTraceLevel()>0) {
cout << "~ChannelProcessLocal() " << pvr->getRecordName() << endl;
}
//cout << "~ChannelProcessLocal()\n";
}
std::tr1::shared_ptr<Channel> ChannelProcessLocal::getChannel()
@ -304,10 +301,7 @@ ChannelGetLocalPtr ChannelGetLocal::create(
ChannelGetLocal::~ChannelGetLocal()
{
PVRecordPtr pvr(pvRecord.lock());
if(pvr && pvr->getTraceLevel()>0) {
cout << "~ChannelGetLocal() " << pvr->getRecordName() << endl;
}
//cout << "~ChannelGetLocal()\n";
}
std::tr1::shared_ptr<Channel> ChannelGetLocal::getChannel()
@ -469,10 +463,7 @@ ChannelPutLocalPtr ChannelPutLocal::create(
ChannelPutLocal::~ChannelPutLocal()
{
PVRecordPtr pvr(pvRecord.lock());
if(pvr && pvr->getTraceLevel()>0) {
cout << "~ChannelPutLocal() " << pvr->getRecordName() << endl;
}
//cout << "~ChannelPutLocal()\n";
}
std::tr1::shared_ptr<Channel> ChannelPutLocal::getChannel()
@ -662,10 +653,7 @@ ChannelPutGetLocalPtr ChannelPutGetLocal::create(
ChannelPutGetLocal::~ChannelPutGetLocal()
{
PVRecordPtr pvr(pvRecord.lock());
if(pvr && pvr->getTraceLevel()>0) {
cout << "~ChannelPutGetLocal() " << pvr->getRecordName() << endl;
}
//cout << "~ChannelPutGetLocal()\n";
}
std::tr1::shared_ptr<Channel> ChannelPutGetLocal::getChannel()
@ -862,10 +850,7 @@ ChannelRPCLocalPtr ChannelRPCLocal::create(
ChannelRPCLocal::~ChannelRPCLocal()
{
PVRecordPtr pvr(pvRecord.lock());
if(pvr && pvr->getTraceLevel()>0) {
cout << "~ChannelRPCLocal() " << pvr->getRecordName() << endl;
}
//cout << "~ChannelRPCLocal()\n";
}
std::tr1::shared_ptr<Channel> ChannelRPCLocal::getChannel()
@ -1104,10 +1089,7 @@ ChannelArrayLocalPtr ChannelArrayLocal::create(
ChannelArrayLocal::~ChannelArrayLocal()
{
PVRecordPtr pvr(pvRecord.lock());
if(pvr && pvr->getTraceLevel()>0) {
cout << "~ChannelArrayLocal() " << pvr->getRecordName() << endl;
}
//cout << "~ChannelArrayLocal()\n";
}
std::tr1::shared_ptr<Channel> ChannelArrayLocal::getChannel()
@ -1261,12 +1243,7 @@ ChannelLocal::ChannelLocal(
ChannelLocal::~ChannelLocal()
{
PVRecordPtr pvr(pvRecord.lock());
if(!pvr) return;
if(pvr->getTraceLevel()>0)
{
cout << "~ChannelLocal()" << endl;
}
// cout << "~ChannelLocal()" << endl;
}
ChannelProvider::shared_pointer ChannelLocal::getProvider()

View File

@ -191,10 +191,7 @@ MonitorLocal::MonitorLocal(
MonitorLocal::~MonitorLocal()
{
if(pvRecord->getTraceLevel()>0)
{
cout << "MonitorLocal::~MonitorLocal()" << endl;
}
//cout << "MonitorLocal::~MonitorLocal()" << endl;
}

View File

@ -29,7 +29,7 @@ namespace epics { namespace pvDatabase {
ControlSupport::~ControlSupport()
{
cout << "ControlSupport::~ControlSupport()\n";
//cout << "ControlSupport::~ControlSupport()\n";
}
epics::pvData::StructureConstPtr ControlSupport::controlField(ScalarType scalarType)

View File

@ -30,7 +30,7 @@ namespace epics { namespace pvDatabase {
ScalarAlarmSupport::~ScalarAlarmSupport()
{
cout << "ScalarAlarmSupport::~ScalarAlarmSupport()\n";
//cout << "ScalarAlarmSupport::~ScalarAlarmSupport()\n";
}