Enable new callback API

- OnData() channel data handler.
 - ConditionalRun() for devices without incoming data.
 - Header file with common main(), to be extended with getDevice/addCustomOptions.
 - Update examples (MQ/Tutorial3) to use the new API and config.
 - NewSimpleMessage() for simpler creation of small messages (additional copy).
 - Replace SetProperty/GetProperty with fConfig access.
 - Runtime configurable channel names for common devices.
 - Configurable logging interval per channel.
 - FairMQMultiplier for distributing same data to multiple outputs.
 - Cleanup state machine messages.
 - Cmd option to toggle signal handling.
 - Simpler API for send/receive timeouts.
 - Enable --log-to-file.
 - Fix coverity issues, warnings.
 - Various code cleanup and minor tweaks.
This commit is contained in:
Alexey Rybalchenko 2016-08-10 09:47:53 +02:00
parent e0a03242ac
commit 16fd63cd5b
54 changed files with 1730 additions and 1665 deletions

View File

@ -81,10 +81,11 @@ Set(SRCS
"FairMQPoller.cxx"
"devices/FairMQBenchmarkSampler.cxx"
"devices/FairMQSink.cxx"
"devices/FairMQProxy.cxx"
"devices/FairMQSplitter.cxx"
"devices/FairMQMerger.cxx"
"devices/FairMQMultiplier.cxx"
"devices/FairMQProxy.cxx"
"devices/FairMQSink.cxx"
"devices/FairMQSplitter.cxx"
"options/FairProgOptions.cxx"
"options/FairMQProgOptions.cxx"
@ -106,6 +107,8 @@ EndIf(NANOMSG_FOUND)
# manual install (globbing add not recommended)
Set(FAIRMQHEADERS
FairMQParts.h
# FairMQPlugin.h
runFairMQDevice.h
options/FairProgOptionsHelper.h
options/FairMQEventManager.h
tools/FairMQTools.h
@ -142,7 +145,7 @@ If(DDS_FOUND)
Set(DEPENDENCIES
${DEPENDENCIES}
${DDS_INTERCOM_LIBRARY_SHARED}
${DDS_PROTOCOL_LIBRARY_SHARED} # also link the two DDS dependency libraries to avoid linking issues on some osx systems
${DDS_PROTOCOL_LIBRARY_SHARED}
${DDS_USER_DEFAULTS_LIBRARY_SHARED}
)
EndIf(DDS_FOUND)
@ -153,10 +156,11 @@ GENERATE_LIBRARY()
Set(Exe_Names
bsampler
merger
multiplier
proxy
sink
splitter
merger
proxy
runConfigExample
)
@ -169,10 +173,11 @@ EndIf(DDS_FOUND)
Set(Exe_Source
run/runBenchmarkSampler.cxx
run/runMerger.cxx
run/runMultiplier.cxx
run/runProxy.cxx
run/runSink.cxx
run/runSplitter.cxx
run/runMerger.cxx
run/runProxy.cxx
options/runConfigEx.cxx
)
@ -197,4 +202,3 @@ EndForEach(_file RANGE 0 ${_length})
configure_file( ${CMAKE_SOURCE_DIR}/fairmq/options/startConfigExample.sh.in
${CMAKE_BINARY_DIR}/bin/startConfigExample.sh )

View File

@ -23,6 +23,8 @@ using namespace std;
boost::mutex FairMQChannel::fChannelMutex;
std::atomic<bool> FairMQChannel::fInterrupted(false);
FairMQChannel::FairMQChannel()
: fSocket(nullptr)
, fType("unspecified")
@ -41,8 +43,6 @@ FairMQChannel::FairMQChannel()
, fTransportFactory(nullptr)
, fNoBlockFlag(0)
, fSndMoreFlag(0)
, fSndTimeoutInMs(-1)
, fRcvTimeoutInMs(-1)
{
}
@ -64,8 +64,6 @@ FairMQChannel::FairMQChannel(const string& type, const string& method, const str
, fTransportFactory(nullptr)
, fNoBlockFlag(0)
, fSndMoreFlag(0)
, fSndTimeoutInMs(-1)
, fRcvTimeoutInMs(-1)
{
}
@ -87,8 +85,6 @@ FairMQChannel::FairMQChannel(const FairMQChannel& chan)
, fTransportFactory(nullptr)
, fNoBlockFlag(chan.fNoBlockFlag)
, fSndMoreFlag(chan.fSndMoreFlag)
, fSndTimeoutInMs(chan.fSndTimeoutInMs)
, fRcvTimeoutInMs(chan.fRcvTimeoutInMs)
{}
FairMQChannel& FairMQChannel::operator=(const FairMQChannel& chan)
@ -110,8 +106,6 @@ FairMQChannel& FairMQChannel::operator=(const FairMQChannel& chan)
fTransportFactory = nullptr;
fNoBlockFlag = chan.fNoBlockFlag;
fSndMoreFlag = chan.fSndMoreFlag;
fSndTimeoutInMs = chan.fSndTimeoutInMs;
fRcvTimeoutInMs = chan.fRcvTimeoutInMs;
return *this;
}
@ -425,8 +419,8 @@ bool FairMQChannel::ValidateChannel()
{
ss << "INVALID";
LOG(DEBUG) << ss.str();
LOG(DEBUG) << "Invalid channel type: \"" << fType << "\"";
return false;
LOG(ERROR) << "Invalid channel type: \"" << fType << "\"";
exit(EXIT_FAILURE);
}
// validate socket method
@ -436,8 +430,8 @@ bool FairMQChannel::ValidateChannel()
{
ss << "INVALID";
LOG(DEBUG) << ss.str();
LOG(DEBUG) << "Invalid channel method: \"" << fMethod << "\"";
return false;
LOG(ERROR) << "Invalid channel method: \"" << fMethod << "\"";
exit(EXIT_FAILURE);
}
// validate socket address
@ -459,7 +453,7 @@ bool FairMQChannel::ValidateChannel()
{
ss << "INVALID";
LOG(DEBUG) << ss.str();
LOG(DEBUG) << "invalid channel address: \"" << fAddress << "\" (missing port?)";
LOG(ERROR) << "invalid channel address: \"" << fAddress << "\" (missing port?)";
return false;
}
}
@ -471,7 +465,7 @@ bool FairMQChannel::ValidateChannel()
{
ss << "INVALID";
LOG(DEBUG) << ss.str();
LOG(DEBUG) << "invalid channel address: \"" << fAddress << "\" (empty IPC address?)";
LOG(ERROR) << "invalid channel address: \"" << fAddress << "\" (empty IPC address?)";
return false;
}
}
@ -480,7 +474,7 @@ bool FairMQChannel::ValidateChannel()
// if neither TCP or IPC is specified, return invalid
ss << "INVALID";
LOG(DEBUG) << ss.str();
LOG(DEBUG) << "invalid channel address: \"" << fAddress << "\" (missing protocol specifier?)";
LOG(ERROR) << "invalid channel address: \"" << fAddress << "\" (missing protocol specifier?)";
return false;
}
}
@ -490,8 +484,8 @@ bool FairMQChannel::ValidateChannel()
{
ss << "INVALID";
LOG(DEBUG) << ss.str();
LOG(DEBUG) << "invalid channel send buffer size: \"" << fSndBufSize << "\"";
return false;
LOG(ERROR) << "invalid channel send buffer size (cannot be negative): \"" << fSndBufSize << "\"";
exit(EXIT_FAILURE);
}
// validate socket buffer size for receiving
@ -499,8 +493,8 @@ bool FairMQChannel::ValidateChannel()
{
ss << "INVALID";
LOG(DEBUG) << ss.str();
LOG(DEBUG) << "invalid channel receive buffer size: \"" << fRcvBufSize << "\"";
return false;
LOG(ERROR) << "invalid channel receive buffer size (cannot be negative): \"" << fRcvBufSize << "\"";
exit(EXIT_FAILURE);
}
// validate socket kernel transmit size for sending
@ -508,8 +502,8 @@ bool FairMQChannel::ValidateChannel()
{
ss << "INVALID";
LOG(DEBUG) << ss.str();
LOG(DEBUG) << "invalid channel send kernel transmit size: \"" << fSndKernelSize << "\"";
return false;
LOG(ERROR) << "invalid channel send kernel transmit size (cannot be negative): \"" << fSndKernelSize << "\"";
exit(EXIT_FAILURE);
}
// validate socket kernel transmit size for receiving
@ -517,8 +511,17 @@ bool FairMQChannel::ValidateChannel()
{
ss << "INVALID";
LOG(DEBUG) << ss.str();
LOG(DEBUG) << "invalid channel receive kernel transmit size: \"" << fRcvKernelSize << "\"";
return false;
LOG(ERROR) << "invalid channel receive kernel transmit size (cannot be negative): \"" << fRcvKernelSize << "\"";
exit(EXIT_FAILURE);
}
// validate socket rate logging interval
if (fRateLogging < 0)
{
ss << "INVALID";
LOG(DEBUG) << ss.str();
LOG(ERROR) << "invalid socket rate logging interval (cannot be negative): \"" << fRateLogging << "\"";
exit(EXIT_FAILURE);
}
fIsValid = true;
@ -561,14 +564,17 @@ void FairMQChannel::ResetChannel()
// TODO: implement channel resetting
}
int FairMQChannel::Send(const unique_ptr<FairMQMessage>& msg) const
int FairMQChannel::Send(const unique_ptr<FairMQMessage>& msg, int sndTimeoutInMs) const
{
fPoller->Poll(fSndTimeoutInMs);
fPoller->Poll(sndTimeoutInMs);
if (fPoller->CheckInput(0))
{
HandleUnblock();
return -2;
if (fInterrupted)
{
return -2;
}
}
if (fPoller->CheckOutput(1))
@ -579,14 +585,17 @@ int FairMQChannel::Send(const unique_ptr<FairMQMessage>& msg) const
return -2;
}
int FairMQChannel::Receive(const unique_ptr<FairMQMessage>& msg) const
int FairMQChannel::Receive(const unique_ptr<FairMQMessage>& msg, int rcvTimeoutInMs) const
{
fPoller->Poll(fRcvTimeoutInMs);
fPoller->Poll(rcvTimeoutInMs);
if (fPoller->CheckInput(0))
{
HandleUnblock();
return -2;
if (fInterrupted)
{
return -2;
}
}
if (fPoller->CheckInput(1))
@ -597,14 +606,17 @@ int FairMQChannel::Receive(const unique_ptr<FairMQMessage>& msg) const
return -2;
}
int64_t FairMQChannel::Send(const std::vector<std::unique_ptr<FairMQMessage>>& msgVec) const
int64_t FairMQChannel::Send(const std::vector<std::unique_ptr<FairMQMessage>>& msgVec, int sndTimeoutInMs) const
{
fPoller->Poll(fSndTimeoutInMs);
fPoller->Poll(sndTimeoutInMs);
if (fPoller->CheckInput(0))
{
HandleUnblock();
return -2;
if (fInterrupted)
{
return -2;
}
}
if (fPoller->CheckOutput(1))
@ -615,14 +627,17 @@ int64_t FairMQChannel::Send(const std::vector<std::unique_ptr<FairMQMessage>>& m
return -2;
}
int64_t FairMQChannel::Receive(std::vector<std::unique_ptr<FairMQMessage>>& msgVec) const
int64_t FairMQChannel::Receive(std::vector<std::unique_ptr<FairMQMessage>>& msgVec, int rcvTimeoutInMs) const
{
fPoller->Poll(fRcvTimeoutInMs);
fPoller->Poll(rcvTimeoutInMs);
if (fPoller->CheckInput(0))
{
HandleUnblock();
return -2;
if (fInterrupted)
{
return -2;
}
}
if (fPoller->CheckInput(1))
@ -633,16 +648,20 @@ int64_t FairMQChannel::Receive(std::vector<std::unique_ptr<FairMQMessage>>& msgV
return -2;
}
int FairMQChannel::Send(FairMQMessage* msg, const string& flag) const
int FairMQChannel::Send(FairMQMessage* msg, const string& flag, int sndTimeoutInMs) const
{
if (flag == "")
{
fPoller->Poll(fSndTimeoutInMs);
fPoller->Poll(sndTimeoutInMs);
if (fPoller->CheckInput(0))
{
HandleUnblock();
return -2;
if (fInterrupted)
{
return -2;
}
}
if (fPoller->CheckOutput(1))
@ -658,16 +677,20 @@ int FairMQChannel::Send(FairMQMessage* msg, const string& flag) const
}
}
int FairMQChannel::Send(FairMQMessage* msg, const int flags) const
int FairMQChannel::Send(FairMQMessage* msg, const int flags, int sndTimeoutInMs) const
{
if (flags == 0)
{
fPoller->Poll(fSndTimeoutInMs);
fPoller->Poll(sndTimeoutInMs);
if (fPoller->CheckInput(0))
{
HandleUnblock();
return -2;
if (fInterrupted)
{
return -2;
}
}
if (fPoller->CheckOutput(1))
@ -683,16 +706,20 @@ int FairMQChannel::Send(FairMQMessage* msg, const int flags) const
}
}
int FairMQChannel::Receive(FairMQMessage* msg, const string& flag) const
int FairMQChannel::Receive(FairMQMessage* msg, const string& flag, int rcvTimeoutInMs) const
{
if (flag == "")
{
fPoller->Poll(fRcvTimeoutInMs);
fPoller->Poll(rcvTimeoutInMs);
if (fPoller->CheckInput(0))
{
HandleUnblock();
return -2;
if (fInterrupted)
{
return -2;
}
}
if (fPoller->CheckInput(1))
@ -708,16 +735,20 @@ int FairMQChannel::Receive(FairMQMessage* msg, const string& flag) const
}
}
int FairMQChannel::Receive(FairMQMessage* msg, const int flags) const
int FairMQChannel::Receive(FairMQMessage* msg, const int flags, int rcvTimeoutInMs) const
{
if (flags == 0)
{
fPoller->Poll(fRcvTimeoutInMs);
fPoller->Poll(rcvTimeoutInMs);
if (fPoller->CheckInput(0))
{
HandleUnblock();
return -2;
if (fInterrupted)
{
return -2;
}
}
if (fPoller->CheckInput(1))
@ -761,7 +792,7 @@ inline bool FairMQChannel::HandleUnblock() const
FairMQMessage* cmd = fTransportFactory->CreateMessage();
if (fCmdSocket->Receive(cmd, 0) >= 0)
{
LOG(DEBUG) << "unblocked";
// LOG(DEBUG) << "unblocked";
}
delete cmd;
return true;

View File

@ -17,6 +17,7 @@
#include <string>
#include <memory> // unique_ptr
#include <atomic>
#include <boost/thread/mutex.hpp>
@ -61,57 +62,73 @@ class FairMQChannel
/// Get socket type
/// @return Returns socket type (push/pull/pub/sub/spub/xsub/pair/req/rep/dealer/router/)
std::string GetType() const;
/// Get socket method
/// @return Returns socket method (bind/connect)
std::string GetMethod() const;
/// Get socket address (e.g. "tcp://127.0.0.1:5555" or "ipc://abc")
/// @return Returns socket type (e.g. "tcp://127.0.0.1:5555" or "ipc://abc")
std::string GetAddress() const;
/// Get channel property (custom property)
/// @return Returns property value
std::string GetProperty() const;
/// Get socket send buffer size (in number of messages)
/// @return Returns socket send buffer size (in number of messages)
int GetSndBufSize() const;
/// Get socket receive buffer size (in number of messages)
/// @return Returns socket receive buffer size (in number of messages)
int GetRcvBufSize() const;
/// Get socket kernel transmit send buffer size (in bytes)
/// @return Returns socket kernel transmit send buffer size (in bytes)
int GetSndKernelSize() const;
/// Get socket kernel transmit receive buffer size (in bytes)
/// @return Returns socket kernel transmit receive buffer size (in bytes)
int GetRcvKernelSize() const;
/// Get socket rate logging setting (1/0)
/// @return Returns socket rate logging setting (1/0)
/// Get socket rate logging interval (in seconds)
/// @return Returns socket rate logging interval (in seconds)
int GetRateLogging() const;
/// Set socket type
/// @param type Socket type (push/pull/pub/sub/spub/xsub/pair/req/rep/dealer/router/)
void UpdateType(const std::string& type);
/// Set socket method
/// @param method Socket method (bind/connect)
void UpdateMethod(const std::string& method);
/// Set socket address
/// @param address Socket address (e.g. "tcp://127.0.0.1:5555" or "ipc://abc")
void UpdateAddress(const std::string& address);
/// Set custom channel property
/// @param property Channel property
void UpdateProperty(const std::string& property);
/// Set socket send buffer size
/// @param sndBufSize Socket send buffer size (in number of messages)
void UpdateSndBufSize(const int sndBufSize);
/// Set socket receive buffer size
/// @param rcvBufSize Socket receive buffer size (in number of messages)
void UpdateRcvBufSize(const int rcvBufSize);
/// Set socket kernel transmit send buffer size (in bytes)
/// @param sndKernelSize Socket send buffer size (in bytes)
void UpdateSndKernelSize(const int sndKernelSize);
/// Set socket kernel transmit receive buffer size (in bytes)
/// @param rcvKernelSize Socket receive buffer size (in bytes)
void UpdateRcvKernelSize(const int rcvKernelSize);
/// Set socket rate logging setting
/// @param rateLogging Socket rate logging setting (1/0)
/// Set socket rate logging interval (in seconds)
/// @param rateLogging Socket rate logging interval (in seconds)
void UpdateRateLogging(const int rateLogging);
/// Checks if the configured channel settings are valid (checks the validity parameter, without running full validation (as oposed to ValidateChannel()))
@ -135,7 +152,7 @@ class FairMQChannel
/// @param msg Constant reference of unique_ptr to a FairMQMessage
/// @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, int sndTimeoutInMs = -1) const;
/// Sends a message in non-blocking mode.
/// @details SendAsync method attempts to send a message without blocking by
@ -179,7 +196,7 @@ class FairMQChannel
/// @param msgVec message vector reference
/// @return Number of bytes that have been queued. -2 If queueing was not possible or timed out.
/// In case of errors, returns -1.
int64_t Send(const std::vector<std::unique_ptr<FairMQMessage>>& msgVec) const;
int64_t Send(const std::vector<std::unique_ptr<FairMQMessage>>& msgVec, int sndTimeoutInMs = -1) const;
/// Sends a vector of message in non-blocking mode.
/// @details SendAsync method attempts to send a vector of messages without blocking by
@ -200,7 +217,7 @@ class FairMQChannel
/// @param msg Constant reference of unique_ptr to a FairMQMessage
/// @return 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, int rcvTimeoutInMs = -1) const;
/// Receives a message in non-blocking mode.
///
@ -217,7 +234,7 @@ class FairMQChannel
/// @param msgVec message vector reference
/// @return 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.
int64_t Receive(std::vector<std::unique_ptr<FairMQMessage>>& msgVec) const;
int64_t Receive(std::vector<std::unique_ptr<FairMQMessage>>& msgVec, int rcvTimeoutInMs = -1) const;
/// Receives a vector of messages in non-blocking mode.
///
@ -229,44 +246,16 @@ class FairMQChannel
return fSocket->Receive(msgVec, fNoBlockFlag);
}
// DEPRECATED socket method wrappers with raw pointers and flag checks
int Send(FairMQMessage* msg, const std::string& flag = "") const;
int Send(FairMQMessage* msg, const int flags) const;
int Receive(FairMQMessage* msg, const std::string& flag = "") const;
int Receive(FairMQMessage* msg, const int flags) const;
/// Sets a timeout on the (blocking) Send method
/// @param timeout timeout value in milliseconds
inline void SetSendTimeout(const int timeout)
{
fSndTimeoutInMs = timeout;
}
/// Gets the current value of the timeout on the (blocking) Send method
/// @return Timeout value in milliseconds. -1 for no timeout.
inline int GetSendTimeout() const
{
return fSndTimeoutInMs;
}
/// Sets a timeout on the (blocking) Receive method
/// @param timeout timeout value in milliseconds
inline void SetReceiveTimeout(const int timeout)
{
fRcvTimeoutInMs = timeout;
}
/// Gets the current value of the timeout on the (blocking) Receive method
/// @return Timeout value in milliseconds. -1 for no timeout.
inline int GetReceiveTimeout() const
{
return fRcvTimeoutInMs;
}
/// 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.
bool ExpectsAnotherPart() const;
// DEPRECATED socket method wrappers with raw pointers and flag checks
int Send(FairMQMessage* msg, const std::string& flag = "", int sndTimeoutInMs = -1) const;
int Send(FairMQMessage* msg, const int flags, int sndTimeoutInMs = -1) const;
int Receive(FairMQMessage* msg, const std::string& flag = "", int rcvTimeoutInMs = -1) const;
int Receive(FairMQMessage* msg, const int flags, int rcvTimeoutInMs = -1) const;
private:
std::string fType;
std::string fMethod;
@ -279,7 +268,7 @@ class FairMQChannel
int fRateLogging;
std::string fChannelName;
bool fIsValid;
std::atomic<bool> fIsValid;
FairMQPoller* fPoller;
FairMQSocket* fCmdSocket;
@ -289,9 +278,6 @@ class FairMQChannel
int fNoBlockFlag;
int fSndMoreFlag;
int fSndTimeoutInMs;
int fRcvTimeoutInMs;
bool InitCommandInterface(FairMQTransportFactory* factory, int numIoThreads);
bool HandleUnblock() const;
@ -301,6 +287,8 @@ class FairMQChannel
// this does not hurt much, because mutex is used only during initialization with very low contention
// possible TODO: improve this
static boost::mutex fChannelMutex;
static std::atomic<bool> fInterrupted;
};
#endif /* FAIRMQCHANNEL_H_ */

View File

@ -21,6 +21,7 @@
#include <termios.h> // for the InteractiveStateLoop
#include <poll.h>
#include <boost/timer/timer.hpp>
#include <boost/thread.hpp>
#include <boost/random/mersenne_twister.hpp> // for choosing random port in range
#include <boost/random/uniform_int_distribution.hpp> // for choosing random port in range
@ -47,6 +48,7 @@ static void CallSignalHandler(int signal)
FairMQDevice::FairMQDevice()
: fChannels()
, fConfig(nullptr)
, fId()
, fNetworkInterface()
, fMaxInitializationAttempts(120)
@ -56,13 +58,15 @@ FairMQDevice::FairMQDevice()
, fLogIntervalInMs(1000)
, fCmdSocket(nullptr)
, fTransportFactory(nullptr)
, fConfig(nullptr)
, fInitialValidationFinished(false)
, fInitialValidationCondition()
, fInitialValidationMutex()
, fCatchingSignals(false)
, fTerminated(false)
, fRunning(false)
, fTerminationRequested(false)
, fInteractiveRunning(false)
, fDataCallbacks(false)
, fMsgInputs()
, fMultipartInputs()
{
}
@ -81,8 +85,10 @@ void FairMQDevice::SignalHandler(int signal)
{
LOG(INFO) << "Caught signal " << signal;
if (!fTerminated)
if (!fTerminationRequested)
{
fTerminationRequested = true;
ChangeState(STOP);
ChangeState(RESET_TASK);
@ -94,15 +100,14 @@ void FairMQDevice::SignalHandler(int signal)
ChangeState(END);
// exit(EXIT_FAILURE);
fRunning = false;
fTerminated = true;
fInteractiveRunning = false;
LOG(INFO) << "Exiting.";
}
else
{
LOG(WARN) << "Repeated termination or bad initialization? Aborting.";
// std::abort();
exit(EXIT_FAILURE);
std::abort();
// exit(EXIT_FAILURE);
}
}
@ -224,13 +229,12 @@ void FairMQDevice::InitWrapper()
// go over the list of channels until all are initialized (and removed from the uninitialized list)
int numAttempts = 0;
int maxAttempts = fMaxInitializationAttempts;
while (!uninitializedConnectingChannels.empty())
{
ConnectChannels(uninitializedConnectingChannels);
if (++numAttempts > maxAttempts)
if (++numAttempts > fMaxInitializationAttempts)
{
LOG(ERROR) << "could not connect all channels after " << maxAttempts << " attempts";
LOG(ERROR) << "could not connect all channels after " << fMaxInitializationAttempts << " attempts";
// TODO: goto ERROR state;
exit(EXIT_FAILURE);
}
@ -317,58 +321,6 @@ bool FairMQDevice::ConnectChannel(FairMQChannel& ch)
return true;
}
// bool FairMQDevice::InitChannel(FairMQChannel& ch)
// {
// LOG(DEBUG) << "Initializing channel " << ch.fChannelName << " (" << ch.fType << ")";
// // initialize the socket
// ch.fSocket = fTransportFactory->CreateSocket(ch.fType, ch.fChannelName, fNumIoThreads, fId);
// // set high water marks
// ch.fSocket->SetOption("snd-hwm", &(ch.fSndBufSize), sizeof(ch.fSndBufSize));
// ch.fSocket->SetOption("rcv-hwm", &(ch.fRcvBufSize), sizeof(ch.fRcvBufSize));
// if (ch.fMethod == "bind")
// {
// // number of attempts when choosing a random port
// int maxAttempts = 1000;
// int numAttempts = 0;
// // initialize random generator
// boost::random::mt19937 gen(getpid());
// boost::random::uniform_int_distribution<> randomPort(fPortRangeMin, fPortRangeMax);
// LOG(DEBUG) << "Binding channel " << ch.fChannelName << " on " << ch.fAddress;
// // try to bind to the saved port. In case of failure, try random one.
// if (!ch.fSocket->Bind(ch.fAddress))
// {
// LOG(DEBUG) << "Could not bind to configured port, trying random port in range " << fPortRangeMin << "-" << fPortRangeMax;
// do {
// ++numAttempts;
// if (numAttempts > maxAttempts)
// {
// LOG(ERROR) << "could not bind to any port in the given range after " << maxAttempts << " attempts";
// return false;
// }
// size_t pos = ch.fAddress.rfind(":");
// stringstream newPort;
// newPort << static_cast<int>(randomPort(gen));
// ch.fAddress = ch.fAddress.substr(0, pos + 1) + newPort.str();
// LOG(DEBUG) << "Binding channel " << ch.fChannelName << " on " << ch.fAddress;
// } while (!ch.fSocket->Bind(ch.fAddress));
// }
// }
// else
// {
// LOG(DEBUG) << "Connecting channel " << ch.fChannelName << " to " << ch.fAddress;
// ch.fSocket->Connect(ch.fAddress);
// }
// return true;
// }
void FairMQDevice::InitTaskWrapper()
{
InitTask();
@ -434,15 +386,119 @@ void FairMQDevice::PrintChannel(const string& name)
}
}
void FairMQDevice::OnData(const string& channelName, InputMsgCallback callback)
{
fDataCallbacks = true;
fMsgInputs.insert(make_pair(channelName, callback));
}
void FairMQDevice::OnData(const string& channelName, InputMultipartCallback callback)
{
fDataCallbacks = true;
fMultipartInputs.insert(make_pair(channelName, callback));
}
void FairMQDevice::RunWrapper()
{
LOG(INFO) << "DEVICE: Running...";
boost::thread rateLogger(boost::bind(&FairMQDevice::LogSocketRates, this));
FairMQChannel::fInterrupted = false;
try
{
Run();
PreRun();
if (fDataCallbacks)
{
bool exitingRunningCallback = false;
vector<string> inputChannelKeys;
for (const auto& i: fMsgInputs)
{
inputChannelKeys.push_back(i.first);
}
for (const auto& i: fMultipartInputs)
{
inputChannelKeys.push_back(i.first);
}
unique_ptr<FairMQPoller> poller(fTransportFactory->CreatePoller(fChannels, inputChannelKeys));
while (CheckCurrentState(RUNNING) && !exitingRunningCallback)
{
poller->Poll(200);
for (const auto& mi : fMsgInputs)
{
for (unsigned int i = 0; i < fChannels.at(mi.first).size(); ++i)
{
if (poller->CheckInput(mi.first, i))
{
unique_ptr<FairMQMessage> msg(NewMessage());
if (Receive(msg, mi.first, i) >= 0)
{
if (mi.second(msg, i) == false)
{
exitingRunningCallback = true;
break;
}
}
else
{
exitingRunningCallback = true;
break;
}
}
}
if (exitingRunningCallback)
{
break;
}
}
for (const auto& mi : fMultipartInputs)
{
for (unsigned int i = 0; i < fChannels.at(mi.first).size(); ++i)
{
if (poller->CheckInput(mi.first, i))
{
FairMQParts parts;
if (Receive(parts, mi.first, i) >= 0)
{
if (mi.second(parts, i) == false)
{
exitingRunningCallback = true;
break;
}
}
else
{
exitingRunningCallback = true;
break;
}
}
}
if (exitingRunningCallback)
{
break;
}
}
}
}
else
{
while (CheckCurrentState(RUNNING) && ConditionalRun())
{
}
Run();
}
PostRun();
}
catch (const out_of_range& oor)
{
@ -477,6 +533,19 @@ void FairMQDevice::Run()
{
}
void FairMQDevice::PreRun()
{
}
bool FairMQDevice::ConditionalRun()
{
return false;
}
void FairMQDevice::PostRun()
{
}
void FairMQDevice::Pause()
{
while (true)
@ -656,18 +725,22 @@ void FairMQDevice::LogSocketRates()
int numFilteredSockets = 0;
vector<FairMQSocket*> filteredSockets;
vector<string> filteredChannelNames;
vector<int> logIntervals;
vector<int> intervalCounters;
// iterate over the channels map
for (auto mi = fChannels.begin(); mi != fChannels.end(); ++mi)
for (const auto& mi : fChannels)
{
// iterate over the channels vector
for (auto vi = (mi->second).begin(); vi != (mi->second).end(); ++vi)
for (auto vi = (mi.second).begin(); vi != (mi.second).end(); ++vi)
{
if (vi->fRateLogging == 1)
if (vi->fRateLogging > 0)
{
filteredSockets.push_back(vi->fSocket);
logIntervals.push_back(vi->fRateLogging);
intervalCounters.push_back(0);
stringstream ss;
ss << mi->first << "[" << vi - (mi->second).begin() << "]";
ss << mi.first << "[" << vi - (mi.second).begin() << "]";
filteredChannelNames.push_back(ss.str());
++numFilteredSockets;
}
@ -690,12 +763,12 @@ void FairMQDevice::LogSocketRates()
vector<double> msgPerSecOut(numFilteredSockets);
int i = 0;
for (auto itr = filteredSockets.begin(); itr != filteredSockets.end(); ++itr)
for (const auto& vi : filteredSockets)
{
bytesIn.at(i) = (*itr)->GetBytesRx();
bytesOut.at(i) = (*itr)->GetBytesTx();
msgIn.at(i) = (*itr)->GetMessagesRx();
msgOut.at(i) = (*itr)->GetMessagesTx();
bytesIn.at(i) = vi->GetBytesRx();
bytesOut.at(i) = vi->GetBytesTx();
msgIn.at(i) = vi->GetMessagesRx();
msgOut.at(i) = vi->GetMessagesTx();
++i;
}
@ -711,33 +784,40 @@ void FairMQDevice::LogSocketRates()
i = 0;
for (auto itr = filteredSockets.begin(); itr != filteredSockets.end(); itr++)
for (const auto& vi : filteredSockets)
{
bytesInNew.at(i) = (*itr)->GetBytesRx();
mbPerSecIn.at(i) = (static_cast<double>(bytesInNew.at(i) - bytesIn.at(i)) / (1024. * 1024.)) / static_cast<double>(msSinceLastLog) * 1000.;
bytesIn.at(i) = bytesInNew.at(i);
intervalCounters.at(i)++;
msgInNew.at(i) = (*itr)->GetMessagesRx();
msgPerSecIn.at(i) = static_cast<double>(msgInNew.at(i) - msgIn.at(i)) / static_cast<double>(msSinceLastLog) * 1000.;
msgIn.at(i) = msgInNew.at(i);
if (intervalCounters.at(i) == logIntervals.at(i))
{
intervalCounters.at(i) = 0;
bytesOutNew.at(i) = (*itr)->GetBytesTx();
mbPerSecOut.at(i) = (static_cast<double>(bytesOutNew.at(i) - bytesOut.at(i)) / (1024. * 1024.)) / static_cast<double>(msSinceLastLog) * 1000.;
bytesOut.at(i) = bytesOutNew.at(i);
bytesInNew.at(i) = vi->GetBytesRx();
mbPerSecIn.at(i) = (static_cast<double>(bytesInNew.at(i) - bytesIn.at(i)) / (1024. * 1024.)) / static_cast<double>(msSinceLastLog) * 1000.;
bytesIn.at(i) = bytesInNew.at(i);
msgOutNew.at(i) = (*itr)->GetMessagesTx();
msgPerSecOut.at(i) = static_cast<double>(msgOutNew.at(i) - msgOut.at(i)) / static_cast<double>(msSinceLastLog) * 1000.;
msgOut.at(i) = msgOutNew.at(i);
msgInNew.at(i) = vi->GetMessagesRx();
msgPerSecIn.at(i) = static_cast<double>(msgInNew.at(i) - msgIn.at(i)) / static_cast<double>(msSinceLastLog) * 1000.;
msgIn.at(i) = msgInNew.at(i);
LOG(DEBUG) << filteredChannelNames.at(i) << ": "
<< "in: " << msgPerSecIn.at(i) << " msg (" << mbPerSecIn.at(i) << " MB), "
<< "out: " << msgPerSecOut.at(i) << " msg (" << mbPerSecOut.at(i) << " MB)";
bytesOutNew.at(i) = vi->GetBytesTx();
mbPerSecOut.at(i) = (static_cast<double>(bytesOutNew.at(i) - bytesOut.at(i)) / (1024. * 1024.)) / static_cast<double>(msSinceLastLog) * 1000.;
bytesOut.at(i) = bytesOutNew.at(i);
msgOutNew.at(i) = vi->GetMessagesTx();
msgPerSecOut.at(i) = static_cast<double>(msgOutNew.at(i) - msgOut.at(i)) / static_cast<double>(msSinceLastLog) * 1000.;
msgOut.at(i) = msgOutNew.at(i);
LOG(DEBUG) << filteredChannelNames.at(i) << ": "
<< "in: " << msgPerSecIn.at(i) << " msg (" << mbPerSecIn.at(i) << " MB), "
<< "out: " << msgPerSecOut.at(i) << " msg (" << mbPerSecOut.at(i) << " MB)";
}
++i;
}
t0 = t1;
boost::this_thread::sleep(boost::posix_time::milliseconds(fLogIntervalInMs));
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
}
catch (boost::thread_interrupted&)
{
@ -751,7 +831,7 @@ void FairMQDevice::LogSocketRates()
void FairMQDevice::InteractiveStateLoop()
{
fRunning = true;
fInteractiveRunning = true;
char c; // hold the user console input
pollfd cinfd[1];
cinfd[0].fd = fileno(stdin);
@ -764,11 +844,11 @@ void FairMQDevice::InteractiveStateLoop()
PrintInteractiveStateLoopHelp();
while (fRunning)
while (fInteractiveRunning)
{
if (poll(cinfd, 1, 500))
{
if (!fRunning)
if (!fInteractiveRunning)
{
break;
}
@ -815,11 +895,23 @@ void FairMQDevice::InteractiveStateLoop()
// break;
case 'q':
LOG(INFO) << "[q] end";
ChangeState(STOP);
ChangeState(RESET_TASK);
WaitForEndOfState(RESET_TASK);
ChangeState(RESET_DEVICE);
WaitForEndOfState(RESET_DEVICE);
ChangeState(END);
if (CheckCurrentState("EXITING"))
{
fRunning = false;
fInteractiveRunning = false;
}
LOG(INFO) << "Exiting.";
break;
default:
LOG(INFO) << "Invalid input: [" << c << "]";
@ -836,6 +928,7 @@ void FairMQDevice::InteractiveStateLoop()
void FairMQDevice::Unblock()
{
FairMQChannel::fInterrupted = true;
FairMQMessage* cmd = fTransportFactory->CreateMessage();
fCmdSocket->Send(cmd, 0);
delete cmd;
@ -872,21 +965,21 @@ void FairMQDevice::ResetWrapper()
void FairMQDevice::Reset()
{
// iterate over the channels map
for (auto mi = fChannels.begin(); mi != fChannels.end(); ++mi)
for (auto& mi : fChannels)
{
// iterate over the channels vector
for (auto vi = (mi->second).begin(); vi != (mi->second).end(); ++vi)
for (auto& vi : mi.second)
{
vi->fSocket->Close();
delete vi->fSocket;
vi->fSocket = nullptr;
vi.fSocket->Close();
delete vi.fSocket;
vi.fSocket = nullptr;
delete vi->fPoller;
vi->fPoller = nullptr;
delete vi.fPoller;
vi.fPoller = nullptr;
vi->fCmdSocket->Close();
delete vi->fCmdSocket;
vi->fCmdSocket = nullptr;
vi.fCmdSocket->Close();
delete vi.fCmdSocket;
vi.fCmdSocket = nullptr;
}
}
}
@ -905,18 +998,18 @@ void FairMQDevice::Shutdown()
LOG(DEBUG) << "Closing sockets...";
// iterate over the channels map
for (auto mi = fChannels.begin(); mi != fChannels.end(); ++mi)
for (const auto& mi : fChannels)
{
// iterate over the channels vector
for (auto vi = (mi->second).begin(); vi != (mi->second).end(); ++vi)
for (const auto& vi : mi.second)
{
if (vi->fSocket)
if (vi.fSocket)
{
vi->fSocket->Close();
vi.fSocket->Close();
}
if (vi->fCmdSocket)
if (vi.fCmdSocket)
{
vi->fCmdSocket->Close();
vi.fCmdSocket->Close();
}
}
}
@ -932,20 +1025,20 @@ void FairMQDevice::Shutdown()
FairMQDevice::~FairMQDevice()
{
// iterate over the channels map
for (auto mi = fChannels.begin(); mi != fChannels.end(); ++mi)
for (auto& mi : fChannels)
{
// iterate over the channels vector
for (auto vi = (mi->second).begin(); vi != (mi->second).end(); ++vi)
for (auto& vi : mi.second)
{
if (vi->fSocket)
if (vi.fSocket)
{
delete vi->fSocket;
vi->fSocket = nullptr;
delete vi.fSocket;
vi.fSocket = nullptr;
}
if (vi->fPoller)
if (vi.fPoller)
{
delete vi->fPoller;
vi->fPoller = nullptr;
delete vi.fPoller;
vi.fPoller = nullptr;
}
}
}

View File

@ -20,6 +20,7 @@
#include <string>
#include <iostream>
#include <unordered_map>
#include <functional>
#include <mutex>
#include <condition_variable>
@ -33,8 +34,19 @@
#include "FairMQMessage.h"
#include "FairMQParts.h"
typedef std::unordered_map<std::string, std::vector<FairMQChannel>> FairMQChannelMap;
typedef std::function<bool(std::unique_ptr<FairMQMessage>&, int)> InputMsgCallback;
typedef std::function<bool(FairMQParts&, int)> InputMultipartCallback;
class FairMQProgOptions;
template<typename T>
void FairMQSimpleMsgCleanup(void* /*data*/, void* hint)
{
delete static_cast<T*>(hint);
}
class FairMQDevice : public FairMQStateMachine, public FairMQConfigurable
{
friend class FairMQChannel;
@ -94,9 +106,9 @@ class FairMQDevice : public FairMQStateMachine, public FairMQConfigurable
/// @param i channel index
/// @return Number of bytes that have been queued. -2 If queueing was not possible or timed out.
/// In case of errors, returns -1.
inline int Send(const std::unique_ptr<FairMQMessage>& msg, const std::string& chan, const int i = 0) const
inline int Send(const std::unique_ptr<FairMQMessage>& msg, const std::string& chan, const int i = 0, int sndTimeoutInMs = -1) const
{
return fChannels.at(chan).at(i).Send(msg);
return fChannels.at(chan).at(i).Send(msg, sndTimeoutInMs);
}
/// Shorthand method to send `msg` on `chan` at index `i` without blocking
@ -116,9 +128,9 @@ class FairMQDevice : public FairMQStateMachine, public FairMQConfigurable
/// @param i channel index
/// @return Number of bytes that have been queued. -2 If queueing was not possible or timed out.
/// In case of errors, returns -1.
inline int64_t Send(const FairMQParts& parts, const std::string& chan, const int i = 0) const
inline int64_t Send(const FairMQParts& parts, const std::string& chan, const int i = 0, int sndTimeoutInMs = -1) const
{
return fChannels.at(chan).at(i).Send(parts.fParts);
return fChannels.at(chan).at(i).Send(parts.fParts, sndTimeoutInMs);
}
/// Shorthand method to send FairMQParts on `chan` at index `i` without blocking
@ -138,9 +150,9 @@ class FairMQDevice : public FairMQStateMachine, public FairMQConfigurable
/// @param i channel index
/// @return 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.
inline int Receive(const std::unique_ptr<FairMQMessage>& msg, const std::string& chan, const int i = 0) const
inline int Receive(const std::unique_ptr<FairMQMessage>& msg, const std::string& chan, const int i = 0, int rcvTimeoutInMs = -1) const
{
return fChannels.at(chan).at(i).Receive(msg);
return fChannels.at(chan).at(i).Receive(msg, rcvTimeoutInMs);
}
/// Shorthand method to receive `msg` on `chan` at index `i` without blocking
@ -160,9 +172,9 @@ class FairMQDevice : public FairMQStateMachine, public FairMQConfigurable
/// @param i channel index
/// @return 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.
inline int64_t Receive(FairMQParts& parts, const std::string& chan, const int i = 0) const
inline int64_t Receive(FairMQParts& parts, const std::string& chan, const int i = 0, int rcvTimeoutInMs = -1) const
{
return fChannels.at(chan).at(i).Receive(parts.fParts);
return fChannels.at(chan).at(i).Receive(parts.fParts, rcvTimeoutInMs);
}
/// Shorthand method to receive FairMQParts on `chan` at index `i` without blocking
@ -176,6 +188,13 @@ class FairMQDevice : public FairMQStateMachine, public FairMQConfigurable
return fChannels.at(chan).at(i).ReceiveAsync(parts.fParts);
}
/// @brief Create FairMQPoller
/// @return pointer to FairMQPoller
inline FairMQPoller* NewPoller(const std::initializer_list<std::string> channelList) const
{
return fTransportFactory->CreatePoller(fChannels, channelList);
}
/// @brief Create empty FairMQMessage
/// @return pointer to FairMQMessage
inline FairMQMessage* NewMessage() const
@ -202,6 +221,26 @@ class FairMQDevice : public FairMQStateMachine, public FairMQConfigurable
return fTransportFactory->CreateMessage(data, size, ffn, hint);
}
template<typename T>
inline FairMQMessage* NewSimpleMessage(const T& data) const
{
T* dataCopy = new T(data);
return fTransportFactory->CreateMessage(dataCopy, sizeof(T), FairMQSimpleMsgCleanup<T>, dataCopy);
}
template<std::size_t N>
inline FairMQMessage* NewSimpleMessage(const char(&data)[N]) const
{
std::string* msgStr = new std::string(data);
return fTransportFactory->CreateMessage(const_cast<char*>(msgStr->c_str()), msgStr->length(), FairMQSimpleMsgCleanup<std::string>, msgStr);
}
inline FairMQMessage* NewSimpleMessage(const std::string& str) const
{
std::string* msgStr = new std::string(str);
return fTransportFactory->CreateMessage(const_cast<char*>(msgStr->c_str()), msgStr->length(), FairMQSimpleMsgCleanup<std::string>, msgStr);
}
/// Waits for the first initialization run to finish
void WaitForInitialValidation();
@ -255,8 +294,32 @@ class FairMQDevice : public FairMQStateMachine, public FairMQConfigurable
/// @param rhs Left hand side value for comparison
static bool SortSocketsByAddress(const FairMQChannel &lhs, const FairMQChannel &rhs);
// TODO: make this const?
std::unordered_map<std::string, std::vector<FairMQChannel>> fChannels; ///< Device channels
FairMQProgOptions* fConfig; ///< Program options configuration
template<class T>
void OnData(const std::string& channelName, bool (T::* memberFunction)(std::unique_ptr<FairMQMessage>& msg, int index))
{
fDataCallbacks = true;
fMsgInputs.insert(std::make_pair(channelName, [this, memberFunction](std::unique_ptr<FairMQMessage>& msg, int index)
{
return (static_cast<T*>(this)->*memberFunction)(msg, index);
}));
}
void OnData(const std::string& channelName, InputMsgCallback);
template<class T>
void OnData(const std::string& channelName, bool (T::* memberFunction)(FairMQParts& parts, int index))
{
fDataCallbacks = true;
fMultipartInputs.insert(std::make_pair(channelName, [this, memberFunction](FairMQParts& parts, int index)
{
return (static_cast<T*>(this)->*memberFunction)(parts, index);
}));
}
void OnData(const std::string& channelName, InputMultipartCallback);
protected:
std::string fId; ///< Device ID
@ -274,7 +337,6 @@ class FairMQDevice : public FairMQStateMachine, public FairMQConfigurable
FairMQSocket* fCmdSocket; ///< Socket used for the internal unblocking mechanism
FairMQTransportFactory* fTransportFactory; ///< Transport factory
FairMQProgOptions* fConfig; ///< Program options configuration
/// Additional user initialization (can be overloaded in child classes). Prefer to use InitTask().
virtual void Init();
@ -285,6 +347,15 @@ class FairMQDevice : public FairMQStateMachine, public FairMQConfigurable
/// Runs the device (to be overloaded in child classes)
virtual void Run();
/// Called in the RUNNING state once before executing the Run()/ConditionalRun() method
virtual void PreRun();
/// Called during RUNNING state repeatedly until it returns false or device state changes
virtual bool ConditionalRun();
/// Called in the RUNNING state once after executing the Run()/ConditionalRun() method
virtual void PostRun();
/// Handles the PAUSE state
virtual void Pause();
@ -330,9 +401,13 @@ class FairMQDevice : public FairMQStateMachine, public FairMQConfigurable
/// Signal handler
void SignalHandler(int signal);
bool fCatchingSignals;
bool fTerminated;
bool fTerminationRequested;
// Interactive state loop helper
std::atomic<bool> fRunning;
std::atomic<bool> fInteractiveRunning;
bool fDataCallbacks;
std::unordered_map<std::string, InputMsgCallback> fMsgInputs;
std::unordered_map<std::string, InputMultipartCallback> fMultipartInputs;
};
#endif /* FAIRMQDEVICE_H_ */

View File

@ -39,4 +39,6 @@ class FairMQMessage
virtual ~FairMQMessage() {};
};
using FairMQMessagePtr = std::unique_ptr<FairMQMessage>;
#endif /* FAIRMQMESSAGE_H_ */

View File

@ -31,7 +31,10 @@
// This #define has to be before any msm header includes
#define FUSION_MAX_VECTOR_SIZE 20
#include <boost/mpl/for_each.hpp>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/back/tools.hpp>
#include <boost/msm/back/metafunctions.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
@ -233,7 +236,7 @@ struct FairMQFSM_ : public msm::front::state_machine_def<FairMQFSM_>
template <class EVT, class FSM, class SourceState, class TargetState>
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
{
LOG(STATE) << "Received STOP event";
LOG(STATE) << "Entering READY state";
fsm.fState = READY;
@ -288,7 +291,7 @@ struct FairMQFSM_ : public msm::front::state_machine_def<FairMQFSM_>
template <class EVT, class FSM, class SourceState, class TargetState>
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
{
LOG(STATE) << "Received END event";
LOG(STATE) << "Entering EXITING state";
fsm.fState = EXITING;
@ -321,7 +324,7 @@ struct FairMQFSM_ : public msm::front::state_machine_def<FairMQFSM_>
template <class EVT, class FSM, class SourceState, class TargetState>
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
{
LOG(STATE) << "ERROR!";
LOG(STATE) << "Entering ERROR state";
fsm.fState = ERROR;
}
@ -348,20 +351,20 @@ struct FairMQFSM_ : public msm::front::state_machine_def<FairMQFSM_>
// Start Event Next Action Guard
// +------------------------+----------------------+------------------------+----------------+---------+
msmf::Row<IDLE_FSM, INIT_DEVICE, INITIALIZING_DEVICE_FSM, InitDeviceFct, msmf::none>,
msmf::Row<IDLE_FSM, END, EXITING_FSM, ExitingFct, msmf::none>,
msmf::Row<INITIALIZING_DEVICE_FSM, internal_DEVICE_READY, DEVICE_READY_FSM, DeviceReadyFct, msmf::none>,
msmf::Row<DEVICE_READY_FSM, INIT_TASK, INITIALIZING_TASK_FSM, InitTaskFct, msmf::none>,
msmf::Row<DEVICE_READY_FSM, RESET_DEVICE, RESETTING_DEVICE_FSM, ResetDeviceFct, msmf::none>,
msmf::Row<INITIALIZING_TASK_FSM, internal_READY, READY_FSM, ReadyFct, msmf::none>,
msmf::Row<READY_FSM, RUN, RUNNING_FSM, RunFct, msmf::none>,
msmf::Row<READY_FSM, RESET_TASK, RESETTING_TASK_FSM, ResetTaskFct, msmf::none>,
msmf::Row<RUNNING_FSM, PAUSE, PAUSED_FSM, PauseFct, msmf::none>,
msmf::Row<PAUSED_FSM, RUN, RUNNING_FSM, ResumeFct, msmf::none>,
msmf::Row<RUNNING_FSM, STOP, READY_FSM, StopFct, msmf::none>,
msmf::Row<RUNNING_FSM, internal_READY, READY_FSM, InternalStopFct, msmf::none>,
msmf::Row<READY_FSM, RESET_TASK, RESETTING_TASK_FSM, ResetTaskFct, msmf::none>,
msmf::Row<RESETTING_TASK_FSM, internal_DEVICE_READY, DEVICE_READY_FSM, DeviceReadyFct, msmf::none>,
msmf::Row<DEVICE_READY_FSM, RESET_DEVICE, RESETTING_DEVICE_FSM, ResetDeviceFct, msmf::none>,
msmf::Row<RESETTING_DEVICE_FSM, internal_IDLE, IDLE_FSM, IdleFct, msmf::none>,
msmf::Row<RUNNING_FSM, END, EXITING_FSM, ExitingRunFct, msmf::none>,
msmf::Row<IDLE_FSM, END, EXITING_FSM, ExitingFct, msmf::none>,
msmf::Row<PAUSED_FSM, RUN, RUNNING_FSM, ResumeFct, msmf::none>,
msmf::Row<RESETTING_TASK_FSM, internal_DEVICE_READY, DEVICE_READY_FSM, DeviceReadyFct, msmf::none>,
msmf::Row<RESETTING_DEVICE_FSM, internal_IDLE, IDLE_FSM, IdleFct, msmf::none>,
msmf::Row<OK_FSM, ERROR_FOUND, ERROR_FSM, ErrorFoundFct, msmf::none>>
{};
@ -369,7 +372,25 @@ struct FairMQFSM_ : public msm::front::state_machine_def<FairMQFSM_>
template <class FSM, class Event>
void no_transition(Event const& e, FSM&, int state)
{
LOG(STATE) << "no transition from state " << GetStateName(state) << " (" << state << ") on event " << e.name();
typedef typename boost::msm::back::recursive_get_transition_table<FSM>::type recursive_stt;
typedef typename boost::msm::back::generate_state_set<recursive_stt>::type all_states;
std::string stateName;
boost::mpl::for_each<all_states,boost::msm::wrap<boost::mpl::placeholders::_1> >(boost::msm::back::get_state_name<recursive_stt>(stateName, state));
stateName = stateName.substr(24);
std::size_t pos = stateName.find("_FSME");
stateName.erase(pos);
if (stateName == "1RUNNING" || stateName == "6DEVICE_READY" || stateName == "0PAUSED")
{
stateName = stateName.substr(1);
}
if (stateName != "OK")
{
LOG(STATE) << "No transition from state " << stateName << " on event " << e.name();
}
// LOG(STATE) << "no transition from state " << GetStateName(state) << " (" << state << ") on event " << e.name();
}
// backward compatibility to FairMQStateMachine
@ -461,7 +482,7 @@ struct FairMQFSM_ : public msm::front::state_machine_def<FairMQFSM_>
boost::thread fTerminateStateThread;
// condition variable to notify parent thread about end of state.
bool fStateFinished;
std::atomic<bool> fStateFinished;
boost::condition_variable fStateCondition;
boost::mutex fStateMutex;

View File

@ -30,15 +30,15 @@ class FairMQChannel;
class FairMQTransportFactory
{
public:
virtual FairMQMessage* CreateMessage() = 0;
virtual FairMQMessage* CreateMessage(const size_t size) = 0;
virtual FairMQMessage* CreateMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint = NULL) = 0;
virtual FairMQMessage* CreateMessage() const = 0;
virtual FairMQMessage* CreateMessage(const size_t size) const = 0;
virtual FairMQMessage* CreateMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint = NULL) const = 0;
virtual FairMQSocket* CreateSocket(const std::string& type, const std::string& name, const int numIoThreads, const std::string& id = "") = 0;
virtual FairMQSocket* CreateSocket(const std::string& type, const std::string& name, const int numIoThreads, const std::string& id = "") const = 0;
virtual FairMQPoller* CreatePoller(const std::vector<FairMQChannel>& channels) = 0;
virtual FairMQPoller* CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::initializer_list<std::string> channelList) = 0;
virtual FairMQPoller* CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket) = 0;
virtual FairMQPoller* CreatePoller(const std::vector<FairMQChannel>& channels) const = 0;
virtual FairMQPoller* CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::vector<std::string>& channelList) const = 0;
virtual FairMQPoller* CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket) const = 0;
virtual ~FairMQTransportFactory() {};
};

View File

@ -35,8 +35,33 @@ The communication layer is available through an interface. Two interface impleme
![FairMQ transport interface](../docs/images/fairmq-transport-interface.png?raw=true "FairMQ transport interface")
## State Machine
Each FairMQ device has an internal state machine:
![FairMQ state machine](../docs/images/fairmq-states.png?raw=true "FairMQ state machine")
The state machine can be querried and controlled via `GetCurrentStateName()` and `ChangeState("<state name>")` methods. Only legal state transitions are allowed (see image above). Illegal transitions will fail with an error.
If the device is running in interactive mode (default), states can be changed via keyboard input:
- `'h'` - help
- `'p'` - pause
- `'r'` - run
- `'s'` - stop
- `'t'` - reset task
- `'d'` - reset device
- `'q'` - end
- `'j'` - init task
- `'i'` - init device
Without the interactive mode, for example for a run in background, two other control mechanisms are available:
- static (`--control static`) - device goes through a simple init -> run -> reset -> exit chain.
- dds (`--control dds`) - device is controled by external command, in this case using dds commands (fairmq-dds-command-ui).
## Examples
A collection of simple examples in `examples` directory demonstrates some common usage patterns of FairMQ.
A collection of simple examples in `FairRoot/examples/MQ` directory demonstrates some common usage patterns of FairMQ.
A number of devices to handle the data from the Tutorial3 FairTestDetector of FairRoot are provided as an example and can be found in `FairRoot/base/MQ` directory. The implementation of the tasks run by these devices can be found `FairRoot/example/Tutorial3`. The implementation includes sending raw binary data as well as serializing the data with either [Boost Serialization](http://www.boost.org/doc/libs/release/libs/serialization/), [Google Protocol Buffers](https://developers.google.com/protocol-buffers/) or [Root TMessage](http://root.cern.ch/root/html/TMessage.html). Following the examples you can implement your own devices to transport arbitrary data.
A number of devices to handle the data from the Tutorial3 FairTestDetector of FairRoot are provided as an example and can be found in `FairRoot/base/MQ` directory. The implementation of the tasks run by these devices can be found `FairRoot/examples/advanced/Tutorial3`. The implementation includes sending raw binary data as well as serializing the data with either [Boost Serialization](http://www.boost.org/doc/libs/release/libs/serialization/), [Google Protocol Buffers](https://developers.google.com/protocol-buffers/) or [Root TMessage](http://root.cern.ch/root/html/TMessage.html). Following the examples you can implement your own devices to transport arbitrary data.

View File

@ -20,6 +20,7 @@
#include "FairMQBenchmarkSampler.h"
#include "FairMQLogger.h"
#include "FairMQProgOptions.h"
using namespace std;
@ -28,6 +29,7 @@ FairMQBenchmarkSampler::FairMQBenchmarkSampler()
, fNumMsgs(0)
, fMsgCounter(0)
, fMsgRate(1)
, fOutChannelName()
{
}
@ -35,146 +37,79 @@ FairMQBenchmarkSampler::~FairMQBenchmarkSampler()
{
}
void FairMQBenchmarkSampler::InitTask()
{
fMsgSize = fConfig->GetValue<int>("msg-size");
fNumMsgs = fConfig->GetValue<int>("num-msgs");
fMsgRate = fConfig->GetValue<int>("msg-rate");
fOutChannelName = fConfig->GetValue<string>("out-channel");
}
void FairMQBenchmarkSampler::Run()
{
boost::thread resetMsgCounter(boost::bind(&FairMQBenchmarkSampler::ResetMsgCounter, this));
// boost::thread resetMsgCounter(boost::bind(&FairMQBenchmarkSampler::ResetMsgCounter, this));
int numSentMsgs = 0;
unique_ptr<FairMQMessage> baseMsg(fTransportFactory->CreateMessage(fMsgSize));
FairMQMessagePtr baseMsg(fTransportFactory->CreateMessage(fMsgSize));
// store the channel reference to avoid traversing the map on every loop iteration
const FairMQChannel& dataOutChannel = fChannels.at("data-out").at(0);
const FairMQChannel& dataOutChannel = fChannels.at(fOutChannelName).at(0);
LOG(INFO) << "Starting the benchmark with message size of " << fMsgSize << " and number of messages " << fNumMsgs << ".";
boost::timer::auto_cpu_timer timer;
while (CheckCurrentState(RUNNING))
{
unique_ptr<FairMQMessage> msg(fTransportFactory->CreateMessage());
FairMQMessagePtr msg(fTransportFactory->CreateMessage());
msg->Copy(baseMsg);
if (dataOutChannel.Send(msg) >= 0)
{
if (fNumMsgs > 0)
{
numSentMsgs++;
if (numSentMsgs >= fNumMsgs)
if (++numSentMsgs >= fNumMsgs)
{
break;
}
}
}
--fMsgCounter;
// --fMsgCounter;
while (fMsgCounter == 0) {
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
}
// while (fMsgCounter == 0) {
// boost::this_thread::sleep(boost::posix_time::milliseconds(1));
// }
}
LOG(INFO) << "Sent " << numSentMsgs << " messages, leaving RUNNING state.";
LOG(INFO) << "Sending time: ";
try
{
resetMsgCounter.interrupt();
resetMsgCounter.join();
}
catch(boost::thread_resource_error& e)
{
LOG(ERROR) << e.what();
exit(EXIT_FAILURE);
}
// try
// {
// resetMsgCounter.interrupt();
// resetMsgCounter.join();
// }
// catch(boost::thread_resource_error& e)
// {
// LOG(ERROR) << e.what();
// exit(EXIT_FAILURE);
// }
}
void FairMQBenchmarkSampler::ResetMsgCounter()
{
while (true) {
try {
fMsgCounter = fMsgRate / 100;
boost::this_thread::sleep(boost::posix_time::milliseconds(10));
} catch (boost::thread_interrupted&) {
LOG(DEBUG) << "Event rate limiter thread interrupted";
break;
}
}
}
void FairMQBenchmarkSampler::SetProperty(const int key, const string& value)
{
switch (key)
while (true)
{
default:
FairMQDevice::SetProperty(key, value);
try
{
fMsgCounter = fMsgRate / 100;
boost::this_thread::sleep(boost::posix_time::milliseconds(10));
}
catch (boost::thread_interrupted&)
{
LOG(DEBUG) << "Event rate limiter thread interrupted";
break;
}
}
}
string FairMQBenchmarkSampler::GetProperty(const int key, const string& default_ /*= ""*/)
{
switch (key)
{
default:
return FairMQDevice::GetProperty(key, default_);
}
}
void FairMQBenchmarkSampler::SetProperty(const int key, const int value)
{
switch (key)
{
case MsgSize:
fMsgSize = value;
break;
case MsgRate:
fMsgRate = value;
break;
case NumMsgs:
fNumMsgs = value;
break;
default:
FairMQDevice::SetProperty(key, value);
break;
}
}
int FairMQBenchmarkSampler::GetProperty(const int key, const int default_ /*= 0*/)
{
switch (key)
{
case MsgSize:
return fMsgSize;
case MsgRate:
return fMsgRate;
case NumMsgs:
return fNumMsgs;
default:
return FairMQDevice::GetProperty(key, default_);
}
}
string FairMQBenchmarkSampler::GetPropertyDescription(const int key)
{
switch (key)
{
case MsgSize:
return "MsgSize: Size of the transfered message buffer.";
case NumMsgs:
return "NumMsgs: Number of messages to send.";
case MsgRate:
return "MsgRate: Maximum msg rate.";
default:
return FairMQDevice::GetPropertyDescription(key);
}
}
void FairMQBenchmarkSampler::ListProperties()
{
LOG(INFO) << "Properties of FairMQBenchmarkSampler:";
for (int p = FairMQConfigurable::Last; p < FairMQBenchmarkSampler::Last; ++p)
{
LOG(INFO) << " " << GetPropertyDescription(p);
}
LOG(INFO) << "---------------------------";
}

View File

@ -26,33 +26,19 @@
class FairMQBenchmarkSampler : public FairMQDevice
{
public:
enum
{
MsgSize = FairMQDevice::Last,
NumMsgs,
MsgRate,
Last
};
FairMQBenchmarkSampler();
virtual ~FairMQBenchmarkSampler();
void ResetMsgCounter();
virtual void SetProperty(const int key, const std::string& value);
virtual std::string GetProperty(const int key, const std::string& default_ = "");
virtual void SetProperty(const int key, const int value);
virtual int GetProperty(const int key, const int default_ = 0);
virtual std::string GetPropertyDescription(const int key);
virtual void ListProperties();
protected:
int fMsgSize;
int fNumMsgs;
int fMsgCounter;
int fMsgRate;
std::string fOutChannelName;
virtual void InitTask();
virtual void Run();
};

View File

@ -12,17 +12,17 @@
* @author D. Klein, A. Rybalchenko
*/
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include "FairMQLogger.h"
#include "FairMQMerger.h"
#include "FairMQPoller.h"
#include "FairMQProgOptions.h"
using namespace std;
FairMQMerger::FairMQMerger()
: fMultipart(1)
, fInChannelName()
, fOutChannelName()
{
}
@ -30,11 +30,18 @@ FairMQMerger::~FairMQMerger()
{
}
void FairMQMerger::InitTask()
{
fMultipart = fConfig->GetValue<int>("multipart");
fInChannelName = fConfig->GetValue<string>("in-channel");
fOutChannelName = fConfig->GetValue<string>("out-channel");
}
void FairMQMerger::Run()
{
int numInputs = fChannels.at("data-in").size();
int numInputs = fChannels.at(fInChannelName).size();
std::unique_ptr<FairMQPoller> poller(fTransportFactory->CreatePoller(fChannels.at("data-in")));
std::unique_ptr<FairMQPoller> poller(fTransportFactory->CreatePoller(fChannels.at(fInChannelName)));
if (fMultipart)
{
@ -50,9 +57,9 @@ void FairMQMerger::Run()
{
FairMQParts payload;
if (Receive(payload, "data-in", i) >= 0)
if (Receive(payload, fInChannelName, i) >= 0)
{
if (Send(payload, "data-out") < 0)
if (Send(payload, fOutChannelName) < 0)
{
LOG(DEBUG) << "Transfer interrupted";
break;
@ -79,11 +86,11 @@ void FairMQMerger::Run()
// Check if the channel has data ready to be received.
if (poller->CheckInput(i))
{
unique_ptr<FairMQMessage> payload(fTransportFactory->CreateMessage());
FairMQMessagePtr payload(fTransportFactory->CreateMessage());
if (Receive(payload, "data-in", i) >= 0)
if (Receive(payload, fInChannelName, i) >= 0)
{
if (Send(payload, "data-out") < 0)
if (Send(payload, fOutChannelName) < 0)
{
LOG(DEBUG) << "Transfer interrupted";
break;
@ -99,67 +106,3 @@ void FairMQMerger::Run()
}
}
}
void FairMQMerger::SetProperty(const int key, const string& value)
{
switch (key)
{
default:
FairMQDevice::SetProperty(key, value);
break;
}
}
string FairMQMerger::GetProperty(const int key, const string& default_ /*= ""*/)
{
switch (key)
{
default:
return FairMQDevice::GetProperty(key, default_);
}
}
void FairMQMerger::SetProperty(const int key, const int value)
{
switch (key)
{
case Multipart:
fMultipart = value;
break;
default:
FairMQDevice::SetProperty(key, value);
break;
}
}
int FairMQMerger::GetProperty(const int key, const int default_ /*= 0*/)
{
switch (key)
{
case Multipart:
return fMultipart;
default:
return FairMQDevice::GetProperty(key, default_);
}
}
string FairMQMerger::GetPropertyDescription(const int key)
{
switch (key)
{
case Multipart:
return "Multipart: Handle payloads as multipart messages.";
default:
return FairMQDevice::GetPropertyDescription(key);
}
}
void FairMQMerger::ListProperties()
{
LOG(INFO) << "Properties of FairMQMerger:";
for (int p = FairMQConfigurable::Last; p < FairMQMerger::Last; ++p)
{
LOG(INFO) << " " << GetPropertyDescription(p);
}
LOG(INFO) << "---------------------------";
}

View File

@ -17,30 +17,21 @@
#include "FairMQDevice.h"
#include <string>
class FairMQMerger : public FairMQDevice
{
public:
enum
{
Multipart = FairMQDevice::Last,
Last
};
FairMQMerger();
virtual ~FairMQMerger();
virtual void SetProperty(const int key, const std::string& value);
virtual std::string GetProperty(const int key, const std::string& default_ = "");
virtual void SetProperty(const int key, const int value);
virtual int GetProperty(const int key, const int default_ = 0);
virtual std::string GetPropertyDescription(const int key);
virtual void ListProperties();
protected:
int fMultipart;
std::string fInChannelName;
std::string fOutChannelName;
virtual void Run();
virtual void InitTask();
};
#endif /* FAIRMQMERGER_H_ */

View File

@ -0,0 +1,110 @@
/********************************************************************************
* 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" *
********************************************************************************/
#include "FairMQLogger.h"
#include "FairMQMultiplier.h"
#include "FairMQProgOptions.h"
using namespace std;
FairMQMultiplier::FairMQMultiplier()
: fMultipart(1)
, fNumOutputs(0)
, fInChannelName()
, fOutChannelNames()
{
}
FairMQMultiplier::~FairMQMultiplier()
{
}
void FairMQMultiplier::InitTask()
{
fMultipart = fConfig->GetValue<int>("multipart");
fInChannelName = fConfig->GetValue<string>("in-channel");
fOutChannelNames = fConfig->GetValue<vector<string>>("out-channel");
fNumOutputs = fChannels.at(fOutChannelNames.at(0)).size();
if (fMultipart)
{
OnData(fInChannelName, &FairMQMultiplier::HandleMultipartData);
}
else
{
OnData(fInChannelName, &FairMQMultiplier::HandleSingleData);
}
}
bool FairMQMultiplier::HandleSingleData(std::unique_ptr<FairMQMessage>& payload, int /*index*/)
{
for (unsigned int i = 0; i < fOutChannelNames.size() - 1; ++i) // all except last channel
{
for (unsigned int j = 0; j < fChannels.at(fOutChannelNames.at(i)).size(); ++j) // all subChannels in a channel
{
FairMQMessagePtr msgCopy(fTransportFactory->CreateMessage());
msgCopy->Copy(payload);
Send(msgCopy, fOutChannelNames.at(i), j);
}
}
unsigned int lastChannelSize = fChannels.at(fOutChannelNames.back()).size();
for (unsigned int i = 0; i < lastChannelSize - 1; ++i) // iterate over all except last subChannels of the last channel
{
FairMQMessagePtr msgCopy(fTransportFactory->CreateMessage());
msgCopy->Copy(payload);
Send(msgCopy, fOutChannelNames.back(), i);
}
Send(payload, fOutChannelNames.back(), lastChannelSize - 1); // send final message to last subChannel of last channel
return true;
}
bool FairMQMultiplier::HandleMultipartData(FairMQParts& payload, int /*index*/)
{
for (unsigned int i = 0; i < fOutChannelNames.size() - 1; ++i) // all except last channel
{
for (unsigned int j = 0; j < fChannels.at(fOutChannelNames.at(i)).size(); ++j) // all subChannels in a channel
{
FairMQParts parts;
for (int k = 0; k < payload.Size(); ++k)
{
FairMQMessagePtr msgCopy(fTransportFactory->CreateMessage());
msgCopy->Copy(payload.At(k));
parts.AddPart(msgCopy);
}
Send(parts, fOutChannelNames.at(i), j);
}
}
unsigned int lastChannelSize = fChannels.at(fOutChannelNames.back()).size();
for (unsigned int i = 0; i < lastChannelSize - 1; ++i) // iterate over all except last subChannels of the last channel
{
FairMQParts parts;
for (int k = 0; k < payload.Size(); ++k)
{
FairMQMessagePtr msgCopy(fTransportFactory->CreateMessage());
msgCopy->Copy(payload.At(k));
parts.AddPart(msgCopy);
}
Send(parts, fOutChannelNames.back(), i);
}
Send(payload, fOutChannelNames.back(), lastChannelSize - 1); // send final message to last subChannel of last channel
return true;
}

View File

@ -0,0 +1,34 @@
/********************************************************************************
* 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" *
********************************************************************************/
#ifndef FAIRMQMULTIPLIER_H_
#define FAIRMQMULTIPLIER_H_
#include "FairMQDevice.h"
#include <string>
class FairMQMultiplier : public FairMQDevice
{
public:
FairMQMultiplier();
virtual ~FairMQMultiplier();
protected:
int fMultipart;
int fNumOutputs;
std::string fInChannelName;
std::vector<std::string> fOutChannelNames;
virtual void InitTask();
bool HandleSingleData(std::unique_ptr<FairMQMessage>&, int);
bool HandleMultipartData(FairMQParts&, int);
};
#endif /* FAIRMQMULTIPLIER_H_ */

View File

@ -12,16 +12,16 @@
* @author A. Rybalchenko
*/
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include "FairMQLogger.h"
#include "FairMQProxy.h"
#include "FairMQProgOptions.h"
using namespace std;
FairMQProxy::FairMQProxy()
: fMultipart(1)
, fInChannelName()
, fOutChannelName()
{
}
@ -29,6 +29,13 @@ FairMQProxy::~FairMQProxy()
{
}
void FairMQProxy::InitTask()
{
fMultipart = fConfig->GetValue<int>("multipart");
fInChannelName = fConfig->GetValue<string>("in-channel");
fOutChannelName = fConfig->GetValue<string>("out-channel");
}
void FairMQProxy::Run()
{
if (fMultipart)
@ -36,9 +43,9 @@ void FairMQProxy::Run()
while (CheckCurrentState(RUNNING))
{
FairMQParts payload;
if (Receive(payload, "data-in") >= 0)
if (Receive(payload, fInChannelName) >= 0)
{
if (Send(payload, "data-out") < 0)
if (Send(payload, fOutChannelName) < 0)
{
LOG(DEBUG) << "Transfer interrupted";
break;
@ -56,9 +63,9 @@ void FairMQProxy::Run()
while (CheckCurrentState(RUNNING))
{
unique_ptr<FairMQMessage> payload(fTransportFactory->CreateMessage());
if (Receive(payload, "data-in") >= 0)
if (Receive(payload, fInChannelName) >= 0)
{
if (Send(payload, "data-out") < 0)
if (Send(payload, fOutChannelName) < 0)
{
LOG(DEBUG) << "Transfer interrupted";
break;

View File

@ -17,6 +17,8 @@
#include "FairMQDevice.h"
#include <string>
class FairMQProxy : public FairMQDevice
{
public:
@ -39,8 +41,11 @@ class FairMQProxy : public FairMQDevice
protected:
int fMultipart;
std::string fInChannelName;
std::string fOutChannelName;
virtual void Run();
virtual void InitTask();
};
#endif /* FAIRMQPROXY_H_ */

View File

@ -12,25 +12,31 @@
* @author D. Klein, A. Rybalchenko
*/
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/timer/timer.hpp>
#include "FairMQSink.h"
#include "FairMQLogger.h"
#include "FairMQProgOptions.h"
using namespace std;
FairMQSink::FairMQSink()
: fNumMsgs(0)
, fInChannelName()
{
}
void FairMQSink::InitTask()
{
fNumMsgs = fConfig->GetValue<int>("num-msgs");
fInChannelName = fConfig->GetValue<string>("in-channel");
}
void FairMQSink::Run()
{
int numReceivedMsgs = 0;
// store the channel reference to avoid traversing the map on every loop iteration
const FairMQChannel& dataInChannel = fChannels.at("data-in").at(0);
const FairMQChannel& dataInChannel = fChannels.at(fInChannelName).at(0);
LOG(INFO) << "Starting the benchmark and expecting to receive " << fNumMsgs << " messages.";
boost::timer::auto_cpu_timer timer;
@ -59,67 +65,3 @@ void FairMQSink::Run()
FairMQSink::~FairMQSink()
{
}
void FairMQSink::SetProperty(const int key, const string& value)
{
switch (key)
{
default:
FairMQDevice::SetProperty(key, value);
break;
}
}
string FairMQSink::GetProperty(const int key, const string& default_ /*= ""*/)
{
switch (key)
{
default:
return FairMQDevice::GetProperty(key, default_);
}
}
void FairMQSink::SetProperty(const int key, const int value)
{
switch (key)
{
case NumMsgs:
fNumMsgs = value;
break;
default:
FairMQDevice::SetProperty(key, value);
break;
}
}
int FairMQSink::GetProperty(const int key, const int default_ /*= 0*/)
{
switch (key)
{
case NumMsgs:
return fNumMsgs;
default:
return FairMQDevice::GetProperty(key, default_);
}
}
string FairMQSink::GetPropertyDescription(const int key)
{
switch (key)
{
case NumMsgs:
return "NumMsgs: Number of messages to send.";
default:
return FairMQDevice::GetPropertyDescription(key);
}
}
void FairMQSink::ListProperties()
{
LOG(INFO) << "Properties of FairMQSink:";
for (int p = FairMQConfigurable::Last; p < FairMQSink::Last; ++p)
{
LOG(INFO) << " " << GetPropertyDescription(p);
}
LOG(INFO) << "---------------------------";
}

View File

@ -22,27 +22,15 @@
class FairMQSink : public FairMQDevice
{
public:
enum
{
NumMsgs = FairMQDevice::Last,
Last
};
FairMQSink();
virtual ~FairMQSink();
virtual void SetProperty(const int key, const std::string& value);
virtual std::string GetProperty(const int key, const std::string& default_ = "");
virtual void SetProperty(const int key, const int value);
virtual int GetProperty(const int key, const int default_ = 0);
virtual std::string GetPropertyDescription(const int key);
virtual void ListProperties();
protected:
int fNumMsgs;
std::string fInChannelName;
virtual void Run();
virtual void InitTask();
};
#endif /* FAIRMQSINK_H_ */

View File

@ -12,16 +12,18 @@
* @author D. Klein, A. Rybalchenko
*/
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include "FairMQLogger.h"
#include "FairMQSplitter.h"
#include "FairMQProgOptions.h"
using namespace std;
FairMQSplitter::FairMQSplitter()
: fMultipart(1)
, fNumOutputs(0)
, fDirection(0)
, fInChannelName()
, fOutChannelName()
{
}
@ -29,129 +31,44 @@ FairMQSplitter::~FairMQSplitter()
{
}
void FairMQSplitter::Run()
void FairMQSplitter::InitTask()
{
int numOutputs = fChannels.at("data-out").size();
int direction = 0;
fMultipart = fConfig->GetValue<int>("multipart");
fInChannelName = fConfig->GetValue<string>("in-channel");
fOutChannelName = fConfig->GetValue<string>("out-channel");
fNumOutputs = fChannels.at(fOutChannelName).size();
fDirection = 0;
if (fMultipart)
{
while (CheckCurrentState(RUNNING))
{
FairMQParts payload;
if (Receive(payload, "data-in") >= 0)
{
if (Send(payload, "data-out", direction) < 0)
{
LOG(DEBUG) << "Transfer interrupted";
break;
}
}
else
{
LOG(DEBUG) << "Transfer interrupted";
break;
}
++direction;
if (direction >= numOutputs)
{
direction = 0;
}
}
OnData(fInChannelName, &FairMQSplitter::HandleMultipartData);
}
else
{
while (CheckCurrentState(RUNNING))
{
unique_ptr<FairMQMessage> payload(fTransportFactory->CreateMessage());
if (Receive(payload, "data-in") >= 0)
{
if (Send(payload, "data-out", direction) < 0)
{
LOG(DEBUG) << "Transfer interrupted";
break;
}
}
else
{
LOG(DEBUG) << "Transfer interrupted";
break;
}
++direction;
if (direction >= numOutputs)
{
direction = 0;
}
}
OnData(fInChannelName, &FairMQSplitter::HandleSingleData);
}
}
void FairMQSplitter::SetProperty(const int key, const string& value)
bool FairMQSplitter::HandleSingleData(FairMQMessagePtr& payload, int /*index*/)
{
switch (key)
Send(payload, fOutChannelName, fDirection);
if (++fDirection >= fNumOutputs)
{
default:
FairMQDevice::SetProperty(key, value);
break;
fDirection = 0;
}
return true;
}
string FairMQSplitter::GetProperty(const int key, const string& default_ /*= ""*/)
bool FairMQSplitter::HandleMultipartData(FairMQParts& payload, int /*index*/)
{
switch (key)
{
default:
return FairMQDevice::GetProperty(key, default_);
}
}
Send(payload, fOutChannelName, fDirection);
void FairMQSplitter::SetProperty(const int key, const int value)
{
switch (key)
if (++fDirection >= fNumOutputs)
{
case Multipart:
fMultipart = value;
break;
default:
FairMQDevice::SetProperty(key, value);
break;
fDirection = 0;
}
}
int FairMQSplitter::GetProperty(const int key, const int default_ /*= 0*/)
{
switch (key)
{
case Multipart:
return fMultipart;
default:
return FairMQDevice::GetProperty(key, default_);
}
return true;
}
string FairMQSplitter::GetPropertyDescription(const int key)
{
switch (key)
{
case Multipart:
return "Multipart: Handle payloads as multipart messages.";
default:
return FairMQDevice::GetPropertyDescription(key);
}
}
void FairMQSplitter::ListProperties()
{
LOG(INFO) << "Properties of FairMQSplitter:";
for (int p = FairMQConfigurable::Last; p < FairMQSplitter::Last; ++p)
{
LOG(INFO) << " " << GetPropertyDescription(p);
}
LOG(INFO) << "---------------------------";
}

View File

@ -17,30 +17,25 @@
#include "FairMQDevice.h"
#include <string>
class FairMQSplitter : public FairMQDevice
{
public:
enum
{
Multipart = FairMQDevice::Last,
Last
};
FairMQSplitter();
virtual ~FairMQSplitter();
virtual void SetProperty(const int key, const std::string& value);
virtual std::string GetProperty(const int key, const std::string& default_ = "");
virtual void SetProperty(const int key, const int value);
virtual int GetProperty(const int key, const int default_ = 0);
virtual std::string GetPropertyDescription(const int key);
virtual void ListProperties();
protected:
int fMultipart;
int fNumOutputs;
int fDirection;
std::string fInChannelName;
std::string fOutChannelName;
virtual void Run();
virtual void InitTask();
bool HandleSingleData(std::unique_ptr<FairMQMessage>&, int);
bool HandleMultipartData(FairMQParts&, int);
};
#endif /* FAIRMQSPLITTER_H_ */

View File

@ -33,7 +33,6 @@ namespace expr = boost::log::expressions;
namespace sinks = boost::log::sinks;
namespace attrs = boost::log::attributes;
BOOST_LOG_GLOBAL_LOGGER_INIT(global_logger, src::severity_logger_mt)
{
src::severity_logger_mt<custom_severity_level> global_logger;
@ -42,141 +41,134 @@ BOOST_LOG_GLOBAL_LOGGER_INIT(global_logger, src::severity_logger_mt)
return global_logger;
}
namespace FairMQ
{
namespace Logger
{
std::vector<boost::shared_ptr<boost::log::sinks::basic_sink_frontend>> sinkList;// global var
} // end Logger namespace
} // end FairMQ namespace
namespace FairMQ{
namespace Logger{
std::vector<boost::shared_ptr< boost::log::sinks::basic_sink_frontend > >sinkList;// global var
}}//end namespace
void RemoveRegisteredSinks()
void RemoveRegisteredSinks()
{
if (FairMQ::Logger::sinkList.size() > 0)
{
if(FairMQ::Logger::sinkList.size() > 0)
for (const auto& sink : FairMQ::Logger::sinkList)
{
for(const auto& sink : FairMQ::Logger::sinkList)
logging::core::get()->remove_sink(sink);
FairMQ::Logger::sinkList.clear();
logging::core::get()->remove_sink(sink);
}
FairMQ::Logger::sinkList.clear();
}
}
void reinit_logger(bool color, const std::string& filename, custom_severity_level threshold)
{
BOOST_LOG_SEV(global_logger::get(), custom_severity_level::NOLOG) << "";
RemoveRegisteredSinks();
DefaultConsoleInit(color);
if (threshold != SEVERITY_NOLOG)
{
if (!filename.empty())
{
DefaultAddFileSink(filename, threshold);
}
}
}
// console sink related functions
void DefaultConsoleInit(bool color/* = true*/)
{
// add a text sink
typedef sinks::synchronous_sink<sinks::text_ostream_backend> text_sink;
void reinit_logger(bool color, const std::string& filename, custom_severity_level threshold)
RemoveRegisteredSinks();
// CONSOLE - all severity except error
boost::shared_ptr<text_sink> sink = boost::make_shared<text_sink>();
// add "console" output stream to our sink
sink->locked_backend()->add_stream(boost::shared_ptr<std::ostream>(&std::clog, empty_deleter_t()));
// specify the format of the log message
if (color)
{
BOOST_LOG_SEV(global_logger::get(), custom_severity_level::NOLOG) << "";
RemoveRegisteredSinks();
DefaultConsoleInit(color);
if(threshold!=SEVERITY_NOLOG)
{
if(!filename.empty())
{
DefaultAddFileSink(filename,threshold);
}
}
sink->set_formatter(&InitLogFormatter<tag_console>);
}
else
{
sink->set_formatter(&InitLogFormatter<tag_file>);
}
// console sink related functions
void DefaultConsoleInit(bool color/* = true*/)
{
// add a text sink
typedef sinks::synchronous_sink<sinks::text_ostream_backend> text_sink;
sink->set_filter(severity != SEVERITY_ERROR && severity < SEVERITY_NOLOG);
// add sink to the core
FairMQ::Logger::sinkList.push_back(sink);
logging::core::get()->add_sink(sink);
RemoveRegisteredSinks();
// CONSOLE - only severity error
boost::shared_ptr<text_sink> sink_error = boost::make_shared<text_sink>();
sink_error->locked_backend()->add_stream(boost::shared_ptr<std::ostream>(&std::cerr, empty_deleter_t()));
// CONSOLE - all severity except error
boost::shared_ptr<text_sink> sink = boost::make_shared<text_sink>();
// add "console" output stream to our sink
sink->locked_backend()->add_stream(boost::shared_ptr<std::ostream>(&std::clog, empty_deleter_t()));
if (color)
{
sink_error->set_formatter(&InitLogFormatter<tag_console>);
}
else
{
sink_error->set_formatter(&InitLogFormatter<tag_file>);
}
// specify the format of the log message
if (color)
{
sink->set_formatter(&InitLogFormatter<tag_console>);
}
else
{
sink->set_formatter(&InitLogFormatter<tag_file>);
}
sink_error->set_filter(severity == SEVERITY_ERROR);
FairMQ::Logger::sinkList.push_back(sink_error);
logging::core::get()->add_sink(sink_error);
}
sink->set_filter(severity != SEVERITY_ERROR && severity < SEVERITY_NOLOG);
// add sink to the core
FairMQ::Logger::sinkList.push_back(sink);
logging::core::get()->add_sink(sink);
// CONSOLE - only severity error
boost::shared_ptr<text_sink> sink_error = boost::make_shared<text_sink>();
sink_error->locked_backend()->add_stream(boost::shared_ptr<std::ostream>(&std::cerr, empty_deleter_t()));
if (color)
{
sink_error->set_formatter(&InitLogFormatter<tag_console>);
}
else
{
sink_error->set_formatter(&InitLogFormatter<tag_file>);
}
sink_error->set_filter(severity == SEVERITY_ERROR);
FairMQ::Logger::sinkList.push_back(sink_error);
logging::core::get()->add_sink(sink_error);
}
int DefaultConsoleSetFilter(custom_severity_level threshold)
{
if(FairMQ::Logger::sinkList.size()>=2)
{
FairMQ::Logger::sinkList.at(0)->set_filter([threshold](const boost::log::attribute_value_set& attr_set)
{
auto sev = attr_set["Severity"].extract<custom_severity_level>();
auto mainConsoleSinkCondition = (sev != SEVERITY_ERROR) && (sev < SEVERITY_NOLOG);
return mainConsoleSinkCondition && (sev>=threshold);
});
FairMQ::Logger::sinkList.at(1)->set_filter([threshold](const boost::log::attribute_value_set& attr_set)
{
auto sev = attr_set["Severity"].extract<custom_severity_level>();
auto errorConsoleSinkCondition = sev == SEVERITY_ERROR;
return errorConsoleSinkCondition && (sev>=threshold);
});
return 0;
}
else
{
return 1;
}
return 0;
}
// file sink related functions
void DefaultAddFileSink(const std::string& filename, custom_severity_level threshold)
int DefaultConsoleSetFilter(custom_severity_level threshold)
{
if (FairMQ::Logger::sinkList.size()>=2)
{
FairMQ::Logger::sinkList.at(0)->set_filter([threshold](const boost::log::attribute_value_set& attr_set)
{
// add a text sink
std::string formatted_filename(filename);
formatted_filename += "_%Y-%m-%d_%H-%M-%S.%N.log";
AddFileSink([threshold](const boost::log::attribute_value_set& attr_set)
{
auto sev = attr_set["Severity"].extract<custom_severity_level>();
return (sev >= threshold) && (sev < SEVERITY_NOLOG);
},
boost::log::keywords::file_name = formatted_filename,
boost::log::keywords::rotation_size = 10 * 1024 * 1024,
// rotate at midnight every day
boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),
// log collector,
// -- maximum total size of the stored log files is 1GB.
// -- minimum free space on the drive is 2GB
boost::log::keywords::max_size = 1000 * 1024 * 1024,
boost::log::keywords::min_free_space = 2000 * 1024 * 1024,
boost::log::keywords::auto_flush = true
//keywords::time_based_rotation = &is_it_time_to_rotate
);
}
auto sev = attr_set["Severity"].extract<custom_severity_level>();
auto mainConsoleSinkCondition = (sev != SEVERITY_ERROR) && (sev < SEVERITY_NOLOG);
return mainConsoleSinkCondition && (sev>=threshold);
});
FairMQ::Logger::sinkList.at(1)->set_filter([threshold](const boost::log::attribute_value_set& attr_set)
{
auto sev = attr_set["Severity"].extract<custom_severity_level>();
auto errorConsoleSinkCondition = sev == SEVERITY_ERROR;
return errorConsoleSinkCondition && (sev>=threshold);
});
return 0;
}
else
{
return 1;
}
return 0;
}
// file sink related functions
void DefaultAddFileSink(const std::string& filename, custom_severity_level threshold)
{
// add a text sink
std::string formatted_filename(filename);
formatted_filename += "_%Y-%m-%d_%H-%M-%S.%N.log";
AddFileSink([threshold](const boost::log::attribute_value_set& attr_set)
{
auto sev = attr_set["Severity"].extract<custom_severity_level>();
return (sev >= threshold) && (sev < SEVERITY_NOLOG);
},
boost::log::keywords::file_name = formatted_filename,
boost::log::keywords::rotation_size = 10 * 1024 * 1024,
// rotate at midnight every day
boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),
// log collector,
// -- maximum total size of the stored log files is 1GB.
// -- minimum free space on the drive is 2GB
boost::log::keywords::max_size = 1000 * 1024 * 1024,
boost::log::keywords::min_free_space = 2000 * 1024 * 1024,
boost::log::keywords::auto_flush = true
//keywords::time_based_rotation = &is_it_time_to_rotate
);
}

View File

@ -22,57 +22,61 @@
#include <boost/log/utility/manipulators/to_log.hpp>
#include <boost/log/sources/record_ostream.hpp>
namespace fairmq
namespace FairMQ
{
enum severity_level
{
TRACE,
DEBUG,
RESULTS,
INFO,
WARN,
ERROR,
STATE,
NOLOG
};
static const std::array<std::string, 8> g_LogSeverityLevelString
{
{
"TRACE",
"DEBUG",
"RESULTS",
"INFO",
"WARN",
"ERROR",
"STATE",
"NOLOG"
}
};
enum severity_level
{
TRACE,
DEBUG,
RESULTS,
INFO,
WARN,
ERROR,
STATE,
NOLOG
};
namespace color
static const std::array<std::string, 8> g_LogSeverityLevelString
{
{
enum code
{
FG_BLACK = 30,
FG_RED = 31,
FG_GREEN = 32,
FG_YELLOW = 33,
FG_BLUE = 34,
FG_MAGENTA = 35,
FG_CYAN = 36,
FG_WHITE = 37,
FG_DEFAULT = 39,
BG_RED = 41,
BG_GREEN = 42,
BG_BLUE = 44,
BG_DEFAULT = 49
};
"TRACE",
"DEBUG",
"RESULTS",
"INFO",
"WARN",
"ERROR",
"STATE",
"NOLOG"
}
};
namespace Color
{
enum code
{
FG_BLACK = 30,
FG_RED = 31,
FG_GREEN = 32,
FG_YELLOW = 33,
FG_BLUE = 34,
FG_MAGENTA = 35,
FG_CYAN = 36,
FG_WHITE = 37,
FG_DEFAULT = 39,
BG_RED = 41,
BG_GREEN = 42,
BG_BLUE = 44,
BG_DEFAULT = 49
};
}
} // FairMQ namespace
// helper function to format in color console output
template <fairmq::color::code color>
template <FairMQ::Color::code color>
inline std::string write_in(const std::string& text_in_bold)
{
std::ostringstream os;
@ -82,8 +86,8 @@ inline std::string write_in(const std::string& text_in_bold)
}
// typedef
typedef fairmq::severity_level custom_severity_level;
#define SEVERITY_THRESHOLD custom_severity_level::TRACE
typedef FairMQ::severity_level custom_severity_level;
#define SEVERITY_MINIMUM custom_severity_level::TRACE
#define SEVERITY_ERROR custom_severity_level::ERROR
#define SEVERITY_NOLOG custom_severity_level::NOLOG
@ -100,41 +104,41 @@ inline boost::log::formatting_ostream& operator<<
{
custom_severity_level level = manip.get();
std::size_t idx = static_cast<std::size_t>(level);
if (idx < fairmq::g_LogSeverityLevelString.size())
if (idx < FairMQ::g_LogSeverityLevelString.size())
{
// strm << " idx = " << idx << " ";
switch (level)
{
case custom_severity_level::TRACE :
strm << write_in<fairmq::color::FG_BLUE>(fairmq::g_LogSeverityLevelString.at(idx));
strm << write_in<FairMQ::Color::FG_BLUE>(FairMQ::g_LogSeverityLevelString.at(idx));
break;
case custom_severity_level::DEBUG :
strm << write_in<fairmq::color::FG_BLUE>(fairmq::g_LogSeverityLevelString.at(idx));
strm << write_in<FairMQ::Color::FG_BLUE>(FairMQ::g_LogSeverityLevelString.at(idx));
break;
case custom_severity_level::RESULTS :
strm << write_in<fairmq::color::FG_MAGENTA>(fairmq::g_LogSeverityLevelString.at(idx));
strm << write_in<FairMQ::Color::FG_MAGENTA>(FairMQ::g_LogSeverityLevelString.at(idx));
break;
case custom_severity_level::INFO :
strm << write_in<fairmq::color::FG_GREEN>(fairmq::g_LogSeverityLevelString.at(idx));
strm << write_in<FairMQ::Color::FG_GREEN>(FairMQ::g_LogSeverityLevelString.at(idx));
break;
case custom_severity_level::WARN :
strm << write_in<fairmq::color::FG_YELLOW>(fairmq::g_LogSeverityLevelString.at(idx));
strm << write_in<FairMQ::Color::FG_YELLOW>(FairMQ::g_LogSeverityLevelString.at(idx));
break;
case custom_severity_level::STATE :
strm << write_in<fairmq::color::FG_MAGENTA>(fairmq::g_LogSeverityLevelString.at(idx));
strm << write_in<FairMQ::Color::FG_MAGENTA>(FairMQ::g_LogSeverityLevelString.at(idx));
break;
case custom_severity_level::ERROR :
strm << write_in<fairmq::color::FG_RED>(fairmq::g_LogSeverityLevelString.at(idx));
strm << write_in<FairMQ::Color::FG_RED>(FairMQ::g_LogSeverityLevelString.at(idx));
break;
case custom_severity_level::NOLOG :
strm << write_in<fairmq::color::FG_DEFAULT>(fairmq::g_LogSeverityLevelString.at(idx));
strm << write_in<FairMQ::Color::FG_DEFAULT>(FairMQ::g_LogSeverityLevelString.at(idx));
break;
default:
@ -143,7 +147,7 @@ inline boost::log::formatting_ostream& operator<<
}
else
{
strm << write_in<fairmq::color::FG_RED>("Unknown log level ")
strm << write_in<FairMQ::Color::FG_RED>("Unknown log level ")
<< "(int level = " << static_cast<int>(level) << ")";
}
return strm;
@ -158,13 +162,13 @@ inline boost::log::formatting_ostream& operator<<
{
custom_severity_level level = manip.get();
std::size_t idx = static_cast<std::size_t>(level);
if (idx < fairmq::g_LogSeverityLevelString.size())
if (idx < FairMQ::g_LogSeverityLevelString.size())
{
strm << fairmq::g_LogSeverityLevelString.at(idx);
strm << FairMQ::g_LogSeverityLevelString.at(idx);
}
else
{
strm << write_in<fairmq::color::FG_RED>("Unknown log level ")
strm << write_in<FairMQ::Color::FG_RED>("Unknown log level ")
<< "(int level = " << static_cast<int>(level) << ")";
}
return strm;

View File

@ -23,8 +23,8 @@
#include <boost/log/support/date_time.hpp>
void test_logger()
{
void test_logger()
{
LOG(TRACE) << "this is a trace message";
LOG(DEBUG) << "this is a debug message";
LOG(RESULTS) << "this is a results message";
@ -32,65 +32,62 @@
LOG(WARN) << "this is a warning message";
LOG(ERROR) << "this is an error message";
LOG(STATE) << "this is a state message";
}
void test_console_level()
{
}
void test_console_level()
{
std::cout<<"********* test logger : SET_LOG_CONSOLE_LEVEL(lvl) *********"<<std::endl;
SET_LOG_CONSOLE_LEVEL(TRACE);
test_logger();
std::cout << "----------------------------"<<std::endl;
SET_LOG_CONSOLE_LEVEL(DEBUG);
test_logger();
std::cout << "----------------------------"<<std::endl;
SET_LOG_CONSOLE_LEVEL(RESULTS);
test_logger();
std::cout << "----------------------------"<<std::endl;
SET_LOG_CONSOLE_LEVEL(INFO);
test_logger();
std::cout << "----------------------------"<<std::endl;
SET_LOG_CONSOLE_LEVEL(WARN);
test_logger();
std::cout << "----------------------------"<<std::endl;
SET_LOG_CONSOLE_LEVEL(ERROR);
test_logger();
std::cout << "----------------------------"<<std::endl;
SET_LOG_CONSOLE_LEVEL(STATE);
test_logger();
std::cout << "----------------------------"<<std::endl;
}
}
int main()
int main()
{
test_console_level();
SET_LOG_CONSOLE_LEVEL(INFO);
std::cout << "----------------------------"<<std::endl;
LOG(INFO)<<"open log file 1";
ADD_LOG_FILESINK("test_log1",ERROR);
test_logger();
std::cout << "----------------------------"<<std::endl;
LOG(INFO)<<"open log file 2";
ADD_LOG_FILESINK("test_log2",STATE);
test_logger();
// advanced commands
std::cout << "----------------------------"<<std::endl;
LOG(INFO)<<"open log file 3";// custom file sink setting
AddFileSink([](const boost::log::attribute_value_set& attr_set)
{
auto sev = attr_set["Severity"].extract<custom_severity_level>();
return (sev == fairmq::ERROR);
return (sev == FairMQ::ERROR);
},
boost::log::keywords::file_name = "test_log3_%5N.log",
boost::log::keywords::rotation_size = 5 * 1024 * 1024,
@ -105,7 +102,7 @@ int main()
FairMQ::Logger::sinkList.back()->set_filter([](const boost::log::attribute_value_set& attr_set)
{
auto sev = attr_set["Severity"].extract<custom_severity_level>();
return (sev == fairmq::WARN) || (sev == fairmq::ERROR);
return (sev == FairMQ::WARN) || (sev == FairMQ::ERROR);
});
test_logger();
@ -114,5 +111,3 @@ int main()
test_logger();
return 0;
}

View File

@ -59,7 +59,7 @@ FairMQPollerNN::FairMQPollerNN(const vector<FairMQChannel>& channels)
}
}
FairMQPollerNN::FairMQPollerNN(const unordered_map<string, vector<FairMQChannel>>& channelsMap, const initializer_list<string> channelList)
FairMQPollerNN::FairMQPollerNN(const unordered_map<string, vector<FairMQChannel>>& channelsMap, const vector<string>& channelList)
: items()
, fNumItems(0)
, fOffsetMap()

View File

@ -33,7 +33,7 @@ class FairMQPollerNN : public FairMQPoller
public:
FairMQPollerNN(const std::vector<FairMQChannel>& channels);
FairMQPollerNN(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::initializer_list<std::string> channelList);
FairMQPollerNN(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::vector<std::string>& channelList);
FairMQPollerNN(const FairMQPollerNN&) = delete;
FairMQPollerNN operator=(const FairMQPollerNN&) = delete;

View File

@ -21,37 +21,37 @@ FairMQTransportFactoryNN::FairMQTransportFactoryNN()
LOG(INFO) << "Using nanomsg library";
}
FairMQMessage* FairMQTransportFactoryNN::CreateMessage()
FairMQMessage* FairMQTransportFactoryNN::CreateMessage() const
{
return new FairMQMessageNN();
}
FairMQMessage* FairMQTransportFactoryNN::CreateMessage(const size_t size)
FairMQMessage* FairMQTransportFactoryNN::CreateMessage(const size_t size) const
{
return new FairMQMessageNN(size);
}
FairMQMessage* FairMQTransportFactoryNN::CreateMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint)
FairMQMessage* FairMQTransportFactoryNN::CreateMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint) const
{
return new FairMQMessageNN(data, size, ffn, hint);
}
FairMQSocket* FairMQTransportFactoryNN::CreateSocket(const string& type, const std::string& name, const int numIoThreads, const std::string& id /*= ""*/)
FairMQSocket* FairMQTransportFactoryNN::CreateSocket(const string& type, const std::string& name, const int numIoThreads, const std::string& id /*= ""*/) const
{
return new FairMQSocketNN(type, name, numIoThreads, id);
}
FairMQPoller* FairMQTransportFactoryNN::CreatePoller(const vector<FairMQChannel>& channels)
FairMQPoller* FairMQTransportFactoryNN::CreatePoller(const vector<FairMQChannel>& channels) const
{
return new FairMQPollerNN(channels);
}
FairMQPoller* FairMQTransportFactoryNN::CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::initializer_list<std::string> channelList)
FairMQPoller* FairMQTransportFactoryNN::CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::vector<std::string>& channelList) const
{
return new FairMQPollerNN(channelsMap, channelList);
}
FairMQPoller* FairMQTransportFactoryNN::CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket)
FairMQPoller* FairMQTransportFactoryNN::CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket) const
{
return new FairMQPollerNN(cmdSocket, dataSocket);
}

View File

@ -27,15 +27,15 @@ class FairMQTransportFactoryNN : public FairMQTransportFactory
public:
FairMQTransportFactoryNN();
virtual FairMQMessage* CreateMessage();
virtual FairMQMessage* CreateMessage(const size_t size);
virtual FairMQMessage* CreateMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint = NULL);
virtual FairMQMessage* CreateMessage() const;
virtual FairMQMessage* CreateMessage(const size_t size) const;
virtual FairMQMessage* CreateMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint = NULL) const;
virtual FairMQSocket* CreateSocket(const std::string& type, const std::string& name, const int numIoThreads, const std::string& id = "");
virtual FairMQSocket* CreateSocket(const std::string& type, const std::string& name, const int numIoThreads, const std::string& id = "") const;
virtual FairMQPoller* CreatePoller(const std::vector<FairMQChannel>& channels);
virtual FairMQPoller* CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::initializer_list<std::string> channelList);
virtual FairMQPoller* CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket);
virtual FairMQPoller* CreatePoller(const std::vector<FairMQChannel>& channels) const;
virtual FairMQPoller* CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::vector<std::string>& channelList) const;
virtual FairMQPoller* CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket) const;
virtual ~FairMQTransportFactoryNN() {};
};

View File

@ -26,41 +26,36 @@
#include <boost/signals2.hpp>
#include <boost/signals2/signal.hpp>
enum class EventId : uint32_t
enum class EventId : uint32_t
{
// Place your new EventManager events here
UpdateParam = 0,
Custom = 1,
};
namespace Events
namespace Events
{
template <EventId,typename ...Args> struct Traits;
template <typename T> struct Traits<EventId::UpdateParam, T> { using signal_type = boost::signals2::signal<void(const std::string&, T)>; } ;
template <typename T> struct Traits<EventId::UpdateParam, std::vector<T> > { using signal_type = boost::signals2::signal<void(const std::string&, const std::vector<T>& )>; } ;
template <EventId,typename ...Args> struct Traits;
template <typename T> struct Traits<EventId::UpdateParam, T> { using signal_type = boost::signals2::signal<void(const std::string&, T)>; } ;
template <typename T> struct Traits<EventId::UpdateParam, std::vector<T> > { using signal_type = boost::signals2::signal<void(const std::string&, const std::vector<T>& )>; } ;
template <> struct Traits<EventId::UpdateParam, std::string> { using signal_type = boost::signals2::signal<void(const std::string&, const std::string&)>; } ;
template<std::size_t N> struct Traits<EventId::UpdateParam, const char[N]> { using signal_type = boost::signals2::signal<void(const std::string&, const std::string&)>; } ;
template <typename ...T> struct Traits<EventId::Custom,T...> { using signal_type = boost::signals2::signal<void(T...)>; } ;
/*
template <EventId, typename ...Args> struct Traits2;
template <> struct Traits2<EventId::UpdateParam> { using signal_type = boost::signals2::signal<void(const std::string&, const std::string&)>; } ;
template <typename ...T> struct Traits2<EventId::UpdateParam,T...> { using signal_type = boost::signals2::signal<void(const std::string&, T...)>; } ;
template <> struct Traits2<EventId::UpdateParamInt> { using signal_type = boost::signals2::signal<void(const std::string&, int)>; } ;
// */
}
template <> struct Traits<EventId::UpdateParam, std::string> { using signal_type = boost::signals2::signal<void(const std::string&, const std::string&)>; } ;
template<std::size_t N> struct Traits<EventId::UpdateParam, const char[N]> { using signal_type = boost::signals2::signal<void(const std::string&, const std::string&)>; } ;
class FairMQEventManager
template <typename ...T> struct Traits<EventId::Custom,T...> { using signal_type = boost::signals2::signal<void(T...)>; } ;
/*
template <EventId, typename ...Args> struct Traits2;
template <> struct Traits2<EventId::UpdateParam> { using signal_type = boost::signals2::signal<void(const std::string&, const std::string&)>; } ;
template <typename ...T> struct Traits2<EventId::UpdateParam,T...> { using signal_type = boost::signals2::signal<void(const std::string&, T...)>; } ;
template <> struct Traits2<EventId::UpdateParamInt> { using signal_type = boost::signals2::signal<void(const std::string&, int)>; } ;
// */
} // Events namespace
class FairMQEventManager
{
public:
typedef std::pair<EventId,std::string> EventKey;
@ -99,16 +94,13 @@ class FairMQEventManager
}
private:
std::map<EventKey, boost::any> fEventMap;
template <EventId event, typename... T, typename Slot = typename Events::Traits<event,T...>::signal_type,
typename SlotPtr = boost::shared_ptr<Slot> >
Slot& GetSlot(const std::string& key)
Slot& GetSlot(const std::string& key)
{
try
try
{
EventKey eventKey = std::make_pair(event,key);
//static_assert(std::is_same<decltype(boost::make_shared<Slot>()),SlotPtr>::value, "");
@ -119,7 +111,7 @@ class FairMQEventManager
// auto &&tmp = boost::any_cast<SlotPtr>(fEventMap.at(eventKey));
// return *tmp;
}
catch (boost::bad_any_cast const &e)
catch (boost::bad_any_cast const &e)
{
LOG(ERROR) << "Caught instance of boost::bad_any_cast: "
<< e.what() << " on event #" << static_cast<uint32_t>(event) << " and key" << key;
@ -128,6 +120,4 @@ class FairMQEventManager
}
};
#endif /* FAIRMQEVENTMANAGER_H */

View File

@ -30,7 +30,8 @@ FairMQMap ptreeToMQMap(const boost::property_tree::ptree& pt, const string& id,
FairMQMap channelMap;
// helper::PrintDeviceList(pt.get_child(rootNode));
// Extract value from boost::property_tree
helper::DeviceParser(pt.get_child(rootNode), channelMap, id, formatFlag);
Helper::DeviceParser(pt.get_child(rootNode), channelMap, id, formatFlag);
if (channelMap.size() > 0)
{
stringstream channelKeys;
@ -77,119 +78,86 @@ FairMQMap XML::UserParser(stringstream& input, const string& deviceId, const str
return ptreeToMQMap(pt, deviceId, rootNode, "xml");
}
namespace helper
namespace Helper
{
void PrintDeviceList(const boost::property_tree::ptree& tree, const std::string& formatFlag)
{
string deviceIdKey;
// do a first loop just to print the device-id in json input
for (const auto& p : tree)
void PrintDeviceList(const boost::property_tree::ptree& tree, const std::string& formatFlag)
{
string deviceIdKey;
// do a first loop just to print the device-id in json input
for (const auto& p : tree)
{
if (p.first == "devices")
{
if (p.first == "devices")
for (const auto& q : p.second.get_child(""))
{
for (const auto& q : p.second.get_child(""))
string key = q.second.get<string>("key", "");
if (key != "")
{
string key = q.second.get<string>("key", "");
if (key != "")
{
deviceIdKey = key;
LOG(TRACE) << "Found config for device key '" << deviceIdKey << "' in JSON input";
}
else
{
deviceIdKey = q.second.get<string>("id");
LOG(TRACE) << "Found config for device id '" << deviceIdKey << "' in JSON input";
}
deviceIdKey = key;
LOG(TRACE) << "Found config for device key '" << deviceIdKey << "' in JSON input";
}
else
{
deviceIdKey = q.second.get<string>("id");
LOG(TRACE) << "Found config for device id '" << deviceIdKey << "' in JSON input";
}
}
}
if (p.first == "device")
if (p.first == "device")
{
//get id attribute to choose the device
if (formatFlag == "xml")
{
//get id attribute to choose the device
if (formatFlag == "xml")
{
deviceIdKey = p.second.get<string>("<xmlattr>.id");
LOG(TRACE) << "Found config for '" << deviceIdKey << "' in XML input";
}
deviceIdKey = p.second.get<string>("<xmlattr>.id");
LOG(TRACE) << "Found config for '" << deviceIdKey << "' in XML input";
}
if (formatFlag == "json")
if (formatFlag == "json")
{
string key = p.second.get<string>("key", "");
if (key != "")
{
string key = p.second.get<string>("key", "");
if (key != "")
{
deviceIdKey = key;
LOG(TRACE) << "Found config for device key '" << deviceIdKey << "' in JSON input";
}
else
{
deviceIdKey = p.second.get<string>("id");
LOG(TRACE) << "Found config for device id '" << deviceIdKey << "' in JSON input";
}
deviceIdKey = key;
LOG(TRACE) << "Found config for device key '" << deviceIdKey << "' in JSON input";
}
else
{
deviceIdKey = p.second.get<string>("id");
LOG(TRACE) << "Found config for device id '" << deviceIdKey << "' in JSON input";
}
}
}
}
}
void DeviceParser(const boost::property_tree::ptree& tree, FairMQMap& channelMap, const string& deviceId, const string& formatFlag)
void DeviceParser(const boost::property_tree::ptree& tree, FairMQMap& channelMap, const string& deviceId, const string& formatFlag)
{
string deviceIdKey;
LOG(DEBUG) << "Looking for '" << deviceId << "' id/key in the provided config file...";
// For each node in fairMQOptions
for (const auto& p : tree)
{
string deviceIdKey;
LOG(DEBUG) << "Looking for '" << deviceId << "' id/key in the provided config file...";
// For each node in fairMQOptions
for (const auto& p0 : tree)
if (p.first == "devices")
{
if (p0.first == "devices")
for (const auto& q : p.second)
{
for (const auto& p : p0.second)
// check if key is provided, otherwise use id
string key = q.second.get<string>("key", "");
if (key != "")
{
// check if key is provided, otherwise use id
string key = p.second.get<string>("key", "");
if (key != "")
{
deviceIdKey = key;
// LOG(DEBUG) << "Found config for device key '" << deviceIdKey << "' in JSON input";
}
else
{
deviceIdKey = p.second.get<string>("id");
// LOG(DEBUG) << "Found config for device id '" << deviceIdKey << "' in JSON input";
}
// if not correct device id, do not fill MQMap
if (deviceId != deviceIdKey)
{
continue;
}
LOG(DEBUG) << "[" << p0.first << "] " << deviceIdKey;
ChannelParser(p.second, channelMap, formatFlag);
deviceIdKey = key;
// LOG(DEBUG) << "Found config for device key '" << deviceIdKey << "' in JSON input";
}
}
if (p0.first == "device")
{
if (formatFlag == "xml")
else
{
deviceIdKey = p0.second.get<string>("<xmlattr>.id");
LOG(DEBUG) << "Found config for '" << deviceIdKey << "' in XML input";
}
if (formatFlag == "json")
{
// check if key is provided, otherwise use id
string key = p0.second.get<string>("key", "");
if (key != "")
{
deviceIdKey = key;
// LOG(DEBUG) << "Found config for device key '" << deviceIdKey << "' in JSON input";
}
else
{
deviceIdKey = p0.second.get<string>("id");
// LOG(DEBUG) << "Found config for device id '" << deviceIdKey << "' in JSON input";
}
deviceIdKey = q.second.get<string>("id");
// LOG(DEBUG) << "Found config for device id '" << deviceIdKey << "' in JSON input";
}
// if not correct device id, do not fill MQMap
@ -198,167 +166,255 @@ namespace helper
continue;
}
LOG(DEBUG) << "[" << p0.first << "] " << deviceIdKey;
LOG(DEBUG) << "Found with following channels:";
ChannelParser(p0.second, channelMap, formatFlag);
ChannelParser(q.second, channelMap, formatFlag);
}
}
}
void ChannelParser(const boost::property_tree::ptree& tree, FairMQMap& channelMap, const string& formatFlag)
{
string channelKey;
for (const auto& p : tree)
if (p.first == "device")
{
if (p.first == "channels")
if (formatFlag == "xml")
{
for (const auto& q : p.second)
deviceIdKey = p.second.get<string>("<xmlattr>.id");
}
if (formatFlag == "json")
{
// check if key is provided, otherwise use id
string key = p.second.get<string>("key", "");
if (key != "")
{
channelKey = q.second.get<string>("name");
// try to get common properties to use for all subChannels
FairMQChannel commonChannel;
commonChannel.UpdateType(q.second.get<string>("type", commonChannel.GetType()));
commonChannel.UpdateMethod(q.second.get<string>("method", commonChannel.GetMethod()));
commonChannel.UpdateAddress(q.second.get<string>("address", commonChannel.GetAddress()));
commonChannel.UpdateProperty(q.second.get<string>("property", commonChannel.GetProperty()));
commonChannel.UpdateSndBufSize(q.second.get<int>("sndBufSize", commonChannel.GetSndBufSize()));
commonChannel.UpdateRcvBufSize(q.second.get<int>("rcvBufSize", commonChannel.GetRcvBufSize()));
commonChannel.UpdateRateLogging(q.second.get<int>("rateLogging", commonChannel.GetRateLogging()));
LOG(DEBUG) << "\t[" << p.first << "] " << channelKey;
// temporary FairMQChannel container
vector<FairMQChannel> channelList;
SocketParser(q.second.get_child(""), channelList, commonChannel);
channelMap.insert(make_pair(channelKey, move(channelList)));
deviceIdKey = key;
// LOG(DEBUG) << "Found config for device key '" << deviceIdKey << "' in JSON input";
}
else
{
deviceIdKey = p.second.get<string>("id");
// LOG(DEBUG) << "Found config for device id '" << deviceIdKey << "' in JSON input";
}
}
if (p.first == "channel")
// if not correct device id, do not fill MQMap
if (deviceId != deviceIdKey)
{
continue;
}
LOG(DEBUG) << "Found with following channels:";
ChannelParser(p.second, channelMap, formatFlag);
}
}
}
void ChannelParser(const boost::property_tree::ptree& tree, FairMQMap& channelMap, const string& formatFlag)
{
string channelKey;
for (const auto& p : tree)
{
if (p.first == "channels")
{
for (const auto& q : p.second)
{
channelKey = q.second.get<string>("name");
int numSockets = q.second.get<int>("numSockets", 0);
// try to get common properties to use for all subChannels
FairMQChannel commonChannel;
// get name attribute to form key
if (formatFlag == "xml")
{
channelKey = p.second.get<string>("<xmlattr>.name");
}
if (formatFlag == "json")
{
channelKey = p.second.get<string>("name");
// try to get common properties to use for all subChannels
commonChannel.UpdateType(p.second.get<string>("type", commonChannel.GetType()));
commonChannel.UpdateMethod(p.second.get<string>("method", commonChannel.GetMethod()));
commonChannel.UpdateAddress(p.second.get<string>("address", commonChannel.GetAddress()));
commonChannel.UpdateProperty(p.second.get<string>("property", commonChannel.GetProperty()));
commonChannel.UpdateSndBufSize(p.second.get<int>("sndBufSize", commonChannel.GetSndBufSize()));
commonChannel.UpdateRcvBufSize(p.second.get<int>("rcvBufSize", commonChannel.GetRcvBufSize()));
commonChannel.UpdateRateLogging(p.second.get<int>("rateLogging", commonChannel.GetRateLogging()));
}
LOG(DEBUG) << "\t[" << p.first << "] " << channelKey;
commonChannel.UpdateType(q.second.get<string>("type", commonChannel.GetType()));
commonChannel.UpdateMethod(q.second.get<string>("method", commonChannel.GetMethod()));
commonChannel.UpdateAddress(q.second.get<string>("address", commonChannel.GetAddress()));
commonChannel.UpdateProperty(q.second.get<string>("property", commonChannel.GetProperty()));
commonChannel.UpdateSndBufSize(q.second.get<int>("sndBufSize", commonChannel.GetSndBufSize()));
commonChannel.UpdateRcvBufSize(q.second.get<int>("rcvBufSize", commonChannel.GetRcvBufSize()));
commonChannel.UpdateRateLogging(q.second.get<int>("rateLogging", commonChannel.GetRateLogging()));
// temporary FairMQChannel container
vector<FairMQChannel> channelList;
SocketParser(p.second.get_child(""), channelList, commonChannel);
if (numSockets > 0)
{
LOG(DEBUG) << "" << channelKey << ":";
LOG(DEBUG) << "\tnumSockets of " << numSockets << " specified,";
LOG(DEBUG) << "\tapplying common settings to each:";
LOG(DEBUG) << "\ttype = " << commonChannel.GetType();
LOG(DEBUG) << "\tmethod = " << commonChannel.GetMethod();
LOG(DEBUG) << "\taddress = " << commonChannel.GetAddress();
LOG(DEBUG) << "\tproperty = " << commonChannel.GetProperty();
LOG(DEBUG) << "\tsndBufSize = " << commonChannel.GetSndBufSize();
LOG(DEBUG) << "\trcvBufSize = " << commonChannel.GetRcvBufSize();
LOG(DEBUG) << "\trateLogging = " << commonChannel.GetRateLogging();
for (int i = 0; i < numSockets; ++i)
{
FairMQChannel channel(commonChannel);
channelList.push_back(channel);
}
}
else
{
SocketParser(q.second.get_child(""), channelList, channelKey, commonChannel);
}
channelMap.insert(make_pair(channelKey, move(channelList)));
}
}
}
void SocketParser(const boost::property_tree::ptree& tree, vector<FairMQChannel>& channelList, const FairMQChannel& commonChannel)
{
// for each socket in channel
int socketCounter = 0;
for (const auto& p : tree)
if (p.first == "channel")
{
if (p.first == "sockets")
// try to get common properties to use for all subChannels
FairMQChannel commonChannel;
int numSockets = 0;
// get name attribute to form key
if (formatFlag == "xml")
{
for (const auto& q : p.second)
channelKey = p.second.get<string>("<xmlattr>.name");
}
if (formatFlag == "json")
{
channelKey = p.second.get<string>("name");
numSockets = p.second.get<int>("numSockets", 0);
// try to get common properties to use for all subChannels
commonChannel.UpdateType(p.second.get<string>("type", commonChannel.GetType()));
commonChannel.UpdateMethod(p.second.get<string>("method", commonChannel.GetMethod()));
commonChannel.UpdateAddress(p.second.get<string>("address", commonChannel.GetAddress()));
commonChannel.UpdateProperty(p.second.get<string>("property", commonChannel.GetProperty()));
commonChannel.UpdateSndBufSize(p.second.get<int>("sndBufSize", commonChannel.GetSndBufSize()));
commonChannel.UpdateRcvBufSize(p.second.get<int>("rcvBufSize", commonChannel.GetRcvBufSize()));
commonChannel.UpdateRateLogging(p.second.get<int>("rateLogging", commonChannel.GetRateLogging()));
}
// temporary FairMQChannel container
vector<FairMQChannel> channelList;
if (numSockets > 0)
{
LOG(DEBUG) << "" << channelKey << ":";
LOG(DEBUG) << "\tnumSockets of " << numSockets << " specified,";
LOG(DEBUG) << "\tapplying common settings to each:";
LOG(DEBUG) << "\ttype = " << commonChannel.GetType();
LOG(DEBUG) << "\tmethod = " << commonChannel.GetMethod();
LOG(DEBUG) << "\taddress = " << commonChannel.GetAddress();
LOG(DEBUG) << "\tproperty = " << commonChannel.GetProperty();
LOG(DEBUG) << "\tsndBufSize = " << commonChannel.GetSndBufSize();
LOG(DEBUG) << "\trcvBufSize = " << commonChannel.GetRcvBufSize();
LOG(DEBUG) << "\trateLogging = " << commonChannel.GetRateLogging();
for (int i = 0; i < numSockets; ++i)
{
++socketCounter;
// create new channel and apply setting from the common channel
FairMQChannel channel(commonChannel);
// if the socket field specifies or overrides something from the common channel, apply those settings
channel.UpdateType(q.second.get<string>("type", channel.GetType()));
channel.UpdateMethod(q.second.get<string>("method", channel.GetMethod()));
channel.UpdateAddress(q.second.get<string>("address", channel.GetAddress()));
channel.UpdateProperty(q.second.get<string>("property", channel.GetProperty()));
channel.UpdateSndBufSize(q.second.get<int>("sndBufSize", channel.GetSndBufSize()));
channel.UpdateRcvBufSize(q.second.get<int>("rcvBufSize", channel.GetRcvBufSize()));
channel.UpdateRateLogging(q.second.get<int>("rateLogging", channel.GetRateLogging()));
LOG(DEBUG) << "\t\t[" << p.first << "] " << socketCounter;
LOG(DEBUG) << "\t\t\ttype = " << channel.GetType();
LOG(DEBUG) << "\t\t\tmethod = " << channel.GetMethod();
LOG(DEBUG) << "\t\t\taddress = " << channel.GetAddress();
LOG(DEBUG) << "\t\t\tproperty = " << channel.GetProperty();
LOG(DEBUG) << "\t\t\tsndBufSize = " << channel.GetSndBufSize();
LOG(DEBUG) << "\t\t\trcvBufSize = " << channel.GetRcvBufSize();
LOG(DEBUG) << "\t\t\trateLogging = " << channel.GetRateLogging();
channelList.push_back(channel);
}
}
if (p.first == "socket")
else
{
SocketParser(p.second.get_child(""), channelList, channelKey, commonChannel);
}
channelMap.insert(make_pair(channelKey, move(channelList)));
}
}
}
void SocketParser(const boost::property_tree::ptree& tree, vector<FairMQChannel>& channelList, const string& channelName, const FairMQChannel& commonChannel)
{
// for each socket in channel
int socketCounter = 0;
for (const auto& p : tree)
{
if (p.first == "sockets")
{
for (const auto& q : p.second)
{
++socketCounter;
// create new channel and apply setting from the common channel
FairMQChannel channel(commonChannel);
// if the socket field specifies or overrides something from the common channel, apply those settings
channel.UpdateType(p.second.get<string>("type", channel.GetType()));
channel.UpdateMethod(p.second.get<string>("method", channel.GetMethod()));
channel.UpdateAddress(p.second.get<string>("address", channel.GetAddress()));
channel.UpdateProperty(p.second.get<string>("property", channel.GetProperty()));
channel.UpdateSndBufSize(p.second.get<int>("sndBufSize", channel.GetSndBufSize()));
channel.UpdateRcvBufSize(p.second.get<int>("rcvBufSize", channel.GetRcvBufSize()));
channel.UpdateRateLogging(p.second.get<int>("rateLogging", channel.GetRateLogging()));
channel.UpdateType(q.second.get<string>("type", channel.GetType()));
channel.UpdateMethod(q.second.get<string>("method", channel.GetMethod()));
channel.UpdateAddress(q.second.get<string>("address", channel.GetAddress()));
channel.UpdateProperty(q.second.get<string>("property", channel.GetProperty()));
channel.UpdateSndBufSize(q.second.get<int>("sndBufSize", channel.GetSndBufSize()));
channel.UpdateRcvBufSize(q.second.get<int>("rcvBufSize", channel.GetRcvBufSize()));
channel.UpdateRateLogging(q.second.get<int>("rateLogging", channel.GetRateLogging()));
LOG(DEBUG) << "\t\t[" << p.first << "] " << socketCounter;
LOG(DEBUG) << "\t\t\ttype = " << channel.GetType();
LOG(DEBUG) << "\t\t\tmethod = " << channel.GetMethod();
LOG(DEBUG) << "\t\t\taddress = " << channel.GetAddress();
LOG(DEBUG) << "\t\t\tproperty = " << channel.GetProperty();
LOG(DEBUG) << "\t\t\tsndBufSize = " << channel.GetSndBufSize();
LOG(DEBUG) << "\t\t\trcvBufSize = " << channel.GetRcvBufSize();
LOG(DEBUG) << "\t\t\trateLogging = " << channel.GetRateLogging();
LOG(DEBUG) << "" << channelName << "[" << socketCounter << "]:";
LOG(DEBUG) << "\ttype = " << channel.GetType();
LOG(DEBUG) << "\tmethod = " << channel.GetMethod();
LOG(DEBUG) << "\taddress = " << channel.GetAddress();
LOG(DEBUG) << "\tproperty = " << channel.GetProperty();
LOG(DEBUG) << "\tsndBufSize = " << channel.GetSndBufSize();
LOG(DEBUG) << "\trcvBufSize = " << channel.GetRcvBufSize();
LOG(DEBUG) << "\trateLogging = " << channel.GetRateLogging();
channelList.push_back(channel);
++socketCounter;
}
} // end socket loop
if (socketCounter)
{
LOG(DEBUG) << "Found " << socketCounter << " socket(s) in channel.";
}
else
if (p.first == "socket")
{
LOG(DEBUG) << "\t\t\tNo subChannels specified,";
LOG(DEBUG) << "\t\t\tapplying common settings to the channel:";
// create new channel and apply setting from the common channel
FairMQChannel channel(commonChannel);
LOG(DEBUG) << "\t\t\ttype = " << channel.GetType();
LOG(DEBUG) << "\t\t\tmethod = " << channel.GetMethod();
LOG(DEBUG) << "\t\t\taddress = " << channel.GetAddress();
LOG(DEBUG) << "\t\t\tproperty = " << channel.GetProperty();
LOG(DEBUG) << "\t\t\tsndBufSize = " << channel.GetSndBufSize();
LOG(DEBUG) << "\t\t\trcvBufSize = " << channel.GetRcvBufSize();
LOG(DEBUG) << "\t\t\trateLogging = " << channel.GetRateLogging();
// if the socket field specifies or overrides something from the common channel, apply those settings
channel.UpdateType(p.second.get<string>("type", channel.GetType()));
channel.UpdateMethod(p.second.get<string>("method", channel.GetMethod()));
channel.UpdateAddress(p.second.get<string>("address", channel.GetAddress()));
channel.UpdateProperty(p.second.get<string>("property", channel.GetProperty()));
channel.UpdateSndBufSize(p.second.get<int>("sndBufSize", channel.GetSndBufSize()));
channel.UpdateRcvBufSize(p.second.get<int>("rcvBufSize", channel.GetRcvBufSize()));
channel.UpdateRateLogging(p.second.get<int>("rateLogging", channel.GetRateLogging()));
LOG(DEBUG) << "" << channelName << "[" << socketCounter << "]:";
LOG(DEBUG) << "\ttype = " << channel.GetType();
LOG(DEBUG) << "\tmethod = " << channel.GetMethod();
LOG(DEBUG) << "\taddress = " << channel.GetAddress();
LOG(DEBUG) << "\tproperty = " << channel.GetProperty();
LOG(DEBUG) << "\tsndBufSize = " << channel.GetSndBufSize();
LOG(DEBUG) << "\trcvBufSize = " << channel.GetRcvBufSize();
LOG(DEBUG) << "\trateLogging = " << channel.GetRateLogging();
channelList.push_back(channel);
++socketCounter;
}
} // end socket loop
if (socketCounter)
{
LOG(DEBUG) << "Found " << socketCounter << " socket(s) in channel.";
}
} // end helper namespace
else
{
LOG(DEBUG) << "" << channelName << ":";
LOG(DEBUG) << "\tNo sockets specified,";
LOG(DEBUG) << "\tapplying common settings to the channel:";
} // end FairMQParser namespace
FairMQChannel channel(commonChannel);
LOG(DEBUG) << "\ttype = " << channel.GetType();
LOG(DEBUG) << "\tmethod = " << channel.GetMethod();
LOG(DEBUG) << "\taddress = " << channel.GetAddress();
LOG(DEBUG) << "\tproperty = " << channel.GetProperty();
LOG(DEBUG) << "\tsndBufSize = " << channel.GetSndBufSize();
LOG(DEBUG) << "\trcvBufSize = " << channel.GetRcvBufSize();
LOG(DEBUG) << "\trateLogging = " << channel.GetRateLogging();
channelList.push_back(channel);
}
}
} // Helper namespace
} // FairMQParser namespace

View File

@ -8,16 +8,13 @@
#ifndef FAIRMQPARSER_H
#define FAIRMQPARSER_H
// std
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
// Boost
#include <boost/property_tree/ptree.hpp>
// FairMQ
#include "FairMQChannel.h"
namespace FairMQParser
@ -39,13 +36,15 @@ struct XML
FairMQMap UserParser(std::stringstream& input, const std::string& deviceId, const std::string& rootNode = "fairMQOptions");
};
namespace helper
namespace Helper
{
void PrintDeviceList(const boost::property_tree::ptree& tree, const std::string& formatFlag = "json");
void DeviceParser(const boost::property_tree::ptree& tree, FairMQMap& channelMap, const std::string& deviceId, const std::string& formatFlag);
void ChannelParser(const boost::property_tree::ptree& tree, FairMQMap& channelMap, const std::string& formatFlag);
void SocketParser(const boost::property_tree::ptree& tree, std::vector<FairMQChannel>& channelList, const FairMQChannel& commonChannel);
}
void PrintDeviceList(const boost::property_tree::ptree& tree, const std::string& formatFlag = "json");
void DeviceParser(const boost::property_tree::ptree& tree, FairMQMap& channelMap, const std::string& deviceId, const std::string& formatFlag);
void ChannelParser(const boost::property_tree::ptree& tree, FairMQMap& channelMap, const std::string& formatFlag);
void SocketParser(const boost::property_tree::ptree& tree, std::vector<FairMQChannel>& channelList, const std::string& channelName, const FairMQChannel& commonChannel);
} // Helper namespace
} // FairMQParser namespace

View File

@ -16,6 +16,7 @@
#include <algorithm>
#include "FairMQParser.h"
#include "FairMQLogger.h"
using namespace std;
FairMQProgOptions::FairMQProgOptions()
@ -41,7 +42,6 @@ FairMQProgOptions::~FairMQProgOptions()
void FairMQProgOptions::ParseAll(const int argc, char** argv, bool allowUnregistered)
{
// init description
InitOptionDescription();
// parse command line options
@ -71,33 +71,37 @@ void FairMQProgOptions::ParseAll(const int argc, char** argv, bool allowUnregist
}
}
// set log level before printing (default is 0 = DEBUG level)
std::string verbosity = GetValue<std::string>("verbose");
std::string verbosity = GetValue<std::string>("verbosity");
std::string logFile = GetValue<std::string>("log-to-file");
bool color = GetValue<bool>("log-color");
if (!color)
// check if the provided verbosity level is valid, otherwise set to DEBUG
if (fSeverityMap.count(verbosity) == 0)
{
reinit_logger(false);
LOG(ERROR) << " verbosity level '" << verbosity << "' unknown, it will be set to DEBUG";
verbosity = "DEBUG";
}
if (fSeverityMap.count(verbosity))
if (logFile != "")
{
DefaultConsoleSetFilter(fSeverityMap.at(verbosity));// return 1 if not success
//set_global_log_level(log_op::operation::GREATER_EQ_THAN, fSeverityMap.at(verbosity));
reinit_logger(false, logFile, fSeverityMap.at(verbosity));
DefaultConsoleSetFilter(fSeverityMap.at("NOLOG"));
}
else
{
LOG(ERROR) << " verbosity level '" << verbosity << "' unknown, it will be set to DEBUG";
//set_global_log_level(log_op::operation::GREATER_EQ_THAN, fSeverityMap.at("DEBUG"));
DefaultConsoleSetFilter(fSeverityMap.at("DEBUG"));
if (!color)
{
reinit_logger(false);
}
DefaultConsoleSetFilter(fSeverityMap.at(verbosity));
}
// check if one of required MQ config option is there
auto parserOption_shptr = fMQParserOptions.options();
auto parserOptions = fMQParserOptions.options();
bool optionExists = false;
vector<string> MQParserKeys;
for (const auto& p : parserOption_shptr)
for (const auto& p : parserOptions)
{
MQParserKeys.push_back(p->canonical_display_name());
if (fVarMap.count(p->canonical_display_name()))
@ -164,9 +168,18 @@ void FairMQProgOptions::ParseAll(const int argc, char** argv, bool allowUnregist
{
LOG(DEBUG) << "config-json-string: Parsing JSON string";
std::string id = fVarMap["id"].as<std::string>();
std::string id;
std::string value = fairmq::ConvertVariableValue<fairmq::ToString>().Run(fVarMap.at("config-json-string"));
if (fVarMap.count("config-key"))
{
id = fVarMap["config-key"].as<std::string>();
}
else
{
id = fVarMap["id"].as<std::string>();
}
std::string value = FairMQ::ConvertVariableValue<FairMQ::ToString>().Run(fVarMap.at("config-json-string"));
std::stringstream ss;
ss << value;
UserParser<FairMQParser::JSON>(ss, id);
@ -175,14 +188,24 @@ void FairMQProgOptions::ParseAll(const int argc, char** argv, bool allowUnregist
{
LOG(DEBUG) << "config-json-string: Parsing XML string";
std::string id = fVarMap["id"].as<std::string>();
std::string id;
std::string value = fairmq::ConvertVariableValue<fairmq::ToString>().Run(fVarMap.at("config-xml-string"));
if (fVarMap.count("config-key"))
{
id = fVarMap["config-key"].as<std::string>();
}
else
{
id = fVarMap["id"].as<std::string>();
}
std::string value = FairMQ::ConvertVariableValue<FairMQ::ToString>().Run(fVarMap.at("config-xml-string"));
std::stringstream ss;
ss << value;
UserParser<FairMQParser::XML>(ss, id);
}
}
FairProgOptions::PrintOptions();
}
@ -301,6 +324,8 @@ void FairMQProgOptions::InitOptionDescription()
("control", po::value<string>()->default_value("interactive"), "States control ('interactive'/'static'/'dds').")
("network-interface", po::value<string>()->default_value("eth0"), "Network interface to bind on (e.g. eth0, ib0, wlan0, en0, lo...).")
("config-key", po::value<string>(), "Use provided value instead of device id for fetching the configuration from the config file")
("catch-signals", po::value<int >()->default_value(1), "Enable signal handling (1/0)")
("log-to-file", po::value<string>()->default_value(""), "Log output to a file")
;
fMQOptionsInCfg.add_options()
@ -311,6 +336,8 @@ void FairMQProgOptions::InitOptionDescription()
("control", po::value<string>()->default_value("interactive"), "States control ('interactive'/'static'/'dds').")
("network-interface", po::value<string>()->default_value("eth0"), "Network interface to bind on (e.g. eth0, ib0, wlan0, en0, lo...).")
("config-key", po::value<string>(), "Use provided value instead of device id for fetching the configuration from the config file")
("catch-signals", po::value<int >()->default_value(1), "Enable signal handling (1/0)")
("log-to-file", po::value<string>()->default_value(""), "Log output to a file")
;
}
else
@ -323,6 +350,8 @@ void FairMQProgOptions::InitOptionDescription()
("control", po::value<string>()->default_value("interactive"), "States control ('interactive'/'static'/'dds').")
("network-interface", po::value<string>()->default_value("eth0"), "Network interface to bind on (e.g. eth0, ib0, wlan0, en0, lo...).")
("config-key", po::value<string>(), "Use provided value instead of device id for fetching the configuration from the config file")
("catch-signals", po::value<int >()->default_value(1), "Enable signal handling (1/0)")
("log-to-file", po::value<string>()->default_value(""), "Log output to a file")
;
}

View File

@ -20,13 +20,10 @@
#include <map>
#include <set>
#include "FairProgOptions.h"
#include "FairMQEventManager.h"
#include "FairMQChannel.h"
class FairMQProgOptions : public FairProgOptions , public FairMQEventManager
{
protected:
@ -98,7 +95,7 @@ class FairMQProgOptions : public FairProgOptions , public FairMQEventManager
{
if(!fairmq::is_this_type<std::string>(fVarMap.at(key)))
if(!FairMQ::is_this_type<std::string>(fVarMap.at(key)))
{
LOG(ERROR) << "You try to update a value as string (for key="<< key <<") while it has been defined with a different type in the option description.";
abort();
@ -238,9 +235,6 @@ class FairMQProgOptions : public FairProgOptions , public FairMQEventManager
std::string fHelpTitle;
std::string fVersion;
bool EventKeyFound(const std::string& key)
{
if (
@ -251,8 +245,6 @@ class FairMQProgOptions : public FairProgOptions , public FairMQEventManager
return false;
}
typedef std::tuple<std::string,int,std::string> MQKey;//store key info
std::map<std::string,MQKey> fMQKeyMap;// key=full path - val=key info
@ -264,9 +256,7 @@ class FairMQProgOptions : public FairProgOptions , public FairMQEventManager
void UpdateMQValues();
int Store(const FairMQMap& channels);
private:
/*
// string API
std::map<std::string, signal_type_ptr > fSignalMap;
@ -299,6 +289,4 @@ class FairMQProgOptions : public FairProgOptions , public FairMQEventManager
}
};
#endif /* FAIRMQPROGOPTIONS_H */

View File

@ -28,7 +28,7 @@ FairProgOptions::FairProgOptions() :
fConfigFileOptions("Configuration file options"),
fSeverityMap(),
fVisibleOptions("Visible options"),
fVerboseLvl("INFO"),
fVerbosityLevel("INFO"),
fUseConfigFile(false),
fConfigFile()
{
@ -37,27 +37,27 @@ FairProgOptions::FairProgOptions() :
fGenericDesc.add_options()
("help,h", "produce help")
("version,v", "print version")
("verbose", po::value<std::string>(&fVerboseLvl)->default_value("DEBUG"), "Verbosity level : \n"
" TRACE \n"
" DEBUG \n"
" RESULTS \n"
" INFO \n"
" WARN \n"
" ERROR \n"
" STATE \n"
" NOLOG"
("verbosity", po::value<std::string>(&fVerbosityLevel)->default_value("DEBUG"), "Verbosity level : \n"
" TRACE \n"
" DEBUG \n"
" RESULTS \n"
" INFO \n"
" WARN \n"
" ERROR \n"
" STATE \n"
" NOLOG"
)
("log-color", po::value<bool>()->default_value(true), "logger color: true or false")
;
fSeverityMap["TRACE"] = fairmq::severity_level::TRACE;
fSeverityMap["DEBUG"] = fairmq::severity_level::DEBUG;
fSeverityMap["RESULTS"] = fairmq::severity_level::RESULTS;
fSeverityMap["INFO"] = fairmq::severity_level::INFO;
fSeverityMap["WARN"] = fairmq::severity_level::WARN;
fSeverityMap["ERROR"] = fairmq::severity_level::ERROR;
fSeverityMap["STATE"] = fairmq::severity_level::STATE;
fSeverityMap["NOLOG"] = fairmq::severity_level::NOLOG;
fSeverityMap["TRACE"] = FairMQ::severity_level::TRACE;
fSeverityMap["DEBUG"] = FairMQ::severity_level::DEBUG;
fSeverityMap["RESULTS"] = FairMQ::severity_level::RESULTS;
fSeverityMap["INFO"] = FairMQ::severity_level::INFO;
fSeverityMap["WARN"] = FairMQ::severity_level::WARN;
fSeverityMap["ERROR"] = FairMQ::severity_level::ERROR;
fSeverityMap["STATE"] = FairMQ::severity_level::STATE;
fSeverityMap["NOLOG"] = FairMQ::severity_level::NOLOG;
}
/// Destructor
@ -221,7 +221,7 @@ string FairProgOptions::GetStringValue(const string& key)
{
if (fVarMap.count(key))
{
valueStr=fairmq::ConvertVariableValue<fairmq::ToString>().Run(fVarMap.at(key));
valueStr=FairMQ::ConvertVariableValue<FairMQ::ToString>().Run(fVarMap.at(key));
}
}
catch(exception& e)
@ -288,8 +288,8 @@ int FairProgOptions::PrintOptions()
// formatting and printing
LOG(INFO) << setfill ('*') << setw (totalLength + 3) << "*";// +3 because of string " = "
string PrintOptionsTitle = " Program options found ";
LOG(DEBUG) << setfill ('*') << setw (totalLength + 3) << "*";// +3 because of string " = "
string PrintOptionsTitle = " Configuration ";
int leftSpaceLength = 0;
int rightSpaceLength = 0;
@ -313,11 +313,11 @@ int FairProgOptions::PrintOptions()
rightSpaceLength = (totalLength + 3) / 2 - rightTitleShiftLength;
}
LOG(INFO) << setfill ('*') << setw(leftSpaceLength) << "*"
LOG(DEBUG) << setfill ('*') << setw(leftSpaceLength) << "*"
<< setw(PrintOptionsTitle.length()) << PrintOptionsTitle
<< setfill ('*') << setw(rightSpaceLength) << "*";
LOG(INFO) << setfill ('*') << setw (totalLength+3) << "*";
LOG(DEBUG) << setfill ('*') << setw (totalLength+3) << "*";
for (const auto& p : mapinfo)
{
@ -328,7 +328,7 @@ int FairProgOptions::PrintOptions()
string emptyStr;
keyStr = p.first;
tie(valueStr, typeInfoStr, defaultStr, emptyStr) = p.second;
LOG(INFO) << std::setfill(' ')
LOG(DEBUG) << std::setfill(' ')
<< setw(maxLength1st) << left
<< p.first << " = "
<< setw(maxLength2nd)
@ -340,7 +340,7 @@ int FairProgOptions::PrintOptions()
<< setw(maxLengthEmpty)
<< emptyStr;
}
LOG(INFO) << setfill ('*') << setw (totalLength + 3) << "*";// +3 for " = "
LOG(DEBUG) << setfill ('*') << setw (totalLength + 3) << "*";// +3 for " = "
return 0;
}
@ -365,5 +365,5 @@ int FairProgOptions::NotifySwitchOption()
FairProgOptions::VarValInfo_t FairProgOptions::GetVariableValueInfo(const po::variable_value& varValue)
{
return fairmq::ConvertVariableValue<fairmq::ToVarInfo>().Run(varValue);
return FairMQ::ConvertVariableValue<FairMQ::ToVarInfo>().Run(varValue);
}

View File

@ -54,7 +54,6 @@
* }
*/
namespace po = boost::program_options;
namespace fs = boost::filesystem;
@ -150,10 +149,10 @@ class FairProgOptions
// Description which is printed in help command line
// to handle logger severity
std::map<std::string,fairmq::severity_level> fSeverityMap;
std::map<std::string, FairMQ::severity_level> fSeverityMap;
po::options_description fVisibleOptions;
std::string fVerboseLvl;
std::string fVerbosityLevel;
bool fUseConfigFile;
boost::filesystem::path fConfigFile;
virtual int NotifySwitchOption();

View File

@ -32,213 +32,205 @@ std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
return os;
}
namespace fairmq
namespace FairMQ
{
namespace po = boost::program_options;
//_____________________________________________________________________________________________________________________________
namespace po = boost::program_options;
template<typename T>
bool is_this_type(const po::variable_value& varValue)
template<typename T>
bool is_this_type(const po::variable_value& varValue)
{
auto& value = varValue.value();
if (auto q = boost::any_cast<T>(&value))
return true;
else
return false;
}
template<typename T>
std::string ConvertVariableValueToString(const po::variable_value& varValue)
{
auto& value = varValue.value();
std::ostringstream ostr;
if (auto q = boost::any_cast<T>(&value))
{
auto& value = varValue.value();
if (auto q = boost::any_cast<T>(&value))
return true;
else
return false;
ostr << *q;
}
std::string valueStr = ostr.str();
return valueStr;
}
//_____________________________________________________________________________________________________________________________
template<typename T>
std::string ConvertVariableValueToString(const po::variable_value& varValue)
// string specialization
template<>
inline std::string ConvertVariableValueToString<std::string>(const po::variable_value& varValue)
{
auto& value = varValue.value();
std::string valueStr;
if (auto q = boost::any_cast<std::string>(&value))
{
auto& value = varValue.value();
std::ostringstream ostr;
if (auto q = boost::any_cast<T>(&value))
{
ostr << *q;
}
std::string valueStr = ostr.str();
return valueStr;
valueStr = *q;
}
return valueStr;
}
// string specialization
template<>
inline std::string ConvertVariableValueToString<std::string>(const po::variable_value& varValue)
// boost::filesystem::path specialization
template<>
inline std::string ConvertVariableValueToString<boost::filesystem::path>(const po::variable_value& varValue)
{
auto& value = varValue.value();
std::string valueStr;
if (auto q = boost::any_cast<boost::filesystem::path>(&value))
{
auto& value = varValue.value();
std::string valueStr;
if (auto q = boost::any_cast<std::string>(&value))
{
valueStr = *q;
}
return valueStr;
}
// boost::filesystem::path specialization
template<>
inline std::string ConvertVariableValueToString<boost::filesystem::path>(const po::variable_value& varValue)
{
auto& value = varValue.value();
std::string valueStr;
if (auto q = boost::any_cast<boost::filesystem::path>(&value))
{
valueStr = (*q).string();
}
return valueStr;
valueStr = (*q).string();
}
return valueStr;
}
#if defined(__GNUC__) || defined(__GNUG__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#endif
//_____________________________________________________________________________________________________________________________
// policy to convert boost variable value into string
struct ToString
{
typedef std::string returned_type;
template<typename T>
std::string Value(const po::variable_value& varValue,const std::string&, const std::string&, const std::string&)
{
return ConvertVariableValueToString<T>(varValue);
}
returned_type DefaultValue(const std::string&, const std::string&)
{
return std::string("empty value");
}
};
//_____________________________________________________________________________________________________________________________
// policy to convert variable value content into a tuple with value, type, defaulted, empty information
struct ToVarInfo
{
typedef std::tuple<std::string, std::string,std::string, std::string> returned_type;
template<typename T>
returned_type Value(const po::variable_value& varValue,const std::string& type, const std::string& defaulted, const std::string& empty)
{
std::string valueStr = ConvertVariableValueToString<T>(varValue);
return make_tuple(valueStr, type, defaulted, empty);
}
returned_type DefaultValue(const std::string& defaulted, const std::string& empty)
{
return make_tuple(std::string("Unknown value"), std::string(" [Type=Unknown]"), defaulted, empty);
}
};
//_____________________________________________________________________________________________________________________________
// host class that take one of the two policy defined above
// policy to convert boost variable value into string
struct ToString
{
typedef std::string returned_type;
template<typename T>
struct ConvertVariableValue : T
std::string Value(const po::variable_value& varValue,const std::string&, const std::string&, const std::string&)
{
//typename T::returned_type Run(const po::variable_value& varValue) //-> decltype(T::returned_type)
auto Run(const po::variable_value& varValue) -> typename T::returned_type
{
std::string defaultedValue;
std::string emptyValue;
return ConvertVariableValueToString<T>(varValue);
}
if (varValue.empty())
returned_type DefaultValue(const std::string&, const std::string&)
{
return std::string("empty value");
}
};
// policy to convert variable value content into a tuple with value, type, defaulted, empty information
struct ToVarInfo
{
typedef std::tuple<std::string, std::string,std::string, std::string> returned_type;
template<typename T>
returned_type Value(const po::variable_value& varValue,const std::string& type, const std::string& defaulted, const std::string& empty)
{
std::string valueStr = ConvertVariableValueToString<T>(varValue);
return make_tuple(valueStr, type, defaulted, empty);
}
returned_type DefaultValue(const std::string& defaulted, const std::string& empty)
{
return make_tuple(std::string("Unknown value"), std::string(" [Unknown]"), defaulted, empty);
}
};
// host class that take one of the two policy defined above
template<typename T>
struct ConvertVariableValue : T
{
//typename T::returned_type Run(const po::variable_value& varValue) //-> decltype(T::returned_type)
auto Run(const po::variable_value& varValue) -> typename T::returned_type
{
std::string defaultedValue;
std::string emptyValue;
if (varValue.empty())
{
emptyValue = " [empty]";
}
else
{
if (varValue.defaulted())
{
emptyValue = " [empty]";
defaultedValue = " [default]";
}
else
{
if (varValue.defaulted())
{
defaultedValue = " [default value]";
}
else
{
defaultedValue = " [provided value]";
}
defaultedValue = " [provided]";
}
emptyValue += " *";
//////////////////////////////// std types
// std::string albeit useless here
if (is_this_type<std::string>(varValue))
return T::template Value<std::string>(varValue,std::string(" [Type=string]"),defaultedValue,emptyValue);
// std::vector<std::string>
if (is_this_type<std::vector<std::string>>(varValue))
return T::template Value<std::vector<std::string>>(varValue,std::string(" [Type=vector<string>]"),defaultedValue,emptyValue);
// int
if (is_this_type<int>(varValue))
return T::template Value<int>(varValue,std::string(" [Type=int]"),defaultedValue,emptyValue);
// std::vector<int>
if (is_this_type<std::vector<int>>(varValue))
return T::template Value<std::vector<int>>(varValue,std::string(" [Type=vector<int>]"),defaultedValue,emptyValue);
// float
if (is_this_type<float>(varValue))
return T::template Value<float>(varValue,std::string(" [Type=float]"),defaultedValue,emptyValue);
// std::vector float
if (is_this_type<std::vector<float>>(varValue))
return T::template Value<std::vector<float>>(varValue,std::string(" [Type=vector<float>]"),defaultedValue,emptyValue);
// double
if (is_this_type<double>(varValue))
return T::template Value<double>(varValue,std::string(" [Type=double]"),defaultedValue,emptyValue);
// std::vector double
if (is_this_type<std::vector<double>>(varValue))
return T::template Value<std::vector<double>>(varValue,std::string(" [Type=vector<double>]"),defaultedValue,emptyValue);
// short
if (is_this_type<short>(varValue))
return T::template Value<short>(varValue,std::string(" [Type=short]"),defaultedValue,emptyValue);
// std::vector short
if (is_this_type<std::vector<short>>(varValue))
return T::template Value<std::vector<short>>(varValue,std::string(" [Type=vector<short>]"),defaultedValue,emptyValue);
// long
if (is_this_type<long>(varValue))
return T::template Value<long>(varValue,std::string(" [Type=long]"),defaultedValue,emptyValue);
// std::vector short
if (is_this_type<std::vector<long>>(varValue))
return T::template Value<std::vector<long>>(varValue,std::string(" [Type=vector<long>]"),defaultedValue,emptyValue);
// size_t
if (is_this_type<std::size_t>(varValue))
return T::template Value<std::size_t>(varValue,std::string(" [Type=std::size_t]"),defaultedValue,emptyValue);
// std::vector size_t
if (is_this_type<std::vector<std::size_t>>(varValue))
return T::template Value<std::vector<std::size_t>>(varValue,std::string(" [Type=vector<std::size_t>]"),defaultedValue,emptyValue);
// bool
if (is_this_type<bool>(varValue))
return T::template Value<bool>(varValue,std::string(" [Type=bool]"),defaultedValue,emptyValue);
// std::vector bool
if (is_this_type<std::vector<bool>>(varValue))
return T::template Value<std::vector<bool>>(varValue,std::string(" [Type=vector<bool>]"),defaultedValue,emptyValue);
//////////////////////////////// boost types
// boost::filesystem::path
if (is_this_type<boost::filesystem::path>(varValue))
return T::template Value<boost::filesystem::path>(varValue,std::string(" [Type=boost::filesystem::path]"),defaultedValue,emptyValue);
// if we get here, the type is not supported return unknown info
return T::DefaultValue(defaultedValue,emptyValue);
}
};
// emptyValue += " *";
//////////////////////////////// std types
// std::string albeit useless here
if (is_this_type<std::string>(varValue))
return T::template Value<std::string>(varValue,std::string(" <string>"),defaultedValue,emptyValue);
// std::vector<std::string>
if (is_this_type<std::vector<std::string>>(varValue))
return T::template Value<std::vector<std::string>>(varValue,std::string(" <vector<string>>"),defaultedValue,emptyValue);
// int
if (is_this_type<int>(varValue))
return T::template Value<int>(varValue,std::string(" <int>"),defaultedValue,emptyValue);
// std::vector<int>
if (is_this_type<std::vector<int>>(varValue))
return T::template Value<std::vector<int>>(varValue,std::string(" <vector<int>>"),defaultedValue,emptyValue);
// float
if (is_this_type<float>(varValue))
return T::template Value<float>(varValue,std::string(" <float>"),defaultedValue,emptyValue);
// std::vector float
if (is_this_type<std::vector<float>>(varValue))
return T::template Value<std::vector<float>>(varValue,std::string(" <vector<float>>"),defaultedValue,emptyValue);
// double
if (is_this_type<double>(varValue))
return T::template Value<double>(varValue,std::string(" <double>"),defaultedValue,emptyValue);
// std::vector double
if (is_this_type<std::vector<double>>(varValue))
return T::template Value<std::vector<double>>(varValue,std::string(" <vector<double>>"),defaultedValue,emptyValue);
// short
if (is_this_type<short>(varValue))
return T::template Value<short>(varValue,std::string(" <short>"),defaultedValue,emptyValue);
// std::vector short
if (is_this_type<std::vector<short>>(varValue))
return T::template Value<std::vector<short>>(varValue,std::string(" <vector<short>>"),defaultedValue,emptyValue);
// long
if (is_this_type<long>(varValue))
return T::template Value<long>(varValue,std::string(" <long>"),defaultedValue,emptyValue);
// std::vector short
if (is_this_type<std::vector<long>>(varValue))
return T::template Value<std::vector<long>>(varValue,std::string(" <vector<long>>"),defaultedValue,emptyValue);
// size_t
if (is_this_type<std::size_t>(varValue))
return T::template Value<std::size_t>(varValue,std::string(" <std::size_t>"),defaultedValue,emptyValue);
// std::vector size_t
if (is_this_type<std::vector<std::size_t>>(varValue))
return T::template Value<std::vector<std::size_t>>(varValue,std::string(" <vector<std::size_t>>"),defaultedValue,emptyValue);
// bool
if (is_this_type<bool>(varValue))
return T::template Value<bool>(varValue,std::string(" <bool>"),defaultedValue,emptyValue);
// std::vector bool
if (is_this_type<std::vector<bool>>(varValue))
return T::template Value<std::vector<bool>>(varValue,std::string(" <vector<bool>>"),defaultedValue,emptyValue);
//////////////////////////////// boost types
// boost::filesystem::path
if (is_this_type<boost::filesystem::path>(varValue))
return T::template Value<boost::filesystem::path>(varValue,std::string(" <boost::filesystem::path>"),defaultedValue,emptyValue);
// if we get here, the type is not supported return unknown info
return T::DefaultValue(defaultedValue,emptyValue);
}
};
#if defined(__GNUC__) || defined(__GNUG__)
#pragma GCC diagnostic pop
#endif
} // FairMQ namespace
};
#endif /* FAIRPROGOPTIONSHELPER_H */
#endif /* FAIRPROGOPTIONSHELPER_H */

View File

@ -115,8 +115,8 @@ int main(int argc, char** argv)
return 0;
// Set severity level (Default is 0=DEBUG)
int verbose=config->GetValue<int>("verbose");
FairMQLogger::Level lvl=static_cast<FairMQLogger::Level>(verbose);
int verbosity = config->GetValue<int>("verbosity");
FairMQLogger::Level lvl=static_cast<FairMQLogger::Level>(verbosity);
SET_LOGGER_LEVEL(lvl);

View File

@ -49,8 +49,8 @@ int main(int argc, char** argv)
return 0;
// Set severity level (Default is 0=DEBUG)
int verbose=config.GetValue<int>("verbose");
FairMQLogger::Level lvl=static_cast<FairMQLogger::Level>(verbose);
int verbosity=config.GetValue<int>("verbosity");
FairMQLogger::Level lvl=static_cast<FairMQLogger::Level>(verbosity);
SET_LOGGER_LEVEL(lvl);
// parse XML file

View File

@ -6,6 +6,6 @@ VERBOSE="DEBUG"
JSONCONFIGFILE="@CMAKE_BINARY_DIR@/bin/config/ex1-sampler-sink.json"
########################## start DEVICE
DEVICE="runConfigExample --transport $TRANSPORT --verbose $VERBOSE"
DEVICE="runConfigExample --transport $TRANSPORT --verbosity $VERBOSE"
DEVICE+=" --id sampler1 --mq-config $JSONCONFIGFILE"
@CMAKE_BINARY_DIR@/bin/$DEVICE

View File

@ -1,59 +1,26 @@
/********************************************************************************
* 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, *
* 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" *
********************************************************************************/
/**
* runBenchmarkSampler.cxx
*
* @since 2013-04-23
* @author D. Klein, A. Rybalchenko
*/
#include <iostream>
#include "boost/program_options.hpp"
#include "FairMQLogger.h"
#include "FairMQProgOptions.h"
#include "runFairMQDevice.h"
#include "FairMQBenchmarkSampler.h"
#include "runSimpleMQStateMachine.h"
using namespace boost::program_options;
namespace bpo = boost::program_options;
int main(int argc, char** argv)
void addCustomOptions(bpo::options_description& options)
{
try
{
int msgSize;
int numMsgs;
int msgRate;
options_description samplerOptions("Sampler options");
samplerOptions.add_options()
("msg-size", value<int>(&msgSize)->default_value(1000), "Message size in bytes")
("num-msgs", value<int>(&numMsgs)->default_value(0), "Number of messages to send")
("msg-rate", value<int>(&msgRate)->default_value(0), "Msg rate limit in maximum number of messages per second");
FairMQProgOptions config;
config.AddToCmdLineOptions(samplerOptions);
config.ParseAll(argc, argv);
FairMQBenchmarkSampler sampler;
sampler.SetProperty(FairMQBenchmarkSampler::MsgSize, msgSize);
sampler.SetProperty(FairMQBenchmarkSampler::NumMsgs, numMsgs);
sampler.SetProperty(FairMQBenchmarkSampler::MsgRate, msgRate);
runStateMachine(sampler, config);
}
catch (std::exception& e)
{
LOG(ERROR) << "Unhandled Exception reached the top of main: "
<< e.what() << ", application will now exit";
return 1;
}
return 0;
options.add_options()
("out-channel", bpo::value<std::string>()->default_value("data-out"), "Name of the output channel")
("msg-size", bpo::value<int>()->default_value(1000), "Message size in bytes")
("num-msgs", bpo::value<int>()->default_value(0), "Number of messages to send")
("msg-rate", bpo::value<int>()->default_value(0), "Msg rate limit in maximum number of messages per second");
}
FairMQDevice* getDevice(const FairMQProgOptions& /*config*/)
{
return new FairMQBenchmarkSampler();
}

View File

@ -1,52 +1,25 @@
/********************************************************************************
* 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, *
* 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" *
********************************************************************************/
/**
* runMerger.cxx
*
* @since 2012-12-06
* @author D. Klein, A. Rybalchenko
*/
#include <iostream>
#include "boost/program_options.hpp"
#include "FairMQLogger.h"
#include "FairMQProgOptions.h"
#include "runFairMQDevice.h"
#include "FairMQMerger.h"
#include "runSimpleMQStateMachine.h"
using namespace boost::program_options;
namespace bpo = boost::program_options;
int main(int argc, char** argv)
void addCustomOptions(bpo::options_description& options)
{
try
{
int multipart;
options_description mergerOptions("Proxy options");
mergerOptions.add_options()
("multipart", value<int>(&multipart)->default_value(1), "Handle multipart payloads");
FairMQProgOptions config;
config.AddToCmdLineOptions(mergerOptions);
config.ParseAll(argc, argv);
FairMQMerger merger;
merger.SetProperty(FairMQMerger::Multipart, multipart);
runStateMachine(merger, config);
}
catch (std::exception& e)
{
LOG(ERROR) << "Unhandled Exception reached the top of main: "
<< e.what() << ", application will now exit";
return 1;
}
return 0;
options.add_options()
("in-channel", bpo::value<std::string>()->default_value("data-in"), "Name of the input channel")
("out-channel", bpo::value<std::string>()->default_value("data-out"), "Name of the output channel")
("multipart", bpo::value<int>()->default_value(1), "Handle multipart payloads");
}
FairMQDevice* getDevice(const FairMQProgOptions& /*config*/)
{
return new FairMQMerger();
}

View File

@ -0,0 +1,25 @@
/********************************************************************************
* 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" *
********************************************************************************/
#include "runFairMQDevice.h"
#include "FairMQMultiplier.h"
namespace bpo = boost::program_options;
void addCustomOptions(bpo::options_description& options)
{
options.add_options()
("in-channel", bpo::value<std::string>()->default_value("data-in"), "Name of the input channel")
("out-channel", bpo::value<std::vector<std::string>>()->multitoken(), "Names of the output channels")
("multipart", bpo::value<int>()->default_value(1), "Handle multipart payloads");
}
FairMQDevice* getDevice(const FairMQProgOptions& /*config*/)
{
return new FairMQMultiplier();
}

View File

@ -1,52 +1,25 @@
/********************************************************************************
* 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, *
* 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" *
********************************************************************************/
/**
* runProxy.cxx
*
* @since 2013-10-07
* @author A. Rybalchenko
*/
#include <iostream>
#include "boost/program_options.hpp"
#include "FairMQLogger.h"
#include "FairMQProgOptions.h"
#include "runFairMQDevice.h"
#include "FairMQProxy.h"
#include "runSimpleMQStateMachine.h"
using namespace boost::program_options;
namespace bpo = boost::program_options;
int main(int argc, char** argv)
void addCustomOptions(bpo::options_description& options)
{
try
{
int multipart;
options_description proxyOptions("Proxy options");
proxyOptions.add_options()
("multipart", value<int>(&multipart)->default_value(1), "Handle multipart payloads");
FairMQProgOptions config;
config.AddToCmdLineOptions(proxyOptions);
config.ParseAll(argc, argv);
FairMQProxy proxy;
proxy.SetProperty(FairMQProxy::Multipart, multipart);
runStateMachine(proxy, config);
}
catch (std::exception& e)
{
LOG(ERROR) << "Unhandled Exception reached the top of main: "
<< e.what() << ", application will now exit";
return 1;
}
return 0;
options.add_options()
("in-channel", bpo::value<std::string>()->default_value("data-in"), "Name of the input channel")
("out-channel", bpo::value<std::string>()->default_value("data-out"), "Name of the output channel")
("multipart", bpo::value<int>()->default_value(1), "Handle multipart payloads");
}
FairMQDevice* getDevice(const FairMQProgOptions& /*config*/)
{
return new FairMQProxy();
}

View File

@ -1,53 +1,24 @@
/********************************************************************************
* 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, *
* 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" *
********************************************************************************/
/**
* runSink.cxx
*
* @since 2013-01-21
* @author: D. Klein, A. Rybalchenko
*/
#include <iostream>
#include "boost/program_options.hpp"
#include "FairMQLogger.h"
#include "FairMQProgOptions.h"
#include "runFairMQDevice.h"
#include "FairMQSink.h"
#include "runSimpleMQStateMachine.h"
using namespace boost::program_options;
namespace bpo = boost::program_options;
int main(int argc, char** argv)
void addCustomOptions(bpo::options_description& options)
{
try
{
int numMsgs;
options_description sinkOptions("Sink options");
sinkOptions.add_options()
("num-msgs", value<int>(&numMsgs)->default_value(0), "Number of messages to receive");
FairMQProgOptions config;
config.AddToCmdLineOptions(sinkOptions);
config.ParseAll(argc, argv);
FairMQSink sink;
sink.SetProperty(FairMQSink::NumMsgs, numMsgs);
runStateMachine(sink, config);
}
catch (std::exception& e)
{
LOG(ERROR) << "Unhandled Exception reached the top of main: "
<< e.what() << ", application will now exit";
return 1;
}
return 0;
options.add_options()
("in-channel", bpo::value<std::string>()->default_value("data-in"), "Name of the input channel")
("num-msgs", bpo::value<int>()->default_value(0), "Number of messages to receive");
}
FairMQDevice* getDevice(const FairMQProgOptions& /*config*/)
{
return new FairMQSink();
}

View File

@ -1,52 +1,25 @@
/********************************************************************************
* 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, *
* 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" *
********************************************************************************/
/**
* runSplitter.cxx
*
* @since 2012-12-06
* @author D. Klein, A. Rybalchenko
*/
#include <iostream>
#include "boost/program_options.hpp"
#include "FairMQLogger.h"
#include "FairMQProgOptions.h"
#include "runFairMQDevice.h"
#include "FairMQSplitter.h"
#include "runSimpleMQStateMachine.h"
using namespace boost::program_options;
namespace bpo = boost::program_options;
int main(int argc, char** argv)
void addCustomOptions(bpo::options_description& options)
{
try
{
int multipart;
options_description proxyOptions("Proxy options");
proxyOptions.add_options()
("multipart", value<int>(&multipart)->default_value(1), "Handle multipart payloads");
FairMQProgOptions config;
config.AddToCmdLineOptions(proxyOptions);
config.ParseAll(argc, argv);
FairMQSplitter splitter;
splitter.SetProperty(FairMQSplitter::Multipart, multipart);
runStateMachine(splitter, config);
}
catch (std::exception& e)
{
LOG(ERROR) << "Unhandled Exception reached the top of main: "
<< e.what() << ", application will now exit";
return 1;
}
return 0;
options.add_options()
("in-channel", bpo::value<std::string>()->default_value("data-in"), "Name of the input channel")
("out-channel", bpo::value<std::string>()->default_value("data-out"), "Name of the output channel")
("multipart", bpo::value<int>()->default_value(1), "Handle multipart payloads");
}
FairMQDevice* getDevice(const FairMQProgOptions& /*config*/)
{
return new FairMQSplitter();
}

67
fairmq/runFairMQDevice.h Normal file
View File

@ -0,0 +1,67 @@
/********************************************************************************
* 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" *
********************************************************************************/
#include <boost/program_options.hpp>
#include "FairMQLogger.h"
#include "FairMQProgOptions.h"
#include "FairMQDevice.h"
#include "runSimpleMQStateMachine.h"
template <typename R>
class GenericFairMQDevice : public FairMQDevice
{
public:
GenericFairMQDevice(R func) : r(func) {}
protected:
virtual bool ConditionalRun() { return r(*static_cast<FairMQDevice*>(this)); }
private:
R r;
};
template <typename R>
FairMQDevice* makeDeviceWithConditionalRun(R r)
{
return new GenericFairMQDevice<R>(r);
}
// to be implemented by the user to return a child class of FairMQDevice
FairMQDevice* getDevice(const FairMQProgOptions& config);
// to be implemented by the user to add custom command line options (or just with empty body)
void addCustomOptions(boost::program_options::options_description&);
int main(int argc, char** argv)
{
try
{
boost::program_options::options_description customOptions("Custom options");
addCustomOptions(customOptions);
FairMQProgOptions config;
config.AddToCmdLineOptions(customOptions);
config.ParseAll(argc, argv);
std::unique_ptr<FairMQDevice> device(getDevice(config));
int result = runStateMachine(*device, config);
if (result > 0)
{
return 1;
}
}
catch (std::exception& e)
{
LOG(ERROR) << "Unhandled Exception reached the top of main: " << e.what() << ", application will now exit";
return 1;
}
return 0;
}

View File

@ -24,65 +24,35 @@ class TransferTimeoutTester : public FairMQDevice
protected:
virtual void Run()
{
// bool setSndOK = false;
// bool setRcvOK = false;
bool getSndOK = false;
bool getRcvOK = false;
bool sendCanceling = false;
bool receiveCanceling = false;
fChannels.at("data-out").at(0).SetSendTimeout(1000);
fChannels.at("data-in").at(0).SetReceiveTimeout(1000);
FairMQMessagePtr msg1(NewMessage());
FairMQMessagePtr msg2(NewMessage());
if (fChannels.at("data-out").at(0).GetSendTimeout() == 1000)
if (Send(msg1, "data-out", 0, 1000) == -2)
{
getSndOK = true;
LOG(INFO) << "get send timeout OK: " << fChannels.at("data-out").at(0).GetSendTimeout();
LOG(INFO) << "send canceled";
sendCanceling = true;
}
else
{
LOG(ERROR) << "get send timeout failed";
LOG(ERROR) << "send did not cancel";
}
if (fChannels.at("data-in").at(0).GetReceiveTimeout() == 1000)
if (Receive(msg2, "data-in", 0, 1000) == -2)
{
getRcvOK = true;
LOG(INFO) << "get receive timeout OK: " << fChannels.at("data-in").at(0).GetReceiveTimeout();
LOG(INFO) << "receive canceled";
receiveCanceling = true;
}
else
{
LOG(ERROR) << "get receive timeout failed";
LOG(ERROR) << "receive did not cancel";
}
if (getSndOK && getRcvOK)
if (sendCanceling && receiveCanceling)
{
std::unique_ptr<FairMQMessage> msg1(NewMessage());
std::unique_ptr<FairMQMessage> msg2(NewMessage());
if (Send(msg1, "data-out") == -2)
{
LOG(INFO) << "send canceled";
sendCanceling = true;
}
else
{
LOG(ERROR) << "send did not cancel";
}
if (Receive(msg2, "data-in") == -2)
{
LOG(INFO) << "receive canceled";
receiveCanceling = true;
}
else
{
LOG(ERROR) << "receive did not cancel";
}
if (sendCanceling && receiveCanceling)
{
LOG(INFO) << "Transfer timeout test successfull";
}
LOG(INFO) << "Transfer timeout test successfull";
}
}
};

View File

@ -8,34 +8,44 @@
#ifndef RUNSIMPLEMQSTATEMACHINE_H
#define RUNSIMPLEMQSTATEMACHINE_H
#include "FairMQLogger.h"
#include "FairMQParser.h"
#include "FairMQProgOptions.h"
#include <iostream>
#include <string>
#include <dlfcn.h>
#ifdef DDS_FOUND
#include "FairMQDDSTools.h"
#endif /*DDS_FOUND*/
#include "FairMQLogger.h"
#include "FairMQParser.h"
#include "FairMQProgOptions.h"
// template function that takes any device
// and runs a simple MQ state machine configured from a JSON file and/or (optionally) DDS.
template<typename TMQDevice>
inline int runStateMachine(TMQDevice& device, FairMQProgOptions& config)
{
device.CatchSignals();
if (config.GetValue<int>("catch-signals") > 0)
{
device.CatchSignals();
}
else
{
LOG(WARN) << "Signal handling (e.g. ctrl+C) has been deactivated via command line argument";
}
device.SetConfig(config);
std::string control = config.GetValue<std::string>("control");
device.ChangeState(TMQDevice::INIT_DEVICE);
#ifdef DDS_FOUND
if (control == "dds")
{
HandleConfigViaDDS(device);
}
#endif /*DDS_FOUND*/
device.WaitForEndOfState(TMQDevice::INIT_DEVICE);
device.ChangeState(TMQDevice::INIT_TASK);
@ -78,7 +88,7 @@ inline int runStateMachine(TMQDevice& device, FairMQProgOptions& config)
<< ", 'dds'"
#endif /*DDS_FOUND*/
<< ". Exiting.";
exit(EXIT_FAILURE);
return 1;
}
return 0;

View File

@ -57,7 +57,7 @@ FairMQPollerZMQ::FairMQPollerZMQ(const vector<FairMQChannel>& channels)
}
}
FairMQPollerZMQ::FairMQPollerZMQ(const unordered_map<string, vector<FairMQChannel>>& channelsMap, const initializer_list<string> channelList)
FairMQPollerZMQ::FairMQPollerZMQ(const unordered_map<string, vector<FairMQChannel>>& channelsMap, const vector<string>& channelList)
: items()
, fNumItems(0)
, fOffsetMap()

View File

@ -34,7 +34,7 @@ class FairMQPollerZMQ : public FairMQPoller
public:
FairMQPollerZMQ(const std::vector<FairMQChannel>& channels);
FairMQPollerZMQ(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::initializer_list<std::string> channelList);
FairMQPollerZMQ(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::vector<std::string>& channelList);
FairMQPollerZMQ(const FairMQPollerZMQ&) = delete;
FairMQPollerZMQ operator=(const FairMQPollerZMQ&) = delete;

View File

@ -23,7 +23,7 @@
using namespace std;
// Context to hold the ZeroMQ sockets
boost::shared_ptr<FairMQContextZMQ> FairMQSocketZMQ::fContext = boost::shared_ptr<FairMQContextZMQ>(new FairMQContextZMQ(1));
std::unique_ptr<FairMQContextZMQ> FairMQSocketZMQ::fContext = std::unique_ptr<FairMQContextZMQ>(new FairMQContextZMQ(1));
FairMQSocketZMQ::FairMQSocketZMQ(const string& type, const string& name, const int numIoThreads, const string& id /*= ""*/)
: FairMQSocket(ZMQ_SNDMORE, ZMQ_RCVMORE, ZMQ_DONTWAIT)

View File

@ -17,7 +17,7 @@
#include <atomic>
#include <boost/shared_ptr.hpp>
#include <memory> // unique_ptr
#include "FairMQSocket.h"
#include "FairMQContextZMQ.h"
@ -72,7 +72,7 @@ class FairMQSocketZMQ : public FairMQSocket
std::atomic<unsigned long> fMessagesTx;
std::atomic<unsigned long> fMessagesRx;
static boost::shared_ptr<FairMQContextZMQ> fContext;
static std::unique_ptr<FairMQContextZMQ> fContext;
};
#endif /* FAIRMQSOCKETZMQ_H_ */

View File

@ -25,37 +25,37 @@ FairMQTransportFactoryZMQ::FairMQTransportFactoryZMQ()
LOG(DEBUG) << "Using ZeroMQ library, version: " << major << "." << minor << "." << patch;
}
FairMQMessage* FairMQTransportFactoryZMQ::CreateMessage()
FairMQMessage* FairMQTransportFactoryZMQ::CreateMessage() const
{
return new FairMQMessageZMQ();
}
FairMQMessage* FairMQTransportFactoryZMQ::CreateMessage(const size_t size)
FairMQMessage* FairMQTransportFactoryZMQ::CreateMessage(const size_t size) const
{
return new FairMQMessageZMQ(size);
}
FairMQMessage* FairMQTransportFactoryZMQ::CreateMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint)
FairMQMessage* FairMQTransportFactoryZMQ::CreateMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint) const
{
return new FairMQMessageZMQ(data, size, ffn, hint);
}
FairMQSocket* FairMQTransportFactoryZMQ::CreateSocket(const string& type, const std::string& name, const int numIoThreads, const std::string& id /*= ""*/)
FairMQSocket* FairMQTransportFactoryZMQ::CreateSocket(const string& type, const std::string& name, const int numIoThreads, const std::string& id /*= ""*/) const
{
return new FairMQSocketZMQ(type, name, numIoThreads, id);
}
FairMQPoller* FairMQTransportFactoryZMQ::CreatePoller(const vector<FairMQChannel>& channels)
FairMQPoller* FairMQTransportFactoryZMQ::CreatePoller(const vector<FairMQChannel>& channels) const
{
return new FairMQPollerZMQ(channels);
}
FairMQPoller* FairMQTransportFactoryZMQ::CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::initializer_list<std::string> channelList)
FairMQPoller* FairMQTransportFactoryZMQ::CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::vector<std::string>& channelList) const
{
return new FairMQPollerZMQ(channelsMap, channelList);
}
FairMQPoller* FairMQTransportFactoryZMQ::CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket)
FairMQPoller* FairMQTransportFactoryZMQ::CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket) const
{
return new FairMQPollerZMQ(cmdSocket, dataSocket);
}

View File

@ -28,15 +28,15 @@ class FairMQTransportFactoryZMQ : public FairMQTransportFactory
public:
FairMQTransportFactoryZMQ();
virtual FairMQMessage* CreateMessage();
virtual FairMQMessage* CreateMessage(const size_t size);
virtual FairMQMessage* CreateMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint = NULL);
virtual FairMQMessage* CreateMessage() const;
virtual FairMQMessage* CreateMessage(const size_t size) const;
virtual FairMQMessage* CreateMessage(void* data, const size_t size, fairmq_free_fn* ffn, void* hint = NULL) const;
virtual FairMQSocket* CreateSocket(const std::string& type, const std::string& name, const int numIoThreads, const std::string& id = "");
virtual FairMQSocket* CreateSocket(const std::string& type, const std::string& name, const int numIoThreads, const std::string& id = "") const;
virtual FairMQPoller* CreatePoller(const std::vector<FairMQChannel>& channels);
virtual FairMQPoller* CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::initializer_list<std::string> channelList);
virtual FairMQPoller* CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket);
virtual FairMQPoller* CreatePoller(const std::vector<FairMQChannel>& channels) const;
virtual FairMQPoller* CreatePoller(const std::unordered_map<std::string, std::vector<FairMQChannel>>& channelsMap, const std::vector<std::string>& channelList) const;
virtual FairMQPoller* CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket) const;
virtual ~FairMQTransportFactoryZMQ() {};
};