From 044b0db7af2d80a05a2cba76446115cf611387b9 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Tue, 21 Feb 2023 12:03:00 -0800 Subject: [PATCH] ioc: add instance counter tools to IOC shell --- ioc/iochooks.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/ioc/iochooks.cpp b/ioc/iochooks.cpp index d40ffd6..6a33eee 100644 --- a/ioc/iochooks.cpp +++ b/ioc/iochooks.cpp @@ -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 refs; +} *refTrack; + +epicsThreadOnceId refSavedOnce = EPICS_THREAD_ONCE_INIT; + +void refSavedInit(void *) { + refTrack = new RefTrack(); +} + +void pvxrefsave() { + epicsThreadOnce(&refSavedOnce, &refSavedInit, nullptr); + epicsGuard G(refTrack->lock); + refTrack->refs = instanceSnapshot(); +} + +void pvxrefdiff() { + auto cur(instanceSnapshot()); + std::map diff; + + epicsThreadOnce(&refSavedOnce, &refSavedInit, nullptr); + { + epicsGuard 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();