Add new event type for uninstall/upgrade packages.
[platform/framework/web/data-provider-master.git] / src / package.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 <errno.h>
19 #include <string.h> /* strcmp */
20 #include <stdlib.h> /* free */
21
22 #include <dlog.h>
23 #include <Eina.h>
24 #include <Ecore_Evas.h>
25
26 #include <packet.h>
27 #include <livebox-errno.h>
28 #include <livebox-service.h>
29 #include <ail.h>
30
31 #include "critical_log.h"
32 #include "debug.h"
33 #include "util.h"
34 #include "parser.h"
35 #include "conf.h"
36 #include "slave_life.h"
37 #include "slave_rpc.h"
38 #include "client_life.h"
39 #include "package.h"
40 #include "fault_manager.h"
41 #include "instance.h"
42 #include "script_handler.h"
43 #include "group.h"
44 #include "abi.h"
45 #include "io.h"
46 #include "pkgmgr.h"
47 #include "xmonitor.h"
48
49 int errno;
50
51 struct fault_info {
52         double timestamp;
53         char *filename;
54         char *function;
55 };
56
57 /*!
58  * pkg_info describes the loaded package.
59  */
60
61 struct pkg_info {
62         char *pkgid;
63         char *lbid;
64
65         struct {
66                 enum lb_type type;
67
68                 union {
69                         struct {
70                                 char *path;
71                                 char *group;
72                         } script;
73
74                         struct {
75                                 /*!< Reserved for future use */
76                         } file;
77
78                         struct {
79                                 /*!< Reserved for future use */
80                         } text;
81
82                         struct {
83                                 /*!< Reserved for future use */
84                         } buffer;
85                 } info;
86
87                 unsigned int size_list;
88                 char *auto_launch;
89                 int pinup;
90                 int timeout;
91                 double period;
92                 char *libexec;
93         } lb;
94
95         struct {
96                 enum pd_type type;
97
98                 union {
99                         struct {
100                                 char *path;
101                                 char *group;
102                         } script;
103
104                         struct {
105                                 /*!< Reserved for future use */
106                         } text;
107
108                         struct {
109                                 /*!< Reserved for future use */
110                         } buffer;
111                 } info;
112
113                 unsigned int width;
114                 unsigned int height;
115         } pd;
116
117         int network;
118         int secured;
119         char *script; /* script type: edje, ... */
120         char *abi;
121
122         int fault_count;
123         struct fault_info *fault_info;
124
125         struct slave_node *slave;
126         int refcnt;
127
128         Eina_List *inst_list;
129         Eina_List *ctx_list;
130
131         int is_uninstalled;
132 };
133
134 static struct {
135         Eina_List *pkg_list;
136 } s_info = {
137         .pkg_list = NULL,
138 };
139
140 static int slave_activated_cb(struct slave_node *slave, void *data)
141 {
142         struct pkg_info *info = data;
143         struct inst_info *inst;
144         Eina_List *l;
145         Eina_List *n;
146         int cnt;
147         int ret;
148
149         if (!slave_need_to_reactivate_instances(slave)) {
150                 DbgPrint("Do not need to reactivate instances\n");
151                 return 0;
152         }
153
154         cnt = 0;
155         EINA_LIST_FOREACH_SAFE(info->inst_list, l, n, inst) {
156                 ret = instance_recover_state(inst);
157                 if (!ret) {
158                         continue;
159                 }
160
161                 instance_thaw_updator(inst);
162                 cnt++;
163         }
164
165         DbgPrint("Recover state for %d instances of %s\n", cnt, package_name(info));
166         return 0;
167 }
168
169 static int slave_fault_cb(struct slave_node *slave, void *data)
170 {
171         Eina_List *l;
172         Eina_List *n;
173         struct inst_info *inst;
174         struct pkg_info *info = (struct pkg_info *)data;
175
176         if (package_is_fault(info)) {
177                 ErrPrint("Already faulted package: %s\n", package_name(info));
178                 return 0;
179         }
180
181         (void)package_set_fault_info(info, util_timestamp(), slave_name(slave), __func__);
182         fault_broadcast_info(package_name(info), slave_name(slave), __func__);
183
184         DbgPrint("Slave critical fault - package: %s (by slave fault %s\n", package_name(info), slave_name(slave));
185         EINA_LIST_FOREACH_SAFE(info->inst_list, l, n, inst) {
186                 DbgPrint("Destroy instance %p\n", inst);
187                 instance_destroyed(inst);
188         }
189
190         return 0;
191 }
192
193 static int slave_deactivated_cb(struct slave_node *slave, void *data)
194 {
195         struct pkg_info *info = data;
196         struct inst_info *inst;
197         Eina_List *l;
198         Eina_List *n;
199         int cnt = 0;
200
201         if (info->fault_info) {
202                 EINA_LIST_FOREACH_SAFE(info->inst_list, l, n, inst) {
203                         instance_destroyed(inst);
204                 }
205         } else {
206                 EINA_LIST_FOREACH_SAFE(info->inst_list, l, n, inst) {
207                         cnt += instance_need_slave(inst);
208                         /*!
209                          * instance_deactivated will call the slave_unload_instance.
210                          * if the loaded instance counter meets 0,
211                          * the slave will be deactivated.
212                          * so we should not call the instance activate function
213                          * from here.
214                          *
215                          * activate slave when the slave is reactivated
216                          */
217                 }
218         }
219
220         return cnt ? SLAVE_NEED_TO_REACTIVATE : 0;
221 }
222
223 static int xmonitor_paused_cb(void *data)
224 {
225         struct pkg_info *info = (struct pkg_info *)data;
226         struct inst_info *inst;
227         Eina_List *l;
228
229         if (slave_state(info->slave) != SLAVE_TERMINATED) {
230                 return 0;
231         }
232
233         EINA_LIST_FOREACH(info->inst_list, l, inst) {
234                 instance_freeze_updator(inst);
235         }
236
237         return 0;
238 }
239
240 static int xmonitor_resumed_cb(void *data)
241 {
242         struct pkg_info *info = data;
243         struct inst_info *inst;
244         Eina_List *l;
245
246         if (slave_state(info->slave) != SLAVE_TERMINATED) {
247                 return 0;
248         }
249
250         EINA_LIST_FOREACH(info->inst_list, l, inst) {
251                 instance_thaw_updator(inst);
252         }
253
254         return 0;
255 }
256
257 static int slave_paused_cb(struct slave_node *slave, void *data)
258 {
259         struct pkg_info *info = (struct pkg_info *)data;
260         struct inst_info *inst;
261         Eina_List *l;
262
263         EINA_LIST_FOREACH(info->inst_list, l, inst) {
264                 instance_freeze_updator(inst);
265         }
266
267         return 0;
268 }
269
270 static int slave_resumed_cb(struct slave_node *slave, void *data)
271 {
272         struct pkg_info *info = (struct pkg_info *)data;
273         struct inst_info *inst;
274         Eina_List *l;
275
276         EINA_LIST_FOREACH(info->inst_list, l, inst) {
277                 instance_thaw_updator(inst);
278         }
279
280         return 0;
281 }
282
283 static inline void destroy_package(struct pkg_info *info)
284 {
285         struct context_info *ctx_info __attribute__((unused));
286
287         EINA_LIST_FREE(info->ctx_list, ctx_info) {
288                 /* This items will be deleted from group_del_livebox */
289         }
290
291         group_del_livebox(info->lbid);
292         package_clear_fault(info);
293
294         s_info.pkg_list = eina_list_remove(s_info.pkg_list, info);
295
296         if (info->lb.type == LB_TYPE_SCRIPT) {
297                 DbgFree(info->lb.info.script.path);
298                 DbgFree(info->lb.info.script.group);
299         }
300
301         if (info->pd.type == PD_TYPE_SCRIPT) {
302                 DbgFree(info->pd.info.script.path);
303                 DbgFree(info->pd.info.script.group);
304         }
305
306         DbgFree(info->script);
307         DbgFree(info->abi);
308         DbgFree(info->lbid);
309         DbgFree(info->lb.libexec);
310         DbgFree(info->lb.auto_launch);
311         DbgFree(info->pkgid);
312
313         DbgFree(info);
314 }
315
316 static inline int load_conf(struct pkg_info *info)
317 {
318         struct parser *parser;
319         const char *str;
320         const char *group;
321
322         parser = parser_load(info->lbid);
323         if (!parser) {
324                 info->lb.size_list = 0x01; /* Default */
325
326                 info->script = strdup(DEFAULT_SCRIPT);
327                 if (!info->script) {
328                         ErrPrint("Heap: %s\n", strerror(errno));
329                         return LB_STATUS_ERROR_MEMORY;
330                 }
331
332                 info->abi = strdup(DEFAULT_ABI);
333                 if (!info->abi) {
334                         ErrPrint("Heap: %s\n", strerror(errno));
335                         DbgFree(info->script);
336                         info->script = NULL;
337                         return LB_STATUS_ERROR_MEMORY;
338                 }
339
340                 info->pd.width = g_conf.width;
341                 info->pd.height = g_conf.height >> 2;
342                 info->lb.pinup = 1;
343                 return LB_STATUS_SUCCESS;
344         }
345
346         info->lb.type = LB_TYPE_FILE;
347         if (parser_text_lb(parser)) {
348                 info->lb.type = LB_TYPE_TEXT;
349         } else if (parser_buffer_lb(parser)) {
350                 info->lb.type = LB_TYPE_BUFFER;
351         } else {
352                 str = parser_lb_path(parser);
353                 if (str) {
354                         info->lb.type = LB_TYPE_SCRIPT;
355
356                         info->lb.info.script.path = strdup(str);
357                         if (!info->lb.info.script.path) {
358                                 ErrPrint("Heap: %s\n", strerror(errno));
359                                 parser_unload(parser);
360                                 return LB_STATUS_ERROR_MEMORY;
361                         }
362
363                         str = parser_lb_group(parser);
364                         if (str) {
365                                 info->lb.info.script.group = strdup(str);
366                                 if (!info->lb.info.script.group) {
367                                         ErrPrint("Heap: %s\n", strerror(errno));
368                                         DbgFree(info->lb.info.script.path);
369                                         parser_unload(parser);
370                                         return LB_STATUS_ERROR_MEMORY;
371                                 }
372                         }
373                 }
374         }
375
376         if (parser_text_pd(parser)) {
377                 info->pd.type = PD_TYPE_TEXT;
378         } else if (parser_buffer_pd(parser)) {
379                 info->pd.type = PD_TYPE_BUFFER;
380         } else {
381                 str = parser_pd_path(parser);
382                 if (str) {
383                         info->pd.type = PD_TYPE_SCRIPT;
384                         info->pd.info.script.path = strdup(str);
385                         if (!info->pd.info.script.path) {
386                                 ErrPrint("Heap: %s\n", strerror(errno));
387                                 if (info->lb.type == LB_TYPE_SCRIPT) {
388                                         DbgFree(info->lb.info.script.path);
389                                         DbgFree(info->lb.info.script.group);
390                                 }
391                                 parser_unload(parser);
392                                 return LB_STATUS_ERROR_MEMORY;
393                         }
394
395                         str = parser_pd_group(parser);
396                         if (str) {
397                                 info->pd.info.script.group = strdup(str);
398                                 if (!info->pd.info.script.group) {
399                                         ErrPrint("Heap: %s\n", strerror(errno));
400                                         DbgFree(info->pd.info.script.path);
401                                         if (info->lb.type == LB_TYPE_SCRIPT) {
402                                                 DbgFree(info->lb.info.script.path);
403                                                 DbgFree(info->lb.info.script.group);
404                                         }
405                                         parser_unload(parser);
406                                         return LB_STATUS_ERROR_MEMORY;
407                                 }
408                         }
409                 }
410         }
411
412         str = parser_script(parser);
413         str = str ? str : DEFAULT_SCRIPT;
414         info->script = strdup(str);
415         if (!info->script) {
416                 ErrPrint("Heap: %s\n", strerror(errno));
417                 if (info->pd.type == PD_TYPE_SCRIPT) {
418                         DbgFree(info->pd.info.script.path);
419                         DbgFree(info->pd.info.script.group);
420                 }
421
422                 if (info->lb.type == LB_TYPE_SCRIPT) {
423                         DbgFree(info->lb.info.script.path);
424                         DbgFree(info->lb.info.script.group);
425                 }
426
427                 parser_unload(parser);
428                 return LB_STATUS_ERROR_MEMORY;
429         }
430
431         str = parser_abi(parser);
432         str = str ? str : DEFAULT_ABI;
433         info->abi = strdup(str);
434         if (!info->abi) {
435                 ErrPrint("Heap: %s\n", strerror(errno));
436                 DbgFree(info->script);
437                 if (info->pd.type == PD_TYPE_SCRIPT) {
438                         DbgFree(info->pd.info.script.path);
439                         DbgFree(info->pd.info.script.group);
440                 }
441
442                 if (info->lb.type == LB_TYPE_SCRIPT) {
443                         DbgFree(info->lb.info.script.path);
444                         DbgFree(info->lb.info.script.group);
445                 }
446                 parser_unload(parser);
447                 return LB_STATUS_ERROR_MEMORY;
448         }
449
450         info->lb.timeout = parser_timeout(parser);
451         info->network = parser_network(parser);
452
453         info->lb.period = parser_period(parser);
454         if (info->lb.period < 0.0f) {
455                 info->lb.period = 0.0f;
456         } else if (info->lb.period > 0.0f && info->lb.period < MINIMUM_PERIOD) {
457                 info->lb.period = MINIMUM_PERIOD;
458         }
459
460         info->lb.size_list = parser_size(parser);
461
462         str = parser_auto_launch(parser);
463         str = str ? str : "";
464         info->lb.auto_launch = strdup(str);
465         if (!info->lb.auto_launch) {
466                 ErrPrint("Heap: %s\n", strerror(errno));
467                 DbgFree(info->abi);
468                 DbgFree(info->script);
469                 if (info->pd.type == PD_TYPE_SCRIPT) {
470                         DbgFree(info->pd.info.script.path);
471                         DbgFree(info->pd.info.script.group);
472                 }
473
474                 if (info->lb.type == LB_TYPE_SCRIPT) {
475                         DbgFree(info->lb.info.script.path);
476                         DbgFree(info->lb.info.script.group);
477                 }
478                 parser_unload(parser);
479                 return LB_STATUS_ERROR_MEMORY;
480         }
481
482         info->secured = parser_secured(parser);
483         info->lb.pinup = parser_pinup(parser);
484
485         parser_get_pdsize(parser, &info->pd.width, &info->pd.height);
486
487         group = parser_group_str(parser);
488         if (group && group_add_livebox(group, info->lbid) < 0) {
489                 ErrPrint("Failed to build cluster tree for %s{%s}\n", info->lbid, group);
490         }
491
492         parser_unload(parser);
493         return LB_STATUS_SUCCESS;
494 }
495
496 HAPI struct pkg_info *package_create(const char *pkgid, const char *lbid)
497 {
498         struct pkg_info *pkginfo;
499
500         pkginfo = calloc(1, sizeof(*pkginfo));
501         if (!pkginfo) {
502                 ErrPrint("Heap: %s\n", strerror(errno));
503                 return NULL;
504         }
505
506         pkginfo->pkgid = strdup(pkgid);
507         if (!pkginfo->pkgid) {
508                 ErrPrint("Heap: %s\n", strerror(errno));
509                 DbgFree(pkginfo);
510                 return NULL;
511         }
512
513         pkginfo->lbid = io_livebox_pkgname(lbid);
514         if (!pkginfo->lbid) {
515                 ErrPrint("Failed to get pkgname, fallback to fs checker\n");
516                 if (util_validate_livebox_package(lbid) < 0) {
517                         ErrPrint("Invalid package name: %s\n", lbid);
518                         DbgFree(pkginfo->pkgid);
519                         DbgFree(pkginfo);
520                         return NULL;
521                 }
522
523                 pkginfo->lbid = strdup(lbid);
524                 if (!pkginfo->lbid) {
525                         ErrPrint("Heap: %s\n", strerror(errno));
526                         DbgFree(pkginfo->pkgid);
527                         DbgFree(pkginfo);
528                         return NULL;
529                 }
530         }
531
532         if (io_load_package_db(pkginfo) < 0) {
533                 ErrPrint("Failed to load DB, fall back to conf file loader\n");
534                 if (load_conf(pkginfo) < 0) {
535                         ErrPrint("Failed to initiate the conf file loader\n");
536                         DbgFree(pkginfo->lbid);
537                         DbgFree(pkginfo->pkgid);
538                         DbgFree(pkginfo);
539                         return NULL;
540                 }
541         }
542
543         package_ref(pkginfo);
544
545         s_info.pkg_list = eina_list_append(s_info.pkg_list, pkginfo);
546
547         return pkginfo;
548 }
549
550 HAPI int package_destroy(struct pkg_info *info)
551 {
552         package_unref(info);
553         return LB_STATUS_SUCCESS;
554 }
555
556 HAPI Eina_List *package_ctx_info(struct pkg_info *pkginfo)
557 {
558         return pkginfo->ctx_list;
559 }
560
561 HAPI void package_add_ctx_info(struct pkg_info *pkginfo, struct context_info *info)
562 {
563         pkginfo->ctx_list = eina_list_append(pkginfo->ctx_list, info);
564 }
565
566 HAPI void package_del_ctx_info(struct pkg_info *pkginfo, struct context_info *info)
567 {
568         pkginfo->ctx_list = eina_list_remove(pkginfo->ctx_list, info);
569 }
570
571 HAPI char *package_lb_pkgname(const char *pkgname)
572 {
573         char *lbid;
574
575         lbid = io_livebox_pkgname(pkgname);
576         if (!lbid) {
577                 if (util_validate_livebox_package(pkgname) < 0) {
578                         return NULL;
579                 }
580
581                 lbid = strdup(pkgname);
582                 if (!lbid) {
583                         ErrPrint("Heap: %s\n", strerror(errno));
584                         return NULL;
585                 }
586         }
587
588         return lbid;
589 }
590
591 HAPI int package_is_lb_pkgname(const char *pkgname)
592 {
593         char *lbid;
594         int ret;
595
596         lbid = package_lb_pkgname(pkgname);
597         ret = !!lbid;
598         DbgFree(lbid);
599
600         return ret;
601 }
602
603 HAPI struct pkg_info *package_find(const char *lbid)
604 {
605         Eina_List *l;
606         struct pkg_info *info;
607
608         if (!lbid) {
609                 return NULL;
610         }
611
612         EINA_LIST_FOREACH(s_info.pkg_list, l, info) {
613                 if (!strcmp(info->lbid, lbid)) {
614                         return info;
615                 }
616         }
617
618         return NULL;
619 }
620
621 HAPI struct inst_info *package_find_instance_by_id(const char *lbid, const char *id)
622 {
623         Eina_List *l;
624         struct inst_info *inst;
625         struct pkg_info *info;
626
627         info = package_find(lbid);
628         if (!info) {
629                 ErrPrint("Package %s is not exists\n", lbid);
630                 return NULL;
631         }
632
633         EINA_LIST_FOREACH(info->inst_list, l, inst) {
634                 if (!strcmp(instance_id(inst), id)) {
635                         return inst;
636                 }
637         }
638
639         return NULL;
640 }
641
642 HAPI struct inst_info *package_find_instance_by_timestamp(const char *lbid, double timestamp)
643 {
644         Eina_List *l;
645         struct inst_info *inst;
646         struct pkg_info *info;
647
648         info = package_find(lbid);
649         if (!info) {
650                 ErrPrint("Package %s is not exists\n", lbid);
651                 return NULL;
652         }
653
654         EINA_LIST_FOREACH(info->inst_list, l, inst) {
655                 if (instance_timestamp(inst) == timestamp) {
656                         return inst;
657                 }
658         }
659
660         return NULL;
661 }
662
663 HAPI int package_dump_fault_info(struct pkg_info *info)
664 {
665         if (!info->fault_info) {
666                 return LB_STATUS_ERROR_NOT_EXIST;
667         }
668
669         CRITICAL_LOG("=============\n");
670         CRITICAL_LOG("faulted at %lf\n", info->fault_info->timestamp);
671         CRITICAL_LOG("Package: %s\n", info->lbid);
672         CRITICAL_LOG("Function: %s\n", info->fault_info->function);
673         CRITICAL_LOG("InstanceID: %s\n", info->fault_info->filename);
674         return LB_STATUS_SUCCESS;
675 }
676
677 HAPI int package_get_fault_info(struct pkg_info *info, double *timestamp, const char **filename, const char **function)
678 {
679         if (!info->fault_info) {
680                 return LB_STATUS_ERROR_NOT_EXIST;
681         }
682
683         *timestamp = info->fault_info->timestamp;
684         *filename = info->fault_info->filename;
685         *function = info->fault_info->function;
686         return LB_STATUS_SUCCESS;
687 }
688
689 HAPI int package_set_fault_info(struct pkg_info *info, double timestamp, const char *filename, const char *function)
690 {
691         struct fault_info *fault;
692
693         package_clear_fault(info);
694
695         fault = calloc(1, sizeof(*fault));
696         if (!fault) {
697                 ErrPrint("Heap: %s\n", strerror(errno));
698                 return LB_STATUS_ERROR_MEMORY;
699         }
700
701         fault->timestamp = timestamp;
702         if (!filename) {
703                 filename = "unknown";
704         }
705         if (!function) {
706                 function = "unknown";
707         }
708
709         fault->filename = strdup(filename);
710         if (!fault->filename) {
711                 ErrPrint("Heap: %s\n", strerror(errno));
712                 DbgFree(fault);
713                 return LB_STATUS_ERROR_MEMORY;
714         }
715
716         fault->function = strdup(function);
717         if (!fault->function) {
718                 ErrPrint("Heap: %s\n", strerror(errno));
719                 DbgFree(fault->filename);
720                 DbgFree(fault);
721                 return LB_STATUS_ERROR_MEMORY;
722         }
723
724         info->fault_info = fault;
725         info->fault_count++;
726         return LB_STATUS_SUCCESS;
727 }
728
729 HAPI int package_clear_fault(struct pkg_info *info)
730 {
731         if (!info->fault_info) {
732                 return LB_STATUS_ERROR_INVALID;
733         }
734         
735         package_dump_fault_info(info);
736
737         DbgFree(info->fault_info->function);
738         DbgFree(info->fault_info->filename);
739         DbgFree(info->fault_info);
740         info->fault_info = NULL;
741         return LB_STATUS_SUCCESS;
742 }
743
744 HAPI const int const package_is_fault(const struct pkg_info *info)
745 {
746         return !!info->fault_info;
747 }
748
749 HAPI struct slave_node * const package_slave(const struct pkg_info *info)
750 {
751         return info->slave;
752 }
753
754 HAPI const int const package_timeout(const struct pkg_info *info)
755 {
756         return info->lb.timeout;
757 }
758
759 HAPI void package_set_timeout(struct pkg_info *info, int timeout)
760 {
761         info->lb.timeout = timeout;
762 }
763
764 HAPI const double const package_period(const struct pkg_info *info)
765 {
766         return info->lb.period;
767 }
768
769 HAPI void package_set_period(struct pkg_info *info, double period)
770 {
771         info->lb.period = period;
772 }
773
774 HAPI const int const package_secured(const struct pkg_info *info)
775 {
776         return info->secured;
777 }
778
779 HAPI void package_set_secured(struct pkg_info *info, int secured)
780 {
781         info->secured = secured;
782 }
783
784 HAPI const char * const package_script(const struct pkg_info *info)
785 {
786         return info->script;
787 }
788
789 HAPI int package_set_script(struct pkg_info *info, const char *script)
790 {
791         char *tmp;
792
793         tmp = strdup(script);
794         if (!tmp) {
795                 ErrPrint("Heap: %s\n", strerror(errno));
796                 return LB_STATUS_ERROR_MEMORY;
797         }
798
799         DbgFree(info->script);
800         info->script = tmp;
801         return LB_STATUS_SUCCESS;
802 }
803
804 HAPI const char * const package_abi(const struct pkg_info *info)
805 {
806         return info->abi;
807 }
808
809 HAPI int package_set_abi(struct pkg_info *info, const char *abi)
810 {
811         char *tmp;
812         tmp = strdup(abi);
813         if (!tmp) {
814                 ErrPrint("Heap: %s\n", strerror(errno));
815                 return LB_STATUS_ERROR_MEMORY;
816         }
817
818         DbgFree(info->abi);
819         info->abi = tmp;
820         return LB_STATUS_SUCCESS;
821 }
822
823 HAPI const char * const package_lb_path(const struct pkg_info *info)
824 {
825         if (info->lb.type != LB_TYPE_SCRIPT) {
826                 return NULL;
827         }
828
829         return info->lb.info.script.path;
830 }
831
832 HAPI int package_set_lb_path(struct pkg_info *info, const char *path)
833 {
834         char *tmp;
835
836         if (info->lb.type != LB_TYPE_SCRIPT) {
837                 return LB_STATUS_ERROR_INVALID;
838         }
839
840         tmp = strdup(path);
841         if (!tmp) {
842                 ErrPrint("Heap: %s\n", strerror(errno));
843                 return LB_STATUS_ERROR_MEMORY;
844         }
845
846         DbgFree(info->lb.info.script.path);
847         info->lb.info.script.path = tmp;
848         return LB_STATUS_SUCCESS;
849 }
850
851 HAPI const char * const package_lb_group(const struct pkg_info *info)
852 {
853         if (info->lb.type != LB_TYPE_SCRIPT) {
854                 return NULL;
855         }
856
857         return info->lb.info.script.group;
858 }
859
860 HAPI int package_set_lb_group(struct pkg_info *info, const char *group)
861 {
862         char *tmp;
863
864         if (info->lb.type != LB_TYPE_SCRIPT) {
865                 return LB_STATUS_ERROR_INVALID;
866         }
867
868         tmp = strdup(group);
869         if (!tmp) {
870                 ErrPrint("Heap: %s\n", strerror(errno));
871                 return LB_STATUS_ERROR_MEMORY;
872         }
873
874         DbgFree(info->lb.info.script.group);
875         info->lb.info.script.group = tmp;
876         return LB_STATUS_SUCCESS;
877 }
878
879 HAPI const char * const package_pd_path(const struct pkg_info *info)
880 {
881         if (info->pd.type != PD_TYPE_SCRIPT) {
882                 return NULL;
883         }
884
885         return info->pd.info.script.path;
886 }
887
888 HAPI int package_set_pd_path(struct pkg_info *info, const char *path)
889 {
890         char *tmp;
891
892         if (info->pd.type != PD_TYPE_SCRIPT) {
893                 return LB_STATUS_ERROR_INVALID;
894         }
895
896         tmp = strdup(path);
897         if (!tmp) {
898                 ErrPrint("Heap: %s\n", strerror(errno));
899                 return LB_STATUS_ERROR_MEMORY;
900         }
901
902         DbgFree(info->pd.info.script.path);
903         info->pd.info.script.path = tmp;
904         return LB_STATUS_SUCCESS;
905 }
906
907 HAPI const char * const package_pd_group(const struct pkg_info *info)
908 {
909         if (info->pd.type != PD_TYPE_SCRIPT) {
910                 return NULL;
911         }
912
913         return info->pd.info.script.group;
914 }
915
916 HAPI int package_set_pd_group(struct pkg_info *info, const char *group)
917 {
918         char *tmp;
919
920         if (info->pd.type != PD_TYPE_SCRIPT) {
921                 return LB_STATUS_ERROR_INVALID;
922         }
923
924         tmp = strdup(group);
925         if (!tmp) {
926                 ErrPrint("Heap: %s\n", strerror(errno));
927                 return LB_STATUS_ERROR_MEMORY;
928         }
929
930         DbgFree(info->pd.info.script.group);
931         info->pd.info.script.group = tmp;
932         return LB_STATUS_SUCCESS;
933 }
934
935 HAPI const int const package_pinup(const struct pkg_info *info)
936 {
937         return info->lb.pinup;
938 }
939
940 HAPI void package_set_pinup(struct pkg_info *info, int pinup)
941 {
942         info->lb.pinup = pinup;
943 }
944
945 HAPI const char * const package_auto_launch(const struct pkg_info *info)
946 {
947         return info->lb.auto_launch;
948 }
949
950 HAPI void package_set_auto_launch(struct pkg_info *info, const char *auto_launch)
951 {
952         if (!auto_launch) {
953                 auto_launch = "";
954         }
955
956         info->lb.auto_launch = strdup(auto_launch);
957         if (!info->lb.auto_launch) {
958                 ErrPrint("Heap: %s\n", strerror(errno));
959                 return;
960         }
961 }
962
963 HAPI const unsigned int const package_size_list(const struct pkg_info *info)
964 {
965         return info->lb.size_list;
966 }
967
968 HAPI void package_set_size_list(struct pkg_info *info, unsigned int size_list)
969 {
970         info->lb.size_list = size_list;
971 }
972
973 HAPI const int const package_pd_width(const struct pkg_info *info)
974 {
975         return info->pd.width;
976 }
977
978 HAPI void package_set_pd_width(struct pkg_info *info, int width)
979 {
980         info->pd.width = width;
981 }
982
983 HAPI const int const package_pd_height(const struct pkg_info *info)
984 {
985         return info->pd.height;
986 }
987
988 HAPI void package_set_pd_height(struct pkg_info *info, int height)
989 {
990         info->pd.height = height;
991 }
992
993 HAPI struct pkg_info * const package_ref(struct pkg_info *info)
994 {
995         info->refcnt++;
996         return info;
997 }
998
999 HAPI struct pkg_info * const package_unref(struct pkg_info *info)
1000 {
1001         if (info->refcnt == 0) {
1002                 ErrPrint("Invalid request\n");
1003                 return NULL;
1004         }
1005
1006         info->refcnt--;
1007         if (info->refcnt == 0) {
1008                 destroy_package(info);
1009                 info = NULL;
1010         }
1011
1012         return info;
1013 }
1014
1015 HAPI const int const package_refcnt(const struct pkg_info *info)
1016 {
1017         return info->refcnt;
1018 }
1019
1020 HAPI const enum lb_type package_lb_type(const struct pkg_info *info)
1021 {
1022         return info->lb.type;
1023 }
1024
1025 HAPI void package_set_lb_type(struct pkg_info *info, enum lb_type type)
1026 {
1027         info->lb.type = type;
1028 }
1029
1030 HAPI const char * const package_libexec(struct pkg_info *info)
1031 {
1032         return info->lb.libexec;
1033 }
1034
1035 HAPI int package_set_libexec(struct pkg_info *info, const char *libexec)
1036 {
1037         char *tmp;
1038
1039         tmp = strdup(libexec);
1040         if (!tmp) {
1041                 ErrPrint("Heap: %s\n", strerror(errno));
1042                 return LB_STATUS_ERROR_MEMORY;
1043         }
1044
1045         DbgFree(info->lb.libexec);
1046         info->lb.libexec = tmp;
1047         return LB_STATUS_SUCCESS;
1048 }
1049
1050 HAPI int package_network(struct pkg_info *info)
1051 {
1052         return info->network;
1053 }
1054
1055 HAPI void package_set_network(struct pkg_info *info, int network)
1056 {
1057         info->network = network;
1058 }
1059
1060 HAPI const enum pd_type const package_pd_type(const struct pkg_info *info)
1061 {
1062         return info->pd.type;
1063 }
1064
1065 HAPI void package_set_pd_type(struct pkg_info *info, enum pd_type type)
1066 {
1067         info->pd.type = type;
1068 }
1069
1070 /*!
1071  * \note
1072  * Add the instance to the package info.
1073  * If a package has no slave, assign a new slave.
1074  */
1075 static inline int assign_new_slave(struct pkg_info *info)
1076 {
1077         char *s_name;
1078         char *s_pkgname;
1079         const char *tmp;
1080
1081         s_name = util_slavename();
1082         if (!s_name) {
1083                 ErrPrint("Failed to get a new slave name\n");
1084                 return LB_STATUS_ERROR_FAULT;
1085         }
1086
1087         tmp = abi_find_slave(info->abi);
1088         if (!tmp) {
1089                 DbgFree(s_name);
1090                 ErrPrint("Failed to find a proper pkgname of a slave\n");
1091                 return LB_STATUS_ERROR_INVALID;
1092         }
1093
1094         s_pkgname = util_replace_string(tmp, REPLACE_TAG_APPID, info->lbid);
1095         if (!s_pkgname) {
1096                 DbgPrint("Failed to get replaced string\n");
1097                 s_pkgname = strdup(tmp);
1098                 if (!s_pkgname) {
1099                         ErrPrint("Heap: %s\n", strerror(errno));
1100                         DbgFree(s_name);
1101                         return LB_STATUS_ERROR_MEMORY;
1102                 }
1103         }
1104
1105         DbgPrint("New slave[%s] is assigned for %s (using %s / abi[%s])\n", s_name, info->lbid, s_pkgname, info->abi);
1106         info->slave = slave_create(s_name, info->secured, info->abi, s_pkgname, info->network);
1107
1108         DbgFree(s_name);
1109         DbgFree(s_pkgname);
1110
1111         if (!info->slave) {
1112                 /*!
1113                  * \note
1114                  * package_destroy will try to remove "info" from the pkg_list.
1115                  * but we didn't add this to it yet.
1116                  * If the list method couldn't find an "info" from the list,
1117                  * it just do nothing so I'll leave this.
1118                  */
1119                 return LB_STATUS_ERROR_FAULT;
1120         }
1121         /*!
1122          * \note
1123          * Slave is not activated yet.
1124          */
1125         return LB_STATUS_SUCCESS;
1126 }
1127
1128 HAPI int package_add_instance(struct pkg_info *info, struct inst_info *inst)
1129 {
1130         if (!info->inst_list) {
1131                 info->slave = slave_find_available(info->abi, info->secured, info->network);
1132
1133                 if (!info->slave) {
1134                         int ret;
1135
1136                         ret = assign_new_slave(info);
1137                         if (ret < 0) {
1138                                 return ret;
1139                         }
1140                 } else {
1141                         DbgPrint("Slave %s is used for %s\n", slave_name(info->slave), info->lbid);
1142                 }
1143
1144                 slave_ref(info->slave);
1145                 slave_load_package(info->slave);
1146                 slave_event_callback_add(info->slave, SLAVE_EVENT_DEACTIVATE, slave_deactivated_cb, info);
1147                 slave_event_callback_add(info->slave, SLAVE_EVENT_ACTIVATE, slave_activated_cb, info);
1148                 slave_event_callback_add(info->slave, SLAVE_EVENT_FAULT, slave_fault_cb, info);
1149
1150                 if (info->secured) {
1151                         slave_event_callback_add(info->slave, SLAVE_EVENT_PAUSE, slave_paused_cb, info);
1152                         slave_event_callback_add(info->slave, SLAVE_EVENT_RESUME, slave_resumed_cb, info);
1153
1154                         /*!
1155                          * \note
1156                          * In case of the slave is terminated because of expired TTL timer,
1157                          * Master should freeze the all update time.
1158                          * But the callback should check the slave's state to prevent from duplicated freezing.
1159                          *
1160                          * This callback will freeze the timer only if a slave doesn't running.
1161                          */
1162                         xmonitor_add_event_callback(XMONITOR_PAUSED, xmonitor_paused_cb, info);
1163                         xmonitor_add_event_callback(XMONITOR_RESUMED, xmonitor_resumed_cb, info);
1164                 }
1165         }
1166
1167         info->inst_list = eina_list_append(info->inst_list, inst);
1168         return LB_STATUS_SUCCESS;
1169 }
1170
1171 HAPI int package_del_instance(struct pkg_info *info, struct inst_info *inst)
1172 {
1173         info->inst_list = eina_list_remove(info->inst_list, inst);
1174
1175         if (info->inst_list) {
1176                 return LB_STATUS_SUCCESS;
1177         }
1178
1179         if (info->slave) {
1180                 slave_unload_package(info->slave);
1181
1182                 slave_event_callback_del(info->slave, SLAVE_EVENT_FAULT, slave_fault_cb, info);
1183                 slave_event_callback_del(info->slave, SLAVE_EVENT_DEACTIVATE, slave_deactivated_cb, info);
1184                 slave_event_callback_del(info->slave, SLAVE_EVENT_ACTIVATE, slave_activated_cb, info);
1185
1186                 if (info->secured) {
1187                         slave_event_callback_del(info->slave, SLAVE_EVENT_PAUSE, slave_paused_cb, info);
1188                         slave_event_callback_del(info->slave, SLAVE_EVENT_RESUME, slave_resumed_cb, info);
1189
1190                         xmonitor_del_event_callback(XMONITOR_PAUSED, xmonitor_paused_cb, info);
1191                         xmonitor_del_event_callback(XMONITOR_RESUMED, xmonitor_resumed_cb, info);
1192                 }
1193
1194                 slave_unref(info->slave);
1195                 info->slave = NULL;
1196         }
1197
1198         if (info->is_uninstalled) {
1199                 package_destroy(info);
1200         }
1201
1202         return LB_STATUS_SUCCESS;
1203 }
1204
1205 HAPI Eina_List *package_instance_list(struct pkg_info *info)
1206 {
1207         return info->inst_list;
1208 }
1209
1210 static int client_created_cb(struct client_node *client, void *data)
1211 {
1212         struct pkg_info *info;
1213         Eina_List *l;
1214
1215         struct inst_info *inst;
1216         Eina_List *i_l;
1217
1218         EINA_LIST_FOREACH(s_info.pkg_list, l, info) {
1219                 if (info->fault_info) {
1220                         fault_unicast_info(client, info->lbid, info->fault_info->filename, info->fault_info->function);
1221                         continue;
1222                 }
1223
1224                 EINA_LIST_FOREACH(info->inst_list, i_l, inst) {
1225                         switch (instance_state(inst)) {
1226                         case INST_INIT:
1227                                 /* Will be send a created event after the instance gets created event */
1228                                 break;
1229                         case INST_ACTIVATED: /*!< This instance is actiavted, and used */
1230                         case INST_REQUEST_TO_REACTIVATE: /*!< This instance will be reactivated soon */
1231                         case INST_REQUEST_TO_DESTROY: /*!< This instance will be destroy soon */
1232                                 if (instance_client(inst) == client) {
1233                                         instance_unicast_created_event(inst, client);
1234                                 } else if (instance_client(inst) == NULL) {
1235                                         /*!
1236                                          * \note
1237                                          * Instances are lives in the system cluster/sub-cluster
1238                                          */
1239                                         if (client_is_subscribed(client, instance_cluster(inst), instance_category(inst))) {
1240                                                 instance_unicast_created_event(inst, client);
1241                                                 DbgPrint("(Subscribed) Created package: %s\n", info->lbid);
1242                                         }
1243                                 }
1244
1245                                 break;
1246                         default:
1247                                 DbgPrint("%s(%s) is not activated (%d)\n",
1248                                                 package_name(info), instance_id(inst), instance_state(inst));
1249                                 break;
1250                         }
1251                 }
1252         }
1253
1254         return 0;
1255 }
1256
1257 static int io_uninstall_cb(const char *pkgid, const char *lbid, int prime, void *data)
1258 {
1259         struct pkg_info *info;
1260         Eina_List *l;
1261         Eina_List *n;
1262         struct inst_info *inst;
1263
1264         DbgPrint("Package %s is uninstalled\n", lbid);
1265         info = package_find(lbid);
1266         if (!info) {
1267                 DbgPrint("%s is not yet loaded\n", lbid);
1268                 return 0;
1269         }
1270
1271         info->is_uninstalled = 1;
1272
1273         /*!
1274          * \NOTE
1275          * Don't delete an item from the inst_list.
1276          * destroy callback will use this list again.
1277          * So, Don't touch it from here.
1278          */
1279         if (info->inst_list) {
1280                 EINA_LIST_FOREACH_SAFE(info->inst_list, l, n, inst) {
1281                         instance_destroy(inst, INSTANCE_DESTROY_UNINSTALL);
1282                 }
1283         } else {
1284                 package_destroy(info);
1285         }
1286
1287         return 0;
1288 }
1289
1290 static inline void reload_package_info(struct pkg_info *info)
1291 {
1292         Eina_List *l;
1293         Eina_List *n;
1294         struct inst_info *inst;
1295         unsigned int size_type;
1296         int width;
1297         int height;
1298
1299         DbgPrint("Already exists, try to update it\n");
1300
1301         group_del_livebox(info->lbid);
1302         package_clear_fault(info);
1303
1304         /*!
1305          * \NOTE:
1306          * Nested DB I/O
1307          */
1308         io_load_package_db(info);
1309
1310         /*!
1311          * \note
1312          * Without "is_uninstalled", the package will be kept
1313          */
1314         EINA_LIST_FOREACH_SAFE(info->inst_list, l, n, inst) {
1315                 width = instance_lb_width(inst);
1316                 height = instance_lb_height(inst);
1317                 size_type = livebox_service_size_type(width, height);
1318                 if (info->lb.size_list & size_type) {
1319                         instance_reload(inst, INSTANCE_DESTROY_UPGRADE);
1320                 } else {
1321                         instance_destroy(inst, INSTANCE_DESTROY_UNINSTALL);
1322                 }
1323         }
1324 }
1325
1326 static int io_install_cb(const char *pkgid, const char *lbid, int prime, void *data)
1327 {
1328         struct pkg_info *info;
1329
1330         info = package_find(lbid);
1331         if (info) {
1332                 /*!
1333                  * Already exists. skip to create this.
1334                  */
1335                 return 0;
1336         }
1337
1338         info = package_create(pkgid, lbid);
1339         if (!info) {
1340                 ErrPrint("Failed to build an info %s\n", lbid);
1341         } else {
1342                 DbgPrint("Livebox %s is built\n", lbid);
1343         }
1344
1345         return 0;
1346 }
1347
1348 static int uninstall_cb(const char *pkgname, enum pkgmgr_status status, double value, void *data)
1349 {
1350         Eina_List *l;
1351         Eina_List *n;
1352         struct pkg_info *info;
1353
1354         if (status != PKGMGR_STATUS_END) {
1355                 return 0;
1356         }
1357
1358         EINA_LIST_FOREACH_SAFE(s_info.pkg_list, l, n, info) {
1359                 if (!strcmp(info->pkgid, pkgname)) {
1360                         io_uninstall_cb(pkgname, info->lbid, -1, NULL);
1361                 }
1362         }
1363
1364         return 0;
1365 }
1366
1367 static int update_cb(const char *pkgname, enum pkgmgr_status status, double value, void *data)
1368 {
1369         Eina_List *l;
1370         Eina_List *n;
1371         struct pkg_info *info;
1372
1373         if (status != PKGMGR_STATUS_END) {
1374                 return 0;
1375         }
1376
1377         EINA_LIST_FOREACH_SAFE(s_info.pkg_list, l, n, info) {
1378                 if (!strcmp(info->pkgid, pkgname)) {
1379                         DbgPrint("Update lbid: %s\n", info->lbid);
1380                         if (io_is_exists(info->lbid) == 1) {
1381                                 reload_package_info(info);
1382                         } else {
1383                                 io_uninstall_cb(pkgname, info->lbid, -1, NULL);
1384                         }
1385                 }
1386         }
1387
1388         (void)io_update_livebox_package(pkgname, io_install_cb, NULL);
1389         return 0;
1390 }
1391
1392 static int crawling_liveboxes(const char *pkgid, const char *lbid, int prime, void *data)
1393 {
1394         if (package_find(lbid)) {
1395                 ErrPrint("Information of %s is already built\n", lbid);
1396         } else {
1397                 struct pkg_info *info;
1398                 info = package_create(pkgid, lbid);
1399                 if (info) {
1400                         DbgPrint("[%s] information is built prime(%d)\n", lbid, prime);
1401                 }
1402         }
1403
1404         return 0;
1405 }
1406
1407 HAPI int package_init(void)
1408 {
1409         client_global_event_handler_add(CLIENT_GLOBAL_EVENT_CREATE, client_created_cb, NULL);
1410         pkgmgr_init();
1411
1412         pkgmgr_add_event_callback(PKGMGR_EVENT_INSTALL, update_cb, NULL);
1413         pkgmgr_add_event_callback(PKGMGR_EVENT_UNINSTALL, uninstall_cb, NULL);
1414         pkgmgr_add_event_callback(PKGMGR_EVENT_UPDATE, update_cb, NULL);
1415
1416         io_crawling_liveboxes(crawling_liveboxes, NULL);
1417         return 0;
1418 }
1419
1420 HAPI int package_fini(void)
1421 {
1422         Eina_List *p_l;
1423         Eina_List *p_n;
1424         Eina_List *i_l;
1425         Eina_List *i_n;
1426         struct pkg_info *info;
1427         struct inst_info *inst;
1428
1429         pkgmgr_del_event_callback(PKGMGR_EVENT_INSTALL, update_cb, NULL);
1430         pkgmgr_del_event_callback(PKGMGR_EVENT_UNINSTALL, uninstall_cb, NULL);
1431         pkgmgr_del_event_callback(PKGMGR_EVENT_UPDATE, update_cb, NULL);
1432         pkgmgr_fini();
1433         client_global_event_handler_del(CLIENT_GLOBAL_EVENT_CREATE, client_created_cb, NULL);
1434
1435         EINA_LIST_FOREACH_SAFE(s_info.pkg_list, p_l, p_n, info) {
1436                 EINA_LIST_FOREACH_SAFE(info->inst_list, i_l, i_n, inst) {
1437                         instance_state_reset(inst);
1438                         instance_destroy(inst, INSTANCE_DESTROY_TERMINATE);
1439                 }
1440
1441                 package_destroy(info);
1442         }
1443
1444         return 0;
1445 }
1446
1447 HAPI const char *package_find_by_secured_slave(struct slave_node *slave)
1448 {
1449         Eina_List *l;
1450         struct pkg_info *info;
1451
1452         if (!slave_is_secured(slave)) {
1453                 return NULL;
1454         }
1455
1456         EINA_LIST_FOREACH(s_info.pkg_list, l, info) {
1457                 if (info->slave == slave) {
1458                         return info->lbid;
1459                 }
1460         }
1461
1462         return NULL;
1463 }
1464
1465 HAPI const char * const package_name(const struct pkg_info *info)
1466 {
1467         return info->lbid;
1468 }
1469
1470 /*!
1471  * del_or_creat : 1 == create, 0 == delete
1472  */
1473 HAPI int package_alter_instances_to_client(struct client_node *client, enum alter_type alter)
1474 {
1475         struct pkg_info *info;
1476         Eina_List *l;
1477
1478         struct inst_info *inst;
1479         Eina_List *i_l;
1480
1481         EINA_LIST_FOREACH(s_info.pkg_list, l, info) {
1482                 EINA_LIST_FOREACH(info->inst_list, i_l, inst) {
1483                         if (instance_client(inst)) {
1484                                 continue;
1485                         }
1486
1487                         if (!client_is_subscribed(client, instance_cluster(inst), instance_category(inst))) {
1488                                 continue;
1489                         }
1490
1491                         switch (instance_state(inst)) {
1492                         case INST_INIT:
1493                         case INST_REQUEST_TO_ACTIVATE:
1494                                 /* Will be send a created event after the instance gets created event */
1495                                 switch (alter) {
1496                                 case ALTER_CREATE:
1497                                         if (!instance_has_client(inst, client)) {
1498                                                 instance_add_client(inst, client);
1499                                         }
1500                                         break;
1501                                 case ALTER_DESTROY:
1502                                         if (instance_has_client(inst, client)) {
1503                                                 instance_del_client(inst, client);
1504                                         }
1505                                         break;
1506                                 default:
1507                                         break;
1508                                 }
1509                                 break;
1510                         case INST_ACTIVATED: /*!< This instance is actiavted, and used */
1511                         case INST_REQUEST_TO_REACTIVATE: /*!< This instance will be reactivated soon */
1512                         case INST_REQUEST_TO_DESTROY: /*!< This instance will be destroy soon */
1513                                 /*!
1514                                  * \note
1515                                  * Instances are lives in the system cluster/sub-cluster
1516                                  */
1517                                 switch (alter) {
1518                                 case ALTER_CREATE:
1519                                         if (!instance_has_client(inst, client)) {
1520                                                 instance_unicast_created_event(inst, client);
1521                                                 instance_add_client(inst, client);
1522                                                 DbgPrint("(Subscribed) Created package: %s\n", info->lbid);
1523                                         }
1524                                         break;
1525                                 case ALTER_DESTROY:
1526                                         if (instance_has_client(inst, client)) {
1527                                                 instance_unicast_deleted_event(inst, client);
1528                                                 instance_del_client(inst, client);
1529                                         }
1530                                         break;
1531                                 default:
1532                                         break;
1533                                 }
1534
1535                                 break;
1536                         default:
1537                                 DbgPrint("%s(%s) is not activated (%d)\n",
1538                                                 package_name(info), instance_id(inst), instance_state(inst));
1539                                 break;
1540                         }
1541                 }
1542         }
1543
1544         return 0;
1545 }
1546
1547 HAPI const Eina_List *package_list(void)
1548 {
1549         return s_info.pkg_list;
1550 }
1551
1552 HAPI int const package_fault_count(struct pkg_info *info)
1553 {
1554         return info ? info->fault_count : 0;
1555 }
1556
1557 HAPI int package_is_enabled(const char *appid)
1558 {
1559         ail_appinfo_h ai;
1560         bool enabled;
1561         int ret;
1562
1563         ret = ail_get_appinfo(appid, &ai);
1564         if (ret != AIL_ERROR_OK) {
1565                 ErrPrint("Unable to get appinfo: %d\n", ret);
1566                 return 0;
1567         }
1568
1569         if (ail_appinfo_get_bool(ai, AIL_PROP_X_SLP_ENABLED_BOOL, &enabled) != AIL_ERROR_OK) {
1570                 enabled = false;
1571         }
1572
1573         ail_destroy_appinfo(ai);
1574
1575         return enabled == true;
1576 }
1577
1578 HAPI int package_faulted(struct pkg_info *pkg)
1579 {
1580         Eina_List *l;
1581         Eina_List *n;
1582         struct slave_node *slave;
1583         struct inst_info *inst;
1584
1585         slave = package_slave(pkg);
1586         if (!slave) {
1587                 ErrPrint("Package has no slave?\n");
1588                 return LB_STATUS_ERROR_FAULT;
1589         }
1590
1591         /* Emulated fault routine */
1592         // (void)package_set_fault_info(pkg, util_timestamp(), slave_name(slave), __func__);
1593         fault_broadcast_info(package_name(pkg), slave_name(slave), __func__);
1594
1595         DbgPrint("package: %s (forucely faulted %s)\n", package_name(pkg), slave_name(slave));
1596         EINA_LIST_FOREACH_SAFE(pkg->inst_list, l, n, inst) {
1597                 DbgPrint("Destroy instance %p\n", inst);
1598                 instance_destroy(inst, INSTANCE_DESTROY_FAULT);
1599         }
1600
1601         return LB_STATUS_SUCCESS;
1602 }
1603
1604 /* End of a file */