tizen 2.3 release
[apps/livebox/data-provider-master.git] / src / slave_life.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 <string.h> /* strerror */
19 #include <errno.h> /* errno */
20 #include <unistd.h> /* pid_t */
21 #include <stdlib.h> /* free */
22 #include <pthread.h>
23 #include <malloc.h>
24 #include <sys/time.h>
25 #include <sys/resource.h>
26
27 #include <Eina.h>
28 #include <Ecore.h>
29
30 #include <aul.h> /* aul_launch_app */
31 #include <dlog.h>
32 #include <bundle.h>
33
34 #include <packet.h>
35 #include <dynamicbox_errno.h>
36 #include <dynamicbox_conf.h>
37 #include <dynamicbox_cmd_list.h>
38 #include <dynamicbox_service.h>
39
40 #include "critical_log.h"
41 #include "slave_life.h"
42 #include "slave_rpc.h"
43 #include "client_life.h"
44 #include "fault_manager.h"
45 #include "debug.h"
46 #include "conf.h"
47 #include "setting.h"
48 #include "util.h"
49 #include "abi.h"
50 #include "xmonitor.h"
51
52 #include "package.h"
53 #include "instance.h"
54
55 #define BUNDLE_SLAVE_SVC_OP_TYPE "__APP_SVC_OP_TYPE__"
56 #define APP_CONTROL_OPERATION_MAIN "http://tizen.org/appcontrol/operation/main"
57 #define LOW_PRIORITY    10
58
59 int errno;
60
61 struct slave_node {
62         char *name;
63         char *abi;
64         char *pkgname;
65         int secured;    /* Only A package(dynamicbox) is loaded for security requirements */
66         int refcnt;
67         int fault_count;
68         int critical_fault_count;
69         enum slave_state state;
70         int network;
71
72         int loaded_instance;
73         int loaded_package;
74
75         int reactivate_instances;
76         int reactivate_slave;
77
78         pid_t pid;
79
80         enum event_process {
81                 SLAVE_EVENT_PROCESS_IDLE = 0x00,
82                 SLAVE_EVENT_PROCESS_ACTIVATE = 0x01,
83                 SLAVE_EVENT_PROCESS_DEACTIVATE = 0x02,
84                 SLAVE_EVENT_PROCESS_DELETE = 0x04,
85                 SLAVE_EVENT_PROCESS_FAULT = 0x08,
86                 SLAVE_EVENT_PROCESS_PAUSE = 0x10,
87                 SLAVE_EVENT_PROCESS_RESUME = 0x20
88         } in_event_process;
89         Eina_List *event_activate_list;
90         Eina_List *event_deactivate_list;
91         Eina_List *event_delete_list;
92         Eina_List *event_fault_list;
93         Eina_List *event_pause_list;
94         Eina_List *event_resume_list;
95
96         Eina_List *data_list;
97
98         Ecore_Timer *ttl_timer; /*!< Time to live */
99         Ecore_Timer *activate_timer; /*!< Waiting hello packet for this time */
100         Ecore_Timer *relaunch_timer; /*!< Try to relaunch service app */
101         Ecore_Timer *terminate_timer; /*!< Waiting this timer before terminate the service provider */
102         int relaunch_count;
103
104         int ctrl_option;
105
106 #if defined(_USE_ECORE_TIME_GET)
107         double activated_at;
108 #else
109         struct timeval activated_at;
110 #endif
111
112         char *hw_acceleration;
113 };
114
115 struct event {
116         struct slave_node *slave;
117
118         int (*evt_cb)(struct slave_node *, void *);
119         void *cbdata;
120         int deleted;
121 };
122
123 struct priv_data {
124         char *tag;
125         void *data;
126 };
127
128 static struct {
129         Eina_List *slave_list;
130         int deactivate_all_refcnt;
131 } s_info = {
132         .slave_list = NULL,
133         .deactivate_all_refcnt = 0,
134 };
135
136 static Eina_Bool terminate_timer_cb(void *data)
137 {
138         struct slave_node *slave = data;
139         int ret;
140
141         /*!
142          * \todo
143          * check the return value of the aul_terminate_pid
144          */
145         slave->state = SLAVE_REQUEST_TO_TERMINATE;
146         slave->terminate_timer = NULL;
147
148         DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave));
149         ret = aul_terminate_pid_async(slave->pid);
150         if (ret < 0) {
151                 ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret);
152                 slave = slave_deactivated(slave);
153                 if (slave == NULL) {
154                         DbgPrint("Slave is deleted\n");
155                 }
156         }
157
158         return ECORE_CALLBACK_CANCEL;
159 }
160
161 static struct slave_node *slave_deactivate(struct slave_node *slave, int no_timer)
162 {
163         int ret;
164
165         /**
166          * @note
167          * The caller must has to check the slave's state.
168          * If it is not activated, this function must has not to be called.
169          */
170
171         if (slave_pid(slave) <= 0) {
172                 return slave;
173         }
174
175         if (slave->ttl_timer) {
176                 /**
177                  * @note
178                  * If there is an activated TTL timer,
179                  * It has to be cleared before deactivate the slave.
180                  */
181                 ecore_timer_del(slave->ttl_timer);
182                 slave->ttl_timer = NULL;
183         }
184
185         if ((slave->ctrl_option & PROVIDER_CTRL_MANUAL_TERMINATION) == PROVIDER_CTRL_MANUAL_TERMINATION) {
186                 /*!
187                  * \note
188                  * In this case,
189                  * The provider requests MANUAL TERMINATION control option.
190                  * Master will not send terminate request in this case, the provider should be terminated by itself.
191                  */
192                 DbgPrint("Manual termination is turned on\n");
193                 slave->state = SLAVE_REQUEST_TO_DISCONNECT;
194                 (void)slave_rpc_disconnect(slave);
195         } else if (slave->terminate_timer) {
196                 ErrPrint("Terminate timer is already fired (%d)\n", slave->pid);
197         } else if (!no_timer && !slave->secured) {
198                 DbgPrint("Fire the terminate timer: %d\n", slave->pid);
199                 slave->terminate_timer = ecore_timer_add(DYNAMICBOX_CONF_SLAVE_ACTIVATE_TIME, terminate_timer_cb, slave);
200                 if (!slave->terminate_timer) {
201                         /*!
202                          * \note
203                          * Normally, Call the terminate_timer_cb directly from here
204                          * But in this case. if the aul_terminate_pid failed, Call the slave_deactivated function directly.
205                          * Then the "slave" pointer can be changed. To trace it, Copy the body of terminate_timer_cb to here.
206                          */
207                         ErrPrint("Failed to add a new timer for terminating\n");
208                         DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave));
209                         /*!
210                          * \todo
211                          * check the return value of the aul_terminate_pid
212                          */
213                         slave->state = SLAVE_REQUEST_TO_TERMINATE;
214
215                         ret = aul_terminate_pid_async(slave->pid);
216                         if (ret < 0) {
217                                 ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret);
218                                 slave = slave_deactivated(slave);
219                         }
220                 }
221         } else {
222                 /*!
223                  * \todo
224                  * check the return value of the aul_terminate_pid
225                  */
226                 slave->state = SLAVE_REQUEST_TO_TERMINATE;
227
228                 DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave));
229                 ret = aul_terminate_pid_async(slave->pid);
230                 if (ret < 0) {
231                         ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret);
232                         slave = slave_deactivated(slave);
233                 }
234         }
235
236         return slave;
237 }
238
239 static Eina_Bool slave_ttl_cb(void *data)
240 {
241         struct pkg_info *info;
242         struct slave_node *slave = (struct slave_node *)data;
243         Eina_List *l;
244         Eina_List *pkg_list;
245
246         pkg_list = (Eina_List *)package_list();
247         EINA_LIST_FOREACH(pkg_list, l, info) {
248                 if (package_slave(info) == slave) {
249                         struct inst_info *inst;
250                         Eina_List *inst_list;
251                         Eina_List *n;
252
253                         inst_list = (Eina_List *)package_instance_list(info);
254                         EINA_LIST_FOREACH(inst_list, n, inst) {
255                                 if (instance_visible_state(inst) == DBOX_SHOW) {
256                                         DbgPrint("Instance is in show, give more ttl to %d for %s\n", slave_pid(slave), instance_id(inst));
257                                         return ECORE_CALLBACK_RENEW;
258                                 }
259                         }
260                 }
261         }
262
263         /*!
264          * \note
265          * ttl_timer must has to be set to NULL before deactivate the slave
266          * It will be used for making decision of the expired TTL timer or the fault of a dynamicbox.
267          */
268         slave->ttl_timer = NULL;
269
270         if (slave_is_activated(slave)) {
271                 slave_set_reactivation(slave, 0);
272                 slave_set_reactivate_instances(slave, 1);
273
274                 slave = slave_deactivate(slave, 1);
275                 if (!slave) {
276                         DbgPrint("Slave is deleted\n");
277                 }
278         }
279
280         /*! To recover all instances state it is activated again */
281         return ECORE_CALLBACK_CANCEL;
282 }
283
284 static inline int xmonitor_pause_cb(void *data)
285 {
286         slave_pause(data);
287         return DBOX_STATUS_ERROR_NONE;
288 }
289
290 static inline int xmonitor_resume_cb(void *data)
291 {
292         slave_resume(data);
293         return DBOX_STATUS_ERROR_NONE;
294 }
295
296 static inline struct slave_node *create_slave_node(const char *name, int is_secured, const char *abi, const char *pkgname, int network, const char *hw_acceleration)
297 {
298         struct slave_node *slave;
299
300         slave = calloc(1, sizeof(*slave));
301         if (!slave) {
302                 ErrPrint("Heap: %s\n", strerror(errno));
303                 return NULL;
304         }
305
306         slave->name = strdup(name);
307         if (!slave->name) {
308                 ErrPrint("Heap: %s\n", strerror(errno));
309                 DbgFree(slave);
310                 return NULL;
311         }
312
313         slave->abi = strdup(abi);
314         if (!slave->abi) {
315                 ErrPrint("Heap: %s\n", strerror(errno));
316                 DbgFree(slave->name);
317                 DbgFree(slave);
318                 return NULL;
319         }
320
321         slave->pkgname = strdup(pkgname);
322         if (!slave->pkgname) {
323                 ErrPrint("Heap: %s\n", strerror(errno));
324                 DbgFree(slave->abi);
325                 DbgFree(slave->name);
326                 DbgFree(slave);
327                 return NULL;
328         }
329
330         if (hw_acceleration) {
331                 slave->hw_acceleration = strdup(hw_acceleration);
332                 if (!slave->hw_acceleration) {
333                         ErrPrint("Heap: %s\n", strerror(errno));
334                         DbgFree(slave->pkgname);
335                         DbgFree(slave->abi);
336                         DbgFree(slave->name);
337                         DbgFree(slave);
338                         return NULL;
339                 }
340         }
341
342         slave->secured = is_secured;
343         slave->pid = (pid_t)-1;
344         slave->state = SLAVE_TERMINATED;
345         slave->network = network;
346         slave->relaunch_count = DYNAMICBOX_CONF_SLAVE_RELAUNCH_COUNT;
347
348         xmonitor_add_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
349         xmonitor_add_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
350
351         s_info.slave_list = eina_list_append(s_info.slave_list, slave);
352         return slave;
353 }
354
355 static inline void invoke_delete_cb(struct slave_node *slave)
356 {
357         Eina_List *l;
358         Eina_List *n;
359         struct event *event;
360
361         slave->in_event_process |= SLAVE_EVENT_PROCESS_DELETE;
362         EINA_LIST_FOREACH_SAFE(slave->event_delete_list, l, n, event) {
363                 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
364                         slave->event_delete_list = eina_list_remove(slave->event_delete_list, event);
365                         DbgFree(event);
366                 }
367         }
368         slave->in_event_process &= ~SLAVE_EVENT_PROCESS_DELETE;
369 }
370
371 static inline void destroy_slave_node(struct slave_node *slave)
372 {
373         struct event *event;
374         struct priv_data *priv;
375
376         if (slave_pid(slave) != (pid_t)-1) {
377                 ErrPrint("Slave is not deactivated\n");
378                 return;
379         }
380
381         xmonitor_del_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
382         xmonitor_del_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
383
384         invoke_delete_cb(slave);
385         slave_rpc_fini(slave); /*!< Finalize the RPC after handling all delete callbacks */
386
387         EINA_LIST_FREE(slave->event_delete_list, event) {
388                 DbgFree(event);
389         }
390
391         EINA_LIST_FREE(slave->event_activate_list, event) {
392                 DbgFree(event);
393         }
394
395         EINA_LIST_FREE(slave->event_deactivate_list, event) {
396                 DbgFree(event);
397         }
398
399         EINA_LIST_FREE(slave->event_fault_list, event) {
400                 DbgFree(event);
401         }
402
403         EINA_LIST_FREE(slave->data_list, priv) {
404                 DbgFree(priv->tag);
405                 DbgFree(priv);
406         }
407
408         s_info.slave_list = eina_list_remove(s_info.slave_list, slave);
409
410         if (slave->ttl_timer) {
411                 ecore_timer_del(slave->ttl_timer);
412         }
413
414         if (slave->activate_timer) {
415                 ecore_timer_del(slave->activate_timer);
416         }
417
418         if (slave->relaunch_timer) {
419                 ecore_timer_del(slave->relaunch_timer);
420         }
421
422         DbgFree(slave->abi);
423         DbgFree(slave->name);
424         DbgFree(slave->pkgname);
425         DbgFree(slave->hw_acceleration);
426         DbgFree(slave);
427         return;
428 }
429
430 static inline struct slave_node *find_slave(const char *name)
431 {
432         struct slave_node *slave;
433         Eina_List *l;
434
435         EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
436                 if (!strcmp(slave->name, name)) {
437                         return slave;
438                 }
439         }
440
441         return NULL;
442 }
443
444 HAPI int slave_expired_ttl(struct slave_node *slave)
445 {
446         if (!slave) {
447                 return 0;
448         }
449
450         if (!slave->secured && !(DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL)) {
451                 return 0;
452         }
453
454         return !!slave->ttl_timer;
455 }
456
457 HAPI struct slave_node *slave_ref(struct slave_node *slave)
458 {
459         if (!slave) {
460                 return NULL;
461         }
462
463         slave->refcnt++;
464         return slave;
465 }
466
467 HAPI struct slave_node *slave_unref(struct slave_node *slave)
468 {
469         if (!slave) {
470                 return NULL;
471         }
472
473         if (slave->refcnt == 0) {
474                 ErrPrint("Slave refcnt is not valid\n");
475                 return NULL;
476         }
477
478         slave->refcnt--;
479         if (slave->refcnt == 0) {
480                 destroy_slave_node(slave);
481                 slave = NULL;
482         }
483
484         return slave;
485 }
486
487 HAPI const int const slave_refcnt(struct slave_node *slave)
488 {
489         return slave->refcnt;
490 }
491
492 HAPI struct slave_node *slave_create(const char *name, int is_secured, const char *abi, const char *pkgname, int network, const char *hw_acceleration)
493 {
494         struct slave_node *slave;
495
496         slave = find_slave(name);
497         if (slave) {
498                 if (slave->secured != is_secured) {
499                         ErrPrint("Exists slave and creating slave's security flag is not matched\n");
500                 }
501                 return slave;
502         }
503
504         slave = create_slave_node(name, is_secured, abi, pkgname, network, hw_acceleration);
505         if (!slave) {
506                 return NULL;
507         }
508
509         slave_ref(slave);
510         slave_rpc_init(slave);
511
512         return slave;
513 }
514
515 /*!
516  * \note
517  * Before destroying slave object,
518  * you should check the RPC(slave_async_XXX) state and Private data field (slave_set_data)
519  */
520 HAPI void slave_destroy(struct slave_node *slave)
521 {
522         slave_unref(slave);
523 }
524
525 static inline struct slave_node *invoke_fault_cb(struct slave_node *slave)
526 {
527         Eina_List *l;
528         Eina_List *n;
529         struct event *event;
530
531         slave_ref(slave);
532         slave->in_event_process |= SLAVE_EVENT_PROCESS_FAULT;
533         EINA_LIST_FOREACH_SAFE(slave->event_fault_list, l, n, event) {
534                 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
535                         slave->event_fault_list = eina_list_remove(slave->event_fault_list, event);
536                         DbgFree(event);
537                 }
538         }
539         slave->in_event_process &= ~SLAVE_EVENT_PROCESS_FAULT;
540         slave = slave_unref(slave);
541
542         return slave;
543 }
544
545 static inline void invoke_activate_cb(struct slave_node *slave)
546 {
547         Eina_List *l;
548         Eina_List *n;
549         struct event *event;
550
551         slave->in_event_process |= SLAVE_EVENT_PROCESS_ACTIVATE;
552         EINA_LIST_FOREACH_SAFE(slave->event_activate_list, l, n, event) {
553                 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
554                         slave->event_activate_list = eina_list_remove(slave->event_activate_list, event);
555                         DbgFree(event);
556                 }
557         }
558         slave->in_event_process &= ~SLAVE_EVENT_PROCESS_ACTIVATE;
559 }
560
561 static Eina_Bool activate_timer_cb(void *data)
562 {
563         struct slave_node *slave = data;
564
565         if (slave->relaunch_timer) {
566                 ecore_timer_del(slave->relaunch_timer);
567                 slave->relaunch_timer = NULL;
568         }
569
570         slave->fault_count++;
571
572         if (invoke_fault_cb(slave) == NULL) {
573                 ErrPrint("Slave is deleted while processing fault handler\n");
574                 return ECORE_CALLBACK_CANCEL;
575         }
576
577         slave_set_reactivation(slave, 0);
578         slave_set_reactivate_instances(slave, 0);
579
580         slave->activate_timer = NULL;
581         if (slave_pid(slave) > 0) {
582                 int ret;
583                 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
584                 ret = aul_terminate_pid_async(slave_pid(slave));
585                 if (ret < 0) {
586                         ErrPrint("Terminate failed, pid %d (reason: %d)\n", slave_pid(slave), ret);
587                 }
588         }
589
590         CRITICAL_LOG("Slave is not activated in %lf sec (slave: %s)\n", DYNAMICBOX_CONF_SLAVE_ACTIVATE_TIME, slave_name(slave));
591         slave = slave_deactivated(slave);
592         return ECORE_CALLBACK_CANCEL;
593 }
594
595 static inline void invoke_slave_fault_handler(struct slave_node *slave)
596 {
597         slave->fault_count++;
598         if (invoke_fault_cb(slave) == NULL) {
599                 ErrPrint("Slave is deleted while processing fault handler\n");
600                 return;
601         }
602
603         slave_set_reactivation(slave, 0);
604         slave_set_reactivate_instances(slave, 0);
605
606         if (slave_pid(slave) > 0) {
607                 if ((slave->ctrl_option & PROVIDER_CTRL_MANUAL_TERMINATION) == PROVIDER_CTRL_MANUAL_TERMINATION) {
608                         DbgPrint("Manual termination is turned on\n");
609                         (void)slave_rpc_disconnect(slave);
610                 } else {
611                         int ret;
612                         DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
613                         ret = aul_terminate_pid_async(slave_pid(slave));
614                         if (ret < 0) {
615                                 ErrPrint("Terminate failed, pid %d (reason: %d)\n", slave_pid(slave), ret);
616                         }
617                 }
618         }
619
620         slave->state = SLAVE_TERMINATED;
621 }
622
623 static Eina_Bool relaunch_timer_cb(void *data)
624 {
625         struct slave_node *slave = data;
626         int ret = ECORE_CALLBACK_CANCEL;
627
628         if (!slave->activate_timer) {
629                 ErrPrint("Activate timer is not valid\n");
630                 slave->relaunch_timer = NULL;
631
632                 invoke_slave_fault_handler(slave);
633         } else if (!slave->relaunch_count) {
634                 ErrPrint("Relaunch count is exhahausted\n");
635                 ecore_timer_del(slave->activate_timer);
636                 slave->activate_timer = NULL;
637
638                 slave->relaunch_timer = NULL;
639                 invoke_slave_fault_handler(slave);
640         } else {
641                 bundle *param;
642
643                 param = bundle_create();
644                 if (!param) {
645                         ErrPrint("Failed to create a bundle\n");
646
647                         ecore_timer_del(slave->activate_timer);
648                         slave->activate_timer = NULL;
649
650                         slave->relaunch_timer = NULL;
651
652                         invoke_slave_fault_handler(slave);
653                 } else {
654                         bundle_add(param, BUNDLE_SLAVE_SVC_OP_TYPE, APP_CONTROL_OPERATION_MAIN);
655                         bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_NAME, slave_name(slave));
656                         bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_SECURED, ((DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL) || slave->secured) ? "true" : "false");
657                         bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_ABI, slave->abi);
658                         bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_HW_ACCELERATION, slave->hw_acceleration);
659
660                         slave->pid = (pid_t)aul_launch_app(slave_pkgname(slave), param);
661
662                         bundle_free(param);
663
664                         switch (slave->pid) {
665                         case AUL_R_EHIDDENFORGUEST:     /**< App hidden for guest mode */
666                         case AUL_R_ENOLAUNCHPAD:        /**< no launchpad */
667                         case AUL_R_EILLACC:             /**< Illegal Access */
668                         case AUL_R_EINVAL:              /**< Invalid argument */
669                         case AUL_R_ENOINIT:             /**< AUL handler NOT initialized */
670                         case AUL_R_ERROR:               /**< General error */
671                                 CRITICAL_LOG("Failed to launch a new slave %s (%d)\n", slave_name(slave), slave->pid);
672                                 slave->pid = (pid_t)-1;
673                                 ecore_timer_del(slave->activate_timer);
674                                 slave->activate_timer = NULL;
675
676                                 slave->relaunch_timer = NULL;
677
678                                 invoke_slave_fault_handler(slave);
679                                 /* Waiting app-launch result */
680                                 break;
681                         case AUL_R_ETIMEOUT:            /**< Timeout */
682                         case AUL_R_ECOMM:               /**< Comunication Error */
683                         case AUL_R_ETERMINATING:        /**< application terminating */
684                         case AUL_R_ECANCELED:           /**< Operation canceled */
685                                 slave->relaunch_count--;
686
687                                 CRITICAL_LOG("Try relaunch again %s (%d), %d\n", slave_name(slave), slave->pid, slave->relaunch_count);
688                                 slave->pid = (pid_t)-1;
689                                 ret = ECORE_CALLBACK_RENEW;
690                                 ecore_timer_reset(slave->activate_timer);
691                                 /* Try again after a few secs later */
692                                 break;
693                         case AUL_R_LOCAL:               /**< Launch by himself */
694                         case AUL_R_OK:                  /**< General success */
695                         default:
696                                 DbgPrint("Slave %s is launched with %d as %s\n", slave_pkgname(slave), slave->pid, slave_name(slave));
697                                 slave->relaunch_timer = NULL;
698                                 ecore_timer_reset(slave->activate_timer);
699                                 break;
700                         }
701                 }
702
703         }
704
705         return ret;
706 }
707
708 HAPI int slave_activate(struct slave_node *slave)
709 {
710         /**
711          * @todo
712          * If a slave is deactivated by OOM killer,
713          * We should not activate it again from here.
714          * Instead of this, it should be reactivated by user event or oom event(normal)
715          */
716
717         /**
718          * @note
719          * This check code can be replaced with the slave->state check code
720          * If the slave data has the PID, it means, it is activated
721          * Even if it is in the termiating sequence, it will have the PID
722          * until it is terminated at last.
723          * So we can use this simple code for checking the slave's last state.
724          * whether it is alive or not.
725          */
726         if (slave_pid(slave) != (pid_t)-1) {
727                 if (slave->terminate_timer) {
728                         DbgPrint("Clear terminate timer. to reuse (%d)\n", slave->pid);
729                         ecore_timer_del(slave->terminate_timer);
730                         slave->terminate_timer = NULL;
731                 } else if (slave_state(slave) == SLAVE_REQUEST_TO_TERMINATE || slave_state(slave) == SLAVE_REQUEST_TO_DISCONNECT) {
732                         slave_set_reactivation(slave, 1);
733                 }
734                 return DBOX_STATUS_ERROR_ALREADY;
735         } else if (slave_state(slave) == SLAVE_REQUEST_TO_LAUNCH) {
736                 DbgPrint("Slave is already launched: but the AUL is timed out\n");
737                 return DBOX_STATUS_ERROR_ALREADY;
738         }
739
740         if (DYNAMICBOX_CONF_DEBUG_MODE || g_conf.debug_mode) {
741                 DbgPrint("Debug Mode enabled. name[%s] secured[%d] abi[%s]\n", slave_name(slave), slave->secured, slave->abi);
742         } else {
743                 bundle *param;
744
745                 slave->relaunch_count = DYNAMICBOX_CONF_SLAVE_RELAUNCH_COUNT;
746
747                 param = bundle_create();
748                 if (!param) {
749                         ErrPrint("Failed to create a bundle\n");
750                         return DBOX_STATUS_ERROR_FAULT;
751                 }
752
753                 bundle_add(param, BUNDLE_SLAVE_SVC_OP_TYPE, APP_CONTROL_OPERATION_MAIN);
754                 bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_NAME, slave_name(slave));
755                 bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_SECURED, ((DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL) || slave->secured) ? "true" : "false");
756                 bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_ABI, slave->abi);
757                 bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_HW_ACCELERATION, slave->hw_acceleration);
758
759                 slave->pid = (pid_t)aul_launch_app(slave_pkgname(slave), param);
760
761                 bundle_free(param);
762
763                 switch (slave->pid) {
764                 case AUL_R_EHIDDENFORGUEST:     /**< App hidden for guest mode */
765                 case AUL_R_ENOLAUNCHPAD:        /**< no launchpad */
766                 case AUL_R_EILLACC:             /**< Illegal Access */
767                 case AUL_R_EINVAL:              /**< Invalid argument */
768                 case AUL_R_ENOINIT:             /**< AUL handler NOT initialized */
769                 case AUL_R_ERROR:               /**< General error */
770                         CRITICAL_LOG("Failed to launch a new slave %s (%d)\n", slave_name(slave), slave->pid);
771                         slave->pid = (pid_t)-1;
772                         /* Waiting app-launch result */
773                         break;
774                 case AUL_R_ECOMM:               /**< Comunication Error */
775                 case AUL_R_ETERMINATING:        /**< application terminating */
776                 case AUL_R_ECANCELED:           /**< Operation canceled */
777                 case AUL_R_ETIMEOUT:            /**< Timeout */
778                         CRITICAL_LOG("Try relaunch this soon %s (%d)\n", slave_name(slave), slave->pid);
779                         slave->relaunch_timer = ecore_timer_add(DYNAMICBOX_CONF_SLAVE_RELAUNCH_TIME, relaunch_timer_cb, slave);
780                         if (!slave->relaunch_timer) {
781                                 CRITICAL_LOG("Failed to register a relaunch timer (%s)\n", slave_name(slave));
782                                 slave->pid = (pid_t)-1;
783                                 return DBOX_STATUS_ERROR_FAULT;
784                         }
785                         /* Try again after a few secs later */
786                         break;
787                 case AUL_R_LOCAL:               /**< Launch by himself */
788                 case AUL_R_OK:                  /**< General success */
789                 default:
790                         DbgPrint("Slave %s is launched with %d as %s\n", slave_pkgname(slave), slave->pid, slave_name(slave));
791                         break;
792                 }
793
794                 slave->activate_timer = ecore_timer_add(DYNAMICBOX_CONF_SLAVE_ACTIVATE_TIME, activate_timer_cb, slave);
795                 if (!slave->activate_timer) {
796                         ErrPrint("Failed to register an activate timer\n");
797                 }
798         }
799
800         slave->state = SLAVE_REQUEST_TO_LAUNCH;
801         /*!
802          * \note
803          * Increase the refcnt of a slave,
804          * To prevent from making an orphan(slave).
805          */
806         (void)slave_ref(slave);
807
808         return DBOX_STATUS_ERROR_NONE;
809 }
810
811 HAPI int slave_give_more_ttl(struct slave_node *slave)
812 {
813         double delay;
814
815         if (!(DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL) && (!slave->secured || !slave->ttl_timer)) {
816                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
817         }
818
819         delay = DYNAMICBOX_CONF_SLAVE_TTL - ecore_timer_pending_get(slave->ttl_timer);
820         ecore_timer_delay(slave->ttl_timer, delay);
821         return DBOX_STATUS_ERROR_NONE;
822 }
823
824 HAPI int slave_freeze_ttl(struct slave_node *slave)
825 {
826         if (!(DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL) && (!slave->secured || !slave->ttl_timer)) {
827                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
828         }
829
830         ecore_timer_freeze(slave->ttl_timer);
831         return DBOX_STATUS_ERROR_NONE;
832 }
833
834 HAPI int slave_thaw_ttl(struct slave_node *slave)
835 {
836         double delay;
837
838         if (!(DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL) && (!slave->secured || !slave->ttl_timer)) {
839                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
840         }
841
842         ecore_timer_thaw(slave->ttl_timer);
843
844         delay = DYNAMICBOX_CONF_SLAVE_TTL - ecore_timer_pending_get(slave->ttl_timer);
845         ecore_timer_delay(slave->ttl_timer, delay);
846         return DBOX_STATUS_ERROR_NONE;
847 }
848
849 HAPI int slave_activated(struct slave_node *slave)
850 {
851         slave->state = SLAVE_RESUMED;
852
853         if (xmonitor_is_paused()) {
854                 slave_pause(slave);
855         }
856
857         if (((DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL) || slave->secured == 1) && DYNAMICBOX_CONF_SLAVE_TTL > 0.0f) {
858                 DbgPrint("Slave deactivation timer is added (%s - %lf)\n", slave_name(slave), DYNAMICBOX_CONF_SLAVE_TTL);
859                 slave->ttl_timer = ecore_timer_add(DYNAMICBOX_CONF_SLAVE_TTL, slave_ttl_cb, slave);
860                 if (!slave->ttl_timer) {
861                         ErrPrint("Failed to create a TTL timer\n");
862                 }
863         }
864
865         invoke_activate_cb(slave);
866
867         slave_set_reactivation(slave, 0);
868         slave_set_reactivate_instances(slave, 0);
869
870 #if defined(_USE_ECORE_TIME_GET)
871         slave->activated_at = ecore_time_get();
872 #else
873         if (gettimeofday(&slave->activated_at, NULL) < 0) {
874                 ErrPrint("Failed to get time of day: %s\n", strerror(errno));
875                 slave->activated_at.tv_sec = 0;
876                 slave->activated_at.tv_usec = 0;
877         }
878 #endif
879
880         if (slave->activate_timer) {
881                 ecore_timer_del(slave->activate_timer);
882                 slave->activate_timer = NULL;
883         }
884
885         if (slave->relaunch_timer) {
886                 ecore_timer_del(slave->relaunch_timer);
887                 slave->relaunch_timer = NULL;
888         }
889
890         slave_set_priority(slave, LOW_PRIORITY);
891         return DBOX_STATUS_ERROR_NONE;
892 }
893
894 static inline int invoke_deactivate_cb(struct slave_node *slave)
895 {
896         Eina_List *l;
897         Eina_List *n;
898         struct event *event;
899         int ret;
900         int reactivate = 0;
901
902         slave->in_event_process |= SLAVE_EVENT_PROCESS_DEACTIVATE;
903
904         EINA_LIST_FOREACH_SAFE(slave->event_deactivate_list, l, n, event) {
905                 if (event->deleted) {
906                         slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, event);
907                         DbgFree(event);
908                         continue;
909                 }
910
911                 ret = event->evt_cb(event->slave, event->cbdata);
912                 if (ret < 0 || event->deleted) {
913                         slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, event);
914                         DbgFree(event);
915                 }
916
917                 if (ret == SLAVE_NEED_TO_REACTIVATE) {
918                         reactivate++;
919                 }
920         }
921
922         slave->in_event_process &= ~SLAVE_EVENT_PROCESS_DEACTIVATE;
923
924         return reactivate;
925 }
926
927 HAPI struct slave_node *slave_deactivated(struct slave_node *slave)
928 {
929         int reactivate;
930
931         slave->pid = (pid_t)-1;
932         slave->state = SLAVE_TERMINATED;
933
934         if (slave->ttl_timer) {
935                 ecore_timer_del(slave->ttl_timer);
936                 slave->ttl_timer = NULL;
937         }
938
939         if (slave->activate_timer) {
940                 ecore_timer_del(slave->activate_timer);
941                 slave->activate_timer = NULL;
942         }
943
944         if (slave->relaunch_timer) {
945                 ecore_timer_del(slave->relaunch_timer);
946                 slave->relaunch_timer = NULL;
947         }
948
949         if (slave->terminate_timer) {
950                 ecore_timer_del(slave->terminate_timer);
951                 slave->terminate_timer = NULL;
952         }
953
954         /**
955          * @note
956          * FOR SAFETY
957          * If the deactivated event callback is called for package.c
958          * It can delete the instance if it has fault information
959          * then it also try to delete the slave object again.
960          * To prevent from unexpected slave object deletetion while handling callback,
961          * increase the refcnt of slave
962          * when it get back from callback, try to decrease the refcnt of slave
963          * At that time, we can delete slave safely.
964          */
965         slave_ref(slave);
966         reactivate = invoke_deactivate_cb(slave);
967         slave = slave_unref(slave);
968         if (!slave) {
969                 ErrPrint("Slave object is deleted\n");
970                 return slave;
971         }
972
973         slave = slave_unref(slave);
974         if (!slave) {
975                 DbgPrint("SLAVE object is destroyed\n");
976                 return slave;
977         }
978
979         if ((slave->ctrl_option & PROVIDER_CTRL_MANUAL_REACTIVATION) == PROVIDER_CTRL_MANUAL_REACTIVATION) {
980                 /*!
981                  * \note
982                  * In this case, the provider(Slave) should be reactivated by itself or user.
983                  * The master will not reactivate it automatically.
984                  */
985                 DbgPrint("Manual reactivate option is turned on\n");
986         } else if (reactivate && slave_need_to_reactivate(slave) && setting_oom_level() == OOM_TYPE_NORMAL) {
987                 int ret;
988
989                 DbgPrint("Need to reactivate a slave\n");
990                 ret = slave_activate(slave);
991                 if (ret < 0 && ret != DBOX_STATUS_ERROR_ALREADY) {
992                         ErrPrint("Failed to reactivate a slave\n");
993                 }
994         } else if (slave_loaded_instance(slave) == 0) {
995                 /*!
996                  * \note
997                  * If a slave has no more instances,
998                  * Destroy it
999                  */
1000                 slave = slave_unref(slave);
1001         }
1002
1003         return slave;
1004 }
1005
1006 HAPI struct slave_node *slave_deactivated_by_fault(struct slave_node *slave)
1007 {
1008         int ret;
1009         int reactivate = 1;
1010         int reactivate_instances = 1;
1011         int max_load;
1012
1013         if (g_conf.slave_max_load < 0) {
1014                 max_load = DYNAMICBOX_CONF_SLAVE_MAX_LOAD;
1015         } else {
1016                 max_load = g_conf.slave_max_load;
1017         }
1018
1019         if (!slave_is_activated(slave)) {
1020                 DbgPrint("Deactivating in progress\n");
1021                 if (slave_loaded_instance(slave) == 0) {
1022                         slave = slave_unref(slave);
1023                 }
1024
1025                 return slave;
1026         }
1027
1028         slave->fault_count++;
1029
1030         (void)fault_check_pkgs(slave);
1031
1032         if (slave_pid(slave) > 0) {
1033                 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
1034                 ret = aul_terminate_pid_async(slave_pid(slave));
1035                 if (ret < 0) {
1036                         ErrPrint("Terminate failed, pid %d\n", slave_pid(slave));
1037                 }
1038         }
1039
1040 #if defined(_USE_ECORE_TIME_GET)
1041         double faulted_at;
1042
1043         faulted_at = ecore_time_get();
1044         if (faulted_at - slave->activated_at < DYNAMICBOX_CONF_MINIMUM_REACTIVATION_TIME) {
1045                 slave->critical_fault_count++;
1046
1047                 if (!slave_loaded_instance(slave) || slave->critical_fault_count >= max_load) {
1048                         ErrPrint("Reactivation time is too fast and frequently occurred - Stop to auto reactivation\n");
1049                         reactivate = 0;
1050                         reactivate_instances = 0;
1051                         slave->critical_fault_count = 0;
1052                         /*!
1053                          * \note
1054                          * Fault callback can access the slave information.
1055                          */
1056                         if (invoke_fault_cb(slave) == NULL) {
1057                                 ErrPrint("Slave is deleted while processing fault handler\n");
1058                                 return NULL;
1059                         }
1060                 } else {
1061                         slave->critical_fault_count = 0;
1062                 }
1063         }
1064 #else
1065         struct timeval faulted_at;
1066
1067         if (gettimeofday(&faulted_at, NULL) == 0) {
1068                 struct timeval rtv;
1069
1070                 timersub(&faulted_at, &slave->activated_at, &rtv);
1071                 if (rtv.tv_sec < DYNAMICBOX_CONF_MINIMUM_REACTIVATION_TIME) {
1072                         slave->critical_fault_count++;
1073                         if (!slave_loaded_instance(slave) || slave->critical_fault_count >= max_load) {
1074                                 ErrPrint("Reactivation time is too fast and frequently occurred - Stop to auto reactivation\n");
1075                                 reactivate = 0;
1076                                 reactivate_instances = 0;
1077                                 slave->critical_fault_count = 0;
1078                                 /*!
1079                                  * \note
1080                                  * Fault callback can access the slave information.
1081                                  */
1082                                 if (invoke_fault_cb(slave) == NULL) {
1083                                         ErrPrint("Slave is deleted while processing fault handler\n");
1084                                         return NULL;
1085                                 }
1086                         }
1087                 } else {
1088                         slave->critical_fault_count = 0;
1089                 }
1090         } else {
1091                 ErrPrint("Failed to get time of day: %s\n", strerror(errno));
1092         }
1093 #endif
1094
1095         slave_set_reactivation(slave, reactivate);
1096         slave_set_reactivate_instances(slave, reactivate_instances);
1097
1098         slave = slave_deactivated(slave);
1099         return slave;
1100 }
1101
1102 HAPI const int const slave_is_activated(struct slave_node *slave)
1103 {
1104         switch (slave->state) {
1105         case SLAVE_REQUEST_TO_TERMINATE:
1106         case SLAVE_TERMINATED:
1107                 return 0;
1108         case SLAVE_REQUEST_TO_DISCONNECT:
1109                 /* This case should be treated as an activated state.
1110                  * To send the last request to the provider.
1111                  */
1112         case SLAVE_REQUEST_TO_LAUNCH:
1113                 /* Not yet launched. but the slave incurred an unexpected error */
1114         case SLAVE_REQUEST_TO_PAUSE:
1115         case SLAVE_REQUEST_TO_RESUME:
1116         case SLAVE_PAUSED:
1117         case SLAVE_RESUMED:
1118                 return 1;
1119         default:
1120                 return slave->pid != (pid_t)-1;
1121         }
1122
1123         /* Could not be reach to here */
1124         return 0;
1125 }
1126
1127 HAPI int slave_event_callback_add(struct slave_node *slave, enum slave_event event, int (*cb)(struct slave_node *, void *), void *data)
1128 {
1129         struct event *ev;
1130
1131         ev = calloc(1, sizeof(*ev));
1132         if (!ev) {
1133                 ErrPrint("Heap: %s\n", strerror(errno));
1134                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1135         }
1136
1137         ev->slave = slave;
1138         ev->cbdata = data;
1139         ev->evt_cb = cb;
1140
1141         /*!
1142          * \note
1143          * Use the eina_list_prepend API.
1144          * To keep the sequence of a callback invocation.
1145          *
1146          * Here is an example sequence.
1147          *
1148          * slave_event_callback_add(CALLBACK_01);
1149          * slave_event_callback_add(CALLBACK_02);
1150          * slave_event_callback_add(CALLBACK_03);
1151          *
1152          * Then the invoke_event_callback function will call the CALLBACKS as below sequence
1153          *
1154          * invoke_CALLBACK_03
1155          * invoke_CALLBACK_02
1156          * invoke_CALLBACK_01
1157          */
1158
1159         switch (event) {
1160         case SLAVE_EVENT_ACTIVATE:
1161                 slave->event_activate_list = eina_list_prepend(slave->event_activate_list, ev);
1162                 break;
1163         case SLAVE_EVENT_DELETE:
1164                 slave->event_delete_list = eina_list_prepend(slave->event_delete_list, ev);
1165                 break;
1166         case SLAVE_EVENT_DEACTIVATE:
1167                 slave->event_deactivate_list = eina_list_prepend(slave->event_deactivate_list, ev);
1168                 break;
1169         case SLAVE_EVENT_PAUSE:
1170                 slave->event_pause_list = eina_list_prepend(slave->event_pause_list, ev);
1171                 break;
1172         case SLAVE_EVENT_RESUME:
1173                 slave->event_resume_list = eina_list_prepend(slave->event_resume_list, ev);
1174                 break;
1175         case SLAVE_EVENT_FAULT:
1176                 slave->event_fault_list = eina_list_prepend(slave->event_fault_list, ev);
1177                 break;
1178         default:
1179                 DbgFree(ev);
1180                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1181         }
1182
1183         return DBOX_STATUS_ERROR_NONE;
1184 }
1185
1186 HAPI int slave_event_callback_del(struct slave_node *slave, enum slave_event event, int (*cb)(struct slave_node *, void *), void *data)
1187 {
1188         struct event *ev;
1189         Eina_List *l;
1190         Eina_List *n;
1191
1192         switch (event) {
1193         case SLAVE_EVENT_DEACTIVATE:
1194                 EINA_LIST_FOREACH_SAFE(slave->event_deactivate_list, l, n, ev) {
1195                         if (ev->evt_cb == cb && ev->cbdata == data) {
1196                                 if (slave->in_event_process & SLAVE_EVENT_PROCESS_DEACTIVATE) {
1197                                         ev->deleted = 1;
1198                                 } else {
1199                                         slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, ev);
1200                                         DbgFree(ev);
1201                                 }
1202                                 return DBOX_STATUS_ERROR_NONE;
1203                         }
1204                 }
1205                 break;
1206         case SLAVE_EVENT_DELETE:
1207                 EINA_LIST_FOREACH_SAFE(slave->event_delete_list, l, n, ev) {
1208                         if (ev->evt_cb == cb && ev->cbdata == data) {
1209                                 if (slave->in_event_process & SLAVE_EVENT_PROCESS_DELETE) {
1210                                         ev->deleted = 1;
1211                                 } else {
1212                                         slave->event_delete_list = eina_list_remove(slave->event_delete_list, ev);
1213                                         DbgFree(ev);
1214                                 }
1215                                 return DBOX_STATUS_ERROR_NONE;
1216                         }
1217                 }
1218                 break;
1219         case SLAVE_EVENT_ACTIVATE:
1220                 EINA_LIST_FOREACH_SAFE(slave->event_activate_list, l, n, ev) {
1221                         if (ev->evt_cb == cb && ev->cbdata == data) {
1222                                 if (slave->in_event_process & SLAVE_EVENT_PROCESS_ACTIVATE) {
1223                                         ev->deleted = 1;
1224                                 } else {
1225                                         slave->event_activate_list = eina_list_remove(slave->event_activate_list, ev);
1226                                         DbgFree(ev);
1227                                 }
1228                                 return DBOX_STATUS_ERROR_NONE;
1229                         }
1230                 }
1231                 break;
1232         case SLAVE_EVENT_PAUSE:
1233                 EINA_LIST_FOREACH_SAFE(slave->event_pause_list, l, n, ev) {
1234                         if (ev->evt_cb == cb && ev->cbdata == data) {
1235                                 if (slave->in_event_process & SLAVE_EVENT_PROCESS_PAUSE) {
1236                                         ev->deleted = 1;
1237                                 } else {
1238                                         slave->event_pause_list = eina_list_remove(slave->event_pause_list, ev);
1239                                         DbgFree(ev);
1240                                 }
1241                                 return DBOX_STATUS_ERROR_NONE;
1242                         }
1243                 }
1244                 break;
1245         case SLAVE_EVENT_RESUME:
1246                 EINA_LIST_FOREACH_SAFE(slave->event_resume_list, l, n, ev) {
1247                         if (ev->evt_cb == cb && ev->cbdata == data) {
1248                                 if (slave->in_event_process & SLAVE_EVENT_PROCESS_RESUME) {
1249                                         ev->deleted = 1;
1250                                 } else {
1251                                         slave->event_resume_list = eina_list_remove(slave->event_resume_list, ev);
1252                                         DbgFree(ev);
1253                                 }
1254                                 return DBOX_STATUS_ERROR_NONE;
1255                         }
1256                 }
1257                 break;
1258         case SLAVE_EVENT_FAULT:
1259                 EINA_LIST_FOREACH_SAFE(slave->event_fault_list, l, n, ev) {
1260                         if (ev->evt_cb == cb && ev->cbdata == data) {
1261                                 if (slave->in_event_process & SLAVE_EVENT_PROCESS_FAULT) {
1262                                         ev->deleted = 1;
1263                                 } else {
1264                                         slave->event_fault_list = eina_list_remove(slave->event_fault_list, ev);
1265                                         DbgFree(ev);
1266                                 }
1267                                 return DBOX_STATUS_ERROR_NONE;
1268                         }
1269                 }
1270                 break;
1271         default:
1272                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1273         }
1274
1275         return DBOX_STATUS_ERROR_NOT_EXIST;
1276 }
1277
1278 HAPI int slave_set_data(struct slave_node *slave, const char *tag, void *data)
1279 {
1280         struct priv_data *priv;
1281
1282         priv = calloc(1, sizeof(*priv));
1283         if (!priv) {
1284                 ErrPrint("Heap: %s\n", strerror(errno));
1285                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1286         }
1287
1288         priv->tag = strdup(tag);
1289         if (!priv->tag) {
1290                 ErrPrint("Heap: %s\n", strerror(errno));
1291                 DbgFree(priv);
1292                 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1293         }
1294
1295         priv->data = data;
1296         slave->data_list = eina_list_append(slave->data_list, priv);
1297         return DBOX_STATUS_ERROR_NONE;
1298 }
1299
1300 HAPI void *slave_del_data(struct slave_node *slave, const char *tag)
1301 {
1302         struct priv_data *priv;
1303         void *data;
1304         Eina_List *l;
1305         Eina_List *n;
1306
1307         EINA_LIST_FOREACH_SAFE(slave->data_list, l, n, priv) {
1308                 if (!strcmp(priv->tag, tag)) {
1309                         slave->data_list = eina_list_remove(slave->data_list, priv);
1310
1311                         data = priv->data;
1312                         DbgFree(priv->tag);
1313                         DbgFree(priv);
1314                         return data;
1315                 }
1316         }
1317
1318         return NULL;
1319 }
1320
1321 HAPI void *slave_data(struct slave_node *slave, const char *tag)
1322 {
1323         struct priv_data *priv;
1324         Eina_List *l;
1325
1326         EINA_LIST_FOREACH(slave->data_list, l, priv) {
1327                 if (!strcmp(priv->tag, tag)) {
1328                         return priv->data;
1329                 }
1330         }
1331
1332         return NULL;
1333 }
1334
1335 HAPI struct slave_node *slave_find_by_pid(pid_t pid)
1336 {
1337         Eina_List *l;
1338         struct slave_node *slave;
1339
1340         EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1341                 if (slave_pid(slave) == pid) {
1342                         return slave;
1343                 }
1344         }
1345
1346         return NULL;
1347 }
1348
1349 HAPI struct slave_node *slave_find_by_name(const char *name)
1350 {
1351         Eina_List *l;
1352         struct slave_node *slave;
1353
1354         EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1355                 if (!strcmp(slave_name(slave), name)) {
1356                         return slave;
1357                 }
1358         }
1359
1360         return NULL;
1361 }
1362
1363 HAPI struct slave_node *slave_find_available(const char *slave_pkgname, const char *abi, int secured, int network, const char *hw_acceleration)
1364 {
1365         Eina_List *l;
1366         struct slave_node *slave;
1367
1368         EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1369                 if (slave->secured != secured) {
1370                         continue;
1371                 }
1372
1373                 if ((slave->state == SLAVE_REQUEST_TO_TERMINATE || slave->state == SLAVE_REQUEST_TO_DISCONNECT) && slave->loaded_instance == 0) {
1374                         /*!
1375                          * \note
1376                          * If a slave is in request_to_terminate state,
1377                          * and the slave object has no more intances,
1378                          * the slave object will be deleted soon.
1379                          * so we cannot reuse it.
1380                          *
1381                          * This object is not usable.
1382                          */
1383                         continue;
1384                 }
1385
1386                 if (strcasecmp(slave->abi, abi)) {
1387                         continue;
1388                 }
1389
1390                 if (strcasecmp(slave->pkgname, slave_pkgname)) {
1391                         continue;
1392                 }
1393
1394                 if (slave->hw_acceleration != hw_acceleration) {
1395                         if (!slave->hw_acceleration || !hw_acceleration || strcasecmp(slave->hw_acceleration, hw_acceleration)) {
1396                                 continue;
1397                         }
1398                 }
1399
1400                 if (slave->secured) {
1401                         if (slave->loaded_package == 0) {
1402                                 DbgPrint("Found secured slave - has no instances (%s)\n", slave_name(slave));
1403                                 return slave;
1404                         }
1405                 } else if (slave->network == network) {
1406                         DbgPrint("slave[%s] loaded_package[%d] net: [%d]\n", slave_name(slave), slave->loaded_package, slave->network);
1407                         if (!strcasecmp(abi, DYNAMICBOX_CONF_DEFAULT_ABI)) {
1408                                 int max_load;
1409                                 if (g_conf.slave_max_load < 0) {
1410                                         max_load = DYNAMICBOX_CONF_SLAVE_MAX_LOAD;
1411                                 } else {
1412                                         max_load = g_conf.slave_max_load;
1413                                 }
1414
1415                                 if (slave->loaded_package < max_load) {
1416                                         return slave;
1417                                 }
1418                         } else {
1419                                 return slave;
1420                         }
1421                 }
1422         }
1423
1424         return NULL;
1425 }
1426
1427 HAPI struct slave_node *slave_find_by_pkgname(const char *pkgname)
1428 {
1429         Eina_List *l;
1430         struct slave_node *slave;
1431
1432         EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1433                 if (!strcmp(slave_pkgname(slave), pkgname)) {
1434                         if (slave_pid(slave) == (pid_t)-1) {
1435                                 return slave;
1436                         }
1437                 }
1438         }
1439
1440         return NULL;
1441 }
1442
1443 HAPI struct slave_node *slave_find_by_rpc_handle(int handle)
1444 {
1445         Eina_List *l;
1446         struct slave_node *slave;
1447
1448         if (handle <= 0) {
1449                 ErrPrint("Invalid RPC handle: %d\n", handle);
1450                 return NULL;
1451         }
1452
1453         EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1454                 if (slave_rpc_handle(slave) == handle) {
1455                         return slave;
1456                 }
1457         }
1458
1459         /* Not found */
1460         return NULL;
1461 }
1462
1463 HAPI char *slave_package_name(const char *abi, const char *lbid)
1464 {
1465         char *s_pkgname;
1466         const char *tmp;
1467
1468         tmp = abi_find_slave(abi);
1469         if (!tmp) {
1470                 ErrPrint("Failed to find a proper pkgname of a slave\n");
1471                 return NULL;
1472         }
1473
1474         s_pkgname = util_replace_string(tmp, DYNAMICBOX_CONF_REPLACE_TAG_APPID, lbid);
1475         if (!s_pkgname) {
1476                 DbgPrint("Failed to get replaced string\n");
1477                 s_pkgname = strdup(tmp);
1478                 if (!s_pkgname) {
1479                         ErrPrint("Heap: %s\n", strerror(errno));
1480                         return NULL;
1481                 }
1482         }
1483
1484         return s_pkgname;
1485 }
1486
1487 HAPI void slave_load_package(struct slave_node *slave)
1488 {
1489         slave->loaded_package++;
1490 }
1491
1492 HAPI void slave_unload_package(struct slave_node *slave)
1493 {
1494         if (!slave || slave->loaded_package == 0) {
1495                 ErrPrint("Slave loaded package is not correct\n");
1496                 return;
1497         }
1498
1499         slave->loaded_package--;
1500 }
1501
1502 HAPI void slave_load_instance(struct slave_node *slave)
1503 {
1504         slave->loaded_instance++;
1505         DbgPrint("Instance: (%d)%d\n", slave_pid(slave), slave->loaded_instance);
1506 }
1507
1508 HAPI int const slave_loaded_instance(struct slave_node *slave)
1509 {
1510         return slave->loaded_instance;
1511 }
1512
1513 HAPI int const slave_loaded_package(struct slave_node *slave)
1514 {
1515         return slave->loaded_package;
1516 }
1517
1518 HAPI struct slave_node *slave_unload_instance(struct slave_node *slave)
1519 {
1520         if (!slave || slave->loaded_instance == 0) {
1521                 ErrPrint("Slave loaded instance is not correct\n");
1522                 return slave;
1523         }
1524
1525         slave->loaded_instance--;
1526         DbgPrint("Instance: (%d)%d\n", slave_pid(slave), slave->loaded_instance);
1527         if (slave->loaded_instance == 0 && slave_is_activated(slave)) {
1528                 slave_set_reactivation(slave, 0);
1529                 slave_set_reactivate_instances(slave, 0);
1530
1531                 slave = slave_deactivate(slave, 0);
1532         }
1533
1534         return slave;
1535 }
1536
1537 HAPI const int const slave_is_secured(const struct slave_node *slave)
1538 {
1539         return slave->secured;
1540 }
1541
1542 HAPI const char * const slave_name(const struct slave_node *slave)
1543 {
1544         return slave->name;
1545 }
1546
1547 HAPI const char * const slave_abi(const struct slave_node *slave)
1548 {
1549         return slave->abi;
1550 }
1551
1552 HAPI const pid_t const slave_pid(const struct slave_node *slave)
1553 {
1554         return slave->pid;
1555 }
1556
1557 HAPI int slave_set_pid(struct slave_node *slave, pid_t pid)
1558 {
1559         if (!slave) {
1560                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1561         }
1562
1563         DbgPrint("Slave PID is updated to %d from %d\n", pid, slave_pid(slave));
1564
1565         slave->pid = pid;
1566         return DBOX_STATUS_ERROR_NONE;
1567 }
1568
1569 static inline void invoke_resumed_cb(struct slave_node *slave)
1570 {
1571         Eina_List *l;
1572         Eina_List *n;
1573         struct event *event;
1574
1575         slave->in_event_process |= SLAVE_EVENT_PROCESS_RESUME;
1576         EINA_LIST_FOREACH_SAFE(slave->event_resume_list, l, n, event) {
1577                 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
1578                         slave->event_resume_list = eina_list_remove(slave->event_resume_list, event);
1579                         DbgFree(event);
1580                 }
1581         }
1582         slave->in_event_process &= ~SLAVE_EVENT_PROCESS_RESUME;
1583 }
1584
1585 static void resume_cb(struct slave_node *slave, const struct packet *packet, void *data)
1586 {
1587         int ret;
1588
1589         if (slave->state == SLAVE_REQUEST_TO_TERMINATE || slave->state == SLAVE_REQUEST_TO_DISCONNECT) {
1590                 DbgPrint("Slave is terminating now. ignore resume result\n");
1591                 return;
1592         }
1593
1594         if (!packet) {
1595                 ErrPrint("Failed to change the state of the slave\n");
1596                 slave->state = SLAVE_PAUSED;
1597                 return;
1598         }
1599
1600         if (packet_get(packet, "i", &ret) != 1) {
1601                 ErrPrint("Invalid parameter\n");
1602                 return;
1603         }
1604
1605         if (ret == 0) {
1606                 slave->state = SLAVE_RESUMED;
1607                 slave_rpc_ping_thaw(slave);
1608                 invoke_resumed_cb(slave);
1609         }
1610 }
1611
1612 static inline void invoke_paused_cb(struct slave_node *slave)
1613 {
1614         Eina_List *l;
1615         Eina_List *n;
1616         struct event *event;
1617
1618         slave->in_event_process |= SLAVE_EVENT_PROCESS_PAUSE;
1619         EINA_LIST_FOREACH_SAFE(slave->event_pause_list, l, n, event) {
1620                 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
1621                         slave->event_pause_list = eina_list_remove(slave->event_pause_list, event);
1622                         DbgFree(event);
1623                 }
1624         }
1625         slave->in_event_process &= ~SLAVE_EVENT_PROCESS_PAUSE;
1626 }
1627
1628 static void pause_cb(struct slave_node *slave, const struct packet *packet, void *data)
1629 {
1630         int ret;
1631
1632         if (slave->state == SLAVE_REQUEST_TO_TERMINATE || slave->state == SLAVE_REQUEST_TO_DISCONNECT) {
1633                 DbgPrint("Slave is terminating now. ignore pause result\n");
1634                 return;
1635         }
1636
1637         if (!packet) {
1638                 ErrPrint("Failed to change the state of the slave\n");
1639                 slave->state = SLAVE_RESUMED;
1640                 return;
1641         }
1642
1643         if (packet_get(packet, "i", &ret) != 1) {
1644                 ErrPrint("Invalid parameter\n");
1645                 return;
1646         }
1647
1648         if (ret == 0) {
1649                 slave->state = SLAVE_PAUSED;
1650                 slave_rpc_ping_freeze(slave);
1651                 invoke_paused_cb(slave);
1652         }
1653 }
1654
1655 HAPI int slave_resume(struct slave_node *slave)
1656 {
1657         double timestamp;
1658         struct packet *packet;
1659         unsigned int cmd = CMD_RESUME;
1660
1661         switch (slave->state) {
1662         case SLAVE_REQUEST_TO_DISCONNECT:
1663         case SLAVE_REQUEST_TO_LAUNCH:
1664         case SLAVE_REQUEST_TO_TERMINATE:
1665         case SLAVE_TERMINATED:
1666                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1667         case SLAVE_RESUMED:
1668         case SLAVE_REQUEST_TO_RESUME:
1669                 return DBOX_STATUS_ERROR_NONE;
1670         default:
1671                 break;
1672         }
1673
1674         timestamp = util_timestamp();
1675
1676         packet = packet_create((const char *)&cmd, "d", timestamp);
1677         if (!packet) {
1678                 ErrPrint("Failed to prepare param\n");
1679                 return DBOX_STATUS_ERROR_FAULT;
1680         }
1681
1682         slave->state = SLAVE_REQUEST_TO_RESUME;
1683         return slave_rpc_async_request(slave, NULL, packet, resume_cb, NULL, 0);
1684 }
1685
1686 HAPI int slave_pause(struct slave_node *slave)
1687 {
1688         double timestamp;
1689         struct packet *packet;
1690         unsigned int cmd = CMD_PAUSE;
1691
1692         switch (slave->state) {
1693         case SLAVE_REQUEST_TO_DISCONNECT:
1694         case SLAVE_REQUEST_TO_LAUNCH:
1695         case SLAVE_REQUEST_TO_TERMINATE:
1696         case SLAVE_TERMINATED:
1697                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1698         case SLAVE_PAUSED:
1699         case SLAVE_REQUEST_TO_PAUSE:
1700                 return DBOX_STATUS_ERROR_NONE;
1701         default:
1702                 break;
1703         }
1704
1705         timestamp = util_timestamp();
1706
1707         packet = packet_create((const char *)&cmd, "d", timestamp);
1708         if (!packet) {
1709                 ErrPrint("Failed to prepare param\n");
1710                 return DBOX_STATUS_ERROR_FAULT;
1711         }
1712
1713         slave->state = SLAVE_REQUEST_TO_PAUSE;
1714         return slave_rpc_async_request(slave, NULL, packet, pause_cb, NULL, 0);
1715 }
1716
1717 HAPI const char *slave_pkgname(const struct slave_node *slave)
1718 {
1719         return slave ? slave->pkgname : NULL;
1720 }
1721
1722 HAPI enum slave_state slave_state(const struct slave_node *slave)
1723 {
1724         return slave ? slave->state : SLAVE_ERROR;
1725 }
1726
1727 HAPI const char *slave_state_string(const struct slave_node *slave)
1728 {
1729         switch (slave->state) {
1730         case SLAVE_REQUEST_TO_DISCONNECT:
1731                 return "RequestToDisconnect";
1732         case SLAVE_REQUEST_TO_LAUNCH:
1733                 return "RequestToLaunch";
1734         case SLAVE_REQUEST_TO_TERMINATE:
1735                 return "RequestToTerminate";
1736         case SLAVE_TERMINATED:
1737                 return "Terminated";
1738         case SLAVE_REQUEST_TO_PAUSE:
1739                 return "RequestToPause";
1740         case SLAVE_REQUEST_TO_RESUME:
1741                 return "RequestToResume";
1742         case SLAVE_PAUSED:
1743                 return "Paused";
1744         case SLAVE_RESUMED:
1745                 return "Resumed";
1746         case SLAVE_ERROR:
1747                 return "Error";
1748         default:
1749                 break;
1750         }
1751
1752         return "Unknown";
1753 }
1754
1755 HAPI const void *slave_list(void)
1756 {
1757         return s_info.slave_list;
1758 }
1759
1760 HAPI int const slave_fault_count(const struct slave_node *slave)
1761 {
1762         return slave->fault_count;
1763 }
1764
1765 HAPI double const slave_ttl(const struct slave_node *slave)
1766 {
1767         if (!slave->ttl_timer) {
1768                 return 0.0f;
1769         }
1770
1771         return ecore_timer_pending_get(slave->ttl_timer);
1772 }
1773
1774 HAPI void slave_set_reactivate_instances(struct slave_node *slave, int reactivate)
1775 {
1776         slave->reactivate_instances = reactivate;
1777 }
1778
1779 HAPI int slave_need_to_reactivate_instances(struct slave_node *slave)
1780 {
1781         return slave->reactivate_instances;
1782 }
1783
1784 HAPI void slave_set_reactivation(struct slave_node *slave, int flag)
1785 {
1786         slave->reactivate_slave = flag;
1787 }
1788
1789 HAPI int slave_need_to_reactivate(struct slave_node *slave)
1790 {
1791         return slave->reactivate_slave;
1792 }
1793
1794 HAPI int slave_network(const struct slave_node *slave)
1795 {
1796         return slave->network;
1797 }
1798
1799 HAPI void slave_set_network(struct slave_node *slave, int network)
1800 {
1801         slave->network = network;
1802 }
1803
1804 HAPI int slave_deactivate_all(int reactivate, int reactivate_instances, int no_timer)
1805 {
1806         Eina_List *l;
1807         Eina_List *n;
1808         struct slave_node *slave;
1809         int cnt = 0;
1810
1811         s_info.deactivate_all_refcnt++;
1812         if (s_info.deactivate_all_refcnt > 1) {
1813                 return 0;
1814         }
1815         DbgPrint("Deactivate all\n");
1816
1817         EINA_LIST_FOREACH_SAFE(s_info.slave_list, l, n, slave) {
1818                 if (slave_is_activated(slave)) {
1819                         slave_set_reactivate_instances(slave, reactivate_instances);
1820                         slave_set_reactivation(slave, reactivate);
1821
1822                         if (!slave_deactivate(slave, no_timer)) {
1823                                 s_info.slave_list = eina_list_remove(s_info.slave_list, slave);
1824                         }
1825                 }
1826
1827                 cnt++;
1828         }
1829
1830         return cnt;
1831 }
1832
1833 HAPI int slave_activate_all(void)
1834 {
1835         Eina_List *l;
1836         struct slave_node *slave;
1837         int cnt = 0;
1838
1839         s_info.deactivate_all_refcnt--;
1840         if (s_info.deactivate_all_refcnt > 0) {
1841                 return 0;
1842         }
1843         DbgPrint("Activate all\n");
1844
1845         EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1846                 slave_activate(slave);
1847                 cnt++;
1848         }
1849
1850         return cnt;
1851 }
1852
1853 HAPI void slave_set_control_option(struct slave_node *slave, int ctrl)
1854 {
1855         slave->ctrl_option = ctrl;
1856 }
1857
1858 HAPI int slave_control_option(struct slave_node *slave)
1859 {
1860         return slave->ctrl_option;
1861 }
1862
1863 HAPI int slave_set_priority(struct slave_node *slave, int priority)
1864 {
1865         pid_t pid;
1866
1867         if (!slave) {
1868                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1869         }
1870
1871         pid = slave_pid(slave);
1872         if (pid < 0) {
1873                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1874         }
1875
1876         if (setpriority(PRIO_PROCESS, slave_pid(slave), priority) < 0) {
1877                 ErrPrint("setpriority: %s\n", strerror(errno));
1878                 return DBOX_STATUS_ERROR_FAULT;
1879         }
1880
1881         return DBOX_STATUS_ERROR_NONE;
1882 }
1883
1884 HAPI int slave_priority(struct slave_node *slave)
1885 {
1886         pid_t pid;
1887         int priority;
1888
1889         if (!slave) {
1890                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1891         }
1892
1893         pid = slave_pid(slave);
1894         if (pid < 0) {
1895                 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1896         }
1897
1898         priority = getpriority(PRIO_PROCESS, pid);
1899         if (priority < 0) {
1900                 ErrPrint("getpriority: %s\n", strerror(errno));
1901                 return DBOX_STATUS_ERROR_FAULT;
1902         }
1903
1904         return priority;
1905 }
1906
1907 /* End of a file */