Add slave control option.
authorSung-jae Park <nicesj.park@samsung.com>
Thu, 20 Mar 2014 00:31:09 +0000 (09:31 +0900)
committerSung-jae Park <nicesj.park@samsung.com>
Thu, 20 Mar 2014 12:54:55 +0000 (21:54 +0900)
* 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
include/slave_rpc.h
packaging/data-provider-master.spec
src/dead_monitor.c
src/server.c
src/slave_life.c
src/slave_rpc.c

index 3f110f1..156c4a8 100644 (file)
@@ -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 */
index f38702d..f5dc7fa 100644 (file)
@@ -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);
 
index 66560a1..8eca2c7 100755 (executable)
@@ -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
index 9769996..313327f 100644 (file)
@@ -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;
                        }
                }
 
index 129bf97..36689d8 100644 (file)
@@ -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,
index d0b292b..74f59b4 100644 (file)
@@ -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 */
index 5f8de15..7f64c9d 100644 (file)
@@ -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 */