From 8d3bf70e6447b82380e1270a1cfa0096d4761614 Mon Sep 17 00:00:00 2001 From: Eduard Bagdasaryan Date: Wed, 6 Sep 2023 02:32:22 +0000 Subject: [PATCH] Report all AsyncJob objects (mgr:jobs) (#1468) This new cache manager report is useful in triage and test automation. It complements mgr:objects, mgr:events, and mgr:filedescriptors reports. --- src/Makefile.am | 1 + src/base/AsyncJob.cc | 38 ++++++++++++++++++++++++++++++++++++++ src/base/AsyncJob.h | 5 +++++ src/main.cc | 2 ++ 4 files changed, 46 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index 0e98936913..26ba97859d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1691,6 +1691,7 @@ nodist_tests_testACLMaxUserIP_SOURCES = \ String.cc \ tests/stub_access_log.cc \ tests/stub_cache_cf.cc \ + tests/stub_cache_manager.cc \ tests/stub_cbdata.cc \ tests/stub_client_side.cc \ tests/stub_debug.cc \ diff --git a/src/base/AsyncJob.cc b/src/base/AsyncJob.cc index bcaf45b693..5c63bc6b26 100644 --- a/src/base/AsyncJob.cc +++ b/src/base/AsyncJob.cc @@ -12,14 +12,27 @@ #include "base/AsyncCall.h" #include "base/AsyncJob.h" #include "base/AsyncJobCalls.h" +#include "base/PackableStream.h" #include "base/TextException.h" #include "cbdata.h" +#include "mem/PoolingAllocator.h" #include "MemBuf.h" +#include "mgr/Registration.h" +#include "Store.h" #include +#include InstanceIdDefinitions(AsyncJob, "job"); +/// a set of all AsyncJob objects in existence +static auto & +AllJobs() +{ + static const auto jobs = new std::unordered_set, std::equal_to, PoolingAllocator >(); + return *jobs; +} + void AsyncJob::Start(const Pointer &job) { @@ -32,6 +45,7 @@ AsyncJob::AsyncJob(const char *aTypeName) : { debugs(93,5, "AsyncJob constructed, this=" << this << " type=" << typeName << " [" << id << ']'); + AllJobs().insert(this); } AsyncJob::~AsyncJob() @@ -39,6 +53,7 @@ AsyncJob::~AsyncJob() debugs(93,5, "AsyncJob destructed, this=" << this << " type=" << typeName << " [" << id << ']'); assert(!started_ || swanSang_); + AllJobs().erase(this); } void AsyncJob::start() @@ -179,3 +194,26 @@ const char *AsyncJob::status() const return buf.content(); } +void +AsyncJob::ReportAllJobs(StoreEntry *e) +{ + PackableStream os(*e); + // this loop uses YAML syntax, but AsyncJob::status() still needs to be adjusted to use YAML + const char *indent = " "; + for (const auto job: AllJobs()) { + os << indent << job->id << ":\n"; + os << indent << indent << "type: '" << job->typeName << "'\n"; + os << indent << indent << "status:" << job->status() << '\n'; + if (!job->started_) + os << indent << indent << "started: false\n"; + if (job->stopReason) + os << indent << indent << "stopped: '" << job->stopReason << "'\n"; + } +} + +void +AsyncJob::RegisterWithCacheManager() +{ + Mgr::RegisterAction("jobs", "All AsyncJob objects", &AsyncJob::ReportAllJobs, 0, 1); +} + diff --git a/src/base/AsyncJob.h b/src/base/AsyncJob.h index 32f83482f4..93faee9884 100644 --- a/src/base/AsyncJob.h +++ b/src/base/AsyncJob.h @@ -44,6 +44,8 @@ public: /// successfully (i.e. without throwing). static void Start(const Pointer &job); + static void RegisterWithCacheManager(); + protected: // XXX: temporary method to replace "delete this" in jobs-in-transition. // Will be replaced with calls to mustStop() when transition is complete. @@ -76,6 +78,9 @@ protected: // external destruction prohibited to ensure swanSong() is called ~AsyncJob() override; + /// writes a cache manager report about all jobs existing in this worker + static void ReportAllJobs(StoreEntry *); + const char *stopReason; ///< reason for forcing done() to be true const char *typeName; ///< kid (leaf) class name, for debugging AsyncCall::Pointer inCall; ///< the asynchronous call being handled, if any diff --git a/src/main.cc b/src/main.cc index 41cfb194d8..1a78e1c205 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1203,6 +1203,8 @@ mainInitialize(void) FwdState::initModule(); SBufStatsAction::RegisterWithCacheManager(); + AsyncJob::RegisterWithCacheManager(); + /* These use separate calls so that the comm loops can eventually * coexist. */ -- 2.47.2