Fix the crash bug of slave.
[platform/framework/web/data-provider-slave.git] / src / lb.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 <stdlib.h> /* exit */
19 #include <errno.h>
20 #include <unistd.h> /* access */
21
22 #include <Ecore.h>
23 #include <Eina.h>
24
25 #include <dlog.h>
26 #include <provider.h>
27 #include <livebox.h>
28 #include <livebox-errno.h>
29
30 #include "critical_log.h"
31 #include "debug.h"
32 #include "conf.h"
33 #include "so_handler.h"
34 #include "lb.h"
35 #include "update_monitor.h"
36 #include "fault.h"
37 #include "util.h"
38
39 #define IS_LB_SHOWN(itm) (!(itm)->inst->item->has_livebox_script || ((itm)->inst->item->has_livebox_script && (itm)->is_lb_show))
40
41 int errno;
42
43 struct item {
44         Ecore_Timer *timer;
45         struct instance *inst;
46         int monitor_cnt;
47         Ecore_Timer *monitor;
48         int deleteme;
49         double update_interval;
50         int heavy_updating; /* Only for debugging message */
51         int is_paused; /* 1 is paused, 0 is resumed */
52         double sleep_at;
53
54         unsigned int updated_in_pause;
55
56         int is_lb_show;
57         int is_pd_show;
58         int is_lb_updated;
59 };
60
61 static struct info {
62         Eina_List *item_list;
63         struct item *update;
64         Eina_List *pending_list;
65         Ecore_Timer *pending_timer;
66         Eina_List *pd_open_pending_list;
67         Ecore_Timer *pd_open_pending_timer;
68         int paused;
69         Eina_List *pd_list;
70         int secured;
71         int pending_timer_freezed;
72 } s_info  = {
73         .item_list = NULL,
74         .update = NULL,
75         .pending_list = NULL,
76         .pending_timer = NULL,
77         .pd_open_pending_list = NULL,
78         .pd_open_pending_timer = NULL,
79         .paused = 0,
80         .pd_list = NULL,
81         .secured = 0,
82         .pending_timer_freezed = 0,
83 };
84
85 static Eina_Bool updator_cb(void *data);
86
87 static void pending_timer_freeze(void)
88 {
89         DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
90         if (s_info.pending_timer && !s_info.pending_timer_freezed) {
91                 DbgPrint("Freeze the pending timer\n");
92                 ecore_timer_freeze(s_info.pending_timer);
93         }
94
95         s_info.pending_timer_freezed++;
96 }
97
98 static void pending_timer_thaw(void)
99 {
100         DbgPrint("Freezed Count: %d\n", s_info.pending_timer_freezed);
101         if (!s_info.pending_timer_freezed)
102                 return;
103
104         s_info.pending_timer_freezed--;
105         if (s_info.pending_timer && !s_info.pending_timer_freezed) {
106                 DbgPrint("Thaw the pending timer\n");
107                 ecore_timer_thaw(s_info.pending_timer);
108         }
109 }
110
111 /*
112  * -1 : PD is opened, but not mine
113  *  0 : PD is not opened
114  *  1 : my PD is opened
115  */
116 static inline int pd_is_opened(const char *pkgname)
117 {
118         int i;
119         Eina_List *l;
120         char *tmp;
121
122         i = 0;
123         EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
124                 if (pkgname && !strcmp(pkgname, tmp))
125                         return 1;
126
127                 i++;
128         }
129
130         return i > 0 ? -1 : 0;
131 }
132
133 static Eina_Bool pd_open_pended_cmd_consumer_cb(void *data)
134 {
135         struct item *item;
136
137         item = eina_list_nth(s_info.pd_open_pending_list, 0);
138         if (!item)
139                 goto cleanout;
140
141         if (s_info.update)
142                 return ECORE_CALLBACK_RENEW;
143
144         s_info.pd_open_pending_list = eina_list_remove(s_info.pd_open_pending_list, item);
145         /*!
146          * \note
147          * To prevent from checking the is_updated function
148          */
149         (void)updator_cb(item);
150         if (s_info.pd_open_pending_list)
151                 return ECORE_CALLBACK_RENEW;
152
153 cleanout:
154         s_info.pd_open_pending_timer = NULL;
155         return ECORE_CALLBACK_CANCEL;
156 }
157
158 static Eina_Bool pended_cmd_consumer_cb(void *data)
159 {
160         struct item *item;
161
162         item = eina_list_nth(s_info.pending_list, 0);
163         if (!item)
164                 goto cleanout;
165
166         if (s_info.update || pd_is_opened(item->inst->item->pkgname) < 0)
167                 return ECORE_CALLBACK_RENEW;
168
169         s_info.pending_list = eina_list_remove(s_info.pending_list, item);
170         /*!
171          * \note
172          * To prevent from checking the is_updated function
173          */
174         (void)updator_cb(item);
175         if (s_info.pending_list)
176                 return ECORE_CALLBACK_RENEW;
177
178 cleanout:
179         s_info.pending_timer = NULL;
180         s_info.pending_timer_freezed = 0;
181         return ECORE_CALLBACK_CANCEL;
182 }
183
184 static inline __attribute__((always_inline)) int activate_pending_consumer(void)
185 {
186         if (s_info.pending_timer)
187                 return 0;
188
189         s_info.pending_timer = ecore_timer_add(0.000001f, pended_cmd_consumer_cb, NULL);
190         if (!s_info.pending_timer) {
191                 ErrPrint("Failed to add a new pended command consumer\n");
192                 return LB_STATUS_ERROR_FAULT;
193         }
194
195         /*!
196          * Do not increase the freezed counter.
197          * Just freeze the timer.
198          */
199         if (s_info.pending_timer_freezed)
200                 ecore_timer_freeze(s_info.pending_timer);
201
202         return 0;
203 }
204
205 static inline void deactivate_pending_consumer(void)
206 {
207         if (!s_info.pending_timer)
208                 return;
209
210         ecore_timer_del(s_info.pending_timer);
211         s_info.pending_timer = NULL;
212         s_info.pending_timer_freezed = 0;
213 }
214
215 static inline void deactivate_pd_open_pending_consumer(void)
216 {
217         if (!s_info.pd_open_pending_timer)
218                 return;
219
220         ecore_timer_del(s_info.pd_open_pending_timer);
221         s_info.pd_open_pending_timer = NULL;
222 }
223
224 static inline int __attribute__((always_inline)) activate_pd_open_pending_consumer(void)
225 {
226         if (s_info.pd_open_pending_timer)
227                 return 0;
228
229         s_info.pd_open_pending_timer = ecore_timer_add(0.000001f, pd_open_pended_cmd_consumer_cb, NULL);
230         if (!s_info.pd_open_pending_timer) {
231                 ErrPrint("Failed to add a new pended command consumer\n");
232                 return LB_STATUS_ERROR_FAULT;
233         }
234
235         return 0;
236 }
237
238 static inline void migrate_to_pd_open_pending_list(const char *pkgname)
239 {
240         Eina_List *l;
241         Eina_List *n;
242         struct item *item;
243         int cnt = 0;
244
245         EINA_LIST_FOREACH_SAFE(s_info.pending_list, l, n, item) {
246                 if (strcmp(pkgname, item->inst->item->pkgname))
247                         continue;
248
249                 s_info.pending_list = eina_list_remove(s_info.pending_list, item);
250                 s_info.pd_open_pending_list = eina_list_append(s_info.pd_open_pending_list, item);
251                 cnt++;
252         }
253
254         if (s_info.pd_open_pending_list)
255                 activate_pd_open_pending_consumer();
256
257         if (!s_info.pending_list)
258                 deactivate_pending_consumer();
259 }
260
261 static inline void migrate_to_pending_list(const char *pkgname)
262 {
263         Eina_List *l;
264         Eina_List *n;
265         struct item *item;
266         int cnt = 0;
267
268         EINA_LIST_FOREACH_SAFE(s_info.pd_open_pending_list, l, n, item) {
269                 if (strcmp(pkgname, item->inst->item->pkgname))
270                         continue;
271
272                 s_info.pd_open_pending_list = eina_list_remove(s_info.pd_open_pending_list, item);
273                 s_info.pending_list = eina_list_append(s_info.pending_list, item);
274                 cnt++;
275         }
276
277         if (s_info.pending_list)
278                 activate_pending_consumer();
279
280         if (!s_info.pd_open_pending_list)
281                 deactivate_pd_open_pending_consumer();
282 }
283
284 static inline int is_pended_item(struct item *item)
285 {
286         struct item *in_item;
287         if (pd_is_opened(item->inst->item->pkgname) == 1) {
288                 in_item = eina_list_data_find(s_info.pd_open_pending_list, item);
289         } else {
290                 in_item = eina_list_data_find(s_info.pending_list, item);
291         }
292
293         return (in_item == item);
294 }
295
296 static int append_pending_list(struct item *item)
297 {
298         if (pd_is_opened(item->inst->item->pkgname) == 1) {
299                 if (eina_list_data_find(s_info.pd_open_pending_list, item) == item) {
300                         DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
301                         return LB_STATUS_ERROR_EXIST;
302                 }
303
304                 if (activate_pd_open_pending_consumer() < 0) {
305                         ErrPrint("Failed to activate PD open pending consumer\n");
306                         return LB_STATUS_ERROR_FAULT;
307                 }
308
309                 s_info.pd_open_pending_list = eina_list_append(s_info.pd_open_pending_list, item);
310         } else {
311                 if (eina_list_data_find(s_info.pending_list, item) == item) {
312                         DbgPrint("Already pended - %s\n", item->inst->item->pkgname);
313                         return LB_STATUS_ERROR_EXIST;
314                 }
315
316                 if (activate_pending_consumer() < 0)
317                         return LB_STATUS_ERROR_FAULT;
318
319                 s_info.pending_list = eina_list_append(s_info.pending_list, item);
320         }
321         return 0;
322 }
323
324 static inline void timer_thaw(struct item *item)
325 {
326         double pending;
327         double period;
328         double delay;
329         double sleep_time;
330
331         if (!item->timer)
332                 return;
333
334         ecore_timer_thaw(item->timer);
335         period = ecore_timer_interval_get(item->timer);
336         pending = ecore_timer_pending_get(item->timer);
337         delay = util_time_delay_for_compensation(period) - pending;
338         ecore_timer_delay(item->timer, delay);
339
340         if (item->sleep_at == 0.0f)
341                 return;
342
343         sleep_time = util_timestamp() - item->sleep_at;
344         if (sleep_time > pending)
345                 (void)updator_cb(item);
346
347         item->sleep_at = 0.0f;
348 }
349
350 static inline void timer_freeze(struct item *item)
351 {
352         struct timeval tv;
353
354         if (!item->timer)
355                 return;
356
357         ecore_timer_freeze(item->timer);
358
359         if (ecore_timer_interval_get(item->timer) <= 1.0f)
360                 return;
361
362         if (gettimeofday(&tv, NULL) < 0) {
363                 ErrPrint("gettimeofday: %s\n", strerror(errno));
364                 tv.tv_sec = 0;
365                 tv.tv_usec = 0;
366         }
367
368         item->sleep_at = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0f;
369 }
370
371 static inline void update_monitor_cnt(struct item *item)
372 {
373         double now;
374         double interval;
375
376         now = util_timestamp();
377         interval = now - item->update_interval;
378
379         /*!
380          * \note
381          * If the content update is processed in too short time,
382          * don't increase the monitor counter, instead of it
383          * set the heavy updating flag.
384          * And handling this heavy updating from the
385          * file update callback.
386          */
387         if (interval >= MINIMUM_UPDATE_INTERVAL) {
388                 if (s_info.update == item) {
389                         /*!
390                          * \note
391                          * If already in updating mode,
392                          * reset the monitor_cnt to 1,
393                          * all updated event will be merged into A inotify event
394                          */
395                         DbgPrint("While waiting updated event, content is updated [%s]\n", item->inst->id);
396                         item->monitor_cnt = 1;
397                 } else {
398                         item->monitor_cnt++;
399                 }
400         } else {
401                 item->heavy_updating = 1;
402         }
403
404         item->update_interval = now;
405 }
406
407 static inline Eina_List *find_item(struct instance *inst)
408 {
409         Eina_List *l;
410         struct item *item;
411         
412         EINA_LIST_FOREACH(s_info.item_list, l, item) {
413                 if (item->inst == inst)
414                         return l;
415         }
416
417         return NULL;
418 }
419
420 static inline int output_handler(struct item *item)
421 {
422         int invalid = 0;
423
424         item->monitor_cnt--;
425         if (item->monitor_cnt < 0 || item->heavy_updating) {
426                 if (!item->heavy_updating) {
427                         WarnPrint("%s has invalid monitor_cnt\n", item->inst->id);
428                         invalid = 1;
429                 } else {
430                         item->heavy_updating = 0;       /* Reset flag */
431                 }
432
433                 item->monitor_cnt = 0;
434         }
435
436         if (item->monitor_cnt == 0) {
437                 if (!invalid)
438                         fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
439
440                 if (item->monitor) {
441                         ecore_timer_del(item->monitor);
442                         item->monitor = NULL;
443                 }
444
445                 if (s_info.update == item)
446                         s_info.update = NULL;
447
448                 if (item->deleteme) {
449                         provider_send_deleted(item->inst->item->pkgname, item->inst->id);
450                         (void)so_destroy(item->inst);
451                         free(item);
452                         return EXIT_FAILURE;
453                 }
454         }
455
456         return EXIT_SUCCESS;
457 }
458
459 static int desc_updated_cb(const char *filename, void *data, int over)
460 {
461         struct item *item;
462
463         if (over)
464                 WarnPrint("Event Q overflow\n");
465
466         item = data;
467
468         DbgPrint("DESC %s is updated\n", filename);
469         if (item->is_pd_show) {
470                 provider_send_desc_updated(item->inst->item->pkgname, item->inst->id, filename);
471         } else {
472                 ErrPrint("But PD is not opened, Ignore this update (%s)\n", item->inst->id);
473         }
474         return EXIT_SUCCESS;
475 }
476
477 static int file_updated_cb(const char *filename, void *data, int over)
478 {
479         struct item *item;
480         int w;
481         int h;
482         double priority;
483         char *content = NULL;
484         char *title = NULL;
485         int ret;
486
487         if (over)
488                 WarnPrint("Event Q overflow\n");
489
490         item = data;
491
492         ret = util_get_filesize(filename);
493         if (ret <= 0) {
494                 ErrPrint("Content is updated. but invalid. ret = %d (Update is ignored)\n", ret);
495                 return EXIT_SUCCESS; /*!< To keep the callback */
496         }
497
498         ret = so_get_output_info(item->inst, &w, &h, &priority, &content, &title);
499         if (ret < 0) {
500                 ErrPrint("livebox_get_info returns %d\n", ret);
501                 return EXIT_SUCCESS; /*!< To keep the callback */
502         }
503
504         if (IS_LB_SHOWN(item)) {
505                 provider_send_updated(item->inst->item->pkgname, item->inst->id,
506                                         item->inst->w, item->inst->h, item->inst->priority,
507                                         content, title);
508         } else {
509                 item->is_lb_updated++;
510         }
511
512         return output_handler(item);
513 }
514
515 static void reset_lb_updated_flag(struct item *item)
516 {
517         if (!item->is_lb_updated)
518                 return;
519
520         DbgPrint("[%s] Updated %d times, (content: %s), (title: %s)\n",
521                         item->inst->id, item->is_lb_updated,
522                         item->inst->content, item->inst->title);
523
524         provider_send_updated(item->inst->item->pkgname, item->inst->id,
525                         item->inst->w, item->inst->h, item->inst->priority,
526                         item->inst->content, item->inst->title);
527
528         item->is_lb_updated = 0;
529 }
530
531 static inline int clear_from_pd_open_pending_list(struct item *item)
532 {
533         Eina_List *l;
534         struct item *tmp;
535
536         EINA_LIST_FOREACH(s_info.pd_open_pending_list, l, tmp) {
537                 if (tmp != item)
538                         continue;
539
540                 s_info.pd_open_pending_list = eina_list_remove_list(s_info.pd_open_pending_list, l);
541                 if (!s_info.pd_open_pending_list)
542                         deactivate_pd_open_pending_consumer();
543                 return LB_STATUS_SUCCESS;
544         }
545
546         return LB_STATUS_ERROR_NOT_EXIST;
547 }
548
549 static inline int clear_from_pending_list(struct item *item)
550 {
551         Eina_List *l;
552         struct item *tmp;
553
554         EINA_LIST_FOREACH(s_info.pending_list, l, tmp) {
555                 if (tmp != item)
556                         continue;
557
558                 s_info.pending_list = eina_list_remove_list(s_info.pending_list, l);
559                 if (!s_info.pending_list)
560                         deactivate_pending_consumer();
561                 return LB_STATUS_SUCCESS;
562         }
563
564         return LB_STATUS_ERROR_NOT_EXIST;
565 }
566
567 static Eina_Bool update_timeout_cb(void *data)
568 {
569         struct item *item;
570
571         item = data;
572
573         ErrPrint("UPDATE TIMEOUT ========> %s - %s\n", item->inst->item->pkgname, item->inst->id);
574
575         if (s_info.update != item)
576                 ErrPrint("Updating item is not matched\n");
577
578         fault_unmark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM);
579         fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,timeout", NO_ALARM, DEFAULT_LIFE_TIMER);
580         s_info.update = NULL;
581
582         exit(ETIME);
583         return ECORE_CALLBACK_CANCEL;
584 }
585
586 static Eina_Bool updator_cb(void *data)
587 {
588         struct item *item;
589         int ret;
590
591         item = data;
592
593         if (item->monitor) {/*!< If this item is already in update process */
594                 return ECORE_CALLBACK_RENEW;
595         }
596
597         if (!IS_LB_SHOWN(item)) {
598                 DbgPrint("%s is not shown yet. make delay for updates\n", item->inst->item->pkgname);
599                 (void)append_pending_list(item);
600                 return ECORE_CALLBACK_RENEW;
601         }
602
603         if (item->is_paused) {
604                 item->updated_in_pause++;
605                 DbgPrint("%s is paused[%d]. make delay for updating\n", item->inst->item->pkgname, item->updated_in_pause);
606                 return ECORE_CALLBACK_RENEW;
607         }
608
609         item->updated_in_pause = 0;
610
611         ret = so_is_updated(item->inst);
612         if (ret <= 0) {
613                 if (so_need_to_destroy(item->inst) == NEED_TO_DESTROY) {
614                         provider_send_deleted(item->inst->item->pkgname, item->inst->id);
615                         lb_destroy(item->inst->item->pkgname, item->inst->id);
616                         return ECORE_CALLBACK_CANCEL;
617                 }
618
619                 reset_lb_updated_flag(item);
620                 return ECORE_CALLBACK_RENEW;
621         }
622
623         if (s_info.update || pd_is_opened(item->inst->item->pkgname) < 0) {
624                 DbgPrint("%s is busy\n", s_info.update ? s_info.update->inst->id : item->inst->id);
625                 (void)append_pending_list(item);
626                 return ECORE_CALLBACK_RENEW;
627         }
628
629         item->monitor = ecore_timer_add(item->inst->item->timeout, update_timeout_cb, item);
630         if (!item->monitor) {
631                 ErrPrint("Failed to add update monitor %s(%s):%d\n",
632                                         item->inst->item->pkgname, item->inst->id, item->inst->item->timeout);
633                 return ECORE_CALLBACK_RENEW;
634         }
635
636         ret = so_update(item->inst);
637         if (ret < 0) {
638                 ecore_timer_del(item->monitor);
639                 item->monitor = NULL;
640                 reset_lb_updated_flag(item);
641                 return ECORE_CALLBACK_RENEW;
642         }
643
644         /*!
645          * \note
646          * Counter of the event monitor is only used for asynchronous content updating,
647          * So reset it to 1 from here because the async updating is started now,
648          * even if it is accumulated by other event function before this.
649          */
650         item->monitor_cnt = 1;
651
652         /*!
653          * \note
654          * While waiting the Callback function call,
655          * Add this for finding the crash
656          */
657         fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM, DEFAULT_LIFE_TIMER);
658
659         if (ret & NEED_TO_SCHEDULE)
660                 (void)append_pending_list(item);
661
662         if (ret & OUTPUT_UPDATED) {
663                 /*!
664                  * \NOTE 
665                  * In this case, there is potential issue
666                  * 1. User added update CALLBACK -> Inotify event (Only once)
667                  *    > We have to detect this case. Is it possible to be a user callback called faster than inotify event handler?
668                  * 2. Inotify event -> User added update CALLBACK -> Inotify event
669                  *    > Okay. What we want is this.
670                  */
671                 update_monitor_cnt(item);
672         }
673
674         /*
675          * \NOTE
676          * This should be updated after "update_monitor_cnt" function call,
677          * because the update_monitor_cnt function will see the s_info.update variable,
678          */
679         s_info.update = item;
680
681         return ECORE_CALLBACK_RENEW;
682 }
683
684 static inline void update_monitor_del(const char *id, struct item *item)
685 {
686         char *tmp;
687         int len;
688
689         update_monitor_del_update_cb(util_uri_to_path(id), file_updated_cb);
690
691         len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
692         tmp = malloc(len);
693         if (!tmp) {
694                 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
695                 return;
696         }
697
698         snprintf(tmp, len, "%s.desc", util_uri_to_path(id));
699         update_monitor_del_update_cb(tmp, desc_updated_cb);
700         free(tmp);
701 }
702
703 static inline int add_desc_update_monitor(const char *id, struct item *item)
704 {
705         char *filename;
706         int len;
707
708         len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
709         filename = malloc(len);
710         if (!filename) {
711                 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
712                 return LB_STATUS_ERROR_MEMORY;
713         }
714
715         snprintf(filename, len, "%s.desc", util_uri_to_path(id));
716         return update_monitor_add_update_cb(filename, desc_updated_cb, item);
717 }
718
719 static inline int add_file_update_monitor(const char *id, struct item *item)
720 {
721         char *filename;
722
723         filename = strdup(util_uri_to_path(id));
724         if (!filename) {
725                 ErrPrint("Heap: %s (%s)\n", strerror(errno), id);
726                 return LB_STATUS_ERROR_MEMORY;
727         }
728
729         return update_monitor_add_update_cb(filename, file_updated_cb, item);
730 }
731
732 static inline int update_monitor_add(const char *id, struct item *item)
733 {
734         /*!
735          * \NOTE
736          * item->inst is not available yet.
737          */
738         add_file_update_monitor(id, item);
739         add_desc_update_monitor(id, item);
740         return LB_STATUS_SUCCESS;
741 }
742
743 HAPI int lb_init(void)
744 {
745         return LB_STATUS_SUCCESS;
746 }
747
748 HAPI int lb_fini(void)
749 {
750         Eina_List *l;
751         Eina_List *n;
752         struct item *item;
753
754         deactivate_pending_consumer();
755         deactivate_pd_open_pending_consumer();
756
757         EINA_LIST_FREE(s_info.pd_open_pending_list, item);
758         EINA_LIST_FREE(s_info.pending_list, item);
759
760         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
761                 provider_send_deleted(item->inst->item->pkgname, item->inst->id);
762                 lb_destroy(item->inst->item->pkgname, item->inst->id);
763         }
764
765         return LB_STATUS_SUCCESS;
766 }
767
768 /*!
769  * \note
770  * Exported API for each liveboxes.
771  */
772 const char *livebox_find_pkgname(const char *filename)
773 {
774         Eina_List *l;
775         struct item *item;
776
777         EINA_LIST_FOREACH(s_info.item_list, l, item) {
778                 if (!strcmp(item->inst->id, filename))
779                         return item->inst->item->pkgname;
780         }
781
782         return NULL;
783 }
784
785 int livebox_request_update_by_id(const char *filename)
786 {
787         Eina_List *l;
788         struct item *item;
789
790         if (so_current_op() != LIVEBOX_OP_UNKNOWN) {
791                 ErrPrint("Current operation: %d\n", so_current_op());
792                 return LB_STATUS_ERROR_INVALID;
793         }
794
795         EINA_LIST_FOREACH(s_info.item_list, l, item) {
796                 if (!strcmp(item->inst->id, filename)) {
797                         return append_pending_list(item);
798                 }
799         }
800
801         return LB_STATUS_ERROR_NOT_EXIST;
802 }
803
804 int livebox_trigger_update_monitor(const char *filename, int is_pd)
805 {
806         char *fname;
807         int ret;
808
809         if (so_current_op() != LIVEBOX_OP_UNKNOWN) {
810                 ErrPrint("Current operation: %d\n", so_current_op());
811                 return LB_STATUS_ERROR_INVALID;
812         }
813
814         if (is_pd) {
815                 int len;
816                 len = strlen(filename) + strlen(".desc");
817
818                 fname = malloc(len + 1);
819                 if (!fname) {
820                         ErrPrint("Heap: %s\n", strerror(errno));
821                         return LB_STATUS_ERROR_MEMORY;
822                 }
823
824                 snprintf(fname, len, "%s.desc", filename);
825         } else {
826                 fname = strdup(filename);
827                 if (!fname) {
828                         ErrPrint("Heap: %s\n", strerror(errno));
829                         return LB_STATUS_ERROR_MEMORY;
830                 }
831         }
832
833         if (access(fname, R_OK | W_OK) != 0) {
834                 ErrPrint("access: %s (%s)\n", fname, strerror(errno));
835                 ret = LB_STATUS_ERROR_IO;
836         } else {
837                 ret = update_monitor_trigger_update_cb(fname, 0);
838         }
839
840         free(fname);
841         return ret;
842 }
843
844 HAPI int lb_open_pd(const char *pkgname)
845 {
846         Eina_List *l;
847         char *tmp;
848
849         EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
850                 if (!strcmp(pkgname, tmp))
851                         return 0;
852         }
853
854         tmp = strdup(pkgname);
855         if (!tmp) {
856                 ErrPrint("Heap: %s\n", strerror(errno));
857                 return LB_STATUS_ERROR_MEMORY;
858         }
859
860         if (!s_info.pd_list)
861                 pending_timer_freeze();
862
863         s_info.pd_list = eina_list_append(s_info.pd_list, tmp);
864
865         /*!
866          * Find all instances from the pending list.
867          * Move them to pd_open_pending_timer
868          */
869         migrate_to_pd_open_pending_list(pkgname);
870         return LB_STATUS_SUCCESS;
871 }
872
873 HAPI int lb_close_pd(const char *pkgname)
874 {
875         Eina_List *l;
876         Eina_List *n;
877         char *tmp;
878
879         EINA_LIST_FOREACH_SAFE(s_info.pd_list, l, n, tmp) {
880                 if (strcmp(tmp, pkgname))
881                         continue;
882
883                 s_info.pd_list = eina_list_remove(s_info.pd_list, tmp);
884                 free(tmp);
885
886                 if (!s_info.pd_list)
887                         pending_timer_thaw();
888
889                 /*!
890                  * Move all items in pd_open_pending_list
891                  * to pending_list.
892                  */
893                 migrate_to_pending_list(pkgname);
894                 return LB_STATUS_SUCCESS;
895         }
896
897         return LB_STATUS_ERROR_NOT_EXIST;
898 }
899
900 HAPI int lb_create(const char *pkgname, const char *id, const char *content_info, int timeout, int has_livebox_script, double period, const char *cluster, const char *category, int *w, int *h, double *priority, int skip_need_to_create, const char *abi, char **out_content, char **out_title)
901 {
902         struct instance *inst;
903         struct item *item;
904         int ret;
905         int create_ret;
906         int need_to_create;
907
908         need_to_create = 0;
909         *out_content = NULL;
910         *out_title = NULL;
911
912         inst = so_find_instance(pkgname, id);
913         if (inst) {
914                 DbgPrint("Instance is already exists [%s - %s] content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
915                 return LB_STATUS_SUCCESS;
916         }
917
918         if (!skip_need_to_create) {
919                 ret = so_create_needed(pkgname, cluster, category, abi);
920                 if (ret != NEED_TO_CREATE)
921                         return LB_STATUS_ERROR_PERMISSION;
922
923                 need_to_create = 1;
924         }
925
926         item = calloc(1, sizeof(*item));
927         if (!item) {
928                 ErrPrint("Heap: %s (%s - %s, content[%s], cluster[%s], category[%s], abi[%s])\n", strerror(errno), pkgname, id, content_info, cluster, category, abi);
929                 return LB_STATUS_ERROR_MEMORY;
930         }
931
932         ret = update_monitor_add(id, item);
933         if (ret < 0) {
934                 free(item);
935                 return ret;
936         }
937
938         create_ret = so_create(pkgname, id, content_info, timeout, has_livebox_script, cluster, category, abi, &inst);
939         if (create_ret < 0) {
940                 update_monitor_del(id,  item);
941                 free(item);
942
943                 *w = 0;
944                 *h = 0;
945                 *priority = 0.0f;
946                 return create_ret;
947         }
948
949         item->inst = inst;
950
951         if (period > 0.0f && !s_info.secured) {
952                 item->timer = util_timer_add(period, updator_cb, item);
953                 if (!item->timer) {
954                         ErrPrint("Failed to add timer (%s - %s, content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
955                         update_monitor_del(id, item);
956                         (void)so_destroy(inst);
957                         free(item);
958                         return LB_STATUS_ERROR_FAULT;
959                 }
960
961                 if (s_info.paused)
962                         timer_freeze(item);
963         } else {
964                 DbgPrint("Local update timer is disabled: %lf (%d)\n", period, s_info.secured);
965                 item->timer = NULL;
966         }
967
968         s_info.item_list = eina_list_append(s_info.item_list, item);
969
970         if (create_ret & NEED_TO_SCHEDULE) {
971                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
972                 (void)append_pending_list(item);
973         }
974
975         if (create_ret & OUTPUT_UPDATED) {
976                 update_monitor_cnt(item);
977                 /*!
978                  * \note
979                  * To send a output info, get the info forcely.
980                  * but the output file monitor will do this again
981                  *
982                  * This function will set the tmp_content and tmp_title
983                  * even if it has no updates on the content, title,
984                  * it will set them to NULL.
985                  */
986                 if (so_get_output_info(inst, w, h, priority, out_content, out_title) == LB_STATUS_SUCCESS) {
987                         if (*out_content) {
988                                 char *tmp;
989
990                                 tmp = strdup(*out_content);
991                                 if (!tmp)
992                                         ErrPrint("Memory: %s\n", strerror(errno));
993
994                                 *out_content = tmp;
995                         }
996
997                         if (*out_title) {
998                                 char *tmp;
999
1000                                 tmp = strdup(*out_title);
1001                                 if (!tmp)
1002                                         ErrPrint("Memory: %s\n", strerror(errno));
1003
1004                                 *out_title = tmp;
1005                         }
1006                 }
1007         }
1008
1009         *w = inst->w;
1010         *h = inst->h;
1011         *priority = inst->priority;
1012         return need_to_create;
1013 }
1014
1015 HAPI int lb_destroy(const char *pkgname, const char *id)
1016 {
1017         Eina_List *l;
1018         struct instance *inst;
1019         struct item *item;
1020
1021         inst = so_find_instance(pkgname, id);
1022         if (!inst) {
1023                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1024                 return LB_STATUS_ERROR_INVALID;
1025         }
1026
1027         l = find_item(inst);
1028         if (!l) {
1029                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1030                 return LB_STATUS_ERROR_NOT_EXIST;
1031         }
1032
1033         item = eina_list_data_get(l);
1034         s_info.item_list = eina_list_remove_list(s_info.item_list, l);
1035
1036         if (s_info.update == item)
1037                 s_info.update = NULL;
1038
1039         if (item->timer) {
1040                 clear_from_pd_open_pending_list(item);
1041                 clear_from_pending_list(item);
1042                 ecore_timer_del(item->timer);
1043                 item->timer = NULL;
1044
1045                 if (item->monitor)
1046                         item->deleteme = 1;
1047                 else
1048                         update_monitor_del(id, item);
1049         }
1050
1051         if (!item->monitor) {
1052                 free(item);
1053                 (void)so_destroy(inst);
1054         }
1055
1056         return LB_STATUS_SUCCESS;
1057 }
1058
1059 HAPI int lb_resize(const char *pkgname, const char *id, int w, int h)
1060 {
1061         Eina_List *l;
1062         struct instance *inst;
1063         struct item *item;
1064         int ret;
1065
1066         inst = so_find_instance(pkgname, id);
1067         if (!inst) {
1068                 ErrPrint("Instance %s - %s is not created (%dx%d)\n", pkgname, id, w, h);
1069                 return LB_STATUS_ERROR_INVALID;
1070         }
1071
1072         l = find_item(inst);
1073         if (!l) {
1074                 ErrPrint("Instance is not found (%s - %s, %dx%d)\n", pkgname, id, w, h);
1075                 return LB_STATUS_ERROR_NOT_EXIST;
1076         }
1077
1078         item = eina_list_data_get(l);
1079
1080         ret = so_resize(inst, w, h);
1081         if (ret < 0)
1082                 return ret;
1083
1084         if (ret & NEED_TO_SCHEDULE) {
1085                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1086                 (void)append_pending_list(item);
1087         }
1088
1089         if (ret & OUTPUT_UPDATED)
1090                 update_monitor_cnt(item);
1091
1092         return LB_STATUS_SUCCESS;
1093 }
1094
1095 HAPI char *lb_pinup(const char *pkgname, const char *id, int pinup)
1096 {
1097         struct instance *inst;
1098         char *ret;
1099
1100         inst = so_find_instance(pkgname, id);
1101         if (!inst) {
1102                 ErrPrint("Instance %s - %s is not found (pinup[%d])\n", pkgname, id, pinup);
1103                 return NULL;
1104         }
1105
1106         ret = so_pinup(inst, pinup);
1107         return ret;
1108 }
1109
1110 HAPI int lb_set_period(const char *pkgname, const char *id, double period)
1111 {
1112         Eina_List *l;
1113         struct instance *inst;
1114         struct item *item;
1115
1116         inst = so_find_instance(pkgname, id);
1117         if (!inst) {
1118                 ErrPrint("Instance %s - %s is not found (period[%lf])\n", pkgname, id, period);
1119                 return LB_STATUS_ERROR_INVALID;
1120         }
1121
1122         l = find_item(inst);
1123         if (!l) {
1124                 ErrPrint("Instance is not found (%s - %s, period[%lf])\n", pkgname, id, period);
1125                 return LB_STATUS_ERROR_NOT_EXIST;
1126         }
1127
1128         item = eina_list_data_get(l);
1129
1130         if (period <= 0.0f) {
1131                 if (item->timer) {
1132                         ecore_timer_del(item->timer);
1133                         item->timer = NULL;
1134                 }
1135         } else {
1136                 if (item->timer) {
1137                         util_timer_interval_set(item->timer, period);
1138                 } else if (!s_info.secured) {
1139                         item->timer = util_timer_add(period, updator_cb, item);
1140                         if (!item->timer) {
1141                                 ErrPrint("Failed to add timer (%s - %s)\n", pkgname, id);
1142                                 return LB_STATUS_ERROR_FAULT;
1143                         }
1144
1145                         if (s_info.paused)
1146                                 timer_freeze(item);
1147                 }
1148         }
1149
1150         return LB_STATUS_SUCCESS;
1151 }
1152
1153 HAPI int lb_clicked(const char *pkgname, const char *id, const char *event, double timestamp, double x, double y)
1154 {
1155         Eina_List *l;
1156         struct instance *inst;
1157         struct item *item;
1158         int ret;
1159
1160         inst = so_find_instance(pkgname, id);
1161         if (!inst) {
1162                 ErrPrint("Instance %s - %s is not exists (event[%s])\n", pkgname, id, event);
1163                 return LB_STATUS_ERROR_INVALID;
1164         }
1165
1166         l = find_item(inst);
1167         if (!l) {
1168                 ErrPrint("Instance is not found (%s - %s, event[%s])\n", pkgname, id, event);
1169                 return LB_STATUS_ERROR_NOT_EXIST;
1170         }
1171
1172         item = eina_list_data_get(l);
1173
1174         ret = so_clicked(inst, event, timestamp, x, y);
1175         if (ret < 0)
1176                 return ret;
1177
1178         if (ret & NEED_TO_SCHEDULE) {
1179                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1180                 (void)append_pending_list(item);
1181         }
1182
1183         if (ret & OUTPUT_UPDATED)
1184                 update_monitor_cnt(item);
1185
1186         return LB_STATUS_SUCCESS;
1187 }
1188
1189 HAPI int lb_script_event(const char *pkgname, const char *id, const char *emission, const char *source, struct event_info *event_info)
1190 {
1191         Eina_List *l;
1192         struct instance *inst;
1193         struct item *item;
1194         int ret;
1195
1196         inst = so_find_instance(pkgname, id);
1197         if (!inst) {
1198                 ErrPrint("Instance %s - %s is not exists (emission[%s], source[%s])\n", pkgname, id, emission, source);
1199                 return LB_STATUS_ERROR_INVALID;
1200         }
1201
1202         l = find_item(inst);
1203         if (!l) {
1204                 ErrPrint("Instance is not found (%s - %s, emissino[%s], source[%s])\n", pkgname, id, emission, source);
1205                 return LB_STATUS_ERROR_NOT_EXIST;
1206         }
1207
1208         item = eina_list_data_get(l);
1209
1210         if (emission && source && !strcmp(source, id)) {
1211                 if (item->inst->item->has_livebox_script) {
1212                         if (!strcmp(emission, "lb,show")) {
1213                                 item->is_lb_show = 1;
1214
1215                                 if (item->is_lb_updated && !is_pended_item(item))
1216                                         reset_lb_updated_flag(item);
1217
1218                                 source = util_uri_to_path(source);
1219                         } else if (!strcmp(emission, "lb,hide")) {
1220                                 DbgPrint("Livebox(%s) script is hide now\n", id);
1221                                 item->is_lb_show = 0;
1222
1223                                 source = util_uri_to_path(source);
1224                         }
1225                 }
1226
1227                 if (!strcmp(emission, "pd,show")) {
1228                         item->is_pd_show = 1;
1229                         source = util_uri_to_path(source);
1230                 } else if (!strcmp(emission, "pd,hide")) {
1231                         item->is_pd_show = 0;
1232                         source = util_uri_to_path(source);
1233                 }
1234         }
1235
1236         ret = so_script_event(inst, emission, source, event_info);
1237         if (ret < 0)
1238                 return ret;
1239
1240         if (ret & NEED_TO_SCHEDULE) {
1241                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1242                 (void)append_pending_list(item);
1243         }
1244
1245         if (ret & OUTPUT_UPDATED)
1246                 update_monitor_cnt(item);
1247
1248         return LB_STATUS_SUCCESS;
1249 }
1250
1251 HAPI int lb_is_pinned_up(const char *pkgname, const char *id)
1252 {
1253         Eina_List *l;
1254         struct instance *inst;
1255         struct item *item;
1256
1257         inst = so_find_instance(pkgname, id);
1258         if (!inst) {
1259                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1260                 return LB_STATUS_ERROR_INVALID;
1261         }
1262
1263         l = find_item(inst);
1264         if (!l) {
1265                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1266                 return LB_STATUS_ERROR_NOT_EXIST;
1267         }
1268
1269         item = eina_list_data_get(l);
1270         if (!item) {
1271                 ErrPrint("Invalid item(%s - %s)\n", pkgname, id);
1272                 return LB_STATUS_ERROR_FAULT;
1273         }
1274         /*!
1275          * NOTE:
1276          * item is not used.
1277          * Maybe this is not neccessary for this operation
1278          */
1279         return so_is_pinned_up(inst);
1280 }
1281
1282 HAPI int lb_change_group(const char *pkgname, const char *id, const char *cluster, const char *category)
1283 {
1284         Eina_List *l;
1285         struct instance *inst;
1286         struct item *item;
1287         int ret;
1288
1289         inst = so_find_instance(pkgname, id);
1290         if (!inst) {
1291                 ErrPrint("Instance %s - %s is not created (cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1292                 return LB_STATUS_ERROR_INVALID;
1293         }
1294
1295         l = find_item(inst);
1296         if (!l) {
1297                 ErrPrint("Instance is not found(%s - %s, cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1298                 return LB_STATUS_ERROR_NOT_EXIST;
1299         }
1300
1301         item = eina_list_data_get(l);
1302
1303         ret = so_change_group(inst, cluster, category);
1304         if (ret < 0)
1305                 return ret;
1306
1307         if (ret & NEED_TO_SCHEDULE) {
1308                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1309                 (void)append_pending_list(item);
1310         }
1311
1312         if (ret & OUTPUT_UPDATED)
1313                 update_monitor_cnt(item);
1314
1315         return LB_STATUS_SUCCESS;
1316 }
1317
1318 static inline int lb_sys_event(struct instance *inst, struct item *item, int event)
1319 {
1320         int ret;
1321
1322         ret = so_sys_event(inst, event);
1323         if (ret < 0)
1324                 return ret;
1325
1326         if (ret & NEED_TO_SCHEDULE)
1327                 (void)append_pending_list(item);
1328
1329         if (ret & OUTPUT_UPDATED)
1330                 update_monitor_cnt(item);
1331
1332         return LB_STATUS_SUCCESS;
1333 }
1334
1335 HAPI int lb_system_event(const char *pkgname, const char *id, int event)
1336 {
1337         Eina_List *l;
1338         struct instance *inst;
1339         struct item *item;
1340
1341         inst = so_find_instance(pkgname, id);
1342         if (!inst) {
1343                 ErrPrint("instance %s - %s is not created\n");
1344                 return LB_STATUS_ERROR_INVALID;
1345         }
1346
1347         l = find_item(inst);
1348         if (!l) {
1349                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1350                 return LB_STATUS_ERROR_NOT_EXIST;
1351         }
1352
1353         item = eina_list_data_get(l);
1354         return lb_sys_event(inst, item, event);
1355 }
1356
1357 HAPI int lb_update(const char *pkgname, const char *id)
1358 {
1359         Eina_List *l;
1360         struct instance *inst;
1361         struct item *item;
1362
1363         inst = so_find_instance(pkgname, id);
1364         if (!inst) {
1365                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1366                 return LB_STATUS_ERROR_INVALID;
1367         }
1368
1369         l = find_item(inst);
1370         if (!l) {
1371                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1372                 return LB_STATUS_ERROR_NOT_EXIST;
1373         }
1374
1375         item = eina_list_data_get(l);
1376         (void)append_pending_list(item);
1377         return LB_STATUS_SUCCESS;
1378 }
1379
1380 HAPI int lb_update_all(const char *pkgname, const char *cluster, const char *category)
1381 {
1382         Eina_List *l;
1383         Eina_List *n;
1384         struct item *item;
1385
1386         DbgPrint("Update content for %s\n", pkgname ? pkgname : "(all)");
1387         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1388                 if (item->deleteme)
1389                         continue;
1390
1391                 if (cluster && strcasecmp(item->inst->cluster, cluster))
1392                         continue;
1393
1394                 if (category && strcasecmp(item->inst->category, category))
1395                         continue;
1396
1397                 if (pkgname && strlen(pkgname)) {
1398                         if (!strcmp(item->inst->item->pkgname, pkgname)) {
1399                                 (void)append_pending_list(item);
1400                         }
1401                 } else {
1402                         (void)append_pending_list(item);
1403                 }
1404         }
1405
1406         return LB_STATUS_SUCCESS;
1407 }
1408
1409 HAPI int lb_delete_all_deleteme(void)
1410 {
1411         Eina_List *l;
1412         Eina_List *n;
1413         struct item *item;
1414         int cnt = 0;
1415
1416         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1417                 if (!item->deleteme)
1418                         continue;
1419
1420                 s_info.item_list = eina_list_remove(s_info.item_list, item);
1421
1422                 update_monitor_del(item->inst->id, item);
1423                 (void)so_destroy(item->inst);
1424                 free(item);
1425                 cnt++;
1426         }
1427
1428         DbgPrint("Delete all deleteme: %d\n", cnt);
1429         return LB_STATUS_SUCCESS;
1430 }
1431
1432 HAPI int lb_system_event_all(int event)
1433 {
1434         Eina_List *l;
1435         Eina_List *n;
1436         struct item *item;
1437
1438         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1439                 if (item->deleteme)
1440                         continue;
1441
1442                 DbgPrint("System event for %s (%d)\n", item->inst->id, event);
1443                 lb_sys_event(item->inst, item, event);
1444         }
1445
1446         return LB_STATUS_SUCCESS;
1447 }
1448
1449 HAPI void lb_pause_all(void)
1450 {
1451         Eina_List *l;
1452         struct item *item;
1453
1454         s_info.paused = 1;
1455
1456         pending_timer_freeze();
1457
1458         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1459                 if (item->deleteme) {
1460                         DbgPrint("Instance %s skip timer pause (deleteme)\n", item->inst->item->pkgname);
1461                         continue;
1462                 }
1463
1464                 if (item->is_paused)
1465                         continue;
1466
1467                 timer_freeze(item);
1468
1469                 lb_sys_event(item->inst, item, LB_SYS_EVENT_PAUSED);
1470         }
1471 }
1472
1473 HAPI void lb_resume_all(void)
1474 {
1475         Eina_List *l;
1476         struct item *item;
1477
1478         s_info.paused = 0;
1479
1480         pending_timer_thaw();
1481
1482         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1483                 if (item->deleteme) {
1484                         DbgPrint("Instance %s skip timer resume (deleteme)\n", item->inst->item->pkgname);
1485                         continue;
1486                 }
1487
1488                 if (item->is_paused)
1489                         continue;
1490
1491                 timer_thaw(item);
1492
1493                 lb_sys_event(item->inst, item, LB_SYS_EVENT_RESUMED);
1494
1495                 if (item->updated_in_pause) {
1496                         (void)append_pending_list(item);
1497                         item->updated_in_pause = 0;
1498                 }
1499         }
1500 }
1501
1502 HAPI int lb_pause(const char *pkgname, const char *id)
1503 {
1504         struct instance *inst;
1505         Eina_List *l;
1506         struct item *item;
1507
1508         inst = so_find_instance(pkgname, id);
1509         if (!inst)
1510                 return LB_STATUS_ERROR_INVALID;
1511
1512         l = find_item(inst);
1513         if (!l) {
1514                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1515                 return LB_STATUS_ERROR_NOT_EXIST;
1516         }
1517
1518         item = eina_list_data_get(l);
1519         if (!item)
1520                 return LB_STATUS_ERROR_FAULT;
1521
1522         if (item->deleteme) {
1523                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1524                 return LB_STATUS_ERROR_BUSY;
1525         }
1526
1527         item->is_paused = 1;
1528
1529         if (s_info.paused)
1530                 return LB_STATUS_SUCCESS;
1531
1532         timer_freeze(item);
1533
1534         lb_sys_event(inst, item, LB_SYS_EVENT_PAUSED);
1535
1536         return LB_STATUS_SUCCESS;
1537 }
1538
1539 HAPI int lb_resume(const char *pkgname, const char *id)
1540 {
1541         struct instance *inst;
1542         Eina_List *l;
1543         struct item *item;
1544
1545         inst = so_find_instance(pkgname, id);
1546         if (!inst)
1547                 return LB_STATUS_ERROR_INVALID;
1548
1549         l = find_item(inst);
1550         if (!l) {
1551                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1552                 return LB_STATUS_ERROR_NOT_EXIST;
1553         }
1554
1555         item = eina_list_data_get(l);
1556         if (!item)
1557                 return LB_STATUS_ERROR_FAULT;
1558
1559         if (item->deleteme) {
1560                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1561                 return LB_STATUS_ERROR_BUSY;
1562         }
1563
1564         item->is_paused = 0;
1565
1566         if (s_info.paused)
1567                 return LB_STATUS_SUCCESS;
1568
1569         timer_thaw(item);
1570
1571         lb_sys_event(inst, item, LB_SYS_EVENT_RESUMED);
1572
1573         if (item->updated_in_pause) {
1574                 (void)append_pending_list(item);
1575                 item->updated_in_pause = 0;
1576         }
1577
1578         return LB_STATUS_SUCCESS;
1579 }
1580
1581 HAPI void lb_turn_secured_on(void)
1582 {
1583         s_info.secured = 1;
1584 }
1585
1586 HAPI int lb_is_all_paused(void)
1587 {
1588         return s_info.paused;
1589 }
1590
1591 /* End of a file */