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