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