Commit 2cef05d8 authored by Martin Sustrik's avatar Martin Sustrik

reconnection mechanism added to tcp transport

parent 14b11230
...@@ -36,8 +36,19 @@ namespace zmq ...@@ -36,8 +36,19 @@ namespace zmq
// Flush all the previously written messages downstream. // Flush all the previously written messages downstream.
virtual void flush () = 0; virtual void flush () = 0;
// Drop all the references to the engine. // Drop all the references to the engine. The parameter is the object
virtual void detach () = 0; // to use to reconnect. If reconnection is not required, the argument
// is set to NULL.
virtual void detach (class owned_t *reconnecter_) = 0;
// Returns least loaded I/O thread.
virtual class io_thread_t *get_io_thread () = 0;
// Return pointer to the owning socket.
virtual class socket_base_t *get_owner () = 0;
// Returns the name of associated session.
virtual const char *get_session_name () = 0;
}; };
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <stddef.h> #include <stddef.h>
#include "stdint.hpp"
#include "poller.hpp" #include "poller.hpp"
#include "i_poll_events.hpp" #include "i_poll_events.hpp"
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <vector> #include <vector>
#include "stdint.hpp"
#include "object.hpp" #include "object.hpp"
#include "poller.hpp" #include "poller.hpp"
#include "i_poll_events.hpp" #include "i_poll_events.hpp"
......
...@@ -55,9 +55,10 @@ namespace zmq ...@@ -55,9 +55,10 @@ namespace zmq
void unregister_endpoints (class socket_base_t *socket_); void unregister_endpoints (class socket_base_t *socket_);
class socket_base_t *find_endpoint (const char *addr_); class socket_base_t *find_endpoint (const char *addr_);
// Derived object can use following functions to interact with // Returns number of thead slots in the dispatcher.
// global repositories. See dispatcher.hpp for function details.
int thread_slot_count (); int thread_slot_count ();
// Chooses least loaded I/O thread.
class io_thread_t *choose_io_thread (uint64_t taskset_); class io_thread_t *choose_io_thread (uint64_t taskset_);
// Derived object can use these functions to send commands // Derived object can use these functions to send commands
......
...@@ -65,9 +65,13 @@ void zmq::session_t::flush () ...@@ -65,9 +65,13 @@ void zmq::session_t::flush ()
out_pipe->flush (); out_pipe->flush ();
} }
void zmq::session_t::detach () void zmq::session_t::detach (owned_t *reconnecter_)
{ {
// TODO: Start reconnection process here. // Plug in the reconnecter object if any.
if (reconnecter_) {
send_plug (reconnecter_);
send_own (owner, reconnecter_);
}
// Engine is terminating itself. No need to deallocate it from here. // Engine is terminating itself. No need to deallocate it from here.
engine = NULL; engine = NULL;
...@@ -77,6 +81,21 @@ void zmq::session_t::detach () ...@@ -77,6 +81,21 @@ void zmq::session_t::detach ()
term (); term ();
} }
zmq::io_thread_t *zmq::session_t::get_io_thread ()
{
return choose_io_thread (options.affinity);
}
class zmq::socket_base_t *zmq::session_t::get_owner ()
{
return owner;
}
const char *zmq::session_t::get_session_name ()
{
return name.c_str ();
}
void zmq::session_t::attach_pipes (class reader_t *inpipe_, void zmq::session_t::attach_pipes (class reader_t *inpipe_,
class writer_t *outpipe_) class writer_t *outpipe_)
{ {
......
...@@ -41,7 +41,10 @@ namespace zmq ...@@ -41,7 +41,10 @@ namespace zmq
bool read (::zmq_msg_t *msg_); bool read (::zmq_msg_t *msg_);
bool write (::zmq_msg_t *msg_); bool write (::zmq_msg_t *msg_);
void flush (); void flush ();
void detach (); void detach (owned_t *reconnecter_);
class io_thread_t *get_io_thread ();
class socket_base_t *get_owner ();
const char *get_session_name ();
// i_endpoint interface implementation. // i_endpoint interface implementation.
void attach_pipes (class reader_t *inpipe_, class writer_t *outpipe_); void attach_pipes (class reader_t *inpipe_, class writer_t *outpipe_);
......
...@@ -38,9 +38,13 @@ zmq::zmq_connecter_t::~zmq_connecter_t () ...@@ -38,9 +38,13 @@ zmq::zmq_connecter_t::~zmq_connecter_t ()
{ {
} }
int zmq::zmq_connecter_t::set_address (const char *addr_) int zmq::zmq_connecter_t::set_address (const char *address_)
{ {
return tcp_connecter.set_address (addr_); int rc = tcp_connecter.set_address (address_);
if (rc != 0)
return rc;
address = address_;
return 0;
} }
void zmq::zmq_connecter_t::process_plug () void zmq::zmq_connecter_t::process_plug ()
...@@ -84,7 +88,7 @@ void zmq::zmq_connecter_t::out_event () ...@@ -84,7 +88,7 @@ void zmq::zmq_connecter_t::out_event ()
// Create an init object. // Create an init object.
io_thread_t *io_thread = choose_io_thread (options.affinity); io_thread_t *io_thread = choose_io_thread (options.affinity);
zmq_connecter_init_t *init = new zmq_connecter_init_t (io_thread, owner, zmq_connecter_init_t *init = new zmq_connecter_init_t (io_thread, owner,
fd, options, session_name.c_str ()); fd, options, session_name.c_str (), address.c_str ());
zmq_assert (init); zmq_assert (init);
send_plug (init); send_plug (init);
send_own (owner, init); send_own (owner, init);
......
...@@ -40,7 +40,7 @@ namespace zmq ...@@ -40,7 +40,7 @@ namespace zmq
~zmq_connecter_t (); ~zmq_connecter_t ();
// Set IP address to connect to. // Set IP address to connect to.
int set_address (const char *addr_); int set_address (const char *address_);
private: private:
...@@ -75,6 +75,9 @@ namespace zmq ...@@ -75,6 +75,9 @@ namespace zmq
// Name of the session associated with the connecter. // Name of the session associated with the connecter.
std::string session_name; std::string session_name;
// Address to connect to.
std::string address;
zmq_connecter_t (const zmq_connecter_t&); zmq_connecter_t (const zmq_connecter_t&);
void operator = (const zmq_connecter_t&); void operator = (const zmq_connecter_t&);
}; };
......
...@@ -25,13 +25,13 @@ ...@@ -25,13 +25,13 @@
zmq::zmq_connecter_init_t::zmq_connecter_init_t (io_thread_t *parent_, zmq::zmq_connecter_init_t::zmq_connecter_init_t (io_thread_t *parent_,
socket_base_t *owner_, fd_t fd_, const options_t &options_, socket_base_t *owner_, fd_t fd_, const options_t &options_,
const char *session_name_) : const char *session_name_, const char *address_) :
owned_t (parent_, owner_), owned_t (parent_, owner_),
options (options_), options (options_),
session_name (session_name_) session_name (session_name_)
{ {
// Create associated engine object. // Create associated engine object.
engine = new zmq_engine_t (parent_, fd_, options); engine = new zmq_engine_t (parent_, fd_, options, true, address_);
zmq_assert (engine); zmq_assert (engine);
} }
...@@ -87,27 +87,33 @@ void zmq::zmq_connecter_init_t::flush () ...@@ -87,27 +87,33 @@ void zmq::zmq_connecter_init_t::flush ()
// We are not expecting any messages. No point in flushing. // We are not expecting any messages. No point in flushing.
} }
void zmq::zmq_connecter_init_t::detach () void zmq::zmq_connecter_init_t::detach (owned_t *reconnecter_)
{ {
// TODO: Start reconnection process here. // Plug in the reconnecter object.
/* zmq_assert (reconnecter_);
// Create a connecter object to attempt reconnect. Ask it to wait for a send_plug (reconnecter_);
// while before reconnecting. send_own (owner, reconnecter_);
io_thread_t *io_thread = choose_io_thread (options.affinity);
zmq_connecter_t *connecter = new zmq_connecter_t (io_thread, owner,
options, session_name.c_str (), true);
connecter->set_address (...);
zmq_assert (connecter);
send_plug (connecter);
send_own (owner, connecter);
*/
// This function is called by engine when disconnection occurs. // This function is called by engine when disconnection occurs.
// The engine will destroy itself, so we just drop the pointer here and // The engine will destroy itself, so we just drop the pointer here and
// start termination of the init object. // start termination of the init object.
engine = NULL; engine = NULL;
term (); term ();
}
zmq::io_thread_t *zmq::zmq_connecter_init_t::get_io_thread ()
{
return choose_io_thread (options.affinity);
}
class zmq::socket_base_t *zmq::zmq_connecter_init_t::get_owner ()
{
return owner;
}
const char *zmq::zmq_connecter_init_t::get_session_name ()
{
return session_name.c_str ();
} }
void zmq::zmq_connecter_init_t::process_plug () void zmq::zmq_connecter_init_t::process_plug ()
......
...@@ -40,7 +40,8 @@ namespace zmq ...@@ -40,7 +40,8 @@ namespace zmq
public: public:
zmq_connecter_init_t (class io_thread_t *parent_, socket_base_t *owner_, zmq_connecter_init_t (class io_thread_t *parent_, socket_base_t *owner_,
fd_t fd_, const options_t &options, const char *session_name_); fd_t fd_, const options_t &options, const char *session_name_,
const char *address_);
~zmq_connecter_init_t (); ~zmq_connecter_init_t ();
private: private:
...@@ -49,7 +50,10 @@ namespace zmq ...@@ -49,7 +50,10 @@ namespace zmq
bool read (::zmq_msg_t *msg_); bool read (::zmq_msg_t *msg_);
bool write (::zmq_msg_t *msg_); bool write (::zmq_msg_t *msg_);
void flush (); void flush ();
void detach (); void detach (owned_t *reconnecter_);
class io_thread_t *get_io_thread ();
class socket_base_t *get_owner ();
const char *get_session_name ();
// Handlers for incoming commands. // Handlers for incoming commands.
void process_plug (); void process_plug ();
...@@ -63,8 +67,7 @@ namespace zmq ...@@ -63,8 +67,7 @@ namespace zmq
// Associated socket options. // Associated socket options.
options_t options; options_t options;
// Name of the session to bind new connection to. Makes sense only // Name of the session to bind new connection to.
// when 'connected' is true.
std::string session_name; std::string session_name;
zmq_connecter_init_t (const zmq_connecter_init_t&); zmq_connecter_init_t (const zmq_connecter_init_t&);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include "err.hpp" #include "err.hpp"
zmq::zmq_engine_t::zmq_engine_t (io_thread_t *parent_, fd_t fd_, zmq::zmq_engine_t::zmq_engine_t (io_thread_t *parent_, fd_t fd_,
const options_t &options_) : const options_t &options_, bool reconnect_, const char *address_) :
io_object_t (parent_), io_object_t (parent_),
inpos (NULL), inpos (NULL),
insize (0), insize (0),
...@@ -34,8 +34,12 @@ zmq::zmq_engine_t::zmq_engine_t (io_thread_t *parent_, fd_t fd_, ...@@ -34,8 +34,12 @@ zmq::zmq_engine_t::zmq_engine_t (io_thread_t *parent_, fd_t fd_,
outsize (0), outsize (0),
encoder (out_batch_size, false), encoder (out_batch_size, false),
inout (NULL), inout (NULL),
options (options_) options (options_),
reconnect (reconnect_)
{ {
if (reconnect)
address = address_;
// Initialise the underlying socket. // Initialise the underlying socket.
int rc = tcp_socket.open (fd_, options.sndbuf, options.rcvbuf); int rc = tcp_socket.open (fd_, options.sndbuf, options.rcvbuf);
zmq_assert (rc == 0); zmq_assert (rc == 0);
...@@ -145,7 +149,20 @@ void zmq::zmq_engine_t::revive () ...@@ -145,7 +149,20 @@ void zmq::zmq_engine_t::revive ()
void zmq::zmq_engine_t::error () void zmq::zmq_engine_t::error ()
{ {
zmq_assert (inout); zmq_assert (inout);
inout->detach ();
zmq_connecter_t *reconnecter = NULL;
if (reconnect) {
// Create a connecter object to attempt reconnect.
// Ask it to wait for a while before reconnecting.
reconnecter = new zmq_connecter_t (
inout->get_io_thread (), inout->get_owner (),
options, inout->get_session_name (), true);
zmq_assert (reconnecter);
reconnecter->set_address (address.c_str ());
}
inout->detach (reconnecter);
unplug (); unplug ();
delete this; delete this;
} }
...@@ -37,7 +37,7 @@ namespace zmq ...@@ -37,7 +37,7 @@ namespace zmq
public: public:
zmq_engine_t (class io_thread_t *parent_, fd_t fd_, zmq_engine_t (class io_thread_t *parent_, fd_t fd_,
const options_t &options_); const options_t &options_, bool reconnect_, const char *address_);
~zmq_engine_t (); ~zmq_engine_t ();
// i_engine interface implementation. // i_engine interface implementation.
...@@ -69,6 +69,9 @@ namespace zmq ...@@ -69,6 +69,9 @@ namespace zmq
options_t options; options_t options;
bool reconnect;
std::string address;
zmq_engine_t (const zmq_engine_t&); zmq_engine_t (const zmq_engine_t&);
void operator = (const zmq_engine_t&); void operator = (const zmq_engine_t&);
}; };
......
...@@ -29,7 +29,7 @@ zmq::zmq_listener_init_t::zmq_listener_init_t (io_thread_t *parent_, ...@@ -29,7 +29,7 @@ zmq::zmq_listener_init_t::zmq_listener_init_t (io_thread_t *parent_,
has_peer_identity (false) has_peer_identity (false)
{ {
// Create associated engine object. // Create associated engine object.
engine = new zmq_engine_t (parent_, fd_, options); engine = new zmq_engine_t (parent_, fd_, options, false, NULL);
zmq_assert (engine); zmq_assert (engine);
} }
...@@ -93,8 +93,11 @@ void zmq::zmq_listener_init_t::flush () ...@@ -93,8 +93,11 @@ void zmq::zmq_listener_init_t::flush ()
term (); term ();
} }
void zmq::zmq_listener_init_t::detach () void zmq::zmq_listener_init_t::detach (owned_t *reconnecter_)
{ {
// On the listening side of the connection we are never reconnecting.
zmq_assert (reconnecter_ == NULL);
// This function is called by engine when disconnection occurs. // This function is called by engine when disconnection occurs.
// The engine will destroy itself, so we just drop the pointer here and // The engine will destroy itself, so we just drop the pointer here and
// start termination of the init object. // start termination of the init object.
...@@ -102,6 +105,21 @@ void zmq::zmq_listener_init_t::detach () ...@@ -102,6 +105,21 @@ void zmq::zmq_listener_init_t::detach ()
term (); term ();
} }
zmq::io_thread_t *zmq::zmq_listener_init_t::get_io_thread ()
{
return choose_io_thread (options.affinity);
}
class zmq::socket_base_t *zmq::zmq_listener_init_t::get_owner ()
{
return owner;
}
const char *zmq::zmq_listener_init_t::get_session_name ()
{
zmq_assert (false);
}
void zmq::zmq_listener_init_t::process_plug () void zmq::zmq_listener_init_t::process_plug ()
{ {
zmq_assert (engine); zmq_assert (engine);
......
...@@ -49,7 +49,10 @@ namespace zmq ...@@ -49,7 +49,10 @@ namespace zmq
bool read (::zmq_msg_t *msg_); bool read (::zmq_msg_t *msg_);
bool write (::zmq_msg_t *msg_); bool write (::zmq_msg_t *msg_);
void flush (); void flush ();
void detach (); void detach (owned_t *reconnecter_);
class io_thread_t *get_io_thread ();
class socket_base_t *get_owner ();
const char *get_session_name ();
// Handlers for incoming commands. // Handlers for incoming commands.
void process_plug (); void process_plug ();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment