diff options
Diffstat (limited to 'tests/net_load_tests/srv.cpp')
-rw-r--r-- | tests/net_load_tests/srv.cpp | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/tests/net_load_tests/srv.cpp b/tests/net_load_tests/srv.cpp new file mode 100644 index 000000000..52895c9dd --- /dev/null +++ b/tests/net_load_tests/srv.cpp @@ -0,0 +1,211 @@ +// Copyright (c) 2012-2013 The Cryptonote developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include <mutex> +#include <thread> + +#include "include_base_utils.h" +#include "misc_log_ex.h" +#include "storages/levin_abstract_invoke2.h" + +#include "net_load_tests.h" + +using namespace net_load_tests; + +#define EXIT_ON_ERROR(cond) { if (!(cond)) { LOG_PRINT_L0("ERROR: " << #cond); exit(1); } else {} } + +namespace +{ + struct srv_levin_commands_handler : public test_levin_commands_handler + { + srv_levin_commands_handler(test_tcp_server& tcp_server) + : m_tcp_server(tcp_server) + , m_open_close_test_conn_id(boost::uuids::nil_uuid()) + { + } + + virtual void on_connection_new(test_connection_context& context) + { + test_levin_commands_handler::on_connection_new(context); + context.m_closed = false; + + //std::this_thread::sleep_for(std::chrono::milliseconds(10)); + + std::unique_lock<std::mutex> lock(m_open_close_test_mutex); + if (!m_open_close_test_conn_id.is_nil()) + { + EXIT_ON_ERROR(m_open_close_test_helper->handle_new_connection(context.m_connection_id, true)); + } + } + + virtual void on_connection_close(test_connection_context& context) + { + test_levin_commands_handler::on_connection_close(context); + + std::unique_lock<std::mutex> lock(m_open_close_test_mutex); + if (context.m_connection_id == m_open_close_test_conn_id) + { + LOG_PRINT_L0("Stop open/close test"); + m_open_close_test_conn_id = boost::uuids::nil_uuid(); + m_open_close_test_helper.reset(0); + } + } + + CHAIN_LEVIN_INVOKE_MAP2(test_connection_context); + CHAIN_LEVIN_NOTIFY_MAP2(test_connection_context); + + BEGIN_INVOKE_MAP2(srv_levin_commands_handler) + HANDLE_NOTIFY_T2(CMD_CLOSE_ALL_CONNECTIONS, &srv_levin_commands_handler::handle_close_all_connections) + HANDLE_NOTIFY_T2(CMD_SHUTDOWN, &srv_levin_commands_handler::handle_shutdown) + HANDLE_NOTIFY_T2(CMD_SEND_DATA_REQUESTS, &srv_levin_commands_handler::handle_send_data_requests) + HANDLE_INVOKE_T2(CMD_GET_STATISTICS, &srv_levin_commands_handler::handle_get_statistics) + HANDLE_INVOKE_T2(CMD_RESET_STATISTICS, &srv_levin_commands_handler::handle_reset_statistics) + HANDLE_INVOKE_T2(CMD_START_OPEN_CLOSE_TEST, &srv_levin_commands_handler::handle_start_open_close_test) + END_INVOKE_MAP2() + + int handle_close_all_connections(int command, const CMD_CLOSE_ALL_CONNECTIONS::request& req, test_connection_context& context) + { + close_connections(context.m_connection_id); + return 1; + } + + int handle_get_statistics(int command, const CMD_GET_STATISTICS::request&, CMD_GET_STATISTICS::response& rsp, test_connection_context& /*context*/) + { + rsp.opened_connections_count = m_tcp_server.get_config_object().get_connections_count(); + rsp.new_connection_counter = new_connection_counter(); + rsp.close_connection_counter = close_connection_counter(); + LOG_PRINT_L0("Statistics: " << rsp.to_string()); + return 1; + } + + int handle_reset_statistics(int command, const CMD_RESET_STATISTICS::request&, CMD_RESET_STATISTICS::response& /*rsp*/, test_connection_context& /*context*/) + { + m_new_connection_counter.reset(); + m_new_connection_counter.inc(); + m_close_connection_counter.reset(); + return 1; + } + + int handle_start_open_close_test(int command, const CMD_START_OPEN_CLOSE_TEST::request& req, CMD_START_OPEN_CLOSE_TEST::response&, test_connection_context& context) + { + std::unique_lock<std::mutex> lock(m_open_close_test_mutex); + if (0 == m_open_close_test_helper.get()) + { + LOG_PRINT_L0("Start open/close test (" << req.open_request_target << ", " << req.max_opened_conn_count << ")"); + + m_open_close_test_conn_id = context.m_connection_id; + m_open_close_test_helper.reset(new open_close_test_helper(m_tcp_server, req.open_request_target, req.max_opened_conn_count)); + return 1; + } + else + { + return -1; + } + } + + int handle_shutdown(int command, const CMD_SHUTDOWN::request& req, test_connection_context& /*context*/) + { + LOG_PRINT_L0("Got shutdown requst. Shutting down..."); + m_tcp_server.send_stop_signal(); + return 1; + } + + int handle_send_data_requests(int /*command*/, const CMD_SEND_DATA_REQUESTS::request& req, test_connection_context& context) + { + boost::uuids::uuid cmd_conn_id = context.m_connection_id; + m_tcp_server.get_config_object().foreach_connection([&](test_connection_context& ctx) { + if (ctx.m_connection_id != cmd_conn_id) + { + CMD_DATA_REQUEST::request req2; + req2.data.resize(req.request_size); + + bool r = epee::net_utils::async_invoke_remote_command2<CMD_DATA_REQUEST::response>(ctx.m_connection_id, CMD_DATA_REQUEST::ID, req2, + m_tcp_server.get_config_object(), [=](int code, const CMD_DATA_REQUEST::response& rsp, const test_connection_context&) { + if (code <= 0) + { + LOG_PRINT_L0("Failed to invoke CMD_DATA_REQUEST. code = " << code); + } + }); + if (!r) + LOG_PRINT_L0("Failed to invoke CMD_DATA_REQUEST"); + } + return true; + }); + + return 1; + } + + private: + void close_connections(boost::uuids::uuid cmd_conn_id) + { + LOG_PRINT_L0("Closing connections. Number of opened connections: " << m_tcp_server.get_config_object().get_connections_count()); + + size_t count = 0; + bool r = m_tcp_server.get_config_object().foreach_connection([&](test_connection_context& ctx) { + if (ctx.m_connection_id != cmd_conn_id) + { + ++count; + if (!ctx.m_closed) + { + ctx.m_closed = true; + m_tcp_server.get_config_object().close(ctx.m_connection_id); + } + else + { + LOG_PRINT_L0(count << " connection already closed"); + } + } + return true; + }); + + if (0 < count) + { + // Perhaps not all connections were closed, try to close it after 7 seconds + boost::shared_ptr<boost::asio::deadline_timer> sh_deadline(new boost::asio::deadline_timer(m_tcp_server.get_io_service(), boost::posix_time::seconds(7))); + sh_deadline->async_wait([=](const boost::system::error_code& ec) + { + boost::shared_ptr<boost::asio::deadline_timer> t = sh_deadline; // Capture sh_deadline + if (!ec) + { + close_connections(cmd_conn_id); + } + else + { + LOG_PRINT_L0("ERROR: " << ec.message() << ':' << ec.value()); + } + }); + } + } + + private: + test_tcp_server& m_tcp_server; + + boost::uuids::uuid m_open_close_test_conn_id; + std::mutex m_open_close_test_mutex; + std::unique_ptr<open_close_test_helper> m_open_close_test_helper; + }; +} + +int main(int argc, char** argv) +{ + //set up logging options + epee::log_space::get_set_log_detalisation_level(true, LOG_LEVEL_0); + epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL); + + size_t thread_count = (std::max)(min_thread_count, std::thread::hardware_concurrency() / 2); + + test_tcp_server tcp_server; + if (!tcp_server.init_server(srv_port, "127.0.0.1")) + return 1; + + srv_levin_commands_handler commands_handler(tcp_server); + tcp_server.get_config_object().m_pcommands_handler = &commands_handler; + tcp_server.get_config_object().m_invoke_timeout = 10000; + //tcp_server.get_config_object().m_max_packet_size = max_packet_size; + + if (!tcp_server.run_server(thread_count, true)) + return 2; + + return 0; +} |