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