MEDIUM: cache: "show cache" on the cli
The cli command "show cache" displays the status of the cache, the first
displayed line is the shctx informations with how much blocks available
blocks it contains (blocks are 1k by default).
The next lines are the objects stored in the cache tree, the pointer,
the size of the object and how much blocks it uses, a refcount for the
number of users of the object, and the remaining expiration time (which
can be negative if expired)
Example:
$ echo "show cache" | socat - /run/haproxy.sock
0x7fa54e9ab03a: foobar (shctx:0x7fa54e9ab000, available blocks:3921)
0x7fa54ed65b8c (size: 43190 (43 blocks), refcount:2, expire: 2)
0x7fa54ecf1b4c (size: 45238 (45 blocks), refcount:0, expire: 2)
0x7fa54ed70cec (size: 61622 (61 blocks), refcount:0, expire: 2)
0x7fa54ecdbcac (size: 42166 (42 blocks), refcount:1, expire: 2)
0x7fa54ec9736c (size: 44214 (44 blocks), refcount:2, expire: 2)
0x7fa54eca28ec (size: 46262 (46 blocks), refcount:2, expire: -2)
diff --git a/src/cache.c b/src/cache.c
index 19a91b4..0d726c7 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -13,11 +13,13 @@
#include <eb32tree.h>
#include <types/action.h>
+#include <types/cli.h>
#include <types/filters.h>
#include <types/proxy.h>
#include <types/shctx.h>
#include <proto/channel.h>
+#include <proto/cli.h>
#include <proto/proxy.h>
#include <proto/hdr_idx.h>
#include <proto/filters.h>
@@ -835,6 +837,74 @@
};
+static int cli_parse_show_cache(char **args, struct appctx *appctx, void *private)
+{
+ if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
+ return 1;
+
+ return 0;
+}
+
+static int cli_io_handler_show_cache(struct appctx *appctx)
+{
+ struct cache* cache = appctx->ctx.cli.p0;
+ struct stream_interface *si = appctx->owner;
+
+ chunk_reset(&trash);
+
+
+ if (cache == NULL) {
+ cache = LIST_ELEM((caches).n, typeof(struct cache *), list);
+ }
+
+ list_for_each_entry_from(cache, &caches, list) {
+ struct eb32_node *node = NULL;
+ unsigned int next_key;
+ struct cache_entry *entry;
+
+ chunk_appendf(&trash, "%p: %s (shctx:%p, available blocks:%d)\n", cache, cache->id, shctx_ptr(cache), shctx_ptr(cache)->nbav);
+
+ next_key = appctx->ctx.cli.i0;
+
+ appctx->ctx.cli.p0 = cache;
+
+ while (1) {
+
+ shctx_lock(shctx_ptr(cache));
+ node = eb32_lookup_ge(&cache->entries, next_key);
+ if (!node) {
+ shctx_unlock(shctx_ptr(cache));
+ break;
+ }
+
+ entry = container_of(node, struct cache_entry, eb);
+ chunk_appendf(&trash, "%p (size: %u (%u blocks), refcount:%u, expire: %d)\n", entry, block_ptr(entry)->len, block_ptr(entry)->block_count, block_ptr(entry)->refcount, entry->expire - (int)now.tv_sec);
+
+ next_key = node->key + 1;
+ appctx->ctx.cli.i0 = next_key;
+
+ shctx_unlock(shctx_ptr(cache));
+
+ if (ci_putchk(si_ic(si), &trash) == -1) {
+ si_applet_cant_put(si);
+ return 0;
+ }
+ }
+
+ }
+
+ return 1;
+
+}
+
+static struct cli_kw_list cli_kws = {{},{
+ { { "show", "cache", NULL },
+ "show cache : show cache status",
+ cli_parse_show_cache, cli_io_handler_show_cache, NULL,
+ },
+}};
+
+
static struct action_kw_list http_res_actions = {
.kw = {
{ "cache-store", parse_cache_store },
@@ -861,6 +931,7 @@
{
cfg_register_section("cache", cfg_parse_cache, cfg_post_parse_section_cache);
cfg_register_postparser("cache", cfg_cache_postparser);
+ cli_register_kw(&cli_kws);
http_res_keywords_register(&http_res_actions);
http_req_keywords_register(&http_req_actions);
pool2_cache_st = create_pool("cache_st", sizeof(struct cache_st), MEM_F_SHARED);