From a356bac1a8789fd3da2b071cb4cb801bc941244e Mon Sep 17 00:00:00 2001 From: Pere Diaz Bou Date: Wed, 26 May 2021 17:47:06 +0200 Subject: [PATCH] mgr: TTLCache basic implementation Signed-off-by: Pere Diaz Bou Fixes: https://tracker.ceph.com/issues/48388 --- qa/mgr_ttl_cache/disable.yaml | 5 + qa/mgr_ttl_cache/enable.yaml | 5 + qa/suites/rados/mgr/mgr_ttl_cache/.qa | 1 + .../rados/mgr/mgr_ttl_cache/disable.yaml | 1 + qa/suites/rados/mgr/mgr_ttl_cache/enable.yaml | 1 + qa/tasks/ceph_test_case.py | 5 + qa/tasks/mgr/test_cache.py | 83 +++++++++ src/common/Formatter.h | 3 + src/common/options.cc | 8 +- src/mgr/ActivePyModules.cc | 160 +++++++++++------- src/mgr/ActivePyModules.h | 7 + src/mgr/BaseMgrModule.cc | 3 +- src/mgr/CMakeLists.txt | 1 + src/mgr/Gil.h | 2 +- src/mgr/MgrStandby.cc | 9 +- src/mgr/PyFormatter.cc | 13 ++ src/mgr/PyFormatter.h | 18 ++ src/mgr/TTLCache.cc | 100 +++++++++++ src/mgr/TTLCache.h | 124 ++++++++++++++ src/mgr/mgr_perf_counters.cc | 28 +++ src/mgr/mgr_perf_counters.h | 20 +++ src/pybind/mgr/mgr_module.py | 6 +- src/test/mgr/CMakeLists.txt | 7 +- src/test/mgr/test_ttlcache.cc | 70 ++++++++ 24 files changed, 610 insertions(+), 70 deletions(-) create mode 100644 qa/mgr_ttl_cache/disable.yaml create mode 100644 qa/mgr_ttl_cache/enable.yaml create mode 120000 qa/suites/rados/mgr/mgr_ttl_cache/.qa create mode 120000 qa/suites/rados/mgr/mgr_ttl_cache/disable.yaml create mode 120000 qa/suites/rados/mgr/mgr_ttl_cache/enable.yaml create mode 100644 qa/tasks/mgr/test_cache.py create mode 100644 src/mgr/TTLCache.cc create mode 100644 src/mgr/TTLCache.h create mode 100644 src/mgr/mgr_perf_counters.cc create mode 100644 src/mgr/mgr_perf_counters.h create mode 100644 src/test/mgr/test_ttlcache.cc diff --git a/qa/mgr_ttl_cache/disable.yaml b/qa/mgr_ttl_cache/disable.yaml new file mode 100644 index 0000000000000..bbd78d53f2f85 --- /dev/null +++ b/qa/mgr_ttl_cache/disable.yaml @@ -0,0 +1,5 @@ +overrides: + ceph: + conf: + mgr: + mgr ttl cache expire seconds: 0 diff --git a/qa/mgr_ttl_cache/enable.yaml b/qa/mgr_ttl_cache/enable.yaml new file mode 100644 index 0000000000000..2c1c0e0533ec2 --- /dev/null +++ b/qa/mgr_ttl_cache/enable.yaml @@ -0,0 +1,5 @@ +overrides: + ceph: + conf: + mgr: + mgr ttl cache expire seconds: 5 diff --git a/qa/suites/rados/mgr/mgr_ttl_cache/.qa b/qa/suites/rados/mgr/mgr_ttl_cache/.qa new file mode 120000 index 0000000000000..fea2489fdf6d9 --- /dev/null +++ b/qa/suites/rados/mgr/mgr_ttl_cache/.qa @@ -0,0 +1 @@ +../.qa \ No newline at end of file diff --git a/qa/suites/rados/mgr/mgr_ttl_cache/disable.yaml b/qa/suites/rados/mgr/mgr_ttl_cache/disable.yaml new file mode 120000 index 0000000000000..d7db486dd9f12 --- /dev/null +++ b/qa/suites/rados/mgr/mgr_ttl_cache/disable.yaml @@ -0,0 +1 @@ +.qa/mgr_ttl_cache/disable.yaml \ No newline at end of file diff --git a/qa/suites/rados/mgr/mgr_ttl_cache/enable.yaml b/qa/suites/rados/mgr/mgr_ttl_cache/enable.yaml new file mode 120000 index 0000000000000..18286a656bafa --- /dev/null +++ b/qa/suites/rados/mgr/mgr_ttl_cache/enable.yaml @@ -0,0 +1 @@ +.qa/mgr_ttl_cache/enable.yaml \ No newline at end of file diff --git a/qa/tasks/ceph_test_case.py b/qa/tasks/ceph_test_case.py index 7040853dfb437..0de395c0682a7 100644 --- a/qa/tasks/ceph_test_case.py +++ b/qa/tasks/ceph_test_case.py @@ -86,6 +86,11 @@ class CephTestCase(unittest.TestCase): self._mon_configs_set.add((section, key)) self.ceph_cluster.mon_manager.raw_cluster_cmd("config", "set", section, key, str(value)) + def cluster_cmd(self, command: str): + assert self.ceph_cluster is not None + return self.ceph_cluster.mon_manager.raw_cluster_cmd(*(command.split(" "))) + + def assert_cluster_log(self, expected_pattern, invert_match=False, timeout=10, watch_channel=None): """ diff --git a/qa/tasks/mgr/test_cache.py b/qa/tasks/mgr/test_cache.py new file mode 100644 index 0000000000000..71131cbc6afa6 --- /dev/null +++ b/qa/tasks/mgr/test_cache.py @@ -0,0 +1,83 @@ +import json + +from .mgr_test_case import MgrTestCase + +class TestCache(MgrTestCase): + + def setUp(self): + super(TestCache, self).setUp() + self.setup_mgrs() + self._load_module("cli_api") + self.ttl = 10 + self.enable_cache(self.ttl) + + def tearDown(self): + self.disable_cache() + + def get_hit_miss_ratio(self): + perf_dump_command = f"daemon mgr.{self.mgr_cluster.get_active_id()} perf dump" + perf_dump_res = self.cluster_cmd(perf_dump_command) + perf_dump = json.loads(perf_dump_res) + h = perf_dump["mgr"]["cache_hit"] + m = perf_dump["mgr"]["cache_miss"] + return int(h), int(m) + + def enable_cache(self, ttl): + set_ttl = f"config set mgr mgr_ttl_cache_expire_seconds {ttl}" + self.cluster_cmd(set_ttl) + + def disable_cache(self): + set_ttl = "config set mgr mgr_ttl_cache_expire_seconds 0" + self.cluster_cmd(set_ttl) + + + def test_init_cache(self): + get_ttl = "config get mgr mgr_ttl_cache_expire_seconds" + res = self.cluster_cmd(get_ttl) + self.assertEquals(int(res), 10) + + def test_health_not_cached(self): + get_health = "mgr api get health" + + h_start, m_start = self.get_hit_miss_ratio() + self.cluster_cmd(get_health) + h, m = self.get_hit_miss_ratio() + + self.assertEquals(h, h_start) + self.assertEquals(m, m_start) + + def test_osdmap(self): + get_osdmap = "mgr api get osd_map" + + # store in cache + self.cluster_cmd(get_osdmap) + # get from cache + res = self.cluster_cmd(get_osdmap) + osd_map = json.loads(res) + self.assertIn("osds", osd_map) + self.assertGreater(len(osd_map["osds"]), 0) + self.assertIn("epoch", osd_map) + + + + def test_hit_miss_ratio(self): + get_osdmap = "mgr api get osd_map" + + hit_start, miss_start = self.get_hit_miss_ratio() + + def wait_miss(): + self.cluster_cmd(get_osdmap) + _, m = self.get_hit_miss_ratio() + return m == miss_start + 1 + + # Miss, add osd_map to cache + self.wait_until_true(wait_miss, self.ttl + 5) + h, m = self.get_hit_miss_ratio() + self.assertEquals(h, hit_start) + self.assertEquals(m, miss_start+1) + + # Hit, get osd_map from cache + self.cluster_cmd(get_osdmap) + h, m = self.get_hit_miss_ratio() + self.assertEquals(h, hit_start+1) + self.assertEquals(m, miss_start+1) diff --git a/src/common/Formatter.h b/src/common/Formatter.h index e57ede878d9e5..6751e4709ce0b 100644 --- a/src/common/Formatter.h +++ b/src/common/Formatter.h @@ -171,6 +171,8 @@ namespace ceph { return false; /* is handling done? */ } + int stack_size() { return m_stack.size(); } + private: struct json_formatter_stack_entry_d { @@ -309,3 +311,4 @@ namespace ceph { std::string fixed_u_to_string(uint64_t num, int scale); } #endif + diff --git a/src/common/options.cc b/src/common/options.cc index a5d22fb638506..908221eb13465 100644 --- a/src/common/options.cc +++ b/src/common/options.cc @@ -5735,7 +5735,13 @@ std::vector