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