2 * Copyright 2013 Samsung Electronics Co., Ltd
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
8 * http://floralicense.org/license/
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.
18 #include <string.h> /* strerror */
19 #include <errno.h> /* errno */
20 #include <unistd.h> /* pid_t */
21 #include <stdlib.h> /* free */
29 #include <aul.h> /* aul_launch_app */
34 #include <livebox-errno.h>
36 #include "critical_log.h"
37 #include "slave_life.h"
38 #include "slave_rpc.h"
39 #include "client_life.h"
40 #include "fault_manager.h"
54 int secured; /* Only A package(livebox) is loaded for security requirements */
57 int critical_fault_count;
58 enum slave_state state;
64 int reactivate_instances;
70 SLAVE_EVENT_PROCESS_IDLE = 0x00,
71 SLAVE_EVENT_PROCESS_ACTIVATE = 0x01,
72 SLAVE_EVENT_PROCESS_DEACTIVATE = 0x02,
73 SLAVE_EVENT_PROCESS_DELETE = 0x04,
74 SLAVE_EVENT_PROCESS_FAULT = 0x08,
75 SLAVE_EVENT_PROCESS_PAUSE = 0x10,
76 SLAVE_EVENT_PROCESS_RESUME = 0x20
78 Eina_List *event_activate_list;
79 Eina_List *event_deactivate_list;
80 Eina_List *event_delete_list;
81 Eina_List *event_fault_list;
82 Eina_List *event_pause_list;
83 Eina_List *event_resume_list;
87 Ecore_Timer *ttl_timer; /* Time to live */
88 Ecore_Timer *activate_timer; /* Waiting hello packet for this time */
89 Ecore_Timer *relaunch_timer; /* Try to relaunch service app */
92 #if defined(_USE_ECORE_TIME_GET)
95 struct timeval activated_at;
100 struct slave_node *slave;
102 int (*evt_cb)(struct slave_node *, void *);
113 Eina_List *slave_list;
114 int deactivate_all_refcnt;
117 .deactivate_all_refcnt = 0,
120 static Eina_Bool slave_ttl_cb(void *data)
122 struct slave_node *slave = (struct slave_node *)data;
126 * ttl_timer must has to be set to NULL before deactivate the slave
127 * It will be used for making decision of the expired TTL timer or the fault of a livebox.
129 slave->ttl_timer = NULL;
131 slave_set_reactivation(slave, 0);
132 slave_set_reactivate_instances(slave, 1);
134 slave = slave_deactivate(slave);
136 DbgPrint("Slave is deleted\n");
139 /*! To recover all instances state it is activated again */
140 return ECORE_CALLBACK_CANCEL;
143 static inline int xmonitor_pause_cb(void *data)
146 return LB_STATUS_SUCCESS;
149 static inline int xmonitor_resume_cb(void *data)
152 return LB_STATUS_SUCCESS;
155 static inline struct slave_node *create_slave_node(const char *name, int is_secured, const char *abi, const char *pkgname, int network)
157 struct slave_node *slave;
159 slave = calloc(1, sizeof(*slave));
161 ErrPrint("Heap: %s\n", strerror(errno));
165 slave->name = strdup(name);
167 ErrPrint("Heap: %s\n", strerror(errno));
172 slave->abi = strdup(abi);
174 ErrPrint("Heap: %s\n", strerror(errno));
175 DbgFree(slave->name);
180 slave->pkgname = strdup(pkgname);
181 if (!slave->pkgname) {
182 ErrPrint("Heap: %s\n", strerror(errno));
184 DbgFree(slave->name);
189 slave->secured = is_secured;
190 slave->pid = (pid_t)-1;
191 slave->state = SLAVE_TERMINATED;
192 slave->network = network;
193 slave->relaunch_count = SLAVE_RELAUNCH_COUNT;
195 xmonitor_add_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
196 xmonitor_add_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
198 s_info.slave_list = eina_list_append(s_info.slave_list, slave);
202 static inline void invoke_delete_cb(struct slave_node *slave)
208 slave->in_event_process |= SLAVE_EVENT_PROCESS_DELETE;
209 EINA_LIST_FOREACH_SAFE(slave->event_delete_list, l, n, event) {
210 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
211 slave->event_delete_list = eina_list_remove(slave->event_delete_list, event);
215 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_DELETE;
218 static inline void destroy_slave_node(struct slave_node *slave)
221 struct priv_data *priv;
223 if (slave_pid(slave) != (pid_t)-1) {
224 ErrPrint("Slave is not deactivated\n");
228 xmonitor_del_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
229 xmonitor_del_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
231 invoke_delete_cb(slave);
232 slave_rpc_fini(slave); /*!< Finalize the RPC after handling all delete callbacks */
234 EINA_LIST_FREE(slave->event_delete_list, event) {
238 EINA_LIST_FREE(slave->event_activate_list, event) {
242 EINA_LIST_FREE(slave->event_deactivate_list, event) {
246 EINA_LIST_FREE(slave->event_fault_list, event) {
250 EINA_LIST_FREE(slave->data_list, priv) {
255 s_info.slave_list = eina_list_remove(s_info.slave_list, slave);
257 if (slave->ttl_timer) {
258 ecore_timer_del(slave->ttl_timer);
261 if (slave->activate_timer) {
262 ecore_timer_del(slave->activate_timer);
265 if (slave->relaunch_timer) {
266 ecore_timer_del(slave->relaunch_timer);
270 DbgFree(slave->name);
271 DbgFree(slave->pkgname);
276 static inline struct slave_node *find_slave(const char *name)
278 struct slave_node *slave;
281 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
282 if (!strcmp(slave->name, name)) {
290 HAPI int slave_expired_ttl(struct slave_node *slave)
296 if (!slave->secured) {
300 return !!slave->ttl_timer;
303 HAPI struct slave_node *slave_ref(struct slave_node *slave)
313 HAPI struct slave_node *slave_unref(struct slave_node *slave)
319 if (slave->refcnt == 0) {
320 ErrPrint("Slave refcnt is not valid\n");
325 if (slave->refcnt == 0) {
326 destroy_slave_node(slave);
333 HAPI const int const slave_refcnt(struct slave_node *slave)
335 return slave->refcnt;
338 HAPI struct slave_node *slave_create(const char *name, int is_secured, const char *abi, const char *pkgname, int network)
340 struct slave_node *slave;
342 slave = find_slave(name);
344 if (slave->secured != is_secured) {
345 ErrPrint("Exists slave and creating slave's security flag is not matched\n");
350 slave = create_slave_node(name, is_secured, abi, pkgname, network);
356 slave_rpc_init(slave);
363 * Before destroying slave object,
364 * you should check the RPC(slave_async_XXX) state and Private data field (slave_set_data)
366 HAPI void slave_destroy(struct slave_node *slave)
371 static inline void invoke_fault_cb(struct slave_node *slave)
377 EINA_LIST_FOREACH_SAFE(slave->event_fault_list, l, n, event) {
378 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
379 slave->event_fault_list = eina_list_remove(slave->event_fault_list, event);
385 static inline void invoke_activate_cb(struct slave_node *slave)
391 slave->in_event_process |= SLAVE_EVENT_PROCESS_ACTIVATE;
392 EINA_LIST_FOREACH_SAFE(slave->event_activate_list, l, n, event) {
393 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
394 slave->event_activate_list = eina_list_remove(slave->event_activate_list, event);
398 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_ACTIVATE;
401 static Eina_Bool activate_timer_cb(void *data)
403 struct slave_node *slave = data;
405 if (slave->relaunch_timer) {
406 ecore_timer_del(slave->relaunch_timer);
407 slave->relaunch_timer = NULL;
410 slave->fault_count++;
411 invoke_fault_cb(slave);
413 slave_set_reactivation(slave, 0);
414 slave_set_reactivate_instances(slave, 0);
416 slave->activate_timer = NULL;
417 if (slave_pid(slave) > 0) {
419 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
420 ret = aul_terminate_pid(slave_pid(slave));
422 ErrPrint("Terminate failed, pid %d (reason: %d)\n", slave_pid(slave), ret);
426 CRITICAL_LOG("Slave is not activated in %lf sec (slave: %s)\n", SLAVE_ACTIVATE_TIME, slave_name(slave));
427 slave = slave_deactivated(slave);
428 return ECORE_CALLBACK_CANCEL;
431 static inline void invoke_slave_fault_handler(struct slave_node *slave)
433 slave->fault_count++;
434 invoke_fault_cb(slave);
436 slave_set_reactivation(slave, 0);
437 slave_set_reactivate_instances(slave, 0);
439 if (slave_pid(slave) > 0) {
441 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
442 ret = aul_terminate_pid(slave_pid(slave));
444 ErrPrint("Terminate failed, pid %d (reason: %d)\n", slave_pid(slave), ret);
449 static Eina_Bool relaunch_timer_cb(void *data)
451 struct slave_node *slave = data;
452 int ret = ECORE_CALLBACK_CANCEL;
454 if (!slave->activate_timer) {
455 ErrPrint("Activate timer is not valid\n");
456 slave->relaunch_timer = NULL;
458 invoke_slave_fault_handler(slave);
459 } else if (!slave->relaunch_count) {
460 ErrPrint("Relaunch count is exhahausted\n");
461 ecore_timer_del(slave->activate_timer);
462 slave->activate_timer = NULL;
464 slave->relaunch_timer = NULL;
465 invoke_slave_fault_handler(slave);
469 param = bundle_create();
471 ErrPrint("Failed to create a bundle\n");
473 ecore_timer_del(slave->activate_timer);
474 slave->activate_timer = NULL;
476 slave->relaunch_timer = NULL;
478 invoke_slave_fault_handler(slave);
480 bundle_add(param, BUNDLE_SLAVE_NAME, slave_name(slave));
481 bundle_add(param, BUNDLE_SLAVE_SECURED, slave->secured ? "true" : "false");
482 bundle_add(param, BUNDLE_SLAVE_ABI, slave->abi);
484 slave->pid = (pid_t)aul_launch_app(slave_pkgname(slave), param);
488 switch (slave->pid) {
489 //case AUL_R_EHIDDENFORGUEST: /**< App hidden for guest mode */
490 case AUL_R_ENOLAUNCHPAD: /**< no launchpad */
491 case AUL_R_EILLACC: /**< Illegal Access */
492 case AUL_R_EINVAL: /**< Invalid argument */
493 case AUL_R_ENOINIT: /**< AUL handler NOT initialized */
494 case AUL_R_ERROR: /**< General error */
495 CRITICAL_LOG("Failed to launch a new slave %s (%d)\n", slave_name(slave), slave->pid);
496 slave->pid = (pid_t)-1;
497 ecore_timer_del(slave->activate_timer);
498 slave->activate_timer = NULL;
500 slave->relaunch_timer = NULL;
502 invoke_slave_fault_handler(slave);
503 /* Waiting app-launch result */
505 case AUL_R_ETIMEOUT: /**< Timeout */
506 case AUL_R_ECOMM: /**< Comunication Error */
507 case AUL_R_ETERMINATING: /**< application terminating */
508 case AUL_R_ECANCELED: /**< Operation canceled */
509 slave->relaunch_count--;
511 CRITICAL_LOG("Try relaunch again %s (%d), %d\n", slave_name(slave), slave->pid, slave->relaunch_count);
512 slave->pid = (pid_t)-1;
513 ret = ECORE_CALLBACK_RENEW;
514 ecore_timer_reset(slave->activate_timer);
515 /* Try again after a few secs later */
517 case AUL_R_LOCAL: /**< Launch by himself */
518 case AUL_R_OK: /**< General success */
520 DbgPrint("Slave %s is launched with %d as %s\n", slave_pkgname(slave), slave->pid, slave_name(slave));
521 slave->relaunch_timer = NULL;
522 ecore_timer_reset(slave->activate_timer);
533 HAPI int slave_activate(struct slave_node *slave)
537 * This check code can be replaced with the slave->state check code
538 * If the slave data has the PID, it means, it is activated
539 * Even if it is in the termiating sequence, it will have the PID
540 * before terminated at last.
541 * So we can use this simple code for checking the slave's last state.
542 * about it is alive? or not.
544 if (slave_pid(slave) != (pid_t)-1) {
545 if (slave_state(slave) == SLAVE_REQUEST_TO_TERMINATE) {
546 slave_set_reactivation(slave, 1);
548 return LB_STATUS_ERROR_ALREADY;
549 } else if (slave_state(slave) == SLAVE_REQUEST_TO_LAUNCH) {
550 DbgPrint("Slave is already launched: but the AUL is timed out\n");
551 return LB_STATUS_ERROR_ALREADY;
555 DbgPrint("Debug Mode enabled. name[%s] secured[%d] abi[%s]\n", slave_name(slave), slave->secured, slave->abi);
559 slave->relaunch_count = SLAVE_RELAUNCH_COUNT;
561 param = bundle_create();
563 ErrPrint("Failed to create a bundle\n");
564 return LB_STATUS_ERROR_FAULT;
567 bundle_add(param, BUNDLE_SLAVE_NAME, slave_name(slave));
568 bundle_add(param, BUNDLE_SLAVE_SECURED, slave->secured ? "true" : "false");
569 bundle_add(param, BUNDLE_SLAVE_ABI, slave->abi);
571 slave->pid = (pid_t)aul_launch_app(slave_pkgname(slave), param);
575 switch (slave->pid) {
576 //case AUL_R_EHIDDENFORGUEST: /**< App hidden for guest mode */
577 case AUL_R_ENOLAUNCHPAD: /**< no launchpad */
578 case AUL_R_EILLACC: /**< Illegal Access */
579 case AUL_R_EINVAL: /**< Invalid argument */
580 case AUL_R_ENOINIT: /**< AUL handler NOT initialized */
581 case AUL_R_ERROR: /**< General error */
582 CRITICAL_LOG("Failed to launch a new slave %s (%d)\n", slave_name(slave), slave->pid);
583 slave->pid = (pid_t)-1;
584 /* Waiting app-launch result */
586 case AUL_R_ECOMM: /**< Comunication Error */
587 case AUL_R_ETERMINATING: /**< application terminating */
588 case AUL_R_ECANCELED: /**< Operation canceled */
589 case AUL_R_ETIMEOUT: /**< Timeout */
590 CRITICAL_LOG("Try relaunch this soon %s (%d)\n", slave_name(slave), slave->pid);
591 slave->relaunch_timer = ecore_timer_add(SLAVE_RELAUNCH_TIME, relaunch_timer_cb, slave);
592 if (!slave->relaunch_timer) {
593 CRITICAL_LOG("Failed to register a relaunch timer (%s)\n", slave_name(slave));
594 slave->pid = (pid_t)-1;
595 return LB_STATUS_ERROR_FAULT;
597 /* Try again after a few secs later */
599 case AUL_R_LOCAL: /**< Launch by himself */
600 case AUL_R_OK: /**< General success */
602 DbgPrint("Slave %s is launched with %d as %s\n", slave_pkgname(slave), slave->pid, slave_name(slave));
606 slave->activate_timer = ecore_timer_add(SLAVE_ACTIVATE_TIME, activate_timer_cb, slave);
607 if (!slave->activate_timer) {
608 ErrPrint("Failed to register an activate timer\n");
612 slave->state = SLAVE_REQUEST_TO_LAUNCH;
615 * Increase the refcnt of a slave,
616 * To prevent from making an orphan(slave).
618 (void)slave_ref(slave);
620 return LB_STATUS_SUCCESS;
623 HAPI int slave_give_more_ttl(struct slave_node *slave)
627 if (!slave->secured || !slave->ttl_timer) {
628 return LB_STATUS_ERROR_INVALID;
631 delay = SLAVE_TTL - ecore_timer_pending_get(slave->ttl_timer);
632 ecore_timer_delay(slave->ttl_timer, delay);
633 return LB_STATUS_SUCCESS;
636 HAPI int slave_freeze_ttl(struct slave_node *slave)
638 if (!slave->secured || !slave->ttl_timer) {
639 return LB_STATUS_ERROR_INVALID;
642 ecore_timer_freeze(slave->ttl_timer);
643 return LB_STATUS_SUCCESS;
646 HAPI int slave_thaw_ttl(struct slave_node *slave)
650 if (!slave->secured || !slave->ttl_timer) {
651 return LB_STATUS_ERROR_INVALID;
654 ecore_timer_thaw(slave->ttl_timer);
656 delay = SLAVE_TTL - ecore_timer_pending_get(slave->ttl_timer);
657 ecore_timer_delay(slave->ttl_timer, delay);
658 return LB_STATUS_SUCCESS;
661 HAPI int slave_activated(struct slave_node *slave)
663 slave->state = SLAVE_RESUMED;
665 if (xmonitor_is_paused()) {
669 if (slave->secured == 1) {
670 DbgPrint("Slave deactivation timer is added (%s - %lf)\n", slave_name(slave), SLAVE_TTL);
671 slave->ttl_timer = ecore_timer_add(SLAVE_TTL, slave_ttl_cb, slave);
672 if (!slave->ttl_timer) {
673 ErrPrint("Failed to create a TTL timer\n");
677 invoke_activate_cb(slave);
679 slave_set_reactivation(slave, 0);
680 slave_set_reactivate_instances(slave, 0);
682 #if defined(_USE_ECORE_TIME_GET)
683 slave->activated_at = ecore_time_get();
685 if (gettimeofday(&slave->activated_at, NULL) < 0) {
686 ErrPrint("Failed to get time of day: %s\n", strerror(errno));
687 slave->activated_at.tv_sec = 0;
688 slave->activated_at.tv_usec = 0;
692 if (slave->activate_timer) {
693 ecore_timer_del(slave->activate_timer);
694 slave->activate_timer = NULL;
697 if (slave->relaunch_timer) {
698 ecore_timer_del(slave->relaunch_timer);
699 slave->relaunch_timer = NULL;
702 return LB_STATUS_SUCCESS;
705 static inline int invoke_deactivate_cb(struct slave_node *slave)
713 slave->in_event_process |= SLAVE_EVENT_PROCESS_DEACTIVATE;
715 EINA_LIST_FOREACH_SAFE(slave->event_deactivate_list, l, n, event) {
716 if (event->deleted) {
717 slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, event);
722 ret = event->evt_cb(event->slave, event->cbdata);
723 if (ret < 0 || event->deleted) {
724 slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, event);
728 if (ret == SLAVE_NEED_TO_REACTIVATE) {
733 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_DEACTIVATE;
738 HAPI struct slave_node *slave_deactivate(struct slave_node *slave)
742 if (!slave_is_activated(slave)) {
743 ErrPrint("Slave is already deactivated\n");
744 if (slave_loaded_instance(slave) == 0) {
747 * If a slave has no more instances,
750 slave = slave_unref(slave);
757 * check the return value of the aul_terminate_pid
759 slave->state = SLAVE_REQUEST_TO_TERMINATE;
761 if (slave_pid(slave) > 0) {
762 DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave));
763 ret = aul_terminate_pid(slave->pid);
765 ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret);
766 slave = slave_deactivated(slave);
773 HAPI struct slave_node *slave_deactivated(struct slave_node *slave)
777 slave->pid = (pid_t)-1;
778 slave->state = SLAVE_TERMINATED;
780 if (slave->ttl_timer) {
781 ecore_timer_del(slave->ttl_timer);
782 slave->ttl_timer = NULL;
785 if (slave->activate_timer) {
786 ecore_timer_del(slave->activate_timer);
787 slave->activate_timer = NULL;
790 if (slave->relaunch_timer) {
791 ecore_timer_del(slave->relaunch_timer);
792 slave->relaunch_timer = NULL;
795 reactivate = invoke_deactivate_cb(slave);
797 slave = slave_unref(slave);
799 DbgPrint("SLAVE object is destroyed\n");
803 if (reactivate && slave_need_to_reactivate(slave)) {
806 DbgPrint("Need to reactivate a slave\n");
807 ret = slave_activate(slave);
808 if (ret < 0 && ret != LB_STATUS_ERROR_ALREADY) {
809 ErrPrint("Failed to reactivate a slave\n");
811 } else if (slave_loaded_instance(slave) == 0) {
814 * If a slave has no more instances,
817 slave = slave_unref(slave);
823 HAPI struct slave_node *slave_deactivated_by_fault(struct slave_node *slave)
827 int reactivate_instances = 1;
829 if (!slave_is_activated(slave)) {
830 DbgPrint("Deactivating in progress\n");
831 if (slave_loaded_instance(slave) == 0) {
832 slave = slave_unref(slave);
838 slave->fault_count++;
840 (void)fault_check_pkgs(slave);
842 if (slave_pid(slave) > 0) {
843 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
844 ret = aul_terminate_pid(slave_pid(slave));
846 ErrPrint("Terminate failed, pid %d\n", slave_pid(slave));
850 #if defined(_USE_ECORE_TIME_GET)
853 faulted_at = ecore_time_get();
854 if (faulted_at - slave->activated_at < MINIMUM_REACTIVATION_TIME) {
855 slave->critical_fault_count++;
856 if (!slave_loaded_instance(slave) || slave->critical_fault_count >= SLAVE_MAX_LOAD) {
857 ErrPrint("Reactivation time is too fast and frequently occurred - Stop to auto reactivation\n");
859 reactivate_instances = 0;
860 slave->critical_fault_count = 0;
863 * Fault callback can access the slave information.
865 invoke_fault_cb(slave);
867 slave->critical_fault_count = 0;
871 struct timeval faulted_at;
873 if (gettimeofday(&faulted_at, NULL) == 0) {
876 timersub(&faulted_at, &slave->activated_at, &rtv);
877 if (rtv.tv_sec < MINIMUM_REACTIVATION_TIME) {
878 slave->critical_fault_count++;
879 if (!slave_loaded_instance(slave) || slave->critical_fault_count >= SLAVE_MAX_LOAD) {
880 ErrPrint("Reactivation time is too fast and frequently occurred - Stop to auto reactivation\n");
882 reactivate_instances = 0;
883 slave->critical_fault_count = 0;
886 * Fault callback can access the slave information.
888 invoke_fault_cb(slave);
891 slave->critical_fault_count = 0;
894 ErrPrint("Failed to get time of day: %s\n", strerror(errno));
898 slave_set_reactivation(slave, reactivate);
899 slave_set_reactivate_instances(slave, reactivate_instances);
901 slave = slave_deactivated(slave);
905 HAPI const int const slave_is_activated(struct slave_node *slave)
907 switch (slave->state) {
908 case SLAVE_REQUEST_TO_TERMINATE:
909 case SLAVE_TERMINATED:
911 case SLAVE_REQUEST_TO_LAUNCH:
912 /* Not yet launched. but the slave incurred an unexpected error */
913 case SLAVE_REQUEST_TO_PAUSE:
914 case SLAVE_REQUEST_TO_RESUME:
919 return slave->pid != (pid_t)-1;
922 /* Could not be reach to here */
926 HAPI int slave_event_callback_add(struct slave_node *slave, enum slave_event event, int (*cb)(struct slave_node *, void *), void *data)
930 ev = calloc(1, sizeof(*ev));
932 ErrPrint("Heap: %s\n", strerror(errno));
933 return LB_STATUS_ERROR_MEMORY;
942 * Use the eina_list_prepend API.
943 * To keep the sequence of a callback invocation.
945 * Here is an example sequence.
947 * slave_event_callback_add(CALLBACK_01);
948 * slave_event_callback_add(CALLBACK_02);
949 * slave_event_callback_add(CALLBACK_03);
951 * Then the invoke_event_callback function will call the CALLBACKS as below sequence
959 case SLAVE_EVENT_ACTIVATE:
960 slave->event_activate_list = eina_list_prepend(slave->event_activate_list, ev);
962 case SLAVE_EVENT_DELETE:
963 slave->event_delete_list = eina_list_prepend(slave->event_delete_list, ev);
965 case SLAVE_EVENT_DEACTIVATE:
966 slave->event_deactivate_list = eina_list_prepend(slave->event_deactivate_list, ev);
968 case SLAVE_EVENT_PAUSE:
969 slave->event_pause_list = eina_list_prepend(slave->event_pause_list, ev);
971 case SLAVE_EVENT_RESUME:
972 slave->event_resume_list = eina_list_prepend(slave->event_resume_list, ev);
974 case SLAVE_EVENT_FAULT:
975 slave->event_fault_list = eina_list_prepend(slave->event_fault_list, ev);
979 return LB_STATUS_ERROR_INVALID;
982 return LB_STATUS_SUCCESS;
985 HAPI int slave_event_callback_del(struct slave_node *slave, enum slave_event event, int (*cb)(struct slave_node *, void *), void *data)
992 case SLAVE_EVENT_DEACTIVATE:
993 EINA_LIST_FOREACH_SAFE(slave->event_deactivate_list, l, n, ev) {
994 if (ev->evt_cb == cb && ev->cbdata == data) {
995 if (slave->in_event_process & SLAVE_EVENT_PROCESS_DEACTIVATE) {
998 slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, ev);
1001 return LB_STATUS_SUCCESS;
1005 case SLAVE_EVENT_DELETE:
1006 EINA_LIST_FOREACH_SAFE(slave->event_delete_list, l, n, ev) {
1007 if (ev->evt_cb == cb && ev->cbdata == data) {
1008 if (slave->in_event_process & SLAVE_EVENT_PROCESS_DELETE) {
1011 slave->event_delete_list = eina_list_remove(slave->event_delete_list, ev);
1014 return LB_STATUS_SUCCESS;
1018 case SLAVE_EVENT_ACTIVATE:
1019 EINA_LIST_FOREACH_SAFE(slave->event_activate_list, l, n, ev) {
1020 if (ev->evt_cb == cb && ev->cbdata == data) {
1021 if (slave->in_event_process & SLAVE_EVENT_PROCESS_ACTIVATE) {
1024 slave->event_activate_list = eina_list_remove(slave->event_activate_list, ev);
1027 return LB_STATUS_SUCCESS;
1031 case SLAVE_EVENT_PAUSE:
1032 EINA_LIST_FOREACH_SAFE(slave->event_pause_list, l, n, ev) {
1033 if (ev->evt_cb == cb && ev->cbdata == data) {
1034 if (slave->in_event_process & SLAVE_EVENT_PROCESS_PAUSE) {
1037 slave->event_pause_list = eina_list_remove(slave->event_pause_list, ev);
1040 return LB_STATUS_SUCCESS;
1044 case SLAVE_EVENT_RESUME:
1045 EINA_LIST_FOREACH_SAFE(slave->event_resume_list, l, n, ev) {
1046 if (ev->evt_cb == cb && ev->cbdata == data) {
1047 if (slave->in_event_process & SLAVE_EVENT_PROCESS_RESUME) {
1050 slave->event_resume_list = eina_list_remove(slave->event_resume_list, ev);
1053 return LB_STATUS_SUCCESS;
1057 case SLAVE_EVENT_FAULT:
1058 EINA_LIST_FOREACH_SAFE(slave->event_fault_list, l, n, ev) {
1059 if (ev->evt_cb == cb && ev->cbdata == data) {
1060 if (slave->in_event_process & SLAVE_EVENT_PROCESS_FAULT) {
1063 slave->event_fault_list = eina_list_remove(slave->event_fault_list, ev);
1066 return LB_STATUS_SUCCESS;
1071 return LB_STATUS_ERROR_INVALID;
1074 return LB_STATUS_ERROR_NOT_EXIST;
1077 HAPI int slave_set_data(struct slave_node *slave, const char *tag, void *data)
1079 struct priv_data *priv;
1081 priv = calloc(1, sizeof(*priv));
1083 ErrPrint("Heap: %s\n", strerror(errno));
1084 return LB_STATUS_ERROR_MEMORY;
1087 priv->tag = strdup(tag);
1089 ErrPrint("Heap: %s\n", strerror(errno));
1091 return LB_STATUS_ERROR_MEMORY;
1095 slave->data_list = eina_list_append(slave->data_list, priv);
1096 return LB_STATUS_SUCCESS;
1099 HAPI void *slave_del_data(struct slave_node *slave, const char *tag)
1101 struct priv_data *priv;
1106 EINA_LIST_FOREACH_SAFE(slave->data_list, l, n, priv) {
1107 if (!strcmp(priv->tag, tag)) {
1108 slave->data_list = eina_list_remove(slave->data_list, priv);
1120 HAPI void *slave_data(struct slave_node *slave, const char *tag)
1122 struct priv_data *priv;
1125 EINA_LIST_FOREACH(slave->data_list, l, priv) {
1126 if (!strcmp(priv->tag, tag)) {
1134 HAPI struct slave_node *slave_find_by_pid(pid_t pid)
1137 struct slave_node *slave;
1139 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1140 if (slave_pid(slave) == pid) {
1148 HAPI struct slave_node *slave_find_by_name(const char *name)
1151 struct slave_node *slave;
1153 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1154 if (!strcmp(slave_name(slave), name)) {
1162 HAPI struct slave_node *slave_find_available(const char *abi, int secured, int network)
1165 struct slave_node *slave;
1167 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1168 if (slave->secured != secured) {
1172 if (slave->state == SLAVE_REQUEST_TO_TERMINATE && slave->loaded_instance == 0) {
1175 * If a slave is in request_to_terminate state,
1176 * and the slave object has no more intances,
1177 * the slave object will be deleted soon.
1178 * so we cannot reuse it.
1180 * This object is not usable.
1185 if (strcasecmp(slave->abi, abi)) {
1189 if (slave->secured) {
1190 if (slave->loaded_package == 0) {
1191 DbgPrint("Found secured slave - has no instances (%s)\n", slave_name(slave));
1194 } else if (slave->network == network) {
1195 DbgPrint("slave[%s] loaded_package[%d] net: [%d]\n", slave_name(slave), slave->loaded_package, slave->network);
1196 if (!strcasecmp(abi, DEFAULT_ABI)) {
1197 if (slave->loaded_package < SLAVE_MAX_LOAD) {
1209 HAPI struct slave_node *slave_find_by_pkgname(const char *pkgname)
1212 struct slave_node *slave;
1214 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1215 if (!strcmp(slave_pkgname(slave), pkgname)) {
1216 if (slave_pid(slave) == (pid_t)-1) {
1225 HAPI struct slave_node *slave_find_by_rpc_handle(int handle)
1228 struct slave_node *slave;
1231 ErrPrint("Invalid RPC handle: %d\n", handle);
1235 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1236 if (slave_rpc_handle(slave) == handle) {
1245 HAPI void slave_load_package(struct slave_node *slave)
1247 slave->loaded_package++;
1250 HAPI void slave_unload_package(struct slave_node *slave)
1252 if (!slave || slave->loaded_package == 0) {
1253 ErrPrint("Slave loaded package is not correct\n");
1257 slave->loaded_package--;
1260 HAPI void slave_load_instance(struct slave_node *slave)
1262 slave->loaded_instance++;
1263 DbgPrint("Instance: (%d)%d\n", slave_pid(slave), slave->loaded_instance);
1266 HAPI int const slave_loaded_instance(struct slave_node *slave)
1268 return slave->loaded_instance;
1271 HAPI int const slave_loaded_package(struct slave_node *slave)
1273 return slave->loaded_package;
1276 HAPI struct slave_node *slave_unload_instance(struct slave_node *slave)
1278 if (!slave || slave->loaded_instance == 0) {
1279 ErrPrint("Slave loaded instance is not correct\n");
1283 slave->loaded_instance--;
1284 DbgPrint("Instance: (%d)%d\n", slave_pid(slave), slave->loaded_instance);
1285 if (slave->loaded_instance == 0 && slave_is_activated(slave)) {
1286 slave_set_reactivation(slave, 0);
1287 slave_set_reactivate_instances(slave, 0);
1289 slave = slave_deactivate(slave);
1295 HAPI const int const slave_is_secured(const struct slave_node *slave)
1297 return slave->secured;
1300 HAPI const char * const slave_name(const struct slave_node *slave)
1305 HAPI const char * const slave_abi(const struct slave_node *slave)
1310 HAPI const pid_t const slave_pid(const struct slave_node *slave)
1315 HAPI int slave_set_pid(struct slave_node *slave, pid_t pid)
1318 return LB_STATUS_ERROR_INVALID;
1321 DbgPrint("Slave PID is updated to %d from %d\n", pid, slave_pid(slave));
1324 return LB_STATUS_SUCCESS;
1327 static inline void invoke_resumed_cb(struct slave_node *slave)
1331 struct event *event;
1333 slave->in_event_process |= SLAVE_EVENT_PROCESS_RESUME;
1334 EINA_LIST_FOREACH_SAFE(slave->event_resume_list, l, n, event) {
1335 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
1336 slave->event_resume_list = eina_list_remove(slave->event_resume_list, event);
1340 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_RESUME;
1343 static void resume_cb(struct slave_node *slave, const struct packet *packet, void *data)
1347 if (slave->state == SLAVE_REQUEST_TO_TERMINATE) {
1348 DbgPrint("Slave is terminating now. ignore resume result\n");
1353 ErrPrint("Failed to change the state of the slave\n");
1354 slave->state = SLAVE_PAUSED;
1358 if (packet_get(packet, "i", &ret) != 1) {
1359 ErrPrint("Invalid parameter\n");
1364 slave->state = SLAVE_RESUMED;
1365 slave_rpc_ping_thaw(slave);
1366 invoke_resumed_cb(slave);
1370 static inline void invoke_paused_cb(struct slave_node *slave)
1374 struct event *event;
1376 slave->in_event_process |= SLAVE_EVENT_PROCESS_PAUSE;
1377 EINA_LIST_FOREACH_SAFE(slave->event_pause_list, l, n, event) {
1378 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
1379 slave->event_pause_list = eina_list_remove(slave->event_pause_list, event);
1383 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_PAUSE;
1386 static void pause_cb(struct slave_node *slave, const struct packet *packet, void *data)
1390 if (slave->state == SLAVE_REQUEST_TO_TERMINATE) {
1391 DbgPrint("Slave is terminating now. ignore pause result\n");
1396 ErrPrint("Failed to change the state of the slave\n");
1397 slave->state = SLAVE_RESUMED;
1401 if (packet_get(packet, "i", &ret) != 1) {
1402 ErrPrint("Invalid parameter\n");
1407 slave->state = SLAVE_PAUSED;
1408 slave_rpc_ping_freeze(slave);
1409 invoke_paused_cb(slave);
1413 HAPI int slave_resume(struct slave_node *slave)
1416 struct packet *packet;
1418 switch (slave->state) {
1419 case SLAVE_REQUEST_TO_LAUNCH:
1420 case SLAVE_REQUEST_TO_TERMINATE:
1421 case SLAVE_TERMINATED:
1422 return LB_STATUS_ERROR_INVALID;
1424 case SLAVE_REQUEST_TO_RESUME:
1425 return LB_STATUS_SUCCESS;
1430 timestamp = util_timestamp();
1432 packet = packet_create("resume", "d", timestamp);
1434 ErrPrint("Failed to prepare param\n");
1435 return LB_STATUS_ERROR_FAULT;
1438 slave->state = SLAVE_REQUEST_TO_RESUME;
1439 return slave_rpc_async_request(slave, NULL, packet, resume_cb, NULL, 0);
1442 HAPI int slave_pause(struct slave_node *slave)
1445 struct packet *packet;
1447 switch (slave->state) {
1448 case SLAVE_REQUEST_TO_LAUNCH:
1449 case SLAVE_REQUEST_TO_TERMINATE:
1450 case SLAVE_TERMINATED:
1451 return LB_STATUS_ERROR_INVALID;
1453 case SLAVE_REQUEST_TO_PAUSE:
1454 return LB_STATUS_SUCCESS;
1459 timestamp = util_timestamp();
1461 packet = packet_create("pause", "d", timestamp);
1463 ErrPrint("Failed to prepare param\n");
1464 return LB_STATUS_ERROR_FAULT;
1467 slave->state = SLAVE_REQUEST_TO_PAUSE;
1468 return slave_rpc_async_request(slave, NULL, packet, pause_cb, NULL, 0);
1471 HAPI const char *slave_pkgname(const struct slave_node *slave)
1473 return slave ? slave->pkgname : NULL;
1476 HAPI enum slave_state slave_state(const struct slave_node *slave)
1478 return slave ? slave->state : SLAVE_ERROR;
1481 HAPI const char *slave_state_string(const struct slave_node *slave)
1483 switch (slave->state) {
1484 case SLAVE_REQUEST_TO_LAUNCH:
1485 return "RequestToLaunch";
1486 case SLAVE_REQUEST_TO_TERMINATE:
1487 return "RequestToTerminate";
1488 case SLAVE_TERMINATED:
1489 return "Terminated";
1490 case SLAVE_REQUEST_TO_PAUSE:
1491 return "RequestToPause";
1492 case SLAVE_REQUEST_TO_RESUME:
1493 return "RequestToResume";
1507 HAPI const void *slave_list(void)
1509 return s_info.slave_list;
1512 HAPI int const slave_fault_count(const struct slave_node *slave)
1514 return slave->fault_count;
1517 HAPI double const slave_ttl(const struct slave_node *slave)
1519 if (!slave->ttl_timer) {
1523 return ecore_timer_pending_get(slave->ttl_timer);
1526 HAPI void slave_set_reactivate_instances(struct slave_node *slave, int reactivate)
1528 slave->reactivate_instances = reactivate;
1531 HAPI int slave_need_to_reactivate_instances(struct slave_node *slave)
1533 return slave->reactivate_instances;
1536 HAPI void slave_set_reactivation(struct slave_node *slave, int flag)
1538 slave->reactivate_slave = flag;
1541 HAPI int slave_need_to_reactivate(struct slave_node *slave)
1543 return slave->reactivate_slave;
1546 HAPI int slave_network(const struct slave_node *slave)
1548 return slave->network;
1551 HAPI void slave_set_network(struct slave_node *slave, int network)
1553 slave->network = network;
1556 HAPI int slave_deactivate_all(int reactivate, int reactivate_instances)
1560 struct slave_node *slave;
1563 s_info.deactivate_all_refcnt++;
1564 if (s_info.deactivate_all_refcnt > 1) {
1567 DbgPrint("Deactivate all\n");
1569 EINA_LIST_FOREACH_SAFE(s_info.slave_list, l, n, slave) {
1570 slave_set_reactivate_instances(slave, reactivate_instances);
1571 slave_set_reactivation(slave, reactivate);
1573 if (!slave_deactivate(slave)) {
1574 s_info.slave_list = eina_list_remove(s_info.slave_list, slave);
1583 HAPI int slave_activate_all(void)
1586 struct slave_node *slave;
1589 s_info.deactivate_all_refcnt--;
1590 if (s_info.deactivate_all_refcnt > 0) {
1593 DbgPrint("Activate all\n");
1595 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1596 slave_activate(slave);