ioc: add instance counter tools to IOC shell
This commit is contained in:
@@ -128,6 +128,79 @@ void pvxsi() {
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void pvxrefshow() {
|
||||
auto refs(instanceSnapshot());
|
||||
for(auto& pair : refs) {
|
||||
if(pair.second>0u)
|
||||
printf("%s\t= %zu\n", pair.first.c_str(), pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
struct RefTrack {
|
||||
epicsMutex lock;
|
||||
std::map<std::string, size_t> refs;
|
||||
} *refTrack;
|
||||
|
||||
epicsThreadOnceId refSavedOnce = EPICS_THREAD_ONCE_INIT;
|
||||
|
||||
void refSavedInit(void *) {
|
||||
refTrack = new RefTrack();
|
||||
}
|
||||
|
||||
void pvxrefsave() {
|
||||
epicsThreadOnce(&refSavedOnce, &refSavedInit, nullptr);
|
||||
epicsGuard<epicsMutex> G(refTrack->lock);
|
||||
refTrack->refs = instanceSnapshot();
|
||||
}
|
||||
|
||||
void pvxrefdiff() {
|
||||
auto cur(instanceSnapshot());
|
||||
std::map<std::string, int64_t> diff;
|
||||
|
||||
epicsThreadOnce(&refSavedOnce, &refSavedInit, nullptr);
|
||||
{
|
||||
epicsGuard<epicsMutex> G(refTrack->lock);
|
||||
|
||||
auto& prev(refTrack->refs);
|
||||
|
||||
// Both std::map will iterate in the same order. So co-iterate.
|
||||
// Some keys may appear in one but not the other.
|
||||
auto itC = cur.begin();
|
||||
auto itP = prev.begin();
|
||||
while(true) {
|
||||
bool haveC = itC!=cur.end();
|
||||
bool haveP = itP!=prev.end();
|
||||
int ord = haveC && haveP ? itC->first.compare(itP->first) : 0;
|
||||
|
||||
if(haveC && haveP && ord==0) {
|
||||
diff[itC->first] = int64_t(itC->second) - int64_t(itP->second);
|
||||
++itC;
|
||||
++itP;
|
||||
|
||||
} else if(haveP && (!haveC || ord > 0)) { // !cur || cur > prev
|
||||
diff[itP->first] = -int64_t(itP->second);
|
||||
++itP;
|
||||
|
||||
} else if(haveC && (!haveP || ord < 0)) { // !prev || cur < prev
|
||||
diff[itC->first] = int64_t(itC->second);
|
||||
++itC;
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(auto& pair : diff) {
|
||||
if(pair.second!=0u)
|
||||
printf("%s\t= %lld\n", pair.first.c_str(), (long long)pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
* Initialise and control state of pvxs ioc server instance in response to iocInitHook events.
|
||||
* Installed on the initHookState hook this function will respond to the following events:
|
||||
@@ -219,6 +292,13 @@ void pvxsBaseRegistrar() {
|
||||
.implementation<&pvxsr>();
|
||||
IOCShCommand<>("pvxsi", "Show detailed server information\n").implementation<&pvxsi>();
|
||||
|
||||
IOCShCommand<>("pvxrefshow",
|
||||
"Show instance counts for various internal data structures.\n").implementation<&pvxrefshow>();
|
||||
IOCShCommand<>("pvxrefsave",
|
||||
"Save the current set of instance counters for reference by later pvxrefdiff.\n").implementation<&pvxrefsave>();
|
||||
IOCShCommand<>("pvxrefdiff",
|
||||
"Show different of current instance counts with those when pvxrefsave was called.\n").implementation<&pvxrefdiff>();
|
||||
|
||||
// Initialise the PVXS Server
|
||||
initialisePvxsServer();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user