config: change matchers to filter
[apps/native/ttsd-worker-task.git] / src / config-deserializer.c
1 /*
2  * Copyright (c) 2018 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Flora License, Version 1.1 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <glib.h>
19 #include <stdlib.h>
20 #include <json-glib/json-glib.h>
21
22 #include "json-schema-defs.h"
23 #include "config-deserializer.h"
24 #include "config.h"
25 #include "err-check.h"
26 #include "log.h"
27
28 static JsonNode *parse_string(JsonParser *parser, const char *config_json);
29 static void config_array_iterate_func(JsonArray *array, guint index, JsonNode *element, gpointer user_data);
30 static int calculate_task_counter(int frequency);
31 static config_top_subject_e config_parse_top_subject(const char *option);
32 static config_data_process_t config_parse_process_data(JsonArray *obj);
33
34 static struct _cfg_data
35 {
36     int total_duration;
37     int task_counter;
38 } cfg_data =
39 {
40     .total_duration = 0,
41     .task_counter = 0
42 };
43
44 config_t *deserialize_configs(const char *config_json, int *size, int *task_counter)
45 {
46     JsonParser *parser = json_parser_new();
47
48     JsonNode *root = parse_string(parser, config_json);
49     JsonObject *obj = json_node_get_object(root);
50
51     cfg_data.total_duration = json_object_get_int_member(obj, SCHEMA_CONFIG_TOTAL_DURATION);
52
53     JsonArray *array = json_object_get_array_member(obj, SCHEMA_CONFIG_ENTRY);
54     if (!array)
55     {
56         ERR("Json config is invalid!");
57         g_object_unref(parser);
58         return NULL;
59     }
60
61     *size = json_array_get_length(array);
62
63     config_t *configs = g_malloc(*size * sizeof(config_t));
64
65     json_array_foreach_element(array, config_array_iterate_func, configs);
66
67     g_object_unref(parser);
68     *task_counter = cfg_data.task_counter;
69     return configs;
70 }
71
72 static JsonNode *parse_string(JsonParser *parser, const char *config_json)
73 {
74     GError *err = NULL;
75
76     if (!json_parser_load_from_data(parser, config_json, -1, &err))
77     {
78         ERR("Function \"json_parser_load_from_data()\" failed with message ", err->message);
79         g_error_free(err);
80         return NULL;
81     }
82
83     return json_parser_get_root(parser);
84 }
85
86 static void config_array_iterate_func(JsonArray *array, guint index, JsonNode *element, gpointer user_data)
87 {
88     config_t *configs = (config_t *)user_data;
89
90     JsonObject *entry = json_node_get_object(element);
91     const gchar *type = json_object_get_string_member(entry, SCHEMA_TYPE);
92     gint64 frequency = json_object_get_int_member(entry, SCHEMA_FREQUENCY);
93
94     configs[index].frequency = frequency;
95     int c = calculate_task_counter(frequency);
96     cfg_data.task_counter += c;
97
98     if (g_strcmp0(type, SCHEMA_TYPE_TOP) == 0)
99     {
100         configs[index].scope = TOP;
101
102         const gchar *subject = json_object_get_string_member(entry, SCHEMA_SUBJECT);
103         configs[index].data.top.subject = config_parse_top_subject(subject);
104
105         gint64 top = json_object_get_int_member(entry, SCHEMA_TOP);
106         configs[index].data.top.top = top;
107     }
108     else if (g_strcmp0(type, SCHEMA_TYPE_SYSTEM) == 0)
109     {
110         configs[index].scope = SYSTEM;
111     }
112     else if (g_strcmp0(type, SCHEMA_TYPE_PROCESS) == 0)
113     {
114         configs[index].scope = PROCESS;
115
116                 configs[index].data.process = config_parse_process_data(json_object_get_array_member(entry, SCHEMA_REQUEST_DATA_FILTERS));
117     }
118     else if (g_strcmp0(type, SCHEMA_TYPE_LOAD_AVG) == 0)
119     {
120         configs[index].scope = LOAD_AVG;
121     }
122 }
123
124 static const char *json_object_safe_get_string_member(JsonObject *obj, const char *member)
125 {
126         if (json_object_has_member(obj, member))
127                 return json_object_get_string_member(obj, member);
128         return NULL;
129 }
130
131 static void _process_foreach_filter(JsonArray *array, guint index,
132                 JsonNode *node, gpointer user_data)
133 {
134         config_data_process_t *ret = user_data;
135         struct filter filter;
136
137         JsonObject *elem = json_node_get_object(node);
138         if (!elem) return;
139
140         const char *appid = json_object_safe_get_string_member(elem, SCHEMA_RESULT_APP_ID);
141         const char *exe = json_object_safe_get_string_member(elem, SCHEMA_RESULT_EXE);
142
143         filter.app_id = appid ? strdup(appid) : NULL;
144         filter.exe = exe ? strdup(exe) : NULL;
145
146         ret->filters[ret->n_filters++] = filter;
147 }
148
149 static config_data_process_t config_parse_process_data(JsonArray *array)
150 {
151         config_data_process_t ret = {0,};
152
153         int len = json_array_get_length(array);
154         if (len == 0) return ret;
155
156         ret.filters = calloc(len, sizeof(struct filter));
157         ret.n_filters = 0;
158
159         json_array_foreach_element(array, _process_foreach_filter, &ret);
160
161         return ret;
162 }
163
164 static int calculate_task_counter(int frequency)
165 {
166     return cfg_data.total_duration / frequency;
167 }
168
169 static config_top_subject_e config_parse_top_subject(const char *option)
170 {
171     if (g_strcmp0(option, SCHEMA_SUBJECT_APPS) == 0)
172     {
173         return TOP_SUBJECT_APPS;
174     }
175     else if (g_strcmp0(option, SCHEMA_SUBJECT_ALL) == 0)
176     {
177         return TOP_SUBJECT_ALL;
178     }
179
180     return -1;
181 }
182
183 void free_configs(config_t *configs, int len)
184 {
185         for (int i=0; i < len; ++i) {
186                 switch (configs[i].scope) {
187                         case PROCESS:
188                                 free(configs[i].data.process.filters);
189                                 break;
190                         default:
191                                 break;
192                 }
193         }
194 }