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 */
25 #include <sys/resource.h>
30 #include <aul.h> /* aul_launch_app */
35 #include <dynamicbox_errno.h>
36 #include <dynamicbox_conf.h>
37 #include <dynamicbox_cmd_list.h>
38 #include <dynamicbox_service.h>
40 #include "critical_log.h"
41 #include "slave_life.h"
42 #include "slave_rpc.h"
43 #include "client_life.h"
44 #include "fault_manager.h"
55 #define BUNDLE_SLAVE_SVC_OP_TYPE "__APP_SVC_OP_TYPE__"
56 #define APP_CONTROL_OPERATION_MAIN "http://tizen.org/appcontrol/operation/main"
57 #define LOW_PRIORITY 10
65 int secured; /* Only A package(dynamicbox) is loaded for security requirements */
68 int critical_fault_count;
69 enum slave_state state;
75 int reactivate_instances;
81 SLAVE_EVENT_PROCESS_IDLE = 0x00,
82 SLAVE_EVENT_PROCESS_ACTIVATE = 0x01,
83 SLAVE_EVENT_PROCESS_DEACTIVATE = 0x02,
84 SLAVE_EVENT_PROCESS_DELETE = 0x04,
85 SLAVE_EVENT_PROCESS_FAULT = 0x08,
86 SLAVE_EVENT_PROCESS_PAUSE = 0x10,
87 SLAVE_EVENT_PROCESS_RESUME = 0x20
89 Eina_List *event_activate_list;
90 Eina_List *event_deactivate_list;
91 Eina_List *event_delete_list;
92 Eina_List *event_fault_list;
93 Eina_List *event_pause_list;
94 Eina_List *event_resume_list;
98 Ecore_Timer *ttl_timer; /*!< Time to live */
99 Ecore_Timer *activate_timer; /*!< Waiting hello packet for this time */
100 Ecore_Timer *relaunch_timer; /*!< Try to relaunch service app */
101 Ecore_Timer *terminate_timer; /*!< Waiting this timer before terminate the service provider */
106 #if defined(_USE_ECORE_TIME_GET)
109 struct timeval activated_at;
112 char *hw_acceleration;
116 struct slave_node *slave;
118 int (*evt_cb)(struct slave_node *, void *);
129 Eina_List *slave_list;
130 int deactivate_all_refcnt;
133 .deactivate_all_refcnt = 0,
136 static Eina_Bool terminate_timer_cb(void *data)
138 struct slave_node *slave = data;
143 * check the return value of the aul_terminate_pid
145 slave->state = SLAVE_REQUEST_TO_TERMINATE;
146 slave->terminate_timer = NULL;
148 DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave));
149 ret = aul_terminate_pid_async(slave->pid);
151 ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret);
152 slave = slave_deactivated(slave);
154 DbgPrint("Slave is deleted\n");
158 return ECORE_CALLBACK_CANCEL;
161 static struct slave_node *slave_deactivate(struct slave_node *slave, int no_timer)
167 * The caller must has to check the slave's state.
168 * If it is not activated, this function must has not to be called.
171 if (slave_pid(slave) <= 0) {
175 if (slave->ttl_timer) {
178 * If there is an activated TTL timer,
179 * It has to be cleared before deactivate the slave.
181 ecore_timer_del(slave->ttl_timer);
182 slave->ttl_timer = NULL;
185 if ((slave->ctrl_option & PROVIDER_CTRL_MANUAL_TERMINATION) == PROVIDER_CTRL_MANUAL_TERMINATION) {
189 * The provider requests MANUAL TERMINATION control option.
190 * Master will not send terminate request in this case, the provider should be terminated by itself.
192 DbgPrint("Manual termination is turned on\n");
193 slave->state = SLAVE_REQUEST_TO_DISCONNECT;
194 (void)slave_rpc_disconnect(slave);
195 } else if (slave->terminate_timer) {
196 ErrPrint("Terminate timer is already fired (%d)\n", slave->pid);
197 } else if (!no_timer && !slave->secured) {
198 DbgPrint("Fire the terminate timer: %d\n", slave->pid);
199 slave->terminate_timer = ecore_timer_add(DYNAMICBOX_CONF_SLAVE_ACTIVATE_TIME, terminate_timer_cb, slave);
200 if (!slave->terminate_timer) {
203 * Normally, Call the terminate_timer_cb directly from here
204 * But in this case. if the aul_terminate_pid failed, Call the slave_deactivated function directly.
205 * Then the "slave" pointer can be changed. To trace it, Copy the body of terminate_timer_cb to here.
207 ErrPrint("Failed to add a new timer for terminating\n");
208 DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave));
211 * check the return value of the aul_terminate_pid
213 slave->state = SLAVE_REQUEST_TO_TERMINATE;
215 ret = aul_terminate_pid_async(slave->pid);
217 ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret);
218 slave = slave_deactivated(slave);
224 * check the return value of the aul_terminate_pid
226 slave->state = SLAVE_REQUEST_TO_TERMINATE;
228 DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave));
229 ret = aul_terminate_pid_async(slave->pid);
231 ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret);
232 slave = slave_deactivated(slave);
239 static Eina_Bool slave_ttl_cb(void *data)
241 struct pkg_info *info;
242 struct slave_node *slave = (struct slave_node *)data;
246 pkg_list = (Eina_List *)package_list();
247 EINA_LIST_FOREACH(pkg_list, l, info) {
248 if (package_slave(info) == slave) {
249 struct inst_info *inst;
250 Eina_List *inst_list;
253 inst_list = (Eina_List *)package_instance_list(info);
254 EINA_LIST_FOREACH(inst_list, n, inst) {
255 if (instance_visible_state(inst) == DBOX_SHOW) {
256 DbgPrint("Instance is in show, give more ttl to %d for %s\n", slave_pid(slave), instance_id(inst));
257 return ECORE_CALLBACK_RENEW;
265 * ttl_timer must has to be set to NULL before deactivate the slave
266 * It will be used for making decision of the expired TTL timer or the fault of a dynamicbox.
268 slave->ttl_timer = NULL;
270 if (slave_is_activated(slave)) {
271 slave_set_reactivation(slave, 0);
272 slave_set_reactivate_instances(slave, 1);
274 slave = slave_deactivate(slave, 1);
276 DbgPrint("Slave is deleted\n");
280 /*! To recover all instances state it is activated again */
281 return ECORE_CALLBACK_CANCEL;
284 static inline int xmonitor_pause_cb(void *data)
287 return DBOX_STATUS_ERROR_NONE;
290 static inline int xmonitor_resume_cb(void *data)
293 return DBOX_STATUS_ERROR_NONE;
296 static inline struct slave_node *create_slave_node(const char *name, int is_secured, const char *abi, const char *pkgname, int network, const char *hw_acceleration)
298 struct slave_node *slave;
300 slave = calloc(1, sizeof(*slave));
302 ErrPrint("Heap: %s\n", strerror(errno));
306 slave->name = strdup(name);
308 ErrPrint("Heap: %s\n", strerror(errno));
313 slave->abi = strdup(abi);
315 ErrPrint("Heap: %s\n", strerror(errno));
316 DbgFree(slave->name);
321 slave->pkgname = strdup(pkgname);
322 if (!slave->pkgname) {
323 ErrPrint("Heap: %s\n", strerror(errno));
325 DbgFree(slave->name);
330 if (hw_acceleration) {
331 slave->hw_acceleration = strdup(hw_acceleration);
332 if (!slave->hw_acceleration) {
333 ErrPrint("Heap: %s\n", strerror(errno));
334 DbgFree(slave->pkgname);
336 DbgFree(slave->name);
342 slave->secured = is_secured;
343 slave->pid = (pid_t)-1;
344 slave->state = SLAVE_TERMINATED;
345 slave->network = network;
346 slave->relaunch_count = DYNAMICBOX_CONF_SLAVE_RELAUNCH_COUNT;
348 xmonitor_add_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
349 xmonitor_add_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
351 s_info.slave_list = eina_list_append(s_info.slave_list, slave);
355 static inline void invoke_delete_cb(struct slave_node *slave)
361 slave->in_event_process |= SLAVE_EVENT_PROCESS_DELETE;
362 EINA_LIST_FOREACH_SAFE(slave->event_delete_list, l, n, event) {
363 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
364 slave->event_delete_list = eina_list_remove(slave->event_delete_list, event);
368 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_DELETE;
371 static inline void destroy_slave_node(struct slave_node *slave)
374 struct priv_data *priv;
376 if (slave_pid(slave) != (pid_t)-1) {
377 ErrPrint("Slave is not deactivated\n");
381 xmonitor_del_event_callback(XMONITOR_PAUSED, xmonitor_pause_cb, slave);
382 xmonitor_del_event_callback(XMONITOR_RESUMED, xmonitor_resume_cb, slave);
384 invoke_delete_cb(slave);
385 slave_rpc_fini(slave); /*!< Finalize the RPC after handling all delete callbacks */
387 EINA_LIST_FREE(slave->event_delete_list, event) {
391 EINA_LIST_FREE(slave->event_activate_list, event) {
395 EINA_LIST_FREE(slave->event_deactivate_list, event) {
399 EINA_LIST_FREE(slave->event_fault_list, event) {
403 EINA_LIST_FREE(slave->data_list, priv) {
408 s_info.slave_list = eina_list_remove(s_info.slave_list, slave);
410 if (slave->ttl_timer) {
411 ecore_timer_del(slave->ttl_timer);
414 if (slave->activate_timer) {
415 ecore_timer_del(slave->activate_timer);
418 if (slave->relaunch_timer) {
419 ecore_timer_del(slave->relaunch_timer);
423 DbgFree(slave->name);
424 DbgFree(slave->pkgname);
425 DbgFree(slave->hw_acceleration);
430 static inline struct slave_node *find_slave(const char *name)
432 struct slave_node *slave;
435 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
436 if (!strcmp(slave->name, name)) {
444 HAPI int slave_expired_ttl(struct slave_node *slave)
450 if (!slave->secured && !(DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL)) {
454 return !!slave->ttl_timer;
457 HAPI struct slave_node *slave_ref(struct slave_node *slave)
467 HAPI struct slave_node *slave_unref(struct slave_node *slave)
473 if (slave->refcnt == 0) {
474 ErrPrint("Slave refcnt is not valid\n");
479 if (slave->refcnt == 0) {
480 destroy_slave_node(slave);
487 HAPI const int const slave_refcnt(struct slave_node *slave)
489 return slave->refcnt;
492 HAPI struct slave_node *slave_create(const char *name, int is_secured, const char *abi, const char *pkgname, int network, const char *hw_acceleration)
494 struct slave_node *slave;
496 slave = find_slave(name);
498 if (slave->secured != is_secured) {
499 ErrPrint("Exists slave and creating slave's security flag is not matched\n");
504 slave = create_slave_node(name, is_secured, abi, pkgname, network, hw_acceleration);
510 slave_rpc_init(slave);
517 * Before destroying slave object,
518 * you should check the RPC(slave_async_XXX) state and Private data field (slave_set_data)
520 HAPI void slave_destroy(struct slave_node *slave)
525 static inline struct slave_node *invoke_fault_cb(struct slave_node *slave)
532 slave->in_event_process |= SLAVE_EVENT_PROCESS_FAULT;
533 EINA_LIST_FOREACH_SAFE(slave->event_fault_list, l, n, event) {
534 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
535 slave->event_fault_list = eina_list_remove(slave->event_fault_list, event);
539 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_FAULT;
540 slave = slave_unref(slave);
545 static inline void invoke_activate_cb(struct slave_node *slave)
551 slave->in_event_process |= SLAVE_EVENT_PROCESS_ACTIVATE;
552 EINA_LIST_FOREACH_SAFE(slave->event_activate_list, l, n, event) {
553 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
554 slave->event_activate_list = eina_list_remove(slave->event_activate_list, event);
558 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_ACTIVATE;
561 static Eina_Bool activate_timer_cb(void *data)
563 struct slave_node *slave = data;
565 if (slave->relaunch_timer) {
566 ecore_timer_del(slave->relaunch_timer);
567 slave->relaunch_timer = NULL;
570 slave->fault_count++;
572 if (invoke_fault_cb(slave) == NULL) {
573 ErrPrint("Slave is deleted while processing fault handler\n");
574 return ECORE_CALLBACK_CANCEL;
577 slave_set_reactivation(slave, 0);
578 slave_set_reactivate_instances(slave, 0);
580 slave->activate_timer = NULL;
581 if (slave_pid(slave) > 0) {
583 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
584 ret = aul_terminate_pid_async(slave_pid(slave));
586 ErrPrint("Terminate failed, pid %d (reason: %d)\n", slave_pid(slave), ret);
590 CRITICAL_LOG("Slave is not activated in %lf sec (slave: %s)\n", DYNAMICBOX_CONF_SLAVE_ACTIVATE_TIME, slave_name(slave));
591 slave = slave_deactivated(slave);
592 return ECORE_CALLBACK_CANCEL;
595 static inline void invoke_slave_fault_handler(struct slave_node *slave)
597 slave->fault_count++;
598 if (invoke_fault_cb(slave) == NULL) {
599 ErrPrint("Slave is deleted while processing fault handler\n");
603 slave_set_reactivation(slave, 0);
604 slave_set_reactivate_instances(slave, 0);
606 if (slave_pid(slave) > 0) {
607 if ((slave->ctrl_option & PROVIDER_CTRL_MANUAL_TERMINATION) == PROVIDER_CTRL_MANUAL_TERMINATION) {
608 DbgPrint("Manual termination is turned on\n");
609 (void)slave_rpc_disconnect(slave);
612 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
613 ret = aul_terminate_pid_async(slave_pid(slave));
615 ErrPrint("Terminate failed, pid %d (reason: %d)\n", slave_pid(slave), ret);
620 slave->state = SLAVE_TERMINATED;
623 static Eina_Bool relaunch_timer_cb(void *data)
625 struct slave_node *slave = data;
626 int ret = ECORE_CALLBACK_CANCEL;
628 if (!slave->activate_timer) {
629 ErrPrint("Activate timer is not valid\n");
630 slave->relaunch_timer = NULL;
632 invoke_slave_fault_handler(slave);
633 } else if (!slave->relaunch_count) {
634 ErrPrint("Relaunch count is exhahausted\n");
635 ecore_timer_del(slave->activate_timer);
636 slave->activate_timer = NULL;
638 slave->relaunch_timer = NULL;
639 invoke_slave_fault_handler(slave);
643 param = bundle_create();
645 ErrPrint("Failed to create a bundle\n");
647 ecore_timer_del(slave->activate_timer);
648 slave->activate_timer = NULL;
650 slave->relaunch_timer = NULL;
652 invoke_slave_fault_handler(slave);
654 bundle_add(param, BUNDLE_SLAVE_SVC_OP_TYPE, APP_CONTROL_OPERATION_MAIN);
655 bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_NAME, slave_name(slave));
656 bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_SECURED, ((DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL) || slave->secured) ? "true" : "false");
657 bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_ABI, slave->abi);
658 bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_HW_ACCELERATION, slave->hw_acceleration);
660 slave->pid = (pid_t)aul_launch_app(slave_pkgname(slave), param);
664 switch (slave->pid) {
665 case AUL_R_EHIDDENFORGUEST: /**< App hidden for guest mode */
666 case AUL_R_ENOLAUNCHPAD: /**< no launchpad */
667 case AUL_R_EILLACC: /**< Illegal Access */
668 case AUL_R_EINVAL: /**< Invalid argument */
669 case AUL_R_ENOINIT: /**< AUL handler NOT initialized */
670 case AUL_R_ERROR: /**< General error */
671 CRITICAL_LOG("Failed to launch a new slave %s (%d)\n", slave_name(slave), slave->pid);
672 slave->pid = (pid_t)-1;
673 ecore_timer_del(slave->activate_timer);
674 slave->activate_timer = NULL;
676 slave->relaunch_timer = NULL;
678 invoke_slave_fault_handler(slave);
679 /* Waiting app-launch result */
681 case AUL_R_ETIMEOUT: /**< Timeout */
682 case AUL_R_ECOMM: /**< Comunication Error */
683 case AUL_R_ETERMINATING: /**< application terminating */
684 case AUL_R_ECANCELED: /**< Operation canceled */
685 slave->relaunch_count--;
687 CRITICAL_LOG("Try relaunch again %s (%d), %d\n", slave_name(slave), slave->pid, slave->relaunch_count);
688 slave->pid = (pid_t)-1;
689 ret = ECORE_CALLBACK_RENEW;
690 ecore_timer_reset(slave->activate_timer);
691 /* Try again after a few secs later */
693 case AUL_R_LOCAL: /**< Launch by himself */
694 case AUL_R_OK: /**< General success */
696 DbgPrint("Slave %s is launched with %d as %s\n", slave_pkgname(slave), slave->pid, slave_name(slave));
697 slave->relaunch_timer = NULL;
698 ecore_timer_reset(slave->activate_timer);
708 HAPI int slave_activate(struct slave_node *slave)
712 * If a slave is deactivated by OOM killer,
713 * We should not activate it again from here.
714 * Instead of this, it should be reactivated by user event or oom event(normal)
719 * This check code can be replaced with the slave->state check code
720 * If the slave data has the PID, it means, it is activated
721 * Even if it is in the termiating sequence, it will have the PID
722 * until it is terminated at last.
723 * So we can use this simple code for checking the slave's last state.
724 * whether it is alive or not.
726 if (slave_pid(slave) != (pid_t)-1) {
727 if (slave->terminate_timer) {
728 DbgPrint("Clear terminate timer. to reuse (%d)\n", slave->pid);
729 ecore_timer_del(slave->terminate_timer);
730 slave->terminate_timer = NULL;
731 } else if (slave_state(slave) == SLAVE_REQUEST_TO_TERMINATE || slave_state(slave) == SLAVE_REQUEST_TO_DISCONNECT) {
732 slave_set_reactivation(slave, 1);
734 return DBOX_STATUS_ERROR_ALREADY;
735 } else if (slave_state(slave) == SLAVE_REQUEST_TO_LAUNCH) {
736 DbgPrint("Slave is already launched: but the AUL is timed out\n");
737 return DBOX_STATUS_ERROR_ALREADY;
740 if (DYNAMICBOX_CONF_DEBUG_MODE || g_conf.debug_mode) {
741 DbgPrint("Debug Mode enabled. name[%s] secured[%d] abi[%s]\n", slave_name(slave), slave->secured, slave->abi);
745 slave->relaunch_count = DYNAMICBOX_CONF_SLAVE_RELAUNCH_COUNT;
747 param = bundle_create();
749 ErrPrint("Failed to create a bundle\n");
750 return DBOX_STATUS_ERROR_FAULT;
753 bundle_add(param, BUNDLE_SLAVE_SVC_OP_TYPE, APP_CONTROL_OPERATION_MAIN);
754 bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_NAME, slave_name(slave));
755 bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_SECURED, ((DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL) || slave->secured) ? "true" : "false");
756 bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_ABI, slave->abi);
757 bundle_add(param, DYNAMICBOX_CONF_BUNDLE_SLAVE_HW_ACCELERATION, slave->hw_acceleration);
759 slave->pid = (pid_t)aul_launch_app(slave_pkgname(slave), param);
763 switch (slave->pid) {
764 case AUL_R_EHIDDENFORGUEST: /**< App hidden for guest mode */
765 case AUL_R_ENOLAUNCHPAD: /**< no launchpad */
766 case AUL_R_EILLACC: /**< Illegal Access */
767 case AUL_R_EINVAL: /**< Invalid argument */
768 case AUL_R_ENOINIT: /**< AUL handler NOT initialized */
769 case AUL_R_ERROR: /**< General error */
770 CRITICAL_LOG("Failed to launch a new slave %s (%d)\n", slave_name(slave), slave->pid);
771 slave->pid = (pid_t)-1;
772 /* Waiting app-launch result */
774 case AUL_R_ECOMM: /**< Comunication Error */
775 case AUL_R_ETERMINATING: /**< application terminating */
776 case AUL_R_ECANCELED: /**< Operation canceled */
777 case AUL_R_ETIMEOUT: /**< Timeout */
778 CRITICAL_LOG("Try relaunch this soon %s (%d)\n", slave_name(slave), slave->pid);
779 slave->relaunch_timer = ecore_timer_add(DYNAMICBOX_CONF_SLAVE_RELAUNCH_TIME, relaunch_timer_cb, slave);
780 if (!slave->relaunch_timer) {
781 CRITICAL_LOG("Failed to register a relaunch timer (%s)\n", slave_name(slave));
782 slave->pid = (pid_t)-1;
783 return DBOX_STATUS_ERROR_FAULT;
785 /* Try again after a few secs later */
787 case AUL_R_LOCAL: /**< Launch by himself */
788 case AUL_R_OK: /**< General success */
790 DbgPrint("Slave %s is launched with %d as %s\n", slave_pkgname(slave), slave->pid, slave_name(slave));
794 slave->activate_timer = ecore_timer_add(DYNAMICBOX_CONF_SLAVE_ACTIVATE_TIME, activate_timer_cb, slave);
795 if (!slave->activate_timer) {
796 ErrPrint("Failed to register an activate timer\n");
800 slave->state = SLAVE_REQUEST_TO_LAUNCH;
803 * Increase the refcnt of a slave,
804 * To prevent from making an orphan(slave).
806 (void)slave_ref(slave);
808 return DBOX_STATUS_ERROR_NONE;
811 HAPI int slave_give_more_ttl(struct slave_node *slave)
815 if (!(DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL) && (!slave->secured || !slave->ttl_timer)) {
816 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
819 delay = DYNAMICBOX_CONF_SLAVE_TTL - ecore_timer_pending_get(slave->ttl_timer);
820 ecore_timer_delay(slave->ttl_timer, delay);
821 return DBOX_STATUS_ERROR_NONE;
824 HAPI int slave_freeze_ttl(struct slave_node *slave)
826 if (!(DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL) && (!slave->secured || !slave->ttl_timer)) {
827 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
830 ecore_timer_freeze(slave->ttl_timer);
831 return DBOX_STATUS_ERROR_NONE;
834 HAPI int slave_thaw_ttl(struct slave_node *slave)
838 if (!(DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL) && (!slave->secured || !slave->ttl_timer)) {
839 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
842 ecore_timer_thaw(slave->ttl_timer);
844 delay = DYNAMICBOX_CONF_SLAVE_TTL - ecore_timer_pending_get(slave->ttl_timer);
845 ecore_timer_delay(slave->ttl_timer, delay);
846 return DBOX_STATUS_ERROR_NONE;
849 HAPI int slave_activated(struct slave_node *slave)
851 slave->state = SLAVE_RESUMED;
853 if (xmonitor_is_paused()) {
857 if (((DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL) || slave->secured == 1) && DYNAMICBOX_CONF_SLAVE_TTL > 0.0f) {
858 DbgPrint("Slave deactivation timer is added (%s - %lf)\n", slave_name(slave), DYNAMICBOX_CONF_SLAVE_TTL);
859 slave->ttl_timer = ecore_timer_add(DYNAMICBOX_CONF_SLAVE_TTL, slave_ttl_cb, slave);
860 if (!slave->ttl_timer) {
861 ErrPrint("Failed to create a TTL timer\n");
865 invoke_activate_cb(slave);
867 slave_set_reactivation(slave, 0);
868 slave_set_reactivate_instances(slave, 0);
870 #if defined(_USE_ECORE_TIME_GET)
871 slave->activated_at = ecore_time_get();
873 if (gettimeofday(&slave->activated_at, NULL) < 0) {
874 ErrPrint("Failed to get time of day: %s\n", strerror(errno));
875 slave->activated_at.tv_sec = 0;
876 slave->activated_at.tv_usec = 0;
880 if (slave->activate_timer) {
881 ecore_timer_del(slave->activate_timer);
882 slave->activate_timer = NULL;
885 if (slave->relaunch_timer) {
886 ecore_timer_del(slave->relaunch_timer);
887 slave->relaunch_timer = NULL;
890 slave_set_priority(slave, LOW_PRIORITY);
891 return DBOX_STATUS_ERROR_NONE;
894 static inline int invoke_deactivate_cb(struct slave_node *slave)
902 slave->in_event_process |= SLAVE_EVENT_PROCESS_DEACTIVATE;
904 EINA_LIST_FOREACH_SAFE(slave->event_deactivate_list, l, n, event) {
905 if (event->deleted) {
906 slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, event);
911 ret = event->evt_cb(event->slave, event->cbdata);
912 if (ret < 0 || event->deleted) {
913 slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, event);
917 if (ret == SLAVE_NEED_TO_REACTIVATE) {
922 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_DEACTIVATE;
927 HAPI struct slave_node *slave_deactivated(struct slave_node *slave)
931 slave->pid = (pid_t)-1;
932 slave->state = SLAVE_TERMINATED;
934 if (slave->ttl_timer) {
935 ecore_timer_del(slave->ttl_timer);
936 slave->ttl_timer = NULL;
939 if (slave->activate_timer) {
940 ecore_timer_del(slave->activate_timer);
941 slave->activate_timer = NULL;
944 if (slave->relaunch_timer) {
945 ecore_timer_del(slave->relaunch_timer);
946 slave->relaunch_timer = NULL;
949 if (slave->terminate_timer) {
950 ecore_timer_del(slave->terminate_timer);
951 slave->terminate_timer = NULL;
957 * If the deactivated event callback is called for package.c
958 * It can delete the instance if it has fault information
959 * then it also try to delete the slave object again.
960 * To prevent from unexpected slave object deletetion while handling callback,
961 * increase the refcnt of slave
962 * when it get back from callback, try to decrease the refcnt of slave
963 * At that time, we can delete slave safely.
966 reactivate = invoke_deactivate_cb(slave);
967 slave = slave_unref(slave);
969 ErrPrint("Slave object is deleted\n");
973 slave = slave_unref(slave);
975 DbgPrint("SLAVE object is destroyed\n");
979 if ((slave->ctrl_option & PROVIDER_CTRL_MANUAL_REACTIVATION) == PROVIDER_CTRL_MANUAL_REACTIVATION) {
982 * In this case, the provider(Slave) should be reactivated by itself or user.
983 * The master will not reactivate it automatically.
985 DbgPrint("Manual reactivate option is turned on\n");
986 } else if (reactivate && slave_need_to_reactivate(slave) && setting_oom_level() == OOM_TYPE_NORMAL) {
989 DbgPrint("Need to reactivate a slave\n");
990 ret = slave_activate(slave);
991 if (ret < 0 && ret != DBOX_STATUS_ERROR_ALREADY) {
992 ErrPrint("Failed to reactivate a slave\n");
994 } else if (slave_loaded_instance(slave) == 0) {
997 * If a slave has no more instances,
1000 slave = slave_unref(slave);
1006 HAPI struct slave_node *slave_deactivated_by_fault(struct slave_node *slave)
1010 int reactivate_instances = 1;
1013 if (g_conf.slave_max_load < 0) {
1014 max_load = DYNAMICBOX_CONF_SLAVE_MAX_LOAD;
1016 max_load = g_conf.slave_max_load;
1019 if (!slave_is_activated(slave)) {
1020 DbgPrint("Deactivating in progress\n");
1021 if (slave_loaded_instance(slave) == 0) {
1022 slave = slave_unref(slave);
1028 slave->fault_count++;
1030 (void)fault_check_pkgs(slave);
1032 if (slave_pid(slave) > 0) {
1033 DbgPrint("Try to terminate PID: %d\n", slave_pid(slave));
1034 ret = aul_terminate_pid_async(slave_pid(slave));
1036 ErrPrint("Terminate failed, pid %d\n", slave_pid(slave));
1040 #if defined(_USE_ECORE_TIME_GET)
1043 faulted_at = ecore_time_get();
1044 if (faulted_at - slave->activated_at < DYNAMICBOX_CONF_MINIMUM_REACTIVATION_TIME) {
1045 slave->critical_fault_count++;
1047 if (!slave_loaded_instance(slave) || slave->critical_fault_count >= max_load) {
1048 ErrPrint("Reactivation time is too fast and frequently occurred - Stop to auto reactivation\n");
1050 reactivate_instances = 0;
1051 slave->critical_fault_count = 0;
1054 * Fault callback can access the slave information.
1056 if (invoke_fault_cb(slave) == NULL) {
1057 ErrPrint("Slave is deleted while processing fault handler\n");
1061 slave->critical_fault_count = 0;
1065 struct timeval faulted_at;
1067 if (gettimeofday(&faulted_at, NULL) == 0) {
1070 timersub(&faulted_at, &slave->activated_at, &rtv);
1071 if (rtv.tv_sec < DYNAMICBOX_CONF_MINIMUM_REACTIVATION_TIME) {
1072 slave->critical_fault_count++;
1073 if (!slave_loaded_instance(slave) || slave->critical_fault_count >= max_load) {
1074 ErrPrint("Reactivation time is too fast and frequently occurred - Stop to auto reactivation\n");
1076 reactivate_instances = 0;
1077 slave->critical_fault_count = 0;
1080 * Fault callback can access the slave information.
1082 if (invoke_fault_cb(slave) == NULL) {
1083 ErrPrint("Slave is deleted while processing fault handler\n");
1088 slave->critical_fault_count = 0;
1091 ErrPrint("Failed to get time of day: %s\n", strerror(errno));
1095 slave_set_reactivation(slave, reactivate);
1096 slave_set_reactivate_instances(slave, reactivate_instances);
1098 slave = slave_deactivated(slave);
1102 HAPI const int const slave_is_activated(struct slave_node *slave)
1104 switch (slave->state) {
1105 case SLAVE_REQUEST_TO_TERMINATE:
1106 case SLAVE_TERMINATED:
1108 case SLAVE_REQUEST_TO_DISCONNECT:
1109 /* This case should be treated as an activated state.
1110 * To send the last request to the provider.
1112 case SLAVE_REQUEST_TO_LAUNCH:
1113 /* Not yet launched. but the slave incurred an unexpected error */
1114 case SLAVE_REQUEST_TO_PAUSE:
1115 case SLAVE_REQUEST_TO_RESUME:
1120 return slave->pid != (pid_t)-1;
1123 /* Could not be reach to here */
1127 HAPI int slave_event_callback_add(struct slave_node *slave, enum slave_event event, int (*cb)(struct slave_node *, void *), void *data)
1131 ev = calloc(1, sizeof(*ev));
1133 ErrPrint("Heap: %s\n", strerror(errno));
1134 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1143 * Use the eina_list_prepend API.
1144 * To keep the sequence of a callback invocation.
1146 * Here is an example sequence.
1148 * slave_event_callback_add(CALLBACK_01);
1149 * slave_event_callback_add(CALLBACK_02);
1150 * slave_event_callback_add(CALLBACK_03);
1152 * Then the invoke_event_callback function will call the CALLBACKS as below sequence
1154 * invoke_CALLBACK_03
1155 * invoke_CALLBACK_02
1156 * invoke_CALLBACK_01
1160 case SLAVE_EVENT_ACTIVATE:
1161 slave->event_activate_list = eina_list_prepend(slave->event_activate_list, ev);
1163 case SLAVE_EVENT_DELETE:
1164 slave->event_delete_list = eina_list_prepend(slave->event_delete_list, ev);
1166 case SLAVE_EVENT_DEACTIVATE:
1167 slave->event_deactivate_list = eina_list_prepend(slave->event_deactivate_list, ev);
1169 case SLAVE_EVENT_PAUSE:
1170 slave->event_pause_list = eina_list_prepend(slave->event_pause_list, ev);
1172 case SLAVE_EVENT_RESUME:
1173 slave->event_resume_list = eina_list_prepend(slave->event_resume_list, ev);
1175 case SLAVE_EVENT_FAULT:
1176 slave->event_fault_list = eina_list_prepend(slave->event_fault_list, ev);
1180 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1183 return DBOX_STATUS_ERROR_NONE;
1186 HAPI int slave_event_callback_del(struct slave_node *slave, enum slave_event event, int (*cb)(struct slave_node *, void *), void *data)
1193 case SLAVE_EVENT_DEACTIVATE:
1194 EINA_LIST_FOREACH_SAFE(slave->event_deactivate_list, l, n, ev) {
1195 if (ev->evt_cb == cb && ev->cbdata == data) {
1196 if (slave->in_event_process & SLAVE_EVENT_PROCESS_DEACTIVATE) {
1199 slave->event_deactivate_list = eina_list_remove(slave->event_deactivate_list, ev);
1202 return DBOX_STATUS_ERROR_NONE;
1206 case SLAVE_EVENT_DELETE:
1207 EINA_LIST_FOREACH_SAFE(slave->event_delete_list, l, n, ev) {
1208 if (ev->evt_cb == cb && ev->cbdata == data) {
1209 if (slave->in_event_process & SLAVE_EVENT_PROCESS_DELETE) {
1212 slave->event_delete_list = eina_list_remove(slave->event_delete_list, ev);
1215 return DBOX_STATUS_ERROR_NONE;
1219 case SLAVE_EVENT_ACTIVATE:
1220 EINA_LIST_FOREACH_SAFE(slave->event_activate_list, l, n, ev) {
1221 if (ev->evt_cb == cb && ev->cbdata == data) {
1222 if (slave->in_event_process & SLAVE_EVENT_PROCESS_ACTIVATE) {
1225 slave->event_activate_list = eina_list_remove(slave->event_activate_list, ev);
1228 return DBOX_STATUS_ERROR_NONE;
1232 case SLAVE_EVENT_PAUSE:
1233 EINA_LIST_FOREACH_SAFE(slave->event_pause_list, l, n, ev) {
1234 if (ev->evt_cb == cb && ev->cbdata == data) {
1235 if (slave->in_event_process & SLAVE_EVENT_PROCESS_PAUSE) {
1238 slave->event_pause_list = eina_list_remove(slave->event_pause_list, ev);
1241 return DBOX_STATUS_ERROR_NONE;
1245 case SLAVE_EVENT_RESUME:
1246 EINA_LIST_FOREACH_SAFE(slave->event_resume_list, l, n, ev) {
1247 if (ev->evt_cb == cb && ev->cbdata == data) {
1248 if (slave->in_event_process & SLAVE_EVENT_PROCESS_RESUME) {
1251 slave->event_resume_list = eina_list_remove(slave->event_resume_list, ev);
1254 return DBOX_STATUS_ERROR_NONE;
1258 case SLAVE_EVENT_FAULT:
1259 EINA_LIST_FOREACH_SAFE(slave->event_fault_list, l, n, ev) {
1260 if (ev->evt_cb == cb && ev->cbdata == data) {
1261 if (slave->in_event_process & SLAVE_EVENT_PROCESS_FAULT) {
1264 slave->event_fault_list = eina_list_remove(slave->event_fault_list, ev);
1267 return DBOX_STATUS_ERROR_NONE;
1272 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1275 return DBOX_STATUS_ERROR_NOT_EXIST;
1278 HAPI int slave_set_data(struct slave_node *slave, const char *tag, void *data)
1280 struct priv_data *priv;
1282 priv = calloc(1, sizeof(*priv));
1284 ErrPrint("Heap: %s\n", strerror(errno));
1285 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1288 priv->tag = strdup(tag);
1290 ErrPrint("Heap: %s\n", strerror(errno));
1292 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
1296 slave->data_list = eina_list_append(slave->data_list, priv);
1297 return DBOX_STATUS_ERROR_NONE;
1300 HAPI void *slave_del_data(struct slave_node *slave, const char *tag)
1302 struct priv_data *priv;
1307 EINA_LIST_FOREACH_SAFE(slave->data_list, l, n, priv) {
1308 if (!strcmp(priv->tag, tag)) {
1309 slave->data_list = eina_list_remove(slave->data_list, priv);
1321 HAPI void *slave_data(struct slave_node *slave, const char *tag)
1323 struct priv_data *priv;
1326 EINA_LIST_FOREACH(slave->data_list, l, priv) {
1327 if (!strcmp(priv->tag, tag)) {
1335 HAPI struct slave_node *slave_find_by_pid(pid_t pid)
1338 struct slave_node *slave;
1340 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1341 if (slave_pid(slave) == pid) {
1349 HAPI struct slave_node *slave_find_by_name(const char *name)
1352 struct slave_node *slave;
1354 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1355 if (!strcmp(slave_name(slave), name)) {
1363 HAPI struct slave_node *slave_find_available(const char *slave_pkgname, const char *abi, int secured, int network, const char *hw_acceleration)
1366 struct slave_node *slave;
1368 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1369 if (slave->secured != secured) {
1373 if ((slave->state == SLAVE_REQUEST_TO_TERMINATE || slave->state == SLAVE_REQUEST_TO_DISCONNECT) && slave->loaded_instance == 0) {
1376 * If a slave is in request_to_terminate state,
1377 * and the slave object has no more intances,
1378 * the slave object will be deleted soon.
1379 * so we cannot reuse it.
1381 * This object is not usable.
1386 if (strcasecmp(slave->abi, abi)) {
1390 if (strcasecmp(slave->pkgname, slave_pkgname)) {
1394 if (slave->hw_acceleration != hw_acceleration) {
1395 if (!slave->hw_acceleration || !hw_acceleration || strcasecmp(slave->hw_acceleration, hw_acceleration)) {
1400 if (slave->secured) {
1401 if (slave->loaded_package == 0) {
1402 DbgPrint("Found secured slave - has no instances (%s)\n", slave_name(slave));
1405 } else if (slave->network == network) {
1406 DbgPrint("slave[%s] loaded_package[%d] net: [%d]\n", slave_name(slave), slave->loaded_package, slave->network);
1407 if (!strcasecmp(abi, DYNAMICBOX_CONF_DEFAULT_ABI)) {
1409 if (g_conf.slave_max_load < 0) {
1410 max_load = DYNAMICBOX_CONF_SLAVE_MAX_LOAD;
1412 max_load = g_conf.slave_max_load;
1415 if (slave->loaded_package < max_load) {
1427 HAPI struct slave_node *slave_find_by_pkgname(const char *pkgname)
1430 struct slave_node *slave;
1432 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1433 if (!strcmp(slave_pkgname(slave), pkgname)) {
1434 if (slave_pid(slave) == (pid_t)-1) {
1443 HAPI struct slave_node *slave_find_by_rpc_handle(int handle)
1446 struct slave_node *slave;
1449 ErrPrint("Invalid RPC handle: %d\n", handle);
1453 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1454 if (slave_rpc_handle(slave) == handle) {
1463 HAPI char *slave_package_name(const char *abi, const char *lbid)
1468 tmp = abi_find_slave(abi);
1470 ErrPrint("Failed to find a proper pkgname of a slave\n");
1474 s_pkgname = util_replace_string(tmp, DYNAMICBOX_CONF_REPLACE_TAG_APPID, lbid);
1476 DbgPrint("Failed to get replaced string\n");
1477 s_pkgname = strdup(tmp);
1479 ErrPrint("Heap: %s\n", strerror(errno));
1487 HAPI void slave_load_package(struct slave_node *slave)
1489 slave->loaded_package++;
1492 HAPI void slave_unload_package(struct slave_node *slave)
1494 if (!slave || slave->loaded_package == 0) {
1495 ErrPrint("Slave loaded package is not correct\n");
1499 slave->loaded_package--;
1502 HAPI void slave_load_instance(struct slave_node *slave)
1504 slave->loaded_instance++;
1505 DbgPrint("Instance: (%d)%d\n", slave_pid(slave), slave->loaded_instance);
1508 HAPI int const slave_loaded_instance(struct slave_node *slave)
1510 return slave->loaded_instance;
1513 HAPI int const slave_loaded_package(struct slave_node *slave)
1515 return slave->loaded_package;
1518 HAPI struct slave_node *slave_unload_instance(struct slave_node *slave)
1520 if (!slave || slave->loaded_instance == 0) {
1521 ErrPrint("Slave loaded instance is not correct\n");
1525 slave->loaded_instance--;
1526 DbgPrint("Instance: (%d)%d\n", slave_pid(slave), slave->loaded_instance);
1527 if (slave->loaded_instance == 0 && slave_is_activated(slave)) {
1528 slave_set_reactivation(slave, 0);
1529 slave_set_reactivate_instances(slave, 0);
1531 slave = slave_deactivate(slave, 0);
1537 HAPI const int const slave_is_secured(const struct slave_node *slave)
1539 return slave->secured;
1542 HAPI const char * const slave_name(const struct slave_node *slave)
1547 HAPI const char * const slave_abi(const struct slave_node *slave)
1552 HAPI const pid_t const slave_pid(const struct slave_node *slave)
1557 HAPI int slave_set_pid(struct slave_node *slave, pid_t pid)
1560 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1563 DbgPrint("Slave PID is updated to %d from %d\n", pid, slave_pid(slave));
1566 return DBOX_STATUS_ERROR_NONE;
1569 static inline void invoke_resumed_cb(struct slave_node *slave)
1573 struct event *event;
1575 slave->in_event_process |= SLAVE_EVENT_PROCESS_RESUME;
1576 EINA_LIST_FOREACH_SAFE(slave->event_resume_list, l, n, event) {
1577 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
1578 slave->event_resume_list = eina_list_remove(slave->event_resume_list, event);
1582 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_RESUME;
1585 static void resume_cb(struct slave_node *slave, const struct packet *packet, void *data)
1589 if (slave->state == SLAVE_REQUEST_TO_TERMINATE || slave->state == SLAVE_REQUEST_TO_DISCONNECT) {
1590 DbgPrint("Slave is terminating now. ignore resume result\n");
1595 ErrPrint("Failed to change the state of the slave\n");
1596 slave->state = SLAVE_PAUSED;
1600 if (packet_get(packet, "i", &ret) != 1) {
1601 ErrPrint("Invalid parameter\n");
1606 slave->state = SLAVE_RESUMED;
1607 slave_rpc_ping_thaw(slave);
1608 invoke_resumed_cb(slave);
1612 static inline void invoke_paused_cb(struct slave_node *slave)
1616 struct event *event;
1618 slave->in_event_process |= SLAVE_EVENT_PROCESS_PAUSE;
1619 EINA_LIST_FOREACH_SAFE(slave->event_pause_list, l, n, event) {
1620 if (event->deleted || event->evt_cb(event->slave, event->cbdata) < 0 || event->deleted) {
1621 slave->event_pause_list = eina_list_remove(slave->event_pause_list, event);
1625 slave->in_event_process &= ~SLAVE_EVENT_PROCESS_PAUSE;
1628 static void pause_cb(struct slave_node *slave, const struct packet *packet, void *data)
1632 if (slave->state == SLAVE_REQUEST_TO_TERMINATE || slave->state == SLAVE_REQUEST_TO_DISCONNECT) {
1633 DbgPrint("Slave is terminating now. ignore pause result\n");
1638 ErrPrint("Failed to change the state of the slave\n");
1639 slave->state = SLAVE_RESUMED;
1643 if (packet_get(packet, "i", &ret) != 1) {
1644 ErrPrint("Invalid parameter\n");
1649 slave->state = SLAVE_PAUSED;
1650 slave_rpc_ping_freeze(slave);
1651 invoke_paused_cb(slave);
1655 HAPI int slave_resume(struct slave_node *slave)
1658 struct packet *packet;
1659 unsigned int cmd = CMD_RESUME;
1661 switch (slave->state) {
1662 case SLAVE_REQUEST_TO_DISCONNECT:
1663 case SLAVE_REQUEST_TO_LAUNCH:
1664 case SLAVE_REQUEST_TO_TERMINATE:
1665 case SLAVE_TERMINATED:
1666 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1668 case SLAVE_REQUEST_TO_RESUME:
1669 return DBOX_STATUS_ERROR_NONE;
1674 timestamp = util_timestamp();
1676 packet = packet_create((const char *)&cmd, "d", timestamp);
1678 ErrPrint("Failed to prepare param\n");
1679 return DBOX_STATUS_ERROR_FAULT;
1682 slave->state = SLAVE_REQUEST_TO_RESUME;
1683 return slave_rpc_async_request(slave, NULL, packet, resume_cb, NULL, 0);
1686 HAPI int slave_pause(struct slave_node *slave)
1689 struct packet *packet;
1690 unsigned int cmd = CMD_PAUSE;
1692 switch (slave->state) {
1693 case SLAVE_REQUEST_TO_DISCONNECT:
1694 case SLAVE_REQUEST_TO_LAUNCH:
1695 case SLAVE_REQUEST_TO_TERMINATE:
1696 case SLAVE_TERMINATED:
1697 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1699 case SLAVE_REQUEST_TO_PAUSE:
1700 return DBOX_STATUS_ERROR_NONE;
1705 timestamp = util_timestamp();
1707 packet = packet_create((const char *)&cmd, "d", timestamp);
1709 ErrPrint("Failed to prepare param\n");
1710 return DBOX_STATUS_ERROR_FAULT;
1713 slave->state = SLAVE_REQUEST_TO_PAUSE;
1714 return slave_rpc_async_request(slave, NULL, packet, pause_cb, NULL, 0);
1717 HAPI const char *slave_pkgname(const struct slave_node *slave)
1719 return slave ? slave->pkgname : NULL;
1722 HAPI enum slave_state slave_state(const struct slave_node *slave)
1724 return slave ? slave->state : SLAVE_ERROR;
1727 HAPI const char *slave_state_string(const struct slave_node *slave)
1729 switch (slave->state) {
1730 case SLAVE_REQUEST_TO_DISCONNECT:
1731 return "RequestToDisconnect";
1732 case SLAVE_REQUEST_TO_LAUNCH:
1733 return "RequestToLaunch";
1734 case SLAVE_REQUEST_TO_TERMINATE:
1735 return "RequestToTerminate";
1736 case SLAVE_TERMINATED:
1737 return "Terminated";
1738 case SLAVE_REQUEST_TO_PAUSE:
1739 return "RequestToPause";
1740 case SLAVE_REQUEST_TO_RESUME:
1741 return "RequestToResume";
1755 HAPI const void *slave_list(void)
1757 return s_info.slave_list;
1760 HAPI int const slave_fault_count(const struct slave_node *slave)
1762 return slave->fault_count;
1765 HAPI double const slave_ttl(const struct slave_node *slave)
1767 if (!slave->ttl_timer) {
1771 return ecore_timer_pending_get(slave->ttl_timer);
1774 HAPI void slave_set_reactivate_instances(struct slave_node *slave, int reactivate)
1776 slave->reactivate_instances = reactivate;
1779 HAPI int slave_need_to_reactivate_instances(struct slave_node *slave)
1781 return slave->reactivate_instances;
1784 HAPI void slave_set_reactivation(struct slave_node *slave, int flag)
1786 slave->reactivate_slave = flag;
1789 HAPI int slave_need_to_reactivate(struct slave_node *slave)
1791 return slave->reactivate_slave;
1794 HAPI int slave_network(const struct slave_node *slave)
1796 return slave->network;
1799 HAPI void slave_set_network(struct slave_node *slave, int network)
1801 slave->network = network;
1804 HAPI int slave_deactivate_all(int reactivate, int reactivate_instances, int no_timer)
1808 struct slave_node *slave;
1811 s_info.deactivate_all_refcnt++;
1812 if (s_info.deactivate_all_refcnt > 1) {
1815 DbgPrint("Deactivate all\n");
1817 EINA_LIST_FOREACH_SAFE(s_info.slave_list, l, n, slave) {
1818 if (slave_is_activated(slave)) {
1819 slave_set_reactivate_instances(slave, reactivate_instances);
1820 slave_set_reactivation(slave, reactivate);
1822 if (!slave_deactivate(slave, no_timer)) {
1823 s_info.slave_list = eina_list_remove(s_info.slave_list, slave);
1833 HAPI int slave_activate_all(void)
1836 struct slave_node *slave;
1839 s_info.deactivate_all_refcnt--;
1840 if (s_info.deactivate_all_refcnt > 0) {
1843 DbgPrint("Activate all\n");
1845 EINA_LIST_FOREACH(s_info.slave_list, l, slave) {
1846 slave_activate(slave);
1853 HAPI void slave_set_control_option(struct slave_node *slave, int ctrl)
1855 slave->ctrl_option = ctrl;
1858 HAPI int slave_control_option(struct slave_node *slave)
1860 return slave->ctrl_option;
1863 HAPI int slave_set_priority(struct slave_node *slave, int priority)
1868 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1871 pid = slave_pid(slave);
1873 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1876 if (setpriority(PRIO_PROCESS, slave_pid(slave), priority) < 0) {
1877 ErrPrint("setpriority: %s\n", strerror(errno));
1878 return DBOX_STATUS_ERROR_FAULT;
1881 return DBOX_STATUS_ERROR_NONE;
1884 HAPI int slave_priority(struct slave_node *slave)
1890 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1893 pid = slave_pid(slave);
1895 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
1898 priority = getpriority(PRIO_PROCESS, pid);
1900 ErrPrint("getpriority: %s\n", strerror(errno));
1901 return DBOX_STATUS_ERROR_FAULT;