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 */
30 #include <com-core_packet.h>
31 #include <dynamicbox_errno.h>
32 #include <dynamicbox_service.h>
33 #include <dynamicbox_cmd_list.h>
34 #include <dynamicbox_conf.h>
37 #include "slave_life.h"
38 #include "slave_rpc.h"
39 #include "client_life.h"
41 #include "fault_manager.h"
46 Ecore_Timer *pong_timer;
49 unsigned long ping_count;
50 unsigned long next_ping_count;
51 Eina_List *pending_list;
55 /* create_command, destroy_command will care these varaibles */
57 struct packet *packet;
58 struct slave_node *slave;
59 int ttl; /* If it fails to handle this, destroy this */
61 /* Don't need to care these data */
62 void (*ret_cb)(struct slave_node *slave, const struct packet *packet, void *cbdata);
67 Eina_List *command_list;
68 Ecore_Timer *command_consuming_timer;
71 .command_consuming_timer = NULL,
74 #define DEFAULT_CMD_TTL 3
76 static void prepend_command(struct command *command);
78 static inline struct command *create_command(struct slave_node *slave, const char *pkgname, struct packet *packet)
80 struct command *command;
82 command = calloc(1, sizeof(*command));
84 ErrPrint("Heap: %s\n", strerror(errno));
89 command->pkgname = strdup(pkgname);
90 if (!command->pkgname) {
91 ErrPrint("Heap: %s\n", strerror(errno));
97 command->slave = slave_ref(slave); /*!< To prevent from destroying of the slave while communicating with the slave */
98 command->packet = packet_ref(packet);
99 command->ttl = DEFAULT_CMD_TTL;
104 static inline void destroy_command(struct command *command)
106 slave_unref(command->slave);
107 packet_unref(command->packet);
108 DbgFree(command->pkgname);
112 static inline struct command *pop_command(void)
114 struct command *command;
116 command = eina_list_nth(s_info.command_list, 0);
121 s_info.command_list = eina_list_remove(s_info.command_list, command);
125 static int slave_async_cb(pid_t pid, int handle, const struct packet *packet, void *data)
127 struct command *command = data;
130 ErrPrint("Command is NIL\n");
131 return DBOX_STATUS_ERROR_NONE;
136 * command->packet is not valid from here.
138 if (!slave_is_activated(command->slave)) {
139 ErrPrint("Slave is not activated (accidently dead)\n");
140 if (command->ret_cb) {
141 command->ret_cb(command->slave, packet, command->cbdata);
147 DbgPrint("packet == NULL\n");
148 if (command->ret_cb) {
149 command->ret_cb(command->slave, packet, command->cbdata);
154 * Slave will be deactivated from dead monitor if it lost its connections.
155 * So we don't need to care it again from here.
157 command->slave = slave_deactivated_by_fault(command->slave);
163 if (command->ret_cb) {
164 command->ret_cb(command->slave, packet, command->cbdata);
168 destroy_command(command);
169 return DBOX_STATUS_ERROR_NONE;
172 static Eina_Bool command_consumer_cb(void *data)
174 struct command *command;
175 struct slave_rpc *rpc;
177 command = pop_command();
179 s_info.command_consuming_timer = NULL;
180 return ECORE_CALLBACK_CANCEL;
183 if (!slave_is_activated(command->slave)) {
184 ErrPrint("Slave is not activated: %s(%d)\n",
185 slave_name(command->slave), slave_pid(command->slave));
189 if (command->pkgname) {
190 struct pkg_info *info;
192 info = package_find(command->pkgname);
193 if (info && package_is_fault(info)) {
194 ErrPrint("info: %p (%s) is fault package\n", info, command->pkgname);
199 rpc = slave_data(command->slave, "rpc");
200 if (!rpc || rpc->handle < 0) {
201 ErrPrint("Slave has no rpc info\n");
205 if (packet_type(command->packet) == PACKET_REQ_NOACK) {
206 if (com_core_packet_send_only(rpc->handle, command->packet) == 0) {
207 /* Keep a slave alive, while processing events */
208 slave_give_more_ttl(command->slave);
209 destroy_command(command);
210 return ECORE_CALLBACK_RENEW;
212 } else if (packet_type(command->packet) == PACKET_REQ) {
213 if (com_core_packet_async_send(rpc->handle, command->packet, 0.0f, slave_async_cb, command) == 0) {
214 /* Keep a slave alive, while processing events */
215 slave_give_more_ttl(command->slave);
216 return ECORE_CALLBACK_RENEW;
222 * What happens at here?
223 * We are failed to send a packet!!!
224 * Let's try to send this again
228 * Do we need to handle this error?
229 * Close current connection and make new one?
230 * how about pended command lists?
232 DbgPrint("Packet type: %d\n", packet_type(command->packet));
233 DbgPrint("Packet: %p\n", command->packet);
234 DbgPrint("Handle: %d\n", rpc->handle);
235 DbgPrint("PID: %d\n", slave_pid(command->slave));
236 DbgPrint("Name: %s\n", slave_name(command->slave));
237 DbgPrint("Package: %s\n", command->pkgname);
239 if (command->ttl == 0) {
240 DbgPrint("Discard packet (%d)\n", command->ttl);
241 destroy_command(command);
243 DbgPrint("Send again (%d)\n", command->ttl);
244 prepend_command(command);
246 return ECORE_CALLBACK_RENEW;
249 if (command->ret_cb) {
250 command->ret_cb(command->slave, NULL, command->cbdata);
253 destroy_command(command);
254 return ECORE_CALLBACK_RENEW;
257 static void prepend_command(struct command *command)
259 s_info.command_list = eina_list_prepend(s_info.command_list, command);
261 if (s_info.command_consuming_timer) {
265 s_info.command_consuming_timer = ecore_timer_add(DYNAMICBOX_CONF_PACKET_TIME, command_consumer_cb, NULL);
266 if (!s_info.command_consuming_timer) {
267 ErrPrint("Failed to add command consumer\n");
268 s_info.command_list = eina_list_remove(s_info.command_list, command);
269 destroy_command(command);
273 static void push_command(struct command *command)
275 s_info.command_list = eina_list_append(s_info.command_list, command);
277 if (s_info.command_consuming_timer) {
281 s_info.command_consuming_timer = ecore_timer_add(DYNAMICBOX_CONF_PACKET_TIME, command_consumer_cb, NULL);
282 if (!s_info.command_consuming_timer) {
283 ErrPrint("Failed to add command consumer\n");
284 s_info.command_list = eina_list_remove(s_info.command_list, command);
285 destroy_command(command);
289 static int slave_deactivate_cb(struct slave_node *slave, void *data)
291 struct slave_rpc *rpc;
292 struct command *command;
296 rpc = slave_data(slave, "rpc");
300 * Return negative value will remove this callback from the event list of the slave
302 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
305 if (rpc->pong_timer) {
306 ecore_timer_del(rpc->pong_timer);
307 rpc->pong_timer = NULL;
309 ErrPrint("slave has no pong timer\n");
312 if (rpc->handle < 0) {
313 EINA_LIST_FREE(rpc->pending_list, command) {
314 assert(command->slave == slave);
315 if (command->ret_cb) {
316 command->ret_cb(command->slave, NULL, command->cbdata);
318 destroy_command(command);
321 EINA_LIST_FOREACH_SAFE(s_info.command_list, l, n, command) {
322 if (command->slave == slave) {
323 s_info.command_list = eina_list_remove(s_info.command_list, command);
324 if (command->ret_cb) {
325 command->ret_cb(command->slave, NULL, command->cbdata);
327 destroy_command(command);
336 DbgPrint("Reset handle for %d (%d)\n", slave_pid(slave), rpc->handle);
341 * Make statistics table
344 rpc->next_ping_count = 1;
345 return DBOX_STATUS_ERROR_NONE;
348 static Eina_Bool ping_timeout_cb(void *data)
350 struct slave_rpc *rpc;
351 struct slave_node *slave = data;
353 rpc = slave_data(slave, "rpc");
355 ErrPrint("Slave RPC is not valid (%s)\n", slave_name(slave));
356 return ECORE_CALLBACK_CANCEL;
361 * Clear the pong_timer
363 rpc->pong_timer = NULL;
365 if (!slave_is_activated(slave)) {
366 ErrPrint("Slave is not activated (%s)\n", slave_name(slave));
367 return ECORE_CALLBACK_CANCEL;
371 * Dead callback will handling this
373 DbgPrint("Slave PING TIMEOUT: %s(%d) : %p\n", slave_name(slave), slave_pid(slave), slave);
374 slave = slave_deactivated_by_fault(slave);
376 DbgPrint("Slave is deleted\n");
379 return ECORE_CALLBACK_CANCEL;
382 HAPI int slave_rpc_async_request(struct slave_node *slave, const char *pkgname, struct packet *packet, void (*ret_cb)(struct slave_node *slave, const struct packet *packet, void *data), void *data, int urgent)
384 struct command *command;
385 struct slave_rpc *rpc;
387 command = create_command(slave, pkgname, packet);
389 ErrPrint("Failed to create command\n");
392 ret_cb(slave, NULL, data);
395 packet_unref(packet);
396 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
399 command->ret_cb = ret_cb;
400 command->cbdata = data;
401 packet_unref(packet);
403 rpc = slave_data(slave, "rpc");
405 ErrPrint("Slave has no RPC\n");
407 ret_cb(slave, NULL, data);
409 destroy_command(command);
410 return DBOX_STATUS_ERROR_FAULT;
413 if (rpc->handle < 0) {
414 DbgPrint("RPC handle is not ready to use it\n");
415 if (((slave_control_option(slave) & PROVIDER_CTRL_MANUAL_REACTIVATION) == PROVIDER_CTRL_MANUAL_REACTIVATION || slave_is_secured(slave) || (DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL))
416 && !slave_is_activated(slave))
419 DbgPrint("Activate slave forcely\n");
420 ret = slave_activate(slave);
421 if (ret < 0 && ret != DBOX_STATUS_ERROR_ALREADY) {
424 ret_cb(slave, NULL, data);
427 destroy_command(command);
433 rpc->pending_list = eina_list_prepend(rpc->pending_list, command);
435 rpc->pending_list = eina_list_append(rpc->pending_list, command);
438 return DBOX_STATUS_ERROR_NONE;
442 prepend_command(command);
444 push_command(command);
447 return DBOX_STATUS_ERROR_NONE;
450 HAPI int slave_rpc_request_only(struct slave_node *slave, const char *pkgname, struct packet *packet, int urgent)
452 struct command *command;
453 struct slave_rpc *rpc;
455 command = create_command(slave, pkgname, packet);
457 ErrPrint("Failed to create a command\n");
458 packet_unref(packet);
459 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
462 command->ret_cb = NULL;
463 command->cbdata = NULL;
464 packet_unref(packet);
466 rpc = slave_data(slave, "rpc");
468 ErrPrint("Slave has no RPC\n");
469 destroy_command(command);
470 return DBOX_STATUS_ERROR_FAULT;
473 if (rpc->handle < 0) {
474 DbgPrint("RPC handle is not ready to use it\n");
475 if (((slave_control_option(slave) & PROVIDER_CTRL_MANUAL_REACTIVATION) == PROVIDER_CTRL_MANUAL_REACTIVATION || slave_is_secured(slave) || (DBOX_IS_INHOUSE(slave_abi(slave)) && DYNAMICBOX_CONF_SLAVE_LIMIT_TO_TTL))
476 && !slave_is_activated(slave))
480 DbgPrint("Activate slave forcely\n");
481 ret = slave_activate(slave);
482 if (ret < 0 && ret != DBOX_STATUS_ERROR_ALREADY) {
483 destroy_command(command);
489 rpc->pending_list = eina_list_prepend(rpc->pending_list, command);
491 rpc->pending_list = eina_list_append(rpc->pending_list, command);
494 return DBOX_STATUS_ERROR_NONE;
498 prepend_command(command);
500 push_command(command);
503 return DBOX_STATUS_ERROR_NONE;
506 HAPI int slave_rpc_update_handle(struct slave_node *slave, int handle)
508 struct slave_rpc *rpc;
509 struct command *command;
511 rpc = slave_data(slave, "rpc");
513 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
516 DbgPrint("SLAVE: New handle assigned for %d, %d\n", slave_pid(slave), handle);
517 rpc->handle = handle;
518 if (rpc->pong_timer) {
519 ecore_timer_del(rpc->pong_timer);
522 rpc->pong_timer = ecore_timer_add(DYNAMICBOX_CONF_DEFAULT_PING_TIME, ping_timeout_cb, slave);
523 if (!rpc->pong_timer) {
524 ErrPrint("Failed to add ping timer\n");
529 * slave_activated will call the activated callback.
530 * activated callback will try to recover the normal instances state.
531 * so the reset_fault should be called after slave_activated function.
533 slave_activated(slave);
535 EINA_LIST_FREE(rpc->pending_list, command) {
536 push_command(command);
539 return DBOX_STATUS_ERROR_NONE;
542 HAPI int slave_rpc_init(struct slave_node *slave)
544 struct slave_rpc *rpc;
546 rpc = calloc(1, sizeof(*rpc));
548 ErrPrint("Heap: %s\n", strerror(errno));
549 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
552 if (slave_set_data(slave, "rpc", rpc) < 0) {
554 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
557 if (slave_event_callback_add(slave, SLAVE_EVENT_DEACTIVATE, slave_deactivate_cb, NULL) < 0) {
558 ErrPrint("Failed to add event callback\n");
562 rpc->next_ping_count = 1;
565 return DBOX_STATUS_ERROR_NONE;
568 HAPI int slave_rpc_fini(struct slave_node *slave)
570 struct slave_rpc *rpc;
572 rpc = slave_del_data(slave, "rpc");
574 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
577 slave_event_callback_del(slave, SLAVE_EVENT_DEACTIVATE, slave_deactivate_cb, NULL);
579 if (rpc->pong_timer) {
580 ecore_timer_del(rpc->pong_timer);
584 return DBOX_STATUS_ERROR_NONE;
587 HAPI int slave_rpc_ping(struct slave_node *slave)
589 struct slave_rpc *rpc;
591 rpc = slave_data(slave, "rpc");
593 ErrPrint("Slave RPC is not valid\n");
594 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
597 if (!slave_is_activated(slave)) {
598 ErrPrint("Slave is not activated\n");
599 return DBOX_STATUS_ERROR_FAULT;
603 if (rpc->ping_count != rpc->next_ping_count) {
604 ErrPrint("Ping count is not correct\n");
605 rpc->next_ping_count = rpc->ping_count;
607 rpc->next_ping_count++;
609 ecore_timer_reset(rpc->pong_timer);
610 return DBOX_STATUS_ERROR_NONE;
613 HAPI int slave_rpc_ping_freeze(struct slave_node *slave)
615 struct slave_rpc *rpc;
617 rpc = slave_data(slave, "rpc");
619 ErrPrint("Slave RPC is not valid\n");
620 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
623 if (!slave_is_activated(slave)) {
624 ErrPrint("Slave is not activated\n");
625 return DBOX_STATUS_ERROR_FAULT;
628 ecore_timer_freeze(rpc->pong_timer);
629 return DBOX_STATUS_ERROR_NONE;
632 HAPI int slave_rpc_ping_thaw(struct slave_node *slave)
634 struct slave_rpc *rpc;
636 rpc = slave_data(slave, "rpc");
638 ErrPrint("Slave RPC is not valid\n");
639 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
642 if (!slave_is_activated(slave)) {
643 ErrPrint("Slave is not activated\n");
644 return DBOX_STATUS_ERROR_FAULT;
647 ecore_timer_thaw(rpc->pong_timer);
648 return DBOX_STATUS_ERROR_NONE;
651 HAPI void slave_rpc_request_update(const char *pkgname, const char *id, const char *cluster, const char *category, const char *content, int force)
653 struct slave_node *slave;
654 struct pkg_info *info;
655 struct packet *packet;
656 unsigned int cmd = CMD_UPDATE_CONTENT;
658 info = package_find(pkgname);
660 ErrPrint("Failed to find a package\n");
664 slave = package_slave(info);
666 ErrPrint("Failed to find a slave for %s\n", pkgname);
670 packet = packet_create_noack((const char *)&cmd, "sssssi", pkgname, id, cluster, category, content, force);
672 ErrPrint("Failed to create a new param\n");
676 (void)slave_rpc_request_only(slave, pkgname, packet, 0);
679 HAPI int slave_rpc_handle(struct slave_node *slave)
681 struct slave_rpc *rpc;
683 rpc = slave_data(slave, "rpc");
685 DbgPrint("Slave RPC is not initiated\n");
686 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
692 HAPI int slave_rpc_disconnect(struct slave_node *slave)
694 struct packet *packet;
695 unsigned int cmd = CMD_DISCONNECT;
697 packet = packet_create_noack((const char *)&cmd, "d", util_timestamp());
699 ErrPrint("Failed to create a packet\n");
700 return DBOX_STATUS_ERROR_FAULT;
703 DbgPrint("Send disconnection request packet\n");
704 return slave_rpc_request_only(slave, NULL, packet, 0);