Don't try to update if a box is paused even though it is triggered by the 3rd process.
[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 inline 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
617                         ecore_timer_del(item->timer);
618                         item->timer = NULL;
619                         return ECORE_CALLBACK_CANCEL;
620                 }
621
622                 reset_lb_updated_flag(item);
623                 return ECORE_CALLBACK_RENEW;
624         }
625
626         if (s_info.update || pd_is_opened(item->inst->item->pkgname) < 0) {
627                 DbgPrint("%s is busy\n", s_info.update ? s_info.update->inst->id : item->inst->id);
628                 (void)append_pending_list(item);
629                 return ECORE_CALLBACK_RENEW;
630         }
631
632         item->monitor = ecore_timer_add(item->inst->item->timeout, update_timeout_cb, item);
633         if (!item->monitor) {
634                 ErrPrint("Failed to add update monitor %s(%s):%d\n",
635                                         item->inst->item->pkgname, item->inst->id, item->inst->item->timeout);
636                 return ECORE_CALLBACK_RENEW;
637         }
638
639         ret = so_update(item->inst);
640         if (ret < 0) {
641                 ecore_timer_del(item->monitor);
642                 item->monitor = NULL;
643                 reset_lb_updated_flag(item);
644                 return ECORE_CALLBACK_RENEW;
645         }
646
647         /*!
648          * \note
649          * Counter of the event monitor is only used for asynchronous content updating,
650          * So reset it to 1 from here because the async updating is started now,
651          * even if it is accumulated by other event function before this.
652          */
653         item->monitor_cnt = 1;
654
655         /*!
656          * \note
657          * While waiting the Callback function call,
658          * Add this for finding the crash
659          */
660         fault_mark_call(item->inst->item->pkgname, item->inst->id, "update,crashed", NO_ALARM, DEFAULT_LIFE_TIMER);
661
662         if (ret & NEED_TO_SCHEDULE)
663                 (void)append_pending_list(item);
664
665         if (ret & OUTPUT_UPDATED) {
666                 /*!
667                  * \NOTE 
668                  * In this case, there is potential issue
669                  * 1. User added update CALLBACK -> Inotify event (Only once)
670                  *    > We have to detect this case. Is it possible to be a user callback called faster than inotify event handler?
671                  * 2. Inotify event -> User added update CALLBACK -> Inotify event
672                  *    > Okay. What we want is this.
673                  */
674                 update_monitor_cnt(item);
675         }
676
677         /*
678          * \NOTE
679          * This should be updated after "update_monitor_cnt" function call,
680          * because the update_monitor_cnt function will see the s_info.update variable,
681          */
682         s_info.update = item;
683
684         return ECORE_CALLBACK_RENEW;
685 }
686
687 static inline void update_monitor_del(const char *id, struct item *item)
688 {
689         char *tmp;
690         int len;
691
692         update_monitor_del_update_cb(util_uri_to_path(id), file_updated_cb);
693
694         len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
695         tmp = malloc(len);
696         if (!tmp) {
697                 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
698                 return;
699         }
700
701         snprintf(tmp, len, "%s.desc", util_uri_to_path(id));
702         update_monitor_del_update_cb(tmp, desc_updated_cb);
703         free(tmp);
704 }
705
706 static inline int add_desc_update_monitor(const char *id, struct item *item)
707 {
708         char *filename;
709         int len;
710
711         len = strlen(util_uri_to_path(id)) + strlen(".desc") + 1;
712         filename = malloc(len);
713         if (!filename) {
714                 ErrPrint("Heap: %s (%s.desc)\n", strerror(errno), util_uri_to_path(id));
715                 return LB_STATUS_ERROR_MEMORY;
716         }
717
718         snprintf(filename, len, "%s.desc", util_uri_to_path(id));
719         return update_monitor_add_update_cb(filename, desc_updated_cb, item);
720 }
721
722 static inline int add_file_update_monitor(const char *id, struct item *item)
723 {
724         char *filename;
725
726         filename = strdup(util_uri_to_path(id));
727         if (!filename) {
728                 ErrPrint("Heap: %s (%s)\n", strerror(errno), id);
729                 return LB_STATUS_ERROR_MEMORY;
730         }
731
732         return update_monitor_add_update_cb(filename, file_updated_cb, item);
733 }
734
735 static inline int update_monitor_add(const char *id, struct item *item)
736 {
737         /*!
738          * \NOTE
739          * item->inst is not available yet.
740          */
741         add_file_update_monitor(id, item);
742         add_desc_update_monitor(id, item);
743         return LB_STATUS_SUCCESS;
744 }
745
746 HAPI int lb_init(void)
747 {
748         return LB_STATUS_SUCCESS;
749 }
750
751 HAPI int lb_fini(void)
752 {
753         Eina_List *l;
754         Eina_List *n;
755         struct item *item;
756
757         deactivate_pending_consumer();
758         deactivate_pd_open_pending_consumer();
759
760         EINA_LIST_FREE(s_info.pd_open_pending_list, item);
761         EINA_LIST_FREE(s_info.pending_list, item);
762
763         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
764                 provider_send_deleted(item->inst->item->pkgname, item->inst->id);
765                 lb_destroy(item->inst->item->pkgname, item->inst->id);
766         }
767
768         return LB_STATUS_SUCCESS;
769 }
770
771 /*!
772  * \note
773  * Exported API for each liveboxes.
774  */
775 const char *livebox_find_pkgname(const char *filename)
776 {
777         Eina_List *l;
778         struct item *item;
779
780         EINA_LIST_FOREACH(s_info.item_list, l, item) {
781                 if (!strcmp(item->inst->id, filename))
782                         return item->inst->item->pkgname;
783         }
784
785         return NULL;
786 }
787
788 int livebox_request_update_by_id(const char *filename)
789 {
790         Eina_List *l;
791         struct item *item;
792
793         if (so_current_op() != LIVEBOX_OP_UNKNOWN) {
794                 ErrPrint("Current operation: %d\n", so_current_op());
795                 return LB_STATUS_ERROR_INVALID;
796         }
797
798         EINA_LIST_FOREACH(s_info.item_list, l, item) {
799                 if (!strcmp(item->inst->id, filename)) {
800                         return append_pending_list(item);
801                 }
802         }
803
804         return LB_STATUS_ERROR_NOT_EXIST;
805 }
806
807 int livebox_trigger_update_monitor(const char *filename, int is_pd)
808 {
809         char *fname;
810         int ret;
811
812         if (so_current_op() != LIVEBOX_OP_UNKNOWN) {
813                 ErrPrint("Current operation: %d\n", so_current_op());
814                 return LB_STATUS_ERROR_INVALID;
815         }
816
817         if (is_pd) {
818                 int len;
819                 len = strlen(filename) + strlen(".desc");
820
821                 fname = malloc(len + 1);
822                 if (!fname) {
823                         ErrPrint("Heap: %s\n", strerror(errno));
824                         return LB_STATUS_ERROR_MEMORY;
825                 }
826
827                 snprintf(fname, len, "%s.desc", filename);
828         } else {
829                 fname = strdup(filename);
830                 if (!fname) {
831                         ErrPrint("Heap: %s\n", strerror(errno));
832                         return LB_STATUS_ERROR_MEMORY;
833                 }
834         }
835
836         if (access(fname, R_OK | W_OK) != 0) {
837                 ErrPrint("access: %s (%s)\n", fname, strerror(errno));
838                 ret = LB_STATUS_ERROR_IO;
839         } else {
840                 ret = update_monitor_trigger_update_cb(fname, 0);
841         }
842
843         free(fname);
844         return ret;
845 }
846
847 HAPI int lb_open_pd(const char *pkgname)
848 {
849         Eina_List *l;
850         char *tmp;
851
852         EINA_LIST_FOREACH(s_info.pd_list, l, tmp) {
853                 if (!strcmp(pkgname, tmp))
854                         return 0;
855         }
856
857         tmp = strdup(pkgname);
858         if (!tmp) {
859                 ErrPrint("Heap: %s\n", strerror(errno));
860                 return LB_STATUS_ERROR_MEMORY;
861         }
862
863         if (!s_info.pd_list)
864                 pending_timer_freeze();
865
866         s_info.pd_list = eina_list_append(s_info.pd_list, tmp);
867
868         /*!
869          * Find all instances from the pending list.
870          * Move them to pd_open_pending_timer
871          */
872         migrate_to_pd_open_pending_list(pkgname);
873         return LB_STATUS_SUCCESS;
874 }
875
876 HAPI int lb_close_pd(const char *pkgname)
877 {
878         Eina_List *l;
879         Eina_List *n;
880         char *tmp;
881
882         EINA_LIST_FOREACH_SAFE(s_info.pd_list, l, n, tmp) {
883                 if (strcmp(tmp, pkgname))
884                         continue;
885
886                 s_info.pd_list = eina_list_remove(s_info.pd_list, tmp);
887                 free(tmp);
888
889                 if (!s_info.pd_list)
890                         pending_timer_thaw();
891
892                 /*!
893                  * Move all items in pd_open_pending_list
894                  * to pending_list.
895                  */
896                 migrate_to_pending_list(pkgname);
897                 return LB_STATUS_SUCCESS;
898         }
899
900         return LB_STATUS_ERROR_NOT_EXIST;
901 }
902
903 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)
904 {
905         struct instance *inst;
906         struct item *item;
907         int ret;
908         int create_ret;
909         int need_to_create;
910
911         need_to_create = 0;
912         *out_content = NULL;
913         *out_title = NULL;
914
915         inst = so_find_instance(pkgname, id);
916         if (inst) {
917                 DbgPrint("Instance is already exists [%s - %s] content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
918                 return LB_STATUS_SUCCESS;
919         }
920
921         if (!skip_need_to_create) {
922                 ret = so_create_needed(pkgname, cluster, category, abi);
923                 if (ret != NEED_TO_CREATE)
924                         return LB_STATUS_ERROR_PERMISSION;
925
926                 need_to_create = 1;
927         }
928
929         item = calloc(1, sizeof(*item));
930         if (!item) {
931                 ErrPrint("Heap: %s (%s - %s, content[%s], cluster[%s], category[%s], abi[%s])\n", strerror(errno), pkgname, id, content_info, cluster, category, abi);
932                 return LB_STATUS_ERROR_MEMORY;
933         }
934
935         ret = update_monitor_add(id, item);
936         if (ret < 0) {
937                 free(item);
938                 return ret;
939         }
940
941         create_ret = so_create(pkgname, id, content_info, timeout, has_livebox_script, cluster, category, abi, &inst);
942         if (create_ret < 0) {
943                 update_monitor_del(id,  item);
944                 free(item);
945
946                 *w = 0;
947                 *h = 0;
948                 *priority = 0.0f;
949                 return create_ret;
950         }
951
952         item->inst = inst;
953
954         if (period > 0.0f && !s_info.secured) {
955                 item->timer = util_timer_add(period, updator_cb, item);
956                 if (!item->timer) {
957                         ErrPrint("Failed to add timer (%s - %s, content[%s], cluster[%s], category[%s], abi[%s]\n", pkgname, id, content_info, cluster, category, abi);
958                         update_monitor_del(id, item);
959                         (void)so_destroy(inst);
960                         free(item);
961                         return LB_STATUS_ERROR_FAULT;
962                 }
963
964                 if (s_info.paused)
965                         timer_freeze(item);
966         } else {
967                 DbgPrint("Local update timer is disabled: %lf (%d)\n", period, s_info.secured);
968                 item->timer = NULL;
969         }
970
971         s_info.item_list = eina_list_append(s_info.item_list, item);
972
973         if (create_ret & NEED_TO_SCHEDULE) {
974                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
975                 (void)append_pending_list(item);
976         }
977
978         if (create_ret & OUTPUT_UPDATED) {
979                 update_monitor_cnt(item);
980                 /*!
981                  * \note
982                  * To send a output info, get the info forcely.
983                  * but the output file monitor will do this again
984                  *
985                  * This function will set the tmp_content and tmp_title
986                  * even if it has no updates on the content, title,
987                  * it will set them to NULL.
988                  */
989                 if (so_get_output_info(inst, w, h, priority, out_content, out_title) == LB_STATUS_SUCCESS) {
990                         if (*out_content) {
991                                 char *tmp;
992
993                                 tmp = strdup(*out_content);
994                                 if (!tmp)
995                                         ErrPrint("Memory: %s\n", strerror(errno));
996
997                                 *out_content = tmp;
998                         }
999
1000                         if (*out_title) {
1001                                 char *tmp;
1002
1003                                 tmp = strdup(*out_title);
1004                                 if (!tmp)
1005                                         ErrPrint("Memory: %s\n", strerror(errno));
1006
1007                                 *out_title = tmp;
1008                         }
1009                 }
1010         }
1011
1012         *w = inst->w;
1013         *h = inst->h;
1014         *priority = inst->priority;
1015         return need_to_create;
1016 }
1017
1018 HAPI int lb_destroy(const char *pkgname, const char *id)
1019 {
1020         Eina_List *l;
1021         struct instance *inst;
1022         struct item *item;
1023
1024         inst = so_find_instance(pkgname, id);
1025         if (!inst) {
1026                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1027                 return LB_STATUS_ERROR_INVALID;
1028         }
1029
1030         l = find_item(inst);
1031         if (!l) {
1032                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1033                 return LB_STATUS_ERROR_NOT_EXIST;
1034         }
1035
1036         item = eina_list_data_get(l);
1037         s_info.item_list = eina_list_remove_list(s_info.item_list, l);
1038
1039         if (s_info.update == item)
1040                 s_info.update = NULL;
1041
1042         if (item->timer) {
1043                 clear_from_pd_open_pending_list(item);
1044                 clear_from_pending_list(item);
1045                 ecore_timer_del(item->timer);
1046                 item->timer = NULL;
1047
1048                 if (item->monitor)
1049                         item->deleteme = 1;
1050                 else
1051                         update_monitor_del(id, item);
1052         }
1053
1054         if (!item->monitor) {
1055                 free(item);
1056                 (void)so_destroy(inst);
1057         }
1058
1059         return LB_STATUS_SUCCESS;
1060 }
1061
1062 HAPI int lb_resize(const char *pkgname, const char *id, int w, int h)
1063 {
1064         Eina_List *l;
1065         struct instance *inst;
1066         struct item *item;
1067         int ret;
1068
1069         inst = so_find_instance(pkgname, id);
1070         if (!inst) {
1071                 ErrPrint("Instance %s - %s is not created (%dx%d)\n", pkgname, id, w, h);
1072                 return LB_STATUS_ERROR_INVALID;
1073         }
1074
1075         l = find_item(inst);
1076         if (!l) {
1077                 ErrPrint("Instance is not found (%s - %s, %dx%d)\n", pkgname, id, w, h);
1078                 return LB_STATUS_ERROR_NOT_EXIST;
1079         }
1080
1081         item = eina_list_data_get(l);
1082
1083         ret = so_resize(inst, w, h);
1084         if (ret < 0)
1085                 return ret;
1086
1087         if (ret & NEED_TO_SCHEDULE) {
1088                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1089                 (void)append_pending_list(item);
1090         }
1091
1092         if (ret & OUTPUT_UPDATED)
1093                 update_monitor_cnt(item);
1094
1095         return LB_STATUS_SUCCESS;
1096 }
1097
1098 HAPI char *lb_pinup(const char *pkgname, const char *id, int pinup)
1099 {
1100         struct instance *inst;
1101         char *ret;
1102
1103         inst = so_find_instance(pkgname, id);
1104         if (!inst) {
1105                 ErrPrint("Instance %s - %s is not found (pinup[%d])\n", pkgname, id, pinup);
1106                 return NULL;
1107         }
1108
1109         ret = so_pinup(inst, pinup);
1110         return ret;
1111 }
1112
1113 HAPI int lb_set_period(const char *pkgname, const char *id, double period)
1114 {
1115         Eina_List *l;
1116         struct instance *inst;
1117         struct item *item;
1118
1119         inst = so_find_instance(pkgname, id);
1120         if (!inst) {
1121                 ErrPrint("Instance %s - %s is not found (period[%lf])\n", pkgname, id, period);
1122                 return LB_STATUS_ERROR_INVALID;
1123         }
1124
1125         l = find_item(inst);
1126         if (!l) {
1127                 ErrPrint("Instance is not found (%s - %s, period[%lf])\n", pkgname, id, period);
1128                 return LB_STATUS_ERROR_NOT_EXIST;
1129         }
1130
1131         item = eina_list_data_get(l);
1132
1133         if (period <= 0.0f) {
1134                 if (item->timer) {
1135                         ecore_timer_del(item->timer);
1136                         item->timer = NULL;
1137                 }
1138         } else {
1139                 if (item->timer) {
1140                         util_timer_interval_set(item->timer, period);
1141                 } else if (!s_info.secured) {
1142                         item->timer = util_timer_add(period, updator_cb, item);
1143                         if (!item->timer) {
1144                                 ErrPrint("Failed to add timer (%s - %s)\n", pkgname, id);
1145                                 return LB_STATUS_ERROR_FAULT;
1146                         }
1147
1148                         if (s_info.paused)
1149                                 timer_freeze(item);
1150                 }
1151         }
1152
1153         return LB_STATUS_SUCCESS;
1154 }
1155
1156 HAPI int lb_clicked(const char *pkgname, const char *id, const char *event, double timestamp, double x, double y)
1157 {
1158         Eina_List *l;
1159         struct instance *inst;
1160         struct item *item;
1161         int ret;
1162
1163         inst = so_find_instance(pkgname, id);
1164         if (!inst) {
1165                 ErrPrint("Instance %s - %s is not exists (event[%s])\n", pkgname, id, event);
1166                 return LB_STATUS_ERROR_INVALID;
1167         }
1168
1169         l = find_item(inst);
1170         if (!l) {
1171                 ErrPrint("Instance is not found (%s - %s, event[%s])\n", pkgname, id, event);
1172                 return LB_STATUS_ERROR_NOT_EXIST;
1173         }
1174
1175         item = eina_list_data_get(l);
1176
1177         ret = so_clicked(inst, event, timestamp, x, y);
1178         if (ret < 0)
1179                 return ret;
1180
1181         if (ret & NEED_TO_SCHEDULE) {
1182                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1183                 (void)append_pending_list(item);
1184         }
1185
1186         if (ret & OUTPUT_UPDATED)
1187                 update_monitor_cnt(item);
1188
1189         return LB_STATUS_SUCCESS;
1190 }
1191
1192 HAPI int lb_script_event(const char *pkgname, const char *id, const char *emission, const char *source, struct event_info *event_info)
1193 {
1194         Eina_List *l;
1195         struct instance *inst;
1196         struct item *item;
1197         int ret;
1198
1199         inst = so_find_instance(pkgname, id);
1200         if (!inst) {
1201                 ErrPrint("Instance %s - %s is not exists (emission[%s], source[%s])\n", pkgname, id, emission, source);
1202                 return LB_STATUS_ERROR_INVALID;
1203         }
1204
1205         l = find_item(inst);
1206         if (!l) {
1207                 ErrPrint("Instance is not found (%s - %s, emissino[%s], source[%s])\n", pkgname, id, emission, source);
1208                 return LB_STATUS_ERROR_NOT_EXIST;
1209         }
1210
1211         item = eina_list_data_get(l);
1212
1213         if (emission && source && !strcmp(source, id)) {
1214                 if (item->inst->item->has_livebox_script) {
1215                         if (!strcmp(emission, "lb,show")) {
1216                                 item->is_lb_show = 1;
1217
1218                                 if (item->is_lb_updated && !is_pended_item(item))
1219                                         reset_lb_updated_flag(item);
1220
1221                                 source = util_uri_to_path(source);
1222                         } else if (!strcmp(emission, "lb,hide")) {
1223                                 DbgPrint("Livebox(%s) script is hide now\n", id);
1224                                 item->is_lb_show = 0;
1225
1226                                 source = util_uri_to_path(source);
1227                         }
1228                 }
1229
1230                 if (!strcmp(emission, "pd,show")) {
1231                         item->is_pd_show = 1;
1232                         source = util_uri_to_path(source);
1233                 } else if (!strcmp(emission, "pd,hide")) {
1234                         item->is_pd_show = 0;
1235                         source = util_uri_to_path(source);
1236                 }
1237         }
1238
1239         ret = so_script_event(inst, emission, source, event_info);
1240         if (ret < 0)
1241                 return ret;
1242
1243         if (ret & NEED_TO_SCHEDULE) {
1244                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1245                 (void)append_pending_list(item);
1246         }
1247
1248         if (ret & OUTPUT_UPDATED)
1249                 update_monitor_cnt(item);
1250
1251         return LB_STATUS_SUCCESS;
1252 }
1253
1254 HAPI int lb_is_pinned_up(const char *pkgname, const char *id)
1255 {
1256         Eina_List *l;
1257         struct instance *inst;
1258         struct item *item;
1259
1260         inst = so_find_instance(pkgname, id);
1261         if (!inst) {
1262                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1263                 return LB_STATUS_ERROR_INVALID;
1264         }
1265
1266         l = find_item(inst);
1267         if (!l) {
1268                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1269                 return LB_STATUS_ERROR_NOT_EXIST;
1270         }
1271
1272         item = eina_list_data_get(l);
1273         if (!item) {
1274                 ErrPrint("Invalid item(%s - %s)\n", pkgname, id);
1275                 return LB_STATUS_ERROR_FAULT;
1276         }
1277         /*!
1278          * NOTE:
1279          * item is not used.
1280          * Maybe this is not neccessary for this operation
1281          */
1282         return so_is_pinned_up(inst);
1283 }
1284
1285 HAPI int lb_change_group(const char *pkgname, const char *id, const char *cluster, const char *category)
1286 {
1287         Eina_List *l;
1288         struct instance *inst;
1289         struct item *item;
1290         int ret;
1291
1292         inst = so_find_instance(pkgname, id);
1293         if (!inst) {
1294                 ErrPrint("Instance %s - %s is not created (cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1295                 return LB_STATUS_ERROR_INVALID;
1296         }
1297
1298         l = find_item(inst);
1299         if (!l) {
1300                 ErrPrint("Instance is not found(%s - %s, cluster[%s], category[%s])\n", pkgname, id, cluster, category);
1301                 return LB_STATUS_ERROR_NOT_EXIST;
1302         }
1303
1304         item = eina_list_data_get(l);
1305
1306         ret = so_change_group(inst, cluster, category);
1307         if (ret < 0)
1308                 return ret;
1309
1310         if (ret & NEED_TO_SCHEDULE) {
1311                 DbgPrint("%s Returns NEED_TO_SCHEDULE\n", pkgname);
1312                 (void)append_pending_list(item);
1313         }
1314
1315         if (ret & OUTPUT_UPDATED)
1316                 update_monitor_cnt(item);
1317
1318         return LB_STATUS_SUCCESS;
1319 }
1320
1321 static inline int lb_sys_event(struct instance *inst, struct item *item, int event)
1322 {
1323         int ret;
1324
1325         ret = so_sys_event(inst, event);
1326         if (ret < 0)
1327                 return ret;
1328
1329         if (ret & NEED_TO_SCHEDULE)
1330                 (void)append_pending_list(item);
1331
1332         if (ret & OUTPUT_UPDATED)
1333                 update_monitor_cnt(item);
1334
1335         return LB_STATUS_SUCCESS;
1336 }
1337
1338 HAPI int lb_system_event(const char *pkgname, const char *id, int event)
1339 {
1340         Eina_List *l;
1341         struct instance *inst;
1342         struct item *item;
1343
1344         inst = so_find_instance(pkgname, id);
1345         if (!inst) {
1346                 ErrPrint("instance %s - %s is not created\n");
1347                 return LB_STATUS_ERROR_INVALID;
1348         }
1349
1350         l = find_item(inst);
1351         if (!l) {
1352                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1353                 return LB_STATUS_ERROR_NOT_EXIST;
1354         }
1355
1356         item = eina_list_data_get(l);
1357         return lb_sys_event(inst, item, event);
1358 }
1359
1360 HAPI int lb_update(const char *pkgname, const char *id)
1361 {
1362         Eina_List *l;
1363         struct instance *inst;
1364         struct item *item;
1365
1366         inst = so_find_instance(pkgname, id);
1367         if (!inst) {
1368                 ErrPrint("Instance %s - %s is not created\n", pkgname, id);
1369                 return LB_STATUS_ERROR_INVALID;
1370         }
1371
1372         l = find_item(inst);
1373         if (!l) {
1374                 ErrPrint("Instance is not found(%s - %s)\n", pkgname, id);
1375                 return LB_STATUS_ERROR_NOT_EXIST;
1376         }
1377
1378         item = eina_list_data_get(l);
1379         (void)append_pending_list(item);
1380         return LB_STATUS_SUCCESS;
1381 }
1382
1383 HAPI int lb_update_all(const char *pkgname, const char *cluster, const char *category)
1384 {
1385         Eina_List *l;
1386         Eina_List *n;
1387         struct item *item;
1388
1389         DbgPrint("Update content for %s\n", pkgname ? pkgname : "(all)");
1390         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1391                 if (item->deleteme)
1392                         continue;
1393
1394                 if (cluster && strcasecmp(item->inst->cluster, cluster))
1395                         continue;
1396
1397                 if (category && strcasecmp(item->inst->category, category))
1398                         continue;
1399
1400                 if (pkgname && strlen(pkgname)) {
1401                         if (!strcmp(item->inst->item->pkgname, pkgname)) {
1402                                 (void)append_pending_list(item);
1403                         }
1404                 } else {
1405                         (void)append_pending_list(item);
1406                 }
1407         }
1408
1409         return LB_STATUS_SUCCESS;
1410 }
1411
1412 HAPI int lb_delete_all_deleteme(void)
1413 {
1414         Eina_List *l;
1415         Eina_List *n;
1416         struct item *item;
1417         int cnt = 0;
1418
1419         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1420                 if (!item->deleteme)
1421                         continue;
1422
1423                 s_info.item_list = eina_list_remove(s_info.item_list, item);
1424
1425                 update_monitor_del(item->inst->id, item);
1426                 (void)so_destroy(item->inst);
1427                 free(item);
1428                 cnt++;
1429         }
1430
1431         DbgPrint("Delete all deleteme: %d\n", cnt);
1432         return LB_STATUS_SUCCESS;
1433 }
1434
1435 HAPI int lb_system_event_all(int event)
1436 {
1437         Eina_List *l;
1438         Eina_List *n;
1439         struct item *item;
1440
1441         EINA_LIST_FOREACH_SAFE(s_info.item_list, l, n, item) {
1442                 if (item->deleteme)
1443                         continue;
1444
1445                 DbgPrint("System event for %s (%d)\n", item->inst->id, event);
1446                 lb_sys_event(item->inst, item, event);
1447         }
1448
1449         return LB_STATUS_SUCCESS;
1450 }
1451
1452 HAPI void lb_pause_all(void)
1453 {
1454         Eina_List *l;
1455         struct item *item;
1456
1457         s_info.paused = 1;
1458
1459         pending_timer_freeze();
1460
1461         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1462                 if (item->deleteme) {
1463                         DbgPrint("Instance %s skip timer pause (deleteme)\n", item->inst->item->pkgname);
1464                         continue;
1465                 }
1466
1467                 if (item->is_paused)
1468                         continue;
1469
1470                 timer_freeze(item);
1471
1472                 lb_sys_event(item->inst, item, LB_SYS_EVENT_PAUSED);
1473         }
1474 }
1475
1476 HAPI void lb_resume_all(void)
1477 {
1478         Eina_List *l;
1479         struct item *item;
1480
1481         s_info.paused = 0;
1482
1483         pending_timer_thaw();
1484
1485         EINA_LIST_FOREACH(s_info.item_list, l, item) {
1486                 if (item->deleteme) {
1487                         DbgPrint("Instance %s skip timer resume (deleteme)\n", item->inst->item->pkgname);
1488                         continue;
1489                 }
1490
1491                 if (item->is_paused)
1492                         continue;
1493
1494                 timer_thaw(item);
1495
1496                 lb_sys_event(item->inst, item, LB_SYS_EVENT_RESUMED);
1497
1498                 if (item->updated_in_pause) {
1499                         (void)append_pending_list(item);
1500                         item->updated_in_pause = 0;
1501                 }
1502         }
1503 }
1504
1505 HAPI int lb_pause(const char *pkgname, const char *id)
1506 {
1507         struct instance *inst;
1508         Eina_List *l;
1509         struct item *item;
1510
1511         inst = so_find_instance(pkgname, id);
1512         if (!inst)
1513                 return LB_STATUS_ERROR_INVALID;
1514
1515         l = find_item(inst);
1516         if (!l) {
1517                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1518                 return LB_STATUS_ERROR_NOT_EXIST;
1519         }
1520
1521         item = eina_list_data_get(l);
1522         if (!item)
1523                 return LB_STATUS_ERROR_FAULT;
1524
1525         if (item->deleteme) {
1526                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1527                 return LB_STATUS_ERROR_BUSY;
1528         }
1529
1530         item->is_paused = 1;
1531
1532         if (s_info.paused)
1533                 return LB_STATUS_SUCCESS;
1534
1535         timer_freeze(item);
1536
1537         lb_sys_event(inst, item, LB_SYS_EVENT_PAUSED);
1538
1539         return LB_STATUS_SUCCESS;
1540 }
1541
1542 HAPI int lb_resume(const char *pkgname, const char *id)
1543 {
1544         struct instance *inst;
1545         Eina_List *l;
1546         struct item *item;
1547
1548         inst = so_find_instance(pkgname, id);
1549         if (!inst)
1550                 return LB_STATUS_ERROR_INVALID;
1551
1552         l = find_item(inst);
1553         if (!l) {
1554                 ErrPrint("Instance is not found (%s - %s)\n", pkgname, id);
1555                 return LB_STATUS_ERROR_NOT_EXIST;
1556         }
1557
1558         item = eina_list_data_get(l);
1559         if (!item)
1560                 return LB_STATUS_ERROR_FAULT;
1561
1562         if (item->deleteme) {
1563                 DbgPrint("Instance %s will be deleted (%s)\n", item->inst->item->pkgname, item->inst->id);
1564                 return LB_STATUS_ERROR_BUSY;
1565         }
1566
1567         item->is_paused = 0;
1568
1569         if (s_info.paused)
1570                 return LB_STATUS_SUCCESS;
1571
1572         timer_thaw(item);
1573
1574         lb_sys_event(inst, item, LB_SYS_EVENT_RESUMED);
1575
1576         if (item->updated_in_pause) {
1577                 (void)append_pending_list(item);
1578                 item->updated_in_pause = 0;
1579         }
1580
1581         return LB_STATUS_SUCCESS;
1582 }
1583
1584 HAPI void lb_turn_secured_on(void)
1585 {
1586         s_info.secured = 1;
1587 }
1588
1589 HAPI int lb_is_all_paused(void)
1590 {
1591         return s_info.paused;
1592 }
1593
1594 /* End of a file */