Add methods to set timeout on blocking Send/Receive

This commit is contained in:
Alexey Rybalchenko 2015-10-15 16:43:30 +02:00
parent 91d3f013c0
commit 8f59db1283
11 changed files with 655 additions and 146 deletions

View File

@ -38,6 +38,8 @@ FairMQChannel::FairMQChannel()
, fTransportFactory(nullptr) , fTransportFactory(nullptr)
, fNoBlockFlag(0) , fNoBlockFlag(0)
, fSndMoreFlag(0) , fSndMoreFlag(0)
, fSndTimeoutInMs(-1)
, fRcvTimeoutInMs(-1)
{ {
} }
@ -56,6 +58,8 @@ FairMQChannel::FairMQChannel(const string& type, const string& method, const str
, fTransportFactory(nullptr) , fTransportFactory(nullptr)
, fNoBlockFlag(0) , fNoBlockFlag(0)
, fSndMoreFlag(0) , fSndMoreFlag(0)
, fSndTimeoutInMs(-1)
, fRcvTimeoutInMs(-1)
{ {
} }
@ -376,12 +380,12 @@ void FairMQChannel::ResetChannel()
int FairMQChannel::Send(const unique_ptr<FairMQMessage>& msg) const int FairMQChannel::Send(const unique_ptr<FairMQMessage>& msg) const
{ {
fPoller->Poll(-1); fPoller->Poll(fSndTimeoutInMs);
if (fPoller->CheckInput(0)) if (fPoller->CheckInput(0))
{ {
HandleUnblock(); HandleUnblock();
return -1; return -2;
} }
if (fPoller->CheckOutput(1)) if (fPoller->CheckOutput(1))
@ -389,7 +393,7 @@ int FairMQChannel::Send(const unique_ptr<FairMQMessage>& msg) const
return fSocket->Send(msg.get(), 0); return fSocket->Send(msg.get(), 0);
} }
return -1; return -2;
} }
int FairMQChannel::SendAsync(const unique_ptr<FairMQMessage>& msg) const int FairMQChannel::SendAsync(const unique_ptr<FairMQMessage>& msg) const
@ -404,12 +408,12 @@ int FairMQChannel::SendPart(const unique_ptr<FairMQMessage>& msg) const
int FairMQChannel::Receive(const unique_ptr<FairMQMessage>& msg) const int FairMQChannel::Receive(const unique_ptr<FairMQMessage>& msg) const
{ {
fPoller->Poll(-1); fPoller->Poll(fRcvTimeoutInMs);
if (fPoller->CheckInput(0)) if (fPoller->CheckInput(0))
{ {
HandleUnblock(); HandleUnblock();
return -1; return -2;
} }
if (fPoller->CheckInput(1)) if (fPoller->CheckInput(1))
@ -417,7 +421,7 @@ int FairMQChannel::Receive(const unique_ptr<FairMQMessage>& msg) const
return fSocket->Receive(msg.get(), 0); return fSocket->Receive(msg.get(), 0);
} }
return -1; return -2;
} }
int FairMQChannel::ReceiveAsync(const unique_ptr<FairMQMessage>& msg) const int FairMQChannel::ReceiveAsync(const unique_ptr<FairMQMessage>& msg) const
@ -429,101 +433,161 @@ int FairMQChannel::Send(FairMQMessage* msg, const string& flag) const
{ {
if (flag == "") if (flag == "")
{ {
fPoller->Poll(-1); fPoller->Poll(fSndTimeoutInMs);
if (fPoller->CheckInput(0)) if (fPoller->CheckInput(0))
{ {
HandleUnblock(); HandleUnblock();
return -1; return -2;
} }
if (fPoller->CheckOutput(1)) if (fPoller->CheckOutput(1))
{ {
return fSocket->Send(msg, flag); return fSocket->Send(msg, flag);
} }
return -2;
} }
else else
{ {
return fSocket->Send(msg, flag); return fSocket->Send(msg, flag);
} }
return -1;
} }
int FairMQChannel::Send(FairMQMessage* msg, const int flags) const int FairMQChannel::Send(FairMQMessage* msg, const int flags) const
{ {
if (flags == 0) if (flags == 0)
{ {
fPoller->Poll(-1); fPoller->Poll(fSndTimeoutInMs);
if (fPoller->CheckInput(0)) if (fPoller->CheckInput(0))
{ {
HandleUnblock(); HandleUnblock();
return -1; return -2;
} }
if (fPoller->CheckOutput(1)) if (fPoller->CheckOutput(1))
{ {
return fSocket->Send(msg, flags); return fSocket->Send(msg, flags);
} }
return -2;
} }
else else
{ {
return fSocket->Send(msg, flags); return fSocket->Send(msg, flags);
} }
return -1;
} }
int FairMQChannel::Receive(FairMQMessage* msg, const string& flag) const int FairMQChannel::Receive(FairMQMessage* msg, const string& flag) const
{ {
if (flag == "") if (flag == "")
{ {
fPoller->Poll(-1); fPoller->Poll(fRcvTimeoutInMs);
if (fPoller->CheckInput(0)) if (fPoller->CheckInput(0))
{ {
HandleUnblock(); HandleUnblock();
return -1; return -2;
} }
if (fPoller->CheckInput(1)) if (fPoller->CheckInput(1))
{ {
return fSocket->Receive(msg, flag); return fSocket->Receive(msg, flag);
} }
return -2;
} }
else else
{ {
return fSocket->Receive(msg, flag); return fSocket->Receive(msg, flag);
} }
return -1;
} }
int FairMQChannel::Receive(FairMQMessage* msg, const int flags) const int FairMQChannel::Receive(FairMQMessage* msg, const int flags) const
{ {
if (flags == 0) if (flags == 0)
{ {
fPoller->Poll(-1); fPoller->Poll(fRcvTimeoutInMs);
if (fPoller->CheckInput(0)) if (fPoller->CheckInput(0))
{ {
HandleUnblock(); HandleUnblock();
return -1; return -2;
} }
if (fPoller->CheckInput(1)) if (fPoller->CheckInput(1))
{ {
return fSocket->Receive(msg, flags); return fSocket->Receive(msg, flags);
} }
return -2;
} }
else else
{ {
return fSocket->Receive(msg, flags); return fSocket->Receive(msg, flags);
} }
}
bool FairMQChannel::SetSendTimeout(const int timeout)
{
if (fSocket)
{
if (fSocket->SetSendTimeout(timeout, fAddress, fMethod))
{
fSndTimeoutInMs = timeout;
return true;
}
}
else
{
LOG(ERROR) << "SetSendTimeout() failed - socket is not initialized!";
return false;
}
}
int FairMQChannel::GetSendTimeout() const
{
if (fSocket)
{
return fSocket->GetSendTimeout();
}
else
{
LOG(ERROR) << "GetSendTimeout() failed - socket is not initialized!";
return -1; return -1;
} }
}
bool FairMQChannel::SetReceiveTimeout(const int timeout)
{
if (fSocket)
{
if (fSocket->SetReceiveTimeout(timeout, fAddress, fMethod))
{
fRcvTimeoutInMs = timeout;
return true;
}
}
else
{
LOG(ERROR) << "SetReceiveTimeout() failed - socket is not initialized!";
return false;
}
}
int FairMQChannel::GetReceiveTimeout() const
{
if (fSocket)
{
return fSocket->GetReceiveTimeout();
}
else
{
LOG(ERROR) << "GetReceiveTimeout() failed - socket is not initialized!";
return -1;
}
}
bool FairMQChannel::ExpectsAnotherPart() const bool FairMQChannel::ExpectsAnotherPart() const
{ {

View File

@ -101,7 +101,7 @@ class FairMQChannel
/// for some other reason (e.g. no peers connected for a binding socket), the method blocks. /// for some other reason (e.g. no peers connected for a binding socket), the method blocks.
/// ///
/// @param msg Constant reference of unique_ptr to a FairMQMessage /// @param msg Constant reference of unique_ptr to a FairMQMessage
/// @return Returns the number of bytes that have been queued. In case of errors, returns -1. /// @return Number of bytes that have been queued. -2 If queueing was not possible or timed out. In case of errors, returns -1.
int Send(const std::unique_ptr<FairMQMessage>& msg) const; int Send(const std::unique_ptr<FairMQMessage>& msg) const;
/// Sends a message in non-blocking mode. /// Sends a message in non-blocking mode.
@ -111,7 +111,7 @@ class FairMQChannel
/// ///
/// @param msg Constant reference of unique_ptr to a FairMQMessage /// @param msg Constant reference of unique_ptr to a FairMQMessage
/// @return Returns the number of bytes that have been queued. If queueing failed due to /// @return Returns the number of bytes that have been queued. If queueing failed due to
/// full queue or no connected peers (when binding), returns 0. In case of errors, returns -1. /// full queue or no connected peers (when binding), returns -2. In case of errors, returns -1.
int SendAsync(const std::unique_ptr<FairMQMessage>& msg) const; int SendAsync(const std::unique_ptr<FairMQMessage>& msg) const;
/// Queues the current message as a part of a multi-part message /// Queues the current message as a part of a multi-part message
@ -119,7 +119,7 @@ class FairMQChannel
/// The actual transfer over the network is initiated once final part has been queued with the Send() or SendAsync methods. /// The actual transfer over the network is initiated once final part has been queued with the Send() or SendAsync methods.
/// ///
/// @param msg Constant reference of unique_ptr to a FairMQMessage /// @param msg Constant reference of unique_ptr to a FairMQMessage
/// @return Returns the number of bytes that have been queued. In case of errors, returns -1. /// @return Returns the number of bytes that have been queued. -2 If queueing was not possible. In case of errors, returns -1.
int SendPart(const std::unique_ptr<FairMQMessage>& msg) const; int SendPart(const std::unique_ptr<FairMQMessage>& msg) const;
/// Receives a message from the socket queue. /// Receives a message from the socket queue.
@ -127,7 +127,7 @@ class FairMQChannel
/// If the queue is empty the method blocks. /// If the queue is empty the method blocks.
/// ///
/// @param msg Constant reference of unique_ptr to a FairMQMessage /// @param msg Constant reference of unique_ptr to a FairMQMessage
/// @return Returns the number of bytes that have been received. In case of errors, returns -1. /// @return Returns the number of bytes that have been received. -2 If reading from the queue was not possible or timed out. In case of errors, returns -1.
int Receive(const std::unique_ptr<FairMQMessage>& msg) const; int Receive(const std::unique_ptr<FairMQMessage>& msg) const;
/// Receives a message in non-blocking mode. /// Receives a message in non-blocking mode.
@ -135,7 +135,7 @@ class FairMQChannel
/// If the queue is empty the method returns 0. /// If the queue is empty the method returns 0.
/// ///
/// @param msg Constant reference of unique_ptr to a FairMQMessage /// @param msg Constant reference of unique_ptr to a FairMQMessage
/// @return Returns the number of bytes that have been received. If queue is empty, returns 0. /// @return Returns the number of bytes that have been received. If queue is empty, returns -2.
/// In case of errors, returns -1. /// In case of errors, returns -1.
int ReceiveAsync(const std::unique_ptr<FairMQMessage>& msg) const; int ReceiveAsync(const std::unique_ptr<FairMQMessage>& msg) const;
@ -145,6 +145,24 @@ class FairMQChannel
int Receive(FairMQMessage* msg, const std::string& flag = "") const; int Receive(FairMQMessage* msg, const std::string& flag = "") const;
int Receive(FairMQMessage* msg, const int flags) const; int Receive(FairMQMessage* msg, const int flags) const;
/// Sets a timeout on the (blocking) Send method
/// @param timeout timeout value in milliseconds
/// @return true if operation was successfull, otherwise false.
bool SetSendTimeout(const int timeout);
/// Gets the current value of the timeout on the (blocking) Send method
/// @return Timeout value in milliseconds. -1 for no timeout.
int GetSendTimeout() const;
/// Sets a timeout on the (blocking) Receive method
/// @param timeout timeout value in milliseconds
/// @return true if operation was successfull, otherwise false.
bool SetReceiveTimeout(const int timeout);
/// Gets the current value of the timeout on the (blocking) Receive method
/// @return Timeout value in milliseconds. -1 for no timeout.
int GetReceiveTimeout() const;
/// Checks if the socket is expecting to receive another part of a multipart message. /// Checks if the socket is expecting to receive another part of a multipart message.
/// @return Return true if the socket expects another part of a multipart message and false otherwise. /// @return Return true if the socket expects another part of a multipart message and false otherwise.
bool ExpectsAnotherPart() const; bool ExpectsAnotherPart() const;
@ -168,6 +186,9 @@ class FairMQChannel
int fNoBlockFlag; int fNoBlockFlag;
int fSndMoreFlag; int fSndMoreFlag;
int fSndTimeoutInMs;
int fRcvTimeoutInMs;
bool InitCommandInterface(FairMQTransportFactory* factory, int numIoThreads); bool InitCommandInterface(FairMQTransportFactory* factory, int numIoThreads);
bool HandleUnblock() const; bool HandleUnblock() const;

View File

@ -77,7 +77,7 @@ void FairMQDevice::SignalHandler(int signal)
Shutdown(); Shutdown();
fTerminateStateThread.join(); fTerminateStateThread.join();
MQLOG(INFO) << "Exiting."; LOG(INFO) << "Exiting.";
stop(); stop();
// std::abort(); // std::abort();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -558,8 +558,8 @@ void FairMQDevice::LogSocketRates()
void FairMQDevice::InteractiveStateLoop() void FairMQDevice::InteractiveStateLoop()
{ {
char c; // hold the user console input
bool running = true; bool running = true;
char c; // hold the user console input
struct termios t; struct termios t;
tcgetattr(STDIN_FILENO, &t); // get the current terminal I/O structure tcgetattr(STDIN_FILENO, &t); // get the current terminal I/O structure

View File

@ -34,32 +34,61 @@ class FairMQDevice : public FairMQStateMachine, public FairMQConfigurable
public: public:
enum enum
{ {
Id = FairMQConfigurable::Last, Id = FairMQConfigurable::Last, ///< Device ID
NumIoThreads, MaxInitializationTime, ///< Timeout for the initialization
MaxInitializationTime, NumIoThreads, ///< Number of ZeroMQ I/O threads
PortRangeMin, PortRangeMin, ///< Minimum value for the port range (if dynamic)
PortRangeMax, PortRangeMax, ///< Maximum value for the port range (if dynamic)
LogIntervalInMs, LogIntervalInMs, ///< Interval for logging the socket transfer rates
Last Last
}; };
/// Default constructor
FairMQDevice(); FairMQDevice();
/// Default destructor
virtual ~FairMQDevice();
/// Catches interrupt signals (SIGINT, SIGTERM)
void CatchSignals(); void CatchSignals();
/// Outputs the socket transfer rates
virtual void LogSocketRates(); virtual void LogSocketRates();
/// Sorts a channel by address, with optional reindexing of the sorted values
/// @param name Channel name
/// @param reindex Should reindexing be done
void SortChannel(const std::string& name, const bool reindex = true); void SortChannel(const std::string& name, const bool reindex = true);
/// Prints channel configuration
/// @param name Name of the channel
void PrintChannel(const std::string& name); void PrintChannel(const std::string& name);
/// Waits for the first initialization run to finish
void WaitForInitialValidation(); void WaitForInitialValidation();
/// Starts interactive (console) loop for controlling the device
/// Works only when running in a terminal. Running in background would exit, because no interactive input (std::cin) is possible.
void InteractiveStateLoop(); void InteractiveStateLoop();
/// Prints the available commands of the InteractiveStateLoop()
void PrintInteractiveStateLoopHelp(); void PrintInteractiveStateLoopHelp();
/// Set Device properties stored as strings
/// @param key Property key
/// @param value Property value
virtual void SetProperty(const int key, const std::string& value); virtual void SetProperty(const int key, const std::string& value);
/// Get Device properties stored as strings
/// @param key Property key
/// @param default_ not used
/// @return Property value
virtual std::string GetProperty(const int key, const std::string& default_ = ""); virtual std::string GetProperty(const int key, const std::string& default_ = "");
/// Set Device properties stored as integers
/// @param key Property key
/// @param value Property value
virtual void SetProperty(const int key, const int value); virtual void SetProperty(const int key, const int value);
/// Get Device properties stored as integers
/// @param key Property key
/// @param default_ not used
/// @return Property value
virtual int GetProperty(const int key, const int default_ = 0); virtual int GetProperty(const int key, const int default_ = 0);
/// Get property description for a given property name /// Get property description for a given property name
@ -69,60 +98,79 @@ class FairMQDevice : public FairMQStateMachine, public FairMQConfigurable
/// Print all properties of this and the parent class to LOG(INFO) /// Print all properties of this and the parent class to LOG(INFO)
virtual void ListProperties(); virtual void ListProperties();
/// Configures the device with a transport factory
/// @param factory Pointer to the transport factory object
virtual void SetTransport(FairMQTransportFactory* factory); virtual void SetTransport(FairMQTransportFactory* factory);
/// Implements the sort algorithm used in SortChannel()
/// @param lhs Right hand side value for comparison
/// @param rhs Left hand side value for comparison
static bool SortSocketsByAddress(const FairMQChannel &lhs, const FairMQChannel &rhs); static bool SortSocketsByAddress(const FairMQChannel &lhs, const FairMQChannel &rhs);
virtual ~FairMQDevice(); std::unordered_map<std::string, std::vector<FairMQChannel>> fChannels; ///< Device channels
std::unordered_map<std::string, std::vector<FairMQChannel>> fChannels;
protected: protected:
std::string fId; std::string fId; ///< Device ID
int fMaxInitializationTime; int fMaxInitializationTime; ///< Timeout for the initialization
int fNumIoThreads; int fNumIoThreads; ///< Number of ZeroMQ I/O threads
int fPortRangeMin; int fPortRangeMin; ///< Minimum value for the port range (if dynamic)
int fPortRangeMax; int fPortRangeMax; ///< Maximum value for the port range (if dynamic)
int fLogIntervalInMs; int fLogIntervalInMs; ///< Interval for logging the socket transfer rates
FairMQSocket* fCmdSocket; FairMQSocket* fCmdSocket; ///< Socket used for the internal unblocking mechanism
FairMQTransportFactory* fTransportFactory; FairMQTransportFactory* fTransportFactory; ///< Transport factory
void InitWrapper(); /// Additional user initialization (can be overloaded in child classes). Prefer to use InitTask().
virtual void Init(); virtual void Init();
void InitTaskWrapper(); /// Task initialization (can be overloaded in child classes)
virtual void InitTask(); virtual void InitTask();
void RunWrapper(); /// Runs the device (to be overloaded in child classes)
virtual void Run(); virtual void Run();
/// Handles the PAUSE state
virtual void Pause(); virtual void Pause();
void ResetTaskWrapper(); /// Resets the user task (to be overloaded in child classes)
virtual void ResetTask(); virtual void ResetTask();
void ResetWrapper(); /// Resets the device (can be overloaded in child classes)
virtual void Reset(); virtual void Reset();
void Shutdown();
void Terminate();
void Unblock();
bool InitChannel(FairMQChannel&);
private: private:
// condition variable to notify parent thread about end of initial validation. // condition variable to notify parent thread about end of initial validation.
bool fInitialValidationFinished; bool fInitialValidationFinished;
boost::condition_variable fInitialValidationCondition; boost::condition_variable fInitialValidationCondition;
boost::mutex fInitialValidationMutex; boost::mutex fInitialValidationMutex;
/// Handles the initialization and the Init() method
void InitWrapper();
/// Handles the InitTask() method
void InitTaskWrapper();
/// Handles the Run() method
void RunWrapper();
/// Handles the ResetTask() method
void ResetTaskWrapper();
/// Handles the Reset() method
void ResetWrapper();
/// Shuts down the device (closses socket connections)
void Shutdown();
/// Terminates the transport interface
void Terminate();
/// Unblocks blocking channel send/receive calls
void Unblock();
/// Initializes a single channel (used in InitWrapper)
bool InitChannel(FairMQChannel&);
/// Signal handler
void SignalHandler(int signal); void SignalHandler(int signal);
bool fCatchingSignals; bool fCatchingSignals;

View File

@ -42,18 +42,23 @@ class FairMQSocket
virtual int Receive(FairMQMessage* msg, const std::string& flag = "") = 0; virtual int Receive(FairMQMessage* msg, const std::string& flag = "") = 0;
virtual int Receive(FairMQMessage* msg, const int flags = 0) = 0; virtual int Receive(FairMQMessage* msg, const int flags = 0) = 0;
virtual void* GetSocket() = 0; virtual void* GetSocket() const = 0;
virtual int GetSocket(int nothing) = 0; virtual int GetSocket(int nothing) const = 0;
virtual void Close() = 0; virtual void Close() = 0;
virtual void Terminate() = 0; virtual void Terminate() = 0;
virtual void SetOption(const std::string& option, const void* value, size_t valueSize) = 0; virtual void SetOption(const std::string& option, const void* value, size_t valueSize) = 0;
virtual void GetOption(const std::string& option, void* value, size_t* valueSize) = 0; virtual void GetOption(const std::string& option, void* value, size_t* valueSize) = 0;
virtual unsigned long GetBytesTx() = 0; virtual unsigned long GetBytesTx() const = 0;
virtual unsigned long GetBytesRx() = 0; virtual unsigned long GetBytesRx() const = 0;
virtual unsigned long GetMessagesTx() = 0; virtual unsigned long GetMessagesTx() const = 0;
virtual unsigned long GetMessagesRx() = 0; virtual unsigned long GetMessagesRx() const = 0;
virtual bool SetSendTimeout(const int timeout, const std::string& address, const std::string& method) = 0;
virtual int GetSendTimeout() const = 0;
virtual bool SetReceiveTimeout(const int timeout, const std::string& address, const std::string& method) = 0;
virtual int GetReceiveTimeout() const = 0;
virtual ~FairMQSocket() {}; virtual ~FairMQSocket() {};
}; };

View File

@ -97,76 +97,96 @@ void FairMQSocketNN::Connect(const string& address)
int FairMQSocketNN::Send(FairMQMessage* msg, const string& flag) int FairMQSocketNN::Send(FairMQMessage* msg, const string& flag)
{ {
void* ptr = msg->GetMessage(); void* ptr = msg->GetMessage();
int rc = nn_send(fSocket, &ptr, NN_MSG, 0); int nbytes = nn_send(fSocket, &ptr, NN_MSG, GetConstant(flag));
if (rc < 0) if (nbytes >= 0)
{ {
LOG(ERROR) << "failed sending on socket " << fId << ", reason: " << nn_strerror(errno); fBytesTx += nbytes;
}
else
{
fBytesTx += rc;
++fMessagesTx; ++fMessagesTx;
static_cast<FairMQMessageNN*>(msg)->fReceiving = false; static_cast<FairMQMessageNN*>(msg)->fReceiving = false;
} }
if (nn_errno() == EAGAIN)
return rc; {
return -2;
}
if (nn_errno() == ETERM)
{
LOG(INFO) << "terminating socket " << fId;
return -1;
}
LOG(ERROR) << "Failed sending on socket " << fId << ", reason: " << nn_strerror(errno);
return nbytes;
} }
int FairMQSocketNN::Send(FairMQMessage* msg, const int flags) int FairMQSocketNN::Send(FairMQMessage* msg, const int flags)
{ {
void* ptr = msg->GetMessage(); void* ptr = msg->GetMessage();
int rc = nn_send(fSocket, &ptr, NN_MSG, flags); int nbytes = nn_send(fSocket, &ptr, NN_MSG, flags);
if (rc < 0) if (nbytes >= 0)
{ {
LOG(ERROR) << "failed sending on socket " << fId << ", reason: " << nn_strerror(errno); fBytesTx += nbytes;
}
else
{
fBytesTx += rc;
++fMessagesTx; ++fMessagesTx;
static_cast<FairMQMessageNN*>(msg)->fReceiving = false; static_cast<FairMQMessageNN*>(msg)->fReceiving = false;
} }
if (nn_errno() == EAGAIN)
return rc; {
return -2;
}
if (nn_errno() == ETERM)
{
LOG(INFO) << "terminating socket " << fId;
return -1;
}
LOG(ERROR) << "Failed sending on socket " << fId << ", reason: " << nn_strerror(errno);
return nbytes;
} }
int FairMQSocketNN::Receive(FairMQMessage* msg, const string& flag) int FairMQSocketNN::Receive(FairMQMessage* msg, const string& flag)
{ {
void* ptr = NULL; void* ptr = NULL;
int rc = nn_recv(fSocket, &ptr, NN_MSG, 0); int nbytes = nn_recv(fSocket, &ptr, NN_MSG, GetConstant(flag));
if (rc < 0) if (nbytes >= 0)
{ {
LOG(ERROR) << "failed receiving on socket " << fId << ", reason: " << nn_strerror(errno); fBytesRx += nbytes;
}
else
{
fBytesRx += rc;
++fMessagesRx; ++fMessagesRx;
msg->Rebuild(); msg->Rebuild();
msg->SetMessage(ptr, rc); msg->SetMessage(ptr, nbytes);
static_cast<FairMQMessageNN*>(msg)->fReceiving = true; static_cast<FairMQMessageNN*>(msg)->fReceiving = true;
} }
if (nn_errno() == EAGAIN)
return rc; {
return -2;
}
if (nn_errno() == ETERM)
{
LOG(INFO) << "terminating socket " << fId;
return -1;
}
LOG(ERROR) << "Failed receiving on socket " << fId << ", reason: " << nn_strerror(errno);
return nbytes;
} }
int FairMQSocketNN::Receive(FairMQMessage* msg, const int flags) int FairMQSocketNN::Receive(FairMQMessage* msg, const int flags)
{ {
void* ptr = NULL; void* ptr = NULL;
int rc = nn_recv(fSocket, &ptr, NN_MSG, flags); int nbytes = nn_recv(fSocket, &ptr, NN_MSG, flags);
if (rc < 0) if (nbytes >= 0)
{ {
LOG(ERROR) << "failed receiving on socket " << fId << ", reason: " << nn_strerror(errno); fBytesRx += nbytes;
}
else
{
fBytesRx += rc;
++fMessagesRx; ++fMessagesRx;
msg->SetMessage(ptr, rc); msg->SetMessage(ptr, nbytes);
static_cast<FairMQMessageNN*>(msg)->fReceiving = true; static_cast<FairMQMessageNN*>(msg)->fReceiving = true;
} }
if (nn_errno() == EAGAIN)
return rc; {
return -2;
}
if (nn_errno() == ETERM)
{
LOG(INFO) << "terminating socket " << fId;
return -1;
}
LOG(ERROR) << "Failed receiving on socket " << fId << ", reason: " << nn_strerror(errno);
return nbytes;
} }
void FairMQSocketNN::Close() void FairMQSocketNN::Close()
@ -179,12 +199,12 @@ void FairMQSocketNN::Terminate()
nn_term(); nn_term();
} }
void* FairMQSocketNN::GetSocket() void* FairMQSocketNN::GetSocket() const
{ {
return NULL; // dummy method to comply with the interface. functionality not possible in zeromq. return NULL; // dummy method to comply with the interface. functionality not possible in zeromq.
} }
int FairMQSocketNN::GetSocket(int nothing) int FairMQSocketNN::GetSocket(int nothing) const
{ {
return fSocket; return fSocket;
} }
@ -206,26 +226,74 @@ void FairMQSocketNN::GetOption(const string& option, void* value, size_t* valueS
} }
} }
unsigned long FairMQSocketNN::GetBytesTx() unsigned long FairMQSocketNN::GetBytesTx() const
{ {
return fBytesTx; return fBytesTx;
} }
unsigned long FairMQSocketNN::GetBytesRx() unsigned long FairMQSocketNN::GetBytesRx() const
{ {
return fBytesRx; return fBytesRx;
} }
unsigned long FairMQSocketNN::GetMessagesTx() unsigned long FairMQSocketNN::GetMessagesTx() const
{ {
return fMessagesTx; return fMessagesTx;
} }
unsigned long FairMQSocketNN::GetMessagesRx() unsigned long FairMQSocketNN::GetMessagesRx() const
{ {
return fMessagesRx; return fMessagesRx;
} }
bool FairMQSocketNN::SetSendTimeout(const int timeout, const string& address, const string& method)
{
if (nn_setsockopt(fSocket, NN_SOL_SOCKET, NN_SNDTIMEO, &timeout, sizeof(int)) != 0)
{
LOG(ERROR) << "Failed setting option 'send timeout' on socket " << fId << ", reason: " << nn_strerror(errno);
return false;
}
return true;
}
int FairMQSocketNN::GetSendTimeout() const
{
int timeout = -1;
size_t size = sizeof(timeout);
if (nn_getsockopt(fSocket, NN_SOL_SOCKET, NN_SNDTIMEO, &timeout, &size) != 0)
{
LOG(ERROR) << "Failed getting option 'send timeout' on socket " << fId << ", reason: " << nn_strerror(errno);
}
return timeout;
}
bool FairMQSocketNN::SetReceiveTimeout(const int timeout, const string& address, const string& method)
{
if (nn_setsockopt(fSocket, NN_SOL_SOCKET, NN_RCVTIMEO, &timeout, sizeof(int)) != 0)
{
LOG(ERROR) << "Failed setting option 'receive timeout' on socket " << fId << ", reason: " << nn_strerror(errno);
return false;
}
return true;
}
int FairMQSocketNN::GetReceiveTimeout() const
{
int timeout = -1;
size_t size = sizeof(timeout);
if (nn_getsockopt(fSocket, NN_SOL_SOCKET, NN_RCVTIMEO, &timeout, &size) != 0)
{
LOG(ERROR) << "Failed getting option 'receive timeout' on socket " << fId << ", reason: " << nn_strerror(errno);
}
return timeout;
}
int FairMQSocketNN::GetConstant(const string& constant) int FairMQSocketNN::GetConstant(const string& constant)
{ {
if (constant == "") if (constant == "")

View File

@ -38,18 +38,23 @@ class FairMQSocketNN : public FairMQSocket
virtual int Receive(FairMQMessage* msg, const std::string& flag = ""); virtual int Receive(FairMQMessage* msg, const std::string& flag = "");
virtual int Receive(FairMQMessage* msg, const int flags = 0); virtual int Receive(FairMQMessage* msg, const int flags = 0);
virtual void* GetSocket(); virtual void* GetSocket() const;
virtual int GetSocket(int nothing); virtual int GetSocket(int nothing) const;
virtual void Close(); virtual void Close();
virtual void Terminate(); virtual void Terminate();
virtual void SetOption(const std::string& option, const void* value, size_t valueSize); virtual void SetOption(const std::string& option, const void* value, size_t valueSize);
virtual void GetOption(const std::string& option, void* value, size_t* valueSize); virtual void GetOption(const std::string& option, void* value, size_t* valueSize);
unsigned long GetBytesTx(); unsigned long GetBytesTx() const;
unsigned long GetBytesRx(); unsigned long GetBytesRx() const;
unsigned long GetMessagesTx(); unsigned long GetMessagesTx() const;
unsigned long GetMessagesRx(); unsigned long GetMessagesRx() const;
virtual bool SetSendTimeout(const int timeout, const std::string& address, const std::string& method);
virtual int GetSendTimeout() const;
virtual bool SetReceiveTimeout(const int timeout, const std::string& address, const std::string& method);
virtual int GetReceiveTimeout() const;
static int GetConstant(const std::string& constant); static int GetConstant(const std::string& constant);

View File

@ -15,6 +15,7 @@ Set(INCLUDE_DIRECTORIES
${CMAKE_SOURCE_DIR}/fairmq/devices ${CMAKE_SOURCE_DIR}/fairmq/devices
${CMAKE_SOURCE_DIR}/fairmq/tools ${CMAKE_SOURCE_DIR}/fairmq/tools
${CMAKE_SOURCE_DIR}/fairmq/options ${CMAKE_SOURCE_DIR}/fairmq/options
${CMAKE_SOURCE_DIR}/fairmq/test/
${CMAKE_SOURCE_DIR}/fairmq/test/push-pull ${CMAKE_SOURCE_DIR}/fairmq/test/push-pull
${CMAKE_SOURCE_DIR}/fairmq/test/pub-sub ${CMAKE_SOURCE_DIR}/fairmq/test/pub-sub
${CMAKE_SOURCE_DIR}/fairmq/test/req-rep ${CMAKE_SOURCE_DIR}/fairmq/test/req-rep
@ -71,6 +72,7 @@ set(Exe_Names
test-fairmq-sub test-fairmq-sub
test-fairmq-req test-fairmq-req
test-fairmq-rep test-fairmq-rep
test-fairmq-transfer-timeout
) )
set(Exe_Source set(Exe_Source
@ -80,6 +82,7 @@ set(Exe_Source
pub-sub/runTestSub.cxx pub-sub/runTestSub.cxx
req-rep/runTestReq.cxx req-rep/runTestReq.cxx
req-rep/runTestRep.cxx req-rep/runTestRep.cxx
runTransferTimeoutTest.cxx
) )
list(LENGTH Exe_Names _length) list(LENGTH Exe_Names _length)
@ -105,3 +108,7 @@ set_tests_properties(run_fairmq_pub_sub PROPERTIES PASS_REGULAR_EXPRESSION "PUB-
add_test(NAME run_fairmq_req_rep COMMAND ${CMAKE_BINARY_DIR}/fairmq/test/test-fairmq-req-rep.sh) add_test(NAME run_fairmq_req_rep COMMAND ${CMAKE_BINARY_DIR}/fairmq/test/test-fairmq-req-rep.sh)
set_tests_properties(run_fairmq_req_rep PROPERTIES TIMEOUT "30") set_tests_properties(run_fairmq_req_rep PROPERTIES TIMEOUT "30")
set_tests_properties(run_fairmq_req_rep PROPERTIES PASS_REGULAR_EXPRESSION "REQ-REP test successfull") set_tests_properties(run_fairmq_req_rep PROPERTIES PASS_REGULAR_EXPRESSION "REQ-REP test successfull")
add_test(NAME run_fairmq_transfer_timeout COMMAND ${CMAKE_BINARY_DIR}/bin/test-fairmq-transfer-timeout)
set_tests_properties(run_fairmq_transfer_timeout PROPERTIES TIMEOUT "30")
set_tests_properties(run_fairmq_transfer_timeout PROPERTIES PASS_REGULAR_EXPRESSION "Transfer timeout test successfull")

View File

@ -0,0 +1,166 @@
/********************************************************************************
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence version 3 (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
/**
* runTransferTimeoutTester.cxx
*
* @since 2015-09-05
* @author A. Rybalchenko
*/
#include "FairMQLogger.h"
#include "FairMQDevice.h"
#ifdef NANOMSG
#include "FairMQTransportFactoryNN.h"
#else
#include "FairMQTransportFactoryZMQ.h"
#endif
class TransferTimeoutTester : public FairMQDevice
{
public:
TransferTimeoutTester() {}
virtual ~TransferTimeoutTester() {}
protected:
virtual void Run()
{
bool setSndOK = false;
bool setRcvOK = false;
bool getSndOK = false;
bool getRcvOK = false;
bool sendCanceling = false;
bool receiveCanceling = false;
if (fChannels.at("data-out").at(0).SetSendTimeout(1000))
{
setSndOK = true;
LOG(INFO) << "set send timeout OK";
}
else
{
LOG(ERROR) << "set send timeout failed";
}
if (fChannels.at("data-in").at(0).SetReceiveTimeout(1000))
{
setRcvOK = true;
LOG(INFO) << "set receive timeout OK";
}
else
{
LOG(ERROR) << "set receive timeout failed";
}
if (setSndOK && setRcvOK)
{
if (fChannels.at("data-out").at(0).GetSendTimeout() == 1000)
{
getSndOK = true;
LOG(INFO) << "get send timeout OK: " << fChannels.at("data-out").at(0).GetSendTimeout();
}
else
{
LOG(ERROR) << "get send timeout failed";
}
if (fChannels.at("data-in").at(0).GetReceiveTimeout() == 1000)
{
getRcvOK = true;
LOG(INFO) << "get receive timeout OK: " << fChannels.at("data-in").at(0).GetReceiveTimeout();
}
else
{
LOG(ERROR) << "get receive timeout failed";
}
}
if (getSndOK && getRcvOK)
{
void* buffer = operator new[](1000);
std::unique_ptr<FairMQMessage> msg1(fTransportFactory->CreateMessage(buffer, 1000));
std::unique_ptr<FairMQMessage> msg2(fTransportFactory->CreateMessage());
if (fChannels.at("data-out").at(0).Send(msg1) == -2)
{
LOG(INFO) << "send canceled";
sendCanceling = true;
}
else
{
LOG(ERROR) << "send did not cancel";
}
if (fChannels.at("data-in").at(0).Receive(msg2) == -2)
{
LOG(INFO) << "receive canceled";
receiveCanceling = true;
}
else
{
LOG(ERROR) << "receive did not cancel";
}
if (sendCanceling && receiveCanceling)
{
LOG(INFO) << "Transfer timeout test successfull";
}
}
}
};
int main(int argc, char** argv)
{
TransferTimeoutTester timeoutTester;
timeoutTester.CatchSignals();
#ifdef NANOMSG
timeoutTester.SetTransport(new FairMQTransportFactoryNN());
#else
timeoutTester.SetTransport(new FairMQTransportFactoryZMQ());
#endif
timeoutTester.SetProperty(TransferTimeoutTester::Id, "timeoutTester");
FairMQChannel dataOutChannel;
dataOutChannel.UpdateType("push");
dataOutChannel.UpdateMethod("bind");
dataOutChannel.UpdateAddress("tcp://127.0.0.1:5559");
dataOutChannel.UpdateSndBufSize(1000);
dataOutChannel.UpdateRcvBufSize(1000);
dataOutChannel.UpdateRateLogging(0);
timeoutTester.fChannels["data-out"].push_back(dataOutChannel);
FairMQChannel dataInChannel;
dataInChannel.UpdateType("pull");
dataInChannel.UpdateMethod("bind");
dataInChannel.UpdateAddress("tcp://127.0.0.1:5560");
dataInChannel.UpdateSndBufSize(1000);
dataInChannel.UpdateRcvBufSize(1000);
dataInChannel.UpdateRateLogging(0);
timeoutTester.fChannels["data-in"].push_back(dataInChannel);
timeoutTester.ChangeState(TransferTimeoutTester::INIT_DEVICE);
timeoutTester.WaitForEndOfState(TransferTimeoutTester::INIT_DEVICE);
timeoutTester.ChangeState(TransferTimeoutTester::INIT_TASK);
timeoutTester.WaitForEndOfState(TransferTimeoutTester::INIT_TASK);
timeoutTester.ChangeState(TransferTimeoutTester::RUN);
timeoutTester.WaitForEndOfState(TransferTimeoutTester::RUN);
timeoutTester.ChangeState(TransferTimeoutTester::RESET_TASK);
timeoutTester.WaitForEndOfState(TransferTimeoutTester::RESET_TASK);
timeoutTester.ChangeState(TransferTimeoutTester::RESET_DEVICE);
timeoutTester.WaitForEndOfState(TransferTimeoutTester::RESET_DEVICE);
timeoutTester.ChangeState(TransferTimeoutTester::END);
return 0;
}

View File

@ -37,20 +37,20 @@ FairMQSocketZMQ::FairMQSocketZMQ(const string& type, const string& name, int num
if (zmq_ctx_set(fContext->GetContext(), ZMQ_IO_THREADS, numIoThreads) != 0) if (zmq_ctx_set(fContext->GetContext(), ZMQ_IO_THREADS, numIoThreads) != 0)
{ {
LOG(ERROR) << "failed configuring context, reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed configuring context, reason: " << zmq_strerror(errno);
} }
fSocket = zmq_socket(fContext->GetContext(), GetConstant(type)); fSocket = zmq_socket(fContext->GetContext(), GetConstant(type));
if (fSocket == NULL) if (fSocket == NULL)
{ {
LOG(ERROR) << "failed creating socket " << fId << ", reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed creating socket " << fId << ", reason: " << zmq_strerror(errno);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (zmq_setsockopt(fSocket, ZMQ_IDENTITY, &fId, fId.length()) != 0) if (zmq_setsockopt(fSocket, ZMQ_IDENTITY, &fId, fId.length()) != 0)
{ {
LOG(ERROR) << "failed setting ZMQ_IDENTITY socket option, reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed setting ZMQ_IDENTITY socket option, reason: " << zmq_strerror(errno);
} }
// Tell socket to try and send/receive outstanding messages for <linger> milliseconds before terminating. // Tell socket to try and send/receive outstanding messages for <linger> milliseconds before terminating.
@ -58,14 +58,14 @@ FairMQSocketZMQ::FairMQSocketZMQ(const string& type, const string& name, int num
int linger = 500; int linger = 500;
if (zmq_setsockopt(fSocket, ZMQ_LINGER, &linger, sizeof(linger)) != 0) if (zmq_setsockopt(fSocket, ZMQ_LINGER, &linger, sizeof(linger)) != 0)
{ {
LOG(ERROR) << "failed setting ZMQ_LINGER socket option, reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed setting ZMQ_LINGER socket option, reason: " << zmq_strerror(errno);
} }
if (type == "sub") if (type == "sub")
{ {
if (zmq_setsockopt(fSocket, ZMQ_SUBSCRIBE, NULL, 0) != 0) if (zmq_setsockopt(fSocket, ZMQ_SUBSCRIBE, NULL, 0) != 0)
{ {
LOG(ERROR) << "failed setting ZMQ_SUBSCRIBE socket option, reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed setting ZMQ_SUBSCRIBE socket option, reason: " << zmq_strerror(errno);
} }
} }
@ -87,7 +87,7 @@ bool FairMQSocketZMQ::Bind(const string& address)
// do not print error in this case, this is handled by FairMQDevice in case no connection could be established after trying a number of random ports from a range. // do not print error in this case, this is handled by FairMQDevice in case no connection could be established after trying a number of random ports from a range.
return false; return false;
} }
LOG(ERROR) << "failed binding socket " << fId << ", reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed binding socket " << fId << ", reason: " << zmq_strerror(errno);
return false; return false;
} }
return true; return true;
@ -99,7 +99,7 @@ void FairMQSocketZMQ::Connect(const string& address)
if (zmq_connect(fSocket, address.c_str()) != 0) if (zmq_connect(fSocket, address.c_str()) != 0)
{ {
LOG(ERROR) << "failed connecting socket " << fId << ", reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed connecting socket " << fId << ", reason: " << zmq_strerror(errno);
// error here means incorrect configuration. exit if it happens. // error here means incorrect configuration. exit if it happens.
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -116,14 +116,14 @@ int FairMQSocketZMQ::Send(FairMQMessage* msg, const string& flag)
} }
if (zmq_errno() == EAGAIN) if (zmq_errno() == EAGAIN)
{ {
return 0; return -2;
} }
if (zmq_errno() == ETERM) if (zmq_errno() == ETERM)
{ {
LOG(INFO) << "terminating socket " << fId; LOG(INFO) << "terminating socket " << fId;
return -1; return -1;
} }
LOG(ERROR) << "failed sending on socket " << fId << ", reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed sending on socket " << fId << ", reason: " << zmq_strerror(errno);
return nbytes; return nbytes;
} }
@ -138,14 +138,14 @@ int FairMQSocketZMQ::Send(FairMQMessage* msg, const int flags)
} }
if (zmq_errno() == EAGAIN) if (zmq_errno() == EAGAIN)
{ {
return 0; return -2;
} }
if (zmq_errno() == ETERM) if (zmq_errno() == ETERM)
{ {
LOG(INFO) << "terminating socket " << fId; LOG(INFO) << "terminating socket " << fId;
return -1; return -1;
} }
LOG(ERROR) << "failed sending on socket " << fId << ", reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed sending on socket " << fId << ", reason: " << zmq_strerror(errno);
return nbytes; return nbytes;
} }
@ -160,14 +160,14 @@ int FairMQSocketZMQ::Receive(FairMQMessage* msg, const string& flag)
} }
if (zmq_errno() == EAGAIN) if (zmq_errno() == EAGAIN)
{ {
return 0; return -2;
} }
if (zmq_errno() == ETERM) if (zmq_errno() == ETERM)
{ {
LOG(INFO) << "terminating socket " << fId; LOG(INFO) << "terminating socket " << fId;
return -1; return -1;
} }
LOG(ERROR) << "failed receiving on socket " << fId << ", reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed receiving on socket " << fId << ", reason: " << zmq_strerror(errno);
return nbytes; return nbytes;
} }
@ -182,14 +182,14 @@ int FairMQSocketZMQ::Receive(FairMQMessage* msg, const int flags)
} }
if (zmq_errno() == EAGAIN) if (zmq_errno() == EAGAIN)
{ {
return 0; return -2;
} }
if (zmq_errno() == ETERM) if (zmq_errno() == ETERM)
{ {
LOG(INFO) << "terminating socket " << fId; LOG(INFO) << "terminating socket " << fId;
return -1; return -1;
} }
LOG(ERROR) << "failed receiving on socket " << fId << ", reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed receiving on socket " << fId << ", reason: " << zmq_strerror(errno);
return nbytes; return nbytes;
} }
@ -204,7 +204,7 @@ void FairMQSocketZMQ::Close()
if (zmq_close(fSocket) != 0) if (zmq_close(fSocket) != 0)
{ {
LOG(ERROR) << "failed closing socket " << fId << ", reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed closing socket " << fId << ", reason: " << zmq_strerror(errno);
} }
fSocket = NULL; fSocket = NULL;
@ -214,16 +214,16 @@ void FairMQSocketZMQ::Terminate()
{ {
if (zmq_ctx_destroy(fContext->GetContext()) != 0) if (zmq_ctx_destroy(fContext->GetContext()) != 0)
{ {
LOG(ERROR) << "failed terminating context, reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed terminating context, reason: " << zmq_strerror(errno);
} }
} }
void* FairMQSocketZMQ::GetSocket() void* FairMQSocketZMQ::GetSocket() const
{ {
return fSocket; return fSocket;
} }
int FairMQSocketZMQ::GetSocket(int nothing) int FairMQSocketZMQ::GetSocket(int nothing) const
{ {
// dummy method to comply with the interface. functionality not possible in zeromq. // dummy method to comply with the interface. functionality not possible in zeromq.
return -1; return -1;
@ -233,7 +233,7 @@ void FairMQSocketZMQ::SetOption(const string& option, const void* value, size_t
{ {
if (zmq_setsockopt(fSocket, GetConstant(option), value, valueSize) < 0) if (zmq_setsockopt(fSocket, GetConstant(option), value, valueSize) < 0)
{ {
LOG(ERROR) << "failed setting socket option, reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed setting socket option, reason: " << zmq_strerror(errno);
} }
} }
@ -241,30 +241,150 @@ void FairMQSocketZMQ::GetOption(const string& option, void* value, size_t* value
{ {
if (zmq_getsockopt(fSocket, GetConstant(option), value, valueSize) < 0) if (zmq_getsockopt(fSocket, GetConstant(option), value, valueSize) < 0)
{ {
LOG(ERROR) << "failed getting socket option, reason: " << zmq_strerror(errno); LOG(ERROR) << "Failed getting socket option, reason: " << zmq_strerror(errno);
} }
} }
unsigned long FairMQSocketZMQ::GetBytesTx() unsigned long FairMQSocketZMQ::GetBytesTx() const
{ {
return fBytesTx; return fBytesTx;
} }
unsigned long FairMQSocketZMQ::GetBytesRx() unsigned long FairMQSocketZMQ::GetBytesRx() const
{ {
return fBytesRx; return fBytesRx;
} }
unsigned long FairMQSocketZMQ::GetMessagesTx() unsigned long FairMQSocketZMQ::GetMessagesTx() const
{ {
return fMessagesTx; return fMessagesTx;
} }
unsigned long FairMQSocketZMQ::GetMessagesRx() unsigned long FairMQSocketZMQ::GetMessagesRx() const
{ {
return fMessagesRx; return fMessagesRx;
} }
bool FairMQSocketZMQ::SetSendTimeout(const int timeout, const string& address, const string& method)
{
if (method == "bind")
{
if (zmq_unbind(fSocket, address.c_str()) != 0)
{
LOG(ERROR) << "Failed unbinding socket " << fId << ", reason: " << zmq_strerror(errno);
return false;
}
if (zmq_setsockopt(fSocket, ZMQ_SNDTIMEO, &timeout, sizeof(int)) != 0)
{
LOG(ERROR) << "Failed setting option on socket " << fId << ", reason: " << zmq_strerror(errno);
return false;
}
if (zmq_bind(fSocket, address.c_str()) != 0)
{
LOG(ERROR) << "Failed binding socket " << fId << ", reason: " << zmq_strerror(errno);
return false;
}
}
else if (method == "connect")
{
if (zmq_disconnect(fSocket, address.c_str()) != 0)
{
LOG(ERROR) << "Failed disconnecting socket " << fId << ", reason: " << zmq_strerror(errno);
return false;
}
if (zmq_setsockopt(fSocket, ZMQ_SNDTIMEO, &timeout, sizeof(int)) != 0)
{
LOG(ERROR) << "Failed setting option on socket " << fId << ", reason: " << zmq_strerror(errno);
return false;
}
if (zmq_connect(fSocket, address.c_str()) != 0)
{
LOG(ERROR) << "Failed connecting socket " << fId << ", reason: " << zmq_strerror(errno);
return false;
}
}
else
{
LOG(ERROR) << "SetSendTimeout() failed - unknown method provided!";
return false;
}
return true;
}
int FairMQSocketZMQ::GetSendTimeout() const
{
int timeout = -1;
size_t size = sizeof(timeout);
if (zmq_getsockopt(fSocket, ZMQ_SNDTIMEO, &timeout, &size) != 0)
{
LOG(ERROR) << "Failed getting option 'receive timeout' on socket " << fId << ", reason: " << zmq_strerror(errno);
}
return timeout;
}
bool FairMQSocketZMQ::SetReceiveTimeout(const int timeout, const string& address, const string& method)
{
if (method == "bind")
{
if (zmq_unbind(fSocket, address.c_str()) != 0)
{
LOG(ERROR) << "Failed unbinding socket " << fId << ", reason: " << zmq_strerror(errno);
return false;
}
if (zmq_setsockopt(fSocket, ZMQ_RCVTIMEO, &timeout, sizeof(int)) != 0)
{
LOG(ERROR) << "Failed setting option on socket " << fId << ", reason: " << zmq_strerror(errno);
return false;
}
if (zmq_bind(fSocket, address.c_str()) != 0)
{
LOG(ERROR) << "Failed binding socket " << fId << ", reason: " << zmq_strerror(errno);
return false;
}
}
else if (method == "connect")
{
if (zmq_disconnect(fSocket, address.c_str()) != 0)
{
LOG(ERROR) << "Failed disconnecting socket " << fId << ", reason: " << zmq_strerror(errno);
return false;
}
if (zmq_setsockopt(fSocket, ZMQ_RCVTIMEO, &timeout, sizeof(int)) != 0)
{
LOG(ERROR) << "Failed setting option on socket " << fId << ", reason: " << zmq_strerror(errno);
return false;
}
if (zmq_connect(fSocket, address.c_str()) != 0)
{
LOG(ERROR) << "Failed connecting socket " << fId << ", reason: " << zmq_strerror(errno);
return false;
}
}
else
{
LOG(ERROR) << "SetReceiveTimeout() failed - unknown method provided!";
return false;
}
return true;
}
int FairMQSocketZMQ::GetReceiveTimeout() const
{
int timeout = -1;
size_t size = sizeof(timeout);
if (zmq_getsockopt(fSocket, ZMQ_RCVTIMEO, &timeout, &size) != 0)
{
LOG(ERROR) << "Failed getting option 'receive timeout' on socket " << fId << ", reason: " << zmq_strerror(errno);
}
return timeout;
}
int FairMQSocketZMQ::GetConstant(const string& constant) int FairMQSocketZMQ::GetConstant(const string& constant)
{ {
if (constant == "") if (constant == "")

View File

@ -35,18 +35,23 @@ class FairMQSocketZMQ : public FairMQSocket
virtual int Receive(FairMQMessage* msg, const std::string& flag = ""); virtual int Receive(FairMQMessage* msg, const std::string& flag = "");
virtual int Receive(FairMQMessage* msg, const int flags = 0); virtual int Receive(FairMQMessage* msg, const int flags = 0);
virtual void* GetSocket(); virtual void* GetSocket() const;
virtual int GetSocket(int nothing); virtual int GetSocket(int nothing) const;
virtual void Close(); virtual void Close();
virtual void Terminate(); virtual void Terminate();
virtual void SetOption(const std::string& option, const void* value, size_t valueSize); virtual void SetOption(const std::string& option, const void* value, size_t valueSize);
virtual void GetOption(const std::string& option, void* value, size_t* valueSize); virtual void GetOption(const std::string& option, void* value, size_t* valueSize);
virtual unsigned long GetBytesTx(); virtual unsigned long GetBytesTx() const;
virtual unsigned long GetBytesRx(); virtual unsigned long GetBytesRx() const;
virtual unsigned long GetMessagesTx(); virtual unsigned long GetMessagesTx() const;
virtual unsigned long GetMessagesRx(); virtual unsigned long GetMessagesRx() const;
virtual bool SetSendTimeout(const int timeout, const std::string& address, const std::string& method);
virtual int GetSendTimeout() const;
virtual bool SetReceiveTimeout(const int timeout, const std::string& address, const std::string& method);
virtual int GetReceiveTimeout() const;
static int GetConstant(const std::string& constant); static int GetConstant(const std::string& constant);