From d4dbc33c4669942ff2281ae476f3b98d7128bfe7 Mon Sep 17 00:00:00 2001 From: Michal Bloch Date: Wed, 1 Feb 2023 19:02:01 +0100 Subject: [PATCH] dlog_logger: refactor QoS distributions * now there's a getter that returns the appropriate func, instead of it being parsed inside config preparation code * the func is now a member of the QoS module struct instead of being global (this is related to the plan of wrapping logger readers in the server struct, since that contains an object of type QoS module) Change-Id: Ic08bc091079e280c891f78b1358d68d63b377669 Signed-off-by: Michal Bloch --- src/logger/logger.c | 19 ++----------------- src/logger/logger_internal.h | 1 + src/logger/qos.c | 4 +--- src/logger/qos.h | 13 ++++++------- src/logger/qos_distributions.c | 35 ++++++++++++++++++++++++++++++----- src/tests/qos_distributions.c | 15 +++++++++++++++ 6 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/logger/logger.c b/src/logger/logger.c index a67a191..63bfb8c 100644 --- a/src/logger/logger.c +++ b/src/logger/logger.c @@ -707,6 +707,7 @@ int logger_create(struct logger_config_data *data, struct logger *l) l->qos.threshold_reapply = data->qos_threshold_reapply; l->qos.limit_duration = data->qos_limit_duration; l->qos.file_path = data->qos_file_path; + l->qos.distribution_func = data->distribution_func; data->qos_file_path = NULL; // Check if the daemon is being launched for the first time since reboot @@ -1126,23 +1127,7 @@ int prepare_config_data(struct logger_config_data *data) data->qos_max_throughput = log_config_get_int(&conf, "qos_max_throughput_logs", DEFAULT_QOS_THROUGHPUT_LOGS); data->qos_threshold = log_config_get_int(&conf, "qos_threshold_logs", DEFAULT_QOS_THRESHOLD_LOGS); data->qos_threshold_reapply = log_config_get_int(&conf, "qos_threshold_reapply_logs", DEFAULT_QOS_THRESHOLD_REAPPLY_LOGS); - - struct { - void (*func)(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count); - const char *name; - } const qos_methods[] = { - { qos_distribution_proportional_raw , "proportional_raw" }, - { qos_distribution_proportional_talmud, "proportional_talmud" }, - { qos_distribution_equal , "equal" }, - { qos_distribution_equal_dual , "equal_dual" }, - { qos_distribution_equal_multi , "equal_multi" }, - }; - qos_distribution_func = qos_distribution_equal_multi; // default - const char *const qos_method = log_config_get(&conf, "qos_method"); - if (qos_method) - for (int i = 0; i < NELEMS(qos_methods); ++i) - if (!strcmp(qos_method, qos_methods[i].name)) - qos_distribution_func = qos_methods[i].func; + data->distribution_func = qos_get_distribution_func_by_name(log_config_get(&conf, "qos_method")); const char *const first_time_file_path = log_config_get(&conf, "first_time_file_path"); data->first_time_file_path = first_time_file_path ? strdup(first_time_file_path) : NULL; diff --git a/src/logger/logger_internal.h b/src/logger/logger_internal.h index 31fdc8f..ef3fab7 100644 --- a/src/logger/logger_internal.h +++ b/src/logger/logger_internal.h @@ -162,6 +162,7 @@ struct logger_config_data { int qos_limit_duration; int qos_threshold; int qos_threshold_reapply; + qos_distribution_func distribution_func; char *first_time_file_path; log_print_format default_format; }; diff --git a/src/logger/qos.c b/src/logger/qos.c index c780beb..a8ddfc6 100644 --- a/src/logger/qos.c +++ b/src/logger/qos.c @@ -18,8 +18,6 @@ #include #include -void (*qos_distribution_func)(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count); - bool qos_is_enabled(const struct qos_module *qos) { assert(qos); @@ -60,7 +58,7 @@ void qos_create_limits_file(struct qos_module *qos, bool is_limiting) } } - qos_distribution_func(qos, aggr_infos, aggr_count); + qos->distribution_func(qos, aggr_infos, aggr_count); const int len = aggr_count * 32; __attribute__((cleanup(free_ptr))) char *buf = malloc(len); diff --git a/src/logger/qos.h b/src/logger/qos.h index 9aee812..650207d 100644 --- a/src/logger/qos.h +++ b/src/logger/qos.h @@ -25,7 +25,12 @@ struct metrics_pid_aggr_info { int count; }; +struct qos_module; + +typedef void (*qos_distribution_func)(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count); + struct qos_module { + qos_distribution_func distribution_func; struct metrics *log_metrics; char *file_path; int max_throughput; @@ -36,13 +41,7 @@ struct qos_module { bool currently_limiting; }; -extern void (*qos_distribution_func)(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count); - -void qos_distribution_equal(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count); -void qos_distribution_equal_dual(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count); -void qos_distribution_equal_multi(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count); -void qos_distribution_proportional_raw(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count); -void qos_distribution_proportional_talmud(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count); +qos_distribution_func qos_get_distribution_func_by_name(const char *name); bool qos_is_enabled(const struct qos_module *qos); void qos_create_limits_file(struct qos_module *qos, bool is_limiting); diff --git a/src/logger/qos_distributions.c b/src/logger/qos_distributions.c index 2fe499f..60813a1 100644 --- a/src/logger/qos_distributions.c +++ b/src/logger/qos_distributions.c @@ -1,5 +1,7 @@ #include "qos.h" +#include + #include #include @@ -17,7 +19,7 @@ static inline int sort_by_count(const void *vlhs, const void *vrhs) return lhs->count - rhs->count; } -void qos_distribution_proportional_raw(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count) +static void qos_distribution_proportional_raw(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count) { const double proportion = (double) qos->max_throughput / (metrics_get_total(qos->log_metrics) ?: 1); @@ -25,7 +27,7 @@ void qos_distribution_proportional_raw(struct qos_module *qos, struct metrics_pi infos[i].count = (int) (infos[i].count * proportion + 0.5); } -void qos_distribution_equal(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count) +static void qos_distribution_equal(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count) { /* round upwards so that it's never 0, to give all clients a chance * to log at least something (so a developer can tell it's alive) */ @@ -36,7 +38,7 @@ void qos_distribution_equal(struct qos_module *qos, struct metrics_pid_aggr_info } -void qos_distribution_equal_dual(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count) +static void qos_distribution_equal_dual(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count) { /* Anything below the "equal" threshold is unlimited. * The ones above this limit get leftovers distributed @@ -62,7 +64,7 @@ void qos_distribution_equal_dual(struct qos_module *qos, struct metrics_pid_aggr infos[i].count = -1; } -void qos_distribution_equal_multi(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count) +static void qos_distribution_equal_multi(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count) { /* Similar to 'dual', except anything not reaching the higher * threshold also gets an unlimited pass (which increases the @@ -97,7 +99,7 @@ void qos_distribution_equal_multi(struct qos_module *qos, struct metrics_pid_agg infos[i].count = -1; } -void qos_distribution_proportional_talmud(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count) +static void qos_distribution_proportional_talmud(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count) { /* As proscribed by the talmudic contested garment rule. * Probably makes little sense given how our QoS works but @@ -138,3 +140,26 @@ void qos_distribution_proportional_talmud(struct qos_module *qos, struct metrics infos[i].count = upper_half ? infos[i].count - final_level : final_level; } +qos_distribution_func qos_get_distribution_func_by_name(const char *name) +{ + if (!name) + return qos_distribution_equal_multi; + + static struct { + void (*func)(struct qos_module *qos, struct metrics_pid_aggr_info *infos, int count); + const char *name; + } qos_methods[] = { + { qos_distribution_proportional_raw , "proportional_raw" }, + { qos_distribution_proportional_talmud, "proportional_talmud" }, + { qos_distribution_equal , "equal" }, + { qos_distribution_equal_dual , "equal_dual" }, + { qos_distribution_equal_multi , "equal_multi" }, + }; + + for (int i = 0; i < NELEMS(qos_methods); ++i) + if (!strcmp(name, qos_methods[i].name)) + return qos_methods[i].func; + + return qos_distribution_equal_multi; +} + diff --git a/src/tests/qos_distributions.c b/src/tests/qos_distributions.c index 0b04476..bba3296 100644 --- a/src/tests/qos_distributions.c +++ b/src/tests/qos_distributions.c @@ -13,6 +13,9 @@ int metrics_get_total(const struct metrics *m) void test_proportional_raw(void) { + const qos_distribution_func qos_distribution_proportional_raw = qos_get_distribution_func_by_name("proportional_raw"); + assert(qos_distribution_proportional_raw); + struct metrics_pid_aggr_info i1 [] = {{ .count = 8, } ,{ .count = 12, } @@ -30,6 +33,9 @@ void test_proportional_raw(void) void test_equal(void) { + const qos_distribution_func qos_distribution_equal = qos_get_distribution_func_by_name("equal"); + assert(qos_distribution_equal); + struct metrics_pid_aggr_info i1 [] = {{ .count = 1, } ,{ .count = 66, } @@ -47,6 +53,9 @@ void test_equal(void) void test_equal_dual(void) { + const qos_distribution_func qos_distribution_equal_dual = qos_get_distribution_func_by_name("equal_dual"); + assert(qos_distribution_equal_dual); + struct metrics_pid_aggr_info i1 [] = {{ .count = 20, } ,{ .count = 85, } @@ -62,6 +71,9 @@ void test_equal_dual(void) void test_equal_multi(void) { + const qos_distribution_func qos_distribution_equal_multi = qos_get_distribution_func_by_name("equal_multi"); + assert(qos_distribution_equal_multi); + struct metrics_pid_aggr_info i1 [] = {{ .count = 30, } ,{ .count = 95, } @@ -90,6 +102,9 @@ void test_equal_multi(void) void test_proportional_talmud(void) { + const qos_distribution_func qos_distribution_proportional_talmud = qos_get_distribution_func_by_name("proportional_talmud"); + assert(qos_distribution_proportional_talmud); + struct metrics_pid_aggr_info i1 [] = {{ .count = 50, } ,{ .count = 100, } -- 2.7.4