FairMQ/fairmq/run/runProtoSink.cxx
2015-01-21 16:19:14 +01:00

167 lines
4.9 KiB
C++

/********************************************************************************
* 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" *
********************************************************************************/
/**
* runSink.cxx
*
* @since 2013-01-21
* @author D. Klein, A. Rybalchenko
*/
#include <iostream>
#include <csignal>
#include "boost/program_options.hpp"
#include "FairMQLogger.h"
#include "FairMQProtoSink.h"
#ifdef NANOMSG
#include "FairMQTransportFactoryNN.h"
#else
#include "FairMQTransportFactoryZMQ.h"
#endif
using namespace std;
FairMQProtoSink sink;
static void s_signal_handler(int signal)
{
cout << endl << "Caught signal " << signal << endl;
sink.ChangeState(FairMQProtoSink::STOP);
sink.ChangeState(FairMQProtoSink::END);
cout << "Shutdown complete. Bye!" << endl;
exit(1);
}
static void s_catch_signals(void)
{
struct sigaction action;
action.sa_handler = s_signal_handler;
action.sa_flags = 0;
sigemptyset(&action.sa_mask);
sigaction(SIGINT, &action, NULL);
sigaction(SIGTERM, &action, NULL);
}
typedef struct DeviceOptions
{
string id;
int ioThreads;
string inputSocketType;
int inputBufSize;
string inputMethod;
string inputAddress;
} DeviceOptions_t;
inline bool parse_cmd_line(int _argc, char* _argv[], DeviceOptions* _options)
{
if (_options == NULL)
throw std::runtime_error("Internal error: options' container is empty.");
namespace bpo = boost::program_options;
bpo::options_description desc("Options");
desc.add_options()
("id", bpo::value<string>()->required(), "Device ID")
("io-threads", bpo::value<int>()->default_value(1), "Number of I/O threads")
("input-socket-type", bpo::value<string>()->required(), "Input socket type: sub/pull")
("input-buff-size", bpo::value<int>()->required(), "Input buffer size in number of messages (ZeroMQ)/bytes(nanomsg)")
("input-method", bpo::value<string>()->required(), "Input method: bind/connect")
("input-address", bpo::value<string>()->required(), "Input address, e.g.: \"tcp://*:5555\"")
("help", "Print help messages");
bpo::variables_map vm;
bpo::store(bpo::parse_command_line(_argc, _argv, desc), vm);
if ( vm.count("help") )
{
LOG(INFO) << "FairMQ Proto Sink" << endl << desc;
return false;
}
bpo::notify(vm);
if ( vm.count("id") )
_options->id = vm["id"].as<string>();
if ( vm.count("io-threads") )
_options->ioThreads = vm["io-threads"].as<int>();
if ( vm.count("input-socket-type") )
_options->inputSocketType = vm["input-socket-type"].as<string>();
if ( vm.count("input-buff-size") )
_options->inputBufSize = vm["input-buff-size"].as<int>();
if ( vm.count("input-method") )
_options->inputMethod = vm["input-method"].as<string>();
if ( vm.count("input-address") )
_options->inputAddress = vm["input-address"].as<string>();
return true;
}
int main(int argc, char** argv)
{
s_catch_signals();
DeviceOptions_t options;
try
{
if (!parse_cmd_line(argc, argv, &options))
return 0;
}
catch (exception& e)
{
LOG(ERROR) << e.what();
return 1;
}
LOG(INFO) << "PID: " << getpid();
#ifdef NANOMSG
FairMQTransportFactory* transportFactory = new FairMQTransportFactoryNN();
#else
FairMQTransportFactory* transportFactory = new FairMQTransportFactoryZMQ();
#endif
sink.SetTransport(transportFactory);
sink.SetProperty(FairMQProtoSink::Id, options.id);
sink.SetProperty(FairMQProtoSink::NumIoThreads, options.ioThreads);
sink.SetProperty(FairMQProtoSink::NumInputs, 1);
sink.SetProperty(FairMQProtoSink::NumOutputs, 0);
sink.ChangeState(FairMQProtoSink::INIT);
sink.SetProperty(FairMQProtoSink::InputSocketType, options.inputSocketType);
sink.SetProperty(FairMQProtoSink::InputRcvBufSize, options.inputBufSize);
sink.SetProperty(FairMQProtoSink::InputMethod, options.inputMethod);
sink.SetProperty(FairMQProtoSink::InputAddress, options.inputAddress);
sink.ChangeState(FairMQProtoSink::SETOUTPUT);
sink.ChangeState(FairMQProtoSink::SETINPUT);
sink.ChangeState(FairMQProtoSink::RUN);
// wait until the running thread has finished processing.
boost::unique_lock<boost::mutex> lock(sink.fRunningMutex);
while (!sink.fRunningFinished)
{
sink.fRunningCondition.wait(lock);
}
sink.ChangeState(FairMQProtoSink::STOP);
sink.ChangeState(FairMQProtoSink::END);
return 0;
}