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