Merge "main: implementation"
[apps/native/ttsd-worker-task.git] / src / report-generator.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 <stdlib.h>
18 #include <string.h>
19 #include <stdbool.h>
20 #include <unistd.h>
21
22 #include "report-generator.h"
23 #include "log.h"
24 #include "err-check.h"
25 #include "appinfo-provider.h"
26 #include "stats.h"
27 #include "clock.h"
28
29 struct report_generator_system {
30         /** system cpu usage statistics */
31         struct stats_system previous;
32 };
33
34 struct report_generator_process
35 {
36         /** process pid */
37         int pid;
38         /** process cpu usage statistics */
39         struct stats_process previous;
40 };
41
42 struct report_generator_app
43 {
44         char *app_id;
45         report_generator_process_t *process_gen;
46 };
47
48 int _app_report_generator_setup_process_generator(report_generator_app_t *generator);
49
50 report_generator_system_t *report_generator_new_system_report_generator()
51 {
52         report_generator_system_t *ret = calloc(1, sizeof(struct report_generator_system));
53         if (!ret)
54                 return NULL;
55
56         if (stats_update_system_stats(&ret->previous) != 0) {
57                 ERR("stats_update_system_stats failed");
58                 free(ret);
59                 return NULL;
60         }
61
62         return ret;
63 }
64
65 void report_generator_free_system_generator(report_generator_system_t *generator)
66 {
67         if (!generator)
68                 return;
69
70         free(generator);
71 }
72
73 report_generator_process_t *report_generator_new_process_report_generator(int pid)
74 {
75         ON_TRUE_RETURN_VAL(pid <= 0, NULL);
76
77         report_generator_process_t *ret = calloc(1, sizeof(struct report_generator_process));
78         if (!ret)
79                 return NULL;
80
81         if (stats_update_process_stats(pid, &ret->previous) != 0) {
82                 ERR("stats_update_process_stats failed.");
83                 free(ret);
84                 return NULL;
85         };
86
87         ret->pid = pid;
88
89         return ret;
90 }
91
92 void report_generator_free_process_generator(report_generator_process_t *generator)
93 {
94         if (!generator)
95                 return;
96
97         free(generator);
98 }
99
100 report_generator_app_t *report_generator_new_app_report_generator(const char *app_id)
101 {
102         ON_NULL_RETURN_VAL(app_id, NULL);
103
104         report_generator_app_t *ret = calloc(1, sizeof(struct report_generator_app));
105         if (!ret) {
106                 ERR("malloc failed");
107                 return NULL;
108         }
109
110         ret->app_id = strdup(app_id);
111         _app_report_generator_setup_process_generator(ret);
112         return ret;
113 }
114
115 void report_generator_free_app_generator(report_generator_app_t *generator)
116 {
117         if (!generator) return;
118         report_generator_free_process_generator(generator->process_gen);
119         free(generator->app_id);
120         free(generator);
121 }
122
123 int report_generator_generate_system_cpu_usage_report(
124                 report_generator_system_t *generator,
125                 int interval,
126                 struct system_cpu_usage_report *report)
127 {
128         ON_NULL_RETURN_VAL(generator, -1);
129         ON_TRUE_RETURN_VAL(interval < 0, -1);
130         ON_NULL_RETURN_VAL(report, -1);
131
132         float usage;
133         bool block = interval > 0;
134         struct stats_system current;
135
136         if (block) {
137                 if (stats_update_system_stats(&generator->previous) != 0) {
138                         ERR("stats_update_system_stats failed.");
139                         return -1;
140                 }
141                 sleep(interval);
142         }
143
144         if (stats_update_system_stats(&current) != 0) {
145                 ERR("stats_update_system_stats failed.");
146                 return -1;
147         }
148
149         if (stats_get_system_cpu_usage_average(&generator->previous, &current, &usage))
150         {
151                 ERR("stats_get_system_cpu_usage_average failed");
152                 return -1;
153         }
154
155         report->usage = usage;
156         report->time = clock_realtime_get().tv_sec;
157
158         generator->previous = current;
159
160         return 0;
161 }
162
163 int report_generator_generate_system_memory_usage_report(
164                 report_generator_system_t *generator,
165                 struct system_memory_usage_report *report) {
166         ON_NULL_RETURN_VAL(generator, -1);
167         ON_NULL_RETURN_VAL(report, -1);
168
169         float usage;
170
171         if (stats_get_system_memory_usage(&usage) != 0) {
172                 ERR("stats_get_system_memory_usage failed.");
173                 return -1;
174         }
175
176         report->time = clock_realtime_get().tv_sec;
177         report->usage = usage;
178
179         return 0;
180 }
181
182 int report_generator_generate_process_cpu_usage_report(
183                 report_generator_process_t *generator,
184                 int interval,
185                 struct process_cpu_usage_report *report)
186 {
187         ON_NULL_RETURN_VAL(generator, -1);
188         ON_TRUE_RETURN_VAL(interval < 0, -1);
189         ON_NULL_RETURN_VAL(report, -1);
190
191         struct stats_process current = {0,};
192         bool block = interval > 0;
193         float usage;
194
195         if (block) {
196                 if (stats_update_process_stats(generator->pid, &generator->previous) != 0) {
197                         ERR("stats_update_process_stats failed.");
198                         return -1;
199                 }
200                 sleep(interval);
201         }
202
203         if (stats_update_process_stats(generator->pid, &current) != 0) {
204                 ERR("stats_update_process_stats failed.");
205                 return -1;
206         }
207
208         if (stats_get_process_cpu_usage_average(&generator->previous, &current, &usage) ) {
209                 ERR("stats_update_process_stats failed.");
210                 return -1;
211         }
212
213         report->time = clock_realtime_get().tv_sec;
214         report->pid = generator->pid;
215         report->usage = usage;
216
217         generator->previous = current;
218
219         return 0;
220 }
221
222 int report_generator_generate_process_memory_usage_report(
223                 report_generator_process_t *generator,
224                 struct process_memory_usage_report *report)
225 {
226         ON_NULL_RETURN_VAL(generator, -1);
227         ON_NULL_RETURN_VAL(report, -1);
228
229         float usage;
230
231         if (stats_get_process_memory_usage(generator->pid, &usage) != 0) {
232                 ERR("stats_get_process_memory_usage failed.");
233                 return -1;
234         }
235
236         report->time = clock_realtime_get().tv_sec;
237         report->usage = usage;
238
239         return 0;
240 }
241
242 int _app_report_generator_setup_process_generator(report_generator_app_t *generator)
243 {
244         int pid = app_info_provider_find_main_pid(generator->app_id);
245         if (pid < 0) {
246                 return -1;
247         }
248
249         if (!generator->process_gen || generator->process_gen->pid != pid) {
250                 if (generator->process_gen)
251                         report_generator_free_process_generator(generator->process_gen);
252                 generator->process_gen = report_generator_new_process_report_generator(pid);
253         }
254         return 0;
255 }
256
257 int report_generator_generate_app_cpu_usage_report(
258                 report_generator_app_t *generator,
259                 int interval,
260                 struct app_cpu_usage_report *report)
261 {
262         ON_NULL_RETURN_VAL(generator, -1);
263         ON_TRUE_RETURN_VAL(interval < 0, -1);
264         ON_NULL_RETURN_VAL(report, -1);
265
266         if (_app_report_generator_setup_process_generator(generator) != 0) {
267                 ERR("_app_report_generator_setup_process_generator failed.");
268                 return -1;
269         }
270
271         if (report_generator_generate_process_cpu_usage_report(
272                                 generator->process_gen, interval, &report->process_report) != 0)
273         {
274                 ERR("report_generator_generate_process_cpu_usage_report failed.");
275                 return 0;
276         }
277
278         strncpy(report->app_id, generator->app_id, sizeof(report->app_id));
279         report->process_report.pid = generator->process_gen->pid;
280
281         return 0;
282 }
283
284 int report_generator_generate_app_memory_usage_report(
285                 report_generator_app_t *generator,
286                 struct app_memory_usage_report *report)
287 {
288         ON_NULL_RETURN_VAL(generator, -1);
289         ON_NULL_RETURN_VAL(report, -1);
290
291         if (_app_report_generator_setup_process_generator(generator)) {
292                 ERR("_app_report_generator_setup_process_generator failed.");
293                 return -1;
294         }
295
296         if (report_generator_generate_process_memory_usage_report(
297                                 generator->process_gen, &report->process_report) != 0)
298         {
299                 ERR("report_generator_generate_process_memory_usage_report failed.");
300                 return 0;
301         }
302
303         strncpy(report->app_id, generator->app_id, sizeof(report->app_id));
304         report->process_report.pid = generator->process_gen->pid;
305
306         return 0;
307 }
308
309 int report_generator_generate_load_average_report(struct system_load_average_report *report)
310 {
311         ON_NULL_RETURN_VAL(report, -1);
312
313         float a1, a5, a15;
314
315         if (stats_get_load_averages(&a1, &a5, &a15) != 0) {
316                 ERR("stats_get_load_averages failed.");
317                 return -1;
318         }
319
320         report->time = clock_realtime_get().tv_sec;
321         report->one_min_avg = a1;
322         report->five_min_avg = a5;
323         report->fifteen_min_avg = a15;
324
325         return 0;
326 }
327