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;
69 Eina_List *event_activate_list;
70 Eina_List *event_deactivate_list;
71 Eina_List *event_delete_list;
72 Eina_List *event_fault_list;
73 Eina_List *event_pause_list;
74 Eina_List *event_resume_list;
78 Ecore_Timer *ttl_timer; /* Time to live */
79 Ecore_Timer *activate_timer; /* Waiting hello packet for this time */
81 struct timeval activated_at;
85 struct slave_node *slave;
87 int (*evt_cb)(struct slave_node *, void *);
97 Eina_List *slave_list;
102 static Eina_Bool slave_ttl_cb(void *data)
104 struct slave_node *slave = (struct slave_node *)data;
108 * ttl_timer must has to be set to NULL before deactivate the slave
109 * It will be used for making decision of the expired TTL timer or the fault of a livebox.
111 slave->ttl_timer = NULL;
113 slave_set_reactivation(slave, 0);
114 slave_set_reactivate_instances(slave, 1);
116 slave = slave_deactivate(slave);
117 DbgPrint("Slave is deactivated(%p)\n", slave);
119 /*! To recover all instances state it is activated again */
120 return ECORE_CALLBACK_CANCEL;
123 static inline int xmonitor_pause_cb(void *data)
126 return LB_STATUS_SUCCESS;
129 static inline int xmonitor_resume_cb(void *data)
132 return LB_STATUS_SUCCESS;
135 static inline struct slave_node *create_slave_node(const char *name, int is_secured, const char *abi, const char *pkgname, int network)
137 struct slave_node *slave;
139 slave = calloc(1, sizeof(*slave));
141 ErrPrint("Heap: %s\n", strerror(errno));
145 slave->name = strdup(name);
147 ErrPrint("Heap: %s\n", strerror(errno));
152 slave->abi = strdup(abi);
154 ErrPrint("Heap: %s\n", strerror(errno));
155 DbgFree(slave->name);
160 slave->pkgname = strdup(pkgname);
161 if (!slave->pkgname) {
162 ErrPrint("Heap: %s\n", strerror(errno));
164 DbgFree(slave->name);
169 slave->secured = is_secured;
170 slave->pid = (pid_t)-1;
171 slave->state = SLAVE_TERMINATED;
172 slave->network = network;
174 xmonitor_add_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
175 xmonitor_add_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
177 s_info.slave_list = eina_list_append(s_info.slave_list, slave);
181 static inline void invoke_delete_cb(struct slave_node *slave)
188 EINA_LIST_FOREACH_SAFE(slave->event_delete_list, l, n, event) {
189 ret = event->evt_cb(event->slave, event->cbdata);
191 if (eina_list_data_find(slave->event_delete_list, event)) {
192 slave->event_delete_list = eina_list_remove(slave->event_delete_list, event);
199 static inline void destroy_slave_node(struct slave_node *slave)
202 struct priv_data *priv;
204 if (slave_pid(slave) != (pid_t)-1) {
205 ErrPrint("Slave is not deactivated\n");
209 xmonitor_del_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
210 xmonitor_del_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
212 invoke_delete_cb(slave);
213 slave_rpc_fini(slave); /*!< Finalize the RPC after handling all delete callbacks */
215 EINA_LIST_FREE(slave->event_delete_list, event) {
219 EINA_LIST_FREE(slave->event_activate_list, event) {
223 EINA_LIST_FREE(slave->event_deactivate_list, event) {
227 EINA_LIST_FREE(slave->event_fault_list, event) {
231 EINA_LIST_FREE(slave->data_list, priv) {
236 s_info.slave_list = eina_list_remove(s_info.slave_list, slave);
238 if (slave->ttl_timer)
239 ecore_timer_del(slave->ttl_timer);
241 if (slave->activate_timer)
242 ecore_timer_del(slave->activate_timer);
245 DbgFree(slave->name);
246 DbgFree(slave->pkgname);
251 static inline struct slave_node *find_slave(const char *name)
253 struct slave_node *slave;
256 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
257 if (!strcmp(slave->name, name))
264 HAPI int slave_expired_ttl(struct slave_node *slave)
272 return !!slave->ttl_timer;
275 HAPI struct slave_node *slave_ref(struct slave_node *slave)
284 HAPI struct slave_node *slave_unref(struct slave_node *slave)
289 if (slave->refcnt == 0) {
290 ErrPrint("Slave refcnt is not valid\n");
295 if (slave->refcnt == 0) {
296 destroy_slave_node(slave);
303 HAPI const int const slave_refcnt(struct slave_node *slave)
305 return slave->refcnt;
308 HAPI struct slave_node *slave_create(const char *name, int is_secured, const char *abi, const char *pkgname, int network)
310 struct slave_node *slave;
312 slave = find_slave(name);
314 if (slave->secured != is_secured)
315 ErrPrint("Exists slave and creating slave's security flag is not matched\n");
319 slave = create_slave_node(name, is_secured, abi, pkgname, network);
324 slave_rpc_init(slave);
331 * Before destroying slave object,
332 * you should check the RPC(slave_async_XXX) state and Private data field (slave_set_data)
334 HAPI void slave_destroy(struct slave_node *slave)
339 static inline void invoke_fault_cb(struct slave_node *slave)
346 EINA_LIST_FOREACH_SAFE(slave->event_fault_list, l, n, event) {
347 ret = event->evt_cb(event->slave, event->cbdata);
349 if (eina_list_data_find(slave->event_fault_list, event)) {
350 slave->event_fault_list = eina_list_remove(slave->event_fault_list, event);
357 static inline void invoke_activate_cb(struct slave_node *slave)
364 EINA_LIST_FOREACH_SAFE(slave->event_activate_list, l, n, event) {
365 ret = event->evt_cb(event->slave, event->cbdata);
367 if (eina_list_data_find(slave->event_activate_list, event)) {
368 slave->event_activate_list = eina_list_remove(slave->event_activate_list, event);
375 static Eina_Bool activate_timer_cb(void *data)
377 struct slave_node *slave = data;
379 slave->fault_count++;
380 invoke_fault_cb(slave);
382 slave_set_reactivation(slave, 0);
383 slave_set_reactivate_instances(slave, 0);
385 slave->activate_timer = NULL;
386 if (slave_pid(slave) > 0) {
388 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
389 ret = aul_terminate_pid(slave_pid(slave));
391 ErrPrint("Terminate failed, pid %d (reason: %d)\n", slave_pid(slave), ret);
394 CRITICAL_LOG("Slave is not activated in %lf sec (slave: %s)\n", SLAVE_ACTIVATE_TIME, slave_name(slave));
395 slave = slave_deactivated(slave);
396 return ECORE_CALLBACK_CANCEL;
399 HAPI int slave_activate(struct slave_node *slave)
403 * This check code can be replaced with the slave->state check code
404 * If the slave data has the PID, it means, it is activated
405 * Even if it is in the termiating sequence, it will have the PID
406 * before terminated at last.
407 * So we can use this simple code for checking the slave's last state.
408 * about it is alive? or not.
410 if (slave_pid(slave) != (pid_t)-1) {
411 if (slave_state(slave) == SLAVE_REQUEST_TO_TERMINATE)
412 slave_set_reactivation(slave, 1);
413 return LB_STATUS_ERROR_ALREADY;
414 } else if (slave_state(slave) == SLAVE_REQUEST_TO_LAUNCH) {
415 DbgPrint("Slave is already launched: but the AUL is timed out\n");
416 return LB_STATUS_ERROR_ALREADY;
420 DbgPrint("Debug Mode enabled. name[%s] secured[%d] abi[%s]\n", slave_name(slave), slave->secured, slave->abi);
424 param = bundle_create();
426 ErrPrint("Failed to create a bundle\n");
427 return LB_STATUS_ERROR_FAULT;
430 bundle_add(param, BUNDLE_SLAVE_NAME, slave_name(slave));
431 bundle_add(param, BUNDLE_SLAVE_SECURED, slave->secured ? "true" : "false");
432 bundle_add(param, BUNDLE_SLAVE_ABI, slave->abi);
434 slave->pid = (pid_t)aul_launch_app(slave_pkgname(slave), param);
438 if (slave->pid < 0) {
439 CRITICAL_LOG("Failed to launch a new slave %s (%d)\n", slave_name(slave), slave->pid);
440 if (slave->pid != AUL_R_ETIMEOUT && slave->pid != AUL_R_ECOMM) {
441 ErrPrint("failed, because of %d\n", slave->pid);
442 slave->pid = (pid_t)-1;
443 return LB_STATUS_ERROR_FAULT;
445 ErrPrint("But waiting \"hello\"\n");
446 slave->pid = (pid_t)-1;
449 DbgPrint("Slave %s is launched with %d as %s\n", slave_pkgname(slave), slave->pid, slave_name(slave));
451 slave->activate_timer = ecore_timer_add(SLAVE_ACTIVATE_TIME, activate_timer_cb, slave);
452 if (!slave->activate_timer)
453 ErrPrint("Failed to register an activate timer\n");
456 slave->state = SLAVE_REQUEST_TO_LAUNCH;
459 * Increase the refcnt of a slave,
460 * To prevent from making an orphan(slave).
462 (void)slave_ref(slave);
464 return LB_STATUS_SUCCESS;
467 HAPI int slave_give_more_ttl(struct slave_node *slave)
471 if (!slave->secured || !slave->ttl_timer)
472 return LB_STATUS_ERROR_INVALID;
474 delay = SLAVE_TTL - ecore_timer_pending_get(slave->ttl_timer);
475 ecore_timer_delay(slave->ttl_timer, delay);
476 return LB_STATUS_SUCCESS;
479 HAPI int slave_freeze_ttl(struct slave_node *slave)
481 if (!slave->secured || !slave->ttl_timer)
482 return LB_STATUS_ERROR_INVALID;
484 ecore_timer_freeze(slave->ttl_timer);
485 return LB_STATUS_SUCCESS;
488 HAPI int slave_thaw_ttl(struct slave_node *slave)
492 if (!slave->secured || !slave->ttl_timer)
493 return LB_STATUS_ERROR_INVALID;
495 ecore_timer_thaw(slave->ttl_timer);
497 delay = SLAVE_TTL - ecore_timer_pending_get(slave->ttl_timer);
498 ecore_timer_delay(slave->ttl_timer, delay);
499 return LB_STATUS_SUCCESS;
502 HAPI int slave_activated(struct slave_node *slave)
504 slave->state = SLAVE_RESUMED;
506 if (xmonitor_is_paused())
509 if (slave->secured == 1) {
510 DbgPrint("Slave deactivation timer is added (%s - %lf)\n", slave_name(slave), SLAVE_TTL);
511 slave->ttl_timer = ecore_timer_add(SLAVE_TTL, slave_ttl_cb, slave);
512 if (!slave->ttl_timer)
513 ErrPrint("Failed to create a TTL timer\n");
516 invoke_activate_cb(slave);
518 slave_set_reactivation(slave, 0);
519 slave_set_reactivate_instances(slave, 0);
521 if (gettimeofday(&slave->activated_at, NULL) < 0) {
522 ErrPrint("Failed to get time of day: %s\n", strerror(errno));
523 slave->activated_at.tv_sec = 0;
524 slave->activated_at.tv_usec = 0;
527 if (slave->activate_timer) {
528 ecore_timer_del(slave->activate_timer);
529 slave->activate_timer = NULL;
532 return LB_STATUS_SUCCESS;
535 static inline int invoke_deactivate_cb(struct slave_node *slave)
543 EINA_LIST_FOREACH_SAFE(slave->event_deactivate_list, l, n, event) {
544 ret = event->evt_cb(event->slave, event->cbdata);
546 if (eina_list_data_find(slave->event_deactivate_list, event)) {
547 slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, event);
550 } else if (ret == SLAVE_NEED_TO_REACTIVATE) {
558 HAPI struct slave_node *slave_deactivate(struct slave_node *slave)
562 if (!slave_is_activated(slave)) {
563 ErrPrint("Slave is already deactivated\n");
564 if (slave_loaded_instance(slave) == 0) {
567 * If a slave has no more instances,
570 slave = slave_unref(slave);
577 * check the return value of the aul_terminate_pid
579 slave->state = SLAVE_REQUEST_TO_TERMINATE;
581 if (slave_pid(slave) > 0) {
582 DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave));
583 ret = aul_terminate_pid(slave->pid);
585 ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret);
586 slave = slave_deactivated(slave);
593 HAPI struct slave_node *slave_deactivated(struct slave_node *slave)
597 slave->pid = (pid_t)-1;
598 slave->state = SLAVE_TERMINATED;
600 if (slave->ttl_timer) {
601 ecore_timer_del(slave->ttl_timer);
602 slave->ttl_timer = NULL;
605 if (slave->activate_timer) {
606 ecore_timer_del(slave->activate_timer);
607 slave->activate_timer = NULL;
610 reactivate = invoke_deactivate_cb(slave);
612 slave = slave_unref(slave);
614 DbgPrint("SLAVE object is destroyed\n");
618 if (reactivate && slave_need_to_reactivate(slave)) {
621 DbgPrint("Need to reactivate a slave\n");
622 ret = slave_activate(slave);
623 if (ret < 0 && ret != LB_STATUS_ERROR_ALREADY)
624 ErrPrint("Failed to reactivate a slave\n");
625 } else if (slave_loaded_instance(slave) == 0) {
628 * If a slave has no more instances,
631 slave = slave_unref(slave);
637 HAPI struct slave_node *slave_deactivated_by_fault(struct slave_node *slave)
640 struct timeval faulted_at;
642 int reactivate_instances = 1;
644 if (!slave_is_activated(slave)) {
645 DbgPrint("Deactivating in progress\n");
646 if (slave_loaded_instance(slave) == 0)
647 slave = slave_unref(slave);
652 slave->fault_count++;
654 (void)fault_check_pkgs(slave);
656 if (slave_pid(slave) > 0) {
657 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
658 ret = aul_terminate_pid(slave_pid(slave));
660 ErrPrint("Terminate failed, pid %d\n", slave_pid(slave));
664 if (gettimeofday(&faulted_at, NULL) == 0) {
667 timersub(&faulted_at, &slave->activated_at, &rtv);
668 if (rtv.tv_sec < MINIMUM_REACTIVATION_TIME) {
669 slave->critical_fault_count++;
670 if (!slave_loaded_instance(slave) || slave->critical_fault_count >= SLAVE_MAX_LOAD) {
671 ErrPrint("Reactivation time is too fast and frequently occurred - Stop to auto reactivation\n");
673 reactivate_instances = 0;
674 slave->critical_fault_count = 0;
677 * Fault callback can access the slave information.
679 invoke_fault_cb(slave);
682 slave->critical_fault_count = 0;
685 ErrPrint("Failed to get time of day: %s\n", strerror(errno));
688 slave_set_reactivation(slave, reactivate);
689 slave_set_reactivate_instances(slave, reactivate_instances);
691 slave = slave_deactivated(slave);
695 HAPI const int const slave_is_activated(struct slave_node *slave)
697 switch (slave->state) {
698 case SLAVE_REQUEST_TO_TERMINATE:
699 case SLAVE_TERMINATED:
701 case SLAVE_REQUEST_TO_LAUNCH:
702 /* Not yet launched. but the slave incurred an unexpected error */
703 case SLAVE_REQUEST_TO_PAUSE:
704 case SLAVE_REQUEST_TO_RESUME:
709 return slave->pid != (pid_t)-1;
712 /* Could not be reach to here */
716 HAPI int slave_event_callback_add(struct slave_node *slave, enum slave_event event, int (*cb)(struct slave_node *, void *), void *data)
720 ev = calloc(1, sizeof(*ev));
722 ErrPrint("Heap: %s\n", strerror(errno));
723 return LB_STATUS_ERROR_MEMORY;
732 * Use the eina_list_prepend API.
733 * To keep the sequence of a callback invocation.
735 * Here is an example sequence.
737 * slave_event_callback_add(CALLBACK_01);
738 * slave_event_callback_add(CALLBACK_02);
739 * slave_event_callback_add(CALLBACK_03);
741 * Then the invoke_event_callback function will call the CALLBACKS as below sequence
749 case SLAVE_EVENT_ACTIVATE:
750 slave->event_activate_list = eina_list_prepend(slave->event_activate_list, ev);
752 case SLAVE_EVENT_DELETE:
753 slave->event_delete_list = eina_list_prepend(slave->event_delete_list, ev);
755 case SLAVE_EVENT_DEACTIVATE:
756 slave->event_deactivate_list = eina_list_prepend(slave->event_deactivate_list, ev);
758 case SLAVE_EVENT_PAUSE:
759 slave->event_pause_list = eina_list_prepend(slave->event_pause_list, ev);
761 case SLAVE_EVENT_RESUME:
762 slave->event_resume_list = eina_list_prepend(slave->event_resume_list, ev);
764 case SLAVE_EVENT_FAULT:
765 slave->event_fault_list = eina_list_prepend(slave->event_fault_list, ev);
769 return LB_STATUS_ERROR_INVALID;
772 return LB_STATUS_SUCCESS;
775 HAPI int slave_event_callback_del(struct slave_node *slave, enum slave_event event, int (*cb)(struct slave_node *, void *), void *data)
782 case SLAVE_EVENT_DEACTIVATE:
783 EINA_LIST_FOREACH_SAFE(slave->event_deactivate_list, l, n, ev) {
784 if (ev->evt_cb == cb && ev->cbdata == data) {
785 slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, ev);
787 return LB_STATUS_SUCCESS;
791 case SLAVE_EVENT_DELETE:
792 EINA_LIST_FOREACH_SAFE(slave->event_delete_list, l, n, ev) {
793 if (ev->evt_cb == cb && ev->cbdata == data) {
794 slave->event_delete_list = eina_list_remove(slave->event_delete_list, ev);
796 return LB_STATUS_SUCCESS;
800 case SLAVE_EVENT_ACTIVATE:
801 EINA_LIST_FOREACH_SAFE(slave->event_activate_list, l, n, ev) {
802 if (ev->evt_cb == cb && ev->cbdata == data) {
803 slave->event_activate_list = eina_list_remove(slave->event_activate_list, ev);
805 return LB_STATUS_SUCCESS;
809 case SLAVE_EVENT_PAUSE:
810 EINA_LIST_FOREACH_SAFE(slave->event_pause_list, l, n, ev) {
811 if (ev->evt_cb == cb && ev->cbdata == data) {
812 slave->event_pause_list = eina_list_remove(slave->event_pause_list, ev);
814 return LB_STATUS_SUCCESS;
818 case SLAVE_EVENT_RESUME:
819 EINA_LIST_FOREACH_SAFE(slave->event_resume_list, l, n, ev) {
820 if (ev->evt_cb == cb && ev->cbdata == data) {
821 slave->event_resume_list = eina_list_remove(slave->event_resume_list, ev);
823 return LB_STATUS_SUCCESS;
827 case SLAVE_EVENT_FAULT:
828 EINA_LIST_FOREACH_SAFE(slave->event_fault_list, l, n, ev) {
829 if (ev->evt_cb == cb && ev->cbdata == data) {
830 slave->event_fault_list = eina_list_remove(slave->event_fault_list, ev);
832 return LB_STATUS_SUCCESS;
837 return LB_STATUS_ERROR_INVALID;
840 return LB_STATUS_ERROR_NOT_EXIST;
843 HAPI int slave_set_data(struct slave_node *slave, const char *tag, void *data)
845 struct priv_data *priv;
847 priv = calloc(1, sizeof(*priv));
849 ErrPrint("Heap: %s\n", strerror(errno));
850 return LB_STATUS_ERROR_MEMORY;
853 priv->tag = strdup(tag);
855 ErrPrint("Heap: %s\n", strerror(errno));
857 return LB_STATUS_ERROR_MEMORY;
861 slave->data_list = eina_list_append(slave->data_list, priv);
862 return LB_STATUS_SUCCESS;
865 HAPI void *slave_del_data(struct slave_node *slave, const char *tag)
867 struct priv_data *priv;
872 EINA_LIST_FOREACH_SAFE(slave->data_list, l, n, priv) {
873 if (!strcmp(priv->tag, tag)) {
874 slave->data_list = eina_list_remove(slave->data_list, priv);
886 HAPI void *slave_data(struct slave_node *slave, const char *tag)
888 struct priv_data *priv;
891 EINA_LIST_FOREACH(slave->data_list, l, priv) {
892 if (!strcmp(priv->tag, tag))
899 HAPI struct slave_node *slave_find_by_pid(pid_t pid)
902 struct slave_node *slave;
904 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
905 if (slave_pid(slave) == pid)
912 HAPI struct slave_node *slave_find_by_name(const char *name)
915 struct slave_node *slave;
917 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
918 if (!strcmp(slave_name(slave), name))
925 HAPI struct slave_node *slave_find_available(const char *abi, int secured, int network)
928 struct slave_node *slave;
930 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
931 if (slave->secured != secured)
934 if (slave->state == SLAVE_REQUEST_TO_TERMINATE && slave->loaded_instance == 0) {
937 * If a slave is in request_to_terminate state,
938 * and the slave object has no more intances,
939 * the slave object will be deleted soon.
940 * so we cannot reuse it.
942 * This object is not usable.
947 if (strcasecmp(slave->abi, abi))
950 if (slave->secured) {
951 if (slave->loaded_package == 0) {
952 DbgPrint("Found secured slave - has no instances (%s)\n", slave_name(slave));
955 } else if (slave->network == network) {
956 DbgPrint("slave[%s] loaded_package[%d] net: [%d]\n", slave_name(slave), slave->loaded_package, slave->network);
957 if (!strcasecmp(abi, DEFAULT_ABI)) {
958 if (slave->loaded_package < SLAVE_MAX_LOAD)
969 HAPI struct slave_node *slave_find_by_pkgname(const char *pkgname)
972 struct slave_node *slave;
974 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
975 if (!strcmp(slave_pkgname(slave), pkgname)) {
976 if (slave_pid(slave) == (pid_t)-1) {
985 HAPI struct slave_node *slave_find_by_rpc_handle(int handle)
988 struct slave_node *slave;
991 ErrPrint("Invalid RPC handle: %d\n", handle);
995 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
996 if (slave_rpc_handle(slave) == handle)
1004 HAPI void slave_load_package(struct slave_node *slave)
1006 slave->loaded_package++;
1009 HAPI void slave_unload_package(struct slave_node *slave)
1011 if (!slave || slave->loaded_package == 0) {
1012 ErrPrint("Slave loaded package is not correct\n");
1016 slave->loaded_package--;
1019 HAPI void slave_load_instance(struct slave_node *slave)
1021 slave->loaded_instance++;
1022 DbgPrint("Instance: (%d)%d\n", slave_pid(slave), slave->loaded_instance);
1025 HAPI int const slave_loaded_instance(struct slave_node *slave)
1027 return slave->loaded_instance;
1030 HAPI int const slave_loaded_package(struct slave_node *slave)
1032 return slave->loaded_package;
1035 HAPI struct slave_node *slave_unload_instance(struct slave_node *slave)
1037 if (!slave || slave->loaded_instance == 0) {
1038 ErrPrint("Slave loaded instance is not correct\n");
1042 slave->loaded_instance--;
1043 DbgPrint("Instance: (%d)%d\n", slave_pid(slave), slave->loaded_instance);
1044 if (slave->loaded_instance == 0 && slave_is_activated(slave)) {
1045 slave_set_reactivation(slave, 0);
1046 slave_set_reactivate_instances(slave, 0);
1048 slave = slave_deactivate(slave);
1054 HAPI const int const slave_is_secured(const struct slave_node *slave)
1056 return slave->secured;
1059 HAPI const char * const slave_name(const struct slave_node *slave)
1064 HAPI const char * const slave_abi(const struct slave_node *slave)
1069 HAPI const pid_t const slave_pid(const struct slave_node *slave)
1074 HAPI int slave_set_pid(struct slave_node *slave, pid_t pid)
1077 return LB_STATUS_ERROR_INVALID;
1079 DbgPrint("Slave PID is updated to %d from %d\n", pid, slave_pid(slave));
1082 return LB_STATUS_SUCCESS;
1085 static inline void invoke_resumed_cb(struct slave_node *slave)
1089 struct event *event;
1092 EINA_LIST_FOREACH_SAFE(slave->event_resume_list, l, n, event) {
1093 ret = event->evt_cb(event->slave, event->cbdata);
1095 if (eina_list_data_find(slave->event_resume_list, event)) {
1096 slave->event_resume_list = eina_list_remove(slave->event_resume_list, event);
1103 static void resume_cb(struct slave_node *slave, const struct packet *packet, void *data)
1107 if (slave->state == SLAVE_REQUEST_TO_TERMINATE) {
1108 DbgPrint("Slave is terminating now. ignore resume result\n");
1113 ErrPrint("Failed to change the state of the slave\n");
1114 slave->state = SLAVE_PAUSED;
1118 if (packet_get(packet, "i", &ret) != 1) {
1119 ErrPrint("Invalid parameter\n");
1124 slave->state = SLAVE_RESUMED;
1125 slave_rpc_ping_thaw(slave);
1126 invoke_resumed_cb(slave);
1130 static inline void invoke_paused_cb(struct slave_node *slave)
1134 struct event *event;
1137 EINA_LIST_FOREACH_SAFE(slave->event_pause_list, l, n, event) {
1138 ret = event->evt_cb(event->slave, event->cbdata);
1140 if (eina_list_data_find(slave->event_pause_list, event)) {
1141 slave->event_pause_list = eina_list_remove(slave->event_pause_list, event);
1148 static void pause_cb(struct slave_node *slave, const struct packet *packet, void *data)
1152 if (slave->state == SLAVE_REQUEST_TO_TERMINATE) {
1153 DbgPrint("Slave is terminating now. ignore pause result\n");
1158 ErrPrint("Failed to change the state of the slave\n");
1159 slave->state = SLAVE_RESUMED;
1163 if (packet_get(packet, "i", &ret) != 1) {
1164 ErrPrint("Invalid parameter\n");
1169 slave->state = SLAVE_PAUSED;
1170 slave_rpc_ping_freeze(slave);
1171 invoke_paused_cb(slave);
1175 HAPI int slave_resume(struct slave_node *slave)
1178 struct packet *packet;
1180 switch (slave->state) {
1181 case SLAVE_REQUEST_TO_LAUNCH:
1182 case SLAVE_REQUEST_TO_TERMINATE:
1183 case SLAVE_TERMINATED:
1184 return LB_STATUS_ERROR_INVALID;
1186 case SLAVE_REQUEST_TO_RESUME:
1187 return LB_STATUS_SUCCESS;
1192 timestamp = util_timestamp();
1194 packet = packet_create("resume", "d", timestamp);
1196 ErrPrint("Failed to prepare param\n");
1197 return LB_STATUS_ERROR_FAULT;
1200 slave->state = SLAVE_REQUEST_TO_RESUME;
1201 return slave_rpc_async_request(slave, NULL, packet, resume_cb, NULL, 0);
1204 HAPI int slave_pause(struct slave_node *slave)
1207 struct packet *packet;
1209 switch (slave->state) {
1210 case SLAVE_REQUEST_TO_LAUNCH:
1211 case SLAVE_REQUEST_TO_TERMINATE:
1212 case SLAVE_TERMINATED:
1213 return LB_STATUS_ERROR_INVALID;
1215 case SLAVE_REQUEST_TO_PAUSE:
1216 return LB_STATUS_SUCCESS;
1221 timestamp = util_timestamp();
1223 packet = packet_create("pause", "d", timestamp);
1225 ErrPrint("Failed to prepare param\n");
1226 return LB_STATUS_ERROR_FAULT;
1229 slave->state = SLAVE_REQUEST_TO_PAUSE;
1230 return slave_rpc_async_request(slave, NULL, packet, pause_cb, NULL, 0);
1233 HAPI const char *slave_pkgname(const struct slave_node *slave)
1235 return slave ? slave->pkgname : NULL;
1238 HAPI enum slave_state slave_state(const struct slave_node *slave)
1240 return slave ? slave->state : SLAVE_ERROR;
1243 HAPI const char *slave_state_string(const struct slave_node *slave)
1245 switch (slave->state) {
1246 case SLAVE_REQUEST_TO_LAUNCH:
1247 return "RequestToLaunch";
1248 case SLAVE_REQUEST_TO_TERMINATE:
1249 return "RequestToTerminate";
1250 case SLAVE_TERMINATED:
1251 return "Terminated";
1252 case SLAVE_REQUEST_TO_PAUSE:
1253 return "RequestToPause";
1254 case SLAVE_REQUEST_TO_RESUME:
1255 return "RequestToResume";
1269 HAPI const void *slave_list(void)
1271 return s_info.slave_list;
1274 HAPI int const slave_fault_count(const struct slave_node *slave)
1276 return slave->fault_count;
1279 HAPI double const slave_ttl(const struct slave_node *slave)
1281 if (!slave->ttl_timer)
1284 return ecore_timer_pending_get(slave->ttl_timer);
1287 HAPI void slave_set_reactivate_instances(struct slave_node *slave, int reactivate)
1289 slave->reactivate_instances = reactivate;
1292 HAPI int slave_need_to_reactivate_instances(struct slave_node *slave)
1294 return slave->reactivate_instances;
1297 HAPI void slave_set_reactivation(struct slave_node *slave, int flag)
1299 slave->reactivate_slave = flag;
1302 HAPI int slave_need_to_reactivate(struct slave_node *slave)
1304 return slave->reactivate_slave;
1307 HAPI int slave_network(const struct slave_node *slave)
1309 return slave->network;
1312 HAPI void slave_set_network(struct slave_node *slave, int network)
1314 slave->network = network;
1317 HAPI int slave_deactivate_all(int reactivate, int reactivate_instances)
1321 struct slave_node *slave;
1324 EINA_LIST_FOREACH_SAFE(s_info.slave_list, l, n, slave) {
1325 slave_set_reactivate_instances(slave, reactivate_instances);
1326 slave_set_reactivation(slave, reactivate);
1328 if (!slave_deactivate(slave))
1329 s_info.slave_list = eina_list_remove(s_info.slave_list, slave);
1337 HAPI int slave_activate_all(void)
1340 struct slave_node *slave;
1343 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1344 slave_activate(slave);