From a7be9ea774634dc90b497acfd652366aae0a3bfe Mon Sep 17 00:00:00 2001 From: Lukasz Stanislawski Date: Mon, 23 Jul 2018 14:35:43 +0200 Subject: [PATCH] report-generator: reafactor process generator Change-Id: Ic1664627b6562f78e7b34d70a2bbdb45f0e07f4a --- src/config-deserializer.c | 64 +++++++++++-- src/config-deserializer.h | 12 ++- src/config.h | 28 +++--- src/json-schema-defs.h | 4 + src/process.c | 24 +++++ src/process.h | 10 +++ src/report-generator.c | 209 +++++++++++++------------------------------ src/report-generator.h | 79 +++------------- src/report-json-serializer.c | 76 +++++----------- src/report-json-serializer.h | 4 +- src/report.h | 14 +++ src/task-factory.c | 109 ++++++++++++---------- src/task-worker.c | 2 +- src/task.h | 18 ---- 14 files changed, 295 insertions(+), 358 deletions(-) diff --git a/src/config-deserializer.c b/src/config-deserializer.c index d753fe5..6e8e233 100644 --- a/src/config-deserializer.c +++ b/src/config-deserializer.c @@ -16,7 +16,9 @@ #include #include +#include #include + #include "json-schema-defs.h" #include "config-deserializer.h" #include "config.h" @@ -28,6 +30,7 @@ static void config_array_iterate_func(JsonArray *array, guint index, JsonNode *e static config_options_e config_parse_options(const char *option); static int calculate_task_counter(int frequency); static config_top_subject_e config_parse_top_subject(const char *option); +static config_data_process_t config_parse_process_data(JsonArray *obj); static struct _cfg_data { @@ -112,13 +115,9 @@ static void config_array_iterate_func(JsonArray *array, guint index, JsonNode *e } else if (g_strcmp0(type, SCHEMA_TYPE_PROCESS) == 0) { - configs[index].scope = APPS; - - const gchar *target = json_object_get_string_member(entry, SCHEMA_TARGET); - configs[index].data.process.options = config_parse_options(target); + configs[index].scope = PROCESS; - const gchar *app_id = json_object_get_string_member(entry, SCHEMA_ID); - snprintf(configs[index].data.process.app_id, APP_ID_REGEX_MAX_LEN + 1, "%s", app_id); + configs[index].data.process = config_parse_process_data(json_object_get_array_member(entry, SCHEMA_REQUEST_DATA_MATCHERS)); } else if (g_strcmp0(type, SCHEMA_TYPE_LOAD_AVG) == 0) { @@ -126,6 +125,46 @@ static void config_array_iterate_func(JsonArray *array, guint index, JsonNode *e } } +static const char *json_object_safe_get_string_member(JsonObject *obj, const char *member) +{ + if (json_object_has_member(obj, member)) + return json_object_get_string_member(obj, member); + return NULL; +} + +static void _process_foreach_matcher(JsonArray *array, guint index, + JsonNode *node, gpointer user_data) +{ + config_data_process_t *ret = user_data; + struct matcher match; + + JsonObject *elem = json_node_get_object(node); + if (!elem) return; + + const char *appid = json_object_safe_get_string_member(elem, SCHEMA_RESULT_APP_ID); + const char *exe = json_object_safe_get_string_member(elem, SCHEMA_RESULT_EXE); + + match.app_id = appid ? strdup(appid) : NULL; + match.exe = exe ? strdup(exe) : NULL; + + ret->matchers[ret->n_matchers++] = match; +} + +static config_data_process_t config_parse_process_data(JsonArray *array) +{ + config_data_process_t ret = {0,}; + + int len = json_array_get_length(array); + if (len == 0) return ret; + + ret.matchers = calloc(len, sizeof(struct matcher)); + ret.n_matchers = 0; + + json_array_foreach_element(array, _process_foreach_matcher, &ret); + + return ret; +} + static config_options_e config_parse_options(const char *option) { if (g_strcmp0(option, SCHEMA_TARGET_CPU) == 0) @@ -158,3 +197,16 @@ static config_top_subject_e config_parse_top_subject(const char *option) return -1; } + +void free_configs(config_t *configs, int len) +{ + for (int i=0; i < len; ++i) { + switch (configs[i].scope) { + case PROCESS: + free(configs[i].data.process.matchers); + break; + default: + break; + } + } +} diff --git a/src/config-deserializer.h b/src/config-deserializer.h index 6793e85..1b44cdd 100644 --- a/src/config-deserializer.h +++ b/src/config-deserializer.h @@ -27,8 +27,16 @@ * @param[out] task_counter The number of tasks to be executed. * * @return Dynamically allocated config_t array. - * @note Returned array should be released with free. + * @note Returned array should be released with @free_configs. */ config_t *deserialize_configs(const char *config_json, int *size, int *task_counter); -#endif \ No newline at end of file +/** + * @brief Releases memory allocated on @deserialize_configs + * + * @param[in] config value returned from @deserialize_configs + * @param[in] size size of the config. Value returned from @deserialize_configs. + */ +void free_configs(config_t *config, int size); + +#endif diff --git a/src/config.h b/src/config.h index 578a91e..dc163f7 100644 --- a/src/config.h +++ b/src/config.h @@ -30,9 +30,9 @@ typedef enum config_scope SYSTEM, /** - * @brief Observe system resources used by one or more app. + * @brief Observe system resources used by processes. */ - APPS, + PROCESS, /** * @brief Observe top usage of memory or cpu. @@ -58,22 +58,24 @@ typedef enum config_options /** * @brief Observe memory usage. */ - OBSERVE_MEMORY } config_options_e; + OBSERVE_MEMORY +} config_options_e; + +/** + * @brief Matcher data + */ +struct matcher { + const char *app_id; + const char *exe; +}; /** * @brief Config app data structure. */ -typedef struct config_data_app +typedef struct config_data_process { - /** - * @brief Config options. - */ - config_options_e options; - - /** - * @brief String containing regular expression with app id. - */ - char app_id[APP_ID_REGEX_MAX_LEN+1]; + struct matcher *matchers; + int n_matchers; } config_data_process_t; typedef enum config_top_subject { diff --git a/src/json-schema-defs.h b/src/json-schema-defs.h index 3492e29..38e15b1 100644 --- a/src/json-schema-defs.h +++ b/src/json-schema-defs.h @@ -38,12 +38,16 @@ #define SCHEMA_TOP "top" #define SCHEMA_ID "id" +#define SCHEMA_REQUEST_DATA_MATCHERS "matchers" + #define SCHEMA_RESULT_DATA_SYSTEM "system_data" #define SCHEMA_RESULT_DATA_LOAD_AVG "load_avg_data" #define SCHEMA_RESULT_DATA_PROCESS "process_data" #define SCHEMA_RESULT_DATA_TOP "top_data" +#define SCHEMA_RESULT_APP_ID "app_id" #define SCHEMA_RESULT_PID "pid" +#define SCHEMA_RESULT_EXE "exe" #define SCHEMA_RESULT_TIME "time" #define SCHEMA_RESULT_USAGE "usage" #define SCHEMA_RESULT_CPU "cpu" diff --git a/src/process.c b/src/process.c index 17159f7..610735e 100644 --- a/src/process.c +++ b/src/process.c @@ -8,6 +8,7 @@ #include "err-check.h" #include "procfs.h" #include "appinfo-provider.h" +#include "json-schema-defs.h" static struct sys_stats sys; static int pagesize; @@ -126,3 +127,26 @@ int process_init() pagesize = getpagesize(); return 0; } + +void process_serialize(struct process *proc, JsonBuilder *builder) +{ + ON_NULL_RETURN(proc); + + float tmp; + json_builder_begin_object(builder); + + json_builder_set_member_name(builder, SCHEMA_RESULT_APP_ID); + json_builder_add_string_value(builder, process_get_appid(proc)); + json_builder_set_member_name(builder, SCHEMA_RESULT_EXE); + json_builder_add_string_value(builder, process_get_exe(proc)); + json_builder_set_member_name(builder, SCHEMA_RESULT_PID); + json_builder_add_int_value(builder, process_get_pid(proc)); + json_builder_set_member_name(builder, SCHEMA_RESULT_CPU); + process_get_cpu_usage_percentage(proc, &tmp); + json_builder_add_double_value(builder, tmp); + json_builder_set_member_name(builder, SCHEMA_RESULT_MEMORY); + process_get_memory_usage_percentage(proc, &tmp); + json_builder_add_double_value(builder, tmp); + + json_builder_end_object(builder); +} diff --git a/src/process.h b/src/process.h index 12344ee..0f7558b 100644 --- a/src/process.h +++ b/src/process.h @@ -17,6 +17,8 @@ #ifndef __PROCESS_H #define __PROCESS_H +#include + /** * @brief The process structure. * @@ -145,4 +147,12 @@ int process_get_cpu_usage_percentage(struct process *proc, float *usage); */ int process_get_memory_usage_percentage(struct process *dst, float *usage); +/** + * @brief Serializes process object as json + * + * @param[in]: proc process + * @param[in/out]: the json builder object. + */ +void process_serialize(struct process *dst, JsonBuilder *builer); + #endif diff --git a/src/report-generator.c b/src/report-generator.c index 9a0f680..9869bcb 100644 --- a/src/report-generator.c +++ b/src/report-generator.c @@ -28,6 +28,7 @@ #include "clock.h" #include "proc-scanner.h" #include "process.h" +#include "json-schema-defs.h" struct report_generator_system { /** system cpu usage statistics */ @@ -36,18 +37,10 @@ struct report_generator_system { struct report_generator_process { - /** process pid */ - int pid; - /** process statistics */ - struct process proc; - /** update time */ - float proc_update_time; -}; - -struct report_generator_app -{ - char *app_id; - report_generator_process_t *process_gen; + proc_scanner_t *scanner; + report_generator_filter_cb filter; + void *user_data; + JsonBuilder *current_builder; }; struct report_generator_top @@ -60,12 +53,10 @@ struct report_generator_top struct report_generator_top_closure { struct sys_stats sys_stats; - int current_index; - int max_index; + int current_index; int max_index; struct process_usage_report *usage_report; }; -int _app_report_generator_setup_process_generator(report_generator_app_t *generator); static int _report_generator_top_report_generator_scan(report_generator_top_t *generator); report_generator_system_t *report_generator_new_system_report_generator() @@ -91,195 +82,115 @@ void report_generator_free_system_generator(report_generator_system_t *generator free(generator); } -report_generator_process_t *report_generator_new_process_report_generator(int pid) +report_generator_process_t *report_generator_new_process_report_generator() { - ON_TRUE_RETURN_VAL(pid <= 0, NULL); - report_generator_process_t *ret = calloc(1, sizeof(struct report_generator_process)); if (!ret) return NULL; - process_init(pid, &ret->proc); - - if (process_update(&ret->proc) != 0) { - ERR("process_update failed."); - free(ret); - return NULL; - }; - - ret->proc_update_time = clock_monotonic_get(); - ret->pid = pid; - - return ret; -} + ret->scanner = proc_scanner_new(); + if (!ret->scanner) goto err; -void report_generator_free_process_generator(report_generator_process_t *generator) -{ - if (!generator) - return; - - free(generator); -} - -report_generator_app_t *report_generator_new_app_report_generator(const char *app_id) -{ - ON_NULL_RETURN_VAL(app_id, NULL); - - report_generator_app_t *ret = calloc(1, sizeof(struct report_generator_app)); - if (!ret) { - ERR("malloc failed"); - return NULL; + if (proc_scanner_scan(ret->scanner) != 0) { + ERR("proc_scanner_scan failed"); + goto err; } - ret->app_id = strdup(app_id); - _app_report_generator_setup_process_generator(ret); return ret; + +err: + proc_scanner_free(ret->scanner); + free(ret); + return NULL; } -void report_generator_free_app_generator(report_generator_app_t *generator) +void report_generator_free_process_generator(report_generator_process_t *generator) { if (!generator) return; - report_generator_free_process_generator(generator->process_gen); - free(generator->app_id); + proc_scanner_free(generator->scanner); free(generator); } -int report_generator_generate_system_report( - report_generator_system_t *generator, - struct system_report *report) +static bool _match_proc_and_append(struct process *proc, void *data) { - ON_NULL_RETURN_VAL(generator, -1); - ON_NULL_RETURN_VAL(report, -1); + report_generator_process_t *gen = data; - if (sys_stats_update(&generator->stats) != 0) { - ERR("stats_update_system_stats failed."); - return -1; + if (gen->filter && gen->filter(proc, gen->user_data)) { + process_serialize(proc, gen->current_builder); } - if (sys_stats_get_cpu_usage_percentage(&generator->stats, &report->cpu)) - { - ERR("stats_get_system_cpu_usage_average failed"); - return -1; - } - - if (sys_stats_get_memory_usage_percentage(&generator->stats, &report->memory) != 0) { - ERR("stats_get_system_memory_usage failed."); - return -1; - } - - - report->time = clock_realtime_get(); - - return 0; + return true; } -int report_generator_generate_process_cpu_usage_report( +int report_generator_generate_process_report( report_generator_process_t *generator, - struct process_usage_report *report) + JsonBuilder *builder) { ON_NULL_RETURN_VAL(generator, -1); - ON_NULL_RETURN_VAL(report, -1); - - float usage; + ON_NULL_RETURN_VAL(builder, -1); - if (process_update(&generator->proc) != 0) { - ERR("process_update failed."); + // refresh data + if (proc_scanner_scan(generator->scanner) != 0) { + ERR("proc_scanner_scan failed"); return -1; } - if (process_get_cpu_usage_percentage(&generator->proc, &usage) != 0) { - ERR("process_get_cpu_usage_percentage failed."); - return -1; - } + generator->current_builder = builder; + json_builder_begin_object(builder); - report->time = clock_realtime_get(); - report->pid = generator->pid; - report->usage = usage; + json_builder_set_member_name(builder, SCHEMA_TYPE); + json_builder_add_string_value(builder, SCHEMA_TYPE_PROCESS); - return 0; -} + json_builder_set_member_name(builder, "time"); + json_builder_add_int_value(builder, clock_realtime_get()); -int report_generator_generate_process_memory_usage_report( - report_generator_process_t *generator, - struct process_usage_report *report) -{ - ON_NULL_RETURN_VAL(generator, -1); - ON_NULL_RETURN_VAL(report, -1); + json_builder_set_member_name(builder, SCHEMA_RESULT_DATA_PROCESS); + json_builder_begin_array(builder); - float usage; + proc_scanner_foreach_process(generator->scanner, _match_proc_and_append, generator); + json_builder_end_array(builder); - if (process_get_memory_usage_percentage(&generator->proc, &usage) != 0) { - ERR("process_get_memory_usage_percentage failed."); - return -1; - } - - report->time = clock_realtime_get(); - report->usage = usage; + json_builder_end_object(builder); // end report + generator->current_builder = NULL; return 0; } -int _app_report_generator_setup_process_generator(report_generator_app_t *generator) +void report_generator_set_filter( + report_generator_process_t *generator, + report_generator_filter_cb cb, const void *user_data) { - int pid = app_info_provider_find_main_pid(generator->app_id); - if (pid < 0) { - return -1; - } + ON_NULL_RETURN(generator); + ON_NULL_RETURN(cb); - if (!generator->process_gen || generator->process_gen->pid != pid) { - if (generator->process_gen) - report_generator_free_process_generator(generator->process_gen); - generator->process_gen = report_generator_new_process_report_generator(pid); - } - return 0; + generator->filter = cb; + generator->user_data = (void*)user_data; } -int report_generator_generate_app_cpu_usage_report( - report_generator_app_t *generator, - struct process_usage_report *report) +int report_generator_generate_system_report( + report_generator_system_t *generator, + struct system_report *report) { ON_NULL_RETURN_VAL(generator, -1); ON_NULL_RETURN_VAL(report, -1); - if (_app_report_generator_setup_process_generator(generator) != 0) { - ERR("_app_report_generator_setup_process_generator failed."); + if (sys_stats_update(&generator->stats) != 0) { + ERR("stats_update_system_stats failed."); return -1; } - if (report_generator_generate_process_cpu_usage_report( - generator->process_gen, report) != 0) + if (sys_stats_get_cpu_usage_percentage(&generator->stats, &report->cpu)) { - ERR("report_generator_generate_process_cpu_usage_report failed."); - return 0; - } - - strncpy(report->app_id, generator->app_id, sizeof(report->app_id)); - report->pid = generator->process_gen->pid; - - return 0; -} - -int report_generator_generate_app_memory_usage_report( - report_generator_app_t *generator, - struct process_usage_report *report) -{ - ON_NULL_RETURN_VAL(generator, -1); - ON_NULL_RETURN_VAL(report, -1); - - if (_app_report_generator_setup_process_generator(generator)) { - ERR("_app_report_generator_setup_process_generator failed."); + ERR("stats_get_system_cpu_usage_average failed"); return -1; } - if (report_generator_generate_process_memory_usage_report( - generator->process_gen, report) != 0) - { - ERR("report_generator_generate_process_memory_usage_report failed."); - return 0; + if (sys_stats_get_memory_usage_percentage(&generator->stats, &report->memory) != 0) { + ERR("stats_get_system_memory_usage failed."); + return -1; } - strncpy(report->app_id, generator->app_id, sizeof(report->app_id)); - report->pid = generator->process_gen->pid; + report->time = clock_realtime_get(); return 0; } diff --git a/src/report-generator.h b/src/report-generator.h index b720379..ac31de0 100644 --- a/src/report-generator.h +++ b/src/report-generator.h @@ -17,6 +17,10 @@ #ifndef __REPORT_GENERATOR_H_ #define __REPORT_GENERATOR_H_ +#include +#include + +#include "process.h" #include "report.h" /** Generator for system-wide reports */ @@ -25,9 +29,6 @@ typedef struct report_generator_system report_generator_system_t; /** Generator for per process report */ typedef struct report_generator_process report_generator_process_t; -/** Generator for app report */ -typedef struct report_generator_app report_generator_app_t; - /** Top report generator yt*/ typedef enum report_generator_top_type { @@ -56,13 +57,12 @@ void report_generator_free_system_generator(report_generator_system_t *generator /** * @brief Creates new instance of report_generator_process_t * - * @param[in] process PID * @return new report_generator_system_t object, or NULL on error * * @remark return value should be released with * @report_generator_free_process_generator */ -report_generator_process_t *report_generator_new_process_report_generator(int pid); +report_generator_process_t *report_generator_new_process_report_generator(); /** * @brief Release report_generator_process_t created with @@ -71,23 +71,6 @@ report_generator_process_t *report_generator_new_process_report_generator(int pi void report_generator_free_process_generator(report_generator_process_t *generator); /** - * @brief Creates new instance of report_generator_app_t - * - * @param[in] Apps id. - * @return New report_generator_app_t object, or NULL on error - * - * @remark return value should be released with - * @report_generator_free_app_generator - */ -report_generator_app_t *report_generator_new_app_report_generator(const char *app_id); - -/** - * @brief Release report_generator_app_t created with - * @report_generator_new_app_report_generator - */ -void report_generator_free_app_generator(report_generator_app_t *generator); - -/** * @brief Creates new instance of report_generator_top_h * * @param[in] type Type of apps to track in generator. @@ -123,59 +106,25 @@ int report_generator_generate_system_report( struct system_report *report); /** - * @brief Fills process_usage_report. + * @brief Get process_report. * * return report with process cpu usage calculated as average between current - * time and last call to report_generator_generate_process_cpu_usage_report for + * time and last call to report_generator_generate_process_report for * generator * * @param[in] generator process generator - * @param[out] report * - * @return 0 on success, other value on failure + * @return 0 on success, other value on error. */ -int report_generator_generate_process_cpu_usage_report( +int report_generator_generate_process_report( report_generator_process_t *generator, - struct process_usage_report *report); + JsonBuilder *builder); -/** - * @brief Fills process_usage_report. - * - * @param[in] generator process generator - * @param[out] report - * @return 0 on success, other value on failure - */ -int report_generator_generate_proccess_memory_usage_report( - report_generator_process_t *generator, - struct process_usage_report *report); +typedef bool (*report_generator_filter_cb)(struct process *proc, void *user_data); -/** - * @brief Fills apps_cpu_usage_report. - * - * return report with apps cpu usage calculated as average between current time - * and last call to report_generator_generate_process_cpu_usage_report for - * generator - * - * @param[in] generator apps generator - * @param[out] report - * - * @return 0 on success, other value on failure - * @remarks Returned value should be freed. - */ -int report_generator_generate_app_cpu_usage_report( - report_generator_app_t *generator, - struct process_usage_report *report); - -/** - * @brief Fills process_usage_report. - * - * @param[in] generator apps generator - * @param[out] report - * @return 0 on success, other value on failure - */ -int report_generator_generate_app_memory_usage_report( - report_generator_app_t *generator, - struct process_usage_report *report); +void report_generator_set_filter( + report_generator_process_t *generator, + report_generator_filter_cb cb, const void *user_data); /** * @brief Fills system_load_average_report diff --git a/src/report-json-serializer.c b/src/report-json-serializer.c index 659fd71..949d82c 100644 --- a/src/report-json-serializer.c +++ b/src/report-json-serializer.c @@ -186,64 +186,37 @@ static void top_memory_usage_reports_to_json_object(JsonBuilder *builder, struct json_builder_end_object(builder); } -static void apps_cpu_usage_report_to_json_object(JsonBuilder *builder, struct process_usage_report *report) +static void process_report_to_json_object(JsonBuilder *builder, struct process_report *report) { json_builder_begin_object(builder); json_builder_set_member_name(builder, SCHEMA_TYPE); json_builder_add_string_value(builder, SCHEMA_TYPE_PROCESS); - json_builder_set_member_name(builder, SCHEMA_TARGET); - json_builder_add_string_value(builder, SCHEMA_TARGET_CPU); - - json_builder_set_member_name(builder, SCHEMA_RESULT_DATA_PROCESS); - json_builder_begin_object(builder); - - json_builder_set_member_name(builder, SCHEMA_ID); - json_builder_add_string_value(builder, report->app_id); - json_builder_set_member_name(builder, SCHEMA_RESULT_PID); - json_builder_add_int_value(builder, report->pid); - - json_builder_set_member_name(builder, SCHEMA_RESULT_RESULT); - json_builder_begin_object(builder); json_builder_set_member_name(builder, SCHEMA_RESULT_TIME); json_builder_add_int_value(builder, report->time); - json_builder_set_member_name(builder, SCHEMA_RESULT_USAGE); - json_builder_add_double_value(builder, report->usage); - - json_builder_end_object(builder); - json_builder_end_object(builder); - json_builder_end_object(builder); -} - -static void apps_memory_usage_report_to_json_object(JsonBuilder *builder, struct process_usage_report *report) -{ - json_builder_begin_object(builder); - - json_builder_set_member_name(builder, SCHEMA_TYPE); - json_builder_add_string_value(builder, SCHEMA_TYPE_PROCESS); - - json_builder_set_member_name(builder, SCHEMA_TARGET); - json_builder_add_string_value(builder, SCHEMA_TARGET_MEMORY); json_builder_set_member_name(builder, SCHEMA_RESULT_DATA_PROCESS); - json_builder_begin_object(builder); - - json_builder_set_member_name(builder, SCHEMA_ID); - json_builder_add_string_value(builder, report->app_id); - json_builder_set_member_name(builder, SCHEMA_RESULT_PID); - json_builder_add_int_value(builder, report->pid); + json_builder_begin_array(builder); - json_builder_set_member_name(builder, SCHEMA_RESULT_RESULT); - json_builder_begin_object(builder); - json_builder_set_member_name(builder, SCHEMA_RESULT_TIME); - json_builder_add_int_value(builder, report->time); - json_builder_set_member_name(builder, SCHEMA_RESULT_USAGE); - json_builder_add_double_value(builder, report->usage); + for (int i = 0; i < report->n_processes; ++i) { + json_builder_begin_object(builder); + json_builder_set_member_name(builder, SCHEMA_RESULT_APP_ID); + json_builder_add_string_value(builder, report->processes[i].app_id); + json_builder_set_member_name(builder, SCHEMA_RESULT_EXE); + json_builder_add_string_value(builder, report->processes[i].exe); + json_builder_set_member_name(builder, SCHEMA_RESULT_PID); + json_builder_add_int_value(builder, report->processes[i].pid); + json_builder_set_member_name(builder, SCHEMA_RESULT_CPU); + json_builder_add_double_value(builder, report->processes[i].cpu); + json_builder_set_member_name(builder, SCHEMA_RESULT_MEMORY); + json_builder_add_double_value(builder, report->processes[i].memory); + json_builder_end_object(builder); + } + json_builder_end_array(builder); - json_builder_end_object(builder); - json_builder_end_object(builder); - json_builder_end_object(builder); + json_builder_end_object(builder); // end data process + json_builder_end_object(builder); // end report } IMPLEMENT_SERIALIZER_FUNC( @@ -257,14 +230,9 @@ IMPLEMENT_SERIALIZER_FUNC( system_report_to_json_object) IMPLEMENT_SERIALIZER_FUNC( - report_json_serializer_serialize_apps_cpu_usage_report, - struct process_usage_report, - apps_cpu_usage_report_to_json_object) - -IMPLEMENT_SERIALIZER_FUNC( - report_json_serializer_serialize_apps_memory_usage_report, - struct process_usage_report, - apps_memory_usage_report_to_json_object) + report_json_serializer_serialize_process_report, + struct process_report, + process_report_to_json_object) IMPLEMENT_ARRAY_SERIALIZER_FUNC( report_json_serializer_serialize_top_cpu_usage_reports, diff --git a/src/report-json-serializer.h b/src/report-json-serializer.h index e607ca1..b236c8a 100644 --- a/src/report-json-serializer.h +++ b/src/report-json-serializer.h @@ -40,14 +40,14 @@ char *report_json_serializer_serialize_system_load_average_report(struct system_ char *report_json_serializer_serialize_system_report(struct system_report *report); /** - * @brief Serializes process_usage_report to json string + * @brief Serializes process_report to json string * * @param[in] report Report structure with usage data. * * @return dynamically allocated string on NULL on error. * @remark returned value should be released with @free */ -char *report_json_serializer_serialize_process_cpu_usage_report(struct process_usage_report *report); +char *report_json_serializer_serialize_process_report(struct process_report *report); /** * @brief Serializes process_usage_report to json string diff --git a/src/report.h b/src/report.h index 4b511e1..dc717c4 100644 --- a/src/report.h +++ b/src/report.h @@ -50,5 +50,19 @@ struct process_usage_report { char app_id[APP_ID_MAX_SIZE]; }; +struct process_info { + const char *app_id; + const char *exe; + int pid; + float cpu; /** CPU utilization (Percent) */ + float memory; /** Memory utilization (Percent) */ +}; + +struct process_report { + time_t time; /** Number of seconds after the Epoch */ + struct process_info *processes; + int n_processes; +}; + #endif diff --git a/src/task-factory.c b/src/task-factory.c index 3c9fcf6..c8c6751 100644 --- a/src/task-factory.c +++ b/src/task-factory.c @@ -27,30 +27,40 @@ static task_t *create_system_report_task(); static task_t *create_load_avg_report_task(); -static task_t *create_app_report_task(config_options_e options, const char *regex); +static task_t *create_process_report_task(config_data_process_t *config); static task_t *create_top_report_task(struct config_data_top options); static void execute_scan_system(task_t *task); static void execute_scan_load_avg(task_t *task); -static void execute_scan_app_memory(task_t *task); -static void execute_scan_apps_cpu(task_t *task); +static void execute_scan_process(task_t *task); static void execute_scan_top_cpu(task_t *task); static void execute_scan_top_memory(task_t *task); static void release_system_task(task_t *task); -static void release_app_task(task_t *task); +static void release_process_task(task_t *task); static void release_top_task(task_t *task); +/** + * @brief Process task structure. + */ +typedef struct process_task +{ + task_t task; + report_generator_process_t *report_generator; + JsonBuilder *builder; + JsonGenerator *generator; +} process_task_t; + task_t *task_factory_create_task(const config_t *config) { - switch(config->scope) + switch (config->scope) { case SYSTEM: return create_system_report_task(); case LOAD_AVG: return create_load_avg_report_task(); - case APPS: - return create_app_report_task(config->data.process.options, config->data.process.app_id); + case PROCESS: + return create_process_report_task(&config->data.process); case TOP: return create_top_report_task(config->data.top); default: @@ -79,28 +89,39 @@ static task_t *create_load_avg_report_task() return _load_avg_task; } -static task_t *create_app_report_task(config_options_e options, const char *app_id) +static bool _report_generator_process_filter_cb(struct process *proc, void *user_data) +{ + config_data_process_t *data = user_data; + + for (int i = 0; i < data->n_matchers; ++i) { + struct matcher *match = &data->matchers[i]; + if (match->app_id && process_get_appid(proc)) { + if (strcmp(match->app_id, process_get_appid(proc)) == 0) + return true; + } + if (match->exe && process_get_exe(proc)) { + if (strcmp(match->exe, process_get_exe(proc)) == 0) + return true; + } + } + return false; +} + +static task_t *create_process_report_task(config_data_process_t *config) { - app_task_t *_app_task = (app_task_t *)g_malloc(sizeof(app_task_t)); + process_task_t *_process_task = (process_task_t *)g_malloc(sizeof(process_task_t)); - _app_task->task.release = release_app_task; - _app_task->report_generator = report_generator_new_app_report_generator(app_id); + _process_task->task.release = release_process_task; + _process_task->report_generator = report_generator_new_process_report_generator(); + _process_task->task.execute = execute_scan_process; + _process_task->builder = json_builder_new(); + _process_task->generator = json_generator_new(); - switch (options) - { - case OBSERVE_CPU: - _app_task->task.execute = execute_scan_apps_cpu; - break; - case OBSERVE_MEMORY: - _app_task->task.execute = execute_scan_app_memory; - break; - default: - report_generator_free_app_generator(_app_task->report_generator); - g_free(_app_task); - return NULL; - } + report_generator_set_filter(_process_task->report_generator, + _report_generator_process_filter_cb, + config); - return &_app_task->task; + return &_process_task->task; } static void execute_scan_system(task_t *task) @@ -133,32 +154,22 @@ static void execute_scan_load_avg(task_t *task) g_free(json_report); } -static void execute_scan_app_memory(task_t *task) +static void execute_scan_process(task_t *task) { ON_NULL_RETURN(task); - app_task_t *_app_task = container_of(task, app_task_t, task); - - struct process_usage_report report; - - report_generator_generate_app_memory_usage_report(_app_task->report_generator, &report); - - char *json_report = report_json_serializer_serialize_apps_memory_usage_report(&report); - ipc_send_report(json_report); - g_free(json_report); -} - -static void execute_scan_apps_cpu(task_t *task) -{ - ON_NULL_RETURN(task); + process_task_t *_process_task = container_of(task, process_task_t, task); - app_task_t *_app_task = container_of(task, app_task_t, task); + json_builder_reset(_process_task->builder); - struct process_usage_report reports; + if (report_generator_generate_process_report(_process_task->report_generator, _process_task->builder) != 0) { + return; + } - report_generator_generate_app_cpu_usage_report(_app_task->report_generator, &reports); + JsonNode *root = json_builder_get_root(_process_task->builder); + json_generator_set_root(_process_task->generator, root); + char *json_report = json_generator_to_data(_process_task->generator, NULL); - char *json_report = report_json_serializer_serialize_apps_cpu_usage_report(&reports); ipc_send_report(json_report); g_free(json_report); } @@ -173,14 +184,16 @@ static void release_system_task(task_t *task) g_free(_system_task); } -static void release_app_task(task_t *task) +static void release_process_task(task_t *task) { ON_NULL_RETURN(task); - app_task_t *_app_task = container_of(task, app_task_t, task); + process_task_t *_process_task = container_of(task, process_task_t, task); - report_generator_free_app_generator(_app_task->report_generator); - g_free(_app_task); + report_generator_free_process_generator(_process_task->report_generator); + g_object_unref(_process_task->builder); + g_object_unref(_process_task->generator); + g_free(_process_task); } static task_t *create_top_report_task(struct config_data_top options) diff --git a/src/task-worker.c b/src/task-worker.c index 6f6a9d3..425d582 100644 --- a/src/task-worker.c +++ b/src/task-worker.c @@ -80,7 +80,7 @@ int main(int argc, char *argv[]) scheduler_destroy(data.scheduler); app_provider_shutdown(); ipc_shutdown(); - g_free(data.current_config); + free_configs(data.current_config, cfg_size); return 0; } diff --git a/src/task.h b/src/task.h index 22f8823..3156f21 100644 --- a/src/task.h +++ b/src/task.h @@ -54,24 +54,6 @@ typedef struct system_task } system_task_t; /** - * @brief Application task structure. - */ -typedef struct app_task -{ - task_t task; - report_generator_app_t *report_generator; -} app_task_t; - -/** - * @brief Process task structure. - */ -typedef struct process_task -{ - task_t task; - report_generator_process_t *report_generator; -} process_task_t; - -/** * @brief Top task structure. */ typedef struct top_task -- 2.7.4