From 219c71d489d9ed1de6a5232f96f7f8a299e57d15 Mon Sep 17 00:00:00 2001 From: Gabriel Braga Date: Tue, 9 Apr 2024 16:48:19 +0200 Subject: [PATCH] Switch socket management API to epoll() (#7785) Previously all the server and client sockets were being managed by the select() API, which operates using a fixed amount of client sockets. This commit changes the code to adapt to the epoll() API. This commit also could have a performance improvement due to epoll's architecture. Note: next commits should fix: - The clock from sec to millisecs as the epoll_wait() uses millisecs. - Unit tests need to be changed to work properly. --- src/client_wrapper.hxx | 32 +++++----- src/command_client.cpp | 33 ++++++---- src/command_client.hxx | 46 +++++++------ src/command_server.cpp | 7 +- src/command_server.hxx | 2 +- src/connection.hxx | 10 +-- src/server.cpp | 5 +- src/server.hxx | 15 ++-- src/socket_client.cpp | 69 +++++++------------- src/socket_client.hxx | 31 ++++----- src/socket_handler.cpp | 170 +++++++++++++++++++++++++----------------------- src/socket_handler.hxx | 24 +++++-- src/socket_server.cpp | 77 ++++++++-------------- src/socket_server.hxx | 18 ++++-- src/socket_wrapper.cpp | 6 +- src/socket_wrapper.hxx | 44 +++++++------ test/hello.cpp | 12 ++-- test/reentrant.cpp | 2 +- test/timeout.cpp | 4 +- test/wrapper.cpp | 14 ++-- 20 files changed, 304 insertions(+), 317 deletions(-) diff --git a/src/client_wrapper.hxx b/src/client_wrapper.hxx index 73fda24..9c62d2d 100644 --- a/src/client_wrapper.hxx +++ b/src/client_wrapper.hxx @@ -48,8 +48,8 @@ namespace libt2n class ConnectionWrapper { private: - long long command_timeout_usec; - long long hello_timeout_usec; + int command_timeout_millisec; + int hello_timeout_millisec; protected: log_level_values log_level; @@ -58,8 +58,8 @@ class ConnectionWrapper public: ConnectionWrapper() - : command_timeout_usec(command_client::command_timeout_usec_default), - hello_timeout_usec(command_client::hello_timeout_usec_default), + : command_timeout_millisec(command_client::command_timeout_millisec_default), + hello_timeout_millisec(command_client::hello_timeout_millisec_default), log_level(none), logstream(NULL) { } @@ -93,17 +93,17 @@ class ConnectionWrapper return true; } - long long get_command_timeout_usec(void) - { return command_timeout_usec; } + int get_command_timeout_millisec() const + { return command_timeout_millisec; } - void set_command_timeout_usec(long long _command_timeout_usec) - { command_timeout_usec=_command_timeout_usec; } + void set_command_timeout_millisec(int _command_timeout_millisec) + { command_timeout_millisec=_command_timeout_millisec; } - long long get_hello_timeout_usec(void) - { return hello_timeout_usec; } + int get_hello_timeout_millisec() const + { return hello_timeout_millisec; } - void set_hello_timeout_usec(long long _hello_timeout_usec) - { hello_timeout_usec=_hello_timeout_usec; } + void set_hello_timeout_millisec(int _hello_timeout_millisec) + { hello_timeout_millisec=_hello_timeout_millisec; } virtual void set_logging(std::ostream *_logstream, log_level_values _log_level); @@ -225,8 +225,8 @@ class T2nSingletonWrapper : public T2nSingletonWrapperMessages throw std::logic_error(NotInitializedMessage); std::auto_ptr stub(new Client(WrappedConnection->get_connection(), - WrappedConnection->get_command_timeout_usec(), - WrappedConnection->get_hello_timeout_usec())); + WrappedConnection->get_command_timeout_millisec(), + WrappedConnection->get_hello_timeout_millisec())); SingletonObject=std::auto_ptr(new T2nSingletonWrapper(stub)); } @@ -267,11 +267,11 @@ class T2nSingletonWrapper : public T2nSingletonWrapperMessages } /// return a pointer to the ConnectionWrapper currently in use - static ConnectionWrapper* get_connection_wrapper(void) + static ConnectionWrapper* get_connection_wrapper() { return WrappedConnection.get(); } /// manually establish the connection without actually executing a call - static void ensure_singleton_there(void) + static void ensure_singleton_there() { if (SingletonObject.get() == NULL) init(); diff --git a/src/command_client.cpp b/src/command_client.cpp index 924fdbf..0780f73 100644 --- a/src/command_client.cpp +++ b/src/command_client.cpp @@ -32,6 +32,7 @@ on this file might be covered by the GNU General Public License. #include #include "command_client.hxx" +#include "monotonic_clock.hxx" #include @@ -43,15 +44,15 @@ namespace libt2n /** * Constructor * @param _c connection for this command. Ownership of the pointer is outside. - * @param _command_timeout_usec timeout until the command has to be completed - * @param _hello_timeout_usec timeout until hello has to be received + * @param _command_timeout_millisec timeout until the command has to be completed + * @param _hello_timeout_millisec timeout until hello has to be received */ -command_client::command_client(client_connection* _c, long long _command_timeout_usec, long long _hello_timeout_usec) +command_client::command_client(client_connection* _c, int _command_timeout_millisec, int _hello_timeout_millisec) : c(_c) , constructorException(NULL) { - command_timeout_usec=_command_timeout_usec; - hello_timeout_usec=_hello_timeout_usec; + command_timeout_millisec=_command_timeout_millisec; + hello_timeout_millisec=_hello_timeout_millisec; // for reconnects c->add_callback(new_connection,bind(&command_client::read_hello, boost::ref(*this))); @@ -114,18 +115,24 @@ void command_client::replace_connection(client_connection* _c) } /** @brief return a complete packet - @param usec_timeout maximum microseconds to wait until the packet is complete + @param millisec_timeout maximum microseconds to wait until the packet is complete @retval packet data as std::string @note throws a t2n_transfer_error if the timeout is exceeded */ -std::string command_client::read_packet(const long long &usec_timeout) +std::string command_client::read_packet(const int &millisec_timeout) { string resultpacket; bool got_packet=false; - long long my_timeout=usec_timeout; + int my_timeout=millisec_timeout, timeout_checkpoint; + while(!(got_packet=c->get_packet(resultpacket)) && my_timeout > 0 && !c->is_closed()) - c->fill_buffer(my_timeout,&my_timeout); + { + timeout_checkpoint=monotonic_clock_gettime_sec(); + c->fill_buffer(millisec_timeout); + my_timeout -= abs(monotonic_clock_gettime_sec() - timeout_checkpoint); + } + if (!got_packet) throw t2n_transfer_error("timeout exceeded"); @@ -141,10 +148,12 @@ void command_client::read_hello() { string resultpacket; bool got_packet=false; - long long my_timeout=hello_timeout_usec; + int my_timeout=hello_timeout_millisec, timeout_checkpoint; while(!(got_packet=c->get_packet(resultpacket)) && my_timeout > 0 && !c->is_closed()) { - c->fill_buffer(my_timeout,&my_timeout); + timeout_checkpoint=monotonic_clock_gettime_sec(); + c->fill_buffer(my_timeout); + my_timeout -= abs(monotonic_clock_gettime_sec() - timeout_checkpoint); c->peek_packet(resultpacket); check_hello(resultpacket); // will throw before timeout if wrong data received @@ -276,7 +285,7 @@ void command_client::send_command(command* cmd, result_container &res) c->write(ofs.str()); - istringstream ifs(read_packet(command_timeout_usec)); + istringstream ifs(read_packet(command_timeout_millisec)); boost::archive::binary_iarchive ia(ifs); try diff --git a/src/command_client.hxx b/src/command_client.hxx index fc72ca7..cef834b 100644 --- a/src/command_client.hxx +++ b/src/command_client.hxx @@ -35,42 +35,48 @@ namespace libt2n class command_client { public: - static const long long command_timeout_usec_default=90000000; - static const long long hello_timeout_usec_default=30000000; + static const int command_timeout_millisec_default=90000; + static const int hello_timeout_millisec_default=30000; private: client_connection *c; - long long hello_timeout_usec; - long long command_timeout_usec; + int hello_timeout_millisec; + int command_timeout_millisec; + + t2n_exception *constructorException; void read_hello(); - std::string read_packet(const long long &usec_timeout); + std::string read_packet(const int &millisec_timeout); bool check_hello(const std::string& hellostr); - t2n_exception *constructorException; - public: - command_client(client_connection* _c, - long long _command_timeout_usec=command_timeout_usec_default, - long long _hello_timeout_usec=hello_timeout_usec_default); + explicit command_client(client_connection* _c, + int _command_timeout_millisec=command_timeout_millisec_default, + int _hello_timeout_millisec=hello_timeout_millisec_default); + virtual ~command_client(); void replace_connection(client_connection* _c); void send_command(command* cmd, result_container &res); - void set_command_timeout_usec(long long _command_timeout_usec=command_timeout_usec_default) - { command_timeout_usec=_command_timeout_usec; } - void set_hello_timeout_usec(long long _hello_timeout_usec=hello_timeout_usec_default) - { hello_timeout_usec=_hello_timeout_usec; } - long long get_command_timeout_usec(void) - { return command_timeout_usec; } - long long get_hello_timeout_usec(void) - { return hello_timeout_usec; } - bool is_connection_closed(void) + void set_command_timeout_millisec(int _command_timeout_millisec=command_timeout_millisec_default) + { command_timeout_millisec=_command_timeout_millisec; } + + void set_hello_timeout_millisec(int _hello_timeout_millisec=hello_timeout_millisec_default) + { hello_timeout_millisec=_hello_timeout_millisec; } + + int get_command_timeout_millisec() const + { return command_timeout_millisec; } + + int get_hello_timeout_millisec() const + { return hello_timeout_millisec; } + + bool is_connection_closed() { return c->is_closed(); } - t2n_exception* get_constuctor_exception(void) + + t2n_exception* get_constructor_exception() { return constructorException; } }; diff --git a/src/command_server.cpp b/src/command_server.cpp index 21aeb79..de18c56 100644 --- a/src/command_server.cpp +++ b/src/command_server.cpp @@ -161,17 +161,16 @@ void command_server::handle_packet(const std::string& packet, server_connection* } /** @brief handle incoming commands - @param[in,out] usec_timeout wait until new data is found, max timeout usecs. + @param[in,out] millisec_timeout wait until new data is found, max timeout millisecs. -1: wait endless, 0: instant return - @param[out] usec_timeout_remaining microseconds from the timeout that were not used */ -void command_server::handle(long long usec_timeout, long long* usec_timeout_remaining) +void command_server::handle(int millisec_timeout) { guard_handle++; try { - if (s.fill_buffer(usec_timeout,usec_timeout_remaining)) + if (s.fill_buffer(millisec_timeout)) { std::string packet; unsigned int conn_id = 0; diff --git a/src/command_server.hxx b/src/command_server.hxx index 95dfe32..384677c 100644 --- a/src/command_server.hxx +++ b/src/command_server.hxx @@ -46,7 +46,7 @@ class command_server command_server(server& _s); ~command_server(); - void handle(long long usec_timeout=-1, long long* usec_timeout_remaining=NULL); + void handle(int millisec_timeout=-1); void send_hello(unsigned int conn_id); diff --git a/src/connection.hxx b/src/connection.hxx index f737559..b178fe1 100644 --- a/src/connection.hxx +++ b/src/connection.hxx @@ -63,29 +63,27 @@ class connection void do_callbacks(callback_event_type event); - void reopen(void); + void reopen(); void remove_incomplete_packets(); public: virtual ~connection(); /// is this connection closed or not - bool is_closed() + bool is_closed() const { return closed; } /// close this connection virtual void close(); /** @brief look for new data and store it in the local buffer - @param usec_timeout wait until new data is found, max timeout usecs. + @param millisec_timeout wait until new data is found, max timeout secs. -1: wait endless 0: return instantly - @param usec_timeout_remaining if non-NULL the function will write the - not used time to the given target @retval true if new data was found (does not mean that the received data is a complete packet though) */ - virtual bool fill_buffer(long long usec_timeout=-1,long long* usec_timeout_remaining=NULL)=0; + virtual bool fill_buffer(int millisec_timeout)=0; bool get_packet(std::string& data); diff --git a/src/server.cpp b/src/server.cpp index 7ee28f2..c61dbf4 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -95,7 +95,7 @@ void server_connection::add_callback(callback_event_type event, const boost::fun server::server() : callbacks(__events_end) { - set_default_timeout(30); + set_default_timeout(30000); set_logging(NULL,none); next_id=1; } @@ -168,7 +168,6 @@ unsigned int server::add_connection(server_connection* newconn) for (i=callbacks[e].begin(); i != ie; i++) newconn->add_callback(static_cast(e),bind(*i,cid)); } - LOGSTREAM(debug,"new connection accepted, id: " << cid); do_callbacks(new_connection,cid); @@ -185,9 +184,7 @@ void server::set_logging(std::ostream *_logstream, log_level_values _log_level) /** @brief Gets a connection by id - @param conn_id Connection ID - @retval Pointer to connection object */ server_connection* server::get_connection(unsigned int conn_id) diff --git a/src/server.hxx b/src/server.hxx index ad82287..cd0ae91 100644 --- a/src/server.hxx +++ b/src/server.hxx @@ -52,6 +52,7 @@ class server_connection : public connection private: int timeout; int last_action_time; + unsigned int connection_id; void set_server(server* _my_server) @@ -63,7 +64,7 @@ class server_connection : public connection protected: server *my_server; - server_connection(int _timeout); + explicit server_connection(int _timeout); virtual ~server_connection(); std::ostream* get_logstream(log_level_values level); @@ -75,7 +76,7 @@ class server_connection : public connection { timeout=_timeout; } /// get the id of this connection within the server object - unsigned int get_id() + unsigned int get_id() const { return connection_id; } void add_callback(callback_event_type event, const boost::function& func); @@ -103,7 +104,7 @@ class server server(); - virtual bool fill_connection_buffers(void)=0; + virtual bool fill_connection_buffers()=0; unsigned int add_connection(server_connection* newconn); @@ -117,7 +118,7 @@ class server { default_timeout=_default_timeout; } /// get the current default timeout for client connections - int get_default_timeout(void) + int get_default_timeout() const { return default_timeout; } void set_logging(std::ostream *_logstream, log_level_values _log_level); @@ -127,15 +128,13 @@ class server void add_callback(callback_event_type event, const boost::function& func); /** @brief look for new data and store it in the local buffer - @param usec_timeout wait until new data is found, max timeout usecs. + @param millisec_timeout wait until new data is found, max timeout millisecs. -1: wait endless 0: return instantly - @param usec_timeout_remaining if non-NULL the function will write the - not used time to the given target @retval true if new data was found (does not mean that the received data is a complete packet though) */ - virtual bool fill_buffer(long long usec_timeout=-1, long long* usec_timeout_remaining=NULL)=0; + virtual bool fill_buffer(int millisec_timeout=-1)=0; void close(); diff --git a/src/socket_client.cpp b/src/socket_client.cpp index 954bb30..5aa32a4 100644 --- a/src/socket_client.cpp +++ b/src/socket_client.cpp @@ -20,25 +20,19 @@ This exception does not invalidate any other reasons why a work based on this file might be covered by the GNU General Public License. */ -#include -#include -#include -#include -#include +#include #include #include -#include +#include #include #include #include #include -#include - -#include -#include +#include #include +#include "monotonic_clock.hxx" #include "socket_client.hxx" #include "t2n_exception.hxx" #include "log.hxx" @@ -49,13 +43,13 @@ namespace libt2n { /// returns a closed connection if connection could not be established, call get_last_error_msg() for details -socket_client_connection::socket_client_connection(int _port, const std::string& _server, - long long _connect_timeout_usec, int _max_retries, - std::ostream *_logstream, log_level_values _log_level) +socket_client_connection::socket_client_connection(int _port, const std::string& _server, + int _connect_timeout_millisec, int _max_retries, + std::ostream *_logstream, log_level_values _log_level) : client_connection(), socket_handler(0,tcp_s) { max_retries=_max_retries; - connect_timeout_usec=_connect_timeout_usec; + connect_timeout_millisec=_connect_timeout_millisec; server=_server; port=_port; @@ -79,13 +73,12 @@ socket_client_connection::socket_client_connection(int _port, const std::string& } /// returns a closed connection if connection could not be established, call get_last_error_msg() for details -socket_client_connection::socket_client_connection(const std::string& _path, - long long _connect_timeout_usec, int _max_retries, - std::ostream *_logstream, log_level_values _log_level) +socket_client_connection::socket_client_connection(const std::string& _path, int _connect_timeout_millisec, int _max_retries, + std::ostream *_logstream, log_level_values _log_level) : client_connection(), socket_handler(0,unix_s) { max_retries=_max_retries; - connect_timeout_usec=_connect_timeout_usec; + connect_timeout_millisec=_connect_timeout_millisec; path=_path; @@ -139,6 +132,8 @@ void socket_client_connection::tcp_connect(int max_retries) if (!sock) throw t2n_connect_error(string("socket() error: ")+strerror(errno)); + socket_handler::create_epoll(); + try { connect_with_timeout((struct sockaddr *) &sock_addr,sizeof(sock_addr)); @@ -178,6 +173,8 @@ void socket_client_connection::unix_connect(int max_retries) if (!sock) throw t2n_connect_error(string("socket() error: ")+strerror(errno)); + socket_handler::create_epoll(); + try { connect_with_timeout((struct sockaddr *) &unix_addr, sizeof(unix_addr)); @@ -193,6 +190,7 @@ void socket_client_connection::unix_connect(int max_retries) else throw t2n_connect_error("no more retries left after connect error"); } + } /// execute a connect on a prepared socket (tcp or unix) respecting timeouts @@ -220,30 +218,11 @@ void socket_client_connection::connect_with_timeout(struct sockaddr *sock_addr,u { LOGSTREAM(debug,"connect_with_timeout(): EINPROGRESS"); - /* set timeout */ - struct timeval tval; - struct timeval *timeout_ptr; - - if (connect_timeout_usec == -1) - timeout_ptr = NULL; - else - { - timeout_ptr = &tval; + int nfds; + while ((nfds=epoll_wait(epoll_fd,epoll_events,EPOLL_MAX_EVENTS,timeout)) && + nfds < 0 && errno==EINTR); - // convert timeout from long long usec to int sec + int usec - tval.tv_sec = connect_timeout_usec / 1000000; - tval.tv_usec = connect_timeout_usec % 1000000; - } - - fd_set connect_socket_set; - FD_ZERO(&connect_socket_set); - FD_SET(sock,&connect_socket_set); - - int ret; - while ((ret=select(FD_SETSIZE, NULL, &connect_socket_set, NULL, timeout_ptr)) && - ret < 0 && errno==EINTR); - - if (ret < 0) + if (nfds < 0) throw t2n_connect_error(string("connect() error (select): ")+strerror(errno)); socklen_t sopt=sizeof(int); @@ -268,9 +247,9 @@ void socket_client_connection::close() } } -/** @brief try to reconnect the current connection with the same connection credentials (host and port or path) - - @note will throw an exeption if reconnecting not possible +/** + * @brief try to reconnect the current connection with the same connection credentials (host and port or path) + * @note will throw an exception if reconnecting not possible */ void socket_client_connection::reconnect() { @@ -286,7 +265,7 @@ void socket_client_connection::reconnect() else if (type == unix_s) unix_connect(max_retries); - // connection is open now, otherwise an execption would have been thrown + // connection is open now, otherwise an exception would have been thrown reopen(); LOGSTREAM(debug,"reconnect() done, client_connection::is_closed() now " << client_connection::is_closed()); diff --git a/src/socket_client.hxx b/src/socket_client.hxx index 037c6ca..7f5d297 100644 --- a/src/socket_client.hxx +++ b/src/socket_client.hxx @@ -30,14 +30,13 @@ struct sockaddr; namespace libt2n { /** @brief a connection from client to server using sockets. - Use this class to connect from a client to a server. */ class socket_client_connection : public client_connection, public socket_handler { public: - static const int max_retries_default=3; - static const long long connect_timeout_usec_default=30000000; + static const int max_retries_default=5; + static const int connect_timeout_millisec_default=30000; private: void real_write(const std::string& data) @@ -48,7 +47,7 @@ class socket_client_connection : public client_connection, public socket_handler void connect_with_timeout(struct sockaddr *sock_addr,unsigned int sockaddr_size); int max_retries; - long long connect_timeout_usec; + int connect_timeout_millisec; std::string path; std::string server; @@ -62,34 +61,30 @@ class socket_client_connection : public client_connection, public socket_handler { return client_connection::get_logstream(level); } public: - socket_client_connection(int _port, const std::string& _server="127.0.0.1", - long long _connect_timeout_usec=connect_timeout_usec_default, - int _max_retries=max_retries_default, - std::ostream *_logstream=NULL, log_level_values _log_level=none); - socket_client_connection(const std::string& _path, - long long _connect_timeout_usec=connect_timeout_usec_default, + explicit socket_client_connection(int _port, const std::string& _server="127.0.0.1", + int _connect_timeout_millisec=connect_timeout_millisec_default, + int _max_retries=max_retries_default, std::ostream *_logstream=NULL, + log_level_values _log_level=none); + + explicit socket_client_connection(const std::string& _path, + int _connect_timeout_millisec=connect_timeout_millisec_default, int _max_retries=max_retries_default, std::ostream *_logstream=NULL, log_level_values _log_level=none); ~socket_client_connection(); /** @brief read data from the socket and copy it into buffer - @param usec_timeout wait until new data is found, max timeout usecs. - -1: wait endless - 0: return instantly - @param usec_timeout_remaining if non-NULL the function will write the - not used time to the given target @retval true if new data was found (does not mean that the received data is a complete packet though) */ - bool fill_buffer(long long usec_timeout=-1, long long *usec_timeout_remaining=NULL) - { return socket_handler::fill_buffer(buffer,usec_timeout,usec_timeout_remaining); } + bool fill_buffer(int millisec_timeout) + { return socket_handler::fill_buffer(buffer, millisec_timeout); } virtual void close(); void reconnect(); - std::string get_last_error_msg(void) + std::string get_last_error_msg() { return lastErrorMsg; } }; diff --git a/src/socket_handler.cpp b/src/socket_handler.cpp index f1f5ef7..355f623 100644 --- a/src/socket_handler.cpp +++ b/src/socket_handler.cpp @@ -28,6 +28,7 @@ on this file might be covered by the GNU General Public License. #include #include #include +#include #include #include #include @@ -50,11 +51,11 @@ namespace libt2n { socket_handler::socket_handler(int _sock, socket_type_value _socket_type) -: sock(_sock) -, recv_buffer_size( default_recv_buffer_size ) -, write_block_size( default_write_block_size ) -, write_timeout( default_write_timeout ) -, socket_type(_socket_type) + : sock(_sock) + , recv_buffer_size( default_recv_buffer_size ) + , write_block_size( default_write_block_size ) + , write_timeout( default_write_timeout ) + , socket_type(_socket_type) { } @@ -66,6 +67,7 @@ socket_handler::~socket_handler() if (sock != -1) { shutdown(sock,SHUT_RDWR); + remove_from_epoll(sock); ::close(sock); sock = -1; @@ -76,12 +78,18 @@ socket_handler::~socket_handler() /// by the connection class you are using. void socket_handler::close() { - LOGSTREAM(debug,"close connection"); - // graceful shutdown - shutdown(sock,SHUT_RDWR); - ::close(sock); + if (sock != -1) + { + LOGSTREAM(debug, "close connection"); + // graceful shutdown + shutdown(sock, SHUT_RDWR);\ + //taking it out of the epoll pool - sock = -1; + remove_from_epoll(sock); + ::close(sock); + + sock = -1; + } } /// set options like fast reuse and keepalive every socket should have @@ -143,12 +151,12 @@ void socket_handler::set_recv_buffer_size(unsigned int new_recv_buffer_size) /** - * @brief set new size for the data chunks when writeing. + * @brief set new size for the data chunks when writing. * @param new_write_block_size the new chunk size. * * The write block size determines the amount of data which is tried to write - * to the socket when data needs to be sended. - * Since writing data is done in a loop, this does not limit the amunt of data which can + * to the socket when data needs to be sent. + * Since writing data is done in a loop, this does not limit the amount of data which can * be written. * * The value is normalized to be at least 512 bytes and at max 32K bytes. @@ -174,39 +182,13 @@ void socket_handler::set_write_timeout(long long new_write_timeout) /** @brief check if new data is waiting on the raw socket - @param[in,out] usec_timeout wait until new data is found, max timeout usecs. + @param[in,out] timeout wait until new data is found, max timeout millisecs. -1: wait endless 0: return instantly - @param[out] usec_timeout_remaining microseconds from the timeout that were not used */ -bool socket_handler::data_waiting(long long usec_timeout,long long* usec_timeout_remaining) +bool socket_handler::data_waiting(int timeout) { - // just our socket - fd_set active_fd_set; - FD_ZERO (&active_fd_set); - FD_SET (sock, &active_fd_set); - - /* set timeout */ - struct timeval tval; - struct timeval *timeout_ptr; - - if (usec_timeout == -1) - timeout_ptr = NULL; - else - { - timeout_ptr = &tval; - - // convert timeout from long long usec to int sec + int usec - tval.tv_sec = usec_timeout / 1000000; - tval.tv_usec = usec_timeout % 1000000; - } - - int ret=select (FD_SETSIZE, &active_fd_set, NULL, NULL, timeout_ptr); - - // return the timeout we did not use - // todo: this is linux specific according to man 2 select - if (usec_timeout > 0 && usec_timeout_remaining != NULL) - *usec_timeout_remaining=(tval.tv_sec*1000000)+tval.tv_usec; + int ret = epoll_wait(epoll_fd,epoll_events,EPOLL_MAX_EVENTS,timeout); if (ret > 0) return true; @@ -216,15 +198,14 @@ bool socket_handler::data_waiting(long long usec_timeout,long long* usec_timeout /** @brief read data from the raw socket and copy it into the provided buffer @param buffer the buffer where to append the new data - @param[in,out] usec_timeout wait until new data is found, max timeout usecs. + @param[in,out] timeout wait until new data is found, max timeout millisecs. -1: wait endless 0: return instantly - @param[out] usec_timeout_remaining microseconds from the timeout that were not used */ -bool socket_handler::fill_buffer(std::string& buffer, long long usec_timeout, long long *usec_timeout_remaining) +bool socket_handler::fill_buffer(std::string& buffer,int timeout) { // fast path for timeout==0 - if (usec_timeout==0 || data_waiting(usec_timeout,usec_timeout_remaining)) + if (timeout == 0 || data_waiting(timeout)) return fill_buffer(buffer); else return false; @@ -303,7 +284,7 @@ void socket_handler::socket_write(const std::string& data) while ((rtn=::write(sock, data.data()+offset, write_size)) == -1 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)) { - wait_ready_to_write(sock,write_timeout); + wait_ready_to_write(write_timeout); LOGSTREAM(debug,"resuming write() call after EAGAIN or EINTR or EWOULDBLOCK"); } @@ -321,53 +302,78 @@ void socket_handler::socket_write(const std::string& data) } LOGSTREAM(debug,"wrote " << data.size() << " bytes"); - - return; } // eo socket_handler::socket_write(const std::string&) /// wait until the socket is ready to write again -void socket_handler::wait_ready_to_write(int socket, long long write_block_timeout) +void socket_handler::wait_ready_to_write(int write_block_timeout) { - // prepare socket sets - fd_set write_set[1]; - fd_set except_set[1]; - FD_ZERO(write_set); - FD_ZERO(except_set); - FD_SET(socket, write_set); - FD_SET(socket, except_set); - - // prepare timeout struct - struct timeval tval; - struct timeval *timeout_ptr; - - if (write_block_timeout == -1) - timeout_ptr = NULL; - else - { - timeout_ptr = &tval; - - // convert timeout from long long usec to int sec + int usec - tval.tv_sec = write_block_timeout / 1000000; - tval.tv_usec = write_block_timeout % 1000000; - } - // let's wait for the socket to become writable again... int rtn; - while ((rtn=::select(socket+1, NULL, write_set, except_set, timeout_ptr)) ==-1 && errno == EINTR); + while ((rtn=::epoll_wait(epoll_fd,epoll_events,EPOLL_MAX_EVENTS,write_block_timeout)) ==-1 && errno == EINTR); - if (rtn > 0 && (!FD_ISSET(socket,write_set)) && FD_ISSET(socket, except_set)) + if (rtn > 0) { - // if we are selected but cannot write and have an exception - // we have serious trouble... - EXCEPTIONSTREAM(error,t2n_transfer_error,"exception on socket; cannot write any more."); + for (int i=0; i < rtn; ++i) + { + // Something very wrong happened + if(epoll_events[i].events != EPOLLOUT && epoll_events[i].events == EPOLLERR) + EXCEPTIONSTREAM(error,t2n_transfer_error,"exception on socket; cannot write any more."); + } } + else if (rtn == 0) + EXCEPTIONSTREAM(error,t2n_transfer_error,"timeout on epoll_wait() for write"); + else if (rtn == -1) + EXCEPTIONSTREAM(error,t2n_transfer_error,"cannot find socket to write: " << strerror(errno)); +} + +/** + * @brief initialize the epoll pool and add the primary socket to it + * assuming the socket is already created! + */ +void socket_handler::create_epoll() +{ + struct epoll_event ev = {}; + ev.events = EPOLLIN; + epoll_fd = epoll_create1(EPOLL_CLOEXEC); - if (rtn==0) - EXCEPTIONSTREAM(error,t2n_transfer_error,"timeout on select() for write"); + if (epoll_fd == -1) + EXCEPTIONSTREAM(error,t2n_server_error, "error opening epoll: " << strerror(errno)); - if (rtn==-1) - EXCEPTIONSTREAM(error,t2n_transfer_error,"cannot select() for write: " << strerror(errno)); + //adding sock (fd) to the set of events that epoll API will monitor + if(sock != -1) + add_to_epoll(sock,&sock); + else + EXCEPTIONSTREAM(error,t2n_server_error, "socket not previously created impossible to add to epoll"); } +/** + * @brief this adds one file descriptor to the epoll pool to monitor events + * assuming the epoll was previously created + * @param fd the file descriptor we want to monitor + */ +void socket_handler::add_to_epoll(int fd,void* ptr) +{ + struct epoll_event ev; + ev.events = EPOLLIN; + ev.data.ptr = ptr; + //adding newsock (client fd) to the set of events that epoll API will monitor + if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd,&ev) == -1) + EXCEPTIONSTREAM(error,t2n_server_error,"error adding server socket to epoll(): " << strerror(errno)); + +} + +/** + * @brief this removes one file descriptor from the epoll pool + * assuming the epoll was previously created and the fd was + * previously added somewhere + * @param fd the file descriptor we want to monitor + */ +void socket_handler::remove_from_epoll(int fd) +{ + struct epoll_event ev; + //removing (client fd) from the set of events that epoll API monitors + if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd,&ev) == -1) + LOGSTREAM(debug,"error deleting server socket to epoll(): " << strerror(errno) << " ...ignoring"< +#include #include "types.hxx" +#define EPOLL_MAX_EVENTS 32 + namespace libt2n { @@ -37,18 +40,21 @@ class socket_handler private: static const unsigned int default_recv_buffer_size=2048; static const unsigned int default_write_block_size=4096; - static const long long default_write_timeout=30000000; - + static const int default_write_timeout=30000; socket_type_value socket_type; - bool data_waiting(long long usec_timeout,long long *usec_timeout_remaining=NULL); - void wait_ready_to_write(int socket, long long write_block_timeout); + bool data_waiting(int timeout); + void wait_ready_to_write(int write_block_timeout); protected: + int epoll_fd; + struct epoll_event epoll_events[EPOLL_MAX_EVENTS]; + int sock; unsigned int recv_buffer_size; unsigned int write_block_size; - long long write_timeout; + time_t write_timeout; + time_t timeout; socket_handler(int _sock, socket_type_value _socket_type); ~socket_handler(); @@ -62,15 +68,19 @@ class socket_handler virtual void close(); - bool fill_buffer(std::string& buffer, long long usec_timeout, long long* usec_timeout_remaining=NULL); + bool fill_buffer(std::string& buffer, int timeout); bool fill_buffer(std::string& buffer); + void create_epoll(); + void remove_from_epoll(int fd); + void add_to_epoll(int fd,void* ptr); + public: /// is this a tcp or unix socket connection socket_type_value get_type() { return socket_type; } - int get_socket() + int get_socket() const { return sock; } bool is_closed(); diff --git a/src/socket_server.cpp b/src/socket_server.cpp index d6ca439..b8c4099 100644 --- a/src/socket_server.cpp +++ b/src/socket_server.cpp @@ -33,12 +33,11 @@ on this file might be covered by the GNU General Public License. #include #include #include -#include #include #include - #include +#include "monotonic_clock.hxx" #include "socket_server.hxx" #include "t2n_exception.hxx" #include "log.hxx" @@ -76,6 +75,8 @@ socket_server::socket_server(int port, const std::string& ip) EXCEPTIONSTREAM(error,t2n_server_error,"error binding socket: " << strerror(errno)); } + create_epoll(); + start_listening(); } @@ -130,7 +131,10 @@ socket_server::socket_server(const std::string& path, mode_t filemode, const std EXCEPTIONSTREAM(error,t2n_server_error,"error changing socket ownership: " << strerror(errno)); } + socket_handler::create_epoll(); + start_listening(); + } /** @@ -142,7 +146,6 @@ socket_server::~socket_server() server::close(); // server socket will be closed by destructor of socket_handler - if (get_type()==unix_s) unlink(unix_path.c_str()); @@ -163,8 +166,6 @@ void socket_server::start_listening() EXCEPTIONSTREAM(error,t2n_server_error,"error listening to socket: " << strerror(errno)); /* clear & insert server sock into the fd_tab to prepare select */ - FD_ZERO(&connection_set); - FD_SET (sock, &connection_set); sockets_set.insert(sock); } @@ -190,72 +191,51 @@ void socket_server::new_connection() EXCEPTIONSTREAM(error,t2n_server_error,"fatal error accepting connection: " << strerror(errno)); } - FD_SET (newsock, &connection_set); sockets_set.insert(newsock); + socket_server_connection *nc=new socket_server_connection(newsock, get_type(), get_default_timeout()); nc->set_socket_options(newsock); add_connection(nc); - - return; + add_to_epoll(newsock,nc); } /** @brief look for new connections and new data in any of the existing connections - @param usec_timeout wait until new data is found, max timeout usecs. + @param timeout wait until new data is found, max timeout millisecs. -1: wait endless 0: return instantly - @param usec_timeout_remaining if non-NULL the function will write the - not used time to the given target - @retval true if new data was found (does not mean that the received data - is a complete packet though) */ -bool socket_server::fill_buffer(long long usec_timeout,long long* usec_timeout_remaining) +bool socket_server::fill_buffer(int timeout) { - fd_set used_fdset=connection_set; - - /* set timeout */ - struct timeval tval; - struct timeval *timeout_ptr; - - if (usec_timeout == -1) - timeout_ptr = NULL; - else - { - timeout_ptr = &tval; - - // timeout von long long usec in int sec + int usec umrechnen - tval.tv_sec = usec_timeout / 1000000; - tval.tv_usec = usec_timeout % 1000000; - } - - int ret=select (FD_SETSIZE, &used_fdset, NULL, NULL, timeout_ptr); - - // return the timeout we did not use - if (usec_timeout > 0 && usec_timeout_remaining != NULL) - *usec_timeout_remaining=(tval.tv_sec*1000000)+tval.tv_usec; + int nfds = epoll_wait(epoll_fd, epoll_events, EPOLL_MAX_EVENTS, timeout); - if (ret < 0) + if (nfds < 0) { if (errno == EINTR) { // select interrupted by signal - ret=0; + nfds=0; } else - EXCEPTIONSTREAM(error,t2n_server_error,"select error: " << strerror(errno)); + EXCEPTIONSTREAM(error,t2n_server_error,"epoll error: " << strerror(errno)); } - if (ret > 0) + if (nfds > 0) { // we have data pending - // check for new connection - if (FD_ISSET (sock, &used_fdset)) + for (int n=0; n < nfds; ++n) { - new_connection(); + if(sock != epoll_events[n].data.fd) + { + new_connection(); + continue; + } + socket_server_connection *ready_client = static_cast(epoll_events[n].data.ptr); + if(ready_client != NULL) + ready_client->fill_buffer(timeout); } - // check all connections for pending data return fill_connection_buffers(); } @@ -288,8 +268,9 @@ bool socket_server::fill_connection_buffers() /// remove the socket of a connection after the connection has been closed void socket_server::remove_connection_socket(int sock) { - FD_CLR(sock, &connection_set); - sockets_set.erase(sock); + int r = sockets_set.erase(sock); + if (r) + remove_from_epoll(sock); } /** @@ -324,9 +305,9 @@ void socket_server_connection::close() } } -bool socket_server_connection::fill_buffer(long long usec_timeout,long long* usec_timeout_remaining) +bool socket_server_connection::fill_buffer(int timeout) { - bool new_data = socket_handler::fill_buffer(buffer,usec_timeout,usec_timeout_remaining); + bool new_data = socket_handler::fill_buffer(buffer, timeout); if (new_data) reset_timeout(); return new_data; diff --git a/src/socket_server.hxx b/src/socket_server.hxx index bbba379..09546c5 100644 --- a/src/socket_server.hxx +++ b/src/socket_server.hxx @@ -22,6 +22,7 @@ on this file might be covered by the GNU General Public License. #ifndef __LIBT2N_SOCKET_SERVER #define __LIBT2N_SOCKET_SERVER +#include #include #include #include @@ -47,7 +48,6 @@ class socket_server : public socket_handler, public server friend class socket_server_connection; private: - fd_set connection_set; std::string unix_path; std::set sockets_set; @@ -55,7 +55,6 @@ class socket_server : public socket_handler, public server void new_connection(); - bool fill_connection_buffers(); void remove_connection_socket(int sock); protected: @@ -68,7 +67,13 @@ class socket_server : public socket_handler, public server ~socket_server(); - bool fill_buffer(long long usec_timeout=-1,long long* usec_timeout_remaining=NULL); + /** @brief look for new connections and new data in any of the existing connections + @param timeout wait until new data is found, max timeout millisecs. + -1: wait endless + 0: return instantly + */ + bool fill_buffer(int timeout); + bool fill_connection_buffers(); std::set get_sockets_set() { return sockets_set; }; }; @@ -83,8 +88,8 @@ class socket_server_connection : public socket_handler, public server_connection private: socket_server_connection(int _sock, socket_type_value _stype, int _timeout) - : socket_handler(_sock,_stype), server_connection(_timeout) - { } + : socket_handler(_sock,_stype), server_connection(_timeout) + { } ~socket_server_connection(); @@ -95,9 +100,10 @@ class socket_server_connection : public socket_handler, public server_connection { socket_write(data); } public: - bool fill_buffer(long long usec_timeout=-1,long long* usec_timeout_remaining=NULL); + bool fill_buffer(int timeout); virtual void close(); + }; } diff --git a/src/socket_wrapper.cpp b/src/socket_wrapper.cpp index 50ec75f..ff083dc 100644 --- a/src/socket_wrapper.cpp +++ b/src/socket_wrapper.cpp @@ -45,10 +45,10 @@ client_connection* BasicSocketWrapper::get_connection(void) { if (socket_type == tcp_s) c=std::auto_ptr - (new socket_client_connection(port,server,connect_timeout_usec,max_retries,logstream,log_level)); + (new socket_client_connection(port, server, connect_timeout_millisec, max_retries, logstream, log_level)); else if (socket_type == unix_s) c=std::auto_ptr - (new socket_client_connection(path,connect_timeout_usec,max_retries,logstream,log_level)); + (new socket_client_connection(path, connect_timeout_millisec, max_retries, logstream, log_level)); } return c.get(); @@ -95,7 +95,7 @@ bool ReconnectSocketWrapper::handle(command_client* stubBase, boost::function< v } /// return active connection, return a dummy-connection if we can't establish one -client_connection* ReconnectIgnoreFailureSocketWrapper::get_connection(void) +client_connection* ReconnectIgnoreFailureSocketWrapper::get_connection() { client_connection* tmp=BasicSocketWrapper::get_connection(); diff --git a/src/socket_wrapper.hxx b/src/socket_wrapper.hxx index cf1d385..20abefa 100644 --- a/src/socket_wrapper.hxx +++ b/src/socket_wrapper.hxx @@ -38,7 +38,7 @@ namespace libt2n /** @brief a basic implementation of ConnectionWrapper This is a basic version of a ConnectionWrapper which does not do any fancy - error handling or anything, it justs executes the regular calls. Use this + error handling or anything, it just executes the regular calls. Use this wrapper if you only want to use the singleton-feature of T2nSingletonWrapper. */ class BasicSocketWrapper : public ConnectionWrapper @@ -50,7 +50,7 @@ class BasicSocketWrapper : public ConnectionWrapper std::string server; int port; - long long connect_timeout_usec; + int connect_timeout_millisec; int max_retries; std::auto_ptr c; @@ -60,29 +60,29 @@ class BasicSocketWrapper : public ConnectionWrapper public: BasicSocketWrapper(int _port, const std::string& _server="127.0.0.1", - long long _connect_timeout_usec=socket_client_connection::connect_timeout_usec_default, + int _connect_timeout_millisec=socket_client_connection::connect_timeout_millisec_default, int _max_retries=socket_client_connection::max_retries_default) : ConnectionWrapper(), socket_type(tcp_s), server(_server), port(_port), - connect_timeout_usec(_connect_timeout_usec), + connect_timeout_millisec(_connect_timeout_millisec), max_retries(_max_retries) { } BasicSocketWrapper(const std::string& _path, - long long _connect_timeout_usec=socket_client_connection::connect_timeout_usec_default, + int _connect_timeout_millisec=socket_client_connection::connect_timeout_millisec_default, int _max_retries=socket_client_connection::max_retries_default) : ConnectionWrapper(), socket_type(unix_s), path(_path), - connect_timeout_usec(_connect_timeout_usec), + connect_timeout_millisec(_connect_timeout_millisec), max_retries(_max_retries) { } - client_connection* get_connection(void); + client_connection* get_connection(); - bool connection_established(void) + bool connection_established() { return (c.get() != NULL); } void set_logging(std::ostream *_logstream, log_level_values _log_level); @@ -96,16 +96,18 @@ class BasicSocketWrapper : public ConnectionWrapper class ReconnectSocketWrapper : public BasicSocketWrapper { public: - ReconnectSocketWrapper(int _port, const std::string& _server="127.0.0.1", - long long _connect_timeout_usec=socket_client_connection::connect_timeout_usec_default, + explicit ReconnectSocketWrapper(int _port, const std::string& _server="127.0.0.1", + int _connect_timeout_millisec=socket_client_connection::connect_timeout_millisec_default, int _max_retries=socket_client_connection::max_retries_default) - : BasicSocketWrapper(_port,_server,_connect_timeout_usec,_max_retries) + : BasicSocketWrapper(_port, _server, _connect_timeout_millisec, + _max_retries) { } - ReconnectSocketWrapper(const std::string& _path, - long long _connect_timeout_usec=socket_client_connection::connect_timeout_usec_default, + explicit ReconnectSocketWrapper(const std::string& _path, + int _connect_timeout_millisec=socket_client_connection::connect_timeout_millisec_default, int _max_retries=socket_client_connection::max_retries_default) - : BasicSocketWrapper(_path,_connect_timeout_usec,_max_retries) + : BasicSocketWrapper(_path, _connect_timeout_millisec, + _max_retries) { } bool handle(command_client* stubBase, boost::function< void() > f); @@ -123,7 +125,7 @@ class dummy_client_connection : public client_connection : client_connection() { close(); } - bool fill_buffer(long long usec_timeout=-1, long long *usec_timeout_remaining=NULL) + bool fill_buffer(int millisec_timeout=-1) { return false; } }; @@ -139,16 +141,16 @@ class ReconnectIgnoreFailureSocketWrapper : public ReconnectSocketWrapper dummy_client_connection dc; public: - ReconnectIgnoreFailureSocketWrapper(int _port, const std::string& _server="127.0.0.1", - long long _connect_timeout_usec=socket_client_connection::connect_timeout_usec_default, + __attribute__((unused)) explicit ReconnectIgnoreFailureSocketWrapper(int _port, const std::string& _server="127.0.0.1", + int _connect_timeout_millisec=socket_client_connection::connect_timeout_millisec_default, int _max_retries=socket_client_connection::max_retries_default) - : ReconnectSocketWrapper(_port,_server,_connect_timeout_usec,_max_retries) + : ReconnectSocketWrapper(_port, _server, _connect_timeout_millisec, _max_retries) { } - ReconnectIgnoreFailureSocketWrapper(const std::string& _path, - long long _connect_timeout_usec=socket_client_connection::connect_timeout_usec_default, + explicit ReconnectIgnoreFailureSocketWrapper(const std::string& _path, + int _connect_timeout_millisec=socket_client_connection::connect_timeout_millisec_default, int _max_retries=socket_client_connection::max_retries_default) - : ReconnectSocketWrapper(_path,_connect_timeout_usec,_max_retries) + : ReconnectSocketWrapper(_path, _connect_timeout_millisec, _max_retries) { } client_connection* get_connection(void); diff --git a/test/hello.cpp b/test/hello.cpp index a7a885d..48ccf5c 100644 --- a/test/hello.cpp +++ b/test/hello.cpp @@ -146,7 +146,7 @@ BOOST_AUTO_TEST_CASE(BadTag) command_client cc(&sc); - t2n_exception* ep=cc.get_constuctor_exception(); + t2n_exception* ep=cc.get_constructor_exception(); string errormsg; if (ep) @@ -205,7 +205,7 @@ BOOST_AUTO_TEST_CASE(BadVersion) command_client cc(&sc); - t2n_exception* ep=cc.get_constuctor_exception(); + t2n_exception* ep=cc.get_constructor_exception(); string errormsg; if (ep) @@ -263,7 +263,7 @@ BOOST_AUTO_TEST_CASE(SeparatorMissing) command_client cc(&sc); - t2n_exception* ep=cc.get_constuctor_exception(); + t2n_exception* ep=cc.get_constructor_exception(); string errormsg; if (ep) @@ -330,7 +330,7 @@ BOOST_AUTO_TEST_CASE(WrongByteOrder) command_client cc(&sc); - t2n_exception* ep=cc.get_constuctor_exception(); + t2n_exception* ep=cc.get_constructor_exception(); string errormsg; if (ep) @@ -386,7 +386,7 @@ BOOST_AUTO_TEST_CASE(OtherServerBig) command_client cc(&sc); - t2n_exception* ep=cc.get_constuctor_exception(); + t2n_exception* ep=cc.get_constructor_exception(); string errormsg; if (ep) @@ -442,7 +442,7 @@ BOOST_AUTO_TEST_CASE(OtherServerSmall) command_client cc(&sc); - t2n_exception* ep=cc.get_constuctor_exception(); + t2n_exception* ep=cc.get_constructor_exception(); string errormsg; if (ep) diff --git a/test/reentrant.cpp b/test/reentrant.cpp index 204e741..c03e330 100644 --- a/test/reentrant.cpp +++ b/test/reentrant.cpp @@ -221,7 +221,7 @@ BOOST_AUTO_TEST_CASE(ReentrantServer) long long maxtime=1000000; while(maxtime > 0) - cs.handle(maxtime,&maxtime); + cs.handle(maxtime); } global_server = NULL; diff --git a/test/timeout.cpp b/test/timeout.cpp index 936cc6a..1eb9e5b 100644 --- a/test/timeout.cpp +++ b/test/timeout.cpp @@ -239,7 +239,7 @@ BOOST_AUTO_TEST_CASE(HelloTimeoutNothing) socket_client_connection sc("./socket"); command_client cc(&sc,1000000,1000000); - t2n_exception* ep=cc.get_constuctor_exception(); + t2n_exception* ep=cc.get_constructor_exception(); string errormsg; if (ep) @@ -301,7 +301,7 @@ BOOST_AUTO_TEST_CASE(HelloTimeoutSlowData) socket_client_connection sc("./socket"); command_client cc(&sc,1000000,1000000); - t2n_exception* ep=cc.get_constuctor_exception(); + t2n_exception* ep=cc.get_constructor_exception(); string errormsg; if (ep) diff --git a/test/wrapper.cpp b/test/wrapper.cpp index 5fedaf5..f7dcb88 100644 --- a/test/wrapper.cpp +++ b/test/wrapper.cpp @@ -202,8 +202,8 @@ class cmd_group_x_client : public command_client { public: cmd_group_x_client(libt2n::client_connection *_c, - long long _command_timeout_usec=command_timeout_usec_default, - long long _hello_timeout_usec=hello_timeout_usec_default) + long long _command_timeout_usec=command_timeout_millisec_default, + long long _hello_timeout_usec=hello_timeout_millisec_default) : libt2n::command_client(_c,_command_timeout_usec,_hello_timeout_usec) {} @@ -358,8 +358,8 @@ BOOST_AUTO_TEST_CASE(reconnect_after_close) wraptype::set_connection(auto_ptr (new ReconnectSocketWrapper("./socket"))); - wraptype::get_connection_wrapper()->set_command_timeout_usec(3000000); - wraptype::get_connection_wrapper()->set_hello_timeout_usec(3000000); + wraptype::get_connection_wrapper()->set_command_timeout_millisec(3000000); + wraptype::get_connection_wrapper()->set_hello_timeout_millisec(3000000); // 42 closes connection on the server side t2n_exec(&cmd_group_x_client::serverfunc)(42); @@ -406,8 +406,8 @@ BOOST_AUTO_TEST_CASE(ignore_handler_reconnects) wraptype::set_connection(auto_ptr (new ReconnectIgnoreFailureSocketWrapper("./socket"))); - wraptype::get_connection_wrapper()->set_command_timeout_usec(3000000); - wraptype::get_connection_wrapper()->set_hello_timeout_usec(3000000); + wraptype::get_connection_wrapper()->set_command_timeout_millisec(3000000); + wraptype::get_connection_wrapper()->set_hello_timeout_millisec(3000000); // 42 closes connection on the server side t2n_exec(&cmd_group_x_client::serverfunc)(42); @@ -493,7 +493,7 @@ BOOST_AUTO_TEST_CASE(ignore_finds_lateserver) // parent { // wait till server is up - sleep(1); + sleep(2); } } -- 1.7.1