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