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