From ce6c41e07c84f0039509430c72063495647e8af3 Mon Sep 17 00:00:00 2001 From: Sung-jae Park Date: Thu, 20 Mar 2014 09:31:09 +0900 Subject: [PATCH] Add slave control option. * Manual reactivation If this flag is on, the master will not reactivate the provider automatically. * Manual termination If this flag is on, the master will not terminate the provider even though it has no DBox instances. Change-Id: Ibc71ee6f5bb735ed24f25b5120713fcf9df130e7 --- include/slave_life.h | 16 +++++ include/slave_rpc.h | 2 + packaging/data-provider-master.spec | 2 +- src/dead_monitor.c | 9 ++- src/server.c | 27 ++++++++ src/slave_life.c | 122 +++++++++++++++++++++++++----------- src/slave_rpc.c | 25 ++++++-- 7 files changed, 158 insertions(+), 45 deletions(-) diff --git a/include/slave_life.h b/include/slave_life.h index 3f110f1..156c4a8 100644 --- a/include/slave_life.h +++ b/include/slave_life.h @@ -59,6 +59,13 @@ enum slave_state { /*! * \note + * Request an action for disconnecting to master from the provider side. + * This flag should be treated as an activated state. + */ + SLAVE_REQUEST_TO_DISCONNECT, + + /*! + * \note * SLAVE_ACTIVATED = { SLAVE_PAUSED, SLAVE_RESUMED } */ SLAVE_PAUSED, @@ -67,6 +74,12 @@ enum slave_state { SLAVE_ERROR = 0xFF /* Explicitly define the size of this enum type */ }; +enum PROVIDER_CTRL { + PROVIDER_CTRL_DEFAULT = 0x00, /*!< Set default control operation */ + PROVIDER_CTRL_MANUAL_TERMINATION = 0x01, /*!< Terminate process manually */ + PROVIDER_CTRL_MANUAL_REACTIVATION = 0x02, /*!< Reactivate process manually */ +}; + extern struct slave_node *slave_ref(struct slave_node *slave); extern struct slave_node *slave_unref(struct slave_node *slave); extern const int const slave_refcnt(struct slave_node *slave); @@ -196,4 +209,7 @@ extern void slave_set_network(struct slave_node *slave, int network); extern int slave_deactivate_all(int reactivate, int reactivate_instances); extern int slave_activate_all(void); +extern void slave_set_control_option(struct slave_node *slave, int ctrl); +extern int slave_control_option(struct slave_node *slave); + /* End of a file */ diff --git a/include/slave_rpc.h b/include/slave_rpc.h index f38702d..f5dc7fa 100644 --- a/include/slave_rpc.h +++ b/include/slave_rpc.h @@ -24,6 +24,8 @@ extern int slave_rpc_handle(struct slave_node *slave); extern int slave_rpc_ping_freeze(struct slave_node *slave); extern int slave_rpc_ping_thaw(struct slave_node *slave); +extern int slave_rpc_disconnect(struct slave_node *slave); + extern int slave_rpc_init(struct slave_node *slave); extern int slave_rpc_fini(struct slave_node *slave); diff --git a/packaging/data-provider-master.spec b/packaging/data-provider-master.spec index 66560a1..8eca2c7 100755 --- a/packaging/data-provider-master.spec +++ b/packaging/data-provider-master.spec @@ -2,7 +2,7 @@ Name: data-provider-master Summary: Master service provider for liveboxes -Version: 0.40.1 +Version: 0.41.0 Release: 1 Group: HomeTF/Livebox License: Flora diff --git a/src/dead_monitor.c b/src/dead_monitor.c index 9769996..313327f 100644 --- a/src/dead_monitor.c +++ b/src/dead_monitor.c @@ -42,10 +42,15 @@ static int evt_cb(int handle, void *data) slave = slave_find_by_rpc_handle(handle); if (slave) { if (slave_pid(slave) != (pid_t)-1) { - if (slave_state(slave) == SLAVE_REQUEST_TO_TERMINATE) { + switch (slave_state(slave)) { + case SLAVE_REQUEST_TO_DISCONNECT: + DbgPrint("Disconnected from %d\n", slave_pid(slave)); + case SLAVE_REQUEST_TO_TERMINATE: slave = slave_deactivated(slave); - } else if (slave_state(slave) != SLAVE_TERMINATED) { + break; + default: slave = slave_deactivated_by_fault(slave); + break; } } diff --git a/src/server.c b/src/server.c index 129bf97..36689d8 100644 --- a/src/server.c +++ b/src/server.c @@ -5960,6 +5960,29 @@ out: return NULL; } +static struct packet *slave_ctrl(pid_t pid, int handle, const struct packet *packet) +{ + struct slave_node *slave; + int ctrl; + int ret; + + slave = slave_find_by_pid(pid); + if (!slave) { + ErrPrint("Slave %d is not exists\n", pid); + goto out; + } + + ret = packet_get(packet, "i", &ctrl); + if (ret != 1) { + ErrPrint("Parameter is not matched\n"); + } else { + slave_set_control_option(slave, ctrl); + } + +out: + return NULL; +} + static struct packet *slave_ping(pid_t pid, int handle, const struct packet *packet) /* slave_name, ret */ { struct slave_node *slave; @@ -7933,6 +7956,10 @@ static struct method s_slave_table[] = { .cmd = "ping", .handler = slave_ping, /* slave_name, ret */ }, + { + .cmd = "ctrl", + .handler = slave_ctrl, /* control bits */ + }, { .cmd = NULL, diff --git a/src/slave_life.c b/src/slave_life.c index d0b292b..74f59b4 100644 --- a/src/slave_life.c +++ b/src/slave_life.c @@ -90,6 +90,8 @@ struct slave_node { Ecore_Timer *terminate_timer; /*!< Waiting this timer before terminate the service provider */ int relaunch_count; + int ctrl_option; + #if defined(_USE_ECORE_TIME_GET) double activated_at; #else @@ -440,13 +442,20 @@ static inline void invoke_slave_fault_handler(struct slave_node *slave) slave_set_reactivate_instances(slave, 0); if (slave_pid(slave) > 0) { - int ret; - DbgPrint("Try to terminate PID: %d\n", slave_pid(slave)); - ret = aul_terminate_pid(slave_pid(slave)); - if (ret < 0) { - ErrPrint("Terminate failed, pid %d (reason: %d)\n", slave_pid(slave), ret); + if ((slave->ctrl_option & PROVIDER_CTRL_MANUAL_TERMINATION) == PROVIDER_CTRL_MANUAL_TERMINATION) { + DbgPrint("Manual termination is turned on\n"); + (void)slave_rpc_disconnect(slave); + } else { + int ret; + DbgPrint("Try to terminate PID: %d\n", slave_pid(slave)); + ret = aul_terminate_pid(slave_pid(slave)); + if (ret < 0) { + ErrPrint("Terminate failed, pid %d (reason: %d)\n", slave_pid(slave), ret); + } } } + + slave->state = SLAVE_TERMINATED; } static Eina_Bool relaunch_timer_cb(void *data) @@ -548,7 +557,7 @@ HAPI int slave_activate(struct slave_node *slave) DbgPrint("Clear terminate timer. to reuse (%d)\n", slave->pid); ecore_timer_del(slave->terminate_timer); slave->terminate_timer = NULL; - } else if (slave_state(slave) == SLAVE_REQUEST_TO_TERMINATE) { + } else if (slave_state(slave) == SLAVE_REQUEST_TO_TERMINATE || slave_state(slave) == SLAVE_REQUEST_TO_DISCONNECT) { slave_set_reactivation(slave, 1); } return LB_STATUS_ERROR_ALREADY; @@ -783,47 +792,59 @@ HAPI struct slave_node *slave_deactivate(struct slave_node *slave, int direct) return slave; } - if (slave_pid(slave) > 0) { - if (slave->terminate_timer) { - ErrPrint("Terminate timer is already fired (%d)\n", slave->pid); - } else if (!direct) { - DbgPrint("Fire the terminate timer: %d\n", slave->pid); - slave->terminate_timer = ecore_timer_add(SLAVE_ACTIVATE_TIME, terminate_timer_cb, slave); - if (!slave->terminate_timer) { - /*! - * \note - * Normally, Call the terminate_timer_cb directly from here - * But in this case. if the aul_terminate_pid failed, Call the slave_deactivated function directly. - * Then the "slave" pointer can be changed. To trace it, Copy the body of terminate_timer_cb to here. - */ - ErrPrint("Failed to add a new timer for terminating\n"); - DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave)); - /*! - * \todo - * check the return value of the aul_terminate_pid - */ - slave->state = SLAVE_REQUEST_TO_TERMINATE; + if (slave_pid(slave) <= 0) { + return slave; + } - ret = aul_terminate_pid(slave->pid); - if (ret < 0) { - ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret); - slave = slave_deactivated(slave); - } - } - } else { + if ((slave->ctrl_option & PROVIDER_CTRL_MANUAL_TERMINATION) == PROVIDER_CTRL_MANUAL_TERMINATION) { + /*! + * \note + * In this case, + * The provider requests MANUAL TERMINATION control option. + * Master will not send terminate request in this case, the provider should be terminated by itself. + */ + DbgPrint("Manual termination is turned on\n"); + slave->state = SLAVE_REQUEST_TO_DISCONNECT; + (void)slave_rpc_disconnect(slave); + } else if (slave->terminate_timer) { + ErrPrint("Terminate timer is already fired (%d)\n", slave->pid); + } else if (!direct) { + DbgPrint("Fire the terminate timer: %d\n", slave->pid); + slave->terminate_timer = ecore_timer_add(SLAVE_ACTIVATE_TIME, terminate_timer_cb, slave); + if (!slave->terminate_timer) { + /*! + * \note + * Normally, Call the terminate_timer_cb directly from here + * But in this case. if the aul_terminate_pid failed, Call the slave_deactivated function directly. + * Then the "slave" pointer can be changed. To trace it, Copy the body of terminate_timer_cb to here. + */ + ErrPrint("Failed to add a new timer for terminating\n"); + DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave)); /*! * \todo * check the return value of the aul_terminate_pid */ slave->state = SLAVE_REQUEST_TO_TERMINATE; - DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave)); ret = aul_terminate_pid(slave->pid); if (ret < 0) { ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret); slave = slave_deactivated(slave); } } + } else { + /*! + * \todo + * check the return value of the aul_terminate_pid + */ + slave->state = SLAVE_REQUEST_TO_TERMINATE; + + DbgPrint("Terminate slave: %d (%s)\n", slave_pid(slave), slave_name(slave)); + ret = aul_terminate_pid(slave->pid); + if (ret < 0) { + ErrPrint("Terminate slave(%s) failed. pid %d (%d)\n", slave_name(slave), slave_pid(slave), ret); + slave = slave_deactivated(slave); + } } return slave; @@ -864,7 +885,14 @@ HAPI struct slave_node *slave_deactivated(struct slave_node *slave) return slave; } - if (reactivate && slave_need_to_reactivate(slave)) { + if ((slave->ctrl_option & PROVIDER_CTRL_MANUAL_REACTIVATION) == PROVIDER_CTRL_MANUAL_REACTIVATION) { + /*! + * \note + * In this case, the provider(Slave) should be reactivated by itself or user. + * The master will not reactivate it automatically. + */ + DbgPrint("Manual reactivate option is turned on\n"); + } else if (reactivate && slave_need_to_reactivate(slave)) { int ret; DbgPrint("Need to reactivate a slave\n"); @@ -972,6 +1000,10 @@ HAPI const int const slave_is_activated(struct slave_node *slave) case SLAVE_REQUEST_TO_TERMINATE: case SLAVE_TERMINATED: return 0; + case SLAVE_REQUEST_TO_DISCONNECT: + /* This case should be treated as an activated state. + * To send the last request to the provider. + */ case SLAVE_REQUEST_TO_LAUNCH: /* Not yet launched. but the slave incurred an unexpected error */ case SLAVE_REQUEST_TO_PAUSE: @@ -1233,7 +1265,7 @@ HAPI struct slave_node *slave_find_available(const char *abi, int secured, int n continue; } - if (slave->state == SLAVE_REQUEST_TO_TERMINATE && slave->loaded_instance == 0) { + if ((slave->state == SLAVE_REQUEST_TO_TERMINATE || slave->state == SLAVE_REQUEST_TO_DISCONNECT) && slave->loaded_instance == 0) { /*! * \note * If a slave is in request_to_terminate state, @@ -1408,7 +1440,7 @@ static void resume_cb(struct slave_node *slave, const struct packet *packet, voi { int ret; - if (slave->state == SLAVE_REQUEST_TO_TERMINATE) { + if (slave->state == SLAVE_REQUEST_TO_TERMINATE || slave->state == SLAVE_REQUEST_TO_DISCONNECT) { DbgPrint("Slave is terminating now. ignore resume result\n"); return; } @@ -1451,7 +1483,7 @@ static void pause_cb(struct slave_node *slave, const struct packet *packet, void { int ret; - if (slave->state == SLAVE_REQUEST_TO_TERMINATE) { + if (slave->state == SLAVE_REQUEST_TO_TERMINATE || slave->state == SLAVE_REQUEST_TO_DISCONNECT) { DbgPrint("Slave is terminating now. ignore pause result\n"); return; } @@ -1480,6 +1512,7 @@ HAPI int slave_resume(struct slave_node *slave) struct packet *packet; switch (slave->state) { + case SLAVE_REQUEST_TO_DISCONNECT: case SLAVE_REQUEST_TO_LAUNCH: case SLAVE_REQUEST_TO_TERMINATE: case SLAVE_TERMINATED: @@ -1509,6 +1542,7 @@ HAPI int slave_pause(struct slave_node *slave) struct packet *packet; switch (slave->state) { + case SLAVE_REQUEST_TO_DISCONNECT: case SLAVE_REQUEST_TO_LAUNCH: case SLAVE_REQUEST_TO_TERMINATE: case SLAVE_TERMINATED: @@ -1545,6 +1579,8 @@ HAPI enum slave_state slave_state(const struct slave_node *slave) HAPI const char *slave_state_string(const struct slave_node *slave) { switch (slave->state) { + case SLAVE_REQUEST_TO_DISCONNECT: + return "RequestToDisconnect"; case SLAVE_REQUEST_TO_LAUNCH: return "RequestToLaunch"; case SLAVE_REQUEST_TO_TERMINATE: @@ -1664,4 +1700,14 @@ HAPI int slave_activate_all(void) return cnt; } +HAPI void slave_set_control_option(struct slave_node *slave, int ctrl) +{ + slave->ctrl_option = ctrl; +} + +HAPI int slave_control_option(struct slave_node *slave) +{ + return slave->ctrl_option; +} + /* End of a file */ diff --git a/src/slave_rpc.c b/src/slave_rpc.c index 5f8de15..7f64c9d 100644 --- a/src/slave_rpc.c +++ b/src/slave_rpc.c @@ -409,7 +409,9 @@ HAPI int slave_rpc_async_request(struct slave_node *slave, const char *pkgname, if (rpc->handle < 0) { DbgPrint("RPC handle is not ready to use it\n"); - if (slave_is_secured(slave) && !slave_is_activated(slave)) { + if (((slave_control_option(slave) & PROVIDER_CTRL_MANUAL_REACTIVATION) == PROVIDER_CTRL_MANUAL_REACTIVATION || slave_is_secured(slave)) + && !slave_is_activated(slave)) + { int ret; DbgPrint("Activate slave forcely\n"); ret = slave_activate(slave); @@ -467,8 +469,9 @@ HAPI int slave_rpc_request_only(struct slave_node *slave, const char *pkgname, s if (rpc->handle < 0) { DbgPrint("RPC handle is not ready to use it\n"); - - if (slave_is_secured(slave) && !slave_is_activated(slave)) { + if (((slave_control_option(slave) & PROVIDER_CTRL_MANUAL_REACTIVATION) == PROVIDER_CTRL_MANUAL_REACTIVATION || slave_is_secured(slave)) + && !slave_is_activated(slave)) + { int ret; DbgPrint("Activate slave forcely\n"); @@ -676,10 +679,24 @@ HAPI int slave_rpc_handle(struct slave_node *slave) rpc = slave_data(slave, "rpc"); if (!rpc) { DbgPrint("Slave RPC is not initiated\n"); - return -EINVAL; + return LB_STATUS_ERROR_INVALID; } return rpc->handle; } +HAPI int slave_rpc_disconnect(struct slave_node *slave) +{ + struct packet *packet; + + packet = packet_create_noack("disconnect", "d", util_timestamp()); + if (!packet) { + ErrPrint("Failed to create a packet\n"); + return LB_STATUS_ERROR_FAULT; + } + + DbgPrint("Send disconnection request packet\n"); + return slave_rpc_request_only(slave, NULL, packet, 0); +} + /* End of a file */ -- 2.7.4