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