adf862173ef4c933d00df6d0b446969ffe116c45
[platform/framework/web/data-provider-master.git] / src / fault_manager.c
1 /*
2  * Copyright 2013  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 <string.h>
19 #include <stdlib.h> /* free */
20
21 #include <gio/gio.h>
22
23 #include <Eina.h>
24 #include <packet.h>
25 #include <dlog.h>
26 #include <livebox-errno.h>
27
28 #include "util.h"
29 #include "debug.h"
30 #include "slave_life.h"
31 #include "slave_rpc.h"
32 #include "client_life.h"
33 #include "instance.h"
34 #include "client_rpc.h"
35 #include "package.h"
36 #include "conf.h"
37 #include "critical_log.h"
38
39 static struct info {
40         Eina_List *call_list;
41         int fault_mark_count;
42 } s_info = {
43         .call_list = NULL,
44         .fault_mark_count = 0,
45 };
46
47 struct fault_info {
48         struct slave_node *slave;
49         double timestamp;
50         char *pkgname;
51         char *filename;
52         char *func;
53 };
54
55 HAPI int const fault_is_occured(void)
56 {
57         return s_info.fault_mark_count;
58 }
59
60 static void clear_log_file(struct slave_node *slave)
61 {
62         char filename[BUFSIZ];
63         int ret;
64
65         ret = snprintf(filename, sizeof(filename) - 1, "%s/slave.%d", SLAVE_LOG_PATH, slave_pid(slave));
66         if (ret == sizeof(filename) - 1) {
67                 filename[sizeof(filename) - 1] = '\0';
68                 ErrPrint("filename buffer is overflowed\n");
69         }
70
71         if (unlink(filename) < 0) {
72                 ErrPrint("unlink: %s\n", strerror(errno));
73         }
74 }
75
76 static char *check_log_file(struct slave_node *slave)
77 {
78         char pkgname[BUFSIZ];
79         const char *pattern = "liblive-";
80         char *ptr;
81         FILE *fp;
82         int i;
83         char filename[BUFSIZ];
84
85         snprintf(filename, sizeof(filename), "%s/slave.%d", SLAVE_LOG_PATH, slave_pid(slave));
86         fp = fopen(filename, "rt");
87         if (!fp) {
88                 ErrPrint("No log file found [%s]\n", strerror(errno));
89                 return NULL;
90         }
91
92         ptr = fgets(pkgname, sizeof(pkgname), fp);
93         if (fclose(fp) != 0) {
94                 ErrPrint("fclose: %s\n", strerror(errno));
95         }
96
97         if (ptr != pkgname) {
98                 ErrPrint("Invalid log\n");
99                 return NULL;
100         }
101
102         for (i = 0; pattern[i] && (pattern[i] == pkgname[i]); i++); /*!< Check pattern of filename */
103         if (strlen(pattern) != i) {
104                 ErrPrint("Pattern is not matched: %d\n", i);
105                 return NULL;
106         }
107
108         ptr = pkgname + i;
109         i = strlen(ptr) - 3; /* Skip the ".so" */
110         if (i <= 0 || strcmp(ptr + i, ".so")) {
111                 ErrPrint("Extension is not matched\n");
112                 return NULL;
113         }
114                 
115         ptr[i] = '\0'; /*!< Truncate tailer ".so" */
116         if (unlink(filename) < 0) {
117                 ErrPrint("Failed to unlink %s\n", filename);
118         }
119
120         return strdup(ptr);
121 }
122
123 HAPI void fault_unicast_info(struct client_node *client, const char *pkgname, const char *filename, const char *func)
124 {
125         struct packet *packet;
126
127         if (!client || !pkgname || !filename || !func) {
128                 return;
129         }
130
131         packet = packet_create_noack("fault_package", "sss", pkgname, filename, func);
132         if (!packet) {
133                 return;
134         }
135
136         client_rpc_async_request(client, packet);
137 }
138
139 HAPI void fault_broadcast_info(const char *pkgname, const char *filename, const char *func)
140 {
141         struct packet *packet;
142
143         packet = packet_create_noack("fault_package", "sss", pkgname, filename, func);
144         if (!packet) {
145                 ErrPrint("Failed to create a param\n");
146                 return;
147         }
148
149         client_broadcast(NULL, packet);
150 }
151
152 static inline void dump_fault_info(const char *name, pid_t pid, const char *pkgname, const char *filename, const char *funcname)
153 {
154         CRITICAL_LOG("Slavename: %s[%d]\n"      \
155                         "Package: %s\n"         \
156                         "Filename: %s\n"        \
157                         "Funcname: %s\n", name, pid, pkgname, filename, funcname);
158 }
159
160 HAPI int fault_info_set(struct slave_node *slave, const char *pkgname, const char *id, const char *func)
161 {
162         struct pkg_info *pkg;
163         int ret;
164
165         pkg = package_find(pkgname);
166         if (!pkg) {
167                 return LB_STATUS_ERROR_NOT_EXIST;
168         }
169
170         ret = package_set_fault_info(pkg, util_timestamp(), id, func);
171         if (ret < 0) {
172                 return LB_STATUS_ERROR_FAULT;
173         }
174
175         dump_fault_info(slave_name(slave), slave_pid(slave), pkgname, id, func);
176         ErrPrint("Set fault %s(%d)\n", !ret ? "Success" : "Failed", ret);
177         fault_broadcast_info(pkgname, id, func);
178
179         /*!
180          * \note
181          * Update statistics
182          */
183         s_info.fault_mark_count++;
184         return LB_STATUS_SUCCESS;
185 }
186
187 HAPI int fault_check_pkgs(struct slave_node *slave)
188 {
189         struct fault_info *info;
190         struct pkg_info *pkg;
191         const char *pkgname;
192         Eina_List *l;
193         Eina_List *n;
194         int checked;
195
196         /*!
197          * \note
198          * First step.
199          * Check the log file
200          */
201         pkgname = (const char *)check_log_file(slave);
202         if (pkgname) {
203                 pkg = package_find(pkgname);
204                 if (pkg) {
205                         int ret;
206                         ret = package_set_fault_info(pkg, util_timestamp(), NULL, NULL);
207                         dump_fault_info(slave_name(slave), slave_pid(slave), pkgname, "", "");
208                         ErrPrint("Set fault %s(%d)\n", !ret ? "Success" : "Failed", ret);
209                         fault_broadcast_info(pkgname, "", "");
210                         DbgFree((char *)pkgname);
211
212                         s_info.fault_mark_count = 0;
213                         clear_log_file(slave);
214                         EINA_LIST_REVERSE_FOREACH_SAFE(s_info.call_list, l, n, info) {
215                                 if (info->slave != slave) {
216                                         continue;
217                                 }
218
219                                 s_info.call_list = eina_list_remove_list(s_info.call_list, l);
220
221                                 DbgFree(info->pkgname);
222                                 DbgFree(info->filename);
223                                 DbgFree(info->func);
224                                 DbgFree(info);
225                         }
226                         return 0;
227                 }
228                 DbgFree((char *)pkgname);
229         }
230
231         /*!
232          * \note
233          * Second step.
234          * Is it secured slave?
235          */
236         pkgname = package_find_by_secured_slave(slave);
237         if (pkgname) {
238                 pkg = package_find(pkgname);
239                 if (pkg) {
240                         int ret;
241                         ret = package_set_fault_info(pkg, util_timestamp(), NULL, NULL);
242                         dump_fault_info(slave_name(slave), slave_pid(slave), pkgname, "", "");
243                         ErrPrint("Set fault %s(%d)\n", !ret ? "Success" : "Failed", ret);
244                         fault_broadcast_info(pkgname, "", "");
245
246                         s_info.fault_mark_count = 0;
247                         clear_log_file(slave);
248                         EINA_LIST_REVERSE_FOREACH_SAFE(s_info.call_list, l, n, info) {
249                                 if (info->slave != slave) {
250                                         continue;
251                                 }
252
253                                 s_info.call_list = eina_list_remove_list(s_info.call_list, l);
254
255                                 DbgFree(info->pkgname);
256                                 DbgFree(info->filename);
257                                 DbgFree(info->func);
258                                 DbgFree(info);
259                         }
260                         return 0;
261                 }
262         }
263
264         /*!
265          * \note
266          * At last, check the pair of function call and return mark
267          */
268         checked = 0;
269         EINA_LIST_REVERSE_FOREACH_SAFE(s_info.call_list, l, n, info) {
270                 if (info->slave == slave) {
271                         const char *filename;
272                         const char *func;
273
274                         pkg = package_find(info->pkgname);
275                         if (!pkg) {
276                                 ErrPrint("Failed to find a package %s\n", info->pkgname);
277                                 continue;
278                         }
279
280                         filename = info->filename ? info->filename : "";
281                         func = info->func ? info->func : "";
282
283                         if (!checked) {
284                                 int ret;
285                                 ret = package_set_fault_info(pkg, info->timestamp, info->filename, info->func);
286                                 fault_broadcast_info(info->pkgname, info->filename, info->func);
287                                 ErrPrint("Set fault %s(%d)\n", !ret ? "Success" : "Failed", ret);
288                         } else {
289                                 DbgPrint("Treated as a false log\n");
290                                 dump_fault_info(
291                                         slave_name(info->slave), slave_pid(info->slave), info->pkgname, filename, func);
292                         }
293
294                         s_info.call_list = eina_list_remove_list(s_info.call_list, l);
295
296                         DbgFree(info->pkgname);
297                         DbgFree(info->filename);
298                         DbgFree(info->func);
299                         DbgFree(info);
300                         checked = 1;
301                 }
302         }
303
304         s_info.fault_mark_count = 0;
305         clear_log_file(slave);
306         return 0;
307 }
308
309 HAPI int fault_func_call(struct slave_node *slave, const char *pkgname, const char *filename, const char *func)
310 {
311         struct fault_info *info;
312
313         info = malloc(sizeof(*info));
314         if (!info) {
315                 return LB_STATUS_ERROR_MEMORY;
316         }
317
318         info->slave = slave;
319
320         info->pkgname = strdup(pkgname);
321         if (!info->pkgname) {
322                 DbgFree(info);
323                 return LB_STATUS_ERROR_MEMORY;
324         }
325
326         info->filename = strdup(filename);
327         if (!info->filename) {
328                 DbgFree(info->pkgname);
329                 DbgFree(info);
330                 return LB_STATUS_ERROR_MEMORY;
331         }
332
333         info->func = strdup(func);
334         if (!info->func) {
335                 DbgFree(info->filename);
336                 DbgFree(info->pkgname);
337                 DbgFree(info);
338                 return LB_STATUS_ERROR_MEMORY;
339         }
340
341         info->timestamp = util_timestamp();
342
343         s_info.call_list = eina_list_append(s_info.call_list, info);
344
345         s_info.fault_mark_count++;
346         return LB_STATUS_SUCCESS;
347 }
348
349 HAPI int fault_func_ret(struct slave_node *slave, const char *pkgname, const char *filename, const char *func)
350 {
351         struct fault_info *info;
352         Eina_List *l;
353
354         EINA_LIST_FOREACH(s_info.call_list, l, info) {
355                 if (info->slave != slave) {
356                         continue;
357                 }
358
359                 if (strcmp(info->pkgname, pkgname)) {
360                         continue;
361                 }
362
363                 if (strcmp(info->filename, filename)) {
364                         continue;
365                 }
366
367                 if (strcmp(info->func, func)) {
368                         continue;
369                 }
370
371                 s_info.call_list = eina_list_remove_list(s_info.call_list, l);
372                 DbgFree(info->filename);
373                 DbgFree(info->pkgname);
374                 DbgFree(info->func);
375                 DbgFree(info);
376
377                 s_info.fault_mark_count--;
378                 return 0;
379         } 
380
381         return LB_STATUS_ERROR_NOT_EXIST;
382 }
383
384 /* End of a file */