"Hot Object" stats were not reported for shared memory cache.
Mean disk object size stats were aggregated inaccurately for SMP.
Moved Store-related stats into a dedicated StoreStats class,
encapsulating memory cache-related (mem), disk cache-related (swap), and
global store (number of objects) stats. Used consistent naming scheme
and a common parent class to make memory and disk stats more alike.
Moved Store stats collection into corresponding Store classes rather
than forcing GetInfo() in stat.cc to know how to deal with all Store stats.
StoreMetaVary.cc \
StoreMetaVary.h \
StoreSearch.h \
+ StoreStats.cc \
+ StoreStats.h \
StoreSwapLogData.cc \
StoreSwapLogData.h \
Server.cc \
tests/stub_HelperChildConfig.cc \
tests/stub_StatHist.cc \
tests/stub_store.cc \
+ tests/stub_store_stats.cc \
tests/testHttpReply.cc \
tests/testHttpReply.h \
tests/testMain.cc \
tests/stub_mime.cc \
tests/stub_store.cc \
tests/stub_store_rebuild.cc \
+ tests/stub_store_stats.cc \
tests/stub_store_swapout.cc \
tests/stub_tools.cc \
tests/stub_cache_manager.cc \
tests/testMain.cc \
tests/stub_main_cc.cc \
tests/stub_ipc_Forwarder.cc \
+ tests/stub_store_stats.cc \
time.cc \
BodyPipe.cc \
cache_manager.cc \
tests/stub_pconn.cc \
tests/stub_Port.cc \
tests/stub_store_client.cc \
+ tests/stub_store_stats.cc \
tests/stub_store_rebuild.cc \
tests/stub_tools.cc \
tests/stub_UdsOp.cc \
tests/testMain.cc \
tests/stub_main_cc.cc \
tests/stub_ipc_Forwarder.cc \
+ tests/stub_store_stats.cc \
time.cc \
tools.cc \
tunnel.cc \
tests/testMain.cc \
tests/stub_main_cc.cc \
tests/stub_ipc_Forwarder.cc \
+ tests/stub_store_stats.cc \
time.cc \
tools.cc \
tunnel.cc \
tests/stub_ipc_Forwarder.cc \
tests/stub_main_cc.cc \
tests/stub_MemStore.cc \
+ tests/stub_store_stats.cc \
time.cc \
tools.cc \
tunnel.cc \
tests/stub_DiskIOModule.cc \
tests/stub_main_cc.cc \
tests/stub_ipc_Forwarder.cc \
+ tests/stub_store_stats.cc \
time.cc \
BodyPipe.cc \
cache_manager.cc \
tests/stub_mime.cc \
tests/stub_Port.cc \
tests/stub_store_client.cc \
+ tests/stub_store_stats.cc \
tests/stub_store_rebuild.cc \
tests/stub_store_swapout.cc \
tests/stub_tools.cc \
tests/stub_UdsOp.cc \
tests/stub_internal.cc \
tests/stub_store_rebuild.cc \
+ tests/stub_store_stats.cc \
fd.cc \
disk.cc \
filemap.cc \
tests/stub_pconn.cc \
tests/stub_store_client.cc \
tests/stub_store_rebuild.cc \
+ tests/stub_store_stats.cc \
tests/stub_tools.cc \
tests/stub_UdsOp.cc \
time.cc \
tests/stub_ipc.cc \
tests/stub_pconn.cc \
tests/stub_store_rebuild.cc \
+ tests/stub_store_stats.cc \
fd.cc \
disk.cc \
filemap.cc \
tests/stub_MemStore.cc \
tests/stub_Port.cc \
tests/stub_store_client.cc \
+ tests/stub_store_stats.cc \
tests/stub_tools.cc \
tests/stub_UdsOp.cc \
tests/testStoreSupport.cc \
tests/stub_internal.cc \
tests/stub_CommIO.cc \
tests/stub_store_rebuild.cc \
+ tests/stub_store_stats.cc \
fd.cc \
disk.cc \
filemap.cc \
tests/stub_access_log.cc \
refresh.cc \
tests/stub_store_client.cc \
+ tests/stub_store_stats.cc \
tests/stub_tools.cc \
tests/testStoreSupport.cc \
tests/testStoreSupport.h \
tests/stub_DiskIOModule.cc \
tests/stub_main_cc.cc \
tests/stub_ipc_Forwarder.cc \
+ tests/stub_store_stats.cc \
tests/testURL.cc \
tests/testURL.h \
tests/testURLScheme.cc \
#include "ipc/mem/Pages.h"
#include "MemObject.h"
#include "MemStore.h"
+#include "StoreStats.h"
#include "HttpReply.h"
/// shared memory segment path to use for MemStore maps
map->cleaner = this;
}
+void
+MemStore::getStats(StoreInfoStats &stats) const
+{
+ const size_t pageSize = Ipc::Mem::PageSize();
+
+ stats.mem.shared = true;
+ stats.mem.capacity =
+ Ipc::Mem::PageLimit(Ipc::Mem::PageId::cachePage) * pageSize;
+ stats.mem.size =
+ Ipc::Mem::PageLevel(Ipc::Mem::PageId::cachePage) * pageSize;
+ stats.mem.count = currentCount();
+}
+
void
MemStore::stat(StoreEntry &e) const
{
virtual uint64_t currentSize() const;
virtual uint64_t currentCount() const;
virtual int64_t maxObjectSize() const;
+ virtual void getStats(StoreInfoStats &stats) const;
virtual void stat(StoreEntry &) const;
virtual StoreSearch *search(String const url, HttpRequest *);
virtual void reference(StoreEntry &);
#include "comm/forward.h"
#include "Packer.h"
#include "RemovalPolicy.h"
+#include "StoreStats.h"
#if USE_SQUID_ESI
#include "esi/Element.h"
class StoreSearch;
class SwapDir;
-typedef struct {
-
- struct {
- int calls;
- int select_fail;
- int create_fail;
- int success;
- } create;
-} StoreIoStats;
-
extern StoreIoStats store_io_stats;
/// maximum number of entries per cache_dir
/** the maximum object size that can be stored, -1 if unlimited */
virtual int64_t maxObjectSize() const = 0;
+ /// collect cache storage-related statistics
+ virtual void getStats(StoreInfoStats &stats) const = 0;
+
/**
* Output stats to the provided store entry.
\todo make these calls asynchronous
virtual int64_t maxObjectSize() const;
+ virtual void getStats(StoreInfoStats &stats) const;
virtual void stat(StoreEntry&) const;
virtual void reference(StoreEntry&);
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 20 Storage Manager Statistics
+ *
+ */
+
+#include "config.h"
+#include "protos.h" /* for xmemset only */
+#include "StoreStats.h"
+
+
+/* StoreInfoStats */
+
+StoreInfoStats::StoreInfoStats()
+{
+ xmemset(this, 0, sizeof(*this));
+}
+
+StoreInfoStats &
+StoreInfoStats::operator +=(const StoreInfoStats &stats)
+{
+ swap.size += stats.swap.size;
+ swap.capacity += stats.swap.capacity;
+ swap.count += stats.swap.count;
+ swap.open_disk_fd += stats.swap.open_disk_fd;
+
+ // Assume that either all workers use shared memory cache or none do.
+ // It is possible but difficult to report correct stats for an arbitrary
+ // mix, and only rather unusual deployments can benefit from mixing.
+
+ // If workers share memory, we will get shared stats from those workers
+ // and non-shared stats from other processes. Ignore order and also
+ // ignore other processes stats because they are zero in most setups.
+ if (stats.mem.shared) { // workers share memory
+ // use the latest reported stats, they all should be about the same
+ mem.shared = true;
+ mem.size = stats.mem.size;
+ mem.capacity = stats.mem.capacity;
+ mem.count = stats.mem.count;
+ } else if (!mem.shared) { // do not corrupt shared stats, if any
+ // workers do not share so we must add everything up
+ mem.size += stats.mem.size;
+ mem.capacity += stats.mem.capacity;
+ mem.count += stats.mem.count;
+ }
+
+ store_entry_count += stats.store_entry_count;
+ mem_object_count += stats.mem_object_count;
+
+ return *this;
+}
+
+
+
+/* StoreIoStats */
+
+StoreIoStats::StoreIoStats()
+{
+ xmemset(this, 0, sizeof(*this));
+}
+
--- /dev/null
+#ifndef SQUID_STORE_STATS_H
+#define SQUID_STORE_STATS_H
+
+/// High-level store statistics used by mgr:info action. Used inside PODs!
+class StoreInfoStats {
+public:
+ /// Info common to memory and disk parts of the storage. Used inside PODs!
+ class Part {
+ public:
+ double size; ///< bytes currently in use
+ double count; ///< number of cached objects
+ double capacity; ///< the size limit
+
+ /// mean size of a cached object
+ double meanObjectSize() const { return count > 0 ? size/count : 0.0; }
+
+ /// number of unused bytes
+ double available() const { return capacity - size; }
+ };
+
+ /// disk cache (all cache_dirs) storage stats
+ class Swap: public Part {
+ public:
+ double open_disk_fd; ///< number of opened disk files
+ };
+
+ /// memory cache (cache_mem) storage stats
+ class Mem: public Part {
+ public:
+ bool shared; ///< whether memory cache is shared among workers
+ };
+
+
+ StoreInfoStats();
+ StoreInfoStats &operator +=(const StoreInfoStats &stats);
+
+
+ Swap swap; ///< cache_mem stats
+ Mem mem; ///< all cache_dirs stats
+
+ /* stats that could be shared by memory and disk storage */
+ double store_entry_count; ///< number of StoreEntry objects in existence
+ double mem_object_count; ///< number of MemObject objects in existence
+};
+
+// TODO: this should be adjusted for use in StoreIoActionData, DiskdActionData
+/// Store statistics related to low-level I/O.
+class StoreIoStats {
+public:
+ StoreIoStats();
+
+ struct {
+ int calls;
+ int select_fail;
+ int create_fail;
+ int success;
+ } create; ///< cache_dir selection and disk entry creation stats
+};
+
+#endif /* SQUID_STORE_STATS_H */
void
SwapDir::unlink(StoreEntry &) {}
+void
+SwapDir::getStats(StoreInfoStats &stats) const
+{
+ if (!doReportStat())
+ return;
+
+ stats.swap.size = currentSize();
+ stats.swap.capacity = maxSize();
+ stats.swap.count = currentCount();
+}
+
void
SwapDir::stat(StoreEntry &output) const
{
virtual int64_t maxObjectSize() const;
+ virtual void getStats(StoreInfoStats &stats) const;
virtual void stat(StoreEntry &) const;
virtual void sync(); /* Sync the store prior to shutdown */
virtual int64_t maxObjectSize() const { return max_objsize; }
+ virtual void getStats(StoreInfoStats &stats) const;
virtual void stat (StoreEntry &anEntry) const;
virtual StoreSearch *search(String const url, HttpRequest *) = 0;
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;
+
+ store += stats.store;
+
unlink_requests += stats.unlink_requests;
http_requests5 += stats.http_requests5;
http_requests60 += stats.http_requests60;
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;
#define SQUID_MGR_INFO_ACTION_H
#include "mgr/Action.h"
+#include "StoreStats.h"
#include <sys/time.h>
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;
+
+ StoreInfoStats store; ///< disk and memory cache statistics
+
double unlink_requests;
double http_requests5;
double http_requests60;
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;
};
stats.request_hit_disk_ratio5 = statRequestHitDiskRatio(5);
stats.request_hit_disk_ratio60 = statRequestHitDiskRatio(60);
- stats.store_swap_size = Store::Root().currentSize() / 1024.0;
- 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.n_disk_objects = Store::Root().currentCount();
- stats.objects_size = stats.n_disk_objects > 0 ?
- stats.store_swap_size / stats.n_disk_objects : 0.0;
+ Store::Root().getStats(stats.store);
stats.unlink_requests = statCounter.unlink.requests;
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;
}
void
stats.request_hit_disk_ratio60 / fct);
storeAppendPrintf(sentry, "\tStorage Swap size:\t%.0f KB\n",
- stats.store_swap_size);
+ stats.store.swap.size / 1024);
storeAppendPrintf(sentry, "\tStorage Swap capacity:\t%4.1f%% used, %4.1f%% free\n",
- 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));
+ Math::doublePercent(stats.store.swap.size, stats.store.swap.capacity),
+ Math::doublePercent(stats.store.swap.available(), stats.store.swap.capacity));
storeAppendPrintf(sentry, "\tStorage Mem size:\t%.0f KB\n",
- stats.store_mem_size / 1024);
+ stats.store.mem.size / 1024);
- 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(stats.store_mem_used, stats.store_pages_max),
- Math::doublePercent(mFree, stats.store_pages_max));
+ Math::doublePercent(stats.store.mem.size, stats.store.mem.capacity),
+ Math::doublePercent(stats.store.mem.available(), stats.store.mem.capacity));
storeAppendPrintf(sentry, "\tMean Object Size:\t%0.2f KB\n",
- stats.objects_size / fct);
+ stats.store.swap.meanObjectSize() / 1024);
storeAppendPrintf(sentry, "\tRequests given to unlinkd:\t%.0f\n",
stats.unlink_requests);
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);
+ stats.store.swap.open_disk_fd);
storeAppendPrintf(sentry, "Internal Data Structures:\n");
storeAppendPrintf(sentry, "\t%6.0f StoreEntries\n",
- stats.store_entries);
+ stats.store.store_entry_count);
storeAppendPrintf(sentry, "\t%6.0f StoreEntries with MemObjects\n",
- stats.store_mem_entries);
+ stats.store.mem_object_count);
storeAppendPrintf(sentry, "\t%6.0f Hot Object Cache Items\n",
- stats.hot_obj_count);
+ stats.store.mem.count);
storeAppendPrintf(sentry, "\t%6.0f on-disk objects\n",
- stats.n_disk_objects);
+ stats.store.swap.count);
}
void
dynamic_cast<SwapDir *>(INDEXSD(e->swap_dirn))->logEntry(*e, op);
}
+void
+StoreController::getStats(StoreInfoStats &stats) const
+{
+ if (memStore)
+ memStore->getStats(stats);
+ else {
+ // move this code to a non-shared memory cache class when we have it
+ stats.mem.shared = false;
+ stats.mem.capacity = Config.memMaxSize;
+ stats.mem.size = mem_node::StoreMemSize();
+ stats.mem.count = hot_obj_count;
+ }
+
+ swapDir->getStats(stats);
+
+ // low-level info not specific to memory or disk cache
+ stats.store_entry_count = StoreEntry::inUseCount();
+ stats.mem_object_count = MemObject::inUseCount();
+}
+
void
StoreController::stat(StoreEntry &output) const
{
return result;
}
+void
+StoreHashIndex::getStats(StoreInfoStats &stats) const
+{
+ // accumulate per-disk cache stats
+ for (int i = 0; i < Config.cacheSwap.n_configured; i++) {
+ StoreInfoStats dirStats;
+ store(i)->getStats(dirStats);
+ stats += dirStats;
+ }
+
+ // common to all disks
+ stats.swap.open_disk_fd = store_open_disk_fd;
+
+ // memory cache stats are collected in StoreController::getStats(), for now
+}
+
void
StoreHashIndex::stat(StoreEntry & output) const
{
{
fatal ("MemObject.cc required.");
}
+
+size_t
+MemObject::inUseCount()
+{
+ fatal ("MemObject.cc required.");
+ return 0;
+}
void MemStore::cleanReadable(const sfileno) STUB
void MemStore::get(String const, STOREGETCLIENT, void *) STUB
void MemStore::init() STUB
+void MemStore::getStats(StoreInfoStats&) const STUB
void MemStore::stat(StoreEntry &) const STUB
int MemStore::callback() STUB_RETVAL(0)
StoreEntry *MemStore::get(const cache_key *) STUB_RETVAL(NULL)
--- /dev/null
+#include "squid.h"
+
+#define STUB_API "StoreStats.cc"
+#include "tests/STUB.h"
+
+#include "StoreStats.h"
+#include <cstring>
+
+StoreInfoStats::StoreInfoStats() STUB
+
+StoreInfoStats &
+StoreInfoStats::operator +=(const StoreInfoStats &stats) STUB_RETVAL(*this)
+
+StoreIoStats::StoreIoStats()
+{
+ // we have to implement this one because tests/stub_store.cc
+ // has a StoreIoStats global
+ memset(this, 0, sizeof(*this));
+}
return 1;
}
+void
+TestStore::getStats(StoreInfoStats &) const
+{
+}
+
void
TestStore::stat(StoreEntry &) const
{
virtual int64_t maxObjectSize() const;
+ virtual void getStats(StoreInfoStats &) const;
+
virtual void stat(StoreEntry &) const; /* output stats to the provided store entry */
virtual void reference(StoreEntry &) {} /* Reference this object */