]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: cache: "show cache" on the cli
authorWilliam Lallemand <wlallemand@haproxy.com>
Tue, 21 Nov 2017 19:01:26 +0000 (20:01 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 21 Nov 2017 20:35:04 +0000 (21:35 +0100)
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)

src/cache.c

index 19a91b4a580ae3febf24b250d359b78ac1cd8ede..0d726c72913a5a9f81d3843ee2959b5a366ec6b3 100644 (file)
 #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 @@ struct flt_ops cache_ops = {
 
 };
 
+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 @@ static void __cache_init(void)
 {
        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);