pvDatabase::removeRecord and pvRecord::remove changes;descructors now have at most a print statement
This commit is contained in:
20
example/createdestroy/README.md
Normal file
20
example/createdestroy/README.md
Normal 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.
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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()
|
||||
|
@ -191,10 +191,7 @@ MonitorLocal::MonitorLocal(
|
||||
|
||||
MonitorLocal::~MonitorLocal()
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>0)
|
||||
{
|
||||
cout << "MonitorLocal::~MonitorLocal()" << endl;
|
||||
}
|
||||
//cout << "MonitorLocal::~MonitorLocal()" << endl;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -30,7 +30,7 @@ namespace epics { namespace pvDatabase {
|
||||
|
||||
ScalarAlarmSupport::~ScalarAlarmSupport()
|
||||
{
|
||||
cout << "ScalarAlarmSupport::~ScalarAlarmSupport()\n";
|
||||
//cout << "ScalarAlarmSupport::~ScalarAlarmSupport()\n";
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user