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 */
90 Ecore_Timer *terminate_timer; /*!< Waiting this timer before terminate the service provider */
93 #if defined(_USE_ECORE_TIME_GET)
96 struct timeval activated_at;
101 struct slave_node *slave;
103 int (*evt_cb)(struct slave_node *, void *);
114 Eina_List *slave_list;
115 int deactivate_all_refcnt;
118 .deactivate_all_refcnt = 0,
121 static Eina_Bool slave_ttl_cb(void *data)
123 struct slave_node *slave = (struct slave_node *)data;
127 * ttl_timer must has to be set to NULL before deactivate the slave
128 * It will be used for making decision of the expired TTL timer or the fault of a livebox.
130 slave->ttl_timer = NULL;
132 slave_set_reactivation(slave, 0);
133 slave_set_reactivate_instances(slave, 1);
135 slave = slave_deactivate(slave, 1);
137 DbgPrint("Slave is deleted\n");
140 /*! To recover all instances state it is activated again */
141 return ECORE_CALLBACK_CANCEL;
144 static inline int xmonitor_pause_cb(void *data)
147 return LB_STATUS_SUCCESS;
150 static inline int xmonitor_resume_cb(void *data)
153 return LB_STATUS_SUCCESS;
156 static inline struct slave_node *create_slave_node(const char *name, int is_secured, const char *abi, const char *pkgname, int network)
158 struct slave_node *slave;
160 slave = calloc(1, sizeof(*slave));
162 ErrPrint("Heap: %s\n", strerror(errno));
166 slave->name = strdup(name);
168 ErrPrint("Heap: %s\n", strerror(errno));
173 slave->abi = strdup(abi);
175 ErrPrint("Heap: %s\n", strerror(errno));
176 DbgFree(slave->name);
181 slave->pkgname = strdup(pkgname);
182 if (!slave->pkgname) {
183 ErrPrint("Heap: %s\n", strerror(errno));
185 DbgFree(slave->name);
190 slave->secured = is_secured;
191 slave->pid = (pid_t)-1;
192 slave->state = SLAVE_TERMINATED;
193 slave->network = network;
194 slave->relaunch_count = SLAVE_RELAUNCH_COUNT;
196 xmonitor_add_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
197 xmonitor_add_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
199 s_info.slave_list = eina_list_append(s_info.slave_list, slave);
203 static inline void invoke_delete_cb(struct slave_node *slave)
209 slave->in_event_process |= SLAVE_EVENT_PROCESS_DELETE;
210 EINA_LIST_FOREACH_SAFE(slave->event_delete_list, l, n, event) {
211 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
212 slave->event_delete_list = eina_list_remove(slave->event_delete_list, event);
216 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_DELETE;
219 static inline void destroy_slave_node(struct slave_node *slave)
222 struct priv_data *priv;
224 if (slave_pid(slave) != (pid_t)-1) {
225 ErrPrint("Slave is not deactivated\n");
229 xmonitor_del_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
230 xmonitor_del_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
232 invoke_delete_cb(slave);
233 slave_rpc_fini(slave); /*!< Finalize the RPC after handling all delete callbacks */
235 EINA_LIST_FREE(slave->event_delete_list, event) {
239 EINA_LIST_FREE(slave->event_activate_list, event) {
243 EINA_LIST_FREE(slave->event_deactivate_list, event) {
247 EINA_LIST_FREE(slave->event_fault_list, event) {
251 EINA_LIST_FREE(slave->data_list, priv) {
256 s_info.slave_list = eina_list_remove(s_info.slave_list, slave);
258 if (slave->ttl_timer) {
259 ecore_timer_del(slave->ttl_timer);
262 if (slave->activate_timer) {
263 ecore_timer_del(slave->activate_timer);
266 if (slave->relaunch_timer) {
267 ecore_timer_del(slave->relaunch_timer);
271 DbgFree(slave->name);
272 DbgFree(slave->pkgname);
277 static inline struct slave_node *find_slave(const char *name)
279 struct slave_node *slave;
282 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
283 if (!strcmp(slave->name, name)) {
291 HAPI int slave_expired_ttl(struct slave_node *slave)
297 if (!slave->secured) {
301 return !!slave->ttl_timer;
304 HAPI struct slave_node *slave_ref(struct slave_node *slave)
314 HAPI struct slave_node *slave_unref(struct slave_node *slave)
320 if (slave->refcnt == 0) {
321 ErrPrint("Slave refcnt is not valid\n");
326 if (slave->refcnt == 0) {
327 destroy_slave_node(slave);
334 HAPI const int const slave_refcnt(struct slave_node *slave)
336 return slave->refcnt;
339 HAPI struct slave_node *slave_create(const char *name, int is_secured, const char *abi, const char *pkgname, int network)
341 struct slave_node *slave;
343 slave = find_slave(name);
345 if (slave->secured != is_secured) {
346 ErrPrint("Exists slave and creating slave's security flag is not matched\n");
351 slave = create_slave_node(name, is_secured, abi, pkgname, network);
357 slave_rpc_init(slave);
364 * Before destroying slave object,
365 * you should check the RPC(slave_async_XXX) state and Private data field (slave_set_data)
367 HAPI void slave_destroy(struct slave_node *slave)
372 static inline void invoke_fault_cb(struct slave_node *slave)
378 EINA_LIST_FOREACH_SAFE(slave->event_fault_list, l, n, event) {
379 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
380 slave->event_fault_list = eina_list_remove(slave->event_fault_list, event);
386 static inline void invoke_activate_cb(struct slave_node *slave)
392 slave->in_event_process |= SLAVE_EVENT_PROCESS_ACTIVATE;
393 EINA_LIST_FOREACH_SAFE(slave->event_activate_list, l, n, event) {
394 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
395 slave->event_activate_list = eina_list_remove(slave->event_activate_list, event);
399 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_ACTIVATE;
402 static Eina_Bool activate_timer_cb(void *data)
404 struct slave_node *slave = data;
406 if (slave->relaunch_timer) {
407 ecore_timer_del(slave->relaunch_timer);
408 slave->relaunch_timer = NULL;
411 slave->fault_count++;
412 invoke_fault_cb(slave);
414 slave_set_reactivation(slave, 0);
415 slave_set_reactivate_instances(slave, 0);
417 slave->activate_timer = NULL;
418 if (slave_pid(slave) > 0) {
420 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
421 ret = aul_terminate_pid(slave_pid(slave));
423 ErrPrint("Terminate failed, pid %d (reason: %d)\n", slave_pid(slave), ret);
427 CRITICAL_LOG("Slave is not activated in %lf sec (slave: %s)\n", SLAVE_ACTIVATE_TIME, slave_name(slave));
428 slave = slave_deactivated(slave);
429 return ECORE_CALLBACK_CANCEL;
432 static inline void invoke_slave_fault_handler(struct slave_node *slave)
434 slave->fault_count++;
435 invoke_fault_cb(slave);
437 slave_set_reactivation(slave, 0);
438 slave_set_reactivate_instances(slave, 0);
440 if (slave_pid(slave) > 0) {
442 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
443 ret = aul_terminate_pid(slave_pid(slave));
445 ErrPrint("Terminate failed, pid %d (reason: %d)\n", slave_pid(slave), ret);
450 static Eina_Bool relaunch_timer_cb(void *data)
452 struct slave_node *slave = data;
453 int ret = ECORE_CALLBACK_CANCEL;
455 if (!slave->activate_timer) {
456 ErrPrint("Activate timer is not valid\n");
457 slave->relaunch_timer = NULL;
459 invoke_slave_fault_handler(slave);
460 } else if (!slave->relaunch_count) {
461 ErrPrint("Relaunch count is exhahausted\n");
462 ecore_timer_del(slave->activate_timer);
463 slave->activate_timer = NULL;
465 slave->relaunch_timer = NULL;
466 invoke_slave_fault_handler(slave);
470 param = bundle_create();
472 ErrPrint("Failed to create a bundle\n");
474 ecore_timer_del(slave->activate_timer);
475 slave->activate_timer = NULL;
477 slave->relaunch_timer = NULL;
479 invoke_slave_fault_handler(slave);
481 bundle_add(param, BUNDLE_SLAVE_NAME, slave_name(slave));
482 bundle_add(param, BUNDLE_SLAVE_SECURED, slave->secured ? "true" : "false");
483 bundle_add(param, BUNDLE_SLAVE_ABI, slave->abi);
485 slave->pid = (pid_t)aul_launch_app(slave_pkgname(slave), param);
489 switch (slave->pid) {
490 //case AUL_R_EHIDDENFORGUEST: /**< App hidden for guest mode */
491 case AUL_R_ENOLAUNCHPAD: /**< no launchpad */
492 case AUL_R_EILLACC: /**< Illegal Access */
493 case AUL_R_EINVAL: /**< Invalid argument */
494 case AUL_R_ENOINIT: /**< AUL handler NOT initialized */
495 case AUL_R_ERROR: /**< General error */
496 CRITICAL_LOG("Failed to launch a new slave %s (%d)\n", slave_name(slave), slave->pid);
497 slave->pid = (pid_t)-1;
498 ecore_timer_del(slave->activate_timer);
499 slave->activate_timer = NULL;
501 slave->relaunch_timer = NULL;
503 invoke_slave_fault_handler(slave);
504 /* Waiting app-launch result */
506 case AUL_R_ETIMEOUT: /**< Timeout */
507 case AUL_R_ECOMM: /**< Comunication Error */
508 case AUL_R_ETERMINATING: /**< application terminating */
509 case AUL_R_ECANCELED: /**< Operation canceled */
510 slave->relaunch_count--;
512 CRITICAL_LOG("Try relaunch again %s (%d), %d\n", slave_name(slave), slave->pid, slave->relaunch_count);
513 slave->pid = (pid_t)-1;
514 ret = ECORE_CALLBACK_RENEW;
515 ecore_timer_reset(slave->activate_timer);
516 /* Try again after a few secs later */
518 case AUL_R_LOCAL: /**< Launch by himself */
519 case AUL_R_OK: /**< General success */
521 DbgPrint("Slave %s is launched with %d as %s\n", slave_pkgname(slave), slave->pid, slave_name(slave));
522 slave->relaunch_timer = NULL;
523 ecore_timer_reset(slave->activate_timer);
534 HAPI int slave_activate(struct slave_node *slave)
538 * This check code can be replaced with the slave->state check code
539 * If the slave data has the PID, it means, it is activated
540 * Even if it is in the termiating sequence, it will have the PID
541 * before terminated at last.
542 * So we can use this simple code for checking the slave's last state.
543 * about it is alive? or not.
545 if (slave_pid(slave) != (pid_t)-1) {
546 if (slave->terminate_timer) {
547 DbgPrint("Clear terminate timer. to reuse (%d)\n", slave->pid);
548 ecore_timer_del(slave->terminate_timer);
549 slave->terminate_timer = NULL;
550 } else if (slave_state(slave) == SLAVE_REQUEST_TO_TERMINATE) {
551 slave_set_reactivation(slave, 1);
553 return LB_STATUS_ERROR_ALREADY;
554 } else if (slave_state(slave) == SLAVE_REQUEST_TO_LAUNCH) {
555 DbgPrint("Slave is already launched: but the AUL is timed out\n");
556 return LB_STATUS_ERROR_ALREADY;
560 DbgPrint("Debug Mode enabled. name[%s] secured[%d] abi[%s]\n", slave_name(slave), slave->secured, slave->abi);
564 slave->relaunch_count = SLAVE_RELAUNCH_COUNT;
566 param = bundle_create();
568 ErrPrint("Failed to create a bundle\n");
569 return LB_STATUS_ERROR_FAULT;
572 bundle_add(param, BUNDLE_SLAVE_NAME, slave_name(slave));
573 bundle_add(param, BUNDLE_SLAVE_SECURED, slave->secured ? "true" : "false");
574 bundle_add(param, BUNDLE_SLAVE_ABI, slave->abi);
576 slave->pid = (pid_t)aul_launch_app(slave_pkgname(slave), param);
580 switch (slave->pid) {
581 //case AUL_R_EHIDDENFORGUEST: /**< App hidden for guest mode */
582 case AUL_R_ENOLAUNCHPAD: /**< no launchpad */
583 case AUL_R_EILLACC: /**< Illegal Access */
584 case AUL_R_EINVAL: /**< Invalid argument */
585 case AUL_R_ENOINIT: /**< AUL handler NOT initialized */
586 case AUL_R_ERROR: /**< General error */
587 CRITICAL_LOG("Failed to launch a new slave %s (%d)\n", slave_name(slave), slave->pid);
588 slave->pid = (pid_t)-1;
589 /* Waiting app-launch result */
591 case AUL_R_ECOMM: /**< Comunication Error */
592 case AUL_R_ETERMINATING: /**< application terminating */
593 case AUL_R_ECANCELED: /**< Operation canceled */
594 case AUL_R_ETIMEOUT: /**< Timeout */
595 CRITICAL_LOG("Try relaunch this soon %s (%d)\n", slave_name(slave), slave->pid);
596 slave->relaunch_timer = ecore_timer_add(SLAVE_RELAUNCH_TIME, relaunch_timer_cb, slave);
597 if (!slave->relaunch_timer) {
598 CRITICAL_LOG("Failed to register a relaunch timer (%s)\n", slave_name(slave));
599 slave->pid = (pid_t)-1;
600 return LB_STATUS_ERROR_FAULT;
602 /* Try again after a few secs later */
604 case AUL_R_LOCAL: /**< Launch by himself */
605 case AUL_R_OK: /**< General success */
607 DbgPrint("Slave %s is launched with %d as %s\n", slave_pkgname(slave), slave->pid, slave_name(slave));
611 slave->activate_timer = ecore_timer_add(SLAVE_ACTIVATE_TIME, activate_timer_cb, slave);
612 if (!slave->activate_timer) {
613 ErrPrint("Failed to register an activate timer\n");
617 slave->state = SLAVE_REQUEST_TO_LAUNCH;
620 * Increase the refcnt of a slave,
621 * To prevent from making an orphan(slave).
623 (void)slave_ref(slave);
625 return LB_STATUS_SUCCESS;
628 HAPI int slave_give_more_ttl(struct slave_node *slave)
632 if (!slave->secured || !slave->ttl_timer) {
633 return LB_STATUS_ERROR_INVALID;
636 delay = SLAVE_TTL - ecore_timer_pending_get(slave->ttl_timer);
637 ecore_timer_delay(slave->ttl_timer, delay);
638 return LB_STATUS_SUCCESS;
641 HAPI int slave_freeze_ttl(struct slave_node *slave)
643 if (!slave->secured || !slave->ttl_timer) {
644 return LB_STATUS_ERROR_INVALID;
647 ecore_timer_freeze(slave->ttl_timer);
648 return LB_STATUS_SUCCESS;
651 HAPI int slave_thaw_ttl(struct slave_node *slave)
655 if (!slave->secured || !slave->ttl_timer) {
656 return LB_STATUS_ERROR_INVALID;
659 ecore_timer_thaw(slave->ttl_timer);
661 delay = SLAVE_TTL - ecore_timer_pending_get(slave->ttl_timer);
662 ecore_timer_delay(slave->ttl_timer, delay);
663 return LB_STATUS_SUCCESS;
666 HAPI int slave_activated(struct slave_node *slave)
668 slave->state = SLAVE_RESUMED;
670 if (xmonitor_is_paused()) {
674 if (slave->secured == 1) {
675 DbgPrint("Slave deactivation timer is added (%s - %lf)\n", slave_name(slave), SLAVE_TTL);
676 slave->ttl_timer = ecore_timer_add(SLAVE_TTL, slave_ttl_cb, slave);
677 if (!slave->ttl_timer) {
678 ErrPrint("Failed to create a TTL timer\n");
682 invoke_activate_cb(slave);
684 slave_set_reactivation(slave, 0);
685 slave_set_reactivate_instances(slave, 0);
687 #if defined(_USE_ECORE_TIME_GET)
688 slave->activated_at = ecore_time_get();
690 if (gettimeofday(&slave->activated_at, NULL) < 0) {
691 ErrPrint("Failed to get time of day: %s\n", strerror(errno));
692 slave->activated_at.tv_sec = 0;
693 slave->activated_at.tv_usec = 0;
697 if (slave->activate_timer) {
698 ecore_timer_del(slave->activate_timer);
699 slave->activate_timer = NULL;
702 if (slave->relaunch_timer) {
703 ecore_timer_del(slave->relaunch_timer);
704 slave->relaunch_timer = NULL;
707 return LB_STATUS_SUCCESS;
710 static inline int invoke_deactivate_cb(struct slave_node *slave)
718 slave->in_event_process |= SLAVE_EVENT_PROCESS_DEACTIVATE;
720 EINA_LIST_FOREACH_SAFE(slave->event_deactivate_list, l, n, event) {
721 if (event->deleted) {
722 slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, event);
727 ret = event->evt_cb(event->slave, event->cbdata);
728 if (ret < 0 || event->deleted) {
729 slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, event);
733 if (ret == SLAVE_NEED_TO_REACTIVATE) {
738 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_DEACTIVATE;
743 static Eina_Bool terminate_timer_cb(void *data)
745 struct slave_node *slave = data;
750 * check the return value of the aul_terminate_pid
752 slave->state = SLAVE_REQUEST_TO_TERMINATE;
753 slave->terminate_timer = NULL;
755 DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave));
756 ret = aul_terminate_pid(slave->pid);
758 ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret);
759 slave = slave_deactivated(slave);
762 return ECORE_CALLBACK_CANCEL;
765 HAPI struct slave_node *slave_deactivate(struct slave_node *slave, int direct)
769 if (!slave_is_activated(slave)) {
770 ErrPrint("Slave is already deactivated\n");
771 if (slave_loaded_instance(slave) == 0) {
774 * If a slave has no more instances,
777 slave = slave_unref(slave);
782 if (slave_pid(slave) > 0) {
783 if (slave->terminate_timer) {
784 ErrPrint("Terminate timer is already fired (%d)\n", slave->pid);
785 } else if (!direct) {
786 DbgPrint("Fire the terminate timer: %d\n", slave->pid);
787 slave->terminate_timer = ecore_timer_add(SLAVE_ACTIVATE_TIME, terminate_timer_cb, slave);
788 if (!slave->terminate_timer) {
791 * Normally, Call the terminate_timer_cb directly from here
792 * But in this case. if the aul_terminate_pid failed, Call the slave_deactivated function directly.
793 * Then the "slave" pointer can be changed. To trace it, Copy the body of terminate_timer_cb to here.
795 ErrPrint("Failed to add a new timer for terminating\n");
796 DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave));
799 * check the return value of the aul_terminate_pid
801 slave->state = SLAVE_REQUEST_TO_TERMINATE;
803 ret = aul_terminate_pid(slave->pid);
805 ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret);
806 slave = slave_deactivated(slave);
812 * check the return value of the aul_terminate_pid
814 slave->state = SLAVE_REQUEST_TO_TERMINATE;
816 DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave));
817 ret = aul_terminate_pid(slave->pid);
819 ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret);
820 slave = slave_deactivated(slave);
828 HAPI struct slave_node *slave_deactivated(struct slave_node *slave)
832 slave->pid = (pid_t)-1;
833 slave->state = SLAVE_TERMINATED;
835 if (slave->ttl_timer) {
836 ecore_timer_del(slave->ttl_timer);
837 slave->ttl_timer = NULL;
840 if (slave->activate_timer) {
841 ecore_timer_del(slave->activate_timer);
842 slave->activate_timer = NULL;
845 if (slave->relaunch_timer) {
846 ecore_timer_del(slave->relaunch_timer);
847 slave->relaunch_timer = NULL;
850 if (slave->terminate_timer) {
851 ecore_timer_del(slave->terminate_timer);
852 slave->terminate_timer = NULL;
855 reactivate = invoke_deactivate_cb(slave);
857 slave = slave_unref(slave);
859 DbgPrint("SLAVE object is destroyed\n");
863 if (reactivate && slave_need_to_reactivate(slave)) {
866 DbgPrint("Need to reactivate a slave\n");
867 ret = slave_activate(slave);
868 if (ret < 0 && ret != LB_STATUS_ERROR_ALREADY) {
869 ErrPrint("Failed to reactivate a slave\n");
871 } else if (slave_loaded_instance(slave) == 0) {
874 * If a slave has no more instances,
877 slave = slave_unref(slave);
883 HAPI struct slave_node *slave_deactivated_by_fault(struct slave_node *slave)
887 int reactivate_instances = 1;
889 if (!slave_is_activated(slave)) {
890 DbgPrint("Deactivating in progress\n");
891 if (slave_loaded_instance(slave) == 0) {
892 slave = slave_unref(slave);
898 slave->fault_count++;
900 (void)fault_check_pkgs(slave);
902 if (slave_pid(slave) > 0) {
903 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
904 ret = aul_terminate_pid(slave_pid(slave));
906 ErrPrint("Terminate failed, pid %d\n", slave_pid(slave));
910 #if defined(_USE_ECORE_TIME_GET)
913 faulted_at = ecore_time_get();
914 if (faulted_at - slave->activated_at < MINIMUM_REACTIVATION_TIME) {
915 slave->critical_fault_count++;
916 if (!slave_loaded_instance(slave) || slave->critical_fault_count >= SLAVE_MAX_LOAD) {
917 ErrPrint("Reactivation time is too fast and frequently occurred - Stop to auto reactivation\n");
919 reactivate_instances = 0;
920 slave->critical_fault_count = 0;
923 * Fault callback can access the slave information.
925 invoke_fault_cb(slave);
927 slave->critical_fault_count = 0;
931 struct timeval faulted_at;
933 if (gettimeofday(&faulted_at, NULL) == 0) {
936 timersub(&faulted_at, &slave->activated_at, &rtv);
937 if (rtv.tv_sec < MINIMUM_REACTIVATION_TIME) {
938 slave->critical_fault_count++;
939 if (!slave_loaded_instance(slave) || slave->critical_fault_count >= SLAVE_MAX_LOAD) {
940 ErrPrint("Reactivation time is too fast and frequently occurred - Stop to auto reactivation\n");
942 reactivate_instances = 0;
943 slave->critical_fault_count = 0;
946 * Fault callback can access the slave information.
948 invoke_fault_cb(slave);
951 slave->critical_fault_count = 0;
954 ErrPrint("Failed to get time of day: %s\n", strerror(errno));
958 slave_set_reactivation(slave, reactivate);
959 slave_set_reactivate_instances(slave, reactivate_instances);
961 slave = slave_deactivated(slave);
965 HAPI const int const slave_is_activated(struct slave_node *slave)
967 switch (slave->state) {
968 case SLAVE_REQUEST_TO_TERMINATE:
969 case SLAVE_TERMINATED:
971 case SLAVE_REQUEST_TO_LAUNCH:
972 /* Not yet launched. but the slave incurred an unexpected error */
973 case SLAVE_REQUEST_TO_PAUSE:
974 case SLAVE_REQUEST_TO_RESUME:
979 return slave->pid != (pid_t)-1;
982 /* Could not be reach to here */
986 HAPI int slave_event_callback_add(struct slave_node *slave, enum slave_event event, int (*cb)(struct slave_node *, void *), void *data)
990 ev = calloc(1, sizeof(*ev));
992 ErrPrint("Heap: %s\n", strerror(errno));
993 return LB_STATUS_ERROR_MEMORY;
1002 * Use the eina_list_prepend API.
1003 * To keep the sequence of a callback invocation.
1005 * Here is an example sequence.
1007 * slave_event_callback_add(CALLBACK_01);
1008 * slave_event_callback_add(CALLBACK_02);
1009 * slave_event_callback_add(CALLBACK_03);
1011 * Then the invoke_event_callback function will call the CALLBACKS as below sequence
1013 * invoke_CALLBACK_03
1014 * invoke_CALLBACK_02
1015 * invoke_CALLBACK_01
1019 case SLAVE_EVENT_ACTIVATE:
1020 slave->event_activate_list = eina_list_prepend(slave->event_activate_list, ev);
1022 case SLAVE_EVENT_DELETE:
1023 slave->event_delete_list = eina_list_prepend(slave->event_delete_list, ev);
1025 case SLAVE_EVENT_DEACTIVATE:
1026 slave->event_deactivate_list = eina_list_prepend(slave->event_deactivate_list, ev);
1028 case SLAVE_EVENT_PAUSE:
1029 slave->event_pause_list = eina_list_prepend(slave->event_pause_list, ev);
1031 case SLAVE_EVENT_RESUME:
1032 slave->event_resume_list = eina_list_prepend(slave->event_resume_list, ev);
1034 case SLAVE_EVENT_FAULT:
1035 slave->event_fault_list = eina_list_prepend(slave->event_fault_list, ev);
1039 return LB_STATUS_ERROR_INVALID;
1042 return LB_STATUS_SUCCESS;
1045 HAPI int slave_event_callback_del(struct slave_node *slave, enum slave_event event, int (*cb)(struct slave_node *, void *), void *data)
1052 case SLAVE_EVENT_DEACTIVATE:
1053 EINA_LIST_FOREACH_SAFE(slave->event_deactivate_list, l, n, ev) {
1054 if (ev->evt_cb == cb && ev->cbdata == data) {
1055 if (slave->in_event_process & SLAVE_EVENT_PROCESS_DEACTIVATE) {
1058 slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, ev);
1061 return LB_STATUS_SUCCESS;
1065 case SLAVE_EVENT_DELETE:
1066 EINA_LIST_FOREACH_SAFE(slave->event_delete_list, l, n, ev) {
1067 if (ev->evt_cb == cb && ev->cbdata == data) {
1068 if (slave->in_event_process & SLAVE_EVENT_PROCESS_DELETE) {
1071 slave->event_delete_list = eina_list_remove(slave->event_delete_list, ev);
1074 return LB_STATUS_SUCCESS;
1078 case SLAVE_EVENT_ACTIVATE:
1079 EINA_LIST_FOREACH_SAFE(slave->event_activate_list, l, n, ev) {
1080 if (ev->evt_cb == cb && ev->cbdata == data) {
1081 if (slave->in_event_process & SLAVE_EVENT_PROCESS_ACTIVATE) {
1084 slave->event_activate_list = eina_list_remove(slave->event_activate_list, ev);
1087 return LB_STATUS_SUCCESS;
1091 case SLAVE_EVENT_PAUSE:
1092 EINA_LIST_FOREACH_SAFE(slave->event_pause_list, l, n, ev) {
1093 if (ev->evt_cb == cb && ev->cbdata == data) {
1094 if (slave->in_event_process & SLAVE_EVENT_PROCESS_PAUSE) {
1097 slave->event_pause_list = eina_list_remove(slave->event_pause_list, ev);
1100 return LB_STATUS_SUCCESS;
1104 case SLAVE_EVENT_RESUME:
1105 EINA_LIST_FOREACH_SAFE(slave->event_resume_list, l, n, ev) {
1106 if (ev->evt_cb == cb && ev->cbdata == data) {
1107 if (slave->in_event_process & SLAVE_EVENT_PROCESS_RESUME) {
1110 slave->event_resume_list = eina_list_remove(slave->event_resume_list, ev);
1113 return LB_STATUS_SUCCESS;
1117 case SLAVE_EVENT_FAULT:
1118 EINA_LIST_FOREACH_SAFE(slave->event_fault_list, l, n, ev) {
1119 if (ev->evt_cb == cb && ev->cbdata == data) {
1120 if (slave->in_event_process & SLAVE_EVENT_PROCESS_FAULT) {
1123 slave->event_fault_list = eina_list_remove(slave->event_fault_list, ev);
1126 return LB_STATUS_SUCCESS;
1131 return LB_STATUS_ERROR_INVALID;
1134 return LB_STATUS_ERROR_NOT_EXIST;
1137 HAPI int slave_set_data(struct slave_node *slave, const char *tag, void *data)
1139 struct priv_data *priv;
1141 priv = calloc(1, sizeof(*priv));
1143 ErrPrint("Heap: %s\n", strerror(errno));
1144 return LB_STATUS_ERROR_MEMORY;
1147 priv->tag = strdup(tag);
1149 ErrPrint("Heap: %s\n", strerror(errno));
1151 return LB_STATUS_ERROR_MEMORY;
1155 slave->data_list = eina_list_append(slave->data_list, priv);
1156 return LB_STATUS_SUCCESS;
1159 HAPI void *slave_del_data(struct slave_node *slave, const char *tag)
1161 struct priv_data *priv;
1166 EINA_LIST_FOREACH_SAFE(slave->data_list, l, n, priv) {
1167 if (!strcmp(priv->tag, tag)) {
1168 slave->data_list = eina_list_remove(slave->data_list, priv);
1180 HAPI void *slave_data(struct slave_node *slave, const char *tag)
1182 struct priv_data *priv;
1185 EINA_LIST_FOREACH(slave->data_list, l, priv) {
1186 if (!strcmp(priv->tag, tag)) {
1194 HAPI struct slave_node *slave_find_by_pid(pid_t pid)
1197 struct slave_node *slave;
1199 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1200 if (slave_pid(slave) == pid) {
1208 HAPI struct slave_node *slave_find_by_name(const char *name)
1211 struct slave_node *slave;
1213 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1214 if (!strcmp(slave_name(slave), name)) {
1222 HAPI struct slave_node *slave_find_available(const char *abi, int secured, int network)
1225 struct slave_node *slave;
1227 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1228 if (slave->secured != secured) {
1232 if (slave->state == SLAVE_REQUEST_TO_TERMINATE && slave->loaded_instance == 0) {
1235 * If a slave is in request_to_terminate state,
1236 * and the slave object has no more intances,
1237 * the slave object will be deleted soon.
1238 * so we cannot reuse it.
1240 * This object is not usable.
1245 if (strcasecmp(slave->abi, abi)) {
1249 if (slave->secured) {
1250 if (slave->loaded_package == 0) {
1251 DbgPrint("Found secured slave - has no instances (%s)\n", slave_name(slave));
1254 } else if (slave->network == network) {
1255 DbgPrint("slave[%s] loaded_package[%d] net: [%d]\n", slave_name(slave), slave->loaded_package, slave->network);
1256 if (!strcasecmp(abi, DEFAULT_ABI)) {
1257 if (slave->loaded_package < SLAVE_MAX_LOAD) {
1269 HAPI struct slave_node *slave_find_by_pkgname(const char *pkgname)
1272 struct slave_node *slave;
1274 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1275 if (!strcmp(slave_pkgname(slave), pkgname)) {
1276 if (slave_pid(slave) == (pid_t)-1) {
1285 HAPI struct slave_node *slave_find_by_rpc_handle(int handle)
1288 struct slave_node *slave;
1291 ErrPrint("Invalid RPC handle: %d\n", handle);
1295 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1296 if (slave_rpc_handle(slave) == handle) {
1305 HAPI void slave_load_package(struct slave_node *slave)
1307 slave->loaded_package++;
1310 HAPI void slave_unload_package(struct slave_node *slave)
1312 if (!slave || slave->loaded_package == 0) {
1313 ErrPrint("Slave loaded package is not correct\n");
1317 slave->loaded_package--;
1320 HAPI void slave_load_instance(struct slave_node *slave)
1322 slave->loaded_instance++;
1323 DbgPrint("Instance: (%d)%d\n", slave_pid(slave), slave->loaded_instance);
1326 HAPI int const slave_loaded_instance(struct slave_node *slave)
1328 return slave->loaded_instance;
1331 HAPI int const slave_loaded_package(struct slave_node *slave)
1333 return slave->loaded_package;
1336 HAPI struct slave_node *slave_unload_instance(struct slave_node *slave)
1338 if (!slave || slave->loaded_instance == 0) {
1339 ErrPrint("Slave loaded instance is not correct\n");
1343 slave->loaded_instance--;
1344 DbgPrint("Instance: (%d)%d\n", slave_pid(slave), slave->loaded_instance);
1345 if (slave->loaded_instance == 0 && slave_is_activated(slave)) {
1346 slave_set_reactivation(slave, 0);
1347 slave_set_reactivate_instances(slave, 0);
1349 slave = slave_deactivate(slave, 0);
1355 HAPI const int const slave_is_secured(const struct slave_node *slave)
1357 return slave->secured;
1360 HAPI const char * const slave_name(const struct slave_node *slave)
1365 HAPI const char * const slave_abi(const struct slave_node *slave)
1370 HAPI const pid_t const slave_pid(const struct slave_node *slave)
1375 HAPI int slave_set_pid(struct slave_node *slave, pid_t pid)
1378 return LB_STATUS_ERROR_INVALID;
1381 DbgPrint("Slave PID is updated to %d from %d\n", pid, slave_pid(slave));
1384 return LB_STATUS_SUCCESS;
1387 static inline void invoke_resumed_cb(struct slave_node *slave)
1391 struct event *event;
1393 slave->in_event_process |= SLAVE_EVENT_PROCESS_RESUME;
1394 EINA_LIST_FOREACH_SAFE(slave->event_resume_list, l, n, event) {
1395 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
1396 slave->event_resume_list = eina_list_remove(slave->event_resume_list, event);
1400 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_RESUME;
1403 static void resume_cb(struct slave_node *slave, const struct packet *packet, void *data)
1407 if (slave->state == SLAVE_REQUEST_TO_TERMINATE) {
1408 DbgPrint("Slave is terminating now. ignore resume result\n");
1413 ErrPrint("Failed to change the state of the slave\n");
1414 slave->state = SLAVE_PAUSED;
1418 if (packet_get(packet, "i", &ret) != 1) {
1419 ErrPrint("Invalid parameter\n");
1424 slave->state = SLAVE_RESUMED;
1425 slave_rpc_ping_thaw(slave);
1426 invoke_resumed_cb(slave);
1430 static inline void invoke_paused_cb(struct slave_node *slave)
1434 struct event *event;
1436 slave->in_event_process |= SLAVE_EVENT_PROCESS_PAUSE;
1437 EINA_LIST_FOREACH_SAFE(slave->event_pause_list, l, n, event) {
1438 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
1439 slave->event_pause_list = eina_list_remove(slave->event_pause_list, event);
1443 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_PAUSE;
1446 static void pause_cb(struct slave_node *slave, const struct packet *packet, void *data)
1450 if (slave->state == SLAVE_REQUEST_TO_TERMINATE) {
1451 DbgPrint("Slave is terminating now. ignore pause result\n");
1456 ErrPrint("Failed to change the state of the slave\n");
1457 slave->state = SLAVE_RESUMED;
1461 if (packet_get(packet, "i", &ret) != 1) {
1462 ErrPrint("Invalid parameter\n");
1467 slave->state = SLAVE_PAUSED;
1468 slave_rpc_ping_freeze(slave);
1469 invoke_paused_cb(slave);
1473 HAPI int slave_resume(struct slave_node *slave)
1476 struct packet *packet;
1478 switch (slave->state) {
1479 case SLAVE_REQUEST_TO_LAUNCH:
1480 case SLAVE_REQUEST_TO_TERMINATE:
1481 case SLAVE_TERMINATED:
1482 return LB_STATUS_ERROR_INVALID;
1484 case SLAVE_REQUEST_TO_RESUME:
1485 return LB_STATUS_SUCCESS;
1490 timestamp = util_timestamp();
1492 packet = packet_create("resume", "d", timestamp);
1494 ErrPrint("Failed to prepare param\n");
1495 return LB_STATUS_ERROR_FAULT;
1498 slave->state = SLAVE_REQUEST_TO_RESUME;
1499 return slave_rpc_async_request(slave, NULL, packet, resume_cb, NULL, 0);
1502 HAPI int slave_pause(struct slave_node *slave)
1505 struct packet *packet;
1507 switch (slave->state) {
1508 case SLAVE_REQUEST_TO_LAUNCH:
1509 case SLAVE_REQUEST_TO_TERMINATE:
1510 case SLAVE_TERMINATED:
1511 return LB_STATUS_ERROR_INVALID;
1513 case SLAVE_REQUEST_TO_PAUSE:
1514 return LB_STATUS_SUCCESS;
1519 timestamp = util_timestamp();
1521 packet = packet_create("pause", "d", timestamp);
1523 ErrPrint("Failed to prepare param\n");
1524 return LB_STATUS_ERROR_FAULT;
1527 slave->state = SLAVE_REQUEST_TO_PAUSE;
1528 return slave_rpc_async_request(slave, NULL, packet, pause_cb, NULL, 0);
1531 HAPI const char *slave_pkgname(const struct slave_node *slave)
1533 return slave ? slave->pkgname : NULL;
1536 HAPI enum slave_state slave_state(const struct slave_node *slave)
1538 return slave ? slave->state : SLAVE_ERROR;
1541 HAPI const char *slave_state_string(const struct slave_node *slave)
1543 switch (slave->state) {
1544 case SLAVE_REQUEST_TO_LAUNCH:
1545 return "RequestToLaunch";
1546 case SLAVE_REQUEST_TO_TERMINATE:
1547 return "RequestToTerminate";
1548 case SLAVE_TERMINATED:
1549 return "Terminated";
1550 case SLAVE_REQUEST_TO_PAUSE:
1551 return "RequestToPause";
1552 case SLAVE_REQUEST_TO_RESUME:
1553 return "RequestToResume";
1567 HAPI const void *slave_list(void)
1569 return s_info.slave_list;
1572 HAPI int const slave_fault_count(const struct slave_node *slave)
1574 return slave->fault_count;
1577 HAPI double const slave_ttl(const struct slave_node *slave)
1579 if (!slave->ttl_timer) {
1583 return ecore_timer_pending_get(slave->ttl_timer);
1586 HAPI void slave_set_reactivate_instances(struct slave_node *slave, int reactivate)
1588 slave->reactivate_instances = reactivate;
1591 HAPI int slave_need_to_reactivate_instances(struct slave_node *slave)
1593 return slave->reactivate_instances;
1596 HAPI void slave_set_reactivation(struct slave_node *slave, int flag)
1598 slave->reactivate_slave = flag;
1601 HAPI int slave_need_to_reactivate(struct slave_node *slave)
1603 return slave->reactivate_slave;
1606 HAPI int slave_network(const struct slave_node *slave)
1608 return slave->network;
1611 HAPI void slave_set_network(struct slave_node *slave, int network)
1613 slave->network = network;
1616 HAPI int slave_deactivate_all(int reactivate, int reactivate_instances)
1620 struct slave_node *slave;
1623 s_info.deactivate_all_refcnt++;
1624 if (s_info.deactivate_all_refcnt > 1) {
1627 DbgPrint("Deactivate all\n");
1629 EINA_LIST_FOREACH_SAFE(s_info.slave_list, l, n, slave) {
1630 slave_set_reactivate_instances(slave, reactivate_instances);
1631 slave_set_reactivation(slave, reactivate);
1633 if (!slave_deactivate(slave, 0)) {
1634 s_info.slave_list = eina_list_remove(s_info.slave_list, slave);
1643 HAPI int slave_activate_all(void)
1646 struct slave_node *slave;
1649 s_info.deactivate_all_refcnt--;
1650 if (s_info.deactivate_all_refcnt > 0) {
1653 DbgPrint("Activate all\n");
1655 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1656 slave_activate(slave);