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