add target_information()
Print from: pvxinfo -D and new iocsh iocsh pvxs_target_info()
This commit is contained in:
@@ -136,3 +136,5 @@ Misc. utility code. ::
|
||||
.. doxygenfunction:: pvxs::cleanup_for_valgrind
|
||||
|
||||
.. doxygenclass:: pvxs::SigInt
|
||||
|
||||
.. doxygenfunction:: pvxs::target_information
|
||||
|
||||
+16
-4
@@ -72,6 +72,17 @@ void pvxsr(int detail)
|
||||
}
|
||||
}
|
||||
|
||||
void pvxs_target_info()
|
||||
{
|
||||
try {
|
||||
std::ostringstream capture;
|
||||
target_information(capture);
|
||||
printf("%s", capture.str().c_str());
|
||||
} catch(std::exception& e) {
|
||||
fprintf(stderr, "Error in %s : %s\n", __func__, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// index_sequence from:
|
||||
//http://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence
|
||||
|
||||
@@ -127,11 +138,11 @@ struct ToStr { typedef const char* type; };
|
||||
template<typename ...Args>
|
||||
struct Reg {
|
||||
const char* const name;
|
||||
const char* const argnames[sizeof...(Args)];
|
||||
const char* const argnames[1+sizeof...(Args)];
|
||||
|
||||
constexpr explicit Reg(const char* name, typename ToStr<Args>::type... descs)
|
||||
:name(name)
|
||||
,argnames{descs...}
|
||||
,argnames{descs..., 0}
|
||||
{}
|
||||
|
||||
template<void (*fn)(Args...), size_t... Idxs>
|
||||
@@ -144,8 +155,8 @@ struct Reg {
|
||||
template<void (*fn)(Args...), size_t... Idxs>
|
||||
void doit(index_sequence<Idxs...>)
|
||||
{
|
||||
static const iocshArg argstack[sizeof...(Args)] = {{argnames[Idxs], Arg<Args>::code}...};
|
||||
static const iocshArg * const args[] = {&argstack[Idxs]...};
|
||||
static const iocshArg argstack[1+sizeof...(Args)] = {{argnames[Idxs], Arg<Args>::code}...};
|
||||
static const iocshArg * const args[] = {&argstack[Idxs]..., 0};
|
||||
static const iocshFuncDef def = {name, sizeof...(Args), args};
|
||||
|
||||
iocshRegister(&def, &call<fn, Idxs...>);
|
||||
@@ -207,6 +218,7 @@ void pvxsRegistrar()
|
||||
|
||||
Reg<int>("pvxsl", "detail").ister<&pvxsl>();
|
||||
Reg<int>("pvxsr", "detail").ister<&pvxsr>();
|
||||
Reg<>("pvxs_target_info").ister<&pvxs_target_info>();
|
||||
|
||||
auto serv = instance.load();
|
||||
if(!serv) {
|
||||
|
||||
@@ -34,9 +34,16 @@ ifeq (,$(PVXS_MAJOR_VERSION))
|
||||
$(error PVXS_MAJOR_VERSION undefined, problem reading cfg/CONFIG_PVXS_VERSION)
|
||||
endif
|
||||
|
||||
# see below for special case versionNum.h
|
||||
EXPAND += describe.h
|
||||
|
||||
EXPANDVARS += PVXS_MAJOR_VERSION
|
||||
EXPANDVARS += PVXS_MINOR_VERSION
|
||||
EXPANDVARS += PVXS_MAINTENANCE_VERSION
|
||||
EXPANDVARS += EPICS_HOST_ARCH T_A OS_CLASS
|
||||
ifdef BASE_3_15
|
||||
EXPANDVARS += CMPLR_CLASS
|
||||
endif
|
||||
|
||||
EXPANDFLAGS += $(foreach var,$(EXPANDVARS),-D$(var)="$(strip $($(var)))")
|
||||
|
||||
@@ -61,6 +68,7 @@ INC += pvxs/client.h
|
||||
|
||||
LIBRARY = pvxs
|
||||
|
||||
LIB_SRCS += describe.cpp
|
||||
LIB_SRCS += log.cpp
|
||||
LIB_SRCS += unittest.cpp
|
||||
LIB_SRCS += util.cpp
|
||||
@@ -118,6 +126,7 @@ include $(TOP)/configure/RULES_PVXS_MODULE
|
||||
$(MKDIR) $(COMMON_DIR)/pvxs
|
||||
$(EXPAND_TOOL) $(EXPANDFLAGS) $($@_EXPANDFLAGS) $< $@
|
||||
|
||||
describe$(DEP): describe.h
|
||||
util$(DEP): $(COMMON_DIR)/$(GENVERSION)
|
||||
|
||||
ifndef GENVERSIONHEADER
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvxs is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#if !defined(_WIN32)
|
||||
# include <sys/utsname.h>
|
||||
#endif
|
||||
|
||||
#include <osiSock.h>
|
||||
#include <dbDefs.h>
|
||||
#include <epicsThread.h>
|
||||
|
||||
#include <pvxs/util.h>
|
||||
#include <pvxs/client.h>
|
||||
#include <pvxs/server.h>
|
||||
|
||||
#include "evhelper.h"
|
||||
#include "describe.h"
|
||||
|
||||
namespace pvxs {
|
||||
|
||||
std::ostream& target_information(std::ostream& strm)
|
||||
{
|
||||
strm<<indent{}<<"Host: "<<EPICS_HOST_ARCH<<"\n";
|
||||
strm<<indent{}<<"Target: "<<T_A<<" "<<OS_CLASS;
|
||||
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
|
||||
strm<<" "<<CMPLR_CLASS;
|
||||
#endif
|
||||
strm<<"\n";
|
||||
|
||||
{
|
||||
strm<<indent{}<<"Toolchain\n";
|
||||
Indented I(strm);
|
||||
|
||||
// standard
|
||||
strm<<indent{}<<"__cplusplus = "<<__cplusplus<<"\n";
|
||||
|
||||
// compiler
|
||||
#ifdef __clang__
|
||||
strm<<indent{}<<"clang "<<__clang_version__<<"\n";
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
strm<<indent{}<<"GCC "<<__GNUC__<<"."<<__GNUC_MINOR__<<"."<<__GNUC_PATCHLEVEL__<<"\n";
|
||||
#endif
|
||||
#ifdef _GLIBCXX_USE_CXX11_ABI
|
||||
strm<<indent{}<<"_GLIBCXX_USE_CXX11_ABI = "<<_GLIBCXX_USE_CXX11_ABI<<"\n";
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
strm<<indent{}<<"MSVC "<<_MSC_FULL_VER<<"\n";
|
||||
#endif
|
||||
|
||||
// library
|
||||
#ifdef __GLIBC__
|
||||
strm<<indent{}<<"GLIBC "<<__GLIBC__<<"."<<__GLIBC_MINOR__<<"\n";
|
||||
#endif
|
||||
#ifdef __UCLIBC__
|
||||
strm<<indent{}<<"GLIBC "<<__UCLIBC_MAJOR__<<"."<<__UCLIBC_MINOR__<<"."<<__UCLIBC_SUBLEVEL__<<"\n";
|
||||
#endif
|
||||
#ifdef _CPPLIB_VER
|
||||
// Dinkumware c++
|
||||
strm<<indent{}<<"_CPPLIB_VER "<<_CPPLIB_VER<<"\n";
|
||||
#endif
|
||||
#ifdef __GLIBCXX__
|
||||
strm<<indent{}<<"__GLIBCXX__ "<<__GLIBCXX__<<"\n";
|
||||
#endif
|
||||
#ifdef _LIBCPP_VERSION
|
||||
// clang c++
|
||||
strm<<indent{}<<"_LIBCPP_VERSION "<<_LIBCPP_VERSION<<"\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
strm<<"Versions\n";
|
||||
Indented I(strm);
|
||||
strm<<indent{}<<version_str()<<"\n";
|
||||
strm<<indent{}<<EPICS_VERSION_STRING<<"\n";
|
||||
strm<<indent{}<<"libevent "<<event_get_version()<<"\n";
|
||||
}
|
||||
|
||||
{
|
||||
strm<<indent{}<<"Runtime\n";
|
||||
Indented I(strm);
|
||||
|
||||
SockAttach attach;
|
||||
evsocket dummy(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
#if !defined(_WIN32)
|
||||
utsname info;
|
||||
if(uname(&info)==0) {
|
||||
strm<<indent{}<<"uname() -> "<<info.sysname<<" "<<info.nodename<<" "<<info.release<<" "<<info.version<<" "<<info.machine<<"\n";
|
||||
} else {
|
||||
strm<<indent{}<<"uname() error "<<errno<<"\n";
|
||||
}
|
||||
#endif
|
||||
|
||||
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,2)
|
||||
strm<<indent{}<<"epicsThreadGetCPUs() -> "<<epicsThreadGetCPUs()<<"\n";
|
||||
#endif
|
||||
|
||||
auto localaddr(osiLocalAddr(dummy.sock));
|
||||
strm<<indent{}<<"osiLocalAddr() -> "<<SockAddr(&localaddr.sa, sizeof(localaddr)).tostring()<<"\n";
|
||||
|
||||
strm<<indent{}<<"osiSockDiscoverBroadcastAddresses() ->\n";
|
||||
Indented J(strm);
|
||||
for(auto& addr : dummy.interfaces()) {
|
||||
strm<<indent{}<<addr.tostring()<<"\n";
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
strm<<indent{}<<"Effective Client config from environment\n";
|
||||
Indented I(strm);
|
||||
auto conf(client::Config::fromEnv());
|
||||
conf.expand();
|
||||
strm<<conf;
|
||||
}
|
||||
|
||||
{
|
||||
strm<<indent{}<<"Effective Server config from environment\n";
|
||||
Indented I(strm);
|
||||
auto conf(server::Config::fromEnv());
|
||||
conf.expand();
|
||||
strm<<conf;
|
||||
}
|
||||
|
||||
strm.flush();
|
||||
return strm;
|
||||
}
|
||||
|
||||
} // namespace pvxs
|
||||
@@ -0,0 +1,4 @@
|
||||
#define EPICS_HOST_ARCH "@EPICS_HOST_ARCH@"
|
||||
#define T_A "@T_A@"
|
||||
#define OS_CLASS "@OS_CLASS@"
|
||||
#define CMPLR_CLASS "@CMPLR_CLASS@"
|
||||
@@ -156,6 +156,18 @@ private:
|
||||
int lvl;
|
||||
};
|
||||
|
||||
/** Describe build and runtime configuration of current system.
|
||||
*
|
||||
* Print information which may be using for when troubleshooting,
|
||||
* or creating a bug report.
|
||||
*
|
||||
* Printed by CLI "pvxinfo -D" and iocsh "pvxs_target_information".
|
||||
*
|
||||
* @returns The same ostream passed as argument.
|
||||
*/
|
||||
PVXS_API
|
||||
std::ostream& target_information(std::ostream&);
|
||||
|
||||
} // namespace pvxs
|
||||
|
||||
#endif // PVXS_UTIL_H
|
||||
|
||||
+2
-1
@@ -25,7 +25,7 @@ namespace {
|
||||
|
||||
MAIN(testioc)
|
||||
{
|
||||
testPlan(4);
|
||||
testPlan(5);
|
||||
testSetup();
|
||||
|
||||
testdbPrepare();
|
||||
@@ -37,6 +37,7 @@ MAIN(testioc)
|
||||
testdbReadDatabase("testioc.dbd", nullptr, nullptr);
|
||||
testEq(0, testioc_registerRecordDeviceDriver(pdbbase));
|
||||
testEq(0, iocshCmd("pvxsr()"));
|
||||
testEq(0, iocshCmd("pvxs_target_info()"));
|
||||
|
||||
testTrue(!!ioc::server());
|
||||
|
||||
|
||||
+5
-1
@@ -29,6 +29,7 @@ void usage(const char* argv0)
|
||||
" -V Print version and exit.\n"
|
||||
" -v Make more noise.\n"
|
||||
" -d Shorthand for $PVXS_LOG=\"pvxs.*=DEBUG\". Make a lot of noise.\n"
|
||||
" -D Print host troubleshooting information.\n"
|
||||
" -w <sec> Operation timeout in seconds. default 5 sec.\n"
|
||||
;
|
||||
}
|
||||
@@ -44,7 +45,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
{
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "hVvdw:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "hVvdDw:")) != -1) {
|
||||
switch(opt) {
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
@@ -60,6 +61,9 @@ int main(int argc, char *argv[])
|
||||
case 'd':
|
||||
logger_level_set("pvxs.*", Level::Debug);
|
||||
break;
|
||||
case 'D':
|
||||
target_information(std::cout);
|
||||
return 0;
|
||||
case 'w':
|
||||
timeout = parseTo<double>(optarg);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user