void force_reconnect(jsonrpc_server_t* server)
{
	INFO("Reconnecting to server %.*s:%d for conn %.*s.\n",
			STR(server->addr), server->port, STR(server->conn));
	force_disconnect(server);
	bev_connect(server);
}
void wait_server_backoff(unsigned int timeout /* seconds */,
		jsonrpc_server_t* server, bool delay)
{
	if(!server) {
		ERR("Trying to close/reconnect a NULL server\n");
		return;
	}

	if(delay == false) {
		if (requests_using_server(server) <= 0) {
			if(server->status == JSONRPC_SERVER_RECONNECTING) {
				bev_connect(server);
			} else if(server->status == JSONRPC_SERVER_CLOSING) {
				close_server(server);
			}
			return;
		}
	}

	const struct timeval tv = {timeout, 0};

	server_backoff_args_t* args = pkg_malloc(sizeof(server_backoff_args_t));
	CHECK_MALLOC_VOID(args);
	memset(args, 0, sizeof(server_backoff_args_t));

	args->ev = evtimer_new(global_ev_base, server_backoff_cb, (void*)args);
	CHECK_MALLOC_GOTO(args->ev, error);

	args->server = server;
	args->timeout = timeout;

	if(evtimer_add(args->ev, &tv)<0) {
		ERR("event_add failed while setting request timer (%s).", strerror(errno));
		goto error;
	}

	return;

error:
	ERR("schedule_server failed.\n");

	if(args) {
		if(args->ev) {
			evtimer_del(args->ev);
		}
		pkg_free(args);
	}

	if (server->status == JSONRPC_SERVER_CLOSING) {
		ERR("Closing server now...\n");
		close_server(server);
	} else if (server->status == JSONRPC_SERVER_RECONNECTING) {
		ERR("Reconnecting server now...\n");
		force_reconnect(server);
	}
}
void connect_servers(jsonrpc_server_group_t** group)
{
	INIT_SERVER_LOOP
	FOREACH_SERVER_IN(group)
		server = wgroup->server;
		if(server->status != JSONRPC_SERVER_FAILURE
				&& server->status != JSONRPC_SERVER_RECONNECTING)
		{
			bev_connect(server);
		}
	ENDFOR
}
示例#4
0
void cmd_pipe_cb(int fd, short event, void *arg)
{
	struct jsonrpc_pipe_cmd *cmd;

	if (read(fd, &cmd, sizeof(cmd)) != sizeof(cmd)) {
		ERR("FATAL ERROR: failed to read from command pipe: %s\n",
				strerror(errno));
		return;
	}


	switch(cmd->type) {
	case CMD_CLOSE:
		if(cmd->server) {
			wait_close(cmd->server);
		}
		goto end;
		break;
	case CMD_RECONNECT:
		if(cmd->server) {
			wait_reconnect(cmd->server);
		}
		goto end;
		break;
	case CMD_CONNECT:
		if(cmd->server) {
			bev_connect(cmd->server);
		}
		goto end;
		break;
	case CMD_UPDATE_SERVER_GROUP:
		if(cmd->new_grp) {
			jsonrpc_server_group_t* old_grp = *global_server_group;
			*global_server_group = cmd->new_grp;
			free_server_group(&old_grp);
		}
		lock_release(jsonrpc_server_group_lock);
		goto end;
		break;

	case CMD_SEND:
		break;

	default:
		ERR("Unrecognized pipe command: %d\n", cmd->type);
		goto end;
		break;
	}

	/* command is SEND */

	jsonrpc_req_cmd_t* req_cmd = cmd->req_cmd;
	if(req_cmd == NULL) {
		ERR("req_cmd is NULL. Invalid send command\n");
		goto end;
	}

	jsonrpc_request_t* req = NULL;
	req = create_request(req_cmd);
	if (!req || !req->payload) {
		json_t* error = internal_error(JRPC_ERR_REQ_BUILD, NULL);
		pv_value_t val;
		char* freeme = NULL;
		jsontoval(&val, &freeme, error);
		if(req_cmd->route.len <=0 && send_to_script(&val, req_cmd)<0) {
			ERR("Failed to build request (method: %.*s, params: %.*s)\n",
					STR(req_cmd->method), STR(req_cmd->params));
		}
		if(freeme) free(freeme);
		if(error) json_decref(error);
		free_req_cmd(req_cmd);
		goto end;
	}

	int sent = jsonrpc_send(req_cmd->conn, req, req_cmd->notify_only);

	char* type;
	if (sent<0) {
		if (req_cmd->notify_only == false) {
			type = "Request";
		} else {
			type = "Notification";
		}
		WARN("%s could not be sent to connection group: %.*s\n",
				type, STR(req_cmd->conn));
		fail_request(JRPC_ERR_SEND, req, "Failed to send request");
	}

end:
	free_pipe_cmd(cmd);
}