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 "slave_life.h"
37 #include "slave_rpc.h"
38 #include "client_life.h"
39 #include "fault_manager.h"
53 int secured; /* Only A package(livebox) is loaded for security requirements */
56 int critical_fault_count;
57 enum slave_state state;
63 int reactivate_instances;
68 Eina_List *event_activate_list;
69 Eina_List *event_deactivate_list;
70 Eina_List *event_delete_list;
71 Eina_List *event_fault_list;
72 Eina_List *event_pause_list;
73 Eina_List *event_resume_list;
77 Ecore_Timer *ttl_timer; /* Time to live */
78 Ecore_Timer *activate_timer; /* Waiting hello packet for this time */
80 struct timeval activated_at;
84 struct slave_node *slave;
86 int (*evt_cb)(struct slave_node *, void *);
96 Eina_List *slave_list;
101 static Eina_Bool slave_ttl_cb(void *data)
103 struct slave_node *slave = (struct slave_node *)data;
107 * ttl_timer must has to be set to NULL before deactivate the slave
108 * It will be used for making decision of the expired TTL timer or the fault of a livebox.
110 slave->ttl_timer = NULL;
112 slave_set_reactivation(slave, 0);
113 slave_set_reactivate_instances(slave, 1);
115 slave = slave_deactivate(slave);
116 DbgPrint("Slave is deactivated(%p)\n", slave);
118 /*! To recover all instances state it is activated again */
119 return ECORE_CALLBACK_CANCEL;
122 static inline int xmonitor_pause_cb(void *data)
125 return LB_STATUS_SUCCESS;
128 static inline int xmonitor_resume_cb(void *data)
131 return LB_STATUS_SUCCESS;
134 static inline struct slave_node *create_slave_node(const char *name, int is_secured, const char *abi, const char *pkgname, int network)
136 struct slave_node *slave;
138 slave = calloc(1, sizeof(*slave));
140 ErrPrint("Heap: %s\n", strerror(errno));
144 slave->name = strdup(name);
146 ErrPrint("Heap: %s\n", strerror(errno));
151 slave->abi = strdup(abi);
153 ErrPrint("Heap: %s\n", strerror(errno));
154 DbgFree(slave->name);
159 slave->pkgname = strdup(pkgname);
160 if (!slave->pkgname) {
161 ErrPrint("Heap: %s\n", strerror(errno));
163 DbgFree(slave->name);
168 slave->secured = is_secured;
169 slave->pid = (pid_t)-1;
170 slave->state = SLAVE_TERMINATED;
171 slave->network = network;
173 xmonitor_add_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
174 xmonitor_add_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
176 s_info.slave_list = eina_list_append(s_info.slave_list, slave);
177 DbgPrint("slave data is created %p\n", 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 != (pid_t)-1) {
205 ErrPrint("Slave is not deactivated\n");
209 DbgPrint("Slave data is destroyed %p\n", slave);
211 xmonitor_del_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
212 xmonitor_del_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
214 invoke_delete_cb(slave);
215 slave_rpc_fini(slave); /*!< Finalize the RPC after handling all delete callbacks */
217 EINA_LIST_FREE(slave->event_delete_list, event) {
221 EINA_LIST_FREE(slave->event_activate_list, event) {
225 EINA_LIST_FREE(slave->event_deactivate_list, event) {
229 EINA_LIST_FREE(slave->event_fault_list, event) {
233 EINA_LIST_FREE(slave->data_list, priv) {
238 s_info.slave_list = eina_list_remove(s_info.slave_list, slave);
240 if (slave->ttl_timer)
241 ecore_timer_del(slave->ttl_timer);
243 if (slave->activate_timer)
244 ecore_timer_del(slave->activate_timer);
247 DbgFree(slave->name);
248 DbgFree(slave->pkgname);
253 static inline struct slave_node *find_slave(const char *name)
255 struct slave_node *slave;
258 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
259 if (!strcmp(slave->name, name))
266 HAPI int slave_expired_ttl(struct slave_node *slave)
274 return !!slave->ttl_timer;
277 HAPI struct slave_node *slave_ref(struct slave_node *slave)
286 HAPI struct slave_node *slave_unref(struct slave_node *slave)
291 if (slave->refcnt == 0) {
292 ErrPrint("Slave refcnt is not valid\n");
297 if (slave->refcnt == 0) {
298 destroy_slave_node(slave);
305 HAPI const int const slave_refcnt(struct slave_node *slave)
307 return slave->refcnt;
310 HAPI struct slave_node *slave_create(const char *name, int is_secured, const char *abi, const char *pkgname, int network)
312 struct slave_node *slave;
314 slave = find_slave(name);
316 if (slave->secured != is_secured)
317 ErrPrint("Exists slave and creating slave's security flag is not matched\n");
321 slave = create_slave_node(name, is_secured, abi, pkgname, network);
326 slave_rpc_init(slave);
333 * Before destroying slave object,
334 * you should check the RPC(slave_async_XXX) state and Private data field (slave_set_data)
336 HAPI void slave_destroy(struct slave_node *slave)
341 static inline void invoke_fault_cb(struct slave_node *slave)
348 EINA_LIST_FOREACH_SAFE(slave->event_fault_list, l, n, event) {
349 ret = event->evt_cb(event->slave, event->cbdata);
351 if (eina_list_data_find(slave->event_fault_list, event)) {
352 slave->event_fault_list = eina_list_remove(slave->event_fault_list, event);
359 static inline void invoke_activate_cb(struct slave_node *slave)
366 EINA_LIST_FOREACH_SAFE(slave->event_activate_list, l, n, event) {
367 ret = event->evt_cb(event->slave, event->cbdata);
369 if (eina_list_data_find(slave->event_activate_list, event)) {
370 slave->event_activate_list = eina_list_remove(slave->event_activate_list, event);
377 static Eina_Bool activate_timer_cb(void *data)
379 struct slave_node *slave = data;
381 slave->fault_count++;
382 invoke_fault_cb(slave);
384 slave_set_reactivation(slave, 0);
385 slave_set_reactivate_instances(slave, 0);
387 slave->activate_timer = NULL;
388 if (slave->pid > 0) {
390 DbgPrint("Try to terminate PID: %d\n", slave->pid);
391 ret = aul_terminate_pid(slave->pid);
393 ErrPrint("Terminate failed, pid %d\n", slave->pid);
396 slave = slave_deactivated(slave);
397 ErrPrint("Slave is not activated in %lf sec (slave: %p)\n", SLAVE_ACTIVATE_TIME, slave);
398 return ECORE_CALLBACK_CANCEL;
401 HAPI int slave_activate(struct slave_node *slave)
406 * This check code can replace the slave->state check code
407 * If the slave data has the PID, it means, it is activated
408 * Even if it is in the termiating sequence, it will have the PID
409 * before terminated at last.
410 * So we can use this simple code for checking the slave's last state.
411 * about it is alive? or not.
413 if (slave->pid != (pid_t)-1)
414 return LB_STATUS_ERROR_ALREADY;
417 DbgPrint("Debug Mode enabled. name[%s] secured[%d] abi[%s]\n", slave->name, slave->secured, slave->abi);
420 param = bundle_create();
422 ErrPrint("Failed to create a bundle\n");
423 return LB_STATUS_ERROR_FAULT;
426 bundle_add(param, BUNDLE_SLAVE_NAME, slave->name);
427 bundle_add(param, BUNDLE_SLAVE_SECURED, slave->secured ? "true" : "false");
428 bundle_add(param, BUNDLE_SLAVE_ABI, slave->abi);
430 DbgPrint("Launch the slave package: %s\n", slave->pkgname);
431 slave->pid = (pid_t)aul_launch_app(slave->pkgname, param);
435 if (slave->pid < 0) {
436 ErrPrint("Failed to launch a new slave %s (%d)\n", slave->name, slave->pid);
437 slave->pid = (pid_t)-1;
438 return LB_STATUS_ERROR_FAULT;
440 DbgPrint("Slave launched %d for %s\n", slave->pid, slave->name);
442 slave->activate_timer = ecore_timer_add(SLAVE_ACTIVATE_TIME, activate_timer_cb, slave);
443 if (!slave->activate_timer)
444 ErrPrint("Failed to register an activate timer\n");
447 slave->state = SLAVE_REQUEST_TO_LAUNCH;
450 * Increase the refcnt of a slave,
451 * To prevent from making an orphan(slave).
455 return LB_STATUS_SUCCESS;
458 HAPI int slave_give_more_ttl(struct slave_node *slave)
462 if (!slave->secured || !slave->ttl_timer)
463 return LB_STATUS_ERROR_INVALID;
465 delay = SLAVE_TTL - ecore_timer_pending_get(slave->ttl_timer);
466 ecore_timer_delay(slave->ttl_timer, delay);
467 return LB_STATUS_SUCCESS;
470 HAPI int slave_freeze_ttl(struct slave_node *slave)
472 if (!slave->secured || !slave->ttl_timer)
473 return LB_STATUS_ERROR_INVALID;
475 ecore_timer_freeze(slave->ttl_timer);
476 return LB_STATUS_SUCCESS;
479 HAPI int slave_thaw_ttl(struct slave_node *slave)
483 if (!slave->secured || !slave->ttl_timer)
484 return LB_STATUS_ERROR_INVALID;
486 ecore_timer_thaw(slave->ttl_timer);
488 delay = SLAVE_TTL - ecore_timer_pending_get(slave->ttl_timer);
489 ecore_timer_delay(slave->ttl_timer, delay);
490 return LB_STATUS_SUCCESS;
493 HAPI int slave_activated(struct slave_node *slave)
495 slave->state = SLAVE_RESUMED;
497 if (xmonitor_is_paused())
500 if (slave->secured == 1) {
501 DbgPrint("Slave deactivation timer is added (%s - %lf)\n", slave->name, SLAVE_TTL);
502 slave->ttl_timer = ecore_timer_add(SLAVE_TTL, slave_ttl_cb, slave);
503 if (!slave->ttl_timer)
504 ErrPrint("Failed to create a TTL timer\n");
507 invoke_activate_cb(slave);
509 slave_set_reactivation(slave, 0);
510 slave_set_reactivate_instances(slave, 0);
512 if (gettimeofday(&slave->activated_at, NULL) < 0) {
513 ErrPrint("Failed to get time of day: %s\n", strerror(errno));
514 slave->activated_at.tv_sec = 0;
515 slave->activated_at.tv_usec = 0;
518 if (slave->activate_timer) {
519 ecore_timer_del(slave->activate_timer);
520 slave->activate_timer = NULL;
523 return LB_STATUS_SUCCESS;
526 static inline int invoke_deactivate_cb(struct slave_node *slave)
534 EINA_LIST_FOREACH_SAFE(slave->event_deactivate_list, l, n, event) {
535 ret = event->evt_cb(event->slave, event->cbdata);
537 if (eina_list_data_find(slave->event_deactivate_list, event)) {
538 slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, event);
541 } else if (ret == SLAVE_NEED_TO_REACTIVATE) {
549 HAPI struct slave_node *slave_deactivate(struct slave_node *slave)
553 if (!slave_is_activated(slave)) {
554 ErrPrint("Slave is already deactivated\n");
555 if (slave_loaded_instance(slave) == 0) {
558 * If a slave has no more instances,
561 slave = slave_unref(slave);
566 DbgPrint("Deactivate a slave: %d\n", slave->pid);
569 * check the return value of the aul_terminate_pid
571 slave->state = SLAVE_REQUEST_TO_TERMINATE;
573 DbgPrint("Terminate PID: %d\n", slave->pid);
574 if (slave->pid > 0) {
575 ret = aul_terminate_pid(slave->pid);
577 ErrPrint("Terminate failed. pid %d (%d)\n", slave->pid, ret);
578 slave = slave_deactivated(slave);
585 HAPI struct slave_node *slave_deactivated(struct slave_node *slave)
589 slave->pid = (pid_t)-1;
590 slave->state = SLAVE_TERMINATED;
592 if (slave->ttl_timer) {
593 ecore_timer_del(slave->ttl_timer);
594 slave->ttl_timer = NULL;
597 if (slave->activate_timer) {
598 ecore_timer_del(slave->activate_timer);
599 slave->activate_timer = NULL;
602 reactivate = invoke_deactivate_cb(slave);
604 slave = slave_unref(slave);
606 DbgPrint("SLAVE object is destroyed\n");
610 if (reactivate && slave_need_to_reactivate(slave)) {
613 DbgPrint("Need to reactivate a slave\n");
614 ret = slave_activate(slave);
615 if (ret < 0 && ret != LB_STATUS_ERROR_ALREADY)
616 ErrPrint("Failed to reactivate a slave\n");
617 } else if (slave_loaded_instance(slave) == 0) {
620 * If a slave has no more instances,
623 slave = slave_unref(slave);
629 HAPI struct slave_node *slave_deactivated_by_fault(struct slave_node *slave)
632 struct timeval faulted_at;
634 int reactivate_instances = 1;
636 if (!slave_is_activated(slave)) {
637 DbgPrint("Deactivating in progress\n");
638 if (slave_loaded_instance(slave) == 0)
639 slave = slave_unref(slave);
644 slave->fault_count++;
646 (void)fault_check_pkgs(slave);
648 if (slave->pid > 0) {
649 DbgPrint("Try to terminate PID: %d\n", slave->pid);
650 ret = aul_terminate_pid(slave->pid);
652 ErrPrint("Terminate failed, pid %d\n", slave->pid);
656 if (gettimeofday(&faulted_at, NULL) == 0) {
659 timersub(&faulted_at, &slave->activated_at, &rtv);
660 if (rtv.tv_sec < MINIMUM_REACTIVATION_TIME) {
661 slave->critical_fault_count++;
662 if (!slave_loaded_instance(slave) || slave->critical_fault_count >= SLAVE_MAX_LOAD) {
663 ErrPrint("Reactivation time is too fast and frequently occurred - Stop to auto reactivation\n");
665 reactivate_instances = 0;
666 slave->critical_fault_count = 0;
669 * Fault callback can access the slave information.
671 invoke_fault_cb(slave);
674 slave->critical_fault_count = 0;
677 ErrPrint("Failed to get time of day: %s\n", strerror(errno));
680 slave_set_reactivation(slave, reactivate);
681 slave_set_reactivate_instances(slave, reactivate_instances);
683 slave = slave_deactivated(slave);
687 HAPI const int const slave_is_activated(struct slave_node *slave)
689 switch (slave->state) {
690 case SLAVE_REQUEST_TO_TERMINATE:
691 case SLAVE_TERMINATED:
693 case SLAVE_REQUEST_TO_LAUNCH:
694 /* Not yet launched. but the slave incurred an unexpected error */
695 case SLAVE_REQUEST_TO_PAUSE:
696 case SLAVE_REQUEST_TO_RESUME:
701 return slave->pid != (pid_t)-1;
704 /* Could not be reach to here */
708 HAPI int slave_event_callback_add(struct slave_node *slave, enum slave_event event, int (*cb)(struct slave_node *, void *), void *data)
712 ev = calloc(1, sizeof(*ev));
714 ErrPrint("Heap: %s\n", strerror(errno));
715 return LB_STATUS_ERROR_MEMORY;
724 * Use the eina_list_prepend API.
725 * To keep the sequence of a callback invocation.
727 * Here is an example sequence.
729 * slave_event_callback_add(CALLBACK_01);
730 * slave_event_callback_add(CALLBACK_02);
731 * slave_event_callback_add(CALLBACK_03);
733 * Then the invoke_event_callback function will call the CALLBACKS as below sequence
741 case SLAVE_EVENT_ACTIVATE:
742 slave->event_activate_list = eina_list_prepend(slave->event_activate_list, ev);
744 case SLAVE_EVENT_DELETE:
745 slave->event_delete_list = eina_list_prepend(slave->event_delete_list, ev);
747 case SLAVE_EVENT_DEACTIVATE:
748 slave->event_deactivate_list = eina_list_prepend(slave->event_deactivate_list, ev);
750 case SLAVE_EVENT_PAUSE:
751 slave->event_pause_list = eina_list_prepend(slave->event_pause_list, ev);
753 case SLAVE_EVENT_RESUME:
754 slave->event_resume_list = eina_list_prepend(slave->event_resume_list, ev);
756 case SLAVE_EVENT_FAULT:
757 slave->event_fault_list = eina_list_prepend(slave->event_fault_list, ev);
761 return LB_STATUS_ERROR_INVALID;
764 return LB_STATUS_SUCCESS;
767 HAPI int slave_event_callback_del(struct slave_node *slave, enum slave_event event, int (*cb)(struct slave_node *, void *), void *data)
774 case SLAVE_EVENT_DEACTIVATE:
775 EINA_LIST_FOREACH_SAFE(slave->event_deactivate_list, l, n, ev) {
776 if (ev->evt_cb == cb && ev->cbdata == data) {
777 slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, ev);
779 return LB_STATUS_SUCCESS;
783 case SLAVE_EVENT_DELETE:
784 EINA_LIST_FOREACH_SAFE(slave->event_delete_list, l, n, ev) {
785 if (ev->evt_cb == cb && ev->cbdata == data) {
786 slave->event_delete_list = eina_list_remove(slave->event_delete_list, ev);
788 return LB_STATUS_SUCCESS;
792 case SLAVE_EVENT_ACTIVATE:
793 EINA_LIST_FOREACH_SAFE(slave->event_activate_list, l, n, ev) {
794 if (ev->evt_cb == cb && ev->cbdata == data) {
795 slave->event_activate_list = eina_list_remove(slave->event_activate_list, ev);
797 return LB_STATUS_SUCCESS;
801 case SLAVE_EVENT_PAUSE:
802 EINA_LIST_FOREACH_SAFE(slave->event_pause_list, l, n, ev) {
803 if (ev->evt_cb == cb && ev->cbdata == data) {
804 slave->event_pause_list = eina_list_remove(slave->event_pause_list, ev);
806 return LB_STATUS_SUCCESS;
810 case SLAVE_EVENT_RESUME:
811 EINA_LIST_FOREACH_SAFE(slave->event_resume_list, l, n, ev) {
812 if (ev->evt_cb == cb && ev->cbdata == data) {
813 slave->event_resume_list = eina_list_remove(slave->event_resume_list, ev);
815 return LB_STATUS_SUCCESS;
819 case SLAVE_EVENT_FAULT:
820 EINA_LIST_FOREACH_SAFE(slave->event_fault_list, l, n, ev) {
821 if (ev->evt_cb == cb && ev->cbdata == data) {
822 slave->event_fault_list = eina_list_remove(slave->event_fault_list, ev);
824 return LB_STATUS_SUCCESS;
829 return LB_STATUS_ERROR_INVALID;
832 return LB_STATUS_ERROR_NOT_EXIST;
835 HAPI int slave_set_data(struct slave_node *slave, const char *tag, void *data)
837 struct priv_data *priv;
839 priv = calloc(1, sizeof(*priv));
841 ErrPrint("Heap: %s\n", strerror(errno));
842 return LB_STATUS_ERROR_MEMORY;
845 priv->tag = strdup(tag);
847 ErrPrint("Heap: %s\n", strerror(errno));
849 return LB_STATUS_ERROR_MEMORY;
853 slave->data_list = eina_list_append(slave->data_list, priv);
854 return LB_STATUS_SUCCESS;
857 HAPI void *slave_del_data(struct slave_node *slave, const char *tag)
859 struct priv_data *priv;
864 EINA_LIST_FOREACH_SAFE(slave->data_list, l, n, priv) {
865 if (!strcmp(priv->tag, tag)) {
866 slave->data_list = eina_list_remove(slave->data_list, priv);
878 HAPI void *slave_data(struct slave_node *slave, const char *tag)
880 struct priv_data *priv;
883 EINA_LIST_FOREACH(slave->data_list, l, priv) {
884 if (!strcmp(priv->tag, tag))
891 HAPI struct slave_node *slave_find_by_pid(pid_t pid)
894 struct slave_node *slave;
896 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
897 if (slave->pid == pid)
904 HAPI struct slave_node *slave_find_by_name(const char *name)
907 struct slave_node *slave;
909 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
910 if (!strcmp(slave->name, name))
917 HAPI struct slave_node *slave_find_available(const char *abi, int secured, int network)
920 struct slave_node *slave;
922 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
923 if (slave->secured != secured)
926 if (slave->state == SLAVE_REQUEST_TO_TERMINATE && slave->loaded_instance == 0) {
929 * If a slave is in request_to_terminate state,
930 * and the slave object has no more intances,
931 * the slave object will be deleted soon.
932 * so we cannot reuse it.
934 * This object is not usable.
939 if (strcasecmp(slave->abi, abi))
942 if (slave->secured) {
943 DbgPrint("Found secured slave - has no instances (%s)\n", slave_name(slave));
944 if (slave->loaded_package == 0)
946 } else if (slave->network == network) {
947 DbgPrint("slave[%s] %d (net: %d)\n", slave_name(slave), slave->loaded_package, slave->network);
948 if (!strcasecmp(abi, DEFAULT_ABI)) {
949 if (slave->loaded_package < SLAVE_MAX_LOAD)
960 HAPI struct slave_node *slave_find_by_pkgname(const char *pkgname)
963 struct slave_node *slave;
965 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
966 if (!strcmp(slave->pkgname, pkgname)) {
967 if (slave->pid == (pid_t)-1) {
976 HAPI struct slave_node *slave_find_by_rpc_handle(int handle)
979 struct slave_node *slave;
982 ErrPrint("Invalid RPC handle: %d\n", handle);
986 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
987 if (slave_rpc_handle(slave) == handle)
995 HAPI void slave_load_package(struct slave_node *slave)
997 slave->loaded_package++;
1000 HAPI void slave_unload_package(struct slave_node *slave)
1002 if (!slave || slave->loaded_package == 0) {
1003 ErrPrint("Slave loaded package is not correct\n");
1007 slave->loaded_package--;
1010 HAPI void slave_load_instance(struct slave_node *slave)
1012 slave->loaded_instance++;
1013 DbgPrint("Instance: (%d)%d\n", slave->pid, slave->loaded_instance);
1016 HAPI int const slave_loaded_instance(struct slave_node *slave)
1018 return slave->loaded_instance;
1021 HAPI int const slave_loaded_package(struct slave_node *slave)
1023 return slave->loaded_package;
1026 HAPI struct slave_node *slave_unload_instance(struct slave_node *slave)
1028 if (!slave || slave->loaded_instance == 0) {
1029 ErrPrint("Slave loaded instance is not correct\n");
1033 slave->loaded_instance--;
1034 DbgPrint("Instance: (%d)%d\n", slave->pid, slave->loaded_instance);
1035 if (slave->loaded_instance == 0 && slave_is_activated(slave)) {
1036 slave_set_reactivation(slave, 0);
1037 slave_set_reactivate_instances(slave, 0);
1039 slave = slave_deactivate(slave);
1045 HAPI const int const slave_is_secured(const struct slave_node *slave)
1047 return slave->secured;
1050 HAPI const char * const slave_name(const struct slave_node *slave)
1055 HAPI const char * const slave_abi(const struct slave_node *slave)
1060 HAPI const pid_t const slave_pid(const struct slave_node *slave)
1065 HAPI int slave_set_pid(struct slave_node *slave, pid_t pid)
1068 return LB_STATUS_ERROR_INVALID;
1070 DbgPrint("Slave PID is updated to %d from %d\n", pid, slave->pid);
1073 return LB_STATUS_SUCCESS;
1076 static inline void invoke_resumed_cb(struct slave_node *slave)
1080 struct event *event;
1083 EINA_LIST_FOREACH_SAFE(slave->event_resume_list, l, n, event) {
1084 ret = event->evt_cb(event->slave, event->cbdata);
1086 if (eina_list_data_find(slave->event_resume_list, event)) {
1087 slave->event_resume_list = eina_list_remove(slave->event_resume_list, event);
1094 static void resume_cb(struct slave_node *slave, const struct packet *packet, void *data)
1098 if (slave->state == SLAVE_REQUEST_TO_TERMINATE) {
1099 DbgPrint("Slave is terminating now. ignore resume result\n");
1104 ErrPrint("Failed to change the state of the slave\n");
1105 slave->state = SLAVE_PAUSED;
1109 if (packet_get(packet, "i", &ret) != 1) {
1110 ErrPrint("Invalid parameter\n");
1115 slave->state = SLAVE_RESUMED;
1116 slave_rpc_ping_thaw(slave);
1117 invoke_resumed_cb(slave);
1121 static inline void invoke_paused_cb(struct slave_node *slave)
1125 struct event *event;
1128 EINA_LIST_FOREACH_SAFE(slave->event_pause_list, l, n, event) {
1129 ret = event->evt_cb(event->slave, event->cbdata);
1131 if (eina_list_data_find(slave->event_pause_list, event)) {
1132 slave->event_pause_list = eina_list_remove(slave->event_pause_list, event);
1139 static void pause_cb(struct slave_node *slave, const struct packet *packet, void *data)
1143 if (slave->state == SLAVE_REQUEST_TO_TERMINATE) {
1144 DbgPrint("Slave is terminating now. ignore pause result\n");
1149 ErrPrint("Failed to change the state of the slave\n");
1150 slave->state = SLAVE_RESUMED;
1154 if (packet_get(packet, "i", &ret) != 1) {
1155 ErrPrint("Invalid parameter\n");
1160 slave->state = SLAVE_PAUSED;
1161 slave_rpc_ping_freeze(slave);
1162 invoke_paused_cb(slave);
1166 HAPI int slave_resume(struct slave_node *slave)
1169 struct packet *packet;
1171 switch (slave->state) {
1172 case SLAVE_REQUEST_TO_LAUNCH:
1173 case SLAVE_REQUEST_TO_TERMINATE:
1174 case SLAVE_TERMINATED:
1175 return LB_STATUS_ERROR_INVALID;
1177 case SLAVE_REQUEST_TO_RESUME:
1178 return LB_STATUS_SUCCESS;
1183 timestamp = util_timestamp();
1185 packet = packet_create("resume", "d", timestamp);
1187 ErrPrint("Failed to prepare param\n");
1188 return LB_STATUS_ERROR_FAULT;
1191 slave->state = SLAVE_REQUEST_TO_RESUME;
1192 return slave_rpc_async_request(slave, NULL, packet, resume_cb, NULL, 0);
1195 HAPI int slave_pause(struct slave_node *slave)
1198 struct packet *packet;
1200 switch (slave->state) {
1201 case SLAVE_REQUEST_TO_LAUNCH:
1202 case SLAVE_REQUEST_TO_TERMINATE:
1203 case SLAVE_TERMINATED:
1204 return LB_STATUS_ERROR_INVALID;
1206 case SLAVE_REQUEST_TO_PAUSE:
1207 return LB_STATUS_SUCCESS;
1212 timestamp = util_timestamp();
1214 packet = packet_create("pause", "d", timestamp);
1216 ErrPrint("Failed to prepare param\n");
1217 return LB_STATUS_ERROR_FAULT;
1220 slave->state = SLAVE_REQUEST_TO_PAUSE;
1221 return slave_rpc_async_request(slave, NULL, packet, pause_cb, NULL, 0);
1224 HAPI const char *slave_pkgname(const struct slave_node *slave)
1226 return slave ? slave->pkgname : NULL;
1229 HAPI enum slave_state slave_state(const struct slave_node *slave)
1231 return slave ? slave->state : SLAVE_ERROR;
1234 HAPI const char *slave_state_string(const struct slave_node *slave)
1236 switch (slave->state) {
1237 case SLAVE_REQUEST_TO_LAUNCH:
1238 return "RequestToLaunch";
1239 case SLAVE_REQUEST_TO_TERMINATE:
1240 return "RequestToTerminate";
1241 case SLAVE_TERMINATED:
1242 return "Terminated";
1243 case SLAVE_REQUEST_TO_PAUSE:
1244 return "RequestToPause";
1245 case SLAVE_REQUEST_TO_RESUME:
1246 return "RequestToResume";
1260 HAPI const void *slave_list(void)
1262 return s_info.slave_list;
1265 HAPI int const slave_fault_count(const struct slave_node *slave)
1267 return slave->fault_count;
1270 HAPI double const slave_ttl(const struct slave_node *slave)
1272 if (!slave->ttl_timer)
1275 return ecore_timer_pending_get(slave->ttl_timer);
1278 HAPI void slave_set_reactivate_instances(struct slave_node *slave, int reactivate)
1280 slave->reactivate_instances = reactivate;
1283 HAPI int slave_need_to_reactivate_instances(struct slave_node *slave)
1285 return slave->reactivate_instances;
1288 HAPI void slave_set_reactivation(struct slave_node *slave, int flag)
1290 slave->reactivate_slave = flag;
1293 HAPI int slave_need_to_reactivate(struct slave_node *slave)
1295 return slave->reactivate_slave;
1298 HAPI int slave_network(const struct slave_node *slave)
1300 return slave->network;
1303 HAPI void slave_set_network(struct slave_node *slave, int network)
1305 slave->network = network;