merge latest from epics-base

This commit is contained in:
mrkraimer
2017-09-01 14:34:51 -04:00
23 changed files with 475 additions and 102 deletions

View File

@@ -17,12 +17,12 @@
#include <epicsEvent.h>
#include <epicsMutex.h>
#include <epicsGuard.h>
#include <epicsGetopt.h>
//! [Headers]
#include <pv/configuration.h>
#include <pv/caProvider.h>
#include <pv/reftrack.h>
#include <pva/client.h>
//! [Headers]
namespace pvd = epics::pvData;
namespace pva = epics::pvAccess;
@@ -92,37 +92,36 @@ struct Getter : public pvac::ClientChannel::GetCallback,
int main(int argc, char *argv[]) {
try {
epics::RefMonitor refmon;
double waitTime = -1.0;
std::string providerName("pva");
typedef std::vector<std::string> pvs_t;
pvs_t pvs;
for(int i=1; i<argc; i++) {
if(argv[i][0]=='-') {
if(strcmp(argv[i], "-P")==0 || strcmp(argv[i], "--provider")==0) {
if(i<argc-1) {
providerName = argv[++i];
} else {
std::cerr << "--provider requires value\n";
return 1;
}
} else if(strcmp(argv[i], "-T")==0 || strcmp(argv[i], "--timeout")==0) {
if(i<argc-1) {
waitTime = pvd::castUnsafe<double, std::string>(argv[++i]);
} else {
std::cerr << "--timeout requires value\n";
return 1;
}
} else {
std::cerr<<"Unknown argument: "<<argv[i]<<"\n";
}
} else {
pvs.push_back(argv[i]);
int opt;
while((opt = getopt(argc, argv, "hRp:w:")) != -1) {
switch(opt) {
case 'R':
refmon.start(5.0);
break;
case 'p':
providerName = optarg;
break;
case 'w':
waitTime = pvd::castUnsafe<double, std::string>(optarg);
break;
case 'h':
std::cout<<"Usage: "<<argv[0]<<" [-p <provider>] [-w <timeout>] [-R] <pvname> ...\n";
return 0;
default:
std::cerr<<"Unknown argument: "<<opt<<"\n";
return -1;
}
}
for(int i=optind; i<argc; i++)
pvs.push_back(argv[i]);
#ifdef USE_SIGNAL
signal(SIGINT, alldone);
signal(SIGTERM, alldone);
@@ -162,6 +161,14 @@ int main(int argc, char *argv[]) {
else
done.wait(waitTime);
if(refmon.running()) {
refmon.stop();
// drop refs to operations, but keep ref to ClientProvider
gets.clear();
// show final counts
refmon.current();
}
} catch(std::exception& e){
std::cerr<<"Error: "<<e.what()<<"\n";
return 1;

View File

@@ -18,9 +18,11 @@
#include <epicsEvent.h>
#include <epicsMutex.h>
#include <epicsGuard.h>
#include <epicsGetopt.h>
#include <pv/configuration.h>
#include <pv/caProvider.h>
#include <pv/reftrack.h>
#include <pv/thread.h>
#include <pva/client.h>
@@ -184,45 +186,40 @@ struct MonTracker : public pvac::ClientChannel::MonitorCallback,
int main(int argc, char *argv[]) {
try {
epics::RefMonitor refmon;
double waitTime = -1.0;
std::string providerName("pva"),
requestStr("field()");
typedef std::vector<std::string> pvs_t;
pvs_t pvs;
for(int i=1; i<argc; i++) {
if(argv[i][0]=='-') {
if(strcmp(argv[i], "-P")==0 || strcmp(argv[i], "--provider")==0) {
if(i<argc-1) {
providerName = argv[++i];
} else {
std::cout << "--provider requires value\n";
return 1;
}
} else if(strcmp(argv[i], "-T")==0 || strcmp(argv[i], "--timeout")==0) {
if(i<argc-1) {
waitTime = pvd::castUnsafe<double, std::string>(argv[++i]);
} else {
std::cout << "--timeout requires value\n";
return 1;
}
} else if(strcmp(argv[i], "-r")==0 || strcmp(argv[i], "--request")==0) {
if(i<argc-1) {
requestStr = argv[++i];
} else {
std::cout << "--request requires value\n";
return 1;
}
} else {
std::cout<<"Unknown argument: "<<argv[i]<<"\n";
}
} else {
pvs.push_back(argv[i]);
int opt;
while((opt = getopt(argc, argv, "hRp:w:r:")) != -1) {
switch(opt) {
case 'R':
refmon.start(5.0);
break;
case 'p':
providerName = optarg;
break;
case 'w':
waitTime = pvd::castUnsafe<double, std::string>(optarg);
break;
case 'r':
requestStr = optarg;
break;
case 'h':
std::cout<<"Usage: "<<argv[0]<<" [-p <provider>] [-w <timeout>] [-r <request>] [-R] <pvname> ...\n";
return 0;
default:
std::cerr<<"Unknown argument: "<<opt<<"\n";
return -1;
}
}
for(int i=optind; i<argc; i++)
pvs.push_back(argv[i]);
#ifdef USE_SIGNAL
signal(SIGINT, sigdone);
signal(SIGTERM, sigdone);
@@ -276,6 +273,14 @@ int main(int argc, char *argv[]) {
}
}
if(refmon.running()) {
refmon.stop();
// drop refs to operations, but keep ref to ClientProvider
monitors.clear();
// show final counts
refmon.current();
}
} catch(std::exception& e){
std::cout<<"Error: "<<e.what()<<"\n";
return 1;

View File

@@ -24,6 +24,7 @@
#include <pv/logger.h>
#include <pv/lock.h>
#include <pv/event.h>
#include <pv/reftrack.h>
#include "pvutils.cpp"
@@ -355,6 +356,7 @@ int main (int argc, char *argv[])
istream* inputStream = 0;
ifstream ifs;
bool fromStream = false;
epics::RefMonitor refmon;
double timeOut = -1.0;
bool explicit_timeout = false;
@@ -363,7 +365,7 @@ int main (int argc, char *argv[])
// ================ Parse Arguments
while ((opt = getopt(argc, argv, ":hvr:w:tmp:qdcF:f:ni")) != -1) {
while ((opt = getopt(argc, argv, ":hvRr:w:tmp:qdcF:f:ni")) != -1) {
switch (opt) {
case 'h': /* Print usage */
usage();
@@ -378,6 +380,9 @@ int main (int argc, char *argv[])
fprintf(stdout, "%s\n", version.getVersionString().c_str());
return 0;
}
case 'R':
refmon.start(5.0);
break;
case 'w': /* Set PVA timeout value */
if((epicsScanDouble(optarg, &timeOut)) != 1 || timeOut <= 0.0)
{
@@ -609,6 +614,14 @@ int main (int argc, char *argv[])
}
}
if(refmon.running()) {
refmon.stop();
// drop refs to operations, but keep ref to ClientProvider
ops.clear();
// show final counts
refmon.current();
}
// ========================== All done now
if(debugFlag)

View File

@@ -10,7 +10,9 @@
#include <pv/standardField.h>
#include <pv/logger.h>
#include <pv/pvAccess.h>
#include <pv/reftrack.h>
#define epicsExportSharedSymbols
#include "caChannel.h"
#include <pv/caStatus.h>
@@ -356,6 +358,8 @@ void CAChannel::disconnected()
}
}
size_t CAChannel::num_instances;
CAChannel::CAChannel(std::string const & _channelName,
CAChannelProvider::shared_pointer const & _channelProvider,
ChannelRequester::shared_pointer const & _channelRequester) :
@@ -367,6 +371,7 @@ CAChannel::CAChannel(std::string const & _channelName,
elementCount(0),
destroyed(false)
{
REFTRACE_INCREMENT(num_instances);
PVACCESS_REFCOUNT_MONITOR_CONSTRUCT(caChannel);
if(CAClientFactory::getDebug()>0) {
cout<< "CAChannel::CAChannel " << channelName << endl;
@@ -443,6 +448,7 @@ CAChannel::~CAChannel()
/* Clear CA Channel */
threadAttach();
ca_clear_channel(channelID);
REFTRACE_DECREMENT(num_instances);
}
@@ -652,6 +658,7 @@ static chtype getDBRType(PVStructure::shared_pointer const & pvRequest, chtype n
return nativeType;
}
size_t CAChannelGet::num_instances;
CAChannelGet::CAChannelGet(CAChannel::shared_pointer const & channel,
ChannelGetRequester::shared_pointer const & channelGetRequester,
@@ -662,6 +669,7 @@ CAChannelGet::CAChannelGet(CAChannel::shared_pointer const & channel,
pvRequest(pvRequest),
lastRequestFlag(false)
{
REFTRACE_INCREMENT(num_instances);
if(CAClientFactory::getDebug()>0) {
cout << "CAChannelGet::CAChannelGet() " << channel->getChannelName() << endl;
}
@@ -675,6 +683,7 @@ CAChannelGet::~CAChannelGet()
if(caChannel) channelName = caChannel->getChannelName();
std::cout << "CAChannelGet::~CAChannelGet() " << channelName << endl;
}
REFTRACE_DECREMENT(num_instances);
}
void CAChannelGet::activate()
@@ -1193,8 +1202,10 @@ CAChannelPut::~CAChannelPut()
if(caChannel) channelName = caChannel->getChannelName();
std::cout << "CAChannelPut::~CAChannelPut() " << channelName << endl;
}
REFTRACE_DECREMENT(num_instances);
}
size_t CAChannelPut::num_instances;
CAChannelPut::CAChannelPut(CAChannel::shared_pointer const & channel,
ChannelPutRequester::shared_pointer const & channelPutRequester,
@@ -1206,6 +1217,7 @@ CAChannelPut::CAChannelPut(CAChannel::shared_pointer const & channel,
block(false),
lastRequestFlag(false)
{
REFTRACE_INCREMENT(num_instances);
if(CAClientFactory::getDebug()>0) {
cout << "CAChannelPut::CAChannePut() " << channel->getChannelName() << endl;
}
@@ -1720,8 +1732,11 @@ CAChannelMonitor::~CAChannelMonitor()
if(!isStarted) return;
caChannel->threadAttach();
ca_clear_subscription(eventID);
REFTRACE_DECREMENT(num_instances);
}
size_t CAChannelMonitor::num_instances;
CAChannelMonitor::CAChannelMonitor(
CAChannel::shared_pointer const & channel,
MonitorRequester::shared_pointer const & monitorRequester,
@@ -1732,6 +1747,7 @@ CAChannelMonitor::CAChannelMonitor(
pvRequest(pvRequest),
isStarted(false)
{
REFTRACE_INCREMENT(num_instances);
if(CAClientFactory::getDebug()>0) {
cout << "CAChannelMonitor::CAChannelMonitor() " << channel->getChannelName() << endl;
}

View File

@@ -46,6 +46,8 @@ class CAChannel :
public:
POINTER_DEFINITIONS(CAChannel);
static size_t num_instances;
static shared_pointer create(CAChannelProvider::shared_pointer const & channelProvider,
std::string const & channelName,
short priority,
@@ -139,6 +141,8 @@ class CAChannelGet :
public:
POINTER_DEFINITIONS(CAChannelGet);
static size_t num_instances;
static CAChannelGet::shared_pointer create(CAChannel::shared_pointer const & channel,
ChannelGetRequester::shared_pointer const & channelGetRequester,
epics::pvData::PVStructure::shared_pointer const & pvRequest);
@@ -198,6 +202,8 @@ class CAChannelPut :
public:
POINTER_DEFINITIONS(CAChannelPut);
static size_t num_instances;
static CAChannelPut::shared_pointer create(CAChannel::shared_pointer const & channel,
ChannelPutRequester::shared_pointer const & channelPutRequester,
epics::pvData::PVStructure::shared_pointer const & pvRequest);
@@ -267,6 +273,8 @@ class CAChannelMonitor :
public:
POINTER_DEFINITIONS(CAChannelMonitor);
static size_t num_instances;
static CAChannelMonitor::shared_pointer create(CAChannel::shared_pointer const & channel,
MonitorRequester::shared_pointer const & monitorRequester,
epics::pvData::PVStructure::shared_pointer const & pvRequest);

View File

@@ -13,6 +13,7 @@
#include <pv/logger.h>
#include <pv/configuration.h>
#include <pv/pvAccess.h>
#include <pv/reftrack.h>
#define epicsExportSharedSymbols
#include <pv/caProvider.h>
@@ -30,17 +31,19 @@ using namespace epics::pvData;
catch (std::exception &e) { LOG(logLevelError, "Unhandled exception caught from client code at %s:%d: %s", __FILE__, __LINE__, e.what()); } \
catch (...) { LOG(logLevelError, "Unhandled exception caught from client code at %s:%d.", __FILE__, __LINE__); }
int CAClientFactory::debug = 1;
size_t CAChannelProvider::num_instances;
int CAClientFactory::debug = 0;
CAChannelProvider::CAChannelProvider()
: current_context(0)
{
REFTRACE_INCREMENT(num_instances);
initialize();
}
CAChannelProvider::CAChannelProvider(const std::tr1::shared_ptr<Configuration>&)
: current_context(0)
{
REFTRACE_INCREMENT(num_instances);
if(CAClientFactory::getDebug()>0) {
std::cout<< "CAChannelProvider::CAChannelProvider\n";
}
@@ -52,6 +55,7 @@ CAChannelProvider::CAChannelProvider(const std::tr1::shared_ptr<Configuration>&)
CAChannelProvider::~CAChannelProvider()
{
if(CAClientFactory::getDebug()>0) std::cout << "CAChannelProvider::~CAChannelProvider()\n";
REFTRACE_DECREMENT(num_instances);
}
std::string CAChannelProvider::getProviderName()
@@ -151,7 +155,9 @@ void CAChannelProvider::initialize()
static
void ca_factory_cleanup(void*)
{
std::cout << "ca_factory_cleanup\n";
if(CAClientFactory::getDebug()>0) {
std::cout << "ca_factory_cleanup\n";
}
try {
ChannelProviderRegistry::clients()->remove("ca");
ca_context_destroy();
@@ -164,6 +170,11 @@ void CAClientFactory::start()
{
epicsSignalInstallSigAlarmIgnore();
epicsSignalInstallSigPipeIgnore();
registerRefCounter("CAChannelProvider", &CAChannelProvider::num_instances);
registerRefCounter("CAChannel", &CAChannel::num_instances);
registerRefCounter("CAChannelGet", &CAChannelGet::num_instances);
registerRefCounter("CAChannelPut", &CAChannelPut::num_instances);
registerRefCounter("CAChannelMonitor", &CAChannelMonitor::num_instances);
if(ChannelProviderRegistry::clients()->add<CAChannelProvider>("ca", false))
epicsAtExit(&ca_factory_cleanup, NULL);

View File

@@ -30,6 +30,8 @@ class CAChannelProvider :
public:
POINTER_DEFINITIONS(CAChannelProvider);
static size_t num_instances;
CAChannelProvider();
CAChannelProvider(const std::tr1::shared_ptr<Configuration>&);
virtual ~CAChannelProvider();

View File

@@ -4,13 +4,14 @@
* in file LICENSE that is included with this distribution.
*/
#define epicsExportSharedSymbols
#include <pv/caStatus.h>
namespace epics {
namespace pvAccess {
namespace ca {
std::string dbrStatus2alarmMessage[] = {
epicsShareDef std::string dbrStatus2alarmMessage[] = {
"NO_ALARM", // 0 ..
"READ_ALARM",
"WRITE_ALARM",
@@ -35,7 +36,7 @@ std::string dbrStatus2alarmMessage[] = {
"WRITE_ACCESS_ALARM" // .. 21
};
int dbrStatus2alarmStatus[] = {
epicsShareDef int dbrStatus2alarmStatus[] = {
noStatus, //"NO_ALARM"
driverStatus, //"READ_ALARM",
driverStatus, //"WRITE_ALARM",

View File

@@ -8,6 +8,7 @@
#define CASTATUS_H
#include <string>
#include <shareLib.h>
namespace epics {
namespace pvAccess {
@@ -18,8 +19,8 @@ enum AlarmStatus {
dbStatus,confStatus,undefinedStatus,clientStatus
};
extern std::string dbrStatus2alarmMessage[];
extern int dbrStatus2alarmStatus[];
epicsShareExtern std::string dbrStatus2alarmMessage[];
epicsShareExtern int dbrStatus2alarmStatus[];
}
}

View File

@@ -1056,7 +1056,10 @@ public:
POINTER_DEFINITIONS(ChannelRequester);
typedef Channel operation_type;
virtual ~ChannelRequester() {}
static size_t num_instances;
ChannelRequester();
virtual ~ChannelRequester();
/**
* The request made with ChannelProvider::createChannel() is satisfied.

View File

@@ -4,6 +4,8 @@
* in file LICENSE that is included with this distribution.
*/
#include <pv/reftrack.h>
#define epicsExportSharedSymbols
#include <pv/pvAccess.h>
@@ -118,6 +120,19 @@ ChannelArray::shared_pointer Channel::createChannelArray(
return ret;
}
size_t ChannelRequester::num_instances;
ChannelRequester::ChannelRequester()
{
REFTRACE_INCREMENT(num_instances);
}
ChannelRequester::~ChannelRequester()
{
REFTRACE_DECREMENT(num_instances);
}
std::string DefaultChannelRequester::getRequesterName() { return "DefaultChannelRequester"; }
void DefaultChannelRequester::channelCreated(const epics::pvData::Status& status, Channel::shared_pointer const & channel)

View File

@@ -12,10 +12,14 @@
#include <pv/lock.h>
#include <pv/noDefaultMethods.h>
#include <pv/pvData.h>
#include <pv/reftrack.h>
#include <pv/timer.h>
#define epicsExportSharedSymbols
#include <pv/pvAccess.h>
#include <pv/factory.h>
#include "pv/codec.h"
#include <pv/serverContextImpl.h>
using namespace epics::pvData;
using std::string;
@@ -156,6 +160,9 @@ epicsThreadOnceId providerRegOnce = EPICS_THREAD_ONCE_INIT;
void providerRegInit(void*)
{
providerRegGbl = new providerRegGbl_t;
registerRefCounter("ServerContext (PVA)", &ServerContextImpl::num_instances);
registerRefCounter("BlockingTCPTransportCodec", &detail::BlockingTCPTransportCodec::num_instances);
registerRefCounter("ChannelRequester", &ChannelRequester::num_instances);
}
} // namespace

View File

@@ -7,11 +7,13 @@ pvAccessIOC_LIBS += pvAccess pvData
pvAccessIOC_LIBS += $(EPICS_BASE_IOC_LIBS)
INC += pv/syncChannelFind.h
INC += pv/iocshelper.h
DBD += PVAServerRegister.dbd
DBD += PVAClientRegister.dbd
pvAccessIOC_SRCS += PVAServerRegister.cpp
pvAccessIOC_SRCS += PVAClientRegister.cpp
pvAccessIOC_SRCS += reftrackioc.cpp
include $(TOP)/configure/RULES

View File

@@ -30,18 +30,19 @@
#include <pv/pvAccess.h>
#include <pv/serverContext.h>
#include <pv/iocshelper.h>
#include <epicsExport.h>
using std::cout;
using std::endl;
namespace pvd = epics::pvData;
namespace pva = epics::pvAccess;
static pvd::Mutex the_server_lock;
static pva::ServerContext::shared_pointer the_server;
namespace {
static void startitup() {
pvd::Mutex the_server_lock;
pva::ServerContext::shared_pointer the_server;
void startitup() {
the_server = pva::ServerContext::create(pva::ServerContext::Config()
.config(pva::ConfigurationBuilder()
// default to all providers instead of just "local"
@@ -53,17 +54,9 @@ static void startitup() {
.build()));
}
static const iocshArg startPVAServerArg0 = { "providerNames", iocshArgString };
static const iocshArg *startPVAServerArgs[] = {
&startPVAServerArg0};
static const iocshFuncDef startPVAServerFuncDef = {
"startPVAServer", 1, startPVAServerArgs
};
static void startPVAServer(const iocshArgBuf *args)
void startPVAServer(const char *names)
{
try {
char *names = args[0].sval;
if(names && names[0]!='\0') {
printf("Warning: startPVAServer() no longer accepts provider list as argument.\n"
" Instead place the following before calling startPVAServer() and iocInit()\n"
@@ -81,11 +74,7 @@ static void startPVAServer(const iocshArgBuf *args)
}
}
static const iocshArg *stopPVAServerArgs[1] = {};
static const iocshFuncDef stopPVAServerFuncDef = {
"stopPVAServer", 0, stopPVAServerArgs
};
static void stopPVAServer(const iocshArgBuf *args)
void stopPVAServer()
{
try {
pvd::Lock G(the_server_lock);
@@ -99,11 +88,7 @@ static void stopPVAServer(const iocshArgBuf *args)
}
}
static const iocshArg *statusPVAServerArgs[1] = {};
static const iocshFuncDef statusPVAServerFuncDef = {
"statusPVAServer", 0, statusPVAServerArgs
};
static void statusPVAServer(const iocshArgBuf *args)
void statusPVAServer()
{
try {
pvd::Lock G(the_server_lock);
@@ -118,7 +103,7 @@ static void statusPVAServer(const iocshArgBuf *args)
}
}
static void initStartPVAServer(initHookState state)
void initStartPVAServer(initHookState state)
{
pvd::Lock G(the_server_lock);
if(state==initHookAfterIocRunning && !the_server) {
@@ -130,14 +115,16 @@ static void initStartPVAServer(initHookState state)
}
static void registerStartPVAServer(void)
void registerStartPVAServer(void)
{
iocshRegister(&startPVAServerFuncDef, startPVAServer);
iocshRegister(&stopPVAServerFuncDef, stopPVAServer);
iocshRegister(&statusPVAServerFuncDef, statusPVAServer);
epics::iocshRegister<const char*, &startPVAServer>("startPVAServer", "provider names");
epics::iocshRegister<&statusPVAServer>("statusPVAServer");
epics::iocshRegister<&stopPVAServer>("stopPVAServer");
initHookRegister(&initStartPVAServer);
}
} // namespace
extern "C" {
epicsExportRegistrar(registerStartPVAServer);
}

View File

@@ -1 +1,2 @@
registrar("registerStartPVAServer")
registrar("refTrackRegistrar")

156
src/ioc/pv/iocshelper.h Normal file
View File

@@ -0,0 +1,156 @@
#ifndef IOCSHELPER_H
#define IOCSHELPER_H
/** Helper for exposing functions and variables in the IOC shell
*
* Limitations:
* - supports functions with up to 4 arguments
* - argument and variable types must be: int, double, char*, or const char*
*
@code
#include <pv/iocshelper.h>
void fn0() {}
void fn2(int a, const char *b) {}
int var;
void myRegistrar() {
epics::iocshRegister<&fn0>("fn0");
epics::iocshRegister<int, const char*, &fn2>("fn0", "a description", "b description");
epics::iocshVariable<int, &var>("var");
}
extern "C" {
epicsExportRegistrar(myRegistrar);
}
@endcode
*/
#include <string>
#include <iocsh.h>
namespace epics {
namespace detail {
template<typename T>
struct getarg {};
template<> struct getarg<int> {
static int op(const iocshArgBuf& a) { return a.ival; }
enum { argtype = iocshArgInt };
};
template<> struct getarg<double> {
static double op(const iocshArgBuf& a) { return a.dval; }
enum { argtype = iocshArgDouble };
};
template<> struct getarg<char*> {
static char* op(const iocshArgBuf& a) { return a.sval; }
enum { argtype = iocshArgString };
};
template<> struct getarg<const char*> {
static const char* op(const iocshArgBuf& a) { return a.sval; }
enum { argtype = iocshArgString };
};
template<int N>
struct iocshFuncInfo{
iocshFuncDef def;
std::string name;
iocshArg *argarr[N+1];
iocshArg args[N+1];
std::string argnames[N+1];
iocshFuncInfo(const std::string& n) :name(n) {
def.name = name.c_str();
def.nargs = N;
def.arg = (iocshArg**)&argarr;
for(size_t i=0; i<N; i++)
argarr[i] = &args[i];
}
template<int n, typename T>
void set(const char *name) {
argnames[n] = name;
args[n].name = argnames[n].c_str();
args[n].type = (iocshArgType)detail::getarg<T>::argtype;
}
};
template<void (*fn)()>
static void call0(const iocshArgBuf *args)
{
fn();
}
template<typename A, void (*fn)(A)>
static void call1(const iocshArgBuf *args)
{
fn(getarg<A>::op(args[0]));
}
template<typename A, typename B, void (*fn)(A,B)>
static void call2(const iocshArgBuf *args)
{
fn(getarg<A>::op(args[0]),
getarg<B>::op(args[1]));
}
template<typename A, typename B, typename C, void (*fn)(A,B,C)>
static void call3(const iocshArgBuf *args)
{
fn(getarg<A>::op(args[0]),
getarg<B>::op(args[1]),
getarg<C>::op(args[2]));
}
} // namespace detail
template<void (*fn)()>
void iocshRegister(const char *name)
{
static detail::iocshFuncInfo<0> info(name);
iocshRegister(&info.def, &detail::call0<fn>);
}
template<typename A, void (*fn)(A)>
void iocshRegister(const char *name, const char *arg1name)
{
static detail::iocshFuncInfo<1> info(name);
info.set<0,A>(arg1name);
iocshRegister(&info.def, &detail::call1<A, fn>);
}
template<typename A, typename B, void (*fn)(A,B)>
void iocshRegister(const char *name,
const char *arg1name,
const char *arg2name)
{
static detail::iocshFuncInfo<2> info(name);
info.set<0,A>(arg1name);
info.set<1,B>(arg2name);
iocshRegister(&info.def, &detail::call2<A, B, fn>);
}
template<typename A, typename B, typename C, void (*fn)(A,B,C)>
void iocshRegister(const char *name,
const char *arg1name,
const char *arg2name,
const char *arg3name)
{
static detail::iocshFuncInfo<3> info(name);
info.set<0,A>(arg1name);
info.set<1,B>(arg2name);
info.set<2,C>(arg3name);
iocshRegister(&info.def, &detail::call3<A, B, C, fn>);
}
template<typename V, V* addr>
void iocshVariable(const char *name)
{
static iocshVarDef def[2];
def[0].name = name;
def[0].pval = (void*)addr;
def[0].type = (iocshArgType)detail::getarg<V>::argtype;
def[1].name = NULL;
iocshRegisterVariable(def);
}
} // namespace epics
#endif // IOCSHELPER_H

90
src/ioc/reftrackioc.cpp Normal file
View File

@@ -0,0 +1,90 @@
/**
* 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.
*/
#include <exception>
#include <pv/reftrack.h>
#include <pv/iocshelper.h>
#include <iocsh.h>
#include <epicsExport.h>
namespace {
void showRefs(const epics::RefSnapshot& snap, int lvl, bool delta)
{
for(epics::RefSnapshot::const_iterator it = snap.begin(), end = snap.end();
it != end; ++it)
{
if(it->second.current==0 && it->second.delta==0 && lvl<=0) continue;
if(delta && it->second.delta==0 && lvl<=0) continue;
if(delta) {
printf(" %s : %zu (delta %zd)\n",
it->first.c_str(), it->second.current, it->second.delta);
} else {
printf(" %s : %zu\n", it->first.c_str(), it->second.current);
}
}
}
#define CATCH() catch(std::exception& e){printf("Error %s\n", e.what());}
void refshow(int lvl)
{
try {
epics::RefSnapshot snap;
snap.update();
showRefs(snap, lvl, false);
}CATCH()
}
// No locking. assume only interactive iocsh use
static epics::RefSnapshot savedSnap;
void refsave()
{
try {
epics::RefSnapshot snap;
snap.update();
savedSnap.swap(snap);
}CATCH()
}
void refdiff(int lvl)
{
epics::RefSnapshot snap;
snap.update();
showRefs(snap-savedSnap, lvl, true);
}
static epics::RefMonitor gblmon;
void refmon(double period, int lvl)
{
if(period==0) {
gblmon.stop();
} else if(period>0) {
gblmon.start(period);
}
}
void refTrackRegistrar()
{
epics::iocshRegister<int, &refshow>("refshow", "detail level");
epics::iocshRegister<&refsave>("refsave");
epics::iocshRegister<int, &refdiff>("refdiff", "detail level");
epics::iocshRegister<double, int, &refmon>("refmon", "update period", "detail level");
}
} // namespace
extern "C" {
epicsExportRegistrar(refTrackRegistrar);
}

View File

@@ -27,6 +27,7 @@
#include <pv/lock.h>
#include <pv/timer.h>
#include <pv/event.h>
#include <pv/reftrack.h>
#define epicsExportSharedSymbols
#include <pv/blockingTCP.h>
@@ -1001,6 +1002,8 @@ bool AbstractCodec::directDeserialize(ByteBuffer *existingBuffer, char* deserial
BlockingTCPTransportCodec::~BlockingTCPTransportCodec()
{
REFTRACE_DECREMENT(num_instances);
waitJoin();
}
@@ -1138,6 +1141,7 @@ void BlockingTCPTransportCodec::sendBufferFull(int tries) {
//
//
size_t BlockingTCPTransportCodec::num_instances;
BlockingTCPTransportCodec::BlockingTCPTransportCodec(bool serverFlag, const Context::shared_pointer &context,
SOCKET channel, const ResponseHandler::shared_pointer &responseHandler,
@@ -1163,6 +1167,8 @@ BlockingTCPTransportCodec::BlockingTCPTransportCodec(bool serverFlag, const Cont
,_remoteTransportRevision(0), _priority(priority)
,_verified(false)
{
REFTRACE_INCREMENT(num_instances);
_isOpen.getAndSet(true);
// get remote address

View File

@@ -302,6 +302,8 @@ public:
POINTER_DEFINITIONS(BlockingTCPTransportCodec);
static size_t num_instances;
BlockingTCPTransportCodec(
bool serverFlag,
Context::shared_pointer const & context,

View File

@@ -374,15 +374,9 @@ public:
epics::pvData::ByteBuffer* payloadBuffer) = 0;
};
/**
* Base (abstract) channel access response handler.
*/
class AbstractResponseHandler : public ResponseHandler {
public:
/**
* @param description
*/
AbstractResponseHandler(Context* context, std::string description) :
AbstractResponseHandler(Context* context, const std::string& description) :
_description(description),
_debugLevel(context->getConfiguration()->getPropertyAsInteger(PVACCESS_DEBUG, 0)) {
}

View File

@@ -14,6 +14,7 @@
#include <pv/timer.h>
#include <pv/bitSetUtil.h>
#include <pv/standardPVField.h>
#include <pv/reftrack.h>
#define epicsExportSharedSymbols
#include <pv/pvAccess.h>
@@ -165,6 +166,9 @@ protected:
return std::tr1::static_pointer_cast<subklass>(P);
}
public:
static size_t num_instances;
static size_t num_active;
template<class subklass>
static
typename std::tr1::shared_ptr<subklass>
@@ -180,6 +184,7 @@ public:
const_cast<BaseRequestImpl::weak_pointer&>(internal->m_this_internal) = internal;
const_cast<BaseRequestImpl::weak_pointer&>(internal->m_this_external) = external;
internal->activate();
REFTRACE_INCREMENT(num_active);
return external;
}
protected:
@@ -197,9 +202,13 @@ protected:
m_destroyed(false),
m_initialized(false),
m_subscribed()
{}
{
REFTRACE_INCREMENT(num_instances);
}
virtual ~BaseRequestImpl() {}
virtual ~BaseRequestImpl() {
REFTRACE_DECREMENT(num_instances);
}
virtual void activate() {
// register response request
@@ -344,6 +353,8 @@ public:
}
}
REFTRACE_DECREMENT(num_active);
}
virtual void timeout() OVERRIDE FINAL {
@@ -396,6 +407,8 @@ public:
};
size_t BaseRequestImpl::num_instances;
size_t BaseRequestImpl::num_active;
PVDataCreatePtr BaseRequestImpl::pvDataCreate = getPVDataCreate();
@@ -3248,6 +3261,11 @@ private:
*/
ServerGUID m_guid;
public:
static size_t num_instances;
static size_t num_active;
private:
/**
* Constructor.
* @param context
@@ -3275,6 +3293,7 @@ private:
m_serverChannelID(0xFFFFFFFF),
m_issueCreateMessage(true)
{
REFTRACE_INCREMENT(num_instances);
PVACCESS_REFCOUNT_MONITOR_CONSTRUCT(channel);
}
@@ -3285,6 +3304,8 @@ private:
// connect
connect();
REFTRACE_INCREMENT(num_active);
}
public:
@@ -3307,11 +3328,15 @@ private:
virtual ~InternalChannelImpl()
{
REFTRACE_DECREMENT(num_instances);
PVACCESS_REFCOUNT_MONITOR_DESTRUCT(channel);
}
virtual void destroy() OVERRIDE FINAL
{
REFTRACE_DECREMENT(num_active);
destroy(false);
}
@@ -4035,6 +4060,7 @@ public:
public:
static size_t num_instances;
InternalClientContextImpl(const Configuration::shared_pointer& conf) :
m_addressList(""), m_autoAddressList(true), m_connectionTimeout(30.0f), m_beaconPeriod(15.0f),
@@ -4049,6 +4075,8 @@ public:
m_configuration(conf),
m_flushStrategy(DELAYED)
{
REFTRACE_INCREMENT(num_instances);
PVACCESS_REFCOUNT_MONITOR_CONSTRUCT(remoteClientContext);
MB_INIT;
if(!m_configuration) m_configuration = ConfigurationFactory::getConfiguration("pvAccess-client");
@@ -4148,6 +4176,7 @@ public:
virtual ~InternalClientContextImpl()
{
REFTRACE_DECREMENT(num_instances);
PVACCESS_REFCOUNT_MONITOR_DESTRUCT(remoteClientContext);
}
@@ -4716,6 +4745,10 @@ private:
FlushStrategy m_flushStrategy;
};
size_t InternalClientContextImpl::num_instances;
size_t InternalClientContextImpl::InternalChannelImpl::num_instances;
size_t InternalClientContextImpl::InternalChannelImpl::num_active;
PVACCESS_REFCOUNT_MONITOR_DEFINE(channelGetField);
class ChannelGetFieldRequestImpl :
@@ -4908,6 +4941,11 @@ namespace pvAccess {
ChannelProvider::shared_pointer createClientProvider(const Configuration::shared_pointer& conf)
{
registerRefCounter("InternalClientContextImpl", &InternalClientContextImpl::num_instances);
registerRefCounter("InternalChannelImpl", &InternalClientContextImpl::InternalChannelImpl::num_instances);
registerRefCounter("InternalChannelImpl (Active)", &InternalClientContextImpl::InternalChannelImpl::num_active);
registerRefCounter("BaseRequestImpl", &BaseRequestImpl::num_instances);
registerRefCounter("BaseRequestImpl (Active)", &BaseRequestImpl::num_active);
InternalClientContextImpl::shared_pointer internal(new InternalClientContextImpl(conf)),
external(internal.get(), epics::pvAccess::Destroyable::cleaner(internal));
const_cast<InternalClientContextImpl::weak_pointer&>(internal->m_external_this) = external;

View File

@@ -32,6 +32,8 @@ public:
typedef std::tr1::shared_ptr<ServerContextImpl> shared_pointer;
typedef std::tr1::shared_ptr<const ServerContextImpl> const_shared_pointer;
static size_t num_instances;
ServerContextImpl();
virtual ~ServerContextImpl();

View File

@@ -9,6 +9,7 @@
#include <pv/lock.h>
#include <pv/timer.h>
#include <pv/thread.h>
#include <pv/reftrack.h>
#define epicsExportSharedSymbols
#include <pv/responseHandlers.h>
@@ -27,6 +28,8 @@ namespace pvAccess {
const Version ServerContextImpl::VERSION("pvAccess Server", "cpp",
EPICS_PVA_MAJOR_VERSION, EPICS_PVA_MINOR_VERSION, EPICS_PVA_MAINTENANCE_VERSION, EPICS_PVA_DEVELOPMENT_FLAG);
size_t ServerContextImpl::num_instances;
ServerContextImpl::ServerContextImpl():
_beaconAddressList(),
_ignoreAddressList(),
@@ -43,6 +46,8 @@ ServerContextImpl::ServerContextImpl():
_beaconServerStatusProvider(),
_startTime()
{
REFTRACE_INCREMENT(num_instances);
epicsTimeGetCurrent(&_startTime);
// TODO maybe there is a better place for this (when there will be some factory)
@@ -63,6 +68,7 @@ ServerContextImpl::~ServerContextImpl()
{
std::cerr<<"Error in: ServerContextImpl::dispose: "<<e.what()<<"\n";
}
REFTRACE_DECREMENT(num_instances);
}
const ServerGUID& ServerContextImpl::getGUID()