From 8822ebee4947bcf883d74aa79a26e896449d0c36 Mon Sep 17 00:00:00 2001 From: Alex Rousskov Date: Thu, 28 Oct 2010 12:52:59 -0600 Subject: [PATCH] SMP Cache Manager, Phase2 implementation. Cache Manager actions are forwarded to Coordinator. Coordinator iterates over Kids, aggregating their stats if possible and/or allowing each kid to dump non-aggregatable output directly into response if needed. Non-aggregated output is wrapped in "by kidN { ... } by kidN" markup to ease auto-processing. Regressions and small output formatting changes are probably unavoidable because stats are aggregated and passed around as doubles instead of integers (no more overflows though!) and because many stats collection and formatting lines had to be touched. These are steps in the right direction though, IMO. Old code both computed and dumped stats to Store at the same time. To avoid computing code duplication, we now collect stats in primitive Stats objects and then either dump those to Store or send them to Coordinator for aggregation and, eventual Store dump. What stats to collect, when to aggregate, and when to dump is decided by action-specific Mgr::Action classes. The Cache Manager menu now consists of ActionProfile objects. ActionProfile maintains hard-coded information about specific actions. It uses ActionCreator member to create Action objects when a cache manager request is received. Added Mgr::ActionParams class to maintain action parameters, including HTTP request details necessary for Store entry creation (in another strand) and action-specific parameters (currently just credentials). In Phase3, this class can be extended to supply more parameters such as kid IDs to which the action should apply. Added Mgr::Command that combines hard-coded ActionProfile details with user-specified ActionParams. This simplifies many interfaces because we no longer need to supply a long list of parameters, covering various parts of action config. Moved Cache Manager registration to Mgr::RegisterAction() globals to reduce dependency on the CacheManager class, which is a singleton anyway, and which is unused by most of the registration callers. On the other hand, without this change, no legacy (function-based actions) code would have been changed! Enhanced TypedMsgHdr class to simplify storing and loading non-POD classes. The caller can now easily handle a non-POD class as a series of put/get calls, one for each POD member. This was necessary to send Mgr::ActionParams to Coordinator and back. Will probably be useful for sending other complex structures as well. Reconfigure, shutdown, and other "basic" actions have been moved to src/mgr/BasicActions.cc. Mgr::RegisterBasics() registers them. Most of the Cache Manager code is now in src/mgr/. Many more polishing touches. More polishing left for future projects: Move CacheManager to Mgr namespace and src/mgr/ directory. Use SBuf instead of String for ActionParams and TypedMsgHdr. Rename Ipc::TypedMsgHdr to Ipc::Msg, Ipc::SocketMsg, or similar because it maintains more than just msghdr struct. More stats aggregation, and Phase3 changes. --- configure.in | 1 + src/CacheManager.h | 131 +- .../DiskDaemon/DiskDaemonDiskIOModule.cc | 30 +- .../DiskDaemon/DiskDaemonDiskIOModule.h | 1 - src/DiskIO/DiskDaemon/DiskdAction.cc | 150 ++ src/DiskIO/DiskDaemon/DiskdAction.h | 72 + .../DiskThreads/DiskThreadsIOStrategy.cc | 10 +- src/HttpHeader.cc | 9 +- src/Makefile.am | 26 +- src/ProfStats.cc | 5 +- src/Store.h | 12 + src/StoreIOBuffer.h | 8 + src/String.cc | 3 +- src/acl/Asn.cc | 4 +- src/auth/basic/auth_basic.cc | 5 +- src/auth/digest/auth_digest.cc | 5 +- src/auth/negotiate/auth_negotiate.cc | 5 +- src/auth/ntlm/auth_ntlm.cc | 5 +- src/base/AsyncJobCalls.h | 6 +- src/cache_cf.cc | 5 +- src/cache_manager.cc | 382 ++--- src/carp.cc | 5 +- src/cbdata.cc | 7 +- src/client_db.cc | 5 +- src/comm_epoll.cc | 5 +- src/comm_kqueue.cc | 1 - src/comm_poll.cc | 5 +- src/comm_select.cc | 5 +- src/comm_select_win32.cc | 5 +- src/delay_pools.cc | 5 +- src/dns.cc | 5 +- src/dns_internal.cc | 5 +- src/event.cc | 5 +- src/external_acl.cc | 5 +- src/forward.cc | 4 +- src/fqdncache.cc | 5 +- src/fs/coss/StoreFScoss.cc | 4 +- src/icmp/net_db.cc | 5 +- src/ipc/Coordinator.cc | 55 +- src/ipc/Coordinator.h | 14 +- src/ipc/Makefile.am | 8 +- src/ipc/Messages.h | 20 +- src/ipc/Port.h | 3 +- src/ipc/SharedListen.cc | 12 +- src/ipc/Strand.cc | 25 + src/ipc/Strand.h | 5 +- src/ipc/{Messages.cc => StrandCoord.cc} | 7 +- src/ipc/StrandCoord.h | 31 + src/ipc/StrandCoords.h | 19 + src/ipc/TypedMsgHdr.cc | 96 +- src/ipc/TypedMsgHdr.h | 44 +- src/ipc/forward.h | 21 + src/ipcache.cc | 5 +- src/log/access_log.cc | 8 +- src/mem.cc | 5 +- src/mgr/Action.cc | 112 ++ src/mgr/Action.h | 94 ++ src/mgr/ActionCreator.h | 33 + src/mgr/ActionParams.cc | 41 + src/mgr/ActionParams.h | 43 + src/mgr/ActionProfile.h | 47 + src/mgr/ActionWriter.cc | 31 + src/mgr/ActionWriter.h | 37 + src/mgr/BasicActions.cc | 136 ++ src/mgr/BasicActions.h | 85 ++ src/mgr/Command.cc | 18 + src/mgr/Command.h | 31 + src/mgr/CountersAction.cc | 135 ++ src/mgr/CountersAction.h | 108 ++ src/mgr/Filler.cc | 43 + src/mgr/Filler.h | 38 + src/mgr/Forwarder.cc | 240 +++ src/mgr/Forwarder.h | 77 + src/mgr/FunAction.cc | 50 + src/mgr/FunAction.h | 60 + src/mgr/InfoAction.cc | 199 +++ src/mgr/InfoAction.h | 149 ++ src/mgr/Inquirer.cc | 250 ++++ src/mgr/Inquirer.h | 87 ++ src/mgr/IntervalAction.cc | 159 ++ src/mgr/IntervalAction.h | 130 ++ src/mgr/IoAction.cc | 86 ++ src/mgr/IoAction.h | 57 + src/mgr/Makefile.am | 47 + src/mgr/Registration.cc | 28 + src/mgr/Registration.h | 27 + src/mgr/Request.cc | 43 + src/mgr/Request.h | 39 + src/mgr/Response.cc | 68 + src/mgr/Response.h | 38 + src/mgr/ServiceTimesAction.cc | 100 ++ src/mgr/ServiceTimesAction.h | 69 + src/mgr/StoreIoAction.cc | 84 ++ src/mgr/StoreIoAction.h | 55 + src/mgr/StoreToCommWriter.cc | 187 +++ src/mgr/StoreToCommWriter.h | 73 + src/mgr/forward.h | 33 + src/neighbors.cc | 7 +- src/pconn.cc | 5 +- src/peer_sourcehash.cc | 5 +- src/peer_userhash.cc | 5 +- src/redirect.cc | 5 +- src/refresh.cc | 5 +- src/stat.cc | 1300 +++++++++++------ src/store.cc | 12 +- src/store_digest.cc | 5 +- src/store_io.cc | 26 +- src/store_log.cc | 5 +- src/structs.h | 7 +- src/tests/stub_Port.cc | 4 + src/tests/stub_TypedMsgHdr.cc | 44 + src/tests/stub_UdsOp.cc | 7 + src/tests/stub_cache_manager.cc | 38 +- src/tests/stub_comm.cc | 25 + src/tests/stub_store_swapout.cc | 10 +- src/tests/stub_tools.cc | 8 + src/tests/testCacheManager.cc | 18 +- src/ufsdump.cc | 12 +- 118 files changed, 5280 insertions(+), 1074 deletions(-) create mode 100644 src/DiskIO/DiskDaemon/DiskdAction.cc create mode 100644 src/DiskIO/DiskDaemon/DiskdAction.h rename src/ipc/{Messages.cc => StrandCoord.cc} (73%) create mode 100644 src/ipc/StrandCoord.h create mode 100644 src/ipc/StrandCoords.h create mode 100644 src/ipc/forward.h create mode 100644 src/mgr/Action.cc create mode 100644 src/mgr/Action.h create mode 100644 src/mgr/ActionCreator.h create mode 100644 src/mgr/ActionParams.cc create mode 100644 src/mgr/ActionParams.h create mode 100644 src/mgr/ActionProfile.h create mode 100644 src/mgr/ActionWriter.cc create mode 100644 src/mgr/ActionWriter.h create mode 100644 src/mgr/BasicActions.cc create mode 100644 src/mgr/BasicActions.h create mode 100644 src/mgr/Command.cc create mode 100644 src/mgr/Command.h create mode 100644 src/mgr/CountersAction.cc create mode 100644 src/mgr/CountersAction.h create mode 100644 src/mgr/Filler.cc create mode 100644 src/mgr/Filler.h create mode 100644 src/mgr/Forwarder.cc create mode 100644 src/mgr/Forwarder.h create mode 100644 src/mgr/FunAction.cc create mode 100644 src/mgr/FunAction.h create mode 100644 src/mgr/InfoAction.cc create mode 100644 src/mgr/InfoAction.h create mode 100644 src/mgr/Inquirer.cc create mode 100644 src/mgr/Inquirer.h create mode 100644 src/mgr/IntervalAction.cc create mode 100644 src/mgr/IntervalAction.h create mode 100644 src/mgr/IoAction.cc create mode 100644 src/mgr/IoAction.h create mode 100644 src/mgr/Makefile.am create mode 100644 src/mgr/Registration.cc create mode 100644 src/mgr/Registration.h create mode 100644 src/mgr/Request.cc create mode 100644 src/mgr/Request.h create mode 100644 src/mgr/Response.cc create mode 100644 src/mgr/Response.h create mode 100644 src/mgr/ServiceTimesAction.cc create mode 100644 src/mgr/ServiceTimesAction.h create mode 100644 src/mgr/StoreIoAction.cc create mode 100644 src/mgr/StoreIoAction.h create mode 100644 src/mgr/StoreToCommWriter.cc create mode 100644 src/mgr/StoreToCommWriter.h create mode 100644 src/mgr/forward.h create mode 100644 src/tests/stub_Port.cc create mode 100644 src/tests/stub_TypedMsgHdr.cc create mode 100644 src/tests/stub_UdsOp.cc diff --git a/configure.in b/configure.in index 62a7b02da7..3e64fe0b15 100644 --- a/configure.in +++ b/configure.in @@ -3324,6 +3324,7 @@ AC_CONFIG_FILES([\ src/ip/Makefile \ src/log/Makefile \ src/ipc/Makefile \ + src/mgr/Makefile \ contrib/Makefile \ snmplib/Makefile \ icons/Makefile \ diff --git a/src/CacheManager.h b/src/CacheManager.h index e365132581..77c0359a72 100644 --- a/src/CacheManager.h +++ b/src/CacheManager.h @@ -34,8 +34,11 @@ #ifndef SQUID_CACHEMANAGER_H #define SQUID_CACHEMANAGER_H -#include "squid.h" -#include "Array.h" +#include "mgr/Action.h" +#include "mgr/ActionProfile.h" +#include "mgr/Command.h" +#include "mgr/forward.h" +#include /** \defgroup CacheManagerAPI Cache Manager API @@ -45,41 +48,6 @@ \ingroup CacheManagerAPI */ -/** - \ingroup CacheManagerInternal - * The basic action handler. Its virtual method run(StoreEntry *) is invoked - * to perform the actual action. - */ -class CacheManagerAction -{ -public: - virtual void run(StoreEntry *sentry) = 0; - char *action; - char *desc; - struct { - unsigned int pw_req:1; - unsigned int atomic:1; - } flags; - virtual ~CacheManagerAction(); - CacheManagerAction(char const *anAction, char const *aDesc, unsigned int isPwReq, unsigned int isAtomic); - -}; - -/** - \ingroup CacheManagerInternal - * wrapper allowing c-style callbacks to be used. Arguments are supposed to - * managed by the caller. - * This object is generated by CacheManager::registerAction - */ -class CacheManagerActionLegacy : public CacheManagerAction -{ -public: - OBJH *handler; - virtual void run (StoreEntry *sentry); - CacheManagerActionLegacy(char const *anAction, char const *aDesc, unsigned int isPwReq, unsigned int isAtomic, OBJH *aHandler); -}; - - /** \ingroup CacheManagerAPI * a CacheManager - the menu system for interacting with squid. @@ -90,90 +58,39 @@ public: */ class CacheManager { - public: - /* the holy trinity - assignment, copy cons, destructor */ - /* unimplemented - prevents bugs from synthetic */ - CacheManager & operator = (CacheManager &); - /* unimplemented - prevents bugs from synthetic */ - CacheManager(CacheManager const &); - /* inline so that we dont need to link in cachemgr.cc at all in tests */ - virtual ~CacheManager() {} - - void registerAction(char const * action, char const * desc, OBJH * handler, int pw_req_flag, int atomic); - void registerAction(CacheManagerAction *anAction); - CacheManagerAction * findAction(char const * action); + typedef std::vector Menu; + + void registerProfile(char const * action, char const * desc, + OBJH * handler, + int pw_req_flag, int atomic); + void registerProfile(char const * action, char const * desc, + Mgr::ClassActionCreationHandler *handler, + int pw_req_flag, int atomic); + Mgr::ActionProfilePointer findAction(char const * action) const; + Mgr::Action::Pointer createNamedAction(const char *actionName); + Mgr::Action::Pointer createRequestedAction(const Mgr::ActionParams &); + const Menu& menu() const { return menu_; } void Start(int fd, HttpRequest * request, StoreEntry * entry); static CacheManager* GetInstance(); - const char *ActionProtection(const CacheManagerAction * at); + const char *ActionProtection(const Mgr::ActionProfilePointer &profile); protected: - // command classes. They are private to the cachemanager, they - // may require access to local data, plus we avoid polluting - // the namespace more than needed. - class ShutdownAction : public CacheManagerAction - { - public: - virtual void run (StoreEntry *sentry); - ShutdownAction(); - }; - class ReconfigureAction : public CacheManagerAction - { - public: - virtual void run (StoreEntry *sentry); - ReconfigureAction(); - }; - class RotateAction : public CacheManagerAction - { - public: - virtual void run (StoreEntry *sentry); - RotateAction(); - }; - class OfflineToggleAction : public CacheManagerAction - { - public: - virtual void run (StoreEntry *sentry); - OfflineToggleAction(); - }; - class MenuAction : public CacheManagerAction - { - private: - //needs to reference the cachemgr in order to get to ActionsList - CacheManager *cmgr; - public: - virtual void run (StoreEntry *sentry); - MenuAction(CacheManager *); - - }; + CacheManager() {} ///< use Instance() instead - /// \ingroup CacheManagerInternal - typedef struct { - StoreEntry *entry; - char *action; - char *user_name; - char *passwd; - } cachemgrStateData; - - - CacheManager(); - cachemgrStateData* ParseUrl(const char *url); - void ParseHeaders(cachemgrStateData * mgr, const HttpRequest * request); - int CheckPassword(cachemgrStateData * mgr); + Mgr::CommandPointer ParseUrl(const char *url); + void ParseHeaders(const HttpRequest * request, Mgr::ActionParams ¶ms); + int CheckPassword(const Mgr::Command &cmd); char *PasswdGet(cachemgr_passwd *, const char *); - // \ingroup CacheManagerInternal - typedef Vector CacheManagerActionList; - CacheManagerActionList ActionsList; + void registerProfile(const Mgr::ActionProfilePointer &profile); + Menu menu_; private: static CacheManager* instance; - - void StateFree(cachemgrStateData * mgr); - - }; #endif /* SQUID_CACHEMANAGER_H */ diff --git a/src/DiskIO/DiskDaemon/DiskDaemonDiskIOModule.cc b/src/DiskIO/DiskDaemon/DiskDaemonDiskIOModule.cc index d737742060..4e482996d6 100644 --- a/src/DiskIO/DiskDaemon/DiskDaemonDiskIOModule.cc +++ b/src/DiskIO/DiskDaemon/DiskDaemonDiskIOModule.cc @@ -33,8 +33,9 @@ #include "squid.h" #include "DiskDaemonDiskIOModule.h" -#include "CacheManager.h" #include "DiskdIOStrategy.h" +#include "DiskIO/DiskDaemon/DiskdAction.h" +#include "mgr/Registration.h" #include "Store.h" DiskDaemonDiskIOModule::DiskDaemonDiskIOModule() : initialised(false) @@ -76,7 +77,7 @@ DiskDaemonDiskIOModule::init() void DiskDaemonDiskIOModule::registerWithCacheManager(void) { - CacheManager::GetInstance()->registerAction("diskd", "DISKD Stats", Stats, 0, 1); + Mgr::RegisterAction("diskd", "DISKD Stats", &DiskdAction::Create, 0, 1); } void @@ -93,31 +94,6 @@ DiskDaemonDiskIOModule::createStrategy() DiskDaemonDiskIOModule DiskDaemonDiskIOModule::Instance; -void -DiskDaemonDiskIOModule::Stats(StoreEntry * sentry) -{ - storeAppendPrintf(sentry, "sent_count: %d\n", diskd_stats.sent_count); - storeAppendPrintf(sentry, "recv_count: %d\n", diskd_stats.recv_count); - storeAppendPrintf(sentry, "max_away: %d\n", diskd_stats.max_away); - storeAppendPrintf(sentry, "max_shmuse: %d\n", diskd_stats.max_shmuse); - storeAppendPrintf(sentry, "open_fail_queue_len: %d\n", diskd_stats.open_fail_queue_len); - storeAppendPrintf(sentry, "block_queue_len: %d\n", diskd_stats.block_queue_len); - diskd_stats.max_away = diskd_stats.max_shmuse = 0; - storeAppendPrintf(sentry, "\n OPS SUCCESS FAIL\n"); - storeAppendPrintf(sentry, "%7s %9d %9d %7d\n", - "open", diskd_stats.open.ops, diskd_stats.open.success, diskd_stats.open.fail); - storeAppendPrintf(sentry, "%7s %9d %9d %7d\n", - "create", diskd_stats.create.ops, diskd_stats.create.success, diskd_stats.create.fail); - storeAppendPrintf(sentry, "%7s %9d %9d %7d\n", - "close", diskd_stats.close.ops, diskd_stats.close.success, diskd_stats.close.fail); - storeAppendPrintf(sentry, "%7s %9d %9d %7d\n", - "unlink", diskd_stats.unlink.ops, diskd_stats.unlink.success, diskd_stats.unlink.fail); - storeAppendPrintf(sentry, "%7s %9d %9d %7d\n", - "read", diskd_stats.read.ops, diskd_stats.read.success, diskd_stats.read.fail); - storeAppendPrintf(sentry, "%7s %9d %9d %7d\n", - "write", diskd_stats.write.ops, diskd_stats.write.success, diskd_stats.write.fail); -} - char const * DiskDaemonDiskIOModule::type () const { diff --git a/src/DiskIO/DiskDaemon/DiskDaemonDiskIOModule.h b/src/DiskIO/DiskDaemon/DiskDaemonDiskIOModule.h index 8ad3cf4bd0..0445d2a718 100644 --- a/src/DiskIO/DiskDaemon/DiskDaemonDiskIOModule.h +++ b/src/DiskIO/DiskDaemon/DiskDaemonDiskIOModule.h @@ -48,7 +48,6 @@ public: virtual DiskIOStrategy* createStrategy(); private: - static void Stats(StoreEntry * sentry); static DiskDaemonDiskIOModule Instance; bool initialised; void registerWithCacheManager(void); diff --git a/src/DiskIO/DiskDaemon/DiskdAction.cc b/src/DiskIO/DiskDaemon/DiskdAction.cc new file mode 100644 index 0000000000..2e44af164c --- /dev/null +++ b/src/DiskIO/DiskDaemon/DiskdAction.cc @@ -0,0 +1,150 @@ +/* + * $Id$ + * + * DEBUG: section 79 Squid-side DISKD I/O functions. + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "Store.h" +#include "ipc/Messages.h" +#include "ipc/TypedMsgHdr.h" +#include "mgr/ActionWriter.h" +#include "DiskIO/DiskDaemon/DiskdAction.h" +#include "DiskIO/DiskDaemon/DiskdIOStrategy.h" + + +DiskdActionData::DiskdActionData() +{ + xmemset(this, 0, sizeof(*this)); +} + +DiskdActionData& +DiskdActionData::operator += (const DiskdActionData& stats) +{ + sent_count += stats.sent_count; + recv_count += stats.recv_count; + if (stats.max_away > max_away) + max_away = stats.max_away; + if (stats.max_shmuse > max_shmuse) + max_shmuse += stats.max_shmuse; + open_fail_queue_len += stats.open_fail_queue_len; + block_queue_len += stats.block_queue_len; + open_ops += stats.open_ops; + open_success += stats.open_success; + open_fail += stats.open_fail; + create_ops += stats.create_ops; + create_success += stats.create_success; + create_fail += stats.create_fail; + close_ops += stats.close_ops; + close_success += stats.close_success; + close_fail += stats.close_fail; + unlink_ops += stats.unlink_ops; + unlink_success += stats.unlink_success; + unlink_fail += stats.unlink_fail; + read_ops += stats.read_ops; + read_success += stats.read_success; + read_fail += stats.read_fail; + write_ops += stats.write_ops; + write_success += stats.write_success; + write_fail += stats.write_fail; + + return *this; +} + + +DiskdAction::Pointer +DiskdAction::Create(const Mgr::CommandPointer &aCmd) +{ + return new DiskdAction(aCmd); +} + +DiskdAction::DiskdAction(const Mgr::CommandPointer &aCmd): + Action(aCmd), data() +{ + debugs(79, 5, HERE); +} + +void +DiskdAction::add(const Action& action) +{ + debugs(79, 5, HERE); + data += dynamic_cast(action).data; +} + +void +DiskdAction::collect() +{ + data.sent_count = diskd_stats.sent_count; + data.recv_count = diskd_stats.recv_count; + data.max_away = diskd_stats.max_away; + data.max_shmuse = diskd_stats.max_shmuse; + data.open_fail_queue_len = diskd_stats.open_fail_queue_len; + data.block_queue_len = diskd_stats.block_queue_len; + diskd_stats.max_away = diskd_stats.max_shmuse = 0; + + data.open_ops = diskd_stats.open.ops; + data.open_success = diskd_stats.open.success; + data.open_fail = diskd_stats.open.fail; + + data.create_ops = diskd_stats.create.ops; + data.create_success = diskd_stats.create.success; + data.create_fail = diskd_stats.create.fail; + + data.close_ops = diskd_stats.close.ops; + data.close_success = diskd_stats.close.success; + data.close_fail = diskd_stats.close.fail; + + data.unlink_ops = diskd_stats.unlink.ops; + data.unlink_success = diskd_stats.unlink.success; + data.unlink_fail = diskd_stats.unlink.fail; + + data.read_ops = diskd_stats.read.ops; + data.read_success = diskd_stats.read.success; + data.read_fail = diskd_stats.read.fail; + + data.write_ops = diskd_stats.write.ops; + data.write_success = diskd_stats.write.success; + data.write_fail = diskd_stats.write.fail; +} + +void +DiskdAction::dump(StoreEntry* entry) +{ + debugs(79, 5, HERE); + Must(entry != NULL); + storeAppendPrintf(entry, "sent_count: %.0f\n", data.sent_count); + storeAppendPrintf(entry, "recv_count: %.0f\n", data.recv_count); + storeAppendPrintf(entry, "max_away: %.0f\n", data.max_away); + storeAppendPrintf(entry, "max_shmuse: %.0f\n", data.max_shmuse); + storeAppendPrintf(entry, "open_fail_queue_len: %.0f\n", data.open_fail_queue_len); + storeAppendPrintf(entry, "block_queue_len: %.0f\n", data.block_queue_len); + storeAppendPrintf(entry, "\n OPS SUCCESS FAIL\n"); + storeAppendPrintf(entry, "%7s %9.0f %9.0f %7.0f\n", + "open", data.open_ops, data.open_success, data.open_fail); + storeAppendPrintf(entry, "%7s %9.0f %9.0f %7.0f\n", + "create", data.create_ops, data.create_success, data.create_fail); + storeAppendPrintf(entry, "%7s %9.0f %9.0f %7.0f\n", + "close", data.close_ops, data.close_success, data.close_fail); + storeAppendPrintf(entry, "%7s %9.0f %9.0f %7.0f\n", + "unlink", data.unlink_ops, data.unlink_success, data.unlink_fail); + storeAppendPrintf(entry, "%7s %9.0f %9.0f %7.0f\n", + "read", data.read_ops, data.read_success, data.read_fail); + storeAppendPrintf(entry, "%7s %9.0f %9.0f %7.0f\n", + "write", data.write_ops, data.write_success, data.write_fail); +} + +void +DiskdAction::pack(Ipc::TypedMsgHdr& hdrMsg) const +{ + hdrMsg.setType(Ipc::mtCacheMgrResponse); + hdrMsg.putPod(data); +} + +void +DiskdAction::unpack(const Ipc::TypedMsgHdr& hdrMsg) +{ + hdrMsg.checkType(Ipc::mtCacheMgrResponse); + hdrMsg.getPod(data); +} diff --git a/src/DiskIO/DiskDaemon/DiskdAction.h b/src/DiskIO/DiskDaemon/DiskdAction.h new file mode 100644 index 0000000000..e950824f89 --- /dev/null +++ b/src/DiskIO/DiskDaemon/DiskdAction.h @@ -0,0 +1,72 @@ +/* + * $Id$ + * + * DEBUG: section 79 Squid-side DISKD I/O functions. + * + */ + +#ifndef SQUID_DISKD_ACTION_H +#define SQUID_DISKD_ACTION_H + +#include "ipc/forward.h" +#include "mgr/forward.h" +#include "mgr/Action.h" + + +/// store disk daemon stats +class DiskdActionData +{ +public: + DiskdActionData(); + DiskdActionData& operator += (const DiskdActionData& stats); + +public: + double sent_count; + double recv_count; + double max_away; + double max_shmuse; + double open_fail_queue_len; + double block_queue_len; + double open_ops; + double open_success; + double open_fail; + double create_ops; + double create_success; + double create_fail; + double close_ops; + double close_success; + double close_fail; + double unlink_ops; + double unlink_success; + double unlink_fail; + double read_ops; + double read_success; + double read_fail; + double write_ops; + double write_success; + double write_fail; +}; + +/// implement aggregated 'diskd' action +class DiskdAction: public Mgr::Action +{ +protected: + DiskdAction(const Mgr::CommandPointer &aCmd); + +public: + static Pointer Create(const Mgr::CommandPointer &aCmd); + /* Action API */ + virtual void add(const Mgr::Action& action); + virtual void pack(Ipc::TypedMsgHdr& hdrMsg) const; + virtual void unpack(const Ipc::TypedMsgHdr& hdrMsg); + +protected: + /* Action API */ + virtual void collect(); + virtual void dump(StoreEntry* entry); + +private: + DiskdActionData data; +}; + +#endif /* SQUID_DISKD_ACTION_H */ diff --git a/src/DiskIO/DiskThreads/DiskThreadsIOStrategy.cc b/src/DiskIO/DiskThreads/DiskThreadsIOStrategy.cc index d2cc0fd6ee..68461f5cb6 100644 --- a/src/DiskIO/DiskThreads/DiskThreadsIOStrategy.cc +++ b/src/DiskIO/DiskThreads/DiskThreadsIOStrategy.cc @@ -36,12 +36,13 @@ #include "squid.h" -#include "CacheManager.h" -#include "DiskThreadsIOStrategy.h" #include "DiskThreadsDiskFile.h" +#include "DiskThreadsIOStrategy.h" +#include "fde.h" +#include "mgr/Registration.h" /* for statfs */ #include "Store.h" -#include "fde.h" + void DiskThreadsIOStrategy::init(void) @@ -65,8 +66,7 @@ DiskThreadsIOStrategy::init(void) void DiskThreadsIOStrategy::registerWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("squidaio_counts", "Async IO Function Counters", + Mgr::RegisterAction("squidaio_counts", "Async IO Function Counters", aioStats, 0, 1); } diff --git a/src/HttpHeader.cc b/src/HttpHeader.cc index 4529de663c..e191b56e6b 100644 --- a/src/HttpHeader.cc +++ b/src/HttpHeader.cc @@ -34,12 +34,12 @@ */ #include "squid.h" -#include "CacheManager.h" -#include "Store.h" -#include "HttpHeader.h" #include "HttpHdrContRange.h" #include "HttpHdrSc.h" +#include "HttpHeader.h" #include "MemBuf.h" +#include "mgr/Registration.h" +#include "Store.h" /* * On naming conventions: @@ -283,8 +283,7 @@ static void httpHeaderStatDump(const HttpHeaderStat * hs, StoreEntry * e); static void httpHeaderRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("http_headers", + Mgr::RegisterAction("http_headers", "HTTP Header Statistics", httpHeaderStoreReport, 0, 1); } diff --git a/src/Makefile.am b/src/Makefile.am index aecf549632..eef3d09d50 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -39,7 +39,7 @@ LOADABLE_MODULES_SOURCES = \ LoadableModules.h \ LoadableModules.cc -SUBDIRS = base comm eui acl fs repl auth ip icmp ident log ipc +SUBDIRS = base comm eui acl fs repl auth ip icmp ident log ipc mgr if USE_ADAPTATION SUBDIRS += adaptation @@ -173,7 +173,8 @@ COMMON_LIBS = \ libsquid.la \ ip/libip.la \ fs/libfs.la \ - ipc/libipc.la + ipc/libipc.la \ + mgr/libmgr.la EXTRA_PROGRAMS = \ DiskIO/DiskDaemon/diskd \ @@ -727,7 +728,9 @@ libDiskDaemon_a_SOURCES = \ DiskIO/DiskDaemon/DiskdIOStrategy.h \ DiskIO/DiskDaemon/diomsg.h \ DiskIO/DiskDaemon/DiskDaemonDiskIOModule.cc \ - DiskIO/DiskDaemon/DiskDaemonDiskIOModule.h + DiskIO/DiskDaemon/DiskDaemonDiskIOModule.h \ + DiskIO/DiskDaemon/DiskdAction.cc \ + DiskIO/DiskDaemon/DiskdAction.h libDiskThreads_a_SOURCES = \ $(AIOPS_SOURCE) \ @@ -1295,7 +1298,10 @@ tests_testDiskIO_SOURCES = \ tests/testDiskIO.h \ tests/testMain.cc \ tests/stub_cache_manager.cc \ - tests/stub_HelperChildConfig.cc + tests/stub_HelperChildConfig.cc \ + tests/stub_Port.cc \ + tests/stub_TypedMsgHdr.cc \ + tests/stub_UdsOp.cc nodist_tests_testDiskIO_SOURCES= \ $(SWAP_TEST_GEN_SOURCES) \ SquidMath.cc \ @@ -1307,6 +1313,8 @@ tests_testDiskIO_LDADD = \ $(DISK_OS_LIBS) \ $(COMMON_LIBS) \ SquidConfig.o \ + CommCalls.o \ + DnsLookupDetails.o \ $(XTRA_LIBS) tests_testDiskIO_LDFLAGS = $(LIBADD_DL) @@ -2015,6 +2023,9 @@ tests_testStore_SOURCES= \ tests/stub_HelperChildConfig.cc \ tests/stub_HttpReply.cc \ tests/stub_cache_manager.cc \ + tests/stub_Port.cc \ + tests/stub_TypedMsgHdr.cc \ + tests/stub_UdsOp.cc \ $(STORE_TEST_SOURCES) \ tests/stub_fd.cc @@ -2030,6 +2041,8 @@ tests_testStore_LDADD= \ $(REGEXLIB) \ $(SQUID_CPPUNIT_LIBS) \ $(SSLLIB) \ + CommCalls.o \ + DnsLookupDetails.o \ $(COMPAT_LIB) \ $(XTRA_LIBS) tests_testStore_LDFLAGS = $(LIBADD_DL) @@ -2123,6 +2136,9 @@ tests_testUfs_SOURCES = \ tests/testUfs.h \ tests/stub_cache_manager.cc \ tests/stub_HelperChildConfig.cc \ + tests/stub_Port.cc \ + tests/stub_TypedMsgHdr.cc \ + tests/stub_UdsOp.cc \ $(SWAP_TEST_SOURCES) nodist_tests_testUfs_SOURCES = \ $(SWAP_TEST_GEN_SOURCES) \ @@ -2133,6 +2149,8 @@ tests_testUfs_LDADD = \ $(SWAP_TEST_LDADD) \ $(COMMON_LIBS) \ $(SSLLIB) \ + CommCalls.o \ + DnsLookupDetails.o \ $(XTRA_LIBS) tests_testUfs_LDFLAGS = $(LIBADD_DL) tests_testUfs_DEPENDENCIES = \ diff --git a/src/ProfStats.cc b/src/ProfStats.cc index 8ea82a64d5..fa671cf9a0 100644 --- a/src/ProfStats.cc +++ b/src/ProfStats.cc @@ -37,8 +37,8 @@ #if USE_XPROF_STATS -#include "CacheManager.h" #include "event.h" +#include "mgr/Registration.h" #include "SquidMath.h" #include "Store.h" @@ -270,8 +270,7 @@ xprof_chk_overhead(int samples) static void xprofRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("cpu_profile", "CPU Profiling Stats", xprof_summary, 0, 1); + Mgr::RegisterAction("cpu_profile", "CPU Profiling Stats", xprof_summary, 0, 1); } // FIXME: diff --git a/src/Store.h b/src/Store.h index f08fa514a8..af0f6b3e77 100644 --- a/src/Store.h +++ b/src/Store.h @@ -60,6 +60,18 @@ class MemObject; class Store; class StoreSearch; +typedef struct { + + struct { + int calls; + int select_fail; + int create_fail; + int success; + } create; +} StoreIoStats; + +extern StoreIoStats store_io_stats; + /** \ingroup StoreAPI */ diff --git a/src/StoreIOBuffer.h b/src/StoreIOBuffer.h index d526789835..db1cb4064d 100644 --- a/src/StoreIOBuffer.h +++ b/src/StoreIOBuffer.h @@ -76,4 +76,12 @@ public: char *data; }; +inline +std::ostream & +operator <<(std::ostream &os, const StoreIOBuffer &b) +{ + return os << "ioBuf(@" << b.offset << ", len=" << b.length << ", " << + (void*)b.data << (b.flags.error ? ", ERR" : "") << ')'; +} + #endif /* SQUID_STOREIOBUFFER_H */ diff --git a/src/String.cc b/src/String.cc index 939a859121..fa13917c6d 100644 --- a/src/String.cc +++ b/src/String.cc @@ -35,6 +35,7 @@ #include "squid.h" #include "base/TextException.h" +#include "mgr/Registration.h" #include "Store.h" int @@ -280,7 +281,7 @@ ptrcmp(C const &lhs, C const &rhs) StringRegistry::StringRegistry() { #if DEBUGSTRINGS - CacheManager::GetInstance()->registerAction("strings", + Mgr::RegisterAction("strings", "Strings in use in squid", Stat, 0, 1); #endif } diff --git a/src/acl/Asn.cc b/src/acl/Asn.cc index 8b6f8419d2..552a2e9670 100644 --- a/src/acl/Asn.cc +++ b/src/acl/Asn.cc @@ -34,7 +34,7 @@ */ #include "squid.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "radix.h" #include "HttpRequest.h" #include "StoreClient.h" @@ -189,7 +189,7 @@ ACLASN::prepareForUse() static void asnRegisterWithCacheManager(void) { - CacheManager::GetInstance()->registerAction("asndb", "AS Number Database", asnStats, 0, 1); + Mgr::RegisterAction("asndb", "AS Number Database", asnStats, 0, 1); } /* initialize the radix tree structure */ diff --git a/src/auth/basic/auth_basic.cc b/src/auth/basic/auth_basic.cc index 135c1c2157..29271940c7 100644 --- a/src/auth/basic/auth_basic.cc +++ b/src/auth/basic/auth_basic.cc @@ -43,7 +43,7 @@ #include "auth/basic/basicUserRequest.h" #include "auth/Gadgets.h" #include "auth/State.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "Store.h" #include "HttpReply.h" #include "rfc1738.h" @@ -544,8 +544,7 @@ AuthBasicConfig::init(AuthConfig * schemeCfg) void AuthBasicConfig::registerWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("basicauthenticator", + Mgr::RegisterAction("basicauthenticator", "Basic User Authenticator Stats", authenticateBasicStats, 0, 1); } diff --git a/src/auth/digest/auth_digest.cc b/src/auth/digest/auth_digest.cc index 6cafdfb8ef..8ff9b80258 100644 --- a/src/auth/digest/auth_digest.cc +++ b/src/auth/digest/auth_digest.cc @@ -42,7 +42,7 @@ #include "auth/digest/auth_digest.h" #include "auth/Gadgets.h" #include "event.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "Store.h" #include "HttpRequest.h" #include "HttpReply.h" @@ -673,8 +673,7 @@ AuthDigestConfig::init(AuthConfig * scheme) void AuthDigestConfig::registerWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("digestauthenticator", + Mgr::RegisterAction("digestauthenticator", "Digest User Authenticator Stats", authenticateDigestStats, 0, 1); } diff --git a/src/auth/negotiate/auth_negotiate.cc b/src/auth/negotiate/auth_negotiate.cc index b3fe433b5a..5fba97f60f 100644 --- a/src/auth/negotiate/auth_negotiate.cc +++ b/src/auth/negotiate/auth_negotiate.cc @@ -41,7 +41,7 @@ #include "auth/negotiate/auth_negotiate.h" #include "auth/Gadgets.h" #include "auth/State.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "Store.h" #include "client_side.h" #include "HttpReply.h" @@ -200,8 +200,7 @@ AuthNegotiateConfig::init(AuthConfig * scheme) void AuthNegotiateConfig::registerWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("negotiateauthenticator", + Mgr::RegisterAction("negotiateauthenticator", "Negotiate User Authenticator Stats", authenticateNegotiateStats, 0, 1); } diff --git a/src/auth/ntlm/auth_ntlm.cc b/src/auth/ntlm/auth_ntlm.cc index d534cd472f..d2c1802554 100644 --- a/src/auth/ntlm/auth_ntlm.cc +++ b/src/auth/ntlm/auth_ntlm.cc @@ -43,7 +43,7 @@ #include "auth/ntlm/ntlmScheme.h" #include "auth/ntlm/ntlmUserRequest.h" #include "auth/State.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "Store.h" #include "client_side.h" #include "HttpReply.h" @@ -186,8 +186,7 @@ AuthNTLMConfig::init(AuthConfig * scheme) void AuthNTLMConfig::registerWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("ntlmauthenticator", + Mgr::RegisterAction("ntlmauthenticator", "NTLM User Authenticator Stats", authenticateNTLMStats, 0, 1); } diff --git a/src/base/AsyncJobCalls.h b/src/base/AsyncJobCalls.h index 23434a1a1a..380eec5817 100644 --- a/src/base/AsyncJobCalls.h +++ b/src/base/AsyncJobCalls.h @@ -101,20 +101,20 @@ protected: virtual void doDial() { ((&(*this->job))->*method)(); } }; -template +template class UnaryMemFunT: public JobDialer { public: typedef void (Job::*Method)(Argument1); explicit UnaryMemFunT(const CbcPointer &aJob, Method aMethod, - const Argument1 &anArg1): JobDialer(aJob), + const Data &anArg1): JobDialer(aJob), method(aMethod), arg1(anArg1) {} virtual void print(std::ostream &os) const { os << '(' << arg1 << ')'; } public: Method method; - Argument1 arg1; + Data arg1; protected: virtual void doDial() { ((&(*this->job))->*method)(arg1); } diff --git a/src/cache_cf.cc b/src/cache_cf.cc index 03602a75d8..b7eb47addc 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -48,7 +48,6 @@ #endif #include "auth/Config.h" #include "auth/Scheme.h" -#include "CacheManager.h" #include "ConfigParser.h" #include "CpuAffinityMap.h" #include "eui/Config.h" @@ -62,6 +61,7 @@ #include "ip/tools.h" #include "log/Config.h" #include "MemBuf.h" +#include "mgr/Registration.h" #include "Parsing.h" #include "ProtoPort.h" #include "rfc1738.h" @@ -536,7 +536,6 @@ int parseConfigFile(const char *file_name) { int err_count = 0; - CacheManager *manager=CacheManager::GetInstance(); debugs(5, 4, HERE); @@ -564,7 +563,7 @@ parseConfigFile(const char *file_name) } if (opt_send_signal == -1) { - manager->registerAction("config", + Mgr::RegisterAction("config", "Current Squid Configuration", dump_config, 1, 1); diff --git a/src/cache_manager.cc b/src/cache_manager.cc index b8b72376ea..b95f30b7a8 100644 --- a/src/cache_manager.cc +++ b/src/cache_manager.cc @@ -33,34 +33,61 @@ * */ +#include "config.h" +#include "base/TextException.h" #include "CacheManager.h" +#include "Debug.h" #include "errorpage.h" +#include "fde.h" #include "HttpReply.h" #include "HttpRequest.h" -#include "Store.h" -#include "fde.h" +#include "mgr/ActionCreator.h" +#include "mgr/Action.h" +#include "mgr/ActionProfile.h" +#include "mgr/BasicActions.h" +#include "mgr/Command.h" +#include "mgr/Forwarder.h" +#include "mgr/FunAction.h" +#include "protos.h" /* rotate_logs() */ #include "SquidTime.h" +#include "Store.h" #include "wordlist.h" -#include "Debug.h" +#include -// for rotate_logs() -#include "protos.h" /// \ingroup CacheManagerInternal #define MGR_PASSWD_SZ 128 +/// creates Action using supplied Action::Create method and command +class ClassActionCreator: public Mgr::ActionCreator +{ +public: + typedef Mgr::Action::Pointer Handler(const Mgr::Command::Pointer &cmd); -/** - \ingroup CacheManagerInternals - * Constructor. Its purpose is to register internal commands - */ -CacheManager::CacheManager() +public: + ClassActionCreator(Handler *aHandler): handler(aHandler) {} + + virtual Mgr::Action::Pointer create(const Mgr::Command::Pointer &cmd) const + { + return handler(cmd); + } + +private: + Handler *handler; +}; + + +/// Registers new profiles, ignoring attempts to register a duplicate +void +CacheManager::registerProfile(const Mgr::ActionProfile::Pointer &profile) { - registerAction(new OfflineToggleAction); - registerAction(new ShutdownAction); - registerAction(new ReconfigureAction); - registerAction(new RotateAction); - registerAction(new MenuAction(this)); + Must(profile != NULL); + if (find(menu_.begin(), menu_.end(), profile) == menu_.end()) { + menu_.push_back(profile); + debugs(16, 3, HERE << "registered profile: " << *profile); + } else { + debugs(16, 2, HERE << "skipped duplicate profile: " << *profile); + } } /** @@ -70,56 +97,69 @@ CacheManager::CacheManager() * Implemented via CacheManagerActionLegacy. */ void -CacheManager::registerAction(char const * action, char const * desc, OBJH * handler, int pw_req_flag, int atomic) +CacheManager::registerProfile(char const * action, char const * desc, OBJH * handler, int pw_req_flag, int atomic) { - debugs(16, 3, "CacheManager::registerAction: registering legacy " << action); - registerAction(new CacheManagerActionLegacy(action,desc,pw_req_flag,atomic,handler)); + debugs(16, 3, HERE << "registering legacy " << action); + const Mgr::ActionProfile::Pointer profile = new Mgr::ActionProfile(action, + desc, pw_req_flag, atomic, new Mgr::FunActionCreator(handler)); + registerProfile(profile); } -/** - \ingroup CacheManagerAPI - * Registers a C++-style action, via a poiner to a subclass of - * a CacheManagerAction object, whose run() method will be invoked when - * CacheManager identifies that the user has requested the action. - */ void -CacheManager::registerAction(CacheManagerAction *anAction) +CacheManager::registerProfile(char const * action, char const * desc, + ClassActionCreator::Handler *handler, + int pw_req_flag, int atomic) { - char *action = anAction->action; - if (findAction(action) != NULL) { - debugs(16, 2, "CacheManager::registerAction: Duplicate '" << action << "'. Skipping."); - return; - } - - assert (strstr (" ", action) == NULL); - - ActionsList += anAction; - - debugs(16, 3, "CacheManager::registerAction: registered " << action); + const Mgr::ActionProfile::Pointer profile = new Mgr::ActionProfile(action, + desc, pw_req_flag, atomic, new ClassActionCreator(handler)); + registerProfile(profile); } - /** \ingroup CacheManagerInternal * Locates an action in the actions registry ActionsList. \retval NULL if Action not found \retval CacheManagerAction* if the action was found */ -CacheManagerAction * -CacheManager::findAction(char const * action) +Mgr::ActionProfile::Pointer +CacheManager::findAction(char const * action) const { - CacheManagerActionList::iterator a; + Must(action != NULL); + Menu::const_iterator a; debugs(16, 5, "CacheManager::findAction: looking for action " << action); - for ( a = ActionsList.begin(); a != ActionsList.end(); a++) { - if (0 == strcmp((*a)->action, action)) { + for (a = menu_.begin(); a != menu_.end(); ++a) { + if (0 == strcmp((*a)->name, action)) { debugs(16, 6, " found"); return *a; } } debugs(16, 6, "Action not found."); - return NULL; + return Mgr::ActionProfilePointer(); +} + +Mgr::Action::Pointer +CacheManager::createNamedAction(const char *actionName) +{ + Must(actionName); + + Mgr::Command::Pointer cmd = new Mgr::Command; + cmd->profile = findAction(actionName); + cmd->params.actionName = actionName; + + Must(cmd->profile != NULL); + return cmd->profile->creator->create(cmd); +} + +Mgr::Action::Pointer +CacheManager::createRequestedAction(const Mgr::ActionParams ¶ms) +{ + Mgr::Command::Pointer cmd = new Mgr::Command; + cmd->params = params; + cmd->profile = findAction(params.actionName.termedBuf()); + Must(cmd->profile != NULL); + return cmd->profile->creator->create(cmd); } /** @@ -130,51 +170,47 @@ CacheManager::findAction(char const * action) \retval CacheManager::cachemgrStateData state object for the following handling \retval NULL if the action can't be found or can't be accessed by the user */ -CacheManager::cachemgrStateData * +Mgr::Command::Pointer CacheManager::ParseUrl(const char *url) { int t; LOCAL_ARRAY(char, host, MAX_URL); LOCAL_ARRAY(char, request, MAX_URL); LOCAL_ARRAY(char, password, MAX_URL); - CacheManagerAction *a; - cachemgrStateData *mgr = NULL; - const char *prot; t = sscanf(url, "cache_object://%[^/]/%[^@]@%s", host, request, password); - if (t < 2) { + if (t < 2) xstrncpy(request, "menu", MAX_URL); + #ifdef _SQUID_OS2_ + if (t == 2 && request[0] == '\0') { /* * emx's sscanf insists of returning 2 because it sets request * to null */ - } else if (request[0] == '\0') { xstrncpy(request, "menu", MAX_URL); + } #endif - } else if ((a = findAction(request)) == NULL) { + Mgr::ActionProfile::Pointer profile = findAction(request); + if (!profile) { debugs(16, DBG_IMPORTANT, "CacheManager::ParseUrl: action '" << request << "' not found"); return NULL; - } else { - prot = ActionProtection(a); - - if (!strcmp(prot, "disabled") || !strcmp(prot, "hidden")) { - debugs(16, DBG_IMPORTANT, "CacheManager::ParseUrl: action '" << request << "' is " << prot); - return NULL; - } } - /* set absent entries to NULL so we can test if they are present later */ - mgr = (cachemgrStateData *)xcalloc(1, sizeof(cachemgrStateData)); - - mgr->user_name = NULL; - - mgr->passwd = t == 3 ? xstrdup(password) : NULL; - - mgr->action = xstrdup(request); + const char *prot = ActionProtection(profile); + if (!strcmp(prot, "disabled") || !strcmp(prot, "hidden")) { + debugs(16, DBG_IMPORTANT, "CacheManager::ParseUrl: action '" << request << "' is " << prot); + return NULL; + } - return mgr; + Mgr::Command::Pointer cmd = new Mgr::Command; + cmd->profile = profile; + cmd->params.httpUri = url; + cmd->params.userName = String(); + cmd->params.password = t == 3 ? String(password) : String(); + cmd->params.actionName = request; + return cmd; } /// \ingroup CacheManagerInternal @@ -184,11 +220,15 @@ CacheManager::ParseUrl(const char *url) * the details into the cachemgrStateData argument */ void -CacheManager::ParseHeaders(cachemgrStateData * mgr, const HttpRequest * request) +CacheManager::ParseHeaders(const HttpRequest * request, Mgr::ActionParams ¶ms) { const char *basic_cookie; /* base 64 _decoded_ user:passwd pair */ const char *passwd_del; - assert(mgr && request); + assert(request); + + params.httpMethod = request->method.id(); + params.httpFlags = request->flags; + basic_cookie = request->header.getAuth(HDR_AUTHORIZATION, "Basic"); if (!basic_cookie) @@ -200,18 +240,12 @@ CacheManager::ParseHeaders(cachemgrStateData * mgr, const HttpRequest * request) } /* found user:password pair, reset old values */ - safe_free(mgr->user_name); - - safe_free(mgr->passwd); - - mgr->user_name = xstrdup(basic_cookie); - - mgr->user_name[passwd_del - basic_cookie] = '\0'; - - mgr->passwd = xstrdup(passwd_del + 1); + params.userName.limitInit(basic_cookie, passwd_del - basic_cookie); + params.password = passwd_del + 1; /* warning: this prints decoded password which maybe not what you want to do @?@ @?@ */ - debugs(16, 9, "CacheManager::ParseHeaders: got user: '" << mgr->user_name << "' passwd: '" << mgr->passwd << "'"); + debugs(16, 9, "CacheManager::ParseHeaders: got user: '" << + params.userName << "' passwd: '" << params.password << "'"); } /** @@ -222,16 +256,16 @@ CacheManager::ParseHeaders(cachemgrStateData * mgr, const HttpRequest * request) \retval !0 if mgr->password does not match configured password */ int -CacheManager::CheckPassword(cachemgrStateData * mgr) +CacheManager::CheckPassword(const Mgr::Command &cmd) { - char *pwd = PasswdGet(Config.passwd_list, mgr->action); - CacheManagerAction *a = findAction(mgr->action); + assert(cmd.profile != NULL); + const char *action = cmd.profile->name; + char *pwd = PasswdGet(Config.passwd_list, action); - debugs(16, 4, "CacheManager::CheckPassword for action " << mgr->action); - assert(a != NULL); + debugs(16, 4, "CacheManager::CheckPassword for action " << action); if (pwd == NULL) - return a->flags.pw_req; + return cmd.profile->isPwReq; if (strcmp(pwd, "disable") == 0) return 1; @@ -239,21 +273,10 @@ CacheManager::CheckPassword(cachemgrStateData * mgr) if (strcmp(pwd, "none") == 0) return 0; - if (!mgr->passwd) + if (!cmd.params.password.size()) return 1; - return strcmp(pwd, mgr->passwd); -} - -/// \ingroup CacheManagerInternal -void -CacheManager::StateFree(cachemgrStateData * mgr) -{ - safe_free(mgr->action); - safe_free(mgr->user_name); - safe_free(mgr->passwd); - mgr->entry->unlock(); - xfree(mgr); + return cmd.params.password != pwd; } /** @@ -265,12 +288,11 @@ CacheManager::StateFree(cachemgrStateData * mgr) void CacheManager::Start(int fd, HttpRequest * request, StoreEntry * entry) { - cachemgrStateData *mgr = NULL; ErrorState *err = NULL; - CacheManagerAction *a; debugs(16, 3, "CacheManager::Start: '" << entry->url() << "'" ); - if ((mgr = ParseUrl(entry->url())) == NULL) { + Mgr::Command::Pointer cmd = ParseUrl(entry->url()); + if (!cmd) { err = errorCon(ERR_INVALID_URL, HTTP_NOT_FOUND, request); err->url = xstrdup(entry->url()); errorAppendEntry(entry, err); @@ -278,45 +300,48 @@ CacheManager::Start(int fd, HttpRequest * request, StoreEntry * entry) return; } - mgr->entry = entry; + const char *actionName = cmd->profile->name; - entry->lock(); entry->expires = squid_curtime; - debugs(16, 5, "CacheManager: " << fd_table[fd].ipaddr << " requesting '" << mgr->action << "'"); + debugs(16, 5, "CacheManager: " << fd_table[fd].ipaddr << " requesting '" << actionName << "'"); /* get additional info from request headers */ - ParseHeaders(mgr, request); + ParseHeaders(request, cmd->params); + + const char *userName = cmd->params.userName.size() ? + cmd->params.userName.termedBuf() : "unknown"; /* Check password */ - if (CheckPassword(mgr) != 0) { + if (CheckPassword(*cmd) != 0) { /* build error message */ ErrorState *errState; HttpReply *rep; errState = errorCon(ERR_CACHE_MGR_ACCESS_DENIED, HTTP_UNAUTHORIZED, request); /* warn if user specified incorrect password */ - if (mgr->passwd) + if (cmd->params.password.size()) { debugs(16, DBG_IMPORTANT, "CacheManager: " << - (mgr->user_name ? mgr->user_name : "") << "@" << + userName << "@" << fd_table[fd].ipaddr << ": incorrect password for '" << - mgr->action << "'" ); - else + actionName << "'" ); + } else { debugs(16, DBG_IMPORTANT, "CacheManager: " << - (mgr->user_name ? mgr->user_name : "") << "@" << + userName << "@" << fd_table[fd].ipaddr << ": password needed for '" << - mgr->action << "'" ); + actionName << "'" ); + } rep = errState->BuildHttpReply(); errorStateFree(errState); /* - * add Authenticate header, use 'action' as a realm because - * password depends on action + * add Authenticate header using action name as a realm because + * password depends on the action */ - rep->header.putAuth("Basic", mgr->action); + rep->header.putAuth("Basic", actionName); /* store the reply */ entry->replaceHttpReply(rep); @@ -325,84 +350,23 @@ CacheManager::Start(int fd, HttpRequest * request, StoreEntry * entry) entry->complete(); - StateFree(mgr); - return; } debugs(16, 2, "CacheManager: " << - (mgr->user_name ? mgr->user_name : "") << "@" << + userName << "@" << fd_table[fd].ipaddr << " requesting '" << - mgr->action << "'" ); - /* retrieve object requested */ - a = findAction(mgr->action); - assert(a != NULL); + actionName << "'" ); - entry->buffer(); - - { - HttpReply *rep = new HttpReply; - rep->setHeaders(HTTP_OK, NULL, "text/plain", -1, squid_curtime, squid_curtime); - entry->replaceHttpReply(rep); + if (UsingSmp() && IamWorkerProcess()) { + AsyncJob::Start(new Mgr::Forwarder(fd, cmd->params, request, entry)); + return; } - a->run(entry); - - entry->flush(); - - if (a->flags.atomic) - entry->complete(); - - StateFree(mgr); -} - -/// \ingroup CacheManagerInternal -void CacheManager::ShutdownAction::run(StoreEntry *sentry) -{ - debugs(16, DBG_CRITICAL, "Shutdown by Cache Manager command."); - shut_down(0); -} -/// \ingroup CacheManagerInternal -CacheManager::ShutdownAction::ShutdownAction() : CacheManagerAction("shutdown","Shut Down the Squid Process", 1, 1) { } - -/// \ingroup CacheManagerInternal -void -CacheManager::ReconfigureAction::run(StoreEntry * sentry) -{ - debugs(16, DBG_IMPORTANT, "Reconfigure by Cache Manager command."); - storeAppendPrintf(sentry, "Reconfiguring Squid Process ...."); - reconfigure(SIGHUP); -} -/// \ingroup CacheManagerInternal -CacheManager::ReconfigureAction::ReconfigureAction() : CacheManagerAction("reconfigure","Reconfigure Squid", 1, 1) { } - -/// \ingroup CacheManagerInternal -void -CacheManager::RotateAction::run(StoreEntry * sentry) -{ - debugs(16, DBG_IMPORTANT, "Rotate Logs by Cache Manager command."); - storeAppendPrintf(sentry, "Rotating Squid Process Logs ...."); -#ifdef _SQUID_LINUX_THREADS_ - rotate_logs(SIGQUIT); -#else - rotate_logs(SIGUSR1); -#endif -} -/// \ingroup CacheManagerInternal -CacheManager::RotateAction::RotateAction() : CacheManagerAction("rotate","Rotate Squid Logs", 1, 1) { } - -/// \ingroup CacheManagerInternal -void -CacheManager::OfflineToggleAction::run(StoreEntry * sentry) -{ - Config.onoff.offline = !Config.onoff.offline; - debugs(16, DBG_IMPORTANT, "offline_mode now " << (Config.onoff.offline ? "ON" : "OFF") << " by Cache Manager request."); - - storeAppendPrintf(sentry, "offline_mode is now %s\n", - Config.onoff.offline ? "ON" : "OFF"); + Mgr::Action::Pointer action = cmd->profile->creator->create(cmd); + Must(action != NULL); + action->run(entry, true); } -/// \ingroup CacheManagerInternal -CacheManager::OfflineToggleAction::OfflineToggleAction() : CacheManagerAction ("offline_toggle", "Toggle offline_mode setting", 1, 1) { } /* \ingroup CacheManagerInternal @@ -410,14 +374,13 @@ CacheManager::OfflineToggleAction::OfflineToggleAction() : CacheManagerAction (" * Also doubles as a check for the protection level. */ const char * -CacheManager::ActionProtection(const CacheManagerAction * at) +CacheManager::ActionProtection(const Mgr::ActionProfile::Pointer &profile) { - char *pwd; - assert(at); - pwd = PasswdGet(Config.passwd_list, at->action); + assert(profile != NULL); + const char *pwd = PasswdGet(Config.passwd_list, profile->name); if (!pwd) - return at->flags.pw_req ? "hidden" : "public"; + return profile->isPwReq ? "hidden" : "public"; if (!strcmp(pwd, "disable")) return "disabled"; @@ -428,22 +391,6 @@ CacheManager::ActionProtection(const CacheManagerAction * at) return "protected"; } -/// \ingroup CacheManagerInternal -void -CacheManager::MenuAction::run(StoreEntry * sentry) -{ - CacheManagerActionList::iterator a; - - debugs(16, 4, "CacheManager::MenuCommand invoked"); - for (a = cmgr->ActionsList.begin(); a != cmgr->ActionsList.end(); ++a) { - debugs(16, 5, " showing action " << (*a)->action); - storeAppendPrintf(sentry, " %-22s\t%-32s\t%s\n", - (*a)->action, (*a)->desc, cmgr->ActionProtection(*a)); - } -} -/// \ingroup CacheManagerInternal -CacheManager::MenuAction::MenuAction(CacheManager *aMgr) : CacheManagerAction ("menu", "Cache Manager Menu", 0, 1), cmgr(aMgr) { } - /* \ingroup CacheManagerInternal * gets from the global Config the password the user would need to supply @@ -481,32 +428,7 @@ CacheManager::GetInstance() if (instance == 0) { debugs(16, 6, "CacheManager::GetInstance: starting cachemanager up"); instance = new CacheManager; + Mgr::RegisterBasics(); } return instance; } - - -/// \ingroup CacheManagerInternal -void CacheManagerActionLegacy::run(StoreEntry *sentry) -{ - handler(sentry); -} -/// \ingroup CacheManagerInternal -CacheManagerAction::CacheManagerAction(char const *anAction, char const *aDesc, unsigned int isPwReq, unsigned int isAtomic) -{ - flags.pw_req = isPwReq; - flags.atomic = isAtomic; - action = xstrdup (anAction); - desc = xstrdup (aDesc); -} -/// \ingroup CacheManagerInternal -CacheManagerAction::~CacheManagerAction() -{ - xfree(action); - xfree(desc); -} - -/// \ingroup CacheManagerInternal -CacheManagerActionLegacy::CacheManagerActionLegacy(char const *anAction, char const *aDesc, unsigned int isPwReq, unsigned int isAtomic, OBJH *aHandler) : CacheManagerAction(anAction, aDesc, isPwReq, isAtomic), handler(aHandler) -{ -} diff --git a/src/carp.cc b/src/carp.cc index 65bec9db05..f5f6f3624a 100644 --- a/src/carp.cc +++ b/src/carp.cc @@ -35,7 +35,7 @@ */ #include "squid.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "Store.h" #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) @@ -55,8 +55,7 @@ peerSortWeight(const void *a, const void *b) static void carpRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("carp", "CARP information", carpCachemgr, 0, 1); + Mgr::RegisterAction("carp", "CARP information", carpCachemgr, 0, 1); } void diff --git a/src/cbdata.cc b/src/cbdata.cc index 300b277331..cd4ce8f998 100644 --- a/src/cbdata.cc +++ b/src/cbdata.cc @@ -49,7 +49,7 @@ */ #include "cbdata.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "Store.h" #if CBDATA_DEBUG #include "Stack.h" @@ -271,13 +271,12 @@ cbdataInternalAddType(cbdata_type type, const char *name, int size, FREE * free_ void cbdataRegisterWithCacheManager(void) { - CacheManager *manager=CacheManager::GetInstance(); - manager->registerAction("cbdata", + Mgr::RegisterAction("cbdata", "Callback Data Registry Contents", cbdataDump, 0, 1); #if CBDATA_DEBUG - manager->registerAction("cbdatahistory", + Mgr::RegisterAction("cbdatahistory", "Detailed call history for all current cbdata contents", cbdataDumpHistory, 0, 1); #endif diff --git a/src/client_db.cc b/src/client_db.cc index aec780da22..89668cd21e 100644 --- a/src/client_db.cc +++ b/src/client_db.cc @@ -34,9 +34,9 @@ #include "squid.h" #include "event.h" -#include "CacheManager.h" #include "ClientInfo.h" #include "ip/Address.h" +#include "mgr/Registration.h" #include "SquidMath.h" #include "SquidTime.h" #include "Store.h" @@ -104,8 +104,7 @@ clientdbAdd(const Ip::Address &addr) static void clientdbRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("client_list", "Cache Client List", clientdbDump, 0, 1); + Mgr::RegisterAction("client_list", "Cache Client List", clientdbDump, 0, 1); } void diff --git a/src/comm_epoll.cc b/src/comm_epoll.cc index 56ee42f82f..e5337203f9 100644 --- a/src/comm_epoll.cc +++ b/src/comm_epoll.cc @@ -53,7 +53,7 @@ #include "squid.h" #include "comm_epoll.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "Store.h" #include "fde.h" #include "SquidTime.h" @@ -221,8 +221,7 @@ static void commIncomingStats(StoreEntry * sentry); static void commEPollRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("comm_epoll_incoming", + Mgr::RegisterAction("comm_epoll_incoming", "comm_incoming() stats", commIncomingStats, 0, 1); } diff --git a/src/comm_kqueue.cc b/src/comm_kqueue.cc index e420c4f0b9..70b94ddeba 100644 --- a/src/comm_kqueue.cc +++ b/src/comm_kqueue.cc @@ -58,7 +58,6 @@ #if USE_KQUEUE #include "comm_kqueue.h" -#include "CacheManager.h" #include "Store.h" #include "fde.h" #include "SquidTime.h" diff --git a/src/comm_poll.cc b/src/comm_poll.cc index 53325aeb19..bb48aa7cbd 100644 --- a/src/comm_poll.cc +++ b/src/comm_poll.cc @@ -33,7 +33,7 @@ #include "squid.h" #include "comm_poll.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "SquidTime.h" #include "Store.h" #include "fde.h" @@ -625,8 +625,7 @@ comm_poll_dns_incoming(void) static void commPollRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("comm_poll_incoming", + Mgr::RegisterAction("comm_poll_incoming", "comm_incoming() stats", commIncomingStats, 0, 1); } diff --git a/src/comm_select.cc b/src/comm_select.cc index 4b74b7e8dc..29f80fa9f8 100644 --- a/src/comm_select.cc +++ b/src/comm_select.cc @@ -33,7 +33,7 @@ #include "squid.h" #include "comm_select.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "SquidTime.h" #if USE_SELECT @@ -663,8 +663,7 @@ comm_select_dns_incoming(void) static void commSelectRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("comm_select_incoming", + Mgr::RegisterAction("comm_select_incoming", "comm_incoming() stats", commIncomingStats, 0, 1); } diff --git a/src/comm_select_win32.cc b/src/comm_select_win32.cc index d436f9421f..cbafca9ab3 100644 --- a/src/comm_select_win32.cc +++ b/src/comm_select_win32.cc @@ -33,7 +33,7 @@ #include "squid.h" #include "comm_select.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "SquidTime.h" #if USE_SELECT_WIN32 @@ -685,8 +685,7 @@ comm_select_dns_incoming(void) static void commSelectRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("comm_select_incoming", + Mgr::RegisterAction("comm_select_incoming", "comm_incoming() stats", commIncomingStats, 0, 1); } diff --git a/src/delay_pools.cc b/src/delay_pools.cc index 73913fa0ec..82fda98d0e 100644 --- a/src/delay_pools.cc +++ b/src/delay_pools.cc @@ -43,7 +43,7 @@ #if DELAY_POOLS #include "squid.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "DelaySpec.h" #include "DelayPools.h" #include "event.h" @@ -543,8 +543,7 @@ unsigned short DelayPools::pools_ (0); void DelayPools::RegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("delay", "Delay Pool Levels", Stats, 0, 1); + Mgr::RegisterAction("delay", "Delay Pool Levels", Stats, 0, 1); } void diff --git a/src/dns.cc b/src/dns.cc index db050e6352..1935cee427 100644 --- a/src/dns.cc +++ b/src/dns.cc @@ -37,7 +37,7 @@ #include "Store.h" #include "wordlist.h" #include "SquidTime.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "helper.h" /* MS VisualStudio Projects are monolitich, so we need the following @@ -58,8 +58,7 @@ dnsStats(StoreEntry * sentry) static void dnsRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("dns", "Dnsserver Statistics", dnsStats, 0, 1); + Mgr::RegisterAction("dns", "Dnsserver Statistics", dnsStats, 0, 1); } void diff --git a/src/dns_internal.cc b/src/dns_internal.cc index 7fd5235515..91cf352376 100644 --- a/src/dns_internal.cc +++ b/src/dns_internal.cc @@ -36,13 +36,13 @@ #include "config.h" #include "squid.h" #include "event.h" -#include "CacheManager.h" #include "SquidTime.h" #include "Store.h" #include "comm.h" #include "fde.h" #include "ip/tools.h" #include "MemBuf.h" +#include "mgr/Registration.h" #include "util.h" #include "wordlist.h" @@ -1432,8 +1432,7 @@ idnsRcodeCount(int rcode, int attempt) static void idnsRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("idns", "Internal DNS Statistics", idnsStats, 0, 1); + Mgr::RegisterAction("idns", "Internal DNS Statistics", idnsStats, 0, 1); } void diff --git a/src/event.cc b/src/event.cc index dd0057884d..66bd0432b2 100644 --- a/src/event.cc +++ b/src/event.cc @@ -34,8 +34,8 @@ #include "config.h" #include "compat/drand48.h" -#include "CacheManager.h" #include "event.h" +#include "mgr/Registration.h" #include "Store.h" #include "SquidTime.h" @@ -154,8 +154,7 @@ eventDelete(EVH * func, void *arg) void eventInit(void) { - CacheManager::GetInstance()-> - registerAction("events", "Event Queue", eventDump, 0, 1); + Mgr::RegisterAction("events", "Event Queue", eventDump, 0, 1); } static void diff --git a/src/external_acl.cc b/src/external_acl.cc index 5808ec5ca7..9a6182251a 100644 --- a/src/external_acl.cc +++ b/src/external_acl.cc @@ -41,7 +41,7 @@ */ #include "squid.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "ExternalACL.h" #include "ExternalACLEntry.h" #include "auth/UserRequest.h" @@ -1420,8 +1420,7 @@ externalAclStats(StoreEntry * sentry) static void externalAclRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("external_acl", + Mgr::RegisterAction("external_acl", "External ACL stats", externalAclStats, 0, 1); } diff --git a/src/forward.cc b/src/forward.cc index 6e0a46be09..3be7191838 100644 --- a/src/forward.cc +++ b/src/forward.cc @@ -50,6 +50,7 @@ #include "icmp/net_db.h" #include "ip/Intercept.h" #include "ip/tools.h" +#include "mgr/Registration.h" static PSC fwdStartCompleteWrapper; static PF fwdServerClosedWrapper; @@ -1280,8 +1281,7 @@ FwdState::initModule() void FwdState::RegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("forward", "Request Forwarding Statistics", fwdStats, 0, 1); + Mgr::RegisterAction("forward", "Request Forwarding Statistics", fwdStats, 0, 1); } void diff --git a/src/fqdncache.cc b/src/fqdncache.cc index f00da301d6..b7344d8cbc 100644 --- a/src/fqdncache.cc +++ b/src/fqdncache.cc @@ -35,7 +35,7 @@ #include "squid.h" #include "cbdata.h" #include "event.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "SquidTime.h" #include "Store.h" #include "wordlist.h" @@ -586,8 +586,7 @@ fqdncache_nbgethostbyaddr(const Ip::Address &addr, FQDNH * handler, void *handle static void fqdncacheRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("fqdncache", "FQDN Cache Stats and Contents", + Mgr::RegisterAction("fqdncache", "FQDN Cache Stats and Contents", fqdnStats, 0, 1); } diff --git a/src/fs/coss/StoreFScoss.cc b/src/fs/coss/StoreFScoss.cc index fed69cb180..5367bc67d3 100644 --- a/src/fs/coss/StoreFScoss.cc +++ b/src/fs/coss/StoreFScoss.cc @@ -35,7 +35,7 @@ #include "StoreFileSystem.h" #include "StoreFScoss.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "Store.h" #include "CossSwapDir.h" #include "store_coss.h" @@ -86,7 +86,7 @@ StoreFScoss::setup() void StoreFScoss::registerWithCacheManager() { - CacheManager::GetInstance()->registerAction("coss", "COSS Stats", Stats, 0, 1); + Mgr::RegisterAction("coss", "COSS Stats", Stats, 0, 1); } void diff --git a/src/icmp/net_db.cc b/src/icmp/net_db.cc index 836a4eee3a..016800d807 100644 --- a/src/icmp/net_db.cc +++ b/src/icmp/net_db.cc @@ -43,7 +43,7 @@ #include "log/File.h" #include "cbdata.h" #include "event.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "Store.h" #include "SwapDir.h" #include "HttpRequest.h" @@ -882,8 +882,7 @@ netdbExchangeDone(void *data) static void netdbRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("netdb", "Network Measurement Database", netdbDump, 0, 1); + Mgr::RegisterAction("netdb", "Network Measurement Database", netdbDump, 0, 1); } #endif /* USE_ICMP */ diff --git a/src/ipc/Coordinator.cc b/src/ipc/Coordinator.cc index 0f2eac9975..02c66fd1b5 100644 --- a/src/ipc/Coordinator.cc +++ b/src/ipc/Coordinator.cc @@ -7,10 +7,16 @@ #include "config.h" +#include "base/TextException.h" +#include "CacheManager.h" #include "comm.h" #include "ipc/Coordinator.h" #include "ipc/FdNotes.h" #include "ipc/SharedListen.h" +#include "mgr/Inquirer.h" +#include "mgr/Request.h" +#include "mgr/Response.h" +#include "mgr/StoreToCommWriter.h" CBDATA_NAMESPACED_CLASS_INIT(Ipc, Coordinator); @@ -29,8 +35,8 @@ void Ipc::Coordinator::start() Ipc::StrandCoord* Ipc::Coordinator::findStrand(int kidId) { - typedef Strands::iterator SI; - for (SI iter = strands.begin(); iter != strands.end(); ++iter) { + typedef StrandCoords::iterator SI; + for (SI iter = strands_.begin(); iter != strands_.end(); ++iter) { if (iter->kidId == kidId) return &(*iter); } @@ -42,7 +48,7 @@ void Ipc::Coordinator::registerStrand(const StrandCoord& strand) if (StrandCoord* found = findStrand(strand.kidId)) *found = strand; else - strands.push_back(strand); + strands_.push_back(strand); } void Ipc::Coordinator::receive(const TypedMsgHdr& message) @@ -58,6 +64,16 @@ void Ipc::Coordinator::receive(const TypedMsgHdr& message) handleSharedListenRequest(SharedListenRequest(message)); break; + case mtCacheMgrRequest: + debugs(54, 6, HERE << "Cache manager request"); + handleCacheMgrRequest(Mgr::Request(message)); + break; + + case mtCacheMgrResponse: + debugs(54, 6, HERE << "Cache manager response"); + handleCacheMgrResponse(Mgr::Response(message)); + break; + default: debugs(54, 1, HERE << "Unhandled message type: " << message.type()); break; @@ -94,6 +110,29 @@ Ipc::Coordinator::handleSharedListenRequest(const SharedListenRequest& request) SendMessage(MakeAddr(strandAddrPfx, request.requestorId), message); } +void +Ipc::Coordinator::handleCacheMgrRequest(const Mgr::Request& request) +{ + debugs(54, 4, HERE); + + // Let the strand know that we are now responsible for handling the request + Mgr::Response response(request.requestId); + TypedMsgHdr message; + response.pack(message); + SendMessage(MakeAddr(strandAddrPfx, request.requestorId), message); + + Mgr::Action::Pointer action = + CacheManager::GetInstance()->createRequestedAction(request.params); + AsyncJob::Start(new Mgr::Inquirer(action, + Mgr::ImportHttpFdIntoComm(request.fd), request, strands_)); +} + +void +Ipc::Coordinator::handleCacheMgrResponse(const Mgr::Response& response) +{ + Mgr::Inquirer::HandleRemoteAck(response); +} + int Ipc::Coordinator::openListenSocket(const SharedListenRequest& request, int &errNo) @@ -120,8 +159,8 @@ Ipc::Coordinator::openListenSocket(const SharedListenRequest& request, void Ipc::Coordinator::broadcastSignal(int sig) const { - typedef Strands::const_iterator SCI; - for (SCI iter = strands.begin(); iter != strands.end(); ++iter) { + typedef StrandCoords::const_iterator SCI; + for (SCI iter = strands_.begin(); iter != strands_.end(); ++iter) { debugs(54, 5, HERE << "signal " << sig << " to kid" << iter->kidId << ", PID=" << iter->pid); kill(iter->pid, sig); @@ -137,3 +176,9 @@ Ipc::Coordinator* Ipc::Coordinator::Instance() // Strands do not re-register, even process death would be pointless. return TheInstance; } + +const Ipc::StrandCoords& +Ipc::Coordinator::strands() const +{ + return strands_; +} diff --git a/src/ipc/Coordinator.h b/src/ipc/Coordinator.h index f508205eb0..11856b1d3e 100644 --- a/src/ipc/Coordinator.h +++ b/src/ipc/Coordinator.h @@ -10,10 +10,13 @@ #include "Array.h" -#include -#include "ipc/Port.h" #include "ipc/Messages.h" +#include "ipc/Port.h" #include "ipc/SharedListen.h" +#include "ipc/StrandCoords.h" +#include "mgr/forward.h" + +#include namespace Ipc { @@ -29,6 +32,8 @@ public: void broadcastSignal(int sig) const; ///< send sig to registered strands + const StrandCoords &strands() const; ///< currently registered strands + protected: virtual void start(); // Port (AsyncJob) API virtual void receive(const TypedMsgHdr& message); // Port API @@ -39,13 +44,14 @@ protected: /// returns cached socket or calls openListenSocket() void handleSharedListenRequest(const SharedListenRequest& request); + void handleCacheMgrRequest(const Mgr::Request& request); + void handleCacheMgrResponse(const Mgr::Response& response); /// calls comm_open_listener() int openListenSocket(const SharedListenRequest& request, int &errNo); private: - typedef Vector Strands; ///< unsorted strands - Strands strands; ///< registered processes and threads + StrandCoords strands_; ///< registered processes and threads typedef std::map Listeners; ///< params:fd map Listeners listeners; ///< cached comm_open_listener() results diff --git a/src/ipc/Makefile.am b/src/ipc/Makefile.am index c81662c482..e2d13504d9 100644 --- a/src/ipc/Makefile.am +++ b/src/ipc/Makefile.am @@ -10,10 +10,12 @@ libipc_la_SOURCES = \ Kid.h \ Kids.cc \ Kids.h \ - Messages.cc \ Messages.h \ StartListening.cc \ StartListening.h \ + StrandCoord.cc \ + StrandCoord.h \ + StrandCoords.h \ SharedListen.cc \ SharedListen.h \ TypedMsgHdr.cc \ @@ -25,6 +27,8 @@ libipc_la_SOURCES = \ Port.cc \ Port.h \ Strand.cc \ - Strand.h + Strand.h \ + \ + forward.h DEFS += -DDEFAULT_PREFIX=\"$(prefix)\" diff --git a/src/ipc/Messages.h b/src/ipc/Messages.h index 7d0e370ac0..57ae03632d 100644 --- a/src/ipc/Messages.h +++ b/src/ipc/Messages.h @@ -8,6 +8,7 @@ #ifndef SQUID_IPC_MESSAGES_H #define SQUID_IPC_MESSAGES_H +#include "ipc/forward.h" #include /** Declarations used by varios IPC messages */ @@ -15,27 +16,12 @@ namespace Ipc { -class TypedMsgHdr; - /// message class identifier typedef enum { mtNone = 0, mtRegistration, - mtSharedListenRequest, mtSharedListenResponse + mtSharedListenRequest, mtSharedListenResponse, + mtCacheMgrRequest, mtCacheMgrResponse } MessageType; -/// Strand location details -class StrandCoord -{ -public: - StrandCoord(); ///< unknown location - StrandCoord(int akidId, pid_t aPid); ///< from registrant - explicit StrandCoord(const TypedMsgHdr &hdrMsg); ///< from recvmsg() - void pack(TypedMsgHdr &hdrMsg) const; ///< prepare for sendmsg() - -public: - int kidId; ///< internal Squid process number - pid_t pid; ///< OS process or thread identifier -}; - } // namespace Ipc; diff --git a/src/ipc/Port.h b/src/ipc/Port.h index ffe791ad3c..a2d69b52b5 100644 --- a/src/ipc/Port.h +++ b/src/ipc/Port.h @@ -22,11 +22,10 @@ class Port: public UdsOp { public: Port(const String &aListenAddr); - -protected: /// calculates IPC message address for strand #id at path static String MakeAddr(const char *path, int id); +protected: virtual void start() = 0; // UdsOp (AsyncJob) API; has body virtual bool doneAll() const; // UdsOp (AsyncJob) API diff --git a/src/ipc/SharedListen.cc b/src/ipc/SharedListen.cc index 77e2e1c224..6b76b96acf 100644 --- a/src/ipc/SharedListen.cc +++ b/src/ipc/SharedListen.cc @@ -71,12 +71,14 @@ Ipc::SharedListenRequest::SharedListenRequest(): requestorId(-1), mapId(-1) Ipc::SharedListenRequest::SharedListenRequest(const TypedMsgHdr &hdrMsg) { - hdrMsg.getData(mtSharedListenRequest, this, sizeof(*this)); + hdrMsg.checkType(mtSharedListenRequest); + hdrMsg.getPod(*this); } void Ipc::SharedListenRequest::pack(TypedMsgHdr &hdrMsg) const { - hdrMsg.putData(mtSharedListenRequest, this, sizeof(*this)); + hdrMsg.setType(mtSharedListenRequest); + hdrMsg.putPod(*this); } @@ -88,13 +90,15 @@ Ipc::SharedListenResponse::SharedListenResponse(int aFd, int anErrNo, int aMapId Ipc::SharedListenResponse::SharedListenResponse(const TypedMsgHdr &hdrMsg): fd(-1), errNo(0), mapId(-1) { - hdrMsg.getData(mtSharedListenResponse, this, sizeof(*this)); + hdrMsg.checkType(mtSharedListenResponse); + hdrMsg.getPod(*this); fd = hdrMsg.getFd(); } void Ipc::SharedListenResponse::pack(TypedMsgHdr &hdrMsg) const { - hdrMsg.putData(mtSharedListenResponse, this, sizeof(*this)); + hdrMsg.setType(mtSharedListenResponse); + hdrMsg.putPod(*this); hdrMsg.putFd(fd); } diff --git a/src/ipc/Strand.cc b/src/ipc/Strand.cc index 384e44794f..a1e9f59c5d 100644 --- a/src/ipc/Strand.cc +++ b/src/ipc/Strand.cc @@ -8,9 +8,14 @@ #include "config.h" #include "base/TextException.h" #include "ipc/Strand.h" +#include "ipc/StrandCoord.h" #include "ipc/Messages.h" #include "ipc/SharedListen.h" #include "ipc/Kids.h" +#include "mgr/Request.h" +#include "mgr/Response.h" +#include "mgr/Forwarder.h" +#include "CacheManager.h" CBDATA_NAMESPACED_CLASS_INIT(Ipc, Strand); @@ -51,6 +56,14 @@ void Ipc::Strand::receive(const TypedMsgHdr &message) SharedListenJoined(SharedListenResponse(message)); break; + case mtCacheMgrRequest: + handleCacheMgrRequest(Mgr::Request(message)); + break; + + case mtCacheMgrResponse: + handleCacheMgrResponse(Mgr::Response(message)); + break; + default: debugs(54, 1, HERE << "Unhandled message type: " << message.type()); break; @@ -70,6 +83,18 @@ void Ipc::Strand::handleRegistrationResponse(const StrandCoord &strand) } } +void Ipc::Strand::handleCacheMgrRequest(const Mgr::Request& request) +{ + Mgr::Action::Pointer action = + CacheManager::GetInstance()->createRequestedAction(request.params); + action->respond(request); +} + +void Ipc::Strand::handleCacheMgrResponse(const Mgr::Response& response) +{ + Mgr::Forwarder::HandleRemoteAck(response.requestId); +} + void Ipc::Strand::timedout() { debugs(54, 6, HERE << isRegistered); diff --git a/src/ipc/Strand.h b/src/ipc/Strand.h index 899c348783..d01cf2b7f2 100644 --- a/src/ipc/Strand.h +++ b/src/ipc/Strand.h @@ -9,13 +9,13 @@ #define SQUID_IPC_STRAND_H #include "ipc/Port.h" +#include "mgr/forward.h" namespace Ipc { class StrandCoord; -class Descriptor; /// Receives coordination messages on behalf of its process or thread class Strand: public Port @@ -32,7 +32,8 @@ protected: private: void registerSelf(); /// let Coordinator know this strand exists void handleRegistrationResponse(const StrandCoord &strand); - void putDescriptor(const Descriptor &message); + void handleCacheMgrRequest(const Mgr::Request& request); + void handleCacheMgrResponse(const Mgr::Response& response); private: bool isRegistered; ///< whether Coordinator ACKed registration (unused) diff --git a/src/ipc/Messages.cc b/src/ipc/StrandCoord.cc similarity index 73% rename from src/ipc/Messages.cc rename to src/ipc/StrandCoord.cc index 5526db7fed..3fdf45a9fc 100644 --- a/src/ipc/Messages.cc +++ b/src/ipc/StrandCoord.cc @@ -8,6 +8,7 @@ #include "config.h" #include "ipc/Messages.h" +#include "ipc/StrandCoord.h" #include "ipc/TypedMsgHdr.h" @@ -21,10 +22,12 @@ Ipc::StrandCoord::StrandCoord(int aKidId, pid_t aPid): kidId(aKidId), pid(aPid) Ipc::StrandCoord::StrandCoord(const TypedMsgHdr &hdrMsg): kidId(-1), pid(0) { - hdrMsg.getData(mtRegistration, this, sizeof(*this)); + hdrMsg.checkType(mtRegistration); + hdrMsg.getPod(*this); } void Ipc::StrandCoord::pack(TypedMsgHdr &hdrMsg) const { - hdrMsg.putData(mtRegistration, this, sizeof(*this)); + hdrMsg.setType(mtRegistration); + hdrMsg.putPod(*this); } diff --git a/src/ipc/StrandCoord.h b/src/ipc/StrandCoord.h new file mode 100644 index 0000000000..02f2056de8 --- /dev/null +++ b/src/ipc/StrandCoord.h @@ -0,0 +1,31 @@ +/* + * $Id$ + * + */ + +#ifndef SQUID_IPC_STRAND_COORD_H +#define SQUID_IPC_STRAND_COORD_H + +#include "ipc/forward.h" +#include + +namespace Ipc +{ + +/// Strand location details +class StrandCoord +{ +public: + StrandCoord(); ///< unknown location + StrandCoord(int akidId, pid_t aPid); ///< from registrant + explicit StrandCoord(const TypedMsgHdr &hdrMsg); ///< from recvmsg() + void pack(TypedMsgHdr &hdrMsg) const; ///< prepare for sendmsg() + +public: + int kidId; ///< internal Squid process number + pid_t pid; ///< OS process or thread identifier +}; + +} // namespace Ipc; + +#endif /* SQUID_IPC_STRAND_COORD_H */ diff --git a/src/ipc/StrandCoords.h b/src/ipc/StrandCoords.h new file mode 100644 index 0000000000..2d83f71a43 --- /dev/null +++ b/src/ipc/StrandCoords.h @@ -0,0 +1,19 @@ +/* + * $Id$ + * + */ + +#ifndef SQUID_IPC_STRAND_COORDS_H +#define SQUID_IPC_STRAND_COORDS_H + +#include "ipc/StrandCoord.h" +#include + +namespace Ipc { + +/// a collection of strand coordinates; the order, if any, is owner-dependent +typedef std::vector StrandCoords; + +}; // namespace Ipc + +#endif /* SQUID_IPC_STRAND_COORDS_H */ diff --git a/src/ipc/TypedMsgHdr.cc b/src/ipc/TypedMsgHdr.cc index 622e142dbb..b38954c3e9 100644 --- a/src/ipc/TypedMsgHdr.cc +++ b/src/ipc/TypedMsgHdr.cc @@ -57,6 +57,7 @@ void Ipc::TypedMsgHdr::sync() } else { Must(!msg_controllen && !msg_control); } + offset = 0; } @@ -78,21 +79,98 @@ Ipc::TypedMsgHdr::address(const struct sockaddr_un& addr) } void -Ipc::TypedMsgHdr::getData(int destType, void *raw, size_t size) const +Ipc::TypedMsgHdr::checkType(int destType) const { Must(type() == destType); - Must(size == data.size); - xmemcpy(raw, data.raw, size); } void -Ipc::TypedMsgHdr::putData(int aType, const void *raw, size_t size) +Ipc::TypedMsgHdr::setType(int aType) { - Must(size <= sizeof(data.raw)); - allocData(); - data.type_ = aType; - data.size = size; - xmemcpy(data.raw, raw, size); + if (data.type_) { + Must(data.type_ == aType); + } else { + allocData(); + data.type_ = aType; + } +} + +int +Ipc::TypedMsgHdr::getInt() const +{ + int n = 0; + getPod(n); + return n; +} + +void +Ipc::TypedMsgHdr::putInt(const int n) +{ + putPod(n); +} + +void +Ipc::TypedMsgHdr::getString(String &s) const +{ + const int length = getInt(); + Must(length >= 0); + // String uses memcpy uncoditionally; TODO: SBuf eliminates this check + if (!length) { + s.clean(); + return; + } + + Must(length <= maxSize); + // TODO: use SBuf.reserve() instead of a temporary buffer + char buf[length]; + getRaw(&buf, length); + s.limitInit(buf, length); +} + +void +Ipc::TypedMsgHdr::putString(const String &s) +{ + Must(s.psize() <= maxSize); + putInt(s.psize()); + putRaw(s.rawBuf(), s.psize()); +} + +void +Ipc::TypedMsgHdr::getFixed(void *raw, size_t size) const +{ + // no need to load size because it is constant + getRaw(raw, size); +} + +void +Ipc::TypedMsgHdr::putFixed(const void *raw, size_t size) +{ + // no need to store size because it is constant + putRaw(raw, size); +} + +/// low-level loading of exactly size bytes of raw data +void +Ipc::TypedMsgHdr::getRaw(void *raw, size_t size) const +{ + Must(size >= 0); + if (size > 0) { + Must(size <= data.size - offset); + xmemcpy(raw, data.raw + offset, size); + offset += size; + } +} + +/// low-level storage of exactly size bytes of raw data +void +Ipc::TypedMsgHdr::putRaw(const void *raw, size_t size) +{ + Must(size >= 0); + if (size > 0) { + Must(size <= sizeof(data.raw) - data.size); + xmemcpy(data.raw + data.size, raw, size); + data.size += size; + } } void diff --git a/src/ipc/TypedMsgHdr.h b/src/ipc/TypedMsgHdr.h index 79b60ab5e8..17468a8caf 100644 --- a/src/ipc/TypedMsgHdr.h +++ b/src/ipc/TypedMsgHdr.h @@ -20,26 +20,51 @@ #include #endif +class String; + namespace Ipc { /// struct msghdr with a known type, fixed-size I/O and control buffers class TypedMsgHdr: public msghdr { +public: + enum {maxSize = 4096}; + public: TypedMsgHdr(); TypedMsgHdr(const TypedMsgHdr &tmh); TypedMsgHdr &operator =(const TypedMsgHdr &tmh); - // type-safe access to message details + void address(const struct sockaddr_un &addr); ///< sets [dest.] address + + /* message type manipulation; these must be called before put/get*() */ + void setType(int aType); ///< sets message type; use MessageType enum + void checkType(int aType) const; ///< throws if stored type is not aType int type() const; ///< returns stored type or zero if none - void address(const struct sockaddr_un& addr); ///< sets [dest.] address - void getData(int ofType, void *raw, size_t size) const; ///< checks type - void putData(int aType, const void *raw, size_t size); ///< stores type + + /* access for Plain Old Data (POD)-based message parts */ + template + void getPod(Pod &pod) const { getFixed(&pod, sizeof(pod)); } ///< load POD + template + void putPod(const Pod &pod) { putFixed(&pod, sizeof(pod)); } ///< store POD + + /* access to message parts for selected commonly-used part types */ + void getString(String &s) const; ///< load variable-length string + void putString(const String &s); ///< store variable-length string + int getInt() const; ///< load an integer + void putInt(int n); ///< store an integer + void getFixed(void *raw, size_t size) const; ///< always load size bytes + void putFixed(const void *raw, size_t size); ///< always store size bytes + + /// returns true if there is data to extract; handy for optional parts + bool hasMoreData() const { return offset < data.size; } + + /* access to a "file" descriptor that can be passed between processes */ void putFd(int aFd); ///< stores descriptor int getFd() const; ///< returns descriptor - /// raw, type-independent access for I/O + /* raw, type-independent access for I/O */ void prepForReading(); ///< reset and provide all buffers char *raw() { return reinterpret_cast(this); } const char *raw() const { return reinterpret_cast(this); } @@ -51,6 +76,10 @@ private: void allocName(); void allocControl(); + /* raw, type-independent manipulation used by type-specific methods */ + void getRaw(void *raw, size_t size) const; + void putRaw(const void *raw, size_t size); + private: struct sockaddr_un name; ///< same as .msg_name @@ -59,12 +88,15 @@ private: struct DataBuffer { int type_; ///< Message kind, uses MessageType values size_t size; ///< actual raw data size (for sanity checks) - char raw[250]; ///< buffer with type-specific data + char raw[maxSize]; ///< buffer with type-specific data } data; ///< same as .msg_iov[0].iov_base struct CtrlBuffer { char raw[CMSG_SPACE(sizeof(int))]; ///< control buffer space for one fd } ctrl; ///< same as .msg_control + + /// data offset for the next get/put*() to start with + mutable unsigned int offset; }; } // namespace Ipc diff --git a/src/ipc/forward.h b/src/ipc/forward.h new file mode 100644 index 0000000000..d5173075db --- /dev/null +++ b/src/ipc/forward.h @@ -0,0 +1,21 @@ +/* + * $Id$ + * + * DEBUG: section 54 Interprocess Communication + * + */ + +#ifndef SQUID_IPC_FORWARD_H +#define SQUID_IPC_FORWARD_H + +#include "config.h" + +namespace Ipc +{ + +class TypedMsgHdr; +class StrandCoord; + +} // namespace Ipc + +#endif /* SQUID_IPC_FORWARD_H */ diff --git a/src/ipcache.cc b/src/ipcache.cc index de31059a96..44ff00f498 100644 --- a/src/ipcache.cc +++ b/src/ipcache.cc @@ -31,11 +31,11 @@ */ #include "squid.h" -#include "CacheManager.h" #include "cbdata.h" #include "event.h" #include "ip/Address.h" #include "ip/tools.h" +#include "mgr/Registration.h" #include "SquidTime.h" #include "Store.h" #include "wordlist.h" @@ -700,8 +700,7 @@ ipcache_nbgethostbyname(const char *name, IPH * handler, void *handlerData) static void ipcacheRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("ipcache", + Mgr::RegisterAction("ipcache", "IP Cache Stats and Contents", stat_ipcache_get, 0, 1); } diff --git a/src/log/access_log.cc b/src/log/access_log.cc index 8eb8982e44..b1e8efa9c8 100644 --- a/src/log/access_log.cc +++ b/src/log/access_log.cc @@ -42,7 +42,7 @@ #include "errorpage.h" #include "err_detail_type.h" #include "acl/Checklist.h" -#include "CacheManager.h" +#include "errorpage.h" #if USE_SQUID_EUI #include "eui/Eui48.h" #include "eui/Eui64.h" @@ -52,6 +52,7 @@ #include "HttpRequest.h" #include "log/File.h" #include "MemBuf.h" +#include "mgr/Registration.h" #include "rfc1738.h" #include "SquidTime.h" @@ -2290,9 +2291,8 @@ fvdbInit(void) static void fvdbRegisterWithCacheManager(void) { - CacheManager *manager=CacheManager::GetInstance(); - manager->registerAction("via_headers", "Via Request Headers", fvdbDumpVia, 0, 1); - manager->registerAction("forw_headers", "X-Forwarded-For Request Headers", + Mgr::RegisterAction("via_headers", "Via Request Headers", fvdbDumpVia, 0, 1); + Mgr::RegisterAction("forw_headers", "X-Forwarded-For Request Headers", fvdbDumpForw, 0, 1); } diff --git a/src/mem.cc b/src/mem.cc index 00ab2d2551..9970cd39b5 100644 --- a/src/mem.cc +++ b/src/mem.cc @@ -34,7 +34,7 @@ #include "squid.h" #include "event.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "ClientInfo.h" #include "Mem.h" #include "memMeter.h" @@ -455,8 +455,7 @@ Mem::Report() void Mem::RegisterWithCacheManager(void) { - CacheManager::GetInstance()->registerAction("mem", "Memory Utilization", - Mem::Stats, 0, 1); + Mgr::RegisterAction("mem", "Memory Utilization", Mem::Stats, 0, 1); } mem_type &operator++ (mem_type &aMem) diff --git a/src/mgr/Action.cc b/src/mgr/Action.cc new file mode 100644 index 0000000000..5adce85264 --- /dev/null +++ b/src/mgr/Action.cc @@ -0,0 +1,112 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "HttpReply.h" +#include "ipc/Port.h" +#include "mgr/ActionCreator.h" +#include "mgr/Action.h" +#include "mgr/ActionParams.h" +#include "mgr/ActionProfile.h" +#include "mgr/Command.h" +#include "mgr/Request.h" +#include "mgr/Response.h" +#include "SquidTime.h" +#include "Store.h" + + +Mgr::Action::Action(const Command::Pointer &aCmd): cmd(aCmd) +{ + Must(cmd != NULL); + Must(cmd->profile != NULL); +} + +Mgr::Action::~Action() +{ +} + +const Mgr::Command & +Mgr::Action::command() const +{ + Must(cmd != NULL); + return *cmd; +} + +bool +Mgr::Action::atomic() const +{ + return command().profile->isAtomic; +} + +const char* +Mgr::Action::name() const +{ + return command().profile->name; +} + +StoreEntry* +Mgr::Action::createStoreEntry() const +{ + const ActionParams ¶ms = command().params; + const char *uri = params.httpUri.termedBuf(); + return storeCreateEntry(uri, uri, params.httpFlags, params.httpMethod); +} + +void +Mgr::Action::add(const Action& action) +{ +} + +void +Mgr::Action::respond(const Request& request) +{ + debugs(16, 5, HERE); + + // Assume most kid classes are fully aggregatable (i.e., they do not dump + // local info at all). Do not import the remote HTTP fd into our Comm + // space; collect and send an IPC msg with collected info to Coordinator. + ::close(request.fd); + collect(); + sendResponse(request.requestId); +} + +void +Mgr::Action::sendResponse(unsigned int requestId) +{ + Response response(requestId, this); + Ipc::TypedMsgHdr message; + response.pack(message); + Ipc::SendMessage(Ipc::coordinatorAddr, message); +} + +void +Mgr::Action::run(StoreEntry* entry, bool writeHttpHeader) +{ + debugs(16, 5, HERE); + collect(); + fillEntry(entry, writeHttpHeader); +} + +void +Mgr::Action::fillEntry(StoreEntry* entry, bool writeHttpHeader) +{ + debugs(16, 5, HERE); + entry->buffer(); + + if (writeHttpHeader) { + HttpReply *rep = new HttpReply; + rep->setHeaders(HTTP_OK, NULL, "text/plain", -1, squid_curtime, squid_curtime); + entry->replaceHttpReply(rep); + } + + dump(entry); + + entry->flush(); + + if (atomic()) + entry->complete(); +} diff --git a/src/mgr/Action.h b/src/mgr/Action.h new file mode 100644 index 0000000000..5e4e14f8c4 --- /dev/null +++ b/src/mgr/Action.h @@ -0,0 +1,94 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_ACTION_H +#define SQUID_MGR_ACTION_H + +#include "ipc/forward.h" +#include "mgr/forward.h" + +class StoreEntry; + +namespace Mgr +{ + +/// Base API for organizing the processing of a compiled cache manager command. +/// Not a job because all methods are synchronous (but they may start jobs). +class Action: public RefCountable +{ +public: + typedef RefCount Pointer; + +public: + Action(const CommandPointer &aCmd); + virtual ~Action(); + + + /* for local Cache Manager use */ + + /// collect + fillEntry: collect local information and fill the store entry + void run(StoreEntry *entry, bool writeHttpHeader); + + /// prepare store entry, dump info, close store entry (if possible) + void fillEntry(StoreEntry *entry, bool writeHttpHeader); + + + /* for global Coordinator use */ + + /// incrementally merge in remote information (of the same action type) + virtual void add(const Action &action); + + + /* global-local communication */ + + /// respond to Coordinator request; default is to collect and sendResponse + virtual void respond(const Request &request); + + /// pack collected action info into a message to be sent to Coordinator + virtual void pack(Ipc::TypedMsgHdr &msg) const {} + /// unpack action info from the message received by Coordinator + virtual void unpack(const Ipc::TypedMsgHdr &msg) {} + + /// notify Coordinator that this action is done with local processing + void sendResponse(unsigned int requestId); + + + /* Action properties */ + + /// whether at least some local kid info can be combined and, hence, the + /// combined data should be written at the end of the coordinated response + virtual bool aggregatable() const { return true; } // most kid classes are + + bool atomic() const; ///< dump() call writes everything before returning + const char *name() const; ///< label as seen in the cache manager menu + const Command &command() const; ///< the cause of this action + + StoreEntry *createStoreEntry() const; ///< creates store entry from params + +protected: + /// calculate and keep local action-specific information + virtual void collect() {} + + /** start writing action-specific info to Store entry; + * may collect info during dump, especially if collect() did nothing + * non-atomic() actions may continue writing asynchronously after returning + */ + virtual void dump(StoreEntry *entry) {} + + +private: + const CommandPointer cmd; ///< the command that caused this action + + +private: + Action(const Action &); // not implemented + Action &operator= (const Action &); // not implemented +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_ACTION_H */ diff --git a/src/mgr/ActionCreator.h b/src/mgr/ActionCreator.h new file mode 100644 index 0000000000..c4f24610c9 --- /dev/null +++ b/src/mgr/ActionCreator.h @@ -0,0 +1,33 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_ACTION_CREATOR_H +#define SQUID_MGR_ACTION_CREATOR_H + +#include "mgr/forward.h" + +namespace Mgr +{ + +/** Creates objects of the right Action class, parameterized with Command. + * A part of the Action profile that allows Cache Manager be ignorant about + * specific Action classes (\see Mgr::ActionProfile). + */ +class ActionCreator: public RefCountable +{ +public: + typedef RefCount Pointer; + + virtual ~ActionCreator() {} + + /// returns a pointer to the new Action object for cmd; never nil + virtual ActionPointer create(const CommandPointer &cmd) const = 0; +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_ACTION_CREATOR_H */ diff --git a/src/mgr/ActionParams.cc b/src/mgr/ActionParams.cc new file mode 100644 index 0000000000..5dea7e5ca1 --- /dev/null +++ b/src/mgr/ActionParams.cc @@ -0,0 +1,41 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "ipc/TypedMsgHdr.h" +#include "mgr/ActionParams.h" + +Mgr::ActionParams::ActionParams(): httpMethod(METHOD_NONE) { +} + +Mgr::ActionParams::ActionParams(const Ipc::TypedMsgHdr &msg) +{ + msg.getString(httpUri); + + const int m = msg.getInt(); + Must(METHOD_NONE <= m && m < METHOD_ENUM_END); + httpMethod = static_cast<_method_t>(m); + + msg.getPod(httpFlags); + + msg.getString(actionName); + msg.getString(userName); + msg.getString(password); +} + +void +Mgr::ActionParams::pack(Ipc::TypedMsgHdr &msg) const +{ + msg.putString(httpUri); + msg.putInt(httpMethod); + msg.putPod(httpFlags); + + msg.putString(actionName); + msg.putString(userName); + msg.putString(password); +} diff --git a/src/mgr/ActionParams.h b/src/mgr/ActionParams.h new file mode 100644 index 0000000000..4287a53455 --- /dev/null +++ b/src/mgr/ActionParams.h @@ -0,0 +1,43 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_ACTION_PARAMS_H +#define SQUID_MGR_ACTION_PARAMS_H + +#include "HttpRequestMethod.h" +#include "ipc/forward.h" + +namespace Mgr +{ + +/// Cache Manager Action parameters extracted from the user request +class ActionParams +{ +public: + ActionParams(); + + explicit ActionParams(const Ipc::TypedMsgHdr &msg); ///< load from msg + void pack(Ipc::TypedMsgHdr &msg) const; ///< store into msg + +public: + /* details of the client HTTP request that caused the action */ + String httpUri; ///< HTTP request URI + _method_t httpMethod; ///< HTTP request method + request_flags httpFlags; ///< HTTP request flags + + /* action parameters extracted from the client HTTP request */ + String actionName; ///< action name (and credentials realm) + String userName; ///< user login name; currently only used for logging + String password; ///< user password; used for acceptance check and cleared + +}; + +} // namespace Mgr + +std::ostream &operator <<(std::ostream &os, const Mgr::ActionParams ¶ms); + +#endif /* SQUID_MGR_ACTION_PARAMS_H */ diff --git a/src/mgr/ActionProfile.h b/src/mgr/ActionProfile.h new file mode 100644 index 0000000000..e0acfe76f6 --- /dev/null +++ b/src/mgr/ActionProfile.h @@ -0,0 +1,47 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_ACTION_PROFILE_H +#define SQUID_MGR_ACTION_PROFILE_H + +#include "mgr/ActionCreator.h" +#include "mgr/forward.h" + +namespace Mgr +{ + +/// hard-coded Cache Manager action configuration, including Action creator +class ActionProfile: public RefCountable +{ +public: + typedef RefCount Pointer; + +public: + ActionProfile(const char* aName, const char* aDesc, bool aPwReq, + bool anAtomic, const ActionCreatorPointer &aCreator): + name(aName), desc(aDesc), isPwReq(aPwReq), isAtomic(anAtomic), + creator(aCreator) + { + } + +public: + const char *name; ///< action label to uniquely identify this action + const char *desc; ///< action description to build an action menu list + bool isPwReq; ///< whether password is required to perform the action + bool isAtomic; ///< whether action dumps everything in one dump() call + ActionCreatorPointer creator; ///< creates Action objects with this profile +}; + +} // namespace Mgr + +inline std::ostream & +operator <<(std::ostream &os, const Mgr::ActionProfile &profile) +{ + return os << profile.name; +} + +#endif /* SQUID_MGR_ACTION_PROFILE_H */ diff --git a/src/mgr/ActionWriter.cc b/src/mgr/ActionWriter.cc new file mode 100644 index 0000000000..18e0dccd36 --- /dev/null +++ b/src/mgr/ActionWriter.cc @@ -0,0 +1,31 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "mgr/ActionWriter.h" +#include "Store.h" + + +CBDATA_NAMESPACED_CLASS_INIT(Mgr, ActionWriter); + +Mgr::ActionWriter::ActionWriter(const Action::Pointer &anAction, int aFd): + StoreToCommWriter(aFd, anAction->createStoreEntry()), + action(anAction) +{ + debugs(16, 5, HERE << "FD " << aFd << " action: " << action); +} + +void +Mgr::ActionWriter::start() +{ + debugs(16, 5, HERE); + Must(action != NULL); + + StoreToCommWriter::start(); + action->fillEntry(entry, false); +} diff --git a/src/mgr/ActionWriter.h b/src/mgr/ActionWriter.h new file mode 100644 index 0000000000..25a4bd204f --- /dev/null +++ b/src/mgr/ActionWriter.h @@ -0,0 +1,37 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_ACTION_WRITER_H +#define SQUID_MGR_ACTION_WRITER_H + +#include "HttpRequestMethod.h" +#include "mgr/StoreToCommWriter.h" + + +namespace Mgr +{ + +/// Creates Store entry, fills it using action's fillEntry(), and +/// Comm-writes it using parent StoreToCommWriter. +class ActionWriter: public StoreToCommWriter +{ +public: + ActionWriter(const Action::Pointer &anAction, int aFd); + +protected: + /* AsyncJob API */ + virtual void start(); + +private: + Action::Pointer action; ///< action that fills the entry + + CBDATA_CLASS2(ActionWriter); +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_ACTION_WRITER_H */ diff --git a/src/mgr/BasicActions.cc b/src/mgr/BasicActions.cc new file mode 100644 index 0000000000..012e9145dd --- /dev/null +++ b/src/mgr/BasicActions.cc @@ -0,0 +1,136 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "CacheManager.h" +#include "mgr/ActionCreator.h" +#include "mgr/ActionProfile.h" +#include "mgr/BasicActions.h" +#include "mgr/Registration.h" +#include "Store.h" + + +Mgr::MenuAction::Pointer +Mgr::MenuAction::Create(const Command::Pointer &cmd) +{ + return new MenuAction(cmd); +} + +Mgr::MenuAction::MenuAction(const Command::Pointer &cmd): Action(cmd) +{ + debugs(16, 5, HERE); +} + +void +Mgr::MenuAction::dump(StoreEntry* entry) +{ + debugs(16, 5, HERE); + Must(entry != NULL); + + typedef CacheManager::Menu::const_iterator Iterator; + const CacheManager::Menu& menu = CacheManager::GetInstance()->menu(); + + for (Iterator a = menu.begin(); a != menu.end(); ++a) { + storeAppendPrintf(entry, " %-22s\t%-32s\t%s\n", + (*a)->name, (*a)->desc, + CacheManager::GetInstance()->ActionProtection(*a)); + } +} + +Mgr::ShutdownAction::Pointer +Mgr::ShutdownAction::Create(const Command::Pointer &cmd) +{ + return new ShutdownAction(cmd); +} + +Mgr::ShutdownAction::ShutdownAction(const Command::Pointer &cmd): Action(cmd) +{ + debugs(16, 5, HERE); +} + +void +Mgr::ShutdownAction::dump(StoreEntry* entry) +{ + debugs(16, DBG_CRITICAL, "Shutdown by Cache Manager command."); + shut_down(SIGTERM); +} + +Mgr::ReconfigureAction::Pointer +Mgr::ReconfigureAction::Create(const Command::Pointer &cmd) +{ + return new ReconfigureAction(cmd); +} + +Mgr::ReconfigureAction::ReconfigureAction(const Command::Pointer &cmd): + Action(cmd) +{ + debugs(16, 5, HERE); +} + +void +Mgr::ReconfigureAction::dump(StoreEntry* entry) +{ + debugs(16, DBG_IMPORTANT, "Reconfigure by Cache Manager command."); + storeAppendPrintf(entry, "Reconfiguring Squid Process ...."); + reconfigure(SIGHUP); +} + +Mgr::RotateAction::Pointer +Mgr::RotateAction::Create(const Command::Pointer &cmd) +{ + return new RotateAction(cmd); +} + +Mgr::RotateAction::RotateAction(const Command::Pointer &cmd): Action(cmd) +{ + debugs(16, 5, HERE); +} + +void +Mgr::RotateAction::dump(StoreEntry* entry) +{ + debugs(16, DBG_IMPORTANT, "Rotate Logs by Cache Manager command."); + storeAppendPrintf(entry, "Rotating Squid Process Logs ...."); +#ifdef _SQUID_LINUX_THREADS_ + rotate_logs(SIGQUIT); +#else + rotate_logs(SIGUSR1); +#endif +} + +Mgr::OfflineToggleAction::Pointer +Mgr::OfflineToggleAction::Create(const Command::Pointer &cmd) +{ + return new OfflineToggleAction(cmd); +} + +Mgr::OfflineToggleAction::OfflineToggleAction(const Command::Pointer &cmd): + Action(cmd) +{ + debugs(16, 5, HERE); +} + +void +Mgr::OfflineToggleAction::dump(StoreEntry* entry) +{ + Config.onoff.offline = !Config.onoff.offline; + debugs(16, DBG_IMPORTANT, "offline_mode now " << (Config.onoff.offline ? "ON" : "OFF") << " by Cache Manager request."); + + storeAppendPrintf(entry, "offline_mode is now %s\n", + Config.onoff.offline ? "ON" : "OFF"); +} + +void +Mgr::RegisterBasics() +{ + RegisterAction("offline_toggle", "Toggle offline_mode setting", &Mgr::OfflineToggleAction::Create, 1, 1); + RegisterAction("shutdown", "Shut Down the Squid Process", &Mgr::ShutdownAction::Create, 1, 1); + RegisterAction("reconfigure", "Reconfigure Squid", &Mgr::ReconfigureAction::Create, 1, 1); + RegisterAction("rotate", "Rotate Squid Logs", &Mgr::RotateAction::Create, 1, 1); + RegisterAction("menu", "Cache Manager Menu", &Mgr::MenuAction::Create, 0, 1); +} diff --git a/src/mgr/BasicActions.h b/src/mgr/BasicActions.h new file mode 100644 index 0000000000..ffe8008579 --- /dev/null +++ b/src/mgr/BasicActions.h @@ -0,0 +1,85 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_BASIC_ACTIONS_H +#define SQUID_MGR_BASIC_ACTIONS_H + +#include "mgr/Action.h" + +/* a collection of simple, mostly stateless actions */ + + +namespace Mgr +{ + +/// returns available Cache Manager actions and their access requirements +class MenuAction: public Action +{ +public: + static Pointer Create(const CommandPointer &cmd); + /* Action API */ + virtual void dump(StoreEntry *entry); + +protected: + MenuAction(const CommandPointer &cmd); +}; + + +/// shuts Squid down +class ShutdownAction: public Action +{ +public: + static Pointer Create(const CommandPointer &cmd); + /* Action API */ + virtual void dump(StoreEntry *entry); + +protected: + ShutdownAction(const CommandPointer &cmd); +}; + +/// reconfigures Squid +class ReconfigureAction: public Action +{ +public: + static Pointer Create(const CommandPointer &cmd); + /* Action API */ + virtual void dump(StoreEntry *entry); + +protected: + ReconfigureAction(const CommandPointer &cmd); +}; + +/// starts log rotation +class RotateAction: public Action +{ +public: + static Pointer Create(const CommandPointer &cmd); + /* Action API */ + virtual void dump(StoreEntry *entry); + +protected: + RotateAction(const CommandPointer &cmd); +}; + +/// changes offline mode +class OfflineToggleAction: public Action +{ +public: + static Pointer Create(const CommandPointer &cmd); + /* Action API */ + virtual void dump(StoreEntry *entry); + +protected: + OfflineToggleAction(const CommandPointer &cmd); +}; + +/// Registeres profiles for the actions above; \todo move elsewhere? +void RegisterBasics(); + +} // namespace Mgr + +#endif /* SQUID_MGR_BASIC_ACTIONS_H */ diff --git a/src/mgr/Command.cc b/src/mgr/Command.cc new file mode 100644 index 0000000000..2d57b2dba0 --- /dev/null +++ b/src/mgr/Command.cc @@ -0,0 +1,18 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "mgr/ActionProfile.h" +#include "mgr/Command.h" + +std::ostream & +operator <<(std::ostream &os, const Mgr::Command &cmd) +{ + if (cmd.profile != NULL) + return os << *cmd.profile; + return os << "undef"; +} diff --git a/src/mgr/Command.h b/src/mgr/Command.h new file mode 100644 index 0000000000..d73395eeb5 --- /dev/null +++ b/src/mgr/Command.h @@ -0,0 +1,31 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_COMMAND_H +#define SQUID_MGR_COMMAND_H + +#include "mgr/ActionParams.h" +#include "mgr/forward.h" + +namespace Mgr +{ + +/// combined hard-coded action profile with user-supplied action parameters +class Command: public RefCountable { +public: + typedef RefCount Pointer; + +public: + ActionProfilePointer profile; ///< hard-coded action specification + ActionParams params; ///< user-supplied action arguments +}; + +} // namespace Mgr + +std::ostream &operator <<(std::ostream &os, const Mgr::Command &cmd); + +#endif /* SQUID_MGR_COMMAND_H */ diff --git a/src/mgr/CountersAction.cc b/src/mgr/CountersAction.cc new file mode 100644 index 0000000000..e780fa43aa --- /dev/null +++ b/src/mgr/CountersAction.cc @@ -0,0 +1,135 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "ipc/Messages.h" +#include "ipc/TypedMsgHdr.h" +#include "mgr/CountersAction.h" +#include "SquidTime.h" +#include "Store.h" + + +extern void GetCountersStats(Mgr::CountersActionData& stats); +extern void DumpCountersStats(Mgr::CountersActionData& stats, StoreEntry* sentry); + +Mgr::CountersActionData::CountersActionData() +{ + xmemset(this, 0, sizeof(*this)); +} + +Mgr::CountersActionData& +Mgr::CountersActionData::operator += (const CountersActionData& stats) +{ + if (timercmp(&sample_time, &stats.sample_time, <)) + sample_time = stats.sample_time; + client_http_requests += stats.client_http_requests; + client_http_hits += stats.client_http_hits; + client_http_errors += stats.client_http_errors; + client_http_kbytes_in += stats.client_http_kbytes_in; + client_http_kbytes_out += stats.client_http_kbytes_out; + client_http_hit_kbytes_out += stats.client_http_hit_kbytes_out; + server_all_requests += stats.server_all_requests; + server_all_errors += stats.server_all_errors; + server_all_kbytes_in += stats.server_all_kbytes_in; + server_all_kbytes_out += stats.server_all_kbytes_out; + server_http_requests += stats.server_http_requests; + server_http_errors += stats.server_http_errors; + server_http_kbytes_in += stats.server_http_kbytes_in; + server_http_kbytes_out += stats.server_http_kbytes_out; + server_ftp_requests += stats.server_ftp_requests; + server_ftp_errors += stats.server_ftp_errors; + server_ftp_kbytes_in += stats.server_ftp_kbytes_in; + server_ftp_kbytes_out += stats.server_ftp_kbytes_out; + server_other_requests += stats.server_other_requests; + server_other_errors += stats.server_other_errors; + server_other_kbytes_in += stats.server_other_kbytes_in; + server_other_kbytes_out += stats.server_other_kbytes_out; + icp_pkts_sent += stats.icp_pkts_sent; + icp_pkts_recv += stats.icp_pkts_recv; + icp_queries_sent += stats.icp_queries_sent; + icp_replies_sent += stats.icp_replies_sent; + icp_queries_recv += stats.icp_queries_recv; + icp_replies_recv += stats.icp_replies_recv; + icp_replies_queued += stats.icp_replies_queued; + icp_query_timeouts += stats.icp_query_timeouts; + icp_kbytes_sent += stats.icp_kbytes_sent; + icp_kbytes_recv += stats.icp_kbytes_recv; + icp_q_kbytes_sent += stats.icp_q_kbytes_sent; + icp_r_kbytes_sent += stats.icp_r_kbytes_sent; + icp_q_kbytes_recv += stats.icp_q_kbytes_recv; + icp_r_kbytes_recv += stats.icp_r_kbytes_recv; +#if USE_CACHE_DIGESTS + icp_times_used += stats.icp_times_used; + cd_times_used += stats.cd_times_used; + cd_msgs_sent += stats.cd_msgs_sent; + cd_msgs_recv += stats.cd_msgs_recv; + cd_memory += stats.cd_memory; + cd_local_memory += stats.cd_local_memory; + cd_kbytes_sent += stats.cd_kbytes_sent; + cd_kbytes_recv += stats.cd_kbytes_recv; +#endif + unlink_requests += stats.unlink_requests; + page_faults += stats.page_faults; + select_loops += stats.select_loops; + cpu_time += stats.cpu_time; + wall_time += stats.wall_time; + swap_outs += stats.swap_outs; + swap_ins += stats.swap_ins; + swap_files_cleaned += stats.swap_files_cleaned; + aborted_requests += stats.aborted_requests; + + return *this; +} + +Mgr::CountersAction::Pointer +Mgr::CountersAction::Create(const CommandPointer &cmd) +{ + return new CountersAction(cmd); +} + +Mgr::CountersAction::CountersAction(const CommandPointer &cmd): + Action(cmd), data() +{ + debugs(16, 5, HERE); +} + +void +Mgr::CountersAction::add(const Action& action) +{ + debugs(16, 5, HERE); + data += dynamic_cast(action).data; +} + +void +Mgr::CountersAction::collect() +{ + debugs(16, 5, HERE); + GetCountersStats(data); +} + +void +Mgr::CountersAction::dump(StoreEntry* entry) +{ + debugs(16, 5, HERE); + Must(entry != NULL); + DumpCountersStats(data, entry); +} + +void +Mgr::CountersAction::pack(Ipc::TypedMsgHdr& msg) const +{ + msg.setType(Ipc::mtCacheMgrResponse); + msg.putPod(data); +} + +void +Mgr::CountersAction::unpack(const Ipc::TypedMsgHdr& msg) +{ + msg.checkType(Ipc::mtCacheMgrResponse); + msg.getPod(data); +} diff --git a/src/mgr/CountersAction.h b/src/mgr/CountersAction.h new file mode 100644 index 0000000000..447bb8bcca --- /dev/null +++ b/src/mgr/CountersAction.h @@ -0,0 +1,108 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_COUNTERS_ACTION_H +#define SQUID_MGR_COUNTERS_ACTION_H + +#include "mgr/Action.h" +#include + + +namespace Mgr +{ + +/// store traffic and resource counters +class CountersActionData +{ +public: + CountersActionData(); + CountersActionData& operator += (const CountersActionData& stats); + +public: + struct timeval sample_time; + double client_http_requests; + double client_http_hits; + double client_http_errors; + double client_http_kbytes_in; + double client_http_kbytes_out; + double client_http_hit_kbytes_out; + double server_all_requests; + double server_all_errors; + double server_all_kbytes_in; + double server_all_kbytes_out; + double server_http_requests; + double server_http_errors; + double server_http_kbytes_in; + double server_http_kbytes_out; + double server_ftp_requests; + double server_ftp_errors; + double server_ftp_kbytes_in; + double server_ftp_kbytes_out; + double server_other_requests; + double server_other_errors; + double server_other_kbytes_in; + double server_other_kbytes_out; + double icp_pkts_sent; + double icp_pkts_recv; + double icp_queries_sent; + double icp_replies_sent; + double icp_queries_recv; + double icp_replies_recv; + double icp_replies_queued; + double icp_query_timeouts; + double icp_kbytes_sent; + double icp_kbytes_recv; + double icp_q_kbytes_sent; + double icp_r_kbytes_sent; + double icp_q_kbytes_recv; + double icp_r_kbytes_recv; +#if USE_CACHE_DIGESTS + double icp_times_used; + double cd_times_used; + double cd_msgs_sent; + double cd_msgs_recv; + double cd_memory; + double cd_local_memory; + double cd_kbytes_sent; + double cd_kbytes_recv; +#endif + double unlink_requests; + double page_faults; + double select_loops; + double cpu_time; + double wall_time; + double swap_outs; + double swap_ins; + double swap_files_cleaned; + double aborted_requests; +}; + +/// implement aggregated 'counters' action +class CountersAction: public Action +{ +protected: + CountersAction(const CommandPointer &cmd); + +public: + static Pointer Create(const CommandPointer &cmd); + /* Action API */ + virtual void add(const Action& action); + virtual void pack(Ipc::TypedMsgHdr& msg) const; + virtual void unpack(const Ipc::TypedMsgHdr& msg); + +protected: + /* Action API */ + virtual void collect(); + virtual void dump(StoreEntry* entry); + +private: + CountersActionData data; +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_COUNTERS_ACTION_H */ diff --git a/src/mgr/Filler.cc b/src/mgr/Filler.cc new file mode 100644 index 0000000000..8646cd8586 --- /dev/null +++ b/src/mgr/Filler.cc @@ -0,0 +1,43 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "mgr/Filler.h" +#include "mgr/Response.h" +#include "Store.h" + + +CBDATA_NAMESPACED_CLASS_INIT(Mgr, Filler); + +Mgr::Filler::Filler(const Action::Pointer &anAction, int aFd, + unsigned int aRequestId): + StoreToCommWriter(aFd, anAction->createStoreEntry()), + action(anAction), + requestId(aRequestId) +{ + debugs(16, 5, HERE << "FD " << aFd << " action: " << action); +} + +void +Mgr::Filler::start() +{ + debugs(16, 5, HERE); + Must(requestId != 0); + Must(action != NULL); + + StoreToCommWriter::start(); + action->run(entry, false); +} + +void +Mgr::Filler::swanSong() +{ + debugs(16, 5, HERE); + action->sendResponse(requestId); + StoreToCommWriter::swanSong(); +} diff --git a/src/mgr/Filler.h b/src/mgr/Filler.h new file mode 100644 index 0000000000..e6c7ba1f03 --- /dev/null +++ b/src/mgr/Filler.h @@ -0,0 +1,38 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_FILLER_H +#define SQUID_MGR_FILLER_H + +#include "HttpRequestMethod.h" +#include "mgr/Action.h" +#include "mgr/StoreToCommWriter.h" + +namespace Mgr +{ + +/// provides Coordinator with a local cache manager response +class Filler: public StoreToCommWriter +{ +public: + Filler(const Action::Pointer &anAction, int aFd, unsigned int aRequestId); + +protected: + /* AsyncJob API */ + virtual void start(); + virtual void swanSong(); + +private: + Action::Pointer action; ///< action that will run() and sendResponse() + unsigned int requestId; ///< the ID of the Request we are responding to + + CBDATA_CLASS2(Filler); +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_FILLER_H */ diff --git a/src/mgr/Forwarder.cc b/src/mgr/Forwarder.cc new file mode 100644 index 0000000000..02a6178928 --- /dev/null +++ b/src/mgr/Forwarder.cc @@ -0,0 +1,240 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/AsyncJobCalls.h" +#include "base/TextException.h" +#include "CommCalls.h" +#include "errorpage.h" +#include "HttpReply.h" +#include "HttpRequest.h" +#include "ipc/Port.h" +#include "mgr/Forwarder.h" +#include "mgr/Request.h" +#include "SquidTime.h" +#include "Store.h" + + +CBDATA_NAMESPACED_CLASS_INIT(Mgr, Forwarder); + +Mgr::Forwarder::RequestsMap Mgr::Forwarder::TheRequestsMap; +unsigned int Mgr::Forwarder::LastRequestId = 0; + +Mgr::Forwarder::Forwarder(int aFd, const ActionParams &aParams, + HttpRequest* aRequest, StoreEntry* anEntry): + AsyncJob("Mgr::Forwarder"), + params(aParams), + request(aRequest), entry(anEntry), fd(aFd), requestId(0), closer(NULL) +{ + debugs(16, 5, HERE << "FD " << aFd); + Must(fd >= 0); + Must(request != NULL); + Must(entry != NULL); + + HTTPMSGLOCK(request); + entry->lock(); + EBIT_SET(entry->flags, ENTRY_FWD_HDR_WAIT); + + closer = asyncCall(16, 5, "Mgr::Forwarder::noteCommClosed", + CommCbMemFunT(this, &Forwarder::noteCommClosed)); + comm_add_close_handler(fd, closer); +} + +Mgr::Forwarder::~Forwarder() +{ + debugs(16, 5, HERE); + Must(request != NULL); + Must(entry != NULL); + Must(requestId == 0); + + HTTPMSGUNLOCK(request); + entry->unregisterAbort(); + entry->unlock(); + close(); +} + +/// closes our copy of the client HTTP connection socket +void +Mgr::Forwarder::close() { + if (fd >= 0) { + if (closer != NULL) { + comm_remove_close_handler(fd, closer); + closer = NULL; + } + comm_close(fd); + fd = -1; + } +} + +void +Mgr::Forwarder::start() +{ + debugs(16, 3, HERE); + entry->registerAbort(&Forwarder::Abort, this); + + typedef NullaryMemFunT Dialer; + AsyncCall::Pointer callback = JobCallback(16, 5, Dialer, this, + Forwarder::handleRemoteAck); + if (++LastRequestId == 0) // don't use zero value as requestId + ++LastRequestId; + requestId = LastRequestId; + TheRequestsMap[requestId] = callback; + Request mgrRequest(KidIdentifier, requestId, fd, params); + Ipc::TypedMsgHdr message; + + try { + mgrRequest.pack(message); + } + catch (...) { + // assume the pack() call failed because the message did not fit + // TODO: add a more specific exception? + debugs(16, DBG_CRITICAL, "ERROR: uri " << entry->url() << " exceeds buffer size"); + quitOnError("long URI", errorCon(ERR_INVALID_URL, HTTP_REQUEST_URI_TOO_LARGE, request)); + } + + Ipc::SendMessage(Ipc::coordinatorAddr, message); + const double timeout = 10; // in seconds + eventAdd("Mgr::Forwarder::requestTimedOut", &Forwarder::RequestTimedOut, + this, timeout, 0, false); +} + +void +Mgr::Forwarder::swanSong() +{ + debugs(16, 5, HERE); + removeTimeoutEvent(); + if (requestId > 0) { + DequeueRequest(requestId); + requestId = 0; + } + close(); +} + +bool +Mgr::Forwarder::doneAll() const +{ + debugs(16, 5, HERE); + return requestId == 0; +} + +/// called when the client socket gets closed by some external force +void +Mgr::Forwarder::noteCommClosed(const CommCloseCbParams& params) +{ + debugs(16, 5, HERE); + Must(fd == params.fd); + fd = -1; + mustStop("commClosed"); +} + +/// called when Coordinator starts processing the request +void +Mgr::Forwarder::handleRemoteAck() +{ + debugs(16, 3, HERE); + Must(entry != NULL); + + requestId = 0; + EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); + entry->complete(); +} + +/// Mgr::Forwarder::requestTimedOut wrapper +void +Mgr::Forwarder::RequestTimedOut(void* param) +{ + debugs(16, 3, HERE); + Must(param != NULL); + Forwarder* mgrFwdr = static_cast(param); + // use async call to enable job call protection that time events lack + CallJobHere(16, 5, mgrFwdr, Mgr::Forwarder, requestTimedOut); +} + +/// called when Coordinator fails to start processing the request [in time] +void +Mgr::Forwarder::requestTimedOut() +{ + debugs(16, 3, HERE); + quitOnError("timeout", errorCon(ERR_LIFETIME_EXP, HTTP_REQUEST_TIMEOUT, request)); +} + +/// terminate with an error +void +Mgr::Forwarder::quitOnError(const char *reason, ErrorState *error) +{ + debugs(16, 3, HERE); + Must(reason != NULL); + Must(error != NULL); + Must(entry != NULL); + Must(request != NULL); + + EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); + entry->buffer(); + entry->replaceHttpReply(error->BuildHttpReply()); + entry->expires = squid_curtime; + errorStateFree(error); + entry->flush(); + entry->complete(); + + mustStop(reason); +} + +void +Mgr::Forwarder::callException(const std::exception& e) +{ + try { + if (entry != NULL && request != NULL && fd >= 0) + quitOnError("exception", errorCon(ERR_INVALID_RESP, HTTP_INTERNAL_SERVER_ERROR, request)); + } catch (const std::exception& ex) { + debugs(16, DBG_CRITICAL, HERE << ex.what()); + } + AsyncJob::callException(e); +} + +/// returns and forgets the right Forwarder callback for the request +AsyncCall::Pointer +Mgr::Forwarder::DequeueRequest(unsigned int requestId) +{ + debugs(16, 3, HERE); + Must(requestId != 0); + AsyncCall::Pointer call; + RequestsMap::iterator request = TheRequestsMap.find(requestId); + if (request != TheRequestsMap.end()) { + call = request->second; + Must(call != NULL); + TheRequestsMap.erase(request); + } + return call; +} + +/// called when we are no longer waiting for Coordinator to respond +void +Mgr::Forwarder::removeTimeoutEvent() +{ + if (eventFind(&Forwarder::RequestTimedOut, this)) + eventDelete(&Forwarder::RequestTimedOut, this); +} + +void +Mgr::Forwarder::HandleRemoteAck(unsigned int requestId) +{ + debugs(16, 3, HERE); + Must(requestId != 0); + + AsyncCall::Pointer call = DequeueRequest(requestId); + if (call != NULL) + ScheduleCallHere(call); +} + +/// called when something goes wrong with the Store entry +void +Mgr::Forwarder::Abort(void* param) +{ + Forwarder* mgrFwdr = static_cast(param); + if (mgrFwdr->fd >= 0) + comm_close(mgrFwdr->fd); +} diff --git a/src/mgr/Forwarder.h b/src/mgr/Forwarder.h new file mode 100644 index 0000000000..21f2427eec --- /dev/null +++ b/src/mgr/Forwarder.h @@ -0,0 +1,77 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_FORWARDER_H +#define SQUID_MGR_FORWARDER_H + +#include "base/AsyncJob.h" +#include "mgr/ActionParams.h" +#include + + +class CommCloseCbParams; +class HttpRequest; +class StoreEntry; +class ErrorState; + +namespace Mgr +{ + +/** Forwards a single client cache manager request to Coordinator. + * Waits for an ACK from Coordinator while holding the Store entry. + * Fills the store entry with an error response if forwarding fails. + */ +class Forwarder: public AsyncJob +{ +public: + Forwarder(int aFd, const ActionParams &aParams, HttpRequest* aRequest, + StoreEntry* anEntry); + virtual ~Forwarder(); + + /// finds and calls the right Forwarder upon Coordinator's response + static void HandleRemoteAck(unsigned int requestId); + + /* has-to-be-public AsyncJob API */ + virtual void callException(const std::exception& e); + +protected: + /* AsyncJob API */ + virtual void start(); + virtual void swanSong(); + virtual bool doneAll() const; + +private: + void handleRemoteAck(); + static void RequestTimedOut(void* param); + void requestTimedOut(); + void quitOnError(const char *reason, ErrorState *error); + void noteCommClosed(const CommCloseCbParams& params); + void removeTimeoutEvent(); + static AsyncCall::Pointer DequeueRequest(unsigned int requestId); + static void Abort(void* param); + void close(); + +private: + ActionParams params; ///< action parameters to pass to the other side + HttpRequest* request; ///< HTTP client request for detailing errors + StoreEntry* entry; ///< Store entry expecting the response + int fd; ///< HTTP client connection descriptor + unsigned int requestId; ///< request id + AsyncCall::Pointer closer; ///< comm_close handler for the HTTP connection + + /// maps requestId to Forwarder::handleRemoteAck callback + typedef std::map RequestsMap; + static RequestsMap TheRequestsMap; ///< pending Coordinator requests + + static unsigned int LastRequestId; ///< last requestId used + + CBDATA_CLASS2(Forwarder); +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_FORWARDER_H */ diff --git a/src/mgr/FunAction.cc b/src/mgr/FunAction.cc new file mode 100644 index 0000000000..e7f11d89e7 --- /dev/null +++ b/src/mgr/FunAction.cc @@ -0,0 +1,50 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "mgr/Command.h" +#include "mgr/Filler.h" +#include "mgr/FunAction.h" +#include "mgr/Request.h" +#include "Store.h" + + +Mgr::FunAction::Pointer +Mgr::FunAction::Create(const Command::Pointer &aCmd, OBJH* aHandler) +{ + return new FunAction(aCmd, aHandler); +} + +Mgr::FunAction::FunAction(const Command::Pointer &aCmd, OBJH* aHandler): + Action(aCmd), handler(aHandler) +{ + Must(handler != NULL); + debugs(16, 5, HERE); +} + +void +Mgr::FunAction::respond(const Request& request) +{ + debugs(16, 5, HERE); + const int fd = ImportHttpFdIntoComm(request.fd); + Must(fd >= 0); + Must(request.requestId != 0); + AsyncJob::Start(new Mgr::Filler(this, fd, request.requestId)); +} + +void +Mgr::FunAction::dump(StoreEntry* entry) +{ + debugs(16, 5, HERE); + Must(entry != NULL); + if (UsingSmp() && IamWorkerProcess()) + storeAppendPrintf(entry, "by kid%d {\n", KidIdentifier); + handler(entry); + if (atomic() && UsingSmp() && IamWorkerProcess()) + storeAppendPrintf(entry, "} by kid%d\n\n", KidIdentifier); +} diff --git a/src/mgr/FunAction.h b/src/mgr/FunAction.h new file mode 100644 index 0000000000..2b70e0b04a --- /dev/null +++ b/src/mgr/FunAction.h @@ -0,0 +1,60 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_FUN_ACTION_H +#define SQUID_MGR_FUN_ACTION_H + +#include "mgr/Action.h" +#include "mgr/ActionCreator.h" + + +namespace Mgr +{ + +/// function-based cache manager Action; a wrapper for so called legacy actions +/// that do everything using a single OBJH function +class FunAction: public Action +{ +protected: + FunAction(const CommandPointer &cmd, OBJH *aHandler); + +public: + static Pointer Create(const CommandPointer &cmd, OBJH *aHandler); + + /* Action API */ + virtual void respond(const Request& request); + // we cannot aggregate because we do not even know what the handler does + virtual bool aggregatable() const { return false; } + +protected: + /* Action API */ + virtual void dump(StoreEntry *entry); + +private: + OBJH *handler; ///< legacy function that collects and dumps info +}; + + +/// creates FunAction using ActionCreator API +class FunActionCreator: public ActionCreator +{ +public: + explicit FunActionCreator(OBJH *aHandler): handler(aHandler) {} + + /* ActionCreator API */ + virtual Action::Pointer create(const CommandPointer &cmd) const + { + return FunAction::Create(cmd, handler); + } + +private: + OBJH *handler; ///< legacy function to pass to the FunAction wrapper +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_FUN_ACTION_H */ diff --git a/src/mgr/InfoAction.cc b/src/mgr/InfoAction.cc new file mode 100644 index 0000000000..1f93cc4995 --- /dev/null +++ b/src/mgr/InfoAction.cc @@ -0,0 +1,199 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "HttpReply.h" +#include "ipc/Messages.h" +#include "ipc/TypedMsgHdr.h" +#include "mgr/Filler.h" +#include "mgr/InfoAction.h" +#include "mgr/Request.h" +#include "mgr/Response.h" +#include "SquidTime.h" +#include "Store.h" + + +extern void GetInfo(Mgr::InfoActionData& stats); +extern void DumpInfo(Mgr::InfoActionData& stats, StoreEntry* sentry); +extern void DumpMallocStatistics(StoreEntry* sentry); + +Mgr::InfoActionData::InfoActionData() +{ + xmemset(this, 0, sizeof(*this)); +} + +Mgr::InfoActionData& +Mgr::InfoActionData::operator += (const InfoActionData& stats) +{ + if (!timerisset(&squid_start) || timercmp(&squid_start, &stats.squid_start, >)) + squid_start = stats.squid_start; + if (timercmp(¤t_time, &stats.current_time, <)) + current_time = stats.current_time; + client_http_clients += stats.client_http_clients; + client_http_requests += stats.client_http_requests; + icp_pkts_recv += stats.icp_pkts_recv; + icp_pkts_sent += stats.icp_pkts_sent; + icp_replies_queued += stats.icp_replies_queued; +#if USE_HTCP + htcp_pkts_recv += stats.htcp_pkts_recv; + htcp_pkts_sent += stats.htcp_pkts_sent; +#endif + request_failure_ratio += stats.request_failure_ratio; + avg_client_http_requests += stats.avg_client_http_requests; + avg_icp_messages += stats.avg_icp_messages; + select_loops += stats.select_loops; + avg_loop_time += stats.avg_loop_time; + request_hit_ratio5 += stats.request_hit_ratio5; + request_hit_ratio60 += stats.request_hit_ratio60; + byte_hit_ratio5 += stats.byte_hit_ratio5; + byte_hit_ratio60 += stats.byte_hit_ratio60; + request_hit_mem_ratio5 += stats.request_hit_mem_ratio5; + request_hit_mem_ratio60 += stats.request_hit_mem_ratio60; + request_hit_disk_ratio5 += stats.request_hit_disk_ratio5; + request_hit_disk_ratio60 += stats.request_hit_disk_ratio60; + store_swap_size += stats.store_swap_size; + store_swap_max_size += stats.store_swap_max_size; + store_mem_size += stats.store_mem_size; + store_pages_max += stats.store_pages_max; + store_mem_used += stats.store_mem_used; + objects_size += stats.objects_size; + unlink_requests += stats.unlink_requests; + http_requests5 += stats.http_requests5; + http_requests60 += stats.http_requests60; + cache_misses5 += stats.cache_misses5; + cache_misses60 += stats.cache_misses60; + cache_hits5 += stats.cache_hits5; + cache_hits60 += stats.cache_hits60; + near_hits5 += stats.near_hits5; + near_hits60 += stats.near_hits60; + not_modified_replies5 += stats.not_modified_replies5; + not_modified_replies60 += stats.not_modified_replies60; + dns_lookups5 += stats.dns_lookups5; + dns_lookups60 += stats.dns_lookups60; + icp_queries5 += stats.icp_queries5; + icp_queries60 += stats.icp_queries60; + if (stats.up_time > up_time) + up_time = stats.up_time; + cpu_time += stats.cpu_time; + cpu_usage += stats.cpu_usage; + cpu_usage5 += stats.cpu_usage5; + cpu_usage60 += stats.cpu_usage60; +#if HAVE_SBRK + proc_data_seg += stats.proc_data_seg; +#endif + maxrss += stats.maxrss; + page_faults += stats.page_faults; +#if HAVE_MSTATS && HAVE_GNUMALLOC_H + ms_bytes_total += stats.ms_bytes_total; + ms_bytes_free += stats.ms_bytes_free; +#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO + mp_arena += stats.mp_arena; + mp_uordblks += stats.mp_uordblks; + mp_ordblks += stats.mp_ordblks; + mp_usmblks += stats.mp_usmblks; + mp_smblks += stats.mp_smblks; + mp_hblkhd += stats.mp_hblkhd; + mp_hblks += stats.mp_hblks; + mp_fsmblks += stats.mp_fsmblks; + mp_fordblks += stats.mp_fordblks; +#if HAVE_STRUCT_MALLINFO_MXFAST + mp_mxfast += stats.mp_mxfast; + mp_nlblks += stats.mp_nlblks; + mp_grain += stats.mp_grain; + mp_uordbytes += stats.mp_uordbytes; + mp_allocated += stats.mp_allocated; + mp_treeoverhead += stats.mp_treeoverhead; +#endif +#endif + total_accounted += stats.total_accounted; +#if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO + mem_pool_allocated += stats.mem_pool_allocated; +#endif + gb_saved_count += stats.gb_saved_count; + gb_freed_count += stats.gb_freed_count; + max_fd += stats.max_fd; + biggest_fd += stats.biggest_fd; + number_fd += stats.number_fd; + opening_fd += stats.opening_fd; + num_fd_free += stats.num_fd_free; + reserved_fd += stats.reserved_fd; + store_open_disk_fd += stats.store_open_disk_fd; + store_entries += stats.store_entries; + store_mem_entries += stats.store_mem_entries; + hot_obj_count += stats.hot_obj_count; + n_disk_objects += stats.n_disk_objects; + ++count; + + return *this; +} + +Mgr::InfoAction::Pointer +Mgr::InfoAction::Create(const CommandPointer &cmd) +{ + return new InfoAction(cmd); +} + +Mgr::InfoAction::InfoAction(const CommandPointer &cmd): + Action(cmd), data() +{ + debugs(16, 5, HERE); +} + +void +Mgr::InfoAction::add(const Action& action) +{ + debugs(16, 5, HERE); + data += dynamic_cast(action).data; +} + +void +Mgr::InfoAction::respond(const Request& request) +{ + debugs(16, 5, HERE); + int fd = ImportHttpFdIntoComm(request.fd); + Must(fd >= 0); + Must(request.requestId != 0); + AsyncJob::Start(new Mgr::Filler(this, fd, request.requestId)); +} + +void +Mgr::InfoAction::collect() +{ + GetInfo(data); +} + +void +Mgr::InfoAction::dump(StoreEntry* entry) +{ + debugs(16, 5, HERE); + Must(entry != NULL); + +#if XMALLOC_STATISTICS + if (UsingSmp() && IamWorkerProcess()) + storeAppendPrintf(entry, "by kid%d {\n", KidIdentifier); + DumpMallocStatistics(entry); + if (UsingSmp() && IamWorkerProcess()) + storeAppendPrintf(entry, "} by kid%d\n\n", KidIdentifier); +#endif + if (IamPrimaryProcess()) + DumpInfo(data, entry); +} + +void +Mgr::InfoAction::pack(Ipc::TypedMsgHdr& msg) const +{ + msg.setType(Ipc::mtCacheMgrResponse); + msg.putPod(data); +} + +void +Mgr::InfoAction::unpack(const Ipc::TypedMsgHdr& msg) +{ + msg.checkType(Ipc::mtCacheMgrResponse); + msg.getPod(data); +} diff --git a/src/mgr/InfoAction.h b/src/mgr/InfoAction.h new file mode 100644 index 0000000000..25721e04ca --- /dev/null +++ b/src/mgr/InfoAction.h @@ -0,0 +1,149 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_INFO_ACTION_H +#define SQUID_MGR_INFO_ACTION_H + +#include "mgr/Action.h" +#include + + +namespace Mgr +{ + +/// store general runtime information +/// and memory usage +class InfoActionData +{ +public: + InfoActionData(); + InfoActionData& operator += (const InfoActionData& stats); + +public: + struct timeval squid_start; + struct timeval current_time; + double client_http_clients; + double client_http_requests; + double icp_pkts_recv; + double icp_pkts_sent; + double icp_replies_queued; +#if USE_HTCP + double htcp_pkts_recv; + double htcp_pkts_sent; +#endif + double request_failure_ratio; + double avg_client_http_requests; + double avg_icp_messages; + double select_loops; + double avg_loop_time; + double request_hit_ratio5; + double request_hit_ratio60; + double byte_hit_ratio5; + double byte_hit_ratio60; + double request_hit_mem_ratio5; + double request_hit_mem_ratio60; + double request_hit_disk_ratio5; + double request_hit_disk_ratio60; + double store_swap_size; + double store_swap_max_size; + double store_mem_size; + double store_pages_max; + double store_mem_used; + double objects_size; + double unlink_requests; + double http_requests5; + double http_requests60; + double cache_misses5; + double cache_misses60; + double cache_hits5; + double cache_hits60; + double near_hits5; + double near_hits60; + double not_modified_replies5; + double not_modified_replies60; + double dns_lookups5; + double dns_lookups60; + double icp_queries5; + double icp_queries60; + double up_time; + double cpu_time; + double cpu_usage; + double cpu_usage5; + double cpu_usage60; +#if HAVE_SBRK + double proc_data_seg; +#endif + double maxrss; + double page_faults; +#if HAVE_MSTATS && HAVE_GNUMALLOC_H + double ms_bytes_total; + double ms_bytes_free; +#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO + double mp_arena; + double mp_uordblks; + double mp_ordblks; + double mp_usmblks; + double mp_smblks; + double mp_hblkhd; + double mp_hblks; + double mp_fsmblks; + double mp_fordblks; +#if HAVE_STRUCT_MALLINFO_MXFAST + double mp_mxfast; + double mp_nlblks; + double mp_grain; + double mp_uordbytes; + double mp_allocated; + double mp_treeoverhead; +#endif +#endif + double total_accounted; +#if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO + double mem_pool_allocated; +#endif + double gb_saved_count; + double gb_freed_count; + double max_fd; + double biggest_fd; + double number_fd; + double opening_fd; + double num_fd_free; + double reserved_fd; + double store_open_disk_fd; + double store_entries; + double store_mem_entries; + double hot_obj_count; + double n_disk_objects; + unsigned int count; +}; + +/// implement aggregated 'info' action +class InfoAction: public Action +{ +protected: + InfoAction(const CommandPointer &cmd); + +public: + static Pointer Create(const CommandPointer &cmd); + /* Action API */ + virtual void add(const Action& action); + virtual void respond(const Request& request); + virtual void pack(Ipc::TypedMsgHdr& msg) const; + virtual void unpack(const Ipc::TypedMsgHdr& msg); + +protected: + /* Action API */ + virtual void collect(); + virtual void dump(StoreEntry* entry); + +private: + InfoActionData data; +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_INFO_ACTION_H */ diff --git a/src/mgr/Inquirer.cc b/src/mgr/Inquirer.cc new file mode 100644 index 0000000000..bd36180deb --- /dev/null +++ b/src/mgr/Inquirer.cc @@ -0,0 +1,250 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "CommCalls.h" +#include "HttpReply.h" +#include "ipc/Coordinator.h" +#include "mgr/ActionWriter.h" +#include "mgr/Command.h" +#include "mgr/Inquirer.h" +#include "mgr/Request.h" +#include "mgr/Response.h" +#include "SquidTime.h" +#include +#include + + +CBDATA_NAMESPACED_CLASS_INIT(Mgr, Inquirer); + +Mgr::Inquirer::RequestsMap Mgr::Inquirer::TheRequestsMap; +unsigned int Mgr::Inquirer::LastRequestId = 0; + +/// compare Ipc::StrandCoord using kidId, for std::sort() below +static bool +LesserStrandByKidId(const Ipc::StrandCoord &c1, const Ipc::StrandCoord &c2) { + return c1.kidId < c2.kidId; +} + +Mgr::Inquirer::Inquirer(Action::Pointer anAction, int aFd, + const Request &aCause, const Ipc::StrandCoords &coords): + AsyncJob("Mgr::Inquirer"), + aggrAction(anAction), + cause(aCause), + fd(aFd), + strands(coords), pos(strands.begin()), + requestId(0), closer(NULL), timeout(aggrAction->atomic() ? 10 : 100) +{ + debugs(16, 5, HERE << "FD " << aFd << " action: " << aggrAction); + + // order by ascending kid IDs; useful for non-aggregatable stats + std::sort(strands.begin(), strands.end(), LesserStrandByKidId); + + closer = asyncCall(16, 5, "Mgr::Inquirer::noteCommClosed", + CommCbMemFunT(this, &Inquirer::noteCommClosed)); + comm_add_close_handler(fd, closer); +} + +Mgr::Inquirer::~Inquirer() +{ + debugs(16, 5, HERE); + close(); +} + +/// closes our copy of the client HTTP connection socket +void +Mgr::Inquirer::close() { + if (fd >= 0) { + removeCloseHandler(); + comm_close(fd); + fd = -1; + } +} + +void +Mgr::Inquirer::removeCloseHandler() +{ + if (closer != NULL) { + comm_remove_close_handler(fd, closer); + closer = NULL; + } +} + +void +Mgr::Inquirer::start() +{ + debugs(16, 5, HERE); + Must(fd >= 0); + Must(aggrAction != NULL); + + std::auto_ptr reply(new HttpReply); + reply->setHeaders(HTTP_OK, NULL, "text/plain", -1, squid_curtime, squid_curtime); + reply->header.putStr(HDR_CONNECTION, "close"); // until we chunk response + std::auto_ptr replyBuf(reply->pack()); + writer = asyncCall(16, 5, "Mgr::Inquirer::noteWroteHeader", + CommCbMemFunT(this, &Inquirer::noteWroteHeader)); + comm_write_mbuf(fd, replyBuf.get(), writer); +} + +/// called when we wrote the response header +void +Mgr::Inquirer::noteWroteHeader(const CommIoCbParams& params) +{ + debugs(16, 5, HERE); + writer = NULL; + Must(params.flag == COMM_OK); + Must(params.fd == fd); + Must(params.size != 0); + // start inquiries at the initial pos + inquire(); +} + +void +Mgr::Inquirer::inquire() +{ + if (pos == strands.end()) { + Must(done()); + return; + } + + Must(requestId == 0); + AsyncCall::Pointer callback = asyncCall(16, 5, "Mgr::Inquirer::handleRemoteAck", + HandleAckDialer(this, &Inquirer::handleRemoteAck, Response())); + if (++LastRequestId == 0) // don't use zero value as requestId + ++LastRequestId; + requestId = LastRequestId; + const int kidId = pos->kidId; + debugs(16, 4, HERE << "inquire kid: " << kidId << status()); + TheRequestsMap[requestId] = callback; + Request mgrRequest(KidIdentifier, requestId, fd, + aggrAction->command().params); + Ipc::TypedMsgHdr message; + mgrRequest.pack(message); + Ipc::SendMessage(Ipc::Port::MakeAddr(Ipc::strandAddrPfx, kidId), message); + eventAdd("Mgr::Inquirer::requestTimedOut", &Inquirer::RequestTimedOut, + this, timeout, 0, false); +} + +/// called when a strand is done writing its output +void +Mgr::Inquirer::handleRemoteAck(const Response& response) +{ + debugs(16, 4, HERE << status()); + requestId = 0; + removeTimeoutEvent(); + if (response.hasAction()) + aggrAction->add(response.getAction()); + Must(!done()); // or we should not be called + ++pos; // advance after a successful inquiry + inquire(); +} + +/// called when the HTTP client or some external force closed our socket +void +Mgr::Inquirer::noteCommClosed(const CommCloseCbParams& params) +{ + debugs(16, 5, HERE); + Must(fd < 0 || fd == params.fd); + fd = -1; + mustStop("commClosed"); +} + +void +Mgr::Inquirer::swanSong() +{ + debugs(16, 5, HERE); + removeTimeoutEvent(); + if (requestId > 0) { + DequeueRequest(requestId); + requestId = 0; + } + if (aggrAction->aggregatable()) { + removeCloseHandler(); + AsyncJob::Start(new ActionWriter(aggrAction, fd)); + fd = -1; // should not close fd because we passed it to ActionWriter + } + close(); +} + +bool +Mgr::Inquirer::doneAll() const +{ + return !writer && pos == strands.end(); +} + +/// returns and forgets the right Inquirer callback for strand request +AsyncCall::Pointer +Mgr::Inquirer::DequeueRequest(unsigned int requestId) +{ + debugs(16, 3, HERE << " requestId " << requestId); + Must(requestId != 0); + AsyncCall::Pointer call; + RequestsMap::iterator request = TheRequestsMap.find(requestId); + if (request != TheRequestsMap.end()) { + call = request->second; + Must(call != NULL); + TheRequestsMap.erase(request); + } + return call; +} + +void +Mgr::Inquirer::HandleRemoteAck(const Mgr::Response& response) +{ + Must(response.requestId != 0); + AsyncCall::Pointer call = DequeueRequest(response.requestId); + if (call != NULL) { + HandleAckDialer* dialer = dynamic_cast(call->getDialer()); + Must(dialer); + dialer->arg1 = response; + ScheduleCallHere(call); + } +} + +/// called when we are no longer waiting for the strand to respond +void +Mgr::Inquirer::removeTimeoutEvent() +{ + if (eventFind(&Inquirer::RequestTimedOut, this)) + eventDelete(&Inquirer::RequestTimedOut, this); +} + +/// Mgr::Inquirer::requestTimedOut wrapper +void +Mgr::Inquirer::RequestTimedOut(void* param) +{ + debugs(16, 3, HERE); + Must(param != NULL); + Inquirer* cmi = static_cast(param); + // use async call to enable job call protection that time events lack + CallJobHere(16, 5, cmi, Mgr::Inquirer, requestTimedOut); +} + +/// called when the strand failed to respond (or finish responding) in time +void +Mgr::Inquirer::requestTimedOut() +{ + debugs(16, 3, HERE); + if (requestId != 0) { + DequeueRequest(requestId); + requestId = 0; + Must(!done()); // or we should not be called + ++pos; // advance after a failed inquiry + inquire(); + } +} + +const char* +Mgr::Inquirer::status() const +{ + static MemBuf buf; + buf.reset(); + buf.Printf(" [FD %d, requestId %u]", fd, requestId); + buf.terminate(); + return buf.content(); +} diff --git a/src/mgr/Inquirer.h b/src/mgr/Inquirer.h new file mode 100644 index 0000000000..c59530da80 --- /dev/null +++ b/src/mgr/Inquirer.h @@ -0,0 +1,87 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_INQUIRER_H +#define SQUID_MGR_INQUIRER_H + +#include "base/AsyncJobCalls.h" +#include "base/AsyncJob.h" +#include "ipc/StrandCoords.h" +#include "MemBuf.h" +#include "mgr/Action.h" +#include "mgr/Request.h" +#include + +class CommIoCbParams; +class CommCloseCbParams; + +namespace Mgr +{ + +/// Coordinator's job that sends a cache manage request to each strand, +/// aggregating individual strand responses and dumping the result if needed +class Inquirer: public AsyncJob +{ +public: + Inquirer(Action::Pointer anAction, int aFd, const Request &aCause, + const Ipc::StrandCoords &coords); + virtual ~Inquirer(); + + /// finds and calls the right Inquirer upon strand's response + static void HandleRemoteAck(const Mgr::Response& response); + +protected: + /* AsyncJob API */ + virtual void start(); + virtual void swanSong(); + virtual bool doneAll() const; + virtual const char *status() const; + +private: + typedef UnaryMemFunT HandleAckDialer; + + void inquire(); + void noteWroteHeader(const CommIoCbParams& params); + void noteCommClosed(const CommCloseCbParams& params); + + void handleRemoteAck(const Response& response); + + static AsyncCall::Pointer DequeueRequest(unsigned int requestId); + + static void RequestTimedOut(void* param); + void requestTimedOut(); + void removeTimeoutEvent(); + + void close(); + void removeCloseHandler(); + +private: + Action::Pointer aggrAction; //< action to aggregate + + Request cause; ///< cache manager request received from HTTP client + int fd; ///< HTTP client socket descriptor + + Ipc::StrandCoords strands; ///< all strands we want to query, in order + Ipc::StrandCoords::const_iterator pos; ///< strand we should query now + + unsigned int requestId; ///< ID of our outstanding request to strand + AsyncCall::Pointer writer; ///< comm_write callback + AsyncCall::Pointer closer; ///< comm_close handler + const double timeout; ///< number of seconds to wait for strand response + + /// maps requestId to Inquirer::handleRemoteAck callback + typedef std::map RequestsMap; + static RequestsMap TheRequestsMap; ///< pending strand requests + + static unsigned int LastRequestId; ///< last requestId used + + CBDATA_CLASS2(Inquirer); +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_INQUIRER_H */ diff --git a/src/mgr/IntervalAction.cc b/src/mgr/IntervalAction.cc new file mode 100644 index 0000000000..3c8d5dd446 --- /dev/null +++ b/src/mgr/IntervalAction.cc @@ -0,0 +1,159 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "ipc/Messages.h" +#include "ipc/TypedMsgHdr.h" +#include "mgr/IntervalAction.h" +#include "SquidMath.h" +#include "Store.h" + + +extern void GetAvgStat(Mgr::IntervalActionData& stats, int minutes, int hours); +extern void DumpAvgStat(Mgr::IntervalActionData& stats, StoreEntry* sentry); + +Mgr::IntervalActionData::IntervalActionData() +{ + xmemset(this, 0, sizeof(*this)); +} + +Mgr::IntervalActionData& +Mgr::IntervalActionData::operator += (const IntervalActionData& stats) +{ + if (!timerisset(&sample_start_time) || timercmp(&sample_start_time, &stats.sample_start_time, >)) + sample_start_time = stats.sample_start_time; + if (timercmp(&sample_end_time, &stats.sample_end_time, <)) + sample_end_time = stats.sample_end_time; + client_http_requests += stats.client_http_requests; + client_http_hits += stats.client_http_hits; + client_http_errors += stats.client_http_errors; + client_http_kbytes_in += stats.client_http_kbytes_in; + client_http_kbytes_out += stats.client_http_kbytes_out; + client_http_all_median_svc_time += stats.client_http_all_median_svc_time; + client_http_miss_median_svc_time += stats.client_http_miss_median_svc_time; + client_http_nm_median_svc_time += stats.client_http_nm_median_svc_time; + client_http_nh_median_svc_time += stats.client_http_nh_median_svc_time; + client_http_hit_median_svc_time += stats.client_http_hit_median_svc_time; + server_all_requests += stats.server_all_requests; + server_all_errors += stats.server_all_errors; + server_all_kbytes_in += stats.server_all_kbytes_in; + server_all_kbytes_out += stats.server_all_kbytes_out; + server_http_requests += stats.server_http_requests; + server_http_errors += stats.server_http_errors; + server_http_kbytes_in += stats.server_http_kbytes_in; + server_http_kbytes_out += stats.server_http_kbytes_out; + server_ftp_requests += stats.server_ftp_requests; + server_ftp_errors += stats.server_ftp_errors; + server_ftp_kbytes_in += stats.server_ftp_kbytes_in; + server_ftp_kbytes_out += stats.server_ftp_kbytes_out; + server_other_requests += stats.server_other_requests; + server_other_errors += stats.server_other_errors; + server_other_kbytes_in += stats.server_other_kbytes_in; + server_other_kbytes_out += stats.server_other_kbytes_out; + icp_pkts_sent += stats.icp_pkts_sent; + icp_pkts_recv += stats.icp_pkts_recv; + icp_queries_sent += stats.icp_queries_sent; + icp_replies_sent += stats.icp_replies_sent; + icp_queries_recv += stats.icp_queries_recv; + icp_replies_recv += stats.icp_replies_recv; + icp_replies_queued += stats.icp_replies_queued; + icp_query_timeouts += stats.icp_query_timeouts; + icp_kbytes_sent += stats.icp_kbytes_sent; + icp_kbytes_recv += stats.icp_kbytes_recv; + icp_q_kbytes_sent += stats.icp_q_kbytes_sent; + icp_r_kbytes_sent += stats.icp_r_kbytes_sent; + icp_q_kbytes_recv += stats.icp_q_kbytes_recv; + icp_r_kbytes_recv += stats.icp_r_kbytes_recv; + icp_query_median_svc_time += stats.icp_query_median_svc_time; + icp_reply_median_svc_time += stats.icp_reply_median_svc_time; + dns_median_svc_time += stats.dns_median_svc_time; + unlink_requests += stats.unlink_requests; + page_faults += stats.page_faults; + select_loops += stats.select_loops; + select_fds += stats.select_fds; + average_select_fd_period += stats.average_select_fd_period; + median_select_fds += stats.median_select_fds; + swap_outs += stats.swap_outs; + swap_ins += stats.swap_ins; + swap_files_cleaned += stats.swap_files_cleaned; + aborted_requests += stats.aborted_requests; + syscalls_disk_opens += stats.syscalls_disk_opens; + syscalls_disk_closes += stats.syscalls_disk_closes; + syscalls_disk_reads += stats.syscalls_disk_reads; + syscalls_disk_writes += stats.syscalls_disk_writes; + syscalls_disk_seeks += stats.syscalls_disk_seeks; + syscalls_disk_unlinks += stats.syscalls_disk_unlinks; + syscalls_sock_accepts += stats.syscalls_sock_accepts; + syscalls_sock_sockets += stats.syscalls_sock_sockets; + syscalls_sock_connects += stats.syscalls_sock_connects; + syscalls_sock_binds += stats.syscalls_sock_binds; + syscalls_sock_closes += stats.syscalls_sock_closes; + syscalls_sock_reads += stats.syscalls_sock_reads; + syscalls_sock_writes += stats.syscalls_sock_writes; + syscalls_sock_recvfroms += stats.syscalls_sock_recvfroms; + syscalls_sock_sendtos += stats.syscalls_sock_sendtos; + syscalls_selects += stats.syscalls_selects; + cpu_time += stats.cpu_time; + wall_time += stats.wall_time; + ++count; + + return *this; +} + +Mgr::IntervalAction::Pointer +Mgr::IntervalAction::Create5min(const CommandPointer &cmd) +{ + return new IntervalAction(cmd, 5, 0); +} + +Mgr::IntervalAction::Pointer +Mgr::IntervalAction::Create60min(const CommandPointer &cmd) +{ + return new IntervalAction(cmd, 60, 0); +} + +Mgr::IntervalAction::IntervalAction(const CommandPointer &cmd, int aMinutes, int aHours): + Action(cmd), minutes(aMinutes), hours(aHours), data() +{ + debugs(16, 5, HERE); +} + +void +Mgr::IntervalAction::add(const Action& action) +{ + debugs(16, 5, HERE); + data += dynamic_cast(action).data; +} + +void +Mgr::IntervalAction::collect() +{ + GetAvgStat(data, minutes, hours); +} + +void +Mgr::IntervalAction::dump(StoreEntry* entry) +{ + debugs(16, 5, HERE); + Must(entry != NULL); + DumpAvgStat(data, entry); +} + +void +Mgr::IntervalAction::pack(Ipc::TypedMsgHdr& msg) const +{ + msg.setType(Ipc::mtCacheMgrResponse); + msg.putPod(data); +} + +void +Mgr::IntervalAction::unpack(const Ipc::TypedMsgHdr& msg) +{ + msg.checkType(Ipc::mtCacheMgrResponse); + msg.getPod(data); +} diff --git a/src/mgr/IntervalAction.h b/src/mgr/IntervalAction.h new file mode 100644 index 0000000000..fb1b80d8fe --- /dev/null +++ b/src/mgr/IntervalAction.h @@ -0,0 +1,130 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_INTERVAL_ACTION_H +#define SQUID_MGR_INTERVAL_ACTION_H + +#include "mgr/Action.h" +#include + + +namespace Mgr +{ + +/// auxiliary class which store stats computed +/// from StatCounters for specified interval +class IntervalActionData +{ +public: + IntervalActionData(); + IntervalActionData& operator += (const IntervalActionData& stats); + +public: + struct timeval sample_start_time; + struct timeval sample_end_time; + double client_http_requests; + double client_http_hits; + double client_http_errors; + double client_http_kbytes_in; + double client_http_kbytes_out; + double client_http_all_median_svc_time; + double client_http_miss_median_svc_time; + double client_http_nm_median_svc_time; + double client_http_nh_median_svc_time; + double client_http_hit_median_svc_time; + double server_all_requests; + double server_all_errors; + double server_all_kbytes_in; + double server_all_kbytes_out; + double server_http_requests; + double server_http_errors; + double server_http_kbytes_in; + double server_http_kbytes_out; + double server_ftp_requests; + double server_ftp_errors; + double server_ftp_kbytes_in; + double server_ftp_kbytes_out; + double server_other_requests; + double server_other_errors; + double server_other_kbytes_in; + double server_other_kbytes_out; + double icp_pkts_sent; + double icp_pkts_recv; + double icp_queries_sent; + double icp_replies_sent; + double icp_queries_recv; + double icp_replies_recv; + double icp_replies_queued; + double icp_query_timeouts; + double icp_kbytes_sent; + double icp_kbytes_recv; + double icp_q_kbytes_sent; + double icp_r_kbytes_sent; + double icp_q_kbytes_recv; + double icp_r_kbytes_recv; + double icp_query_median_svc_time; + double icp_reply_median_svc_time; + double dns_median_svc_time; + double unlink_requests; + double page_faults; + double select_loops; + double select_fds; + double average_select_fd_period; + double median_select_fds; + double swap_outs; + double swap_ins; + double swap_files_cleaned; + double aborted_requests; + double syscalls_disk_opens; + double syscalls_disk_closes; + double syscalls_disk_reads; + double syscalls_disk_writes; + double syscalls_disk_seeks; + double syscalls_disk_unlinks; + double syscalls_sock_accepts; + double syscalls_sock_sockets; + double syscalls_sock_connects; + double syscalls_sock_binds; + double syscalls_sock_closes; + double syscalls_sock_reads; + double syscalls_sock_writes; + double syscalls_sock_recvfroms; + double syscalls_sock_sendtos; + double syscalls_selects; + double cpu_time; + double wall_time; + unsigned int count; +}; + +/// implement aggregated interval actions +class IntervalAction: public Action +{ +protected: + IntervalAction(const CommandPointer &cmd, int aMinutes, int aHours); + +public: + static Pointer Create5min(const CommandPointer &cmd); + static Pointer Create60min(const CommandPointer &cmd); + /* Action API */ + virtual void add(const Action& action); + virtual void pack(Ipc::TypedMsgHdr& msg) const; + virtual void unpack(const Ipc::TypedMsgHdr& msg); + +protected: + /* Action API */ + virtual void collect(); + virtual void dump(StoreEntry* entry); + +private: + int minutes; + int hours; + IntervalActionData data; +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_INTERVAL_ACTION_H */ diff --git a/src/mgr/IoAction.cc b/src/mgr/IoAction.cc new file mode 100644 index 0000000000..87ab7926ca --- /dev/null +++ b/src/mgr/IoAction.cc @@ -0,0 +1,86 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "ipc/Messages.h" +#include "ipc/TypedMsgHdr.h" +#include "mgr/IoAction.h" +#include "SquidMath.h" +#include "Store.h" + + +extern void GetIoStats(Mgr::IoActionData& stats); +extern void DumpIoStats(Mgr::IoActionData& stats, StoreEntry* sentry); + +Mgr::IoActionData::IoActionData() +{ + xmemset(this, 0, sizeof(*this)); +} + +Mgr::IoActionData& +Mgr::IoActionData::operator += (const IoActionData& stats) +{ + http_reads += stats.http_reads; + for (int i = 0; i < _iostats::histSize; ++i) + http_read_hist[i] += stats.http_read_hist[i]; + ftp_reads += stats.ftp_reads; + for (int i = 0; i < _iostats::histSize; ++i) + ftp_read_hist[i] += stats.ftp_read_hist[i]; + gopher_reads += stats.gopher_reads; + for (int i = 0; i < _iostats::histSize; ++i) + gopher_read_hist[i] += stats.gopher_read_hist[i]; + + return *this; +} + +Mgr::IoAction::Pointer +Mgr::IoAction::Create(const CommandPointer &cmd) +{ + return new IoAction(cmd); +} + +Mgr::IoAction::IoAction(const CommandPointer &cmd): + Action(cmd), data() +{ + debugs(16, 5, HERE); +} + +void +Mgr::IoAction::add(const Action& action) +{ + debugs(16, 5, HERE); + data += dynamic_cast(action).data; +} + +void +Mgr::IoAction::collect() +{ + GetIoStats(data); +} + +void +Mgr::IoAction::dump(StoreEntry* entry) +{ + debugs(16, 5, HERE); + Must(entry != NULL); + DumpIoStats(data, entry); +} + +void +Mgr::IoAction::pack(Ipc::TypedMsgHdr& msg) const +{ + msg.setType(Ipc::mtCacheMgrResponse); + msg.putPod(data); +} + +void +Mgr::IoAction::unpack(const Ipc::TypedMsgHdr& msg) +{ + msg.checkType(Ipc::mtCacheMgrResponse); + msg.getPod(data); +} diff --git a/src/mgr/IoAction.h b/src/mgr/IoAction.h new file mode 100644 index 0000000000..812eda63aa --- /dev/null +++ b/src/mgr/IoAction.h @@ -0,0 +1,57 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_IO_ACTION_H +#define SQUID_MGR_IO_ACTION_H + +#include "mgr/Action.h" +#include "structs.h" /* _iostats::histSize */ + +namespace Mgr +{ + +/// store server-side network read() size histograms +class IoActionData +{ +public: + IoActionData(); + IoActionData& operator += (const IoActionData& stats); + +public: + double http_reads; + double ftp_reads; + double gopher_reads; + double http_read_hist[_iostats::histSize]; + double ftp_read_hist[_iostats::histSize]; + double gopher_read_hist[_iostats::histSize]; +}; + +/// implement aggregated 'io' action +class IoAction: public Action +{ +protected: + IoAction(const CommandPointer &cmd); + +public: + static Pointer Create(const CommandPointer &cmd); + /* Action API */ + virtual void add(const Action& action); + virtual void pack(Ipc::TypedMsgHdr& msg) const; + virtual void unpack(const Ipc::TypedMsgHdr& msg); + +protected: + /* Action API */ + virtual void collect(); + virtual void dump(StoreEntry* entry); + +private: + IoActionData data; +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_IO_ACTION_H */ diff --git a/src/mgr/Makefile.am b/src/mgr/Makefile.am new file mode 100644 index 0000000000..2d7d543002 --- /dev/null +++ b/src/mgr/Makefile.am @@ -0,0 +1,47 @@ +include $(top_srcdir)/src/Common.am +include $(top_srcdir)/src/TestHeaders.am + +noinst_LTLIBRARIES = libmgr.la + +libmgr_la_SOURCES = \ + Action.cc \ + ActionCreator.h \ + Action.h \ + ActionParams.cc \ + ActionParams.h \ + ActionProfile.h \ + ActionWriter.cc \ + ActionWriter.h \ + BasicActions.cc \ + BasicActions.h \ + Command.cc \ + Command.h \ + CountersAction.cc \ + CountersAction.h \ + Filler.cc \ + Filler.h \ + Forwarder.cc \ + Forwarder.h \ + forward.h \ + FunAction.cc \ + FunAction.h \ + InfoAction.cc \ + InfoAction.h \ + Inquirer.cc \ + Inquirer.h \ + IntervalAction.cc \ + IntervalAction.h \ + IoAction.cc \ + IoAction.h \ + Registration.cc \ + Registration.h \ + Request.cc \ + Request.h \ + Response.cc \ + Response.h \ + ServiceTimesAction.cc \ + ServiceTimesAction.h \ + StoreIoAction.cc \ + StoreIoAction.h \ + StoreToCommWriter.cc \ + StoreToCommWriter.h diff --git a/src/mgr/Registration.cc b/src/mgr/Registration.cc new file mode 100644 index 0000000000..e6da0e7685 --- /dev/null +++ b/src/mgr/Registration.cc @@ -0,0 +1,28 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "CacheManager.h" +#include "mgr/Registration.h" + +void +Mgr::RegisterAction(char const * action, char const * desc, + OBJH * handler, + int pw_req_flag, int atomic) +{ + CacheManager::GetInstance()->registerProfile(action, desc, handler, + pw_req_flag, atomic); +} + +void +Mgr::RegisterAction(char const * action, char const * desc, + ClassActionCreationHandler *handler, + int pw_req_flag, int atomic) +{ + CacheManager::GetInstance()->registerProfile(action, desc, handler, + pw_req_flag, atomic); +} diff --git a/src/mgr/Registration.h b/src/mgr/Registration.h new file mode 100644 index 0000000000..caaa10e74d --- /dev/null +++ b/src/mgr/Registration.h @@ -0,0 +1,27 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_REGISTRATION_H +#define SQUID_MGR_REGISTRATION_H + +#include "mgr/forward.h" +#include "typedefs.h" /* for OBJH */ + +namespace Mgr +{ + +void RegisterAction(char const * action, char const * desc, + OBJH * handler, + int pw_req_flag, int atomic); + +void RegisterAction(char const * action, char const * desc, + ClassActionCreationHandler *handler, + int pw_req_flag, int atomic); + +} // namespace Mgr + +#endif /* SQUID_MGR_REGISTRATION_H */ diff --git a/src/mgr/Request.cc b/src/mgr/Request.cc new file mode 100644 index 0000000000..b80ad19cda --- /dev/null +++ b/src/mgr/Request.cc @@ -0,0 +1,43 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "ipc/Messages.h" +#include "mgr/ActionParams.h" +#include "mgr/Request.h" + + +Mgr::Request::Request(int aRequestorId, unsigned int aRequestId, int aFd, + const ActionParams &aParams): + requestorId(aRequestorId), requestId(aRequestId), + fd(aFd), params(aParams) +{ + Must(requestorId > 0); + Must(requestId != 0); +} + +Mgr::Request::Request(const Ipc::TypedMsgHdr& msg) +{ + msg.checkType(Ipc::mtCacheMgrRequest); + msg.getPod(requestorId); + msg.getPod(requestId); + params = ActionParams(msg); + + fd = msg.getFd(); +} + +void +Mgr::Request::pack(Ipc::TypedMsgHdr& msg) const +{ + msg.setType(Ipc::mtCacheMgrRequest); + msg.putPod(requestorId); + msg.putPod(requestId); + params.pack(msg); + + msg.putFd(fd); +} diff --git a/src/mgr/Request.h b/src/mgr/Request.h new file mode 100644 index 0000000000..edeaaf4852 --- /dev/null +++ b/src/mgr/Request.h @@ -0,0 +1,39 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_REQUEST_H +#define SQUID_MGR_REQUEST_H + +#include "ipc/TypedMsgHdr.h" +#include "mgr/ActionParams.h" + + +namespace Mgr +{ + +/// cache manager request +class Request +{ +public: + Request(int aRequestorId, unsigned int aRequestId, int aFd, + const ActionParams &aParams); + + explicit Request(const Ipc::TypedMsgHdr& msg); ///< from recvmsg() + void pack(Ipc::TypedMsgHdr& msg) const; ///< prepare for sendmsg() + +public: + int requestorId; ///< kidId of the requestor; used for response destination + unsigned int requestId; ///< unique for sender; matches request w/ response + int fd; ///< HTTP client connection descriptor + + ActionParams params; ///< action name and parameters +}; + + +} // namespace Mgr + +#endif /* SQUID_MGR_REQUEST_H */ diff --git a/src/mgr/Response.cc b/src/mgr/Response.cc new file mode 100644 index 0000000000..1462e6c3b0 --- /dev/null +++ b/src/mgr/Response.cc @@ -0,0 +1,68 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "CacheManager.h" +#include "ipc/Messages.h" +#include "ipc/TypedMsgHdr.h" +#include "mgr/ActionCreator.h" +#include "mgr/ActionProfile.h" +#include "mgr/Response.h" + + +std::ostream& Mgr::operator << (std::ostream &os, const Response& response) +{ + os << "response: {requestId: " << response.requestId << '}'; + return os; +} + +Mgr::Response::Response(unsigned int aRequestId, Action::Pointer anAction): + requestId(aRequestId), action(anAction) +{ + Must(!action || action->name()); // if there is an action, it must be named +} + +Mgr::Response::Response(const Ipc::TypedMsgHdr& msg) +{ + msg.checkType(Ipc::mtCacheMgrResponse); + msg.getPod(requestId); + Must(requestId != 0); + + if (msg.hasMoreData()) { + String actionName; + msg.getString(actionName); + action = CacheManager::GetInstance()->createNamedAction(actionName.termedBuf()); + Must(hasAction()); + action->unpack(msg); + } +} + +void +Mgr::Response::pack(Ipc::TypedMsgHdr& msg) const +{ + Must(requestId != 0); + msg.setType(Ipc::mtCacheMgrResponse); + msg.putPod(requestId); + if (hasAction()) { + msg.putString(action->name()); + action->pack(msg); + } +} + +bool +Mgr::Response::hasAction() const +{ + return action != NULL; +} + +const Mgr::Action& +Mgr::Response::getAction() const +{ + Must(hasAction()); + return *action; +} diff --git a/src/mgr/Response.h b/src/mgr/Response.h new file mode 100644 index 0000000000..7b759926eb --- /dev/null +++ b/src/mgr/Response.h @@ -0,0 +1,38 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_RESPONSE_H +#define SQUID_MGR_RESPONSE_H + +#include "mgr/Action.h" + + +namespace Mgr +{ + +/// A response to Mgr::Request. +/// May carry strand action data to be aggregated with data from other strands. +class Response +{ +public: + Response(unsigned int aRequestId = 0, Action::Pointer anAction = NULL); + + explicit Response(const Ipc::TypedMsgHdr& msg); ///< from recvmsg() + void pack(Ipc::TypedMsgHdr& msg) const; ///< prepare for sendmsg() + bool hasAction() const; ///< whether response contain action object + const Action& getAction() const; ///< returns action object + +public: + unsigned int requestId; ///< ID of request we are responding to + Action::Pointer action; ///< action relating to response +}; + +extern std::ostream& operator <<(std::ostream &os, const Response &response); + +} // namespace Mgr + +#endif /* SQUID_MGR_RESPONSE_H */ diff --git a/src/mgr/ServiceTimesAction.cc b/src/mgr/ServiceTimesAction.cc new file mode 100644 index 0000000000..3c083c37cf --- /dev/null +++ b/src/mgr/ServiceTimesAction.cc @@ -0,0 +1,100 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "ipc/Messages.h" +#include "ipc/TypedMsgHdr.h" +#include "mgr/ServiceTimesAction.h" +#include "Store.h" + + +extern void GetServiceTimesStats(Mgr::ServiceTimesActionData& stats); +extern void DumpServiceTimesStats(Mgr::ServiceTimesActionData& stats, StoreEntry* sentry); + +Mgr::ServiceTimesActionData::ServiceTimesActionData() +{ + xmemset(this, 0, sizeof(*this)); +} + +Mgr::ServiceTimesActionData& +Mgr::ServiceTimesActionData::operator += (const ServiceTimesActionData& stats) +{ + for (int i = 0; i < seriesSize; ++i) { + http_requests5[i] += stats.http_requests5[i]; + http_requests60[i] += stats.http_requests60[i]; + + cache_misses5[i] += stats.cache_misses5[i]; + cache_misses60[i] += stats.cache_misses60[i]; + + cache_hits5[i] += stats.cache_hits5[i]; + cache_hits60[i] += stats.cache_hits60[i]; + + near_hits5[i] += stats.near_hits5[i]; + near_hits60[i] += stats.near_hits60[i]; + + not_modified_replies5[i] += stats.not_modified_replies5[i]; + not_modified_replies60[i] += stats.not_modified_replies60[i]; + + dns_lookups5[i] += stats.dns_lookups5[i]; + dns_lookups60[i] += stats.dns_lookups60[i]; + + icp_queries5[i] += stats.icp_queries5[i]; + icp_queries60[i] += stats.icp_queries60[i]; + } + ++count; + + return *this; +} + +Mgr::ServiceTimesAction::Pointer +Mgr::ServiceTimesAction::Create(const CommandPointer &cmd) +{ + return new ServiceTimesAction(cmd); +} + +Mgr::ServiceTimesAction::ServiceTimesAction(const CommandPointer &cmd): + Action(cmd), data() +{ + debugs(16, 5, HERE); +} + +void +Mgr::ServiceTimesAction::add(const Action& action) +{ + debugs(16, 5, HERE); + data += dynamic_cast(action).data; +} + +void +Mgr::ServiceTimesAction::collect() +{ + debugs(16, 5, HERE); + GetServiceTimesStats(data); +} + +void +Mgr::ServiceTimesAction::dump(StoreEntry* entry) +{ + debugs(16, 5, HERE); + Must(entry != NULL); + DumpServiceTimesStats(data, entry); +} + +void +Mgr::ServiceTimesAction::pack(Ipc::TypedMsgHdr& msg) const +{ + msg.setType(Ipc::mtCacheMgrResponse); + msg.putPod(data); +} + +void +Mgr::ServiceTimesAction::unpack(const Ipc::TypedMsgHdr& msg) +{ + msg.checkType(Ipc::mtCacheMgrResponse); + msg.getPod(data); +} diff --git a/src/mgr/ServiceTimesAction.h b/src/mgr/ServiceTimesAction.h new file mode 100644 index 0000000000..f8191a38b6 --- /dev/null +++ b/src/mgr/ServiceTimesAction.h @@ -0,0 +1,69 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_SERVICE_TIMES_ACTION_H +#define SQUID_MGR_SERVICE_TIMES_ACTION_H + +#include "mgr/Action.h" + + +namespace Mgr +{ + +/// store service times for 5 and 60 min +class ServiceTimesActionData +{ +public: + enum { seriesSize = 19 }; + +public: + ServiceTimesActionData(); + ServiceTimesActionData& operator += (const ServiceTimesActionData& stats); + +public: + double http_requests5[seriesSize]; + double http_requests60[seriesSize]; + double cache_misses5[seriesSize]; + double cache_misses60[seriesSize]; + double cache_hits5[seriesSize]; + double cache_hits60[seriesSize]; + double near_hits5[seriesSize]; + double near_hits60[seriesSize]; + double not_modified_replies5[seriesSize]; + double not_modified_replies60[seriesSize]; + double dns_lookups5[seriesSize]; + double dns_lookups60[seriesSize]; + double icp_queries5[seriesSize]; + double icp_queries60[seriesSize]; + unsigned int count; +}; + +/// implement aggregated 'service_times' action +class ServiceTimesAction: public Action +{ +protected: + ServiceTimesAction(const CommandPointer &cmd); + +public: + static Pointer Create(const CommandPointer &cmd); + /* Action API */ + virtual void add(const Action& action); + virtual void pack(Ipc::TypedMsgHdr& msg) const; + virtual void unpack(const Ipc::TypedMsgHdr& msg); + +protected: + /* Action API */ + virtual void collect(); + virtual void dump(StoreEntry* entry); + +private: + ServiceTimesActionData data; +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_SERVICE_TIMES_ACTION_H */ diff --git a/src/mgr/StoreIoAction.cc b/src/mgr/StoreIoAction.cc new file mode 100644 index 0000000000..41866c49e8 --- /dev/null +++ b/src/mgr/StoreIoAction.cc @@ -0,0 +1,84 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "ipc/Messages.h" +#include "ipc/TypedMsgHdr.h" +#include "mgr/StoreIoAction.h" +#include "Store.h" + + +Mgr::StoreIoActionData::StoreIoActionData() +{ + xmemset(this, 0, sizeof(*this)); +} + +Mgr::StoreIoActionData& +Mgr::StoreIoActionData::operator += (const StoreIoActionData& stats) +{ + create_calls += stats.create_calls; + create_select_fail += stats.create_select_fail; + create_create_fail += stats.create_create_fail; + create_success += stats.create_success; + + return *this; +} + +Mgr::StoreIoAction::Pointer +Mgr::StoreIoAction::Create(const CommandPointer &cmd) +{ + return new StoreIoAction(cmd); +} + +Mgr::StoreIoAction::StoreIoAction(const CommandPointer &cmd): + Action(cmd), data() +{ + debugs(16, 5, HERE); +} + +void +Mgr::StoreIoAction::add(const Action& action) +{ + debugs(16, 5, HERE); + data += dynamic_cast(action).data; +} + +void +Mgr::StoreIoAction::collect() +{ + data.create_calls = store_io_stats.create.calls; + data.create_select_fail = store_io_stats.create.select_fail; + data.create_create_fail = store_io_stats.create.create_fail; + data.create_success = store_io_stats.create.success; +} + +void +Mgr::StoreIoAction::dump(StoreEntry* entry) +{ + debugs(16, 5, HERE); + Must(entry != NULL); + storeAppendPrintf(entry, "Store IO Interface Stats\n"); + storeAppendPrintf(entry, "create.calls %.0f\n", data.create_calls); + storeAppendPrintf(entry, "create.select_fail %.0f\n", data.create_select_fail); + storeAppendPrintf(entry, "create.create_fail %.0f\n", data.create_create_fail); + storeAppendPrintf(entry, "create.success %.0f\n", data.create_success); +} + +void +Mgr::StoreIoAction::pack(Ipc::TypedMsgHdr& msg) const +{ + msg.setType(Ipc::mtCacheMgrResponse); + msg.putPod(data); +} + +void +Mgr::StoreIoAction::unpack(const Ipc::TypedMsgHdr& msg) +{ + msg.checkType(Ipc::mtCacheMgrResponse); + msg.getPod(data); +} diff --git a/src/mgr/StoreIoAction.h b/src/mgr/StoreIoAction.h new file mode 100644 index 0000000000..c9c2db46f1 --- /dev/null +++ b/src/mgr/StoreIoAction.h @@ -0,0 +1,55 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_STORE_IO_ACTION_H +#define SQUID_MGR_STORE_IO_ACTION_H + +#include "mgr/Action.h" + + +namespace Mgr +{ + +/// Store IO interface data +class StoreIoActionData +{ +public: + StoreIoActionData(); + StoreIoActionData& operator += (const StoreIoActionData& stats); + +public: + double create_calls; + double create_select_fail; + double create_create_fail; + double create_success; +}; + +/// implement aggregated 'store_io' action +class StoreIoAction: public Action +{ +protected: + StoreIoAction(const CommandPointer &cmd); + +public: + static Pointer Create(const CommandPointer &cmd); + /* Action API */ + virtual void add(const Action& action); + virtual void pack(Ipc::TypedMsgHdr& msg) const; + virtual void unpack(const Ipc::TypedMsgHdr& msg); + +protected: + /* Action API */ + virtual void collect(); + virtual void dump(StoreEntry* entry); + +private: + StoreIoActionData data; +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_STORE_IO_ACTION_H */ diff --git a/src/mgr/StoreToCommWriter.cc b/src/mgr/StoreToCommWriter.cc new file mode 100644 index 0000000000..b659f40b6f --- /dev/null +++ b/src/mgr/StoreToCommWriter.cc @@ -0,0 +1,187 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "CommCalls.h" +#include "ipc/FdNotes.h" +#include "mgr/StoreToCommWriter.h" +#include "StoreClient.h" +#include "Store.h" + + +CBDATA_NAMESPACED_CLASS_INIT(Mgr, StoreToCommWriter); + + +Mgr::StoreToCommWriter::StoreToCommWriter(int aFd, StoreEntry* anEntry): + AsyncJob("Mgr::StoreToCommWriter"), + fd(aFd), entry(anEntry), sc(NULL), writeOffset(0), closer(NULL) +{ + debugs(16, 6, HERE << "FD " << fd); + closer = asyncCall(16, 5, "Mgr::StoreToCommWriter::noteCommClosed", + CommCbMemFunT(this, &StoreToCommWriter::noteCommClosed)); + comm_add_close_handler(fd, closer); +} + +Mgr::StoreToCommWriter::~StoreToCommWriter() +{ + debugs(16, 6, HERE); + assert(!entry); + assert(!sc); + close(); +} + +/// closes our copy of the client HTTP connection socket +void +Mgr::StoreToCommWriter::close() +{ + if (fd >= 0) { + if (closer != NULL) { + comm_remove_close_handler(fd, closer); + closer = NULL; + } + comm_close(fd); + fd = -1; + } +} + +void +Mgr::StoreToCommWriter::start() +{ + debugs(16, 6, HERE); + Must(fd >= 0); + Must(entry != NULL); + entry->registerAbort(&StoreToCommWriter::Abort, this); + sc = storeClientListAdd(entry, this); + Must(sc != NULL); + + // initiate the receive-from-store, write-to-comm sequence + scheduleStoreCopy(); +} + +void +Mgr::StoreToCommWriter::scheduleStoreCopy() +{ + debugs(16, 6, HERE); + Must(entry != NULL); + Must(sc != NULL); + StoreIOBuffer readBuf(sizeof(buffer), writeOffset, buffer); + storeClientCopy(sc, entry, readBuf, &NoteStoreCopied, this); +} + +void +Mgr::StoreToCommWriter::NoteStoreCopied(void* data, StoreIOBuffer ioBuf) +{ + Must(data != NULL); + // make sync Store call async to get async call protections and features + StoreToCommWriter* writer = static_cast(data); + typedef UnaryMemFunT MyDialer; + AsyncCall::Pointer call = + asyncCall(16, 5, "Mgr::StoreToCommWriter::noteStoreCopied", + MyDialer(writer, &StoreToCommWriter::noteStoreCopied, ioBuf)); + ScheduleCallHere(call); +} + +void +Mgr::StoreToCommWriter::noteStoreCopied(StoreIOBuffer ioBuf) +{ + debugs(16, 6, HERE); + Must(!ioBuf.flags.error); + if (ioBuf.length > 0) + scheduleCommWrite(ioBuf); // write received action results to client + else + Must(doneAll()); // otherwise, why would Store call us with no data? +} + +void +Mgr::StoreToCommWriter::scheduleCommWrite(const StoreIOBuffer& ioBuf) +{ + debugs(16, 6, HERE); + Must(fd >= 0); + Must(ioBuf.data != NULL); + // write filled buffer + typedef CommCbMemFunT MyDialer; + AsyncCall::Pointer writer = + asyncCall(16, 5, "Mgr::StoreToCommWriter::noteCommWrote", + MyDialer(this, &StoreToCommWriter::noteCommWrote)); + comm_write(fd, ioBuf.data, ioBuf.length, writer); +} + +void +Mgr::StoreToCommWriter::noteCommWrote(const CommIoCbParams& params) +{ + debugs(16, 6, HERE); + Must(params.flag == COMM_OK); + Must(params.fd == fd); + Must(params.size != 0); + writeOffset += params.size; + if (!doneAll()) + scheduleStoreCopy(); // retrieve the next data portion +} + +void +Mgr::StoreToCommWriter::noteCommClosed(const CommCloseCbParams& params) +{ + debugs(16, 6, HERE); + Must(fd == params.fd); + fd = -1; + mustStop("commClosed"); +} + +void +Mgr::StoreToCommWriter::swanSong() +{ + debugs(16, 6, HERE); + if (entry != NULL) { + if (sc != NULL) { + storeUnregister(sc, entry, this); + sc = NULL; + } + entry->unregisterAbort(); + entry->unlock(); + entry = NULL; + } + close(); +} + +bool +Mgr::StoreToCommWriter::doneAll() const +{ + return entry && + entry->store_status == STORE_OK && // the action is over + writeOffset >= entry->objectLen(); // we wrote all the results +} + +void +Mgr::StoreToCommWriter::Abort(void* param) +{ + StoreToCommWriter* mgrWriter = static_cast(param); + if (mgrWriter->fd >= 0) + comm_close(mgrWriter->fd); +} + + +int +Mgr::ImportHttpFdIntoComm(int fd) +{ + struct sockaddr_in addr; + socklen_t len = sizeof(addr); + if (getsockname(fd, reinterpret_cast(&addr), &len) == 0) { + Ip::Address ipAddr(addr); + struct addrinfo* addr_info = NULL; + ipAddr.GetAddrInfo(addr_info); + addr_info->ai_socktype = SOCK_STREAM; + addr_info->ai_protocol = IPPROTO_TCP; + comm_import_opened(fd, ipAddr, COMM_NONBLOCKING, Ipc::FdNote(Ipc::fdnHttpSocket), addr_info); + ipAddr.FreeAddrInfo(addr_info); + } else { + debugs(16, DBG_CRITICAL, HERE << "ERROR: FD " << fd << ' ' << xstrerror()); + ::close(fd); + fd = -1; + } + return fd; +} diff --git a/src/mgr/StoreToCommWriter.h b/src/mgr/StoreToCommWriter.h new file mode 100644 index 0000000000..116ffdba51 --- /dev/null +++ b/src/mgr/StoreToCommWriter.h @@ -0,0 +1,73 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_STORE_TO_COMM_WRITER_H +#define SQUID_MGR_STORE_TO_COMM_WRITER_H + +#include "base/AsyncJob.h" +#include "mgr/Action.h" +#include "StoreIOBuffer.h" + + +class store_client; +class CommIoCbParams; +class CommCloseCbParams; + +namespace Mgr +{ + +/// manages receive-from-store, write-to-comm, receive-... sequence +/// for the given StoreEntry and client FD +class StoreToCommWriter: public AsyncJob +{ +public: + StoreToCommWriter(int aFd, StoreEntry *anEntry); + virtual ~StoreToCommWriter(); + +protected: + /* AsyncJob API */ + virtual void start(); + virtual void swanSong(); + virtual bool doneAll() const; + + /// request more action results from the store + void scheduleStoreCopy(); + /// receive some action results from the store + void noteStoreCopied(StoreIOBuffer ioBuf); + static void NoteStoreCopied(void* data, StoreIOBuffer ioBuf); + /// called by Store if the entry is no longer usable + static void Abort(void* param); + + /// tell Comm to write action results + void scheduleCommWrite(const StoreIOBuffer& ioBuf); + /// called by Comm after the action results are written + void noteCommWrote(const CommIoCbParams& params); + /// called by Comm if the client socket got closed + void noteCommClosed(const CommCloseCbParams& params); + + /// closes the local connection to the HTTP client, if any + void close(); + +protected: + int fd; ///< HTTP client descriptor + + StoreEntry* entry; ///< store entry with the cache manager response + store_client* sc; ///< our registration with the store + int64_t writeOffset; ///< number of bytes written to the client + + AsyncCall::Pointer closer; ///< comm_close handler + char buffer[HTTP_REQBUF_SZ]; ///< action results; Store fills, Comm writes + + CBDATA_CLASS2(StoreToCommWriter); +}; + +/// import HTTP socket fd from another strand into our Comm state +extern int ImportHttpFdIntoComm(int fd); + +} // namespace Mgr + +#endif /* SQUID_MGR_STORE_TO_COMM_WRITER_H */ diff --git a/src/mgr/forward.h b/src/mgr/forward.h new file mode 100644 index 0000000000..ecf303a948 --- /dev/null +++ b/src/mgr/forward.h @@ -0,0 +1,33 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_FORWARD_H +#define SQUID_MGR_FORWARD_H + +#include "RefCount.h" + +namespace Mgr +{ + +class Action; +class ActionCreator; +class ActionProfile; +class ActionWriter; +class Command; +class Request; +class Response; + +typedef RefCount ActionPointer; +typedef RefCount ActionProfilePointer; +typedef RefCount ActionCreatorPointer; +typedef RefCount CommandPointer; + +typedef ActionPointer (ClassActionCreationHandler)(const CommandPointer &cmd); + +} // namespace Mgr + +#endif /* SQUID_MGR_FORWARD_H */ diff --git a/src/neighbors.cc b/src/neighbors.cc index 0a636a8ca1..55e8ab7725 100644 --- a/src/neighbors.cc +++ b/src/neighbors.cc @@ -34,7 +34,6 @@ #include "ProtoPort.h" #include "acl/FilledChecklist.h" #include "event.h" -#include "CacheManager.h" #include "htcp.h" #include "HttpRequest.h" #include "ICP.h" @@ -48,6 +47,7 @@ #include "icmp/net_db.h" #include "ip/Address.h" #include "ip/tools.h" +#include "mgr/Registration.h" /* count mcast group peers every 15 minutes */ #define MCAST_COUNT_RATE 900 @@ -541,13 +541,12 @@ neighborRemove(peer * target) static void neighborsRegisterWithCacheManager() { - CacheManager *manager = CacheManager::GetInstance(); - manager->registerAction("server_list", + Mgr::RegisterAction("server_list", "Peer Cache Statistics", neighborDumpPeers, 0, 1); if (theInIcpConnection >= 0) { - manager->registerAction("non_peers", + Mgr::RegisterAction("non_peers", "List of Unknown sites sending ICP messages", neighborDumpNonPeers, 0, 1); } diff --git a/src/pconn.cc b/src/pconn.cc index 414b9c1d4e..d024c38331 100644 --- a/src/pconn.cc +++ b/src/pconn.cc @@ -33,7 +33,7 @@ */ #include "squid.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "Store.h" #include "comm.h" #include "pconn.h" @@ -361,8 +361,7 @@ PconnModule::GetInstance() void PconnModule::registerWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("pconn", + Mgr::RegisterAction("pconn", "Persistent Connection Utilization Histograms", DumpWrapper, 0, 1); } diff --git a/src/peer_sourcehash.cc b/src/peer_sourcehash.cc index fd524acfe4..fb21b321bc 100644 --- a/src/peer_sourcehash.cc +++ b/src/peer_sourcehash.cc @@ -35,9 +35,9 @@ */ #include "squid.h" -#include "CacheManager.h" #include "Store.h" #include "HttpRequest.h" +#include "mgr/Registration.h" #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) @@ -157,8 +157,7 @@ peerSourceHashInit(void) static void peerSourceHashRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("sourcehash", "peer sourcehash information", + Mgr::RegisterAction("sourcehash", "peer sourcehash information", peerSourceHashCachemgr, 0, 1); } diff --git a/src/peer_userhash.cc b/src/peer_userhash.cc index b966336c4a..f189cefdef 100644 --- a/src/peer_userhash.cc +++ b/src/peer_userhash.cc @@ -35,7 +35,7 @@ */ #include "squid.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "Store.h" #include "HttpRequest.h" #include "auth/UserRequest.h" @@ -159,8 +159,7 @@ peerUserHashInit(void) static void peerUserHashRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("userhash", "peer userhash information", peerUserHashCachemgr, + Mgr::RegisterAction("userhash", "peer userhash information", peerUserHashCachemgr, 0, 1); } diff --git a/src/redirect.cc b/src/redirect.cc index 43c884a9bb..999474b535 100644 --- a/src/redirect.cc +++ b/src/redirect.cc @@ -35,7 +35,7 @@ #include "squid.h" #include "auth/UserRequest.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "Store.h" #include "fde.h" #include "client_side_request.h" @@ -179,8 +179,7 @@ redirectStart(ClientHttpRequest * http, RH * handler, void *data) static void redirectRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("redirector", "URL Redirector Stats", redirectStats, 0, 1); + Mgr::RegisterAction("redirector", "URL Redirector Stats", redirectStats, 0, 1); } void diff --git a/src/refresh.cc b/src/refresh.cc index b977e226bd..e4257f812d 100644 --- a/src/refresh.cc +++ b/src/refresh.cc @@ -38,7 +38,7 @@ #endif #include "squid.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "Store.h" #include "MemObject.h" #include "HttpRequest.h" @@ -610,8 +610,7 @@ refreshStats(StoreEntry * sentry) static void refreshRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("refresh", "Refresh Algorithm Statistics", refreshStats, 0, 1); + Mgr::RegisterAction("refresh", "Refresh Algorithm Statistics", refreshStats, 0, 1); } void diff --git a/src/stat.cc b/src/stat.cc index f16f137b29..9527f72000 100644 --- a/src/stat.cc +++ b/src/stat.cc @@ -36,7 +36,7 @@ #include "event.h" #include "StoreClient.h" #include "auth/UserRequest.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "Store.h" #include "HttpRequest.h" #include "MemObject.h" @@ -50,6 +50,12 @@ #include "MemBuf.h" #include "SquidMath.h" #include "SquidTime.h" +#include "mgr/CountersAction.h" +#include "mgr/FunAction.h" +#include "mgr/InfoAction.h" +#include "mgr/IntervalAction.h" +#include "mgr/IoAction.h" +#include "mgr/ServiceTimesAction.h" /* these are included because they expose stats calls */ /* TODO: provide a self registration mechanism for those classes @@ -90,22 +96,29 @@ static void statCountersCopy(StatCounters * dest, const StatCounters * orig); static double statPctileSvc(double, int, int); static void statStoreEntry(MemBuf * mb, StoreEntry * e); static double statCPUUsage(int minutes); -static OBJH stat_io_get; static OBJH stat_objects_get; static OBJH stat_vmobjects_get; #if DEBUG_OPENFD static OBJH statOpenfdObj; #endif static EVH statObjects; -static OBJH info_get; static OBJH statCountersDump; static OBJH statPeerSelect; static OBJH statDigestBlob; -static OBJH statAvg5min; -static OBJH statAvg60min; static OBJH statUtilization; static OBJH statCountersHistograms; static OBJH statClientRequests; +void GetAvgStat(Mgr::IntervalActionData& stats, int minutes, int hours); +void DumpAvgStat(Mgr::IntervalActionData& stats, StoreEntry* sentry); +void GetInfo(Mgr::InfoActionData& stats); +void DumpInfo(Mgr::InfoActionData& stats, StoreEntry* sentry); +void DumpMallocStatistics(StoreEntry* sentry); +void GetCountersStats(Mgr::CountersActionData& stats); +void DumpCountersStats(Mgr::CountersActionData& stats, StoreEntry* sentry); +void GetServiceTimesStats(Mgr::ServiceTimesActionData& stats); +void DumpServiceTimesStats(Mgr::ServiceTimesActionData& stats, StoreEntry* sentry); +void GetIoStats(Mgr::IoActionData& stats); +void DumpIoStats(Mgr::IoActionData& stats, StoreEntry* sentry); #if XMALLOC_STATISTICS static void info_get_mallstat(int, int, int, void *); @@ -186,47 +199,71 @@ statUtilization(StoreEntry * e) statCountersDump(e); } -static void -stat_io_get(StoreEntry * sentry) +void +GetIoStats(Mgr::IoActionData& stats) +{ + int i; + + stats.http_reads = IOStats.Http.reads; + + for (i = 0; i < _iostats::histSize; i++) { + stats.http_read_hist[i] = IOStats.Http.read_hist[i]; + } + + stats.ftp_reads = IOStats.Ftp.reads; + + for (i = 0; i < _iostats::histSize; i++) { + stats.ftp_read_hist[i] = IOStats.Ftp.read_hist[i]; + } + + stats.gopher_reads = IOStats.Gopher.reads; + + for (i = 0; i < _iostats::histSize; i++) { + stats.gopher_read_hist[i] = IOStats.Gopher.read_hist[i]; + } +} + +void +DumpIoStats(Mgr::IoActionData& stats, StoreEntry* sentry) { int i; storeAppendPrintf(sentry, "HTTP I/O\n"); - storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Http.reads); + storeAppendPrintf(sentry, "number of reads: %.0f\n", stats.http_reads); storeAppendPrintf(sentry, "Read Histogram:\n"); - for (i = 0; i < 16; i++) { - storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n", - i ? (1 << (i - 1)) + 1 : 1, - 1 << i, - IOStats.Http.read_hist[i], - Math::intPercent(IOStats.Http.read_hist[i], IOStats.Http.reads)); + for (i = 0; i < _iostats::histSize; i++) { + storeAppendPrintf(sentry, "%5d-%5d: %9.0f %2.0f%%\n", + i ? (1 << (i - 1)) + 1 : 1, + 1 << i, + stats.http_read_hist[i], + Math::doublePercent(stats.http_read_hist[i], stats.http_reads)); } storeAppendPrintf(sentry, "\n"); storeAppendPrintf(sentry, "FTP I/O\n"); - storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Ftp.reads); + storeAppendPrintf(sentry, "number of reads: %.0f\n", stats.ftp_reads); storeAppendPrintf(sentry, "Read Histogram:\n"); - for (i = 0; i < 16; i++) { - storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n", - i ? (1 << (i - 1)) + 1 : 1, - 1 << i, - IOStats.Ftp.read_hist[i], - Math::intPercent(IOStats.Ftp.read_hist[i], IOStats.Ftp.reads)); + for (i = 0; i < _iostats::histSize; i++) { + storeAppendPrintf(sentry, "%5d-%5d: %9.0f %2.0f%%\n", + i ? (1 << (i - 1)) + 1 : 1, + 1 << i, + stats.ftp_read_hist[i], + Math::doublePercent(stats.ftp_read_hist[i], stats.ftp_reads)); } storeAppendPrintf(sentry, "\n"); storeAppendPrintf(sentry, "Gopher I/O\n"); - storeAppendPrintf(sentry, "number of reads: %d\n", IOStats.Gopher.reads); + storeAppendPrintf(sentry, "number of reads: %.0f\n", stats.gopher_reads); storeAppendPrintf(sentry, "Read Histogram:\n"); - for (i = 0; i < 16; i++) { - storeAppendPrintf(sentry, "%5d-%5d: %9d %2d%%\n", - i ? (1 << (i - 1)) + 1 : 1, - 1 << i, - IOStats.Gopher.read_hist[i], - Math::intPercent(IOStats.Gopher.read_hist[i], IOStats.Gopher.reads)); + for (i = 0; i < _iostats::histSize; i++) { + storeAppendPrintf(sentry, "%5d-%5d: %9.0f %2.0f%%\n", + i ? (1 << (i - 1)) + 1 : 1, + 1 << i, + stats.gopher_read_hist[i], + Math::doublePercent(stats.gopher_read_hist[i], stats.gopher_reads)); } storeAppendPrintf(sentry, "\n"); @@ -338,6 +375,8 @@ statObjects(void *data) StoreEntry *e; if (state->theSearch->isDone()) { + if (UsingSmp()) + storeAppendPrintf(state->sentry, "} by kid%d\n\n", KidIdentifier); state->sentry->complete(); state->sentry->unlock(); cbdataFree(state); @@ -438,8 +477,8 @@ info_get_mallstat(int size, int number, int oldnum, void *data) #endif -static void -info_get(StoreEntry * sentry) +void +GetInfo(Mgr::InfoActionData& stats) { struct rusage rusage; @@ -451,7 +490,6 @@ info_get(StoreEntry * sentry) #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO struct mallinfo mp; - long t; #endif runtime = tvSubDsec(squid_start, current_time); @@ -459,6 +497,175 @@ info_get(StoreEntry * sentry) if (runtime == 0.0) runtime = 1.0; + stats.squid_start = squid_start; + + stats.current_time = current_time; + + stats.client_http_clients = statCounter.client_http.clients; + + stats.client_http_requests = statCounter.client_http.requests; + + stats.icp_pkts_recv = statCounter.icp.pkts_recv; + + stats.icp_pkts_sent = statCounter.icp.pkts_sent; + + stats.icp_replies_queued = statCounter.icp.replies_queued; + +#if USE_HTCP + + stats.htcp_pkts_recv = statCounter.htcp.pkts_recv; + + stats.htcp_pkts_sent = statCounter.htcp.pkts_sent; + +#endif + + stats.request_failure_ratio = request_failure_ratio; + + stats.avg_client_http_requests = statCounter.client_http.requests / (runtime / 60.0); + + stats.avg_icp_messages = (statCounter.icp.pkts_sent + statCounter.icp.pkts_recv) / (runtime / 60.0); + + stats.select_loops = statCounter.select_loops; + stats.avg_loop_time = 1000.0 * runtime / statCounter.select_loops; + + stats.request_hit_ratio5 = statRequestHitRatio(5); + stats.request_hit_ratio60 = statRequestHitRatio(60); + + stats.byte_hit_ratio5 = statByteHitRatio(5); + stats.byte_hit_ratio60 = statByteHitRatio(60); + + stats.request_hit_mem_ratio5 = statRequestHitMemoryRatio(5); + stats.request_hit_mem_ratio60 = statRequestHitMemoryRatio(60); + + stats.request_hit_disk_ratio5 = statRequestHitDiskRatio(5); + stats.request_hit_disk_ratio60 = statRequestHitDiskRatio(60); + + stats.store_swap_size = store_swap_size; + stats.store_swap_max_size = Store::Root().maxSize(); + + stats.store_mem_size = mem_node::StoreMemSize(); + stats.store_pages_max = store_pages_max; + stats.store_mem_used = mem_node::InUseCount(); + + stats.objects_size = n_disk_objects ? (double) store_swap_size / n_disk_objects : 0.0; + + stats.unlink_requests = statCounter.unlink.requests; + + stats.http_requests5 = statPctileSvc(0.5, 5, PCTILE_HTTP); + stats.http_requests60 = statPctileSvc(0.5, 60, PCTILE_HTTP); + + stats.cache_misses5 = statPctileSvc(0.5, 5, PCTILE_MISS); + stats.cache_misses60 = statPctileSvc(0.5, 60, PCTILE_MISS); + + stats.cache_hits5 = statPctileSvc(0.5, 5, PCTILE_HIT); + stats.cache_hits60 = statPctileSvc(0.5, 60, PCTILE_HIT); + + stats.near_hits5 = statPctileSvc(0.5, 5, PCTILE_NH); + stats.near_hits60 = statPctileSvc(0.5, 60, PCTILE_NH); + + stats.not_modified_replies5 = statPctileSvc(0.5, 5, PCTILE_NM); + stats.not_modified_replies60 = statPctileSvc(0.5, 60, PCTILE_NM); + + stats.dns_lookups5 = statPctileSvc(0.5, 5, PCTILE_DNS); + stats.dns_lookups60 = statPctileSvc(0.5, 60, PCTILE_DNS); + + stats.icp_queries5 = statPctileSvc(0.5, 5, PCTILE_ICP_QUERY); + stats.icp_queries60 = statPctileSvc(0.5, 60, PCTILE_ICP_QUERY); + + squid_getrusage(&rusage); + cputime = rusage_cputime(&rusage); + + stats.up_time = runtime; + stats.cpu_time = cputime; + stats.cpu_usage = Math::doublePercent(cputime, runtime); + stats.cpu_usage5 = statCPUUsage(5); + stats.cpu_usage60 = statCPUUsage(60); + +#if HAVE_SBRK + + stats.proc_data_seg = ((char *) sbrk(0) - (char *) sbrk_start); + +#endif + + stats.maxrss = rusage_maxrss(&rusage); + + stats.page_faults = rusage_pagefaults(&rusage); + +#if HAVE_MSTATS && HAVE_GNUMALLOC_H + + ms = mstats(); + + stats.ms_bytes_total = ms.bytes_total; + + stats.ms_bytes_free = ms.bytes_free; + +#elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO + + mp = mallinfo(); + + stats.mp_arena = mp.arena; + + stats.mp_uordblks = mp.uordblks; + stats.mp_ordblks = mp.ordblks; + + stats.mp_usmblks = mp.usmblks; + stats.mp_smblks = mp.smblks; + + stats.mp_hblkhd = mp.hblkhd; + stats.mp_hblks = mp.hblks; + + stats.mp_fsmblks = mp.fsmblks; + + stats.mp_fordblks = mp.fordblks; + +#if HAVE_STRUCT_MALLINFO_MXFAST + + stats.mp_mxfast = mp.mxfast; + + stats.mp_nlblks = mp.nlblks; + + stats.mp_grain = mp.grain; + + stats.mp_uordbytes = mp.uordbytes; + + stats.mp_allocated = mp.allocated; + + stats.mp_treeoverhead = mp.treeoverhead; + +#endif /* HAVE_STRUCT_MALLINFO_MXFAST */ +#endif /* HAVE_MALLINFO */ + + stats.total_accounted = statMemoryAccounted(); + + { + MemPoolGlobalStats mp_stats; + memPoolGetGlobalStats(&mp_stats); +#if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO + + stats.mem_pool_allocated = mp_stats.TheMeter->alloc.level; +#endif + + stats.gb_freed_count = mp_stats.TheMeter->gb_saved.count; + stats.gb_freed_count = mp_stats.TheMeter->gb_freed.count; + } + + stats.max_fd = Squid_MaxFD; + stats.biggest_fd = Biggest_FD; + stats.number_fd = Number_FD; + stats.opening_fd = Opening_FD; + stats.num_fd_free = fdNFree(); + stats.reserved_fd = RESERVED_FD; + stats.store_open_disk_fd = store_open_disk_fd; + + stats.store_entries = StoreEntry::inUseCount(); + stats.store_mem_entries = MemObject::inUseCount(); + stats.hot_obj_count = hot_obj_count; + stats.n_disk_objects = n_disk_objects; +} + +void +DumpInfo(Mgr::InfoActionData& stats, StoreEntry* sentry) +{ storeAppendPrintf(sentry, "Squid Object Cache: Version %s\n", version_string); @@ -474,222 +681,215 @@ info_get(StoreEntry * sentry) #endif storeAppendPrintf(sentry, "Start Time:\t%s\n", - mkrfc1123(squid_start.tv_sec)); + mkrfc1123(stats.squid_start.tv_sec)); storeAppendPrintf(sentry, "Current Time:\t%s\n", - mkrfc1123(current_time.tv_sec)); + mkrfc1123(stats.current_time.tv_sec)); storeAppendPrintf(sentry, "Connection information for %s:\n",APP_SHORTNAME); - storeAppendPrintf(sentry, "\tNumber of clients accessing cache:\t%u\n", - statCounter.client_http.clients); + storeAppendPrintf(sentry, "\tNumber of clients accessing cache:\t%.0f\n", + stats.client_http_clients); - storeAppendPrintf(sentry, "\tNumber of HTTP requests received:\t%u\n", - statCounter.client_http.requests); + storeAppendPrintf(sentry, "\tNumber of HTTP requests received:\t%.0f\n", + stats.client_http_requests); - storeAppendPrintf(sentry, "\tNumber of ICP messages received:\t%u\n", - statCounter.icp.pkts_recv); + storeAppendPrintf(sentry, "\tNumber of ICP messages received:\t%.0f\n", + stats.icp_pkts_recv); - storeAppendPrintf(sentry, "\tNumber of ICP messages sent:\t%u\n", - statCounter.icp.pkts_sent); + storeAppendPrintf(sentry, "\tNumber of ICP messages sent:\t%.0f\n", + stats.icp_pkts_sent); - storeAppendPrintf(sentry, "\tNumber of queued ICP replies:\t%u\n", - statCounter.icp.replies_queued); + storeAppendPrintf(sentry, "\tNumber of queued ICP replies:\t%.0f\n", + stats.icp_replies_queued); #if USE_HTCP - storeAppendPrintf(sentry, "\tNumber of HTCP messages received:\t%u\n", - statCounter.htcp.pkts_recv); + storeAppendPrintf(sentry, "\tNumber of HTCP messages received:\t%.0f\n", + stats.htcp_pkts_recv); - storeAppendPrintf(sentry, "\tNumber of HTCP messages sent:\t%u\n", - statCounter.htcp.pkts_sent); + storeAppendPrintf(sentry, "\tNumber of HTCP messages sent:\t%.0f\n", + stats.htcp_pkts_sent); #endif + double fct = stats.count > 1 ? stats.count : 1.0; storeAppendPrintf(sentry, "\tRequest failure ratio:\t%5.2f\n", - request_failure_ratio); + stats.request_failure_ratio / fct); storeAppendPrintf(sentry, "\tAverage HTTP requests per minute since start:\t%.1f\n", - statCounter.client_http.requests / (runtime / 60.0)); + stats.avg_client_http_requests / fct); storeAppendPrintf(sentry, "\tAverage ICP messages per minute since start:\t%.1f\n", - (statCounter.icp.pkts_sent + statCounter.icp.pkts_recv) / (runtime / 60.0)); + stats.avg_icp_messages / fct); - storeAppendPrintf(sentry, "\tSelect loop called: %ld times, %0.3f ms avg\n", - statCounter.select_loops, 1000.0 * runtime / statCounter.select_loops); + storeAppendPrintf(sentry, "\tSelect loop called: %.0f times, %0.3f ms avg\n", + stats.select_loops, stats.avg_loop_time / fct); storeAppendPrintf(sentry, "Cache information for %s:\n",APP_SHORTNAME); storeAppendPrintf(sentry, "\tHits as %% of all requests:\t5min: %3.1f%%, 60min: %3.1f%%\n", - statRequestHitRatio(5), - statRequestHitRatio(60)); + stats.request_hit_ratio5 / fct, + stats.request_hit_ratio60 / fct); storeAppendPrintf(sentry, "\tHits as %% of bytes sent:\t5min: %3.1f%%, 60min: %3.1f%%\n", - statByteHitRatio(5), - statByteHitRatio(60)); + stats.byte_hit_ratio5 / fct, + stats.byte_hit_ratio60 / fct); storeAppendPrintf(sentry, "\tMemory hits as %% of hit requests:\t5min: %3.1f%%, 60min: %3.1f%%\n", - statRequestHitMemoryRatio(5), - statRequestHitMemoryRatio(60)); + stats.request_hit_mem_ratio5 / fct, + stats.request_hit_mem_ratio60 / fct); storeAppendPrintf(sentry, "\tDisk hits as %% of hit requests:\t5min: %3.1f%%, 60min: %3.1f%%\n", - statRequestHitDiskRatio(5), - statRequestHitDiskRatio(60)); + stats.request_hit_disk_ratio5 / fct, + stats.request_hit_disk_ratio60 / fct); - storeAppendPrintf(sentry, "\tStorage Swap size:\t%lu KB\n", - store_swap_size); + storeAppendPrintf(sentry, "\tStorage Swap size:\t%.0f KB\n", + stats.store_swap_size / 1024); storeAppendPrintf(sentry, "\tStorage Swap capacity:\t%4.1f%% used, %4.1f%% free\n", - Math::doublePercent(store_swap_size, Store::Root().maxSize()), - Math::doublePercent((Store::Root().maxSize() - store_swap_size), Store::Root().maxSize())); - + Math::doublePercent(stats.store_swap_size, stats.store_swap_max_size), + Math::doublePercent(stats.store_swap_max_size - stats.store_swap_size, stats.store_swap_max_size)); - storeAppendPrintf(sentry, "\tStorage Mem size:\t%lu KB\n", - (unsigned long)(mem_node::StoreMemSize() >> 10)); + storeAppendPrintf(sentry, "\tStorage Mem size:\t%.0f KB\n", + stats.store_mem_size / 1024); - double mFree = 0.0; - if (mem_node::InUseCount() <= store_pages_max) - mFree = Math::doublePercent((store_pages_max - mem_node::InUseCount()), store_pages_max); + const double mFree = max(0.0, stats.store_pages_max-stats.store_mem_used); storeAppendPrintf(sentry, "\tStorage Mem capacity:\t%4.1f%% used, %4.1f%% free\n", - Math::doublePercent(mem_node::InUseCount(), store_pages_max), - mFree); + Math::doublePercent(stats.store_mem_used, stats.store_pages_max), + Math::doublePercent(mFree, stats.store_pages_max)); storeAppendPrintf(sentry, "\tMean Object Size:\t%0.2f KB\n", - n_disk_objects ? (double) store_swap_size / n_disk_objects : 0.0); + stats.objects_size / fct); - storeAppendPrintf(sentry, "\tRequests given to unlinkd:\t%ld\n", - (long)statCounter.unlink.requests); + storeAppendPrintf(sentry, "\tRequests given to unlinkd:\t%.0f\n", + stats.unlink_requests); storeAppendPrintf(sentry, "Median Service Times (seconds) 5 min 60 min:\n"); + fct = stats.count > 1 ? stats.count * 1000.0 : 1000.0; storeAppendPrintf(sentry, "\tHTTP Requests (All): %8.5f %8.5f\n", - statPctileSvc(0.5, 5, PCTILE_HTTP) / 1000.0, - statPctileSvc(0.5, 60, PCTILE_HTTP) / 1000.0); + stats.http_requests5 / fct, + stats.http_requests60 / fct); storeAppendPrintf(sentry, "\tCache Misses: %8.5f %8.5f\n", - statPctileSvc(0.5, 5, PCTILE_MISS) / 1000.0, - statPctileSvc(0.5, 60, PCTILE_MISS) / 1000.0); + stats.cache_misses5 / fct, + stats.cache_misses60 / fct); storeAppendPrintf(sentry, "\tCache Hits: %8.5f %8.5f\n", - statPctileSvc(0.5, 5, PCTILE_HIT) / 1000.0, - statPctileSvc(0.5, 60, PCTILE_HIT) / 1000.0); + stats.cache_hits5 / fct, + stats.cache_hits60 / fct); storeAppendPrintf(sentry, "\tNear Hits: %8.5f %8.5f\n", - statPctileSvc(0.5, 5, PCTILE_NH) / 1000.0, - statPctileSvc(0.5, 60, PCTILE_NH) / 1000.0); + stats.near_hits5 / fct, + stats.near_hits60 / fct); storeAppendPrintf(sentry, "\tNot-Modified Replies: %8.5f %8.5f\n", - statPctileSvc(0.5, 5, PCTILE_NM) / 1000.0, - statPctileSvc(0.5, 60, PCTILE_NM) / 1000.0); + stats.not_modified_replies5 / fct, + stats.not_modified_replies60 / fct); storeAppendPrintf(sentry, "\tDNS Lookups: %8.5f %8.5f\n", - statPctileSvc(0.5, 5, PCTILE_DNS) / 1000.0, - statPctileSvc(0.5, 60, PCTILE_DNS) / 1000.0); + stats.dns_lookups5 / fct, + stats.dns_lookups60 / fct); + fct = stats.count > 1 ? stats.count * 1000000.0 : 1000000.0; storeAppendPrintf(sentry, "\tICP Queries: %8.5f %8.5f\n", - statPctileSvc(0.5, 5, PCTILE_ICP_QUERY) / 1000000.0, - statPctileSvc(0.5, 60, PCTILE_ICP_QUERY) / 1000000.0); - - squid_getrusage(&rusage); - - cputime = rusage_cputime(&rusage); + stats.icp_queries5 / fct, + stats.icp_queries60 / fct); storeAppendPrintf(sentry, "Resource usage for %s:\n", APP_SHORTNAME); - storeAppendPrintf(sentry, "\tUP Time:\t%.3f seconds\n", runtime); + storeAppendPrintf(sentry, "\tUP Time:\t%.3f seconds\n", stats.up_time); - storeAppendPrintf(sentry, "\tCPU Time:\t%.3f seconds\n", cputime); + storeAppendPrintf(sentry, "\tCPU Time:\t%.3f seconds\n", stats.cpu_time); storeAppendPrintf(sentry, "\tCPU Usage:\t%.2f%%\n", - Math::doublePercent(cputime, runtime)); + stats.cpu_usage); storeAppendPrintf(sentry, "\tCPU Usage, 5 minute avg:\t%.2f%%\n", - statCPUUsage(5)); + stats.cpu_usage5); storeAppendPrintf(sentry, "\tCPU Usage, 60 minute avg:\t%.2f%%\n", - statCPUUsage(60)); + stats.cpu_usage60); #if HAVE_SBRK - storeAppendPrintf(sentry, "\tProcess Data Segment Size via sbrk(): %lu KB\n", - (unsigned long) (((char *) sbrk(0) - (char *) sbrk_start) >> 10)); + storeAppendPrintf(sentry, "\tProcess Data Segment Size via sbrk(): %.0f KB\n", + stats.proc_data_seg / 1024); #endif - storeAppendPrintf(sentry, "\tMaximum Resident Size: %ld KB\n", - (long)rusage_maxrss(&rusage)); + storeAppendPrintf(sentry, "\tMaximum Resident Size: %.0f KB\n", + stats.maxrss); - storeAppendPrintf(sentry, "\tPage faults with physical i/o: %ld\n", - (long)rusage_pagefaults(&rusage)); + storeAppendPrintf(sentry, "\tPage faults with physical i/o: %.0f\n", + stats.page_faults); #if HAVE_MSTATS && HAVE_GNUMALLOC_H - ms = mstats(); - storeAppendPrintf(sentry, "Memory usage for %s via mstats():\n",APP_SHORTNAME); - storeAppendPrintf(sentry, "\tTotal space in arena: %6ld KB\n", - (long)(ms.bytes_total >> 10)); + storeAppendPrintf(sentry, "\tTotal space in arena: %6.0f KB\n", + stats.ms_bytes_total / 1024); - storeAppendPrintf(sentry, "\tTotal free: %6ld KB %d%%\n", - (long)(ms.bytes_free >> 10), Math::intPercent(ms.bytes_free, ms.bytes_total)); + storeAppendPrintf(sentry, "\tTotal free: %6.0f KB %.0f%%\n", + stats.ms_bytes_free / 1024, + Math::doublePercent(stats.ms_bytes_free, stats.ms_bytes_total)); #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO - mp = mallinfo(); - storeAppendPrintf(sentry, "Memory usage for %s via mallinfo():\n",APP_SHORTNAME); - storeAppendPrintf(sentry, "\tTotal space in arena: %6ld KB\n", - (long)(mp.arena >> 10)); + storeAppendPrintf(sentry, "\tTotal space in arena: %6.0f KB\n", + stats.mp_arena / 1024); - storeAppendPrintf(sentry, "\tOrdinary blocks: %6ld KB %6ld blks\n", - (long)(mp.uordblks >> 10), (long)mp.ordblks); + storeAppendPrintf(sentry, "\tOrdinary blocks: %6.0f KB %6.0f blks\n", + stats.mp_uordblks / 1024, stats.mp_ordblks); - storeAppendPrintf(sentry, "\tSmall blocks: %6ld KB %6ld blks\n", - (long)(mp.usmblks >> 10), (long)mp.smblks); + storeAppendPrintf(sentry, "\tSmall blocks: %6.0f KB %6.0f blks\n", + stats.mp_usmblks / 1024, stats.mp_smblks); - storeAppendPrintf(sentry, "\tHolding blocks: %6ld KB %6ld blks\n", - (long)(mp.hblkhd >> 10), (long)mp.hblks); + storeAppendPrintf(sentry, "\tHolding blocks: %6.0f KB %6.0f blks\n", + stats.mp_hblkhd / 1024, stats.mp_hblks); - storeAppendPrintf(sentry, "\tFree Small blocks: %6ld KB\n", - (long)(mp.fsmblks >> 10)); + storeAppendPrintf(sentry, "\tFree Small blocks: %6.0f KB\n", + stats.mp_fsmblks / 1024); - storeAppendPrintf(sentry, "\tFree Ordinary blocks: %6ld KB\n", - (long)(mp.fordblks >> 10)); + storeAppendPrintf(sentry, "\tFree Ordinary blocks: %6.0f KB\n", + stats.mp_fordblks / 1024); - t = mp.uordblks + mp.usmblks + mp.hblkhd; + double t = stats.mp_fsmblks + stats.mp_fordblks; - storeAppendPrintf(sentry, "\tTotal in use: %6ld KB %d%%\n", - (long)(t >> 10), Math::intPercent(t, mp.arena + mp.hblkhd)); + storeAppendPrintf(sentry, "\tTotal in use: %6.0f KB %.0f%%\n", + t / 1024, Math::doublePercent(t, stats.mp_arena + stats.mp_hblkhd)); - t = mp.fsmblks + mp.fordblks; + t = stats.mp_fsmblks + stats.mp_fordblks; - storeAppendPrintf(sentry, "\tTotal free: %6ld KB %d%%\n", - (long)(t >> 10), Math::intPercent(t, mp.arena + mp.hblkhd)); + storeAppendPrintf(sentry, "\tTotal free: %6.0f KB %.0f%%\n", + t / 1024, Math::doublePercent(t, stats.mp_arena + stats.mp_hblkhd)); - t = mp.arena + mp.hblkhd; + t = stats.mp_arena + stats.mp_hblkhd; - storeAppendPrintf(sentry, "\tTotal size: %6ld KB\n", - (long)(t >> 10)); + storeAppendPrintf(sentry, "\tTotal size: %6.0f KB\n", + t / 1024); #if HAVE_STRUCT_MALLINFO_MXFAST - storeAppendPrintf(sentry, "\tmax size of small blocks:\t%d\n", mp.mxfast); + storeAppendPrintf(sentry, "\tmax size of small blocks:\t%.0f\n", stats.mp_mxfast); - storeAppendPrintf(sentry, "\tnumber of small blocks in a holding block:\t%ld\n", - (long)mp.nlblks); + storeAppendPrintf(sentry, "\tnumber of small blocks in a holding block:\t%.0f\n", + stats.mp_nlblks); - storeAppendPrintf(sentry, "\tsmall block rounding factor:\t%ld\n", (long)mp.grain); + storeAppendPrintf(sentry, "\tsmall block rounding factor:\t%.0f\n", stats.mp_grain); - storeAppendPrintf(sentry, "\tspace (including overhead) allocated in ord. blks:\t%ld\n", - (long)mp.uordbytes); + storeAppendPrintf(sentry, "\tspace (including overhead) allocated in ord. blks:\t%.0f\n" + ,stats.mp_uordbytes); - storeAppendPrintf(sentry, "\tnumber of ordinary blocks allocated:\t%ld\n", - (long)mp.allocated); + storeAppendPrintf(sentry, "\tnumber of ordinary blocks allocated:\t%.0f\n", + stats.mp_allocated); - storeAppendPrintf(sentry, "\tbytes used in maintaining the free tree:\t%ld\n", - (long)mp.treeoverhead); + storeAppendPrintf(sentry, "\tbytes used in maintaining the free tree:\t%.0f\n", + stats.mp_treeoverhead); #endif /* HAVE_STRUCT_MALLINFO_MXFAST */ #endif /* HAVE_MALLINFO */ @@ -698,13 +898,13 @@ info_get(StoreEntry * sentry) #if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO - storeAppendPrintf(sentry, "\tTotal accounted: %6ld KB %3d%%\n", - (long)(statMemoryAccounted() >> 10), Math::intPercent(statMemoryAccounted(), t)); + storeAppendPrintf(sentry, "\tTotal accounted: %6.0f KB %3.0f%%\n", + stats.total_accounted / 1024, Math::doublePercent(stats.total_accounted, t)); #else - storeAppendPrintf(sentry, "\tTotal accounted: %6ld KB\n", - (long)(statMemoryAccounted() >> 10)); + storeAppendPrintf(sentry, "\tTotal accounted: %6.0f KB\n", + stats.total_accounted / 1024); #endif { @@ -712,49 +912,52 @@ info_get(StoreEntry * sentry) memPoolGetGlobalStats(&mp_stats); #if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO - storeAppendPrintf(sentry, "\tmemPool accounted: %6ld KB %3d%%\n", - (long)(mp_stats.TheMeter->alloc.level >> 10), - Math::intPercent(mp_stats.TheMeter->alloc.level, t)); + storeAppendPrintf(sentry, "\tmemPool accounted: %6.0f KB %3.0f%%\n", + stats.mem_pool_allocated / 1024, + Math::doublePercent(stats.mem_pool_allocated, t)); - int iFree = 0; - if (t >= mp_stats.TheMeter->alloc.level) - iFree = Math::intPercent((t - mp_stats.TheMeter->alloc.level), t); - storeAppendPrintf(sentry, "\tmemPool unaccounted: %6ld KB %3d%%\n", - (long)((t - mp_stats.TheMeter->alloc.level) >> 10), iFree); + const double iFree = max(0.0, t - stats.mem_pool_allocated); + storeAppendPrintf(sentry, "\tmemPool unaccounted: %6.0f KB %3.0f%%\n", + (t - stats.mem_pool_allocated) / 1024, + Math::doublePercent(iFree, t)); #endif storeAppendPrintf(sentry, "\tmemPoolAlloc calls: %9.0f\n", - mp_stats.TheMeter->gb_saved.count); + stats.gb_saved_count); storeAppendPrintf(sentry, "\tmemPoolFree calls: %9.0f\n", - mp_stats.TheMeter->gb_freed.count); + stats.gb_freed_count); } storeAppendPrintf(sentry, "File descriptor usage for %s:\n", APP_SHORTNAME); - storeAppendPrintf(sentry, "\tMaximum number of file descriptors: %4d\n", - Squid_MaxFD); - storeAppendPrintf(sentry, "\tLargest file desc currently in use: %4d\n", - Biggest_FD); - storeAppendPrintf(sentry, "\tNumber of file desc currently in use: %4d\n", - Number_FD); - storeAppendPrintf(sentry, "\tFiles queued for open: %4d\n", - Opening_FD); - storeAppendPrintf(sentry, "\tAvailable number of file descriptors: %4d\n", - fdNFree()); - storeAppendPrintf(sentry, "\tReserved number of file descriptors: %4d\n", - RESERVED_FD); - storeAppendPrintf(sentry, "\tStore Disk files open: %4d\n", - store_open_disk_fd); + storeAppendPrintf(sentry, "\tMaximum number of file descriptors: %4.0f\n", + stats.max_fd); + storeAppendPrintf(sentry, "\tLargest file desc currently in use: %4.0f\n", + stats.biggest_fd); + storeAppendPrintf(sentry, "\tNumber of file desc currently in use: %4.0f\n", + stats.number_fd); + storeAppendPrintf(sentry, "\tFiles queued for open: %4.0f\n", + stats.opening_fd); + storeAppendPrintf(sentry, "\tAvailable number of file descriptors: %4.0f\n", + stats.num_fd_free); + storeAppendPrintf(sentry, "\tReserved number of file descriptors: %4.0f\n", + stats.reserved_fd); + storeAppendPrintf(sentry, "\tStore Disk files open: %4.0f\n", + stats.store_open_disk_fd); storeAppendPrintf(sentry, "Internal Data Structures:\n"); - storeAppendPrintf(sentry, "\t%6lu StoreEntries\n", - (unsigned long)StoreEntry::inUseCount()); - storeAppendPrintf(sentry, "\t%6lu StoreEntries with MemObjects\n", - (unsigned long)MemObject::inUseCount()); - storeAppendPrintf(sentry, "\t%6ld Hot Object Cache Items\n", - (long)hot_obj_count); - storeAppendPrintf(sentry, "\t%6ld on-disk objects\n", - (long)n_disk_objects); + storeAppendPrintf(sentry, "\t%6.0f StoreEntries\n", + stats.store_entries); + storeAppendPrintf(sentry, "\t%6.0f StoreEntries with MemObjects\n", + stats.store_mem_entries); + storeAppendPrintf(sentry, "\t%6.0f Hot Object Cache Items\n", + stats.hot_obj_count); + storeAppendPrintf(sentry, "\t%6.0f on-disk objects\n", + stats.n_disk_objects); +} +void +DumpMallocStatistics(StoreEntry* sentry) +{ #if XMALLOC_STATISTICS xm_deltat = current_dtime - xm_time; @@ -765,64 +968,100 @@ info_get(StoreEntry * sentry) #endif } -static void -service_times(StoreEntry * sentry) +void +GetServiceTimesStats(Mgr::ServiceTimesActionData& stats) +{ + for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) { + double p = (i + 1) * 5 / 100.0; + stats.http_requests5[i] = statPctileSvc(p, 5, PCTILE_HTTP); + stats.http_requests60[i] = statPctileSvc(p, 60, PCTILE_HTTP); + + stats.cache_misses5[i] = statPctileSvc(p, 5, PCTILE_MISS); + stats.cache_misses60[i] = statPctileSvc(p, 60, PCTILE_MISS); + + stats.cache_hits5[i] = statPctileSvc(p, 5, PCTILE_HIT); + stats.cache_hits60[i] = statPctileSvc(p, 60, PCTILE_HIT); + + stats.near_hits5[i] = statPctileSvc(p, 5, PCTILE_NH); + stats.near_hits60[i] = statPctileSvc(p, 60, PCTILE_NH); + + stats.not_modified_replies5[i] = statPctileSvc(p, 5, PCTILE_NM); + stats.not_modified_replies60[i] = statPctileSvc(p, 60, PCTILE_NM); + + stats.dns_lookups5[i] = statPctileSvc(p, 5, PCTILE_DNS); + stats.dns_lookups60[i] = statPctileSvc(p, 60, PCTILE_DNS); + + stats.icp_queries5[i] = statPctileSvc(p, 5, PCTILE_ICP_QUERY); + stats.icp_queries60[i] = statPctileSvc(p, 60, PCTILE_ICP_QUERY); + } +} + +void +DumpServiceTimesStats(Mgr::ServiceTimesActionData& stats, StoreEntry* sentry) { - int p; storeAppendPrintf(sentry, "Service Time Percentiles 5 min 60 min:\n"); - for (p = 5; p < 100; p += 5) { + double fct = stats.count > 1 ? stats.count * 1000.0 : 1000.0; + for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) { storeAppendPrintf(sentry, "\tHTTP Requests (All): %2d%% %8.5f %8.5f\n", - p, - statPctileSvc((double) p / 100.0, 5, PCTILE_HTTP) / 1000.0, - statPctileSvc((double) p / 100.0, 60, PCTILE_HTTP) / 1000.0); + (i + 1) * 5, + stats.http_requests5[i] / fct, + stats.http_requests60[i] / fct); } - for (p = 5; p < 100; p += 5) { + for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) { storeAppendPrintf(sentry, "\tCache Misses: %2d%% %8.5f %8.5f\n", - p, - statPctileSvc((double) p / 100.0, 5, PCTILE_MISS) / 1000.0, - statPctileSvc((double) p / 100.0, 60, PCTILE_MISS) / 1000.0); + (i + 1) * 5, + stats.cache_misses5[i] / fct, + stats.cache_misses60[i] / fct); } - for (p = 5; p < 100; p += 5) { + for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) { storeAppendPrintf(sentry, "\tCache Hits: %2d%% %8.5f %8.5f\n", - p, - statPctileSvc((double) p / 100.0, 5, PCTILE_HIT) / 1000.0, - statPctileSvc((double) p / 100.0, 60, PCTILE_HIT) / 1000.0); + (i + 1) * 5, + stats.cache_hits5[i] / fct, + stats.cache_hits60[i] / fct); } - for (p = 5; p < 100; p += 5) { + for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) { storeAppendPrintf(sentry, "\tNear Hits: %2d%% %8.5f %8.5f\n", - p, - statPctileSvc((double) p / 100.0, 5, PCTILE_NH) / 1000.0, - statPctileSvc((double) p / 100.0, 60, PCTILE_NH) / 1000.0); + (i + 1) * 5, + stats.near_hits5[i] / fct, + stats.near_hits60[i] / fct); } - for (p = 5; p < 100; p += 5) { + for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) { storeAppendPrintf(sentry, "\tNot-Modified Replies: %2d%% %8.5f %8.5f\n", - p, - statPctileSvc((double) p / 100.0, 5, PCTILE_NM) / 1000.0, - statPctileSvc((double) p / 100.0, 60, PCTILE_NM) / 1000.0); + (i + 1) * 5, + stats.not_modified_replies5[i] / fct, + stats.not_modified_replies60[i] / fct); } - for (p = 5; p < 100; p += 5) { + for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) { storeAppendPrintf(sentry, "\tDNS Lookups: %2d%% %8.5f %8.5f\n", - p, - statPctileSvc((double) p / 100.0, 5, PCTILE_DNS) / 1000.0, - statPctileSvc((double) p / 100.0, 60, PCTILE_DNS) / 1000.0); + (i + 1) * 5, + stats.dns_lookups5[i] / fct, + stats.dns_lookups60[i] / fct); } - for (p = 5; p < 100; p += 5) { + fct = stats.count > 1 ? stats.count * 1000000.0 : 1000000.0; + for (int i = 0; i < Mgr::ServiceTimesActionData::seriesSize; ++i) { storeAppendPrintf(sentry, "\tICP Queries: %2d%% %8.5f %8.5f\n", - p, - statPctileSvc((double) p / 100.0, 5, PCTILE_ICP_QUERY) / 1000000.0, - statPctileSvc((double) p / 100.0, 60, PCTILE_ICP_QUERY) / 1000000.0); + (i + 1) * 5, + stats.icp_queries5[i] / fct, + stats.icp_queries60[i] / fct); } } -#define XAVG(X) (dt ? (double) (f->X - l->X) / dt : 0.0) static void statAvgDump(StoreEntry * sentry, int minutes, int hours) +{ + Mgr::IntervalActionData stats; + GetAvgStat(stats, minutes, hours); + DumpAvgStat(stats, sentry); +} + +#define XAVG(X) (dt ? (double) (f->X - l->X) / dt : 0.0) +void +GetAvgStat(Mgr::IntervalActionData& stats, int minutes, int hours) { StatCounters *f; StatCounters *l; double dt; double ct; - double x; assert(N_COUNT_HIST > 1); assert(minutes > 0 || hours > 0); f = &CountHist[0]; @@ -850,211 +1089,295 @@ statAvgDump(StoreEntry * sentry, int minutes, int hours) dt = tvSubDsec(l->timestamp, f->timestamp); ct = f->cputime - l->cputime; + stats.sample_start_time = l->timestamp; + stats.sample_end_time = f->timestamp; + + stats.client_http_requests = XAVG(client_http.requests); + stats.client_http_hits = XAVG(client_http.hits); + stats.client_http_errors = XAVG(client_http.errors); + stats.client_http_kbytes_in = XAVG(client_http.kbytes_in.kb); + stats.client_http_kbytes_out = XAVG(client_http.kbytes_out.kb); + + stats.client_http_all_median_svc_time = statHistDeltaMedian(&l->client_http.all_svc_time, + &f->client_http.all_svc_time) / 1000.0; + stats.client_http_miss_median_svc_time = statHistDeltaMedian(&l->client_http.miss_svc_time, + &f->client_http.miss_svc_time) / 1000.0; + stats.client_http_nm_median_svc_time = statHistDeltaMedian(&l->client_http.nm_svc_time, + &f->client_http.nm_svc_time) / 1000.0; + stats.client_http_nh_median_svc_time = statHistDeltaMedian(&l->client_http.nh_svc_time, + &f->client_http.nh_svc_time) / 1000.0; + stats.client_http_hit_median_svc_time = statHistDeltaMedian(&l->client_http.hit_svc_time, + &f->client_http.hit_svc_time) / 1000.0; + + stats.server_all_requests = XAVG(server.all.requests); + stats.server_all_errors = XAVG(server.all.errors); + stats.server_all_kbytes_in = XAVG(server.all.kbytes_in.kb); + stats.server_all_kbytes_out = XAVG(server.all.kbytes_out.kb); + + stats.server_http_requests = XAVG(server.http.requests); + stats.server_http_errors = XAVG(server.http.errors); + stats.server_http_kbytes_in = XAVG(server.http.kbytes_in.kb); + stats.server_http_kbytes_out = XAVG(server.http.kbytes_out.kb); + + stats.server_ftp_requests = XAVG(server.ftp.requests); + stats.server_ftp_errors = XAVG(server.ftp.errors); + stats.server_ftp_kbytes_in = XAVG(server.ftp.kbytes_in.kb); + stats.server_ftp_kbytes_out = XAVG(server.ftp.kbytes_out.kb); + + stats.server_other_requests = XAVG(server.other.requests); + stats.server_other_errors = XAVG(server.other.errors); + stats.server_other_kbytes_in = XAVG(server.other.kbytes_in.kb); + stats.server_other_kbytes_out = XAVG(server.other.kbytes_out.kb); + + stats.icp_pkts_sent = XAVG(icp.pkts_sent); + stats.icp_pkts_recv = XAVG(icp.pkts_recv); + stats.icp_queries_sent = XAVG(icp.queries_sent); + stats.icp_replies_sent = XAVG(icp.replies_sent); + stats.icp_queries_recv = XAVG(icp.queries_recv); + stats.icp_replies_recv = XAVG(icp.replies_recv); + stats.icp_replies_queued = XAVG(icp.replies_queued); + stats.icp_query_timeouts = XAVG(icp.query_timeouts); + stats.icp_kbytes_sent = XAVG(icp.kbytes_sent.kb); + stats.icp_kbytes_recv = XAVG(icp.kbytes_recv.kb); + stats.icp_q_kbytes_sent = XAVG(icp.q_kbytes_sent.kb); + stats.icp_r_kbytes_sent = XAVG(icp.r_kbytes_sent.kb); + stats.icp_q_kbytes_recv = XAVG(icp.q_kbytes_recv.kb); + stats.icp_r_kbytes_recv = XAVG(icp.r_kbytes_recv.kb); + + stats.icp_query_median_svc_time = statHistDeltaMedian(&l->icp.query_svc_time, + &f->icp.query_svc_time) / 1000000.0; + stats.icp_reply_median_svc_time = statHistDeltaMedian(&l->icp.reply_svc_time, + &f->icp.reply_svc_time) / 1000000.0; + stats.dns_median_svc_time = statHistDeltaMedian(&l->dns.svc_time, + &f->dns.svc_time) / 1000.0; + + stats.unlink_requests = XAVG(unlink.requests); + stats.page_faults = XAVG(page_faults); + stats.select_loops = XAVG(select_loops); + stats.select_fds = XAVG(select_fds); + stats.average_select_fd_period = f->select_fds > l->select_fds ? + (f->select_time - l->select_time) / (f->select_fds - l->select_fds) : 0.0; + + stats.median_select_fds = statHistDeltaMedian(&l->select_fds_hist, &f->select_fds_hist); + stats.swap_outs = XAVG(swap.outs); + stats.swap_ins = XAVG(swap.ins); + stats.swap_files_cleaned = XAVG(swap.files_cleaned); + stats.aborted_requests = XAVG(aborted_requests); + + stats.syscalls_disk_opens = XAVG(syscalls.disk.opens); + stats.syscalls_disk_closes = XAVG(syscalls.disk.closes); + stats.syscalls_disk_reads = XAVG(syscalls.disk.reads); + stats.syscalls_disk_writes = XAVG(syscalls.disk.writes); + stats.syscalls_disk_seeks = XAVG(syscalls.disk.seeks); + stats.syscalls_disk_unlinks = XAVG(syscalls.disk.unlinks); + stats.syscalls_sock_accepts = XAVG(syscalls.sock.accepts); + stats.syscalls_sock_sockets = XAVG(syscalls.sock.sockets); + stats.syscalls_sock_connects = XAVG(syscalls.sock.connects); + stats.syscalls_sock_binds = XAVG(syscalls.sock.binds); + stats.syscalls_sock_closes = XAVG(syscalls.sock.closes); + stats.syscalls_sock_reads = XAVG(syscalls.sock.reads); + stats.syscalls_sock_writes = XAVG(syscalls.sock.writes); + stats.syscalls_sock_recvfroms = XAVG(syscalls.sock.recvfroms); + stats.syscalls_sock_sendtos = XAVG(syscalls.sock.sendtos); + stats.syscalls_selects = XAVG(syscalls.selects); + + stats.cpu_time = ct; + stats.wall_time = dt; +} + +void +DumpAvgStat(Mgr::IntervalActionData& stats, StoreEntry* sentry) +{ storeAppendPrintf(sentry, "sample_start_time = %d.%d (%s)\n", - (int) l->timestamp.tv_sec, - (int) l->timestamp.tv_usec, - mkrfc1123(l->timestamp.tv_sec)); + (int)stats.sample_start_time.tv_sec, + (int)stats.sample_start_time.tv_usec, + mkrfc1123(stats.sample_start_time.tv_sec)); storeAppendPrintf(sentry, "sample_end_time = %d.%d (%s)\n", - (int) f->timestamp.tv_sec, - (int) f->timestamp.tv_usec, - mkrfc1123(f->timestamp.tv_sec)); + (int)stats.sample_end_time.tv_sec, + (int)stats.sample_end_time.tv_usec, + mkrfc1123(stats.sample_end_time.tv_sec)); storeAppendPrintf(sentry, "client_http.requests = %f/sec\n", - XAVG(client_http.requests)); + stats.client_http_requests); storeAppendPrintf(sentry, "client_http.hits = %f/sec\n", - XAVG(client_http.hits)); + stats.client_http_hits); storeAppendPrintf(sentry, "client_http.errors = %f/sec\n", - XAVG(client_http.errors)); + stats.client_http_errors); storeAppendPrintf(sentry, "client_http.kbytes_in = %f/sec\n", - XAVG(client_http.kbytes_in.kb)); + stats.client_http_kbytes_in); storeAppendPrintf(sentry, "client_http.kbytes_out = %f/sec\n", - XAVG(client_http.kbytes_out.kb)); + stats.client_http_kbytes_out); - x = statHistDeltaMedian(&l->client_http.all_svc_time, - &f->client_http.all_svc_time); + double fct = stats.count > 1 ? stats.count : 1.0; storeAppendPrintf(sentry, "client_http.all_median_svc_time = %f seconds\n", - x / 1000.0); - x = statHistDeltaMedian(&l->client_http.miss_svc_time, - &f->client_http.miss_svc_time); + stats.client_http_all_median_svc_time / fct); storeAppendPrintf(sentry, "client_http.miss_median_svc_time = %f seconds\n", - x / 1000.0); - x = statHistDeltaMedian(&l->client_http.nm_svc_time, - &f->client_http.nm_svc_time); + stats.client_http_miss_median_svc_time / fct); storeAppendPrintf(sentry, "client_http.nm_median_svc_time = %f seconds\n", - x / 1000.0); - x = statHistDeltaMedian(&l->client_http.nh_svc_time, - &f->client_http.nh_svc_time); + stats.client_http_nm_median_svc_time / fct); storeAppendPrintf(sentry, "client_http.nh_median_svc_time = %f seconds\n", - x / 1000.0); - x = statHistDeltaMedian(&l->client_http.hit_svc_time, - &f->client_http.hit_svc_time); + stats.client_http_nh_median_svc_time / fct); storeAppendPrintf(sentry, "client_http.hit_median_svc_time = %f seconds\n", - x / 1000.0); + stats.client_http_hit_median_svc_time / fct); storeAppendPrintf(sentry, "server.all.requests = %f/sec\n", - XAVG(server.all.requests)); + stats.server_all_requests); storeAppendPrintf(sentry, "server.all.errors = %f/sec\n", - XAVG(server.all.errors)); + stats.server_all_errors); storeAppendPrintf(sentry, "server.all.kbytes_in = %f/sec\n", - XAVG(server.all.kbytes_in.kb)); + stats.server_all_kbytes_in); storeAppendPrintf(sentry, "server.all.kbytes_out = %f/sec\n", - XAVG(server.all.kbytes_out.kb)); + stats.server_all_kbytes_out); storeAppendPrintf(sentry, "server.http.requests = %f/sec\n", - XAVG(server.http.requests)); + stats.server_http_requests); storeAppendPrintf(sentry, "server.http.errors = %f/sec\n", - XAVG(server.http.errors)); + stats.server_http_errors); storeAppendPrintf(sentry, "server.http.kbytes_in = %f/sec\n", - XAVG(server.http.kbytes_in.kb)); + stats.server_http_kbytes_in); storeAppendPrintf(sentry, "server.http.kbytes_out = %f/sec\n", - XAVG(server.http.kbytes_out.kb)); + stats.server_http_kbytes_out); storeAppendPrintf(sentry, "server.ftp.requests = %f/sec\n", - XAVG(server.ftp.requests)); + stats.server_ftp_requests); storeAppendPrintf(sentry, "server.ftp.errors = %f/sec\n", - XAVG(server.ftp.errors)); + stats.server_ftp_errors); storeAppendPrintf(sentry, "server.ftp.kbytes_in = %f/sec\n", - XAVG(server.ftp.kbytes_in.kb)); + stats.server_ftp_kbytes_in); storeAppendPrintf(sentry, "server.ftp.kbytes_out = %f/sec\n", - XAVG(server.ftp.kbytes_out.kb)); + stats.server_ftp_kbytes_out); storeAppendPrintf(sentry, "server.other.requests = %f/sec\n", - XAVG(server.other.requests)); + stats.server_other_requests); storeAppendPrintf(sentry, "server.other.errors = %f/sec\n", - XAVG(server.other.errors)); + stats.server_other_errors); storeAppendPrintf(sentry, "server.other.kbytes_in = %f/sec\n", - XAVG(server.other.kbytes_in.kb)); + stats.server_other_kbytes_in); storeAppendPrintf(sentry, "server.other.kbytes_out = %f/sec\n", - XAVG(server.other.kbytes_out.kb)); + stats.server_other_kbytes_out); storeAppendPrintf(sentry, "icp.pkts_sent = %f/sec\n", - XAVG(icp.pkts_sent)); + stats.icp_pkts_sent); storeAppendPrintf(sentry, "icp.pkts_recv = %f/sec\n", - XAVG(icp.pkts_recv)); + stats.icp_pkts_recv); storeAppendPrintf(sentry, "icp.queries_sent = %f/sec\n", - XAVG(icp.queries_sent)); + stats.icp_queries_sent); storeAppendPrintf(sentry, "icp.replies_sent = %f/sec\n", - XAVG(icp.replies_sent)); + stats.icp_replies_sent); storeAppendPrintf(sentry, "icp.queries_recv = %f/sec\n", - XAVG(icp.queries_recv)); + stats.icp_queries_recv); storeAppendPrintf(sentry, "icp.replies_recv = %f/sec\n", - XAVG(icp.replies_recv)); + stats.icp_replies_recv); storeAppendPrintf(sentry, "icp.replies_queued = %f/sec\n", - XAVG(icp.replies_queued)); + stats.icp_replies_queued); storeAppendPrintf(sentry, "icp.query_timeouts = %f/sec\n", - XAVG(icp.query_timeouts)); + stats.icp_query_timeouts); storeAppendPrintf(sentry, "icp.kbytes_sent = %f/sec\n", - XAVG(icp.kbytes_sent.kb)); + stats.icp_kbytes_sent); storeAppendPrintf(sentry, "icp.kbytes_recv = %f/sec\n", - XAVG(icp.kbytes_recv.kb)); + stats.icp_kbytes_recv); storeAppendPrintf(sentry, "icp.q_kbytes_sent = %f/sec\n", - XAVG(icp.q_kbytes_sent.kb)); + stats.icp_q_kbytes_sent); storeAppendPrintf(sentry, "icp.r_kbytes_sent = %f/sec\n", - XAVG(icp.r_kbytes_sent.kb)); + stats.icp_r_kbytes_sent); storeAppendPrintf(sentry, "icp.q_kbytes_recv = %f/sec\n", - XAVG(icp.q_kbytes_recv.kb)); + stats.icp_q_kbytes_recv); storeAppendPrintf(sentry, "icp.r_kbytes_recv = %f/sec\n", - XAVG(icp.r_kbytes_recv.kb)); - x = statHistDeltaMedian(&l->icp.query_svc_time, &f->icp.query_svc_time); + stats.icp_r_kbytes_recv); storeAppendPrintf(sentry, "icp.query_median_svc_time = %f seconds\n", - x / 1000000.0); - x = statHistDeltaMedian(&l->icp.reply_svc_time, &f->icp.reply_svc_time); + stats.icp_query_median_svc_time / fct); storeAppendPrintf(sentry, "icp.reply_median_svc_time = %f seconds\n", - x / 1000000.0); - x = statHistDeltaMedian(&l->dns.svc_time, &f->dns.svc_time); + stats.icp_reply_median_svc_time / fct); storeAppendPrintf(sentry, "dns.median_svc_time = %f seconds\n", - x / 1000.0); + stats.dns_median_svc_time / fct); storeAppendPrintf(sentry, "unlink.requests = %f/sec\n", - XAVG(unlink.requests)); + stats.unlink_requests); storeAppendPrintf(sentry, "page_faults = %f/sec\n", - XAVG(page_faults)); + stats.page_faults); storeAppendPrintf(sentry, "select_loops = %f/sec\n", - XAVG(select_loops)); + stats.select_loops); storeAppendPrintf(sentry, "select_fds = %f/sec\n", - XAVG(select_fds)); + stats.select_fds); storeAppendPrintf(sentry, "average_select_fd_period = %f/fd\n", - f->select_fds > l->select_fds ? - (f->select_time - l->select_time) / (f->select_fds - l->select_fds) - : 0.0); - x = statHistDeltaMedian(&l->select_fds_hist, &f->select_fds_hist); - storeAppendPrintf(sentry, "median_select_fds = %f\n", x); + stats.average_select_fd_period / fct); + storeAppendPrintf(sentry, "median_select_fds = %f\n", + stats.median_select_fds / fct); storeAppendPrintf(sentry, "swap.outs = %f/sec\n", - XAVG(swap.outs)); + stats.swap_outs); storeAppendPrintf(sentry, "swap.ins = %f/sec\n", - XAVG(swap.ins)); + stats.swap_ins); storeAppendPrintf(sentry, "swap.files_cleaned = %f/sec\n", - XAVG(swap.files_cleaned)); + stats.swap_files_cleaned); storeAppendPrintf(sentry, "aborted_requests = %f/sec\n", - XAVG(aborted_requests)); + stats.aborted_requests); #if USE_POLL - storeAppendPrintf(sentry, "syscalls.polls = %f/sec\n", XAVG(syscalls.selects)); + storeAppendPrintf(sentry, "syscalls.polls = %f/sec\n", stats.syscalls_selects); #elif defined(USE_SELECT) || defined(USE_SELECT_WIN32) - storeAppendPrintf(sentry, "syscalls.selects = %f/sec\n", XAVG(syscalls.selects)); + storeAppendPrintf(sentry, "syscalls.selects = %f/sec\n", stats.syscalls_selects); #endif - storeAppendPrintf(sentry, "syscalls.disk.opens = %f/sec\n", XAVG(syscalls.disk.opens)); - storeAppendPrintf(sentry, "syscalls.disk.closes = %f/sec\n", XAVG(syscalls.disk.closes)); - storeAppendPrintf(sentry, "syscalls.disk.reads = %f/sec\n", XAVG(syscalls.disk.reads)); - storeAppendPrintf(sentry, "syscalls.disk.writes = %f/sec\n", XAVG(syscalls.disk.writes)); - storeAppendPrintf(sentry, "syscalls.disk.seeks = %f/sec\n", XAVG(syscalls.disk.seeks)); - storeAppendPrintf(sentry, "syscalls.disk.unlinks = %f/sec\n", XAVG(syscalls.disk.unlinks)); - storeAppendPrintf(sentry, "syscalls.sock.accepts = %f/sec\n", XAVG(syscalls.sock.accepts)); - storeAppendPrintf(sentry, "syscalls.sock.sockets = %f/sec\n", XAVG(syscalls.sock.sockets)); - storeAppendPrintf(sentry, "syscalls.sock.connects = %f/sec\n", XAVG(syscalls.sock.connects)); - storeAppendPrintf(sentry, "syscalls.sock.binds = %f/sec\n", XAVG(syscalls.sock.binds)); - storeAppendPrintf(sentry, "syscalls.sock.closes = %f/sec\n", XAVG(syscalls.sock.closes)); - storeAppendPrintf(sentry, "syscalls.sock.reads = %f/sec\n", XAVG(syscalls.sock.reads)); - storeAppendPrintf(sentry, "syscalls.sock.writes = %f/sec\n", XAVG(syscalls.sock.writes)); - storeAppendPrintf(sentry, "syscalls.sock.recvfroms = %f/sec\n", XAVG(syscalls.sock.recvfroms)); - storeAppendPrintf(sentry, "syscalls.sock.sendtos = %f/sec\n", XAVG(syscalls.sock.sendtos)); - - storeAppendPrintf(sentry, "cpu_time = %f seconds\n", ct); - storeAppendPrintf(sentry, "wall_time = %f seconds\n", dt); - storeAppendPrintf(sentry, "cpu_usage = %f%%\n", Math::doublePercent(ct, dt)); + storeAppendPrintf(sentry, "syscalls.disk.opens = %f/sec\n", stats.syscalls_disk_opens); + storeAppendPrintf(sentry, "syscalls.disk.closes = %f/sec\n", stats.syscalls_disk_closes); + storeAppendPrintf(sentry, "syscalls.disk.reads = %f/sec\n", stats.syscalls_disk_reads); + storeAppendPrintf(sentry, "syscalls.disk.writes = %f/sec\n", stats.syscalls_disk_writes); + storeAppendPrintf(sentry, "syscalls.disk.seeks = %f/sec\n", stats.syscalls_disk_seeks); + storeAppendPrintf(sentry, "syscalls.disk.unlinks = %f/sec\n", stats.syscalls_disk_unlinks); + storeAppendPrintf(sentry, "syscalls.sock.accepts = %f/sec\n", stats.syscalls_sock_accepts); + storeAppendPrintf(sentry, "syscalls.sock.sockets = %f/sec\n", stats.syscalls_sock_sockets); + storeAppendPrintf(sentry, "syscalls.sock.connects = %f/sec\n", stats.syscalls_sock_connects); + storeAppendPrintf(sentry, "syscalls.sock.binds = %f/sec\n", stats.syscalls_sock_binds); + storeAppendPrintf(sentry, "syscalls.sock.closes = %f/sec\n", stats.syscalls_sock_closes); + storeAppendPrintf(sentry, "syscalls.sock.reads = %f/sec\n", stats.syscalls_sock_reads); + storeAppendPrintf(sentry, "syscalls.sock.writes = %f/sec\n", stats.syscalls_sock_writes); + storeAppendPrintf(sentry, "syscalls.sock.recvfroms = %f/sec\n", stats.syscalls_sock_recvfroms); + storeAppendPrintf(sentry, "syscalls.sock.sendtos = %f/sec\n", stats.syscalls_sock_sendtos); + + storeAppendPrintf(sentry, "cpu_time = %f seconds\n", stats.cpu_time); + storeAppendPrintf(sentry, "wall_time = %f seconds\n", stats.wall_time); + storeAppendPrintf(sentry, "cpu_usage = %f%%\n", Math::doublePercent(stats.cpu_time, stats.wall_time)); } static void statRegisterWithCacheManager(void) { - CacheManager *manager = CacheManager::GetInstance(); - manager->registerAction("info", "General Runtime Information", - info_get, 0, 1); - manager->registerAction("service_times", "Service Times (Percentiles)", - service_times, 0, 1); - manager->registerAction("filedescriptors", "Process Filedescriptor Allocation", + Mgr::RegisterAction("info", "General Runtime Information", + &Mgr::InfoAction::Create, 0, 1); + Mgr::RegisterAction("service_times", "Service Times (Percentiles)", + &Mgr::ServiceTimesAction::Create, 0, 1); + Mgr::RegisterAction("filedescriptors", "Process Filedescriptor Allocation", fde::DumpStats, 0, 1); - manager->registerAction("objects", "All Cache Objects", stat_objects_get, 0, 0); - manager->registerAction("vm_objects", "In-Memory and In-Transit Objects", + Mgr::RegisterAction("objects", "All Cache Objects", stat_objects_get, 0, 0); + Mgr::RegisterAction("vm_objects", "In-Memory and In-Transit Objects", stat_vmobjects_get, 0, 0); - manager->registerAction("io", "Server-side network read() size histograms", - stat_io_get, 0, 1); - manager->registerAction("counters", "Traffic and Resource Counters", - statCountersDump, 0, 1); - manager->registerAction("peer_select", "Peer Selection Algorithms", + Mgr::RegisterAction("io", "Server-side network read() size histograms", + &Mgr::IoAction::Create, 0, 1); + Mgr::RegisterAction("counters", "Traffic and Resource Counters", + &Mgr::CountersAction::Create, 0, 1); + Mgr::RegisterAction("peer_select", "Peer Selection Algorithms", statPeerSelect, 0, 1); - manager->registerAction("digest_stats", "Cache Digest and ICP blob", + Mgr::RegisterAction("digest_stats", "Cache Digest and ICP blob", statDigestBlob, 0, 1); - manager->registerAction("5min", "5 Minute Average of Counters", - statAvg5min, 0, 1); - manager->registerAction("60min", "60 Minute Average of Counters", - statAvg60min, 0, 1); - manager->registerAction("utilization", "Cache Utilization", + Mgr::RegisterAction("5min", "5 Minute Average of Counters", + &Mgr::IntervalAction::Create5min, 0, 1); + Mgr::RegisterAction("60min", "60 Minute Average of Counters", + &Mgr::IntervalAction::Create60min, 0, 1); + Mgr::RegisterAction("utilization", "Cache Utilization", statUtilization, 0, 1); - manager->registerAction("histograms", "Full Histogram Counts", + Mgr::RegisterAction("histograms", "Full Histogram Counts", statCountersHistograms, 0, 1); - manager->registerAction("active_requests", + Mgr::RegisterAction("active_requests", "Client-side Active Requests", statClientRequests, 0, 1); - manager->registerAction("username_cache", + Mgr::RegisterAction("username_cache", "Active Cached Usernames", AuthUser::UsernameCacheStats, 0, 1); #if DEBUG_OPENFD - manager->registerAction("openfd_objects", "Objects with Swapout files open", + Mgr::RegisterAction("openfd_objects", "Objects with Swapout files open", statOpenfdObj, 0, 0); #endif #if STAT_GRAPHS - manager->registerAction("graph_variables", "Display cache metrics graphically", + Mgr::RegisterAction("graph_variables", "Display cache metrics graphically", statGraphDump, 0, 1); #endif } @@ -1263,6 +1586,14 @@ statCountersHistograms(StoreEntry * sentry) static void statCountersDump(StoreEntry * sentry) +{ + Mgr::CountersActionData stats; + GetCountersStats(stats); + DumpCountersStats(stats, sentry); +} + +void +GetCountersStats(Mgr::CountersActionData& stats) { StatCounters *f = &statCounter; @@ -1271,126 +1602,195 @@ statCountersDump(StoreEntry * sentry) f->page_faults = rusage_pagefaults(&rusage); f->cputime = rusage_cputime(&rusage); + stats.sample_time = f->timestamp; + stats.client_http_requests = f->client_http.requests; + stats.client_http_hits = f->client_http.hits; + stats.client_http_errors = f->client_http.errors; + stats.client_http_kbytes_in = f->client_http.kbytes_in.kb; + stats.client_http_kbytes_out = f->client_http.kbytes_out.kb; + stats.client_http_hit_kbytes_out = f->client_http.hit_kbytes_out.kb; + + stats.server_all_requests = f->server.all.requests; + stats.server_all_errors = f->server.all.errors; + stats.server_all_kbytes_in = f->server.all.kbytes_in.kb; + stats.server_all_kbytes_out = f->server.all.kbytes_out.kb; + + stats.server_http_requests = f->server.http.requests; + stats.server_http_errors = f->server.http.errors; + stats.server_http_kbytes_in = f->server.http.kbytes_in.kb; + stats.server_http_kbytes_out = f->server.http.kbytes_out.kb; + + stats.server_ftp_requests = f->server.ftp.requests; + stats.server_ftp_errors = f->server.ftp.errors; + stats.server_ftp_kbytes_in = f->server.ftp.kbytes_in.kb; + stats.server_ftp_kbytes_out = f->server.ftp.kbytes_out.kb; + + stats.server_other_requests = f->server.other.requests; + stats.server_other_errors = f->server.other.errors; + stats.server_other_kbytes_in = f->server.other.kbytes_in.kb; + stats.server_other_kbytes_out = f->server.other.kbytes_out.kb; + + stats.icp_pkts_sent = f->icp.pkts_sent; + stats.icp_pkts_recv = f->icp.pkts_recv; + stats.icp_queries_sent = f->icp.queries_sent; + stats.icp_replies_sent = f->icp.replies_sent; + stats.icp_queries_recv = f->icp.queries_recv; + stats.icp_replies_recv = f->icp.replies_recv; + stats.icp_query_timeouts = f->icp.query_timeouts; + stats.icp_replies_queued = f->icp.replies_queued; + stats.icp_kbytes_sent = f->icp.kbytes_sent.kb; + stats.icp_kbytes_recv = f->icp.kbytes_recv.kb; + stats.icp_q_kbytes_sent = f->icp.q_kbytes_sent.kb; + stats.icp_r_kbytes_sent = f->icp.r_kbytes_sent.kb; + stats.icp_q_kbytes_recv = f->icp.q_kbytes_recv.kb; + stats.icp_r_kbytes_recv = f->icp.r_kbytes_recv.kb; + +#if USE_CACHE_DIGESTS + + stats.icp_times_used = f->icp.times_used; + stats.cd_times_used = f->cd.times_used; + stats.cd_msgs_sent = f->cd.msgs_sent; + stats.cd_msgs_recv = f->cd.msgs_recv; + stats.cd_memory = f->cd.memory.kb; + stats.cd_local_memory = store_digest ? store_digest->mask_size / 1024 : 0; + stats.cd_kbytes_sent = f->cd.kbytes_sent.kb; + stats.cd_kbytes_recv = f->cd.kbytes_recv.kb; +#endif + + stats.unlink_requests = f->unlink.requests; + stats.page_faults = f->page_faults; + stats.select_loops = f->select_loops; + stats.cpu_time = f->cputime; + stats.wall_time = tvSubDsec(f->timestamp, current_time); + stats.swap_outs = f->swap.outs; + stats.swap_ins = f->swap.ins; + stats.swap_files_cleaned = f->swap.files_cleaned; + stats.aborted_requests = f->aborted_requests; +} + +void +DumpCountersStats(Mgr::CountersActionData& stats, StoreEntry* sentry) +{ storeAppendPrintf(sentry, "sample_time = %d.%d (%s)\n", - (int) f->timestamp.tv_sec, - (int) f->timestamp.tv_usec, - mkrfc1123(f->timestamp.tv_sec)); - storeAppendPrintf(sentry, "client_http.requests = %ld\n", - (long)f->client_http.requests); - storeAppendPrintf(sentry, "client_http.hits = %ld\n", - (long)f->client_http.hits); - storeAppendPrintf(sentry, "client_http.errors = %ld\n", - (long)f->client_http.errors); - storeAppendPrintf(sentry, "client_http.kbytes_in = %ld\n", - (long)f->client_http.kbytes_in.kb); - storeAppendPrintf(sentry, "client_http.kbytes_out = %ld\n", - (long)f->client_http.kbytes_out.kb); - storeAppendPrintf(sentry, "client_http.hit_kbytes_out = %ld\n", - (long)f->client_http.hit_kbytes_out.kb); - - storeAppendPrintf(sentry, "server.all.requests = %ld\n", - (long)f->server.all.requests); - storeAppendPrintf(sentry, "server.all.errors = %ld\n", - (long) f->server.all.errors); - storeAppendPrintf(sentry, "server.all.kbytes_in = %ld\n", - (long) f->server.all.kbytes_in.kb); - storeAppendPrintf(sentry, "server.all.kbytes_out = %ld\n", - (long) f->server.all.kbytes_out.kb); - - storeAppendPrintf(sentry, "server.http.requests = %ld\n", - (long) f->server.http.requests); - storeAppendPrintf(sentry, "server.http.errors = %ld\n", - (long) f->server.http.errors); - storeAppendPrintf(sentry, "server.http.kbytes_in = %ld\n", - (long) f->server.http.kbytes_in.kb); - storeAppendPrintf(sentry, "server.http.kbytes_out = %ld\n", - (long) f->server.http.kbytes_out.kb); - - storeAppendPrintf(sentry, "server.ftp.requests = %ld\n", - (long) f->server.ftp.requests); - storeAppendPrintf(sentry, "server.ftp.errors = %ld\n", - (long) f->server.ftp.errors); - storeAppendPrintf(sentry, "server.ftp.kbytes_in = %ld\n", - (long) f->server.ftp.kbytes_in.kb); - storeAppendPrintf(sentry, "server.ftp.kbytes_out = %ld\n", - (long) f->server.ftp.kbytes_out.kb); - - storeAppendPrintf(sentry, "server.other.requests = %ld\n", - (long) f->server.other.requests); - storeAppendPrintf(sentry, "server.other.errors = %ld\n", - (long) f->server.other.errors); - storeAppendPrintf(sentry, "server.other.kbytes_in = %ld\n", - (long) f->server.other.kbytes_in.kb); - storeAppendPrintf(sentry, "server.other.kbytes_out = %ld\n", - (long) f->server.other.kbytes_out.kb); - - storeAppendPrintf(sentry, "icp.pkts_sent = %ld\n", - (long)f->icp.pkts_sent); - storeAppendPrintf(sentry, "icp.pkts_recv = %ld\n", - (long)f->icp.pkts_recv); - storeAppendPrintf(sentry, "icp.queries_sent = %ld\n", - (long)f->icp.queries_sent); - storeAppendPrintf(sentry, "icp.replies_sent = %ld\n", - (long)f->icp.replies_sent); - storeAppendPrintf(sentry, "icp.queries_recv = %ld\n", - (long)f->icp.queries_recv); - storeAppendPrintf(sentry, "icp.replies_recv = %ld\n", - (long)f->icp.replies_recv); - storeAppendPrintf(sentry, "icp.query_timeouts = %ld\n", - (long)f->icp.query_timeouts); - storeAppendPrintf(sentry, "icp.replies_queued = %ld\n", - (long)f->icp.replies_queued); - storeAppendPrintf(sentry, "icp.kbytes_sent = %ld\n", - (long) f->icp.kbytes_sent.kb); - storeAppendPrintf(sentry, "icp.kbytes_recv = %ld\n", - (long) f->icp.kbytes_recv.kb); - storeAppendPrintf(sentry, "icp.q_kbytes_sent = %ld\n", - (long) f->icp.q_kbytes_sent.kb); - storeAppendPrintf(sentry, "icp.r_kbytes_sent = %ld\n", - (long) f->icp.r_kbytes_sent.kb); - storeAppendPrintf(sentry, "icp.q_kbytes_recv = %ld\n", - (long) f->icp.q_kbytes_recv.kb); - storeAppendPrintf(sentry, "icp.r_kbytes_recv = %ld\n", - (long) f->icp.r_kbytes_recv.kb); + (int) stats.sample_time.tv_sec, + (int) stats.sample_time.tv_usec, + mkrfc1123(stats.sample_time.tv_sec)); + storeAppendPrintf(sentry, "client_http.requests = %.0f\n", + stats.client_http_requests); + storeAppendPrintf(sentry, "client_http.hits = %.0f\n", + stats.client_http_hits); + storeAppendPrintf(sentry, "client_http.errors = %.0f\n", + stats.client_http_errors); + storeAppendPrintf(sentry, "client_http.kbytes_in = %.0f\n", + stats.client_http_kbytes_in); + storeAppendPrintf(sentry, "client_http.kbytes_out = %.0f\n", + stats.client_http_kbytes_out); + storeAppendPrintf(sentry, "client_http.hit_kbytes_out = %.0f\n", + stats.client_http_hit_kbytes_out); + + storeAppendPrintf(sentry, "server.all.requests = %.0f\n", + stats.server_all_requests); + storeAppendPrintf(sentry, "server.all.errors = %.0f\n", + stats.server_all_errors); + storeAppendPrintf(sentry, "server.all.kbytes_in = %.0f\n", + stats.server_all_kbytes_in); + storeAppendPrintf(sentry, "server.all.kbytes_out = %.0f\n", + stats.server_all_kbytes_out); + + storeAppendPrintf(sentry, "server.http.requests = %.0f\n", + stats.server_http_requests); + storeAppendPrintf(sentry, "server.http.errors = %.0f\n", + stats.server_http_errors); + storeAppendPrintf(sentry, "server.http.kbytes_in = %.0f\n", + stats.server_http_kbytes_in); + storeAppendPrintf(sentry, "server.http.kbytes_out = %.0f\n", + stats.server_http_kbytes_out); + + storeAppendPrintf(sentry, "server.ftp.requests = %.0f\n", + stats.server_ftp_requests); + storeAppendPrintf(sentry, "server.ftp.errors = %.0f\n", + stats.server_ftp_errors); + storeAppendPrintf(sentry, "server.ftp.kbytes_in = %.0f\n", + stats.server_ftp_kbytes_in); + storeAppendPrintf(sentry, "server.ftp.kbytes_out = %.0f\n", + stats.server_ftp_kbytes_out); + + storeAppendPrintf(sentry, "server.other.requests = %.0f\n", + stats.server_other_requests); + storeAppendPrintf(sentry, "server.other.errors = %.0f\n", + stats.server_other_errors); + storeAppendPrintf(sentry, "server.other.kbytes_in = %.0f\n", + stats.server_other_kbytes_in); + storeAppendPrintf(sentry, "server.other.kbytes_out = %.0f\n", + stats.server_other_kbytes_out); + + storeAppendPrintf(sentry, "icp.pkts_sent = %.0f\n", + stats.icp_pkts_sent); + storeAppendPrintf(sentry, "icp.pkts_recv = %.0f\n", + stats.icp_pkts_recv); + storeAppendPrintf(sentry, "icp.queries_sent = %.0f\n", + stats.icp_queries_sent); + storeAppendPrintf(sentry, "icp.replies_sent = %.0f\n", + stats.icp_replies_sent); + storeAppendPrintf(sentry, "icp.queries_recv = %.0f\n", + stats.icp_queries_recv); + storeAppendPrintf(sentry, "icp.replies_recv = %.0f\n", + stats.icp_replies_recv); + storeAppendPrintf(sentry, "icp.query_timeouts = %.0f\n", + stats.icp_query_timeouts); + storeAppendPrintf(sentry, "icp.replies_queued = %.0f\n", + stats.icp_replies_queued); + storeAppendPrintf(sentry, "icp.kbytes_sent = %.0f\n", + stats.icp_kbytes_sent); + storeAppendPrintf(sentry, "icp.kbytes_recv = %.0f\n", + stats.icp_kbytes_recv); + storeAppendPrintf(sentry, "icp.q_kbytes_sent = %.0f\n", + stats.icp_q_kbytes_sent); + storeAppendPrintf(sentry, "icp.r_kbytes_sent = %.0f\n", + stats.icp_r_kbytes_sent); + storeAppendPrintf(sentry, "icp.q_kbytes_recv = %.0f\n", + stats.icp_q_kbytes_recv); + storeAppendPrintf(sentry, "icp.r_kbytes_recv = %.0f\n", + stats.icp_r_kbytes_recv); #if USE_CACHE_DIGESTS - storeAppendPrintf(sentry, "icp.times_used = %ld\n", - (long)f->icp.times_used); - storeAppendPrintf(sentry, "cd.times_used = %ld\n", - (long)f->cd.times_used); - storeAppendPrintf(sentry, "cd.msgs_sent = %ld\n", - (long)f->cd.msgs_sent); - storeAppendPrintf(sentry, "cd.msgs_recv = %ld\n", - (long)f->cd.msgs_recv); - storeAppendPrintf(sentry, "cd.memory = %ld\n", - (long) f->cd.memory.kb); - storeAppendPrintf(sentry, "cd.local_memory = %ld\n", - (long) (store_digest ? store_digest->mask_size / 1024 : 0)); - storeAppendPrintf(sentry, "cd.kbytes_sent = %ld\n", - (long) f->cd.kbytes_sent.kb); - storeAppendPrintf(sentry, "cd.kbytes_recv = %ld\n", - (long) f->cd.kbytes_recv.kb); + storeAppendPrintf(sentry, "icp.times_used = %.0f\n", + stats.icp_times_used); + storeAppendPrintf(sentry, "cd.times_used = %.0f\n", + stats.cd_times_used); + storeAppendPrintf(sentry, "cd.msgs_sent = %.0f\n", + stats.cd_msgs_sent); + storeAppendPrintf(sentry, "cd.msgs_recv = %.0f\n", + stats.cd_msgs_recv); + storeAppendPrintf(sentry, "cd.memory = %.0f\n", + stats.cd_memory); + storeAppendPrintf(sentry, "cd.local_memory = %.0f\n", + stats.cd_local_memory); + storeAppendPrintf(sentry, "cd.kbytes_sent = %.0f\n", + stats.cd_kbytes_sent); + storeAppendPrintf(sentry, "cd.kbytes_recv = %.0f\n", + stats.cd_kbytes_recv); #endif - storeAppendPrintf(sentry, "unlink.requests = %ld\n", - (long)f->unlink.requests); - storeAppendPrintf(sentry, "page_faults = %ld\n", - (long)f->page_faults); - storeAppendPrintf(sentry, "select_loops = %ld\n", - (long)f->select_loops); + storeAppendPrintf(sentry, "unlink.requests = %.0f\n", + stats.unlink_requests); + storeAppendPrintf(sentry, "page_faults = %.0f\n", + stats.page_faults); + storeAppendPrintf(sentry, "select_loops = %.0f\n", + stats.select_loops); storeAppendPrintf(sentry, "cpu_time = %f\n", - f->cputime); + stats.cpu_time); storeAppendPrintf(sentry, "wall_time = %f\n", - tvSubDsec(f->timestamp, current_time)); - storeAppendPrintf(sentry, "swap.outs = %ld\n", - (long)f->swap.outs); - storeAppendPrintf(sentry, "swap.ins = %ld\n", - (long)f->swap.ins); - storeAppendPrintf(sentry, "swap.files_cleaned = %ld\n", - (long)f->swap.files_cleaned); - storeAppendPrintf(sentry, "aborted_requests = %ld\n", - (long)f->aborted_requests); + stats.wall_time); + storeAppendPrintf(sentry, "swap.outs = %.0f\n", + stats.swap_outs); + storeAppendPrintf(sentry, "swap.ins = %.0f\n", + stats.swap_ins); + storeAppendPrintf(sentry, "swap.files_cleaned = %.0f\n", + stats.swap_files_cleaned); + storeAppendPrintf(sentry, "aborted_requests = %.0f\n", + stats.aborted_requests); } void @@ -1455,18 +1855,6 @@ statDigestBlob(StoreEntry * sentry) storeDigestReport(sentry); } -static void -statAvg5min(StoreEntry * e) -{ - statAvgDump(e, 5, 0); -} - -static void -statAvg60min(StoreEntry * e) -{ - statAvgDump(e, 60, 0); -} - static double statPctileSvc(double pctile, int interval, int which) { diff --git a/src/store.cc b/src/store.cc index c4671d1aee..e5c0a43c58 100644 --- a/src/store.cc +++ b/src/store.cc @@ -37,7 +37,7 @@ #include "event.h" #include "fde.h" #include "Store.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #include "StoreClient.h" #include "stmem.h" #include "HttpReply.h" @@ -52,6 +52,7 @@ #include "Stack.h" #include "SquidTime.h" #include "swap_log_op.h" +#include "mgr/StoreIoAction.h" static STMCB storeWriteComplete; @@ -84,8 +85,6 @@ const char *swapStatusStr[] = { "SWAPOUT_DONE" }; -extern OBJH storeIOStats; - /* * This defines an repl type @@ -1378,10 +1377,9 @@ StoreEntry::validLength() const static void storeRegisterWithCacheManager(void) { - CacheManager *manager=CacheManager::GetInstance(); - manager->registerAction("storedir", "Store Directory Stats", Store::Stats, 0, 1); - manager->registerAction("store_io", "Store IO Interface Stats", storeIOStats, 0, 1); - manager->registerAction("store_check_cachable_stats", "storeCheckCachable() Stats", + Mgr::RegisterAction("storedir", "Store Directory Stats", Store::Stats, 0, 1); + Mgr::RegisterAction("store_io", "Store IO Interface Stats", &Mgr::StoreIoAction::Create, 0, 1); + Mgr::RegisterAction("store_check_cachable_stats", "storeCheckCachable() Stats", storeCheckCachableStats, 0, 1); } diff --git a/src/store_digest.cc b/src/store_digest.cc index ac0678dfed..4d419d5e5c 100644 --- a/src/store_digest.cc +++ b/src/store_digest.cc @@ -42,7 +42,7 @@ #include "squid.h" #include "event.h" -#include "CacheManager.h" +#include "mgr/Registration.h" #if USE_CACHE_DIGESTS #include "Store.h" @@ -103,8 +103,7 @@ static void storeDigestAdd(const StoreEntry *); static void storeDigestRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("store_digest", "Store Digest", storeDigestReport, 0, 1); + Mgr::RegisterAction("store_digest", "Store Digest", storeDigestReport, 0, 1); } /* diff --git a/src/store_io.cc b/src/store_io.cc index 4f95df662c..eb4801e218 100644 --- a/src/store_io.cc +++ b/src/store_io.cc @@ -3,17 +3,7 @@ #include "MemObject.h" #include "SwapDir.h" -static struct { - - struct { - int calls; - int select_fail; - int create_fail; - int success; - } create; -} store_io_stats; - -OBJH storeIOStats; +StoreIoStats store_io_stats; /* * submit a request to create a cache object for writing. @@ -97,17 +87,3 @@ storeIOWrite(StoreIOState::Pointer sio, char const *buf, size_t size, off_t offs { sio->write(buf,size,offset,free_func); } - -/* - * Make this non-static so we can register - * it from storeInit(); - */ -void -storeIOStats(StoreEntry * sentry) -{ - storeAppendPrintf(sentry, "Store IO Interface Stats\n"); - storeAppendPrintf(sentry, "create.calls %d\n", store_io_stats.create.calls); - storeAppendPrintf(sentry, "create.select_fail %d\n", store_io_stats.create.select_fail); - storeAppendPrintf(sentry, "create.create_fail %d\n", store_io_stats.create.create_fail); - storeAppendPrintf(sentry, "create.success %d\n", store_io_stats.create.success); -} diff --git a/src/store_log.cc b/src/store_log.cc index 617c57e29e..a9640dce4c 100644 --- a/src/store_log.cc +++ b/src/store_log.cc @@ -33,10 +33,10 @@ */ #include "squid.h" -#include "CacheManager.h" #include "HttpReply.h" #include "log/File.h" #include "MemObject.h" +#include "mgr/Registration.h" #include "Store.h" #include "SquidTime.h" @@ -139,8 +139,7 @@ storeLogClose(void) static void storeLogRegisterWithCacheManager(void) { - CacheManager::GetInstance()-> - registerAction("store_log_tags", "Histogram of store.log tags", + Mgr::RegisterAction("store_log_tags", "Histogram of store.log tags", storeLogTagsHist, 0, 1); } diff --git a/src/structs.h b/src/structs.h index ee814a69fc..80e9563658 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1002,15 +1002,16 @@ struct _netdbEntry { int n_peers; }; - struct _iostats { + enum { histSize = 16 }; + struct { int reads; int reads_deferred; - int read_hist[16]; + int read_hist[histSize]; int writes; - int write_hist[16]; + int write_hist[histSize]; } Http, Ftp, Gopher; diff --git a/src/tests/stub_Port.cc b/src/tests/stub_Port.cc new file mode 100644 index 0000000000..478ce74443 --- /dev/null +++ b/src/tests/stub_Port.cc @@ -0,0 +1,4 @@ +#include "config.h" +#include "ipc/Port.h" + +const char Ipc::coordinatorAddr[] = ""; diff --git a/src/tests/stub_TypedMsgHdr.cc b/src/tests/stub_TypedMsgHdr.cc new file mode 100644 index 0000000000..52fc5c956d --- /dev/null +++ b/src/tests/stub_TypedMsgHdr.cc @@ -0,0 +1,44 @@ +#include "config.h" +#include "fatal.h" +#include "ipc/TypedMsgHdr.h" + +Ipc::TypedMsgHdr::TypedMsgHdr() +{ + fatal("Not implemented"); +} + +void +Ipc::TypedMsgHdr::getFixed(void *raw, size_t size) const +{ + fatal("Not implemented"); +} + +void +Ipc::TypedMsgHdr::putFixed(const void *raw, size_t size) +{ + fatal("Not implemented"); +} + +void +Ipc::TypedMsgHdr::getString(String &size) const +{ + fatal("Not implemented"); +} + +void +Ipc::TypedMsgHdr::putString(const String & size) +{ + fatal("Not implemented"); +} + +void +Ipc::TypedMsgHdr::checkType(int destType) const +{ + fatal("Not implemented"); +} + +void +Ipc::TypedMsgHdr::setType(int aType) +{ + fatal("Not implemented"); +} diff --git a/src/tests/stub_UdsOp.cc b/src/tests/stub_UdsOp.cc new file mode 100644 index 0000000000..7e19dd0200 --- /dev/null +++ b/src/tests/stub_UdsOp.cc @@ -0,0 +1,7 @@ +#include "config.h" +#include "ipc/UdsOp.h" + +void Ipc::SendMessage(const String& toAddress, const TypedMsgHdr& message) +{ + fatal ("Not implemented"); +} diff --git a/src/tests/stub_cache_manager.cc b/src/tests/stub_cache_manager.cc index b67584e549..7e4eb13feb 100644 --- a/src/tests/stub_cache_manager.cc +++ b/src/tests/stub_cache_manager.cc @@ -30,43 +30,39 @@ */ #include "CacheManager.h" +#include "mgr/Registration.h" #include "squid.h" -static CacheManager *cm=0; - -CacheManager::CacheManager() -{ -} - -void -CacheManager::registerAction(char const * action, char const * desc, OBJH * handler, int pw_req_flag, int atomic) +Mgr::Action::Pointer +CacheManager::createNamedAction(char const* action) { - return; + fatal ("Not implemented"); + return NULL; } void -CacheManager::registerAction(CacheManagerAction *anAction) +CacheManager::Start(int fd, HttpRequest * request, StoreEntry * entry) { return; } -CacheManagerAction * -CacheManager::findAction(char const * action) +CacheManager* +CacheManager::GetInstance(void) { - return 0; + static CacheManager *instance = 0; + if (!instance) + instance = new CacheManager(); + return instance; } void -CacheManager::Start(int fd, HttpRequest * request, StoreEntry * entry) +Mgr::RegisterAction(char const*, char const*, OBJH, int, int) { - return; } -CacheManager* -CacheManager::GetInstance(void) +void +Mgr::RegisterAction(char const * action, char const * desc, + Mgr::ClassActionCreationHandler *handler, + int pw_req_flag, int atomic) { - if (!cm) - cm=new CacheManager(); - return cm; } - diff --git a/src/tests/stub_comm.cc b/src/tests/stub_comm.cc index 132d5732de..45f8a8b906 100644 --- a/src/tests/stub_comm.cc +++ b/src/tests/stub_comm.cc @@ -156,3 +156,28 @@ _comm_close(int fd, char const *file, int line) { fatal ("Not implemented"); } + +int +commSetTimeout(int fd, int timeout, AsyncCall::Pointer& callback) +{ + fatal ("Not implemented"); + return -1; +} + +int +comm_open_uds(int sock_type, int proto, struct sockaddr_un* addr, int flags) +{ + fatal ("Not implemented"); + return -1; +} + +void +comm_write(int fd, const char *buf, int size, AsyncCall::Pointer &callback, FREE * free_func) +{ + fatal ("Not implemented"); +} + +ConnectionDetail::ConnectionDetail() : me(), peer() +{ + fatal ("Not implemented"); +} diff --git a/src/tests/stub_store_swapout.cc b/src/tests/stub_store_swapout.cc index fc46bae17a..655405847d 100644 --- a/src/tests/stub_store_swapout.cc +++ b/src/tests/stub_store_swapout.cc @@ -35,6 +35,8 @@ #include "squid.h" #include "Store.h" +StoreIoStats store_io_stats; + void StoreEntry::swapOutFileClose() { @@ -61,14 +63,6 @@ storeUnlink(StoreEntry * e) fatal ("Not implemented"); } - -void -storeIOStats(StoreEntry *) -{ - fatal ("Not implemented"); -} - - #include "StoreMeta.h" char * diff --git a/src/tests/stub_tools.cc b/src/tests/stub_tools.cc index 2e94e7d828..95537ed940 100644 --- a/src/tests/stub_tools.cc +++ b/src/tests/stub_tools.cc @@ -32,6 +32,7 @@ */ #include "config.h" +#include "protos.h" int percent(int a, int b) @@ -46,3 +47,10 @@ death(int sig) fprintf(stderr, "Not implemented"); exit(1); } + +void* +xmemset(void* dst, int val, size_t sz) +{ + assert(dst); + return memset(dst, val, sz); +} diff --git a/src/tests/testCacheManager.cc b/src/tests/testCacheManager.cc index 39d9d806a1..702a88fb69 100644 --- a/src/tests/testCacheManager.cc +++ b/src/tests/testCacheManager.cc @@ -2,6 +2,7 @@ #include "squid.h" #include +#include "mgr/Action.h" #include "Mem.h" #include "testCacheManager.h" @@ -41,16 +42,21 @@ void testCacheManager::testRegister() { CacheManager *manager=CacheManager::GetInstance(); + CPPUNIT_ASSERT(manager != NULL); - manager->registerAction("sample", "my sample", &dummy_action, false, false); - CacheManagerAction *anAction = manager->findAction("sample"); + manager->registerProfile("sample", "my sample", &dummy_action, false, false); + Mgr::Action::Pointer action = manager->createNamedAction("sample"); + CPPUNIT_ASSERT(action != NULL); - CPPUNIT_ASSERT_EQUAL(0, (int)anAction->flags.pw_req); - CPPUNIT_ASSERT_EQUAL(0, (int)anAction->flags.atomic); - CPPUNIT_ASSERT_EQUAL(String("sample"), String(anAction->action)); + const Mgr::ActionProfile::Pointer profile = action->command().profile; + CPPUNIT_ASSERT(profile != NULL); + CPPUNIT_ASSERT(profile->creator != NULL); + CPPUNIT_ASSERT_EQUAL(false, profile->isPwReq); + CPPUNIT_ASSERT_EQUAL(false, profile->isAtomic); + CPPUNIT_ASSERT_EQUAL(String("sample"), String(action->name())); StoreEntry *sentry=new StoreEntry(); sentry->flags=0x25; //arbitrary test value - anAction->run(sentry); + action->run(sentry, false); CPPUNIT_ASSERT_EQUAL(1,(int)sentry->flags); } diff --git a/src/ufsdump.cc b/src/ufsdump.cc index 72c0273b61..401cbdb6bb 100644 --- a/src/ufsdump.cc +++ b/src/ufsdump.cc @@ -37,6 +37,8 @@ #include "StoreMetaUnpacker.h" #include "Store.h" #include "Generic.h" +#include "mgr/Registration.h" + #undef malloc #undef free @@ -70,16 +72,8 @@ storeAppendPrintf(StoreEntry * e, const char *fmt,...) va_end(args); } -#include "CacheManager.h" -CacheManager* -CacheManager::GetInstance() -{ - assert(false); - return NULL; -} - void -CacheManager::registerAction(char const * action, char const * desc, OBJH * handler, int pw_req_flag, int atomic) {} +Mgr::RegisterAction(char const * action, char const * desc, OBJH * handler, int pw_req_flag, int atomic) {} /* MinGW needs also a stub of death() */ void -- 2.47.2