Refactor the examples after move from FairRoot

This commit is contained in:
Alexey Rybalchenko
2018-04-26 23:06:01 +02:00
parent 71b2981526
commit 7aefa0eeb8
148 changed files with 1582 additions and 2027 deletions

View File

@@ -0,0 +1,56 @@
################################################################################
# Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH #
# #
# This software is distributed under the terms of the #
# GNU Lesser General Public Licence (LGPL) version 3, #
# copied verbatim in the file "LICENSE" #
################################################################################
add_library(ExampleMultipleTransportsLib STATIC
"Sampler1.cxx"
"Sampler1.h"
"Sampler2.cxx"
"Sampler2.h"
"Sink.cxx"
"Sink.h"
)
target_link_libraries(ExampleMultipleTransportsLib PUBLIC FairMQ)
add_executable(fairmq-ex-multiple-transports-sampler1 runSampler1.cxx)
target_link_libraries(fairmq-ex-multiple-transports-sampler1 PRIVATE ExampleMultipleTransportsLib)
add_executable(fairmq-ex-multiple-transports-sampler2 runSampler2.cxx)
target_link_libraries(fairmq-ex-multiple-transports-sampler2 PRIVATE ExampleMultipleTransportsLib)
add_executable(fairmq-ex-multiple-transports-sink runSink.cxx)
target_link_libraries(fairmq-ex-multiple-transports-sink PRIVATE ExampleMultipleTransportsLib)
add_custom_target(ExampleMultipleTransports DEPENDS fairmq-ex-multiple-transports-sampler1 fairmq-ex-multiple-transports-sampler2 fairmq-ex-multiple-transports-sink)
install(
TARGETS
fairmq-ex-multiple-transports-sampler1
fairmq-ex-multiple-transports-sampler2
fairmq-ex-multiple-transports-sink
LIBRARY DESTINATION ${PROJECT_INSTALL_LIBDIR}
RUNTIME DESTINATION ${PROJECT_INSTALL_BINDIR}
)
# configure run script with different executable paths for build and for install directories
set(EX_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-multiple-transports.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-multiple-transports.sh)
set(EX_BIN_DIR ${CMAKE_INSTALL_PREFIX}/${PROJECT_INSTALL_BINDIR})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fairmq-start-ex-multiple-transports.sh.in ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-multiple-transports.sh_install)
install(
PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/fairmq-start-ex-multiple-transports.sh_install
DESTINATION ${PROJECT_INSTALL_BINDIR}
RENAME fairmq-start-ex-multiple-transports.sh
)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test-ex-multiple-transports.sh.in ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-transports.sh)
add_test(NAME Example-Multiple-Transports COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test-ex-multiple-transports.sh)
set_tests_properties(Example-Multiple-Transports PROPERTIES TIMEOUT "30" RUN_SERIAL true PASS_REGULAR_EXPRESSION "Received messages from both sources.")

View File

@@ -0,0 +1,12 @@
Multiple Transports example
===========================
This example demonstrates use of multiple transports (zeromq/nanomsg/shmem) within the same topology and/or device. It is a simple topology consisting of two samplers and a sink. The devices are connected via 3 channels:
![Multiple Transports example](../../../docs/images/fairmq-ex-multiple-transports.png?raw=true "Multiple Transports example")
Each device has main transport that it uses. By default it is ZeroMQ, and can be overriden via the `--transport` cmd option. The device will initialize additional transports if any of the channels have them configured (e.g. via the JSON file, see `ex-multiple-transports.json`).
In this example sampler1 and sink are started with `--transport shmem`, making shared memory their main transport, sampler2 with `--transport nanomsg`. Additionally, the ack channel is configured to use zeromq as its transport via the JSON configuration.
The main two things that a transport does is transfer of data and allocation of memory for the messages. By default, new messages are created via the main device transport. If a message has been created with one transport and is to be transferred with another, it has to be copied into a new message of the target transport. This happens automatically behind the scenes. To avoid this copy the device can create messages via `NewMessageFor(const string& channelName, int subChannelIndex, ...)` method, that creates the messages via the transport of the given channel (check sampler1 and sink for an example).

View File

@@ -0,0 +1,80 @@
/********************************************************************************
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "Sampler1.h"
using namespace std;
namespace example_multiple_transports
{
Sampler1::Sampler1()
: fAckListener()
, fMaxIterations(0)
, fNumIterations(0)
{
}
void Sampler1::InitTask()
{
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
void Sampler1::PreRun()
{
fAckListener = thread(&Sampler1::ListenForAcks, this);
}
bool Sampler1::ConditionalRun()
{
// Creates a message using the transport of channel data1
FairMQMessagePtr msg(NewMessageFor("data1", 0, 1000000));
// in case of error or transfer interruption, return false to go to IDLE state
// successfull transfer will return number of bytes transfered (can be 0 if sending an empty message).
if (Send(msg, "data1") < 0)
{
return false;
}
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations)
{
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
return false;
}
return true;
}
void Sampler1::PostRun()
{
fAckListener.join();
}
void Sampler1::ListenForAcks()
{
uint64_t numAcks = 0;
while (CheckCurrentState(RUNNING))
{
FairMQMessagePtr ack(NewMessageFor("ack", 0));
if (Receive(ack, "ack") < 0)
{
break;
}
++numAcks;
}
LOG(info) << "Acknowledged " << numAcks << " messages";
}
Sampler1::~Sampler1()
{
}
} // namespace example_multiple_transports

View File

@@ -0,0 +1,39 @@
/********************************************************************************
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#ifndef FAIRMQEXAMPLEMULTIPLETRANSPORTSSAMPLER1_H
#define FAIRMQEXAMPLEMULTIPLETRANSPORTSSAMPLER1_H
#include <thread>
#include "FairMQDevice.h"
namespace example_multiple_transports
{
class Sampler1 : public FairMQDevice
{
public:
Sampler1();
virtual ~Sampler1();
protected:
virtual void InitTask();
virtual void PreRun();
virtual bool ConditionalRun();
virtual void PostRun();
void ListenForAcks();
std::thread fAckListener;
uint64_t fMaxIterations;
uint64_t fNumIterations;
};
} // namespace example_multiple_transports
#endif /* FAIRMQEXAMPLEMULTIPLETRANSPORTSSAMPLER1_H */

View File

@@ -0,0 +1,51 @@
/********************************************************************************
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "Sampler2.h"
using namespace std;
namespace example_multiple_transports
{
Sampler2::Sampler2()
: fMaxIterations(0)
, fNumIterations(0)
{
}
void Sampler2::InitTask()
{
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
bool Sampler2::ConditionalRun()
{
FairMQMessagePtr msg(NewMessage(1000));
// in case of error or transfer interruption, return false to go to IDLE state
// successfull transfer will return number of bytes transfered (can be 0 if sending an empty message).
if (Send(msg, "data2") < 0)
{
return false;
}
if (fMaxIterations > 0 && ++fNumIterations >= fMaxIterations)
{
LOG(info) << "Configured maximum number of iterations reached. Leaving RUNNING state.";
return false;
}
return true;
}
Sampler2::~Sampler2()
{
}
} // namespace example_multiple_transports

View File

@@ -0,0 +1,34 @@
/********************************************************************************
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#ifndef FAIRMQEXAMPLEMULTIPLETRANSPORTSSAMPLER2_H
#define FAIRMQEXAMPLEMULTIPLETRANSPORTSSAMPLER2_H
#include "FairMQDevice.h"
namespace example_multiple_transports
{
class Sampler2 : public FairMQDevice
{
public:
Sampler2();
virtual ~Sampler2();
protected:
virtual void InitTask();
virtual bool ConditionalRun();
private:
uint64_t fMaxIterations;
uint64_t fNumIterations;
};
} // namespace example_multiple_transports
#endif /* FAIRMQEXAMPLEMULTIPLETRANSPORTSSAMPLER2_H */

View File

@@ -0,0 +1,80 @@
/********************************************************************************
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
/**
* Sink.cxx
*
* @since 2014-10-10
* @author A. Rybalchenko
*/
#include "Sink.h"
using namespace std;
namespace example_multiple_transports
{
Sink::Sink()
: fMaxIterations(0)
, fNumIterations1(0)
, fNumIterations2(0)
, fReceived1(false)
, fReceived2(false)
{
// register a handler for data arriving on "data" channel
OnData("data1", &Sink::HandleData1);
OnData("data2", &Sink::HandleData2);
}
void Sink::InitTask()
{
fMaxIterations = fConfig->GetValue<uint64_t>("max-iterations");
}
// handler is called whenever a message arrives on "data", with a reference to the message and a sub-channel index (here 0)
bool Sink::HandleData1(FairMQMessagePtr& /*msg*/, int /*index*/)
{
fNumIterations1++;
// Creates a message using the transport of channel ack
FairMQMessagePtr ack(NewMessageFor("ack", 0));
if (Send(ack, "ack") < 0)
{
return false;
}
// return true if want to be called again (otherwise go to IDLE state)
return CheckIterations();
}
// handler is called whenever a message arrives on "data", with a reference to the message and a sub-channel index (here 0)
bool Sink::HandleData2(FairMQMessagePtr& /*msg*/, int /*index*/)
{
fNumIterations2++;
// return true if want to be called again (otherwise go to IDLE state)
return CheckIterations();
}
bool Sink::CheckIterations()
{
if (fMaxIterations > 0)
{
if (fNumIterations1 >= fMaxIterations && fNumIterations2 >= fMaxIterations)
{
LOG(info) << "Configured maximum number of iterations reached & Received messages from both sources. Leaving RUNNING state.";
return false;
}
}
return true;
}
Sink::~Sink()
{
}
} // namespace example_multiple_transports

View File

@@ -0,0 +1,45 @@
/********************************************************************************
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
/**
* Sink.h
*
* @since 2014-10-10
* @author A. Rybalchenko
*/
#ifndef FAIRMQEXAMPLEMULTIPLETRANSPORTSSINK_H
#define FAIRMQEXAMPLEMULTIPLETRANSPORTSSINK_H
#include "FairMQDevice.h"
namespace example_multiple_transports
{
class Sink : public FairMQDevice
{
public:
Sink();
virtual ~Sink();
protected:
virtual void InitTask();
bool HandleData1(FairMQMessagePtr&, int);
bool HandleData2(FairMQMessagePtr&, int);
bool CheckIterations();
private:
uint64_t fMaxIterations;
uint64_t fNumIterations1;
uint64_t fNumIterations2;
bool fReceived1;
bool fReceived2;
};
} // namespace example_multiple_transports
#endif /* FAIRMQEXAMPLEMULTIPLETRANSPORTSSINK_H */

View File

@@ -0,0 +1,84 @@
{
"fairMQOptions": {
"devices": [
{
"id": "sampler1",
"channels": [
{
"name": "data1",
"sockets": [
{
"type": "push",
"method": "bind",
"address": "tcp://127.0.0.1:5555"
}
]
},
{
"name": "ack",
"transport": "zeromq",
"sockets": [
{
"type": "sub",
"method": "bind",
"address": "tcp://127.0.0.1:5557"
}
]
}
]
},
{
"id": "sampler2",
"channels": [
{
"name": "data2",
"sockets": [
{
"type": "push",
"method": "bind",
"address": "tcp://127.0.0.1:5556"
}
]
}
]
},
{
"id": "sink1",
"channels": [
{
"name": "data1",
"sockets": [
{
"type": "pull",
"method": "connect",
"address": "tcp://127.0.0.1:5555"
}
]
},
{
"name": "data2",
"transport": "nanomsg",
"sockets": [
{
"type": "pull",
"method": "connect",
"address": "tcp://127.0.0.1:5556"
}
]
},
{
"name": "ack",
"transport": "zeromq",
"sockets": [
{
"type": "pub",
"method": "connect",
"address": "tcp://127.0.0.1:5557"
}
]
}
]
}
]
}
}

View File

@@ -0,0 +1,25 @@
#!/bin/bash
SAMPLER1="fairmq-ex-multiple-transports-sampler1"
SAMPLER1+=" --id sampler1"
SAMPLER1+=" --severity debug"
SAMPLER1+=" --transport shmem"
SAMPLER1+=" --channel-config name=data1,type=push,method=bind,address=tcp://127.0.0.1:5555"
SAMPLER1+=" name=ack,type=sub,method=bind,address=tcp://127.0.0.1:5557,transport=zeromq"
xterm -geometry 80x30+0+0 -hold -e @EX_BIN_DIR@/$SAMPLER1 &
SAMPLER2="fairmq-ex-multiple-transports-sampler2"
SAMPLER2+=" --id sampler2"
SAMPLER2+=" --severity debug"
SAMPLER2+=" --transport nanomsg"
SAMPLER2+=" --channel-config name=data2,type=push,method=bind,address=tcp://127.0.0.1:5556"
xterm -geometry 80x30+0+450 -hold -e @EX_BIN_DIR@/$SAMPLER2 &
SINK="fairmq-ex-multiple-transports-sink"
SINK+=" --id sink1"
SINK+=" --severity debug"
SINK+=" --transport shmem"
SINK+=" --channel-config name=data1,type=pull,method=connect,address=tcp://127.0.0.1:5555"
SINK+=" name=data2,type=pull,method=connect,address=tcp://127.0.0.1:5556,transport=nanomsg"
SINK+=" name=ack,type=pub,method=connect,address=tcp://127.0.0.1:5557,transport=zeromq"
xterm -geometry 80x30+500+0 -hold -e @EX_BIN_DIR@/$SINK &

View File

@@ -0,0 +1,23 @@
/********************************************************************************
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "runFairMQDevice.h"
#include "Sampler1.h"
namespace bpo = boost::program_options;
void addCustomOptions(bpo::options_description& options)
{
options.add_options()
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_multiple_transports::Sampler1();
}

View File

@@ -0,0 +1,23 @@
/********************************************************************************
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "runFairMQDevice.h"
#include "Sampler2.h"
namespace bpo = boost::program_options;
void addCustomOptions(bpo::options_description& options)
{
options.add_options()
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_multiple_transports::Sampler2();
}

View File

@@ -0,0 +1,23 @@
/********************************************************************************
* Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
* *
* This software is distributed under the terms of the *
* GNU Lesser General Public Licence (LGPL) version 3, *
* copied verbatim in the file "LICENSE" *
********************************************************************************/
#include "runFairMQDevice.h"
#include "Sink.h"
namespace bpo = boost::program_options;
void addCustomOptions(bpo::options_description& options)
{
options.add_options()
("max-iterations", bpo::value<uint64_t>()->default_value(0), "Maximum number of iterations of Run/ConditionalRun/OnData (0 - infinite)");
}
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/)
{
return new example_multiple_transports::Sink();
}

View File

@@ -0,0 +1,44 @@
#!/bin/bash
SESSION="$(@CMAKE_BINARY_DIR@/fairmq/uuidGen -h)"
trap 'kill -TERM $SAMPLER1_PID; kill -TERM $SAMPLER2_PID; kill -TERM $SINK_PID; wait $SAMPLER1_PID; wait $SAMPLER2_PID; wait $SINK_PID; @CMAKE_BINARY_DIR@/fairmq/shmmonitor --cleanup --session $SESSION;' TERM
SINK="fairmq-ex-multiple-transports-sink"
SINK+=" --id sink1"
SINK+=" --verbosity veryhigh"
SINK+=" --session $SESSION"
SINK+=" --max-iterations 1"
SINK+=" --control static --color false"
SINK+=" --transport shmem"
SINK+=" --channel-config name=data1,type=pull,method=connect,address=tcp://127.0.0.1:5555"
SINK+=" name=data2,type=pull,method=connect,address=tcp://127.0.0.1:5556,transport=nanomsg"
SINK+=" name=ack,type=pub,method=connect,address=tcp://127.0.0.1:5557,transport=zeromq"
@CMAKE_CURRENT_BINARY_DIR@/$SINK &
SINK_PID=$!
SAMPLER1="fairmq-ex-multiple-transports-sampler1"
SAMPLER1+=" --id sampler1"
SAMPLER1+=" --session $SESSION"
SAMPLER1+=" --verbosity veryhigh"
SAMPLER1+=" --max-iterations 1"
SAMPLER1+=" --control static --color false"
SAMPLER1+=" --transport shmem"
SAMPLER1+=" --channel-config name=data1,type=push,method=bind,address=tcp://127.0.0.1:5555"
SAMPLER1+=" name=ack,type=sub,method=bind,address=tcp://127.0.0.1:5557,transport=zeromq"
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER1 &
SAMPLER1_PID=$!
SAMPLER2="fairmq-ex-multiple-transports-sampler2"
SAMPLER2+=" --id sampler2"
SAMPLER2+=" --session $SESSION"
SAMPLER2+=" --verbosity veryhigh"
SAMPLER2+=" --max-iterations 1"
SAMPLER2+=" --control static --color false"
SAMPLER2+=" --transport nanomsg"
SAMPLER2+=" --channel-config name=data2,type=push,method=bind,address=tcp://127.0.0.1:5556"
@CMAKE_CURRENT_BINARY_DIR@/$SAMPLER2 &
SAMPLER2_PID=$!
wait $SAMPLER1_PID
wait $SAMPLER2_PID
wait $SINK_PID