From 16fd63cd5b39b097270055f61b2fad227df3eac3 Mon Sep 17 00:00:00 2001 From: Alexey Rybalchenko Date: Wed, 10 Aug 2016 09:47:53 +0200 Subject: [PATCH] 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. --- fairmq/CMakeLists.txt | 22 +- fairmq/FairMQChannel.cxx | 127 +++-- fairmq/FairMQChannel.h | 80 ++- fairmq/FairMQDevice.cxx | 329 +++++++----- fairmq/FairMQDevice.h | 99 +++- fairmq/FairMQMessage.h | 2 + fairmq/FairMQStateMachine.h | 43 +- fairmq/FairMQTransportFactory.h | 14 +- fairmq/README.md | 29 +- fairmq/devices/FairMQBenchmarkSampler.cxx | 143 ++---- fairmq/devices/FairMQBenchmarkSampler.h | 18 +- fairmq/devices/FairMQMerger.cxx | 91 +--- fairmq/devices/FairMQMerger.h | 19 +- fairmq/devices/FairMQMultiplier.cxx | 110 ++++ fairmq/devices/FairMQMultiplier.h | 34 ++ fairmq/devices/FairMQProxy.cxx | 21 +- fairmq/devices/FairMQProxy.h | 5 + fairmq/devices/FairMQSink.cxx | 76 +-- fairmq/devices/FairMQSink.h | 16 +- fairmq/devices/FairMQSplitter.cxx | 133 +---- fairmq/devices/FairMQSplitter.h | 25 +- fairmq/logger/logger.cxx | 238 +++++---- fairmq/logger/logger_def.h | 120 ++--- fairmq/logger/run/testLogger.cxx | 41 +- fairmq/nanomsg/FairMQPollerNN.cxx | 2 +- fairmq/nanomsg/FairMQPollerNN.h | 2 +- fairmq/nanomsg/FairMQTransportFactoryNN.cxx | 14 +- fairmq/nanomsg/FairMQTransportFactoryNN.h | 14 +- fairmq/options/FairMQEventManager.h | 54 +- fairmq/options/FairMQParser.cxx | 474 ++++++++++-------- fairmq/options/FairMQParser.h | 17 +- fairmq/options/FairMQProgOptions.cxx | 67 ++- fairmq/options/FairMQProgOptions.h | 14 +- fairmq/options/FairProgOptions.cxx | 52 +- fairmq/options/FairProgOptions.h | 5 +- fairmq/options/FairProgOptionsHelper.h | 346 +++++++------ .../ProgOptionTest/run/testMQoptions1.cxx | 4 +- .../ProgOptionTest/run/testMQoptions2.cxx | 4 +- fairmq/options/startConfigExample.sh.in | 2 +- fairmq/run/runBenchmarkSampler.cxx | 63 +-- fairmq/run/runMerger.cxx | 55 +- fairmq/run/runMultiplier.cxx | 25 + fairmq/run/runProxy.cxx | 55 +- fairmq/run/runSink.cxx | 55 +- fairmq/run/runSplitter.cxx | 55 +- fairmq/runFairMQDevice.h | 67 +++ fairmq/test/runTransferTimeoutTest.cxx | 54 +- fairmq/tools/runSimpleMQStateMachine.h | 22 +- fairmq/zeromq/FairMQPollerZMQ.cxx | 2 +- fairmq/zeromq/FairMQPollerZMQ.h | 2 +- fairmq/zeromq/FairMQSocketZMQ.cxx | 2 +- fairmq/zeromq/FairMQSocketZMQ.h | 4 +- fairmq/zeromq/FairMQTransportFactoryZMQ.cxx | 14 +- fairmq/zeromq/FairMQTransportFactoryZMQ.h | 14 +- 54 files changed, 1730 insertions(+), 1665 deletions(-) create mode 100644 fairmq/devices/FairMQMultiplier.cxx create mode 100644 fairmq/devices/FairMQMultiplier.h create mode 100644 fairmq/run/runMultiplier.cxx create mode 100644 fairmq/runFairMQDevice.h diff --git a/fairmq/CMakeLists.txt b/fairmq/CMakeLists.txt index eafaddd0..6cc7dd6e 100644 --- a/fairmq/CMakeLists.txt +++ b/fairmq/CMakeLists.txt @@ -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 ) - diff --git a/fairmq/FairMQChannel.cxx b/fairmq/FairMQChannel.cxx index 85e878c0..e34c7b37 100644 --- a/fairmq/FairMQChannel.cxx +++ b/fairmq/FairMQChannel.cxx @@ -23,6 +23,8 @@ using namespace std; boost::mutex FairMQChannel::fChannelMutex; +std::atomic 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& msg) const +int FairMQChannel::Send(const unique_ptr& 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& msg) const return -2; } -int FairMQChannel::Receive(const unique_ptr& msg) const +int FairMQChannel::Receive(const unique_ptr& 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& msg) const return -2; } -int64_t FairMQChannel::Send(const std::vector>& msgVec) const +int64_t FairMQChannel::Send(const std::vector>& 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>& m return -2; } -int64_t FairMQChannel::Receive(std::vector>& msgVec) const +int64_t FairMQChannel::Receive(std::vector>& 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>& 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; diff --git a/fairmq/FairMQChannel.h b/fairmq/FairMQChannel.h index cb496336..5d06788b 100644 --- a/fairmq/FairMQChannel.h +++ b/fairmq/FairMQChannel.h @@ -17,6 +17,7 @@ #include #include // unique_ptr +#include #include @@ -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& msg) const; + int Send(const std::unique_ptr& 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>& msgVec) const; + int64_t Send(const std::vector>& 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& msg) const; + int Receive(const std::unique_ptr& 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>& msgVec) const; + int64_t Receive(std::vector>& 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 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 fInterrupted; }; #endif /* FAIRMQCHANNEL_H_ */ diff --git a/fairmq/FairMQDevice.cxx b/fairmq/FairMQDevice.cxx index d7f99f5d..98bb4c36 100644 --- a/fairmq/FairMQDevice.cxx +++ b/fairmq/FairMQDevice.cxx @@ -21,6 +21,7 @@ #include // for the InteractiveStateLoop #include +#include #include #include // for choosing random port in range #include // 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(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 inputChannelKeys; + for (const auto& i: fMsgInputs) + { + inputChannelKeys.push_back(i.first); + } + for (const auto& i: fMultipartInputs) + { + inputChannelKeys.push_back(i.first); + } + + unique_ptr 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 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 filteredSockets; vector filteredChannelNames; + vector logIntervals; + vector 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 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(bytesInNew.at(i) - bytesIn.at(i)) / (1024. * 1024.)) / static_cast(msSinceLastLog) * 1000.; - bytesIn.at(i) = bytesInNew.at(i); + intervalCounters.at(i)++; - msgInNew.at(i) = (*itr)->GetMessagesRx(); - msgPerSecIn.at(i) = static_cast(msgInNew.at(i) - msgIn.at(i)) / static_cast(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(bytesOutNew.at(i) - bytesOut.at(i)) / (1024. * 1024.)) / static_cast(msSinceLastLog) * 1000.; - bytesOut.at(i) = bytesOutNew.at(i); + bytesInNew.at(i) = vi->GetBytesRx(); + mbPerSecIn.at(i) = (static_cast(bytesInNew.at(i) - bytesIn.at(i)) / (1024. * 1024.)) / static_cast(msSinceLastLog) * 1000.; + bytesIn.at(i) = bytesInNew.at(i); - msgOutNew.at(i) = (*itr)->GetMessagesTx(); - msgPerSecOut.at(i) = static_cast(msgOutNew.at(i) - msgOut.at(i)) / static_cast(msSinceLastLog) * 1000.; - msgOut.at(i) = msgOutNew.at(i); + msgInNew.at(i) = vi->GetMessagesRx(); + msgPerSecIn.at(i) = static_cast(msgInNew.at(i) - msgIn.at(i)) / static_cast(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(bytesOutNew.at(i) - bytesOut.at(i)) / (1024. * 1024.)) / static_cast(msSinceLastLog) * 1000.; + bytesOut.at(i) = bytesOutNew.at(i); + + msgOutNew.at(i) = vi->GetMessagesTx(); + msgPerSecOut.at(i) = static_cast(msgOutNew.at(i) - msgOut.at(i)) / static_cast(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; } } } diff --git a/fairmq/FairMQDevice.h b/fairmq/FairMQDevice.h index 6c078c54..82f23d91 100644 --- a/fairmq/FairMQDevice.h +++ b/fairmq/FairMQDevice.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -33,8 +34,19 @@ #include "FairMQMessage.h" #include "FairMQParts.h" +typedef std::unordered_map> FairMQChannelMap; + +typedef std::function&, int)> InputMsgCallback; +typedef std::function InputMultipartCallback; + class FairMQProgOptions; +template +void FairMQSimpleMsgCleanup(void* /*data*/, void* hint) +{ + delete static_cast(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& msg, const std::string& chan, const int i = 0) const + inline int Send(const std::unique_ptr& 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& msg, const std::string& chan, const int i = 0) const + inline int Receive(const std::unique_ptr& 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 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 + inline FairMQMessage* NewSimpleMessage(const T& data) const + { + T* dataCopy = new T(data); + return fTransportFactory->CreateMessage(dataCopy, sizeof(T), FairMQSimpleMsgCleanup, dataCopy); + } + + template + inline FairMQMessage* NewSimpleMessage(const char(&data)[N]) const + { + std::string* msgStr = new std::string(data); + return fTransportFactory->CreateMessage(const_cast(msgStr->c_str()), msgStr->length(), FairMQSimpleMsgCleanup, msgStr); + } + + inline FairMQMessage* NewSimpleMessage(const std::string& str) const + { + std::string* msgStr = new std::string(str); + return fTransportFactory->CreateMessage(const_cast(msgStr->c_str()), msgStr->length(), FairMQSimpleMsgCleanup, 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> fChannels; ///< Device channels + FairMQProgOptions* fConfig; ///< Program options configuration + + template + void OnData(const std::string& channelName, bool (T::* memberFunction)(std::unique_ptr& msg, int index)) + { + fDataCallbacks = true; + fMsgInputs.insert(std::make_pair(channelName, [this, memberFunction](std::unique_ptr& msg, int index) + { + return (static_cast(this)->*memberFunction)(msg, index); + })); + } + + void OnData(const std::string& channelName, InputMsgCallback); + + template + 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(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 fRunning; + std::atomic fInteractiveRunning; + + bool fDataCallbacks; + std::unordered_map fMsgInputs; + std::unordered_map fMultipartInputs; }; #endif /* FAIRMQDEVICE_H_ */ diff --git a/fairmq/FairMQMessage.h b/fairmq/FairMQMessage.h index 1e66f9c1..d8dbf3a2 100644 --- a/fairmq/FairMQMessage.h +++ b/fairmq/FairMQMessage.h @@ -39,4 +39,6 @@ class FairMQMessage virtual ~FairMQMessage() {}; }; +using FairMQMessagePtr = std::unique_ptr; + #endif /* FAIRMQMESSAGE_H_ */ diff --git a/fairmq/FairMQStateMachine.h b/fairmq/FairMQStateMachine.h index 6f0aff8b..c36235a3 100644 --- a/fairmq/FairMQStateMachine.h +++ b/fairmq/FairMQStateMachine.h @@ -31,7 +31,10 @@ // This #define has to be before any msm header includes #define FUSION_MAX_VECTOR_SIZE 20 +#include #include +#include +#include #include #include @@ -233,7 +236,7 @@ struct FairMQFSM_ : public msm::front::state_machine_def template 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 template 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 template 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 // Start Event Next Action Guard // +------------------------+----------------------+------------------------+----------------+---------+ msmf::Row, + msmf::Row, msmf::Row, msmf::Row, + msmf::Row, msmf::Row, msmf::Row, + msmf::Row, msmf::Row, - msmf::Row, msmf::Row, msmf::Row, - msmf::Row, - msmf::Row, - msmf::Row, - msmf::Row, msmf::Row, - msmf::Row, + msmf::Row, + msmf::Row, + msmf::Row, msmf::Row> {}; @@ -369,7 +372,25 @@ struct FairMQFSM_ : public msm::front::state_machine_def template 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::type recursive_stt; + typedef typename boost::msm::back::generate_state_set::type all_states; + std::string stateName; + boost::mpl::for_each >(boost::msm::back::get_state_name(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 boost::thread fTerminateStateThread; // condition variable to notify parent thread about end of state. - bool fStateFinished; + std::atomic fStateFinished; boost::condition_variable fStateCondition; boost::mutex fStateMutex; diff --git a/fairmq/FairMQTransportFactory.h b/fairmq/FairMQTransportFactory.h index bd5fd5ff..82e94053 100644 --- a/fairmq/FairMQTransportFactory.h +++ b/fairmq/FairMQTransportFactory.h @@ -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& channels) = 0; - virtual FairMQPoller* CreatePoller(const std::unordered_map>& channelsMap, const std::initializer_list channelList) = 0; - virtual FairMQPoller* CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket) = 0; + virtual FairMQPoller* CreatePoller(const std::vector& channels) const = 0; + virtual FairMQPoller* CreatePoller(const std::unordered_map>& channelsMap, const std::vector& channelList) const = 0; + virtual FairMQPoller* CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket) const = 0; virtual ~FairMQTransportFactory() {}; }; diff --git a/fairmq/README.md b/fairmq/README.md index 30a0c541..af3f3bc6 100644 --- a/fairmq/README.md +++ b/fairmq/README.md @@ -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("")` 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. diff --git a/fairmq/devices/FairMQBenchmarkSampler.cxx b/fairmq/devices/FairMQBenchmarkSampler.cxx index 9cb19ce1..c29dbc1b 100644 --- a/fairmq/devices/FairMQBenchmarkSampler.cxx +++ b/fairmq/devices/FairMQBenchmarkSampler.cxx @@ -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("msg-size"); + fNumMsgs = fConfig->GetValue("num-msgs"); + fMsgRate = fConfig->GetValue("msg-rate"); + fOutChannelName = fConfig->GetValue("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 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 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) << "---------------------------"; -} diff --git a/fairmq/devices/FairMQBenchmarkSampler.h b/fairmq/devices/FairMQBenchmarkSampler.h index 4566f29d..e0000249 100644 --- a/fairmq/devices/FairMQBenchmarkSampler.h +++ b/fairmq/devices/FairMQBenchmarkSampler.h @@ -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(); }; diff --git a/fairmq/devices/FairMQMerger.cxx b/fairmq/devices/FairMQMerger.cxx index 975c7b3e..5f866223 100644 --- a/fairmq/devices/FairMQMerger.cxx +++ b/fairmq/devices/FairMQMerger.cxx @@ -12,17 +12,17 @@ * @author D. Klein, A. Rybalchenko */ -#include -#include - #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("multipart"); + fInChannelName = fConfig->GetValue("in-channel"); + fOutChannelName = fConfig->GetValue("out-channel"); +} + void FairMQMerger::Run() { - int numInputs = fChannels.at("data-in").size(); + int numInputs = fChannels.at(fInChannelName).size(); - std::unique_ptr poller(fTransportFactory->CreatePoller(fChannels.at("data-in"))); + std::unique_ptr 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 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) << "---------------------------"; -} diff --git a/fairmq/devices/FairMQMerger.h b/fairmq/devices/FairMQMerger.h index d6385330..7f2bda2f 100644 --- a/fairmq/devices/FairMQMerger.h +++ b/fairmq/devices/FairMQMerger.h @@ -17,30 +17,21 @@ #include "FairMQDevice.h" +#include + 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_ */ diff --git a/fairmq/devices/FairMQMultiplier.cxx b/fairmq/devices/FairMQMultiplier.cxx new file mode 100644 index 00000000..d0ab9092 --- /dev/null +++ b/fairmq/devices/FairMQMultiplier.cxx @@ -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("multipart"); + fInChannelName = fConfig->GetValue("in-channel"); + fOutChannelNames = fConfig->GetValue>("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& 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; +} diff --git a/fairmq/devices/FairMQMultiplier.h b/fairmq/devices/FairMQMultiplier.h new file mode 100644 index 00000000..1dfec2c3 --- /dev/null +++ b/fairmq/devices/FairMQMultiplier.h @@ -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 + +class FairMQMultiplier : public FairMQDevice +{ + public: + FairMQMultiplier(); + virtual ~FairMQMultiplier(); + + protected: + int fMultipart; + int fNumOutputs; + std::string fInChannelName; + std::vector fOutChannelNames; + + virtual void InitTask(); + + bool HandleSingleData(std::unique_ptr&, int); + bool HandleMultipartData(FairMQParts&, int); +}; + +#endif /* FAIRMQMULTIPLIER_H_ */ diff --git a/fairmq/devices/FairMQProxy.cxx b/fairmq/devices/FairMQProxy.cxx index d4feb820..66d83f4e 100644 --- a/fairmq/devices/FairMQProxy.cxx +++ b/fairmq/devices/FairMQProxy.cxx @@ -12,16 +12,16 @@ * @author A. Rybalchenko */ -#include -#include - #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("multipart"); + fInChannelName = fConfig->GetValue("in-channel"); + fOutChannelName = fConfig->GetValue("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 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; diff --git a/fairmq/devices/FairMQProxy.h b/fairmq/devices/FairMQProxy.h index d9c0de51..e2fbf125 100644 --- a/fairmq/devices/FairMQProxy.h +++ b/fairmq/devices/FairMQProxy.h @@ -17,6 +17,8 @@ #include "FairMQDevice.h" +#include + 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_ */ diff --git a/fairmq/devices/FairMQSink.cxx b/fairmq/devices/FairMQSink.cxx index 8a8a11c9..5a8ed3c0 100644 --- a/fairmq/devices/FairMQSink.cxx +++ b/fairmq/devices/FairMQSink.cxx @@ -12,25 +12,31 @@ * @author D. Klein, A. Rybalchenko */ -#include -#include #include #include "FairMQSink.h" #include "FairMQLogger.h" +#include "FairMQProgOptions.h" using namespace std; FairMQSink::FairMQSink() : fNumMsgs(0) + , fInChannelName() { } +void FairMQSink::InitTask() +{ + fNumMsgs = fConfig->GetValue("num-msgs"); + fInChannelName = fConfig->GetValue("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) << "---------------------------"; -} diff --git a/fairmq/devices/FairMQSink.h b/fairmq/devices/FairMQSink.h index c1bbccd2..085dcfef 100644 --- a/fairmq/devices/FairMQSink.h +++ b/fairmq/devices/FairMQSink.h @@ -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_ */ diff --git a/fairmq/devices/FairMQSplitter.cxx b/fairmq/devices/FairMQSplitter.cxx index 2c1fe1ae..ecd3d191 100644 --- a/fairmq/devices/FairMQSplitter.cxx +++ b/fairmq/devices/FairMQSplitter.cxx @@ -12,16 +12,18 @@ * @author D. Klein, A. Rybalchenko */ -#include -#include - #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("multipart"); + fInChannelName = fConfig->GetValue("in-channel"); + fOutChannelName = fConfig->GetValue("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 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) << "---------------------------"; -} - diff --git a/fairmq/devices/FairMQSplitter.h b/fairmq/devices/FairMQSplitter.h index 44515235..f7ce71ad 100644 --- a/fairmq/devices/FairMQSplitter.h +++ b/fairmq/devices/FairMQSplitter.h @@ -17,30 +17,25 @@ #include "FairMQDevice.h" +#include + 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&, int); + bool HandleMultipartData(FairMQParts&, int); }; #endif /* FAIRMQSPLITTER_H_ */ diff --git a/fairmq/logger/logger.cxx b/fairmq/logger/logger.cxx index 266aaeed..9c21a44b 100644 --- a/fairmq/logger/logger.cxx +++ b/fairmq/logger/logger.cxx @@ -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 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> sinkList;// global var +} // end Logger namespace +} // end FairMQ namespace - - -namespace FairMQ{ -namespace Logger{ - std::vector >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 text_sink; - void reinit_logger(bool color, const std::string& filename, custom_severity_level threshold) + RemoveRegisteredSinks(); + + // CONSOLE - all severity except error + boost::shared_ptr sink = boost::make_shared(); + // add "console" output stream to our sink + sink->locked_backend()->add_stream(boost::shared_ptr(&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); + } + else + { + sink->set_formatter(&InitLogFormatter); } - // console sink related functions - void DefaultConsoleInit(bool color/* = true*/) - { - // add a text sink - typedef sinks::synchronous_sink 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 sink_error = boost::make_shared(); + sink_error->locked_backend()->add_stream(boost::shared_ptr(&std::cerr, empty_deleter_t())); - // CONSOLE - all severity except error - boost::shared_ptr sink = boost::make_shared(); - // add "console" output stream to our sink - sink->locked_backend()->add_stream(boost::shared_ptr(&std::clog, empty_deleter_t())); + if (color) + { + sink_error->set_formatter(&InitLogFormatter); + } + else + { + sink_error->set_formatter(&InitLogFormatter); + } - // specify the format of the log message - if (color) - { - sink->set_formatter(&InitLogFormatter); - } - else - { - sink->set_formatter(&InitLogFormatter); - } + 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 sink_error = boost::make_shared(); - sink_error->locked_backend()->add_stream(boost::shared_ptr(&std::cerr, empty_deleter_t())); - - if (color) - { - sink_error->set_formatter(&InitLogFormatter); - } - else - { - sink_error->set_formatter(&InitLogFormatter); - } - - 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(); - 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(); - 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(); - 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(); + 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(); + 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(); + 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 + ); +} diff --git a/fairmq/logger/logger_def.h b/fairmq/logger/logger_def.h index 0be34706..fc9efd83 100644 --- a/fairmq/logger/logger_def.h +++ b/fairmq/logger/logger_def.h @@ -22,57 +22,61 @@ #include #include -namespace fairmq +namespace FairMQ { - enum severity_level - { - TRACE, - DEBUG, - RESULTS, - INFO, - WARN, - ERROR, - STATE, - NOLOG - }; - static const std::array 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 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 +template 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(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::g_LogSeverityLevelString.at(idx)); + strm << write_in(FairMQ::g_LogSeverityLevelString.at(idx)); break; case custom_severity_level::DEBUG : - strm << write_in(fairmq::g_LogSeverityLevelString.at(idx)); + strm << write_in(FairMQ::g_LogSeverityLevelString.at(idx)); break; case custom_severity_level::RESULTS : - strm << write_in(fairmq::g_LogSeverityLevelString.at(idx)); + strm << write_in(FairMQ::g_LogSeverityLevelString.at(idx)); break; case custom_severity_level::INFO : - strm << write_in(fairmq::g_LogSeverityLevelString.at(idx)); + strm << write_in(FairMQ::g_LogSeverityLevelString.at(idx)); break; case custom_severity_level::WARN : - strm << write_in(fairmq::g_LogSeverityLevelString.at(idx)); + strm << write_in(FairMQ::g_LogSeverityLevelString.at(idx)); break; case custom_severity_level::STATE : - strm << write_in(fairmq::g_LogSeverityLevelString.at(idx)); + strm << write_in(FairMQ::g_LogSeverityLevelString.at(idx)); break; case custom_severity_level::ERROR : - strm << write_in(fairmq::g_LogSeverityLevelString.at(idx)); + strm << write_in(FairMQ::g_LogSeverityLevelString.at(idx)); break; case custom_severity_level::NOLOG : - strm << write_in(fairmq::g_LogSeverityLevelString.at(idx)); + strm << write_in(FairMQ::g_LogSeverityLevelString.at(idx)); break; default: @@ -143,7 +147,7 @@ inline boost::log::formatting_ostream& operator<< } else { - strm << write_in("Unknown log level ") + strm << write_in("Unknown log level ") << "(int level = " << static_cast(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(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("Unknown log level ") + strm << write_in("Unknown log level ") << "(int level = " << static_cast(level) << ")"; } return strm; diff --git a/fairmq/logger/run/testLogger.cxx b/fairmq/logger/run/testLogger.cxx index f306512b..32c6888b 100644 --- a/fairmq/logger/run/testLogger.cxx +++ b/fairmq/logger/run/testLogger.cxx @@ -23,8 +23,8 @@ #include - 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) *********"<(); - 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(); - 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; } - - diff --git a/fairmq/nanomsg/FairMQPollerNN.cxx b/fairmq/nanomsg/FairMQPollerNN.cxx index 570eae89..198be34c 100644 --- a/fairmq/nanomsg/FairMQPollerNN.cxx +++ b/fairmq/nanomsg/FairMQPollerNN.cxx @@ -59,7 +59,7 @@ FairMQPollerNN::FairMQPollerNN(const vector& channels) } } -FairMQPollerNN::FairMQPollerNN(const unordered_map>& channelsMap, const initializer_list channelList) +FairMQPollerNN::FairMQPollerNN(const unordered_map>& channelsMap, const vector& channelList) : items() , fNumItems(0) , fOffsetMap() diff --git a/fairmq/nanomsg/FairMQPollerNN.h b/fairmq/nanomsg/FairMQPollerNN.h index 76c45a01..d68eece0 100644 --- a/fairmq/nanomsg/FairMQPollerNN.h +++ b/fairmq/nanomsg/FairMQPollerNN.h @@ -33,7 +33,7 @@ class FairMQPollerNN : public FairMQPoller public: FairMQPollerNN(const std::vector& channels); - FairMQPollerNN(const std::unordered_map>& channelsMap, const std::initializer_list channelList); + FairMQPollerNN(const std::unordered_map>& channelsMap, const std::vector& channelList); FairMQPollerNN(const FairMQPollerNN&) = delete; FairMQPollerNN operator=(const FairMQPollerNN&) = delete; diff --git a/fairmq/nanomsg/FairMQTransportFactoryNN.cxx b/fairmq/nanomsg/FairMQTransportFactoryNN.cxx index 4f4e5fc8..bbe86a08 100644 --- a/fairmq/nanomsg/FairMQTransportFactoryNN.cxx +++ b/fairmq/nanomsg/FairMQTransportFactoryNN.cxx @@ -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& channels) +FairMQPoller* FairMQTransportFactoryNN::CreatePoller(const vector& channels) const { return new FairMQPollerNN(channels); } -FairMQPoller* FairMQTransportFactoryNN::CreatePoller(const std::unordered_map>& channelsMap, const std::initializer_list channelList) +FairMQPoller* FairMQTransportFactoryNN::CreatePoller(const std::unordered_map>& channelsMap, const std::vector& 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); } diff --git a/fairmq/nanomsg/FairMQTransportFactoryNN.h b/fairmq/nanomsg/FairMQTransportFactoryNN.h index cdd89280..3e7235d9 100644 --- a/fairmq/nanomsg/FairMQTransportFactoryNN.h +++ b/fairmq/nanomsg/FairMQTransportFactoryNN.h @@ -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& channels); - virtual FairMQPoller* CreatePoller(const std::unordered_map>& channelsMap, const std::initializer_list channelList); - virtual FairMQPoller* CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket); + virtual FairMQPoller* CreatePoller(const std::vector& channels) const; + virtual FairMQPoller* CreatePoller(const std::unordered_map>& channelsMap, const std::vector& channelList) const; + virtual FairMQPoller* CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket) const; virtual ~FairMQTransportFactoryNN() {}; }; diff --git a/fairmq/options/FairMQEventManager.h b/fairmq/options/FairMQEventManager.h index c4b0d35c..52df8a8b 100644 --- a/fairmq/options/FairMQEventManager.h +++ b/fairmq/options/FairMQEventManager.h @@ -26,41 +26,36 @@ #include #include - - - -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 struct Traits; - template struct Traits { using signal_type = boost::signals2::signal; } ; - template struct Traits > { using signal_type = boost::signals2::signal& )>; } ; - +template struct Traits; +template struct Traits { using signal_type = boost::signals2::signal; } ; +template struct Traits > { using signal_type = boost::signals2::signal& )>; } ; - template <> struct Traits { using signal_type = boost::signals2::signal; } ; - - template struct Traits { using signal_type = boost::signals2::signal; } ; - - template struct Traits { using signal_type = boost::signals2::signal; } ; - - /* - template struct Traits2; - template <> struct Traits2 { using signal_type = boost::signals2::signal; } ; - template struct Traits2 { using signal_type = boost::signals2::signal; } ; - template <> struct Traits2 { using signal_type = boost::signals2::signal; } ; - // */ -} +template <> struct Traits { using signal_type = boost::signals2::signal; } ; +template struct Traits { using signal_type = boost::signals2::signal; } ; -class FairMQEventManager +template struct Traits { using signal_type = boost::signals2::signal; } ; + +/* +template struct Traits2; +template <> struct Traits2 { using signal_type = boost::signals2::signal; } ; +template struct Traits2 { using signal_type = boost::signals2::signal; } ; +template <> struct Traits2 { using signal_type = boost::signals2::signal; } ; +// */ + +} // Events namespace + +class FairMQEventManager { public: typedef std::pair EventKey; @@ -99,16 +94,13 @@ class FairMQEventManager } private: - - std::map fEventMap; - template ::signal_type, typename SlotPtr = boost::shared_ptr > - 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()),SlotPtr>::value, ""); @@ -119,7 +111,7 @@ class FairMQEventManager // auto &&tmp = boost::any_cast(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(event) << " and key" << key; @@ -128,6 +120,4 @@ class FairMQEventManager } }; - #endif /* FAIRMQEVENTMANAGER_H */ - diff --git a/fairmq/options/FairMQParser.cxx b/fairmq/options/FairMQParser.cxx index e4948acb..097f5385 100644 --- a/fairmq/options/FairMQParser.cxx +++ b/fairmq/options/FairMQParser.cxx @@ -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("key", ""); + if (key != "") { - string key = q.second.get("key", ""); - if (key != "") - { - deviceIdKey = key; - LOG(TRACE) << "Found config for device key '" << deviceIdKey << "' in JSON input"; - } - else - { - deviceIdKey = q.second.get("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("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(".id"); - LOG(TRACE) << "Found config for '" << deviceIdKey << "' in XML input"; - } + deviceIdKey = p.second.get(".id"); + LOG(TRACE) << "Found config for '" << deviceIdKey << "' in XML input"; + } - if (formatFlag == "json") + if (formatFlag == "json") + { + string key = p.second.get("key", ""); + if (key != "") { - string key = p.second.get("key", ""); - if (key != "") - { - deviceIdKey = key; - LOG(TRACE) << "Found config for device key '" << deviceIdKey << "' in JSON input"; - } - else - { - deviceIdKey = p.second.get("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("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("key", ""); + + if (key != "") { - // check if key is provided, otherwise use id - string key = p.second.get("key", ""); - if (key != "") - { - deviceIdKey = key; - // LOG(DEBUG) << "Found config for device key '" << deviceIdKey << "' in JSON input"; - } - else - { - deviceIdKey = p.second.get("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(".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("key", ""); - if (key != "") - { - deviceIdKey = key; - // LOG(DEBUG) << "Found config for device key '" << deviceIdKey << "' in JSON input"; - } - else - { - deviceIdKey = p0.second.get("id"); - // LOG(DEBUG) << "Found config for device id '" << deviceIdKey << "' in JSON input"; - } + deviceIdKey = q.second.get("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(".id"); + } + + if (formatFlag == "json") + { + // check if key is provided, otherwise use id + string key = p.second.get("key", ""); + + if (key != "") { - channelKey = q.second.get("name"); - - // try to get common properties to use for all subChannels - FairMQChannel commonChannel; - commonChannel.UpdateType(q.second.get("type", commonChannel.GetType())); - commonChannel.UpdateMethod(q.second.get("method", commonChannel.GetMethod())); - commonChannel.UpdateAddress(q.second.get("address", commonChannel.GetAddress())); - commonChannel.UpdateProperty(q.second.get("property", commonChannel.GetProperty())); - commonChannel.UpdateSndBufSize(q.second.get("sndBufSize", commonChannel.GetSndBufSize())); - commonChannel.UpdateRcvBufSize(q.second.get("rcvBufSize", commonChannel.GetRcvBufSize())); - commonChannel.UpdateRateLogging(q.second.get("rateLogging", commonChannel.GetRateLogging())); - - LOG(DEBUG) << "\t[" << p.first << "] " << channelKey; - - // temporary FairMQChannel container - vector 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("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("name"); + + int numSockets = q.second.get("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(".name"); - } - - if (formatFlag == "json") - { - channelKey = p.second.get("name"); - - // try to get common properties to use for all subChannels - commonChannel.UpdateType(p.second.get("type", commonChannel.GetType())); - commonChannel.UpdateMethod(p.second.get("method", commonChannel.GetMethod())); - commonChannel.UpdateAddress(p.second.get("address", commonChannel.GetAddress())); - commonChannel.UpdateProperty(p.second.get("property", commonChannel.GetProperty())); - commonChannel.UpdateSndBufSize(p.second.get("sndBufSize", commonChannel.GetSndBufSize())); - commonChannel.UpdateRcvBufSize(p.second.get("rcvBufSize", commonChannel.GetRcvBufSize())); - commonChannel.UpdateRateLogging(p.second.get("rateLogging", commonChannel.GetRateLogging())); - } - - LOG(DEBUG) << "\t[" << p.first << "] " << channelKey; + commonChannel.UpdateType(q.second.get("type", commonChannel.GetType())); + commonChannel.UpdateMethod(q.second.get("method", commonChannel.GetMethod())); + commonChannel.UpdateAddress(q.second.get("address", commonChannel.GetAddress())); + commonChannel.UpdateProperty(q.second.get("property", commonChannel.GetProperty())); + commonChannel.UpdateSndBufSize(q.second.get("sndBufSize", commonChannel.GetSndBufSize())); + commonChannel.UpdateRcvBufSize(q.second.get("rcvBufSize", commonChannel.GetRcvBufSize())); + commonChannel.UpdateRateLogging(q.second.get("rateLogging", commonChannel.GetRateLogging())); // temporary FairMQChannel container vector 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& 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(".name"); + } + + if (formatFlag == "json") + { + channelKey = p.second.get("name"); + + numSockets = p.second.get("numSockets", 0); + + // try to get common properties to use for all subChannels + commonChannel.UpdateType(p.second.get("type", commonChannel.GetType())); + commonChannel.UpdateMethod(p.second.get("method", commonChannel.GetMethod())); + commonChannel.UpdateAddress(p.second.get("address", commonChannel.GetAddress())); + commonChannel.UpdateProperty(p.second.get("property", commonChannel.GetProperty())); + commonChannel.UpdateSndBufSize(p.second.get("sndBufSize", commonChannel.GetSndBufSize())); + commonChannel.UpdateRcvBufSize(p.second.get("rcvBufSize", commonChannel.GetRcvBufSize())); + commonChannel.UpdateRateLogging(p.second.get("rateLogging", commonChannel.GetRateLogging())); + } + + // temporary FairMQChannel container + vector 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("type", channel.GetType())); - channel.UpdateMethod(q.second.get("method", channel.GetMethod())); - channel.UpdateAddress(q.second.get("address", channel.GetAddress())); - channel.UpdateProperty(q.second.get("property", channel.GetProperty())); - channel.UpdateSndBufSize(q.second.get("sndBufSize", channel.GetSndBufSize())); - channel.UpdateRcvBufSize(q.second.get("rcvBufSize", channel.GetRcvBufSize())); - channel.UpdateRateLogging(q.second.get("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& 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("type", channel.GetType())); - channel.UpdateMethod(p.second.get("method", channel.GetMethod())); - channel.UpdateAddress(p.second.get("address", channel.GetAddress())); - channel.UpdateProperty(p.second.get("property", channel.GetProperty())); - channel.UpdateSndBufSize(p.second.get("sndBufSize", channel.GetSndBufSize())); - channel.UpdateRcvBufSize(p.second.get("rcvBufSize", channel.GetRcvBufSize())); - channel.UpdateRateLogging(p.second.get("rateLogging", channel.GetRateLogging())); + channel.UpdateType(q.second.get("type", channel.GetType())); + channel.UpdateMethod(q.second.get("method", channel.GetMethod())); + channel.UpdateAddress(q.second.get("address", channel.GetAddress())); + channel.UpdateProperty(q.second.get("property", channel.GetProperty())); + channel.UpdateSndBufSize(q.second.get("sndBufSize", channel.GetSndBufSize())); + channel.UpdateRcvBufSize(q.second.get("rcvBufSize", channel.GetRcvBufSize())); + channel.UpdateRateLogging(q.second.get("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("type", channel.GetType())); + channel.UpdateMethod(p.second.get("method", channel.GetMethod())); + channel.UpdateAddress(p.second.get("address", channel.GetAddress())); + channel.UpdateProperty(p.second.get("property", channel.GetProperty())); + channel.UpdateSndBufSize(p.second.get("sndBufSize", channel.GetSndBufSize())); + channel.UpdateRcvBufSize(p.second.get("rcvBufSize", channel.GetRcvBufSize())); + channel.UpdateRateLogging(p.second.get("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 diff --git a/fairmq/options/FairMQParser.h b/fairmq/options/FairMQParser.h index 19a9b39b..7b17212d 100644 --- a/fairmq/options/FairMQParser.h +++ b/fairmq/options/FairMQParser.h @@ -8,16 +8,13 @@ #ifndef FAIRMQPARSER_H #define FAIRMQPARSER_H -// std #include #include #include #include -// Boost #include -// 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& 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& channelList, const std::string& channelName, const FairMQChannel& commonChannel); + +} // Helper namespace } // FairMQParser namespace diff --git a/fairmq/options/FairMQProgOptions.cxx b/fairmq/options/FairMQProgOptions.cxx index ad9111cb..e048dec3 100644 --- a/fairmq/options/FairMQProgOptions.cxx +++ b/fairmq/options/FairMQProgOptions.cxx @@ -16,6 +16,7 @@ #include #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("verbose"); + std::string verbosity = GetValue("verbosity"); + std::string logFile = GetValue("log-to-file"); bool color = GetValue("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 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 id; - std::string value = fairmq::ConvertVariableValue().Run(fVarMap.at("config-json-string")); + if (fVarMap.count("config-key")) + { + id = fVarMap["config-key"].as(); + } + else + { + id = fVarMap["id"].as(); + } + + std::string value = FairMQ::ConvertVariableValue().Run(fVarMap.at("config-json-string")); std::stringstream ss; ss << value; UserParser(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 id; - std::string value = fairmq::ConvertVariableValue().Run(fVarMap.at("config-xml-string")); + if (fVarMap.count("config-key")) + { + id = fVarMap["config-key"].as(); + } + else + { + id = fVarMap["id"].as(); + } + + std::string value = FairMQ::ConvertVariableValue().Run(fVarMap.at("config-xml-string")); std::stringstream ss; ss << value; UserParser(ss, id); } } + FairProgOptions::PrintOptions(); } @@ -301,6 +324,8 @@ void FairMQProgOptions::InitOptionDescription() ("control", po::value()->default_value("interactive"), "States control ('interactive'/'static'/'dds').") ("network-interface", po::value()->default_value("eth0"), "Network interface to bind on (e.g. eth0, ib0, wlan0, en0, lo...).") ("config-key", po::value(), "Use provided value instead of device id for fetching the configuration from the config file") + ("catch-signals", po::value()->default_value(1), "Enable signal handling (1/0)") + ("log-to-file", po::value()->default_value(""), "Log output to a file") ; fMQOptionsInCfg.add_options() @@ -311,6 +336,8 @@ void FairMQProgOptions::InitOptionDescription() ("control", po::value()->default_value("interactive"), "States control ('interactive'/'static'/'dds').") ("network-interface", po::value()->default_value("eth0"), "Network interface to bind on (e.g. eth0, ib0, wlan0, en0, lo...).") ("config-key", po::value(), "Use provided value instead of device id for fetching the configuration from the config file") + ("catch-signals", po::value()->default_value(1), "Enable signal handling (1/0)") + ("log-to-file", po::value()->default_value(""), "Log output to a file") ; } else @@ -323,6 +350,8 @@ void FairMQProgOptions::InitOptionDescription() ("control", po::value()->default_value("interactive"), "States control ('interactive'/'static'/'dds').") ("network-interface", po::value()->default_value("eth0"), "Network interface to bind on (e.g. eth0, ib0, wlan0, en0, lo...).") ("config-key", po::value(), "Use provided value instead of device id for fetching the configuration from the config file") + ("catch-signals", po::value()->default_value(1), "Enable signal handling (1/0)") + ("log-to-file", po::value()->default_value(""), "Log output to a file") ; } diff --git a/fairmq/options/FairMQProgOptions.h b/fairmq/options/FairMQProgOptions.h index f59556c3..2ac1ee38 100644 --- a/fairmq/options/FairMQProgOptions.h +++ b/fairmq/options/FairMQProgOptions.h @@ -20,13 +20,10 @@ #include #include - #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(fVarMap.at(key))) + if(!FairMQ::is_this_type(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 MQKey;//store key info std::map 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 fSignalMap; @@ -299,6 +289,4 @@ class FairMQProgOptions : public FairProgOptions , public FairMQEventManager } }; - #endif /* FAIRMQPROGOPTIONS_H */ - diff --git a/fairmq/options/FairProgOptions.cxx b/fairmq/options/FairProgOptions.cxx index 562572e1..a89d96da 100644 --- a/fairmq/options/FairProgOptions.cxx +++ b/fairmq/options/FairProgOptions.cxx @@ -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(&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(&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()->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().Run(fVarMap.at(key)); + valueStr=FairMQ::ConvertVariableValue().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().Run(varValue); + return FairMQ::ConvertVariableValue().Run(varValue); } diff --git a/fairmq/options/FairProgOptions.h b/fairmq/options/FairProgOptions.h index e1784bc3..25b7c294 100644 --- a/fairmq/options/FairProgOptions.h +++ b/fairmq/options/FairProgOptions.h @@ -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 fSeverityMap; + std::map fSeverityMap; po::options_description fVisibleOptions; - std::string fVerboseLvl; + std::string fVerbosityLevel; bool fUseConfigFile; boost::filesystem::path fConfigFile; virtual int NotifySwitchOption(); diff --git a/fairmq/options/FairProgOptionsHelper.h b/fairmq/options/FairProgOptionsHelper.h index 12d34689..70e0419f 100644 --- a/fairmq/options/FairProgOptionsHelper.h +++ b/fairmq/options/FairProgOptionsHelper.h @@ -32,213 +32,205 @@ std::ostream& operator<<(std::ostream& os, const std::vector& v) return os; } -namespace fairmq +namespace FairMQ { - namespace po = boost::program_options; - //_____________________________________________________________________________________________________________________________ +namespace po = boost::program_options; - template - bool is_this_type(const po::variable_value& varValue) +template +bool is_this_type(const po::variable_value& varValue) +{ + auto& value = varValue.value(); + if (auto q = boost::any_cast(&value)) + return true; + else + return false; +} + +template +std::string ConvertVariableValueToString(const po::variable_value& varValue) +{ + auto& value = varValue.value(); + std::ostringstream ostr; + if (auto q = boost::any_cast(&value)) { - auto& value = varValue.value(); - if (auto q = boost::any_cast(&value)) - return true; - else - return false; + ostr << *q; } + std::string valueStr = ostr.str(); + return valueStr; +} -//_____________________________________________________________________________________________________________________________ - - template - std::string ConvertVariableValueToString(const po::variable_value& varValue) +// string specialization +template<> +inline std::string ConvertVariableValueToString(const po::variable_value& varValue) +{ + auto& value = varValue.value(); + std::string valueStr; + if (auto q = boost::any_cast(&value)) { - auto& value = varValue.value(); - std::ostringstream ostr; - if (auto q = boost::any_cast(&value)) - { - ostr << *q; - } - std::string valueStr = ostr.str(); - return valueStr; + valueStr = *q; } + return valueStr; +} - // string specialization - template<> - inline std::string ConvertVariableValueToString(const po::variable_value& varValue) +// boost::filesystem::path specialization +template<> +inline std::string ConvertVariableValueToString(const po::variable_value& varValue) +{ + auto& value = varValue.value(); + std::string valueStr; + if (auto q = boost::any_cast(&value)) { - auto& value = varValue.value(); - std::string valueStr; - if (auto q = boost::any_cast(&value)) - { - valueStr = *q; - } - return valueStr; - } - - // boost::filesystem::path specialization - template<> - inline std::string ConvertVariableValueToString(const po::variable_value& varValue) - { - auto& value = varValue.value(); - std::string valueStr; - if (auto q = boost::any_cast(&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 - std::string Value(const po::variable_value& varValue,const std::string&, const std::string&, const std::string&) - { - return ConvertVariableValueToString(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 returned_type; - template - returned_type Value(const po::variable_value& varValue,const std::string& type, const std::string& defaulted, const std::string& empty) - { - std::string valueStr = ConvertVariableValueToString(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 - 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(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 returned_type; + template + returned_type Value(const po::variable_value& varValue,const std::string& type, const std::string& defaulted, const std::string& empty) + { + std::string valueStr = ConvertVariableValueToString(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 +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(varValue)) - return T::template Value(varValue,std::string(" [Type=string]"),defaultedValue,emptyValue); - - // std::vector - if (is_this_type>(varValue)) - return T::template Value>(varValue,std::string(" [Type=vector]"),defaultedValue,emptyValue); - - // int - if (is_this_type(varValue)) - return T::template Value(varValue,std::string(" [Type=int]"),defaultedValue,emptyValue); - - // std::vector - if (is_this_type>(varValue)) - return T::template Value>(varValue,std::string(" [Type=vector]"),defaultedValue,emptyValue); - - // float - if (is_this_type(varValue)) - return T::template Value(varValue,std::string(" [Type=float]"),defaultedValue,emptyValue); - - // std::vector float - if (is_this_type>(varValue)) - return T::template Value>(varValue,std::string(" [Type=vector]"),defaultedValue,emptyValue); - - // double - if (is_this_type(varValue)) - return T::template Value(varValue,std::string(" [Type=double]"),defaultedValue,emptyValue); - - // std::vector double - if (is_this_type>(varValue)) - return T::template Value>(varValue,std::string(" [Type=vector]"),defaultedValue,emptyValue); - - // short - if (is_this_type(varValue)) - return T::template Value(varValue,std::string(" [Type=short]"),defaultedValue,emptyValue); - - // std::vector short - if (is_this_type>(varValue)) - return T::template Value>(varValue,std::string(" [Type=vector]"),defaultedValue,emptyValue); - - // long - if (is_this_type(varValue)) - return T::template Value(varValue,std::string(" [Type=long]"),defaultedValue,emptyValue); - - // std::vector short - if (is_this_type>(varValue)) - return T::template Value>(varValue,std::string(" [Type=vector]"),defaultedValue,emptyValue); - - // size_t - if (is_this_type(varValue)) - return T::template Value(varValue,std::string(" [Type=std::size_t]"),defaultedValue,emptyValue); - - // std::vector size_t - if (is_this_type>(varValue)) - return T::template Value>(varValue,std::string(" [Type=vector]"),defaultedValue,emptyValue); - - // bool - if (is_this_type(varValue)) - return T::template Value(varValue,std::string(" [Type=bool]"),defaultedValue,emptyValue); - - // std::vector bool - if (is_this_type>(varValue)) - return T::template Value>(varValue,std::string(" [Type=vector]"),defaultedValue,emptyValue); - - //////////////////////////////// boost types - // boost::filesystem::path - if (is_this_type(varValue)) - return T::template Value(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(varValue)) + return T::template Value(varValue,std::string(" "),defaultedValue,emptyValue); + + // std::vector + if (is_this_type>(varValue)) + return T::template Value>(varValue,std::string(" >"),defaultedValue,emptyValue); + + // int + if (is_this_type(varValue)) + return T::template Value(varValue,std::string(" "),defaultedValue,emptyValue); + + // std::vector + if (is_this_type>(varValue)) + return T::template Value>(varValue,std::string(" >"),defaultedValue,emptyValue); + + // float + if (is_this_type(varValue)) + return T::template Value(varValue,std::string(" "),defaultedValue,emptyValue); + + // std::vector float + if (is_this_type>(varValue)) + return T::template Value>(varValue,std::string(" >"),defaultedValue,emptyValue); + + // double + if (is_this_type(varValue)) + return T::template Value(varValue,std::string(" "),defaultedValue,emptyValue); + + // std::vector double + if (is_this_type>(varValue)) + return T::template Value>(varValue,std::string(" >"),defaultedValue,emptyValue); + + // short + if (is_this_type(varValue)) + return T::template Value(varValue,std::string(" "),defaultedValue,emptyValue); + + // std::vector short + if (is_this_type>(varValue)) + return T::template Value>(varValue,std::string(" >"),defaultedValue,emptyValue); + + // long + if (is_this_type(varValue)) + return T::template Value(varValue,std::string(" "),defaultedValue,emptyValue); + + // std::vector short + if (is_this_type>(varValue)) + return T::template Value>(varValue,std::string(" >"),defaultedValue,emptyValue); + + // size_t + if (is_this_type(varValue)) + return T::template Value(varValue,std::string(" "),defaultedValue,emptyValue); + + // std::vector size_t + if (is_this_type>(varValue)) + return T::template Value>(varValue,std::string(" >"),defaultedValue,emptyValue); + + // bool + if (is_this_type(varValue)) + return T::template Value(varValue,std::string(" "),defaultedValue,emptyValue); + + // std::vector bool + if (is_this_type>(varValue)) + return T::template Value>(varValue,std::string(" >"),defaultedValue,emptyValue); + + //////////////////////////////// boost types + // boost::filesystem::path + if (is_this_type(varValue)) + return T::template Value(varValue,std::string(" "),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 */ \ No newline at end of file +#endif /* FAIRPROGOPTIONSHELPER_H */ diff --git a/fairmq/options/ProgOptionTest/run/testMQoptions1.cxx b/fairmq/options/ProgOptionTest/run/testMQoptions1.cxx index 536eab9a..93ca535d 100644 --- a/fairmq/options/ProgOptionTest/run/testMQoptions1.cxx +++ b/fairmq/options/ProgOptionTest/run/testMQoptions1.cxx @@ -115,8 +115,8 @@ int main(int argc, char** argv) return 0; // Set severity level (Default is 0=DEBUG) - int verbose=config->GetValue("verbose"); - FairMQLogger::Level lvl=static_cast(verbose); + int verbosity = config->GetValue("verbosity"); + FairMQLogger::Level lvl=static_cast(verbosity); SET_LOGGER_LEVEL(lvl); diff --git a/fairmq/options/ProgOptionTest/run/testMQoptions2.cxx b/fairmq/options/ProgOptionTest/run/testMQoptions2.cxx index 51838245..9bf71d4c 100644 --- a/fairmq/options/ProgOptionTest/run/testMQoptions2.cxx +++ b/fairmq/options/ProgOptionTest/run/testMQoptions2.cxx @@ -49,8 +49,8 @@ int main(int argc, char** argv) return 0; // Set severity level (Default is 0=DEBUG) - int verbose=config.GetValue("verbose"); - FairMQLogger::Level lvl=static_cast(verbose); + int verbosity=config.GetValue("verbosity"); + FairMQLogger::Level lvl=static_cast(verbosity); SET_LOGGER_LEVEL(lvl); // parse XML file diff --git a/fairmq/options/startConfigExample.sh.in b/fairmq/options/startConfigExample.sh.in index 5495a1cb..e13323ab 100755 --- a/fairmq/options/startConfigExample.sh.in +++ b/fairmq/options/startConfigExample.sh.in @@ -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 diff --git a/fairmq/run/runBenchmarkSampler.cxx b/fairmq/run/runBenchmarkSampler.cxx index a5c3e616..9e19afdc 100644 --- a/fairmq/run/runBenchmarkSampler.cxx +++ b/fairmq/run/runBenchmarkSampler.cxx @@ -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 - -#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(&msgSize)->default_value(1000), "Message size in bytes") - ("num-msgs", value(&numMsgs)->default_value(0), "Number of messages to send") - ("msg-rate", value(&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()->default_value("data-out"), "Name of the output channel") + ("msg-size", bpo::value()->default_value(1000), "Message size in bytes") + ("num-msgs", bpo::value()->default_value(0), "Number of messages to send") + ("msg-rate", bpo::value()->default_value(0), "Msg rate limit in maximum number of messages per second"); +} + +FairMQDevice* getDevice(const FairMQProgOptions& /*config*/) +{ + return new FairMQBenchmarkSampler(); } diff --git a/fairmq/run/runMerger.cxx b/fairmq/run/runMerger.cxx index 1d48994e..bdad2e8a 100644 --- a/fairmq/run/runMerger.cxx +++ b/fairmq/run/runMerger.cxx @@ -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 - -#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(&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()->default_value("data-in"), "Name of the input channel") + ("out-channel", bpo::value()->default_value("data-out"), "Name of the output channel") + ("multipart", bpo::value()->default_value(1), "Handle multipart payloads"); +} + +FairMQDevice* getDevice(const FairMQProgOptions& /*config*/) +{ + return new FairMQMerger(); } diff --git a/fairmq/run/runMultiplier.cxx b/fairmq/run/runMultiplier.cxx new file mode 100644 index 00000000..3f18239e --- /dev/null +++ b/fairmq/run/runMultiplier.cxx @@ -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()->default_value("data-in"), "Name of the input channel") + ("out-channel", bpo::value>()->multitoken(), "Names of the output channels") + ("multipart", bpo::value()->default_value(1), "Handle multipart payloads"); +} + +FairMQDevice* getDevice(const FairMQProgOptions& /*config*/) +{ + return new FairMQMultiplier(); +} diff --git a/fairmq/run/runProxy.cxx b/fairmq/run/runProxy.cxx index 40a4eb13..0fc50ab0 100644 --- a/fairmq/run/runProxy.cxx +++ b/fairmq/run/runProxy.cxx @@ -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 - -#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(&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()->default_value("data-in"), "Name of the input channel") + ("out-channel", bpo::value()->default_value("data-out"), "Name of the output channel") + ("multipart", bpo::value()->default_value(1), "Handle multipart payloads"); +} + +FairMQDevice* getDevice(const FairMQProgOptions& /*config*/) +{ + return new FairMQProxy(); } diff --git a/fairmq/run/runSink.cxx b/fairmq/run/runSink.cxx index e3163c74..124a3561 100644 --- a/fairmq/run/runSink.cxx +++ b/fairmq/run/runSink.cxx @@ -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 - -#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(&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()->default_value("data-in"), "Name of the input channel") + ("num-msgs", bpo::value()->default_value(0), "Number of messages to receive"); +} + +FairMQDevice* getDevice(const FairMQProgOptions& /*config*/) +{ + return new FairMQSink(); } diff --git a/fairmq/run/runSplitter.cxx b/fairmq/run/runSplitter.cxx index cfc957ea..f14d5171 100644 --- a/fairmq/run/runSplitter.cxx +++ b/fairmq/run/runSplitter.cxx @@ -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 - -#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(&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()->default_value("data-in"), "Name of the input channel") + ("out-channel", bpo::value()->default_value("data-out"), "Name of the output channel") + ("multipart", bpo::value()->default_value(1), "Handle multipart payloads"); +} + +FairMQDevice* getDevice(const FairMQProgOptions& /*config*/) +{ + return new FairMQSplitter(); } diff --git a/fairmq/runFairMQDevice.h b/fairmq/runFairMQDevice.h new file mode 100644 index 00000000..fde9b411 --- /dev/null +++ b/fairmq/runFairMQDevice.h @@ -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 + +#include "FairMQLogger.h" +#include "FairMQProgOptions.h" +#include "FairMQDevice.h" +#include "runSimpleMQStateMachine.h" + +template +class GenericFairMQDevice : public FairMQDevice +{ + public: + GenericFairMQDevice(R func) : r(func) {} + + protected: + virtual bool ConditionalRun() { return r(*static_cast(this)); } + + private: + R r; +}; + +template +FairMQDevice* makeDeviceWithConditionalRun(R r) +{ + return new GenericFairMQDevice(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 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; +} diff --git a/fairmq/test/runTransferTimeoutTest.cxx b/fairmq/test/runTransferTimeoutTest.cxx index 3537feaf..7005ad2b 100644 --- a/fairmq/test/runTransferTimeoutTest.cxx +++ b/fairmq/test/runTransferTimeoutTest.cxx @@ -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 msg1(NewMessage()); - std::unique_ptr 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"; } } }; diff --git a/fairmq/tools/runSimpleMQStateMachine.h b/fairmq/tools/runSimpleMQStateMachine.h index 61703687..c659daba 100644 --- a/fairmq/tools/runSimpleMQStateMachine.h +++ b/fairmq/tools/runSimpleMQStateMachine.h @@ -8,34 +8,44 @@ #ifndef RUNSIMPLEMQSTATEMACHINE_H #define RUNSIMPLEMQSTATEMACHINE_H +#include "FairMQLogger.h" +#include "FairMQParser.h" +#include "FairMQProgOptions.h" + #include #include +#include #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 inline int runStateMachine(TMQDevice& device, FairMQProgOptions& config) { - device.CatchSignals(); + if (config.GetValue("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("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; diff --git a/fairmq/zeromq/FairMQPollerZMQ.cxx b/fairmq/zeromq/FairMQPollerZMQ.cxx index 4d3895a5..76833e3e 100644 --- a/fairmq/zeromq/FairMQPollerZMQ.cxx +++ b/fairmq/zeromq/FairMQPollerZMQ.cxx @@ -57,7 +57,7 @@ FairMQPollerZMQ::FairMQPollerZMQ(const vector& channels) } } -FairMQPollerZMQ::FairMQPollerZMQ(const unordered_map>& channelsMap, const initializer_list channelList) +FairMQPollerZMQ::FairMQPollerZMQ(const unordered_map>& channelsMap, const vector& channelList) : items() , fNumItems(0) , fOffsetMap() diff --git a/fairmq/zeromq/FairMQPollerZMQ.h b/fairmq/zeromq/FairMQPollerZMQ.h index dc4e0b1c..82b80ca9 100644 --- a/fairmq/zeromq/FairMQPollerZMQ.h +++ b/fairmq/zeromq/FairMQPollerZMQ.h @@ -34,7 +34,7 @@ class FairMQPollerZMQ : public FairMQPoller public: FairMQPollerZMQ(const std::vector& channels); - FairMQPollerZMQ(const std::unordered_map>& channelsMap, const std::initializer_list channelList); + FairMQPollerZMQ(const std::unordered_map>& channelsMap, const std::vector& channelList); FairMQPollerZMQ(const FairMQPollerZMQ&) = delete; FairMQPollerZMQ operator=(const FairMQPollerZMQ&) = delete; diff --git a/fairmq/zeromq/FairMQSocketZMQ.cxx b/fairmq/zeromq/FairMQSocketZMQ.cxx index a3c6f9e8..2959035a 100644 --- a/fairmq/zeromq/FairMQSocketZMQ.cxx +++ b/fairmq/zeromq/FairMQSocketZMQ.cxx @@ -23,7 +23,7 @@ using namespace std; // Context to hold the ZeroMQ sockets -boost::shared_ptr FairMQSocketZMQ::fContext = boost::shared_ptr(new FairMQContextZMQ(1)); +std::unique_ptr FairMQSocketZMQ::fContext = std::unique_ptr(new FairMQContextZMQ(1)); FairMQSocketZMQ::FairMQSocketZMQ(const string& type, const string& name, const int numIoThreads, const string& id /*= ""*/) : FairMQSocket(ZMQ_SNDMORE, ZMQ_RCVMORE, ZMQ_DONTWAIT) diff --git a/fairmq/zeromq/FairMQSocketZMQ.h b/fairmq/zeromq/FairMQSocketZMQ.h index d0b5ea71..6ec7c47c 100644 --- a/fairmq/zeromq/FairMQSocketZMQ.h +++ b/fairmq/zeromq/FairMQSocketZMQ.h @@ -17,7 +17,7 @@ #include -#include +#include // unique_ptr #include "FairMQSocket.h" #include "FairMQContextZMQ.h" @@ -72,7 +72,7 @@ class FairMQSocketZMQ : public FairMQSocket std::atomic fMessagesTx; std::atomic fMessagesRx; - static boost::shared_ptr fContext; + static std::unique_ptr fContext; }; #endif /* FAIRMQSOCKETZMQ_H_ */ diff --git a/fairmq/zeromq/FairMQTransportFactoryZMQ.cxx b/fairmq/zeromq/FairMQTransportFactoryZMQ.cxx index c5ea3317..dfb34da8 100644 --- a/fairmq/zeromq/FairMQTransportFactoryZMQ.cxx +++ b/fairmq/zeromq/FairMQTransportFactoryZMQ.cxx @@ -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& channels) +FairMQPoller* FairMQTransportFactoryZMQ::CreatePoller(const vector& channels) const { return new FairMQPollerZMQ(channels); } -FairMQPoller* FairMQTransportFactoryZMQ::CreatePoller(const std::unordered_map>& channelsMap, const std::initializer_list channelList) +FairMQPoller* FairMQTransportFactoryZMQ::CreatePoller(const std::unordered_map>& channelsMap, const std::vector& 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); } diff --git a/fairmq/zeromq/FairMQTransportFactoryZMQ.h b/fairmq/zeromq/FairMQTransportFactoryZMQ.h index f3b8d10f..374eb5eb 100644 --- a/fairmq/zeromq/FairMQTransportFactoryZMQ.h +++ b/fairmq/zeromq/FairMQTransportFactoryZMQ.h @@ -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& channels); - virtual FairMQPoller* CreatePoller(const std::unordered_map>& channelsMap, const std::initializer_list channelList); - virtual FairMQPoller* CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket); + virtual FairMQPoller* CreatePoller(const std::vector& channels) const; + virtual FairMQPoller* CreatePoller(const std::unordered_map>& channelsMap, const std::vector& channelList) const; + virtual FairMQPoller* CreatePoller(const FairMQSocket& cmdSocket, const FairMQSocket& dataSocket) const; virtual ~FairMQTransportFactoryZMQ() {}; };