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