Commit c3bd3f89 authored by Pierre-Alain Loizeau's avatar Pierre-Alain Loizeau
Browse files

[MQ] add optional monitoring histograms in CbmMQTsaMultiSampler

parent 632cfe2e
......@@ -87,6 +87,12 @@ set(DEPENDENCIES
fles_ipc
CbmMQBase
CbmFlibFlesTools
Core
Gpad
Hist
Net
RHTTP
RIO
)
GENERATE_EXECUTABLE()
......
......@@ -8,23 +8,29 @@
#include "CbmMQTsaMultiSampler.h"
#include "CbmMQDefs.h"
//#include "CbmFlesCanvasTools.h"
#include "CbmFlesCanvasTools.h"
#include "CbmFormatDecHexPrintout.h"
#include "FairMQLogger.h"
#include "FairMQProgOptions.h" // device->fConfig
//#include "RootSerializer.h"
#include "BoostSerializer.h"
#include "RootSerializer.h"
#include "TimesliceInputArchive.hpp"
#include "TimesliceMultiInputArchive.hpp"
#include "TimesliceMultiSubscriber.hpp"
#include "TimesliceSubscriber.hpp"
#include <TCanvas.h>
#include <TH1F.h>
#include <TH1I.h>
#include <TProfile.h>
#include <boost/algorithm/string.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/filesystem.hpp>
#include <boost/regex.hpp>
#include <boost/serialization/utility.hpp>
namespace filesys = boost::filesystem;
......@@ -58,7 +64,9 @@ CbmMQTsaMultiSampler::CbmMQTsaMultiSampler()
, fTSCounter(0)
, fMessageCounter(0)
, fSource(nullptr)
, fTime() {}
, fTime()
, fLastPublishTime {std::chrono::system_clock::now()}
{}
void CbmMQTsaMultiSampler::InitTask() try {
// Get the values from the command line options (via fConfig)
......@@ -73,14 +81,13 @@ void CbmMQTsaMultiSampler::InitTask() try {
fbSendTsPerChannel = fConfig->GetValue<bool>("send-ts-per-channel");
fsChannelNameMissedTs = fConfig->GetValue<std::string>("ChNameMissTs");
fsChannelNameCommands = fConfig->GetValue<std::string>("ChNameCmds");
/*
fuPublishFreqTs = fConfig->GetValue< uint32_t >( "PubFreqTs" );
fdMinPublishTime = fConfig->GetValue< double_t >( "PubTimeMin" );
fdMaxPublishTime = fConfig->GetValue< double_t >( "PubTimeMax" );
fsChannelNameHistosInput = fConfig->GetValue< std::string >( "ChNameIn" );
fsChannelNameHistosConfig = fConfig->GetValue< std::string >( "ChNameHistCfg" );
fsChannelNameCanvasConfig = fConfig->GetValue< std::string >( "ChNameCanvCfg" );
*/
fuPublishFreqTs = fConfig->GetValue< uint32_t >( "PubFreqTs" );
fdMinPublishTime = fConfig->GetValue< double_t >( "PubTimeMin" );
fdMaxPublishTime = fConfig->GetValue< double_t >( "PubTimeMax" );
fsChannelNameHistosInput = fConfig->GetValue< std::string >( "ChNameIn" );
fsChannelNameHistosConfig = fConfig->GetValue< std::string >( "ChNameHistCfg" );
fsChannelNameCanvasConfig = fConfig->GetValue< std::string >( "ChNameCanvCfg" );
if (fbNoSplitTs) {
if (fbSendTsPerSysId) {
if (fbSendTsPerChannel) {
......@@ -198,10 +205,12 @@ void CbmMQTsaMultiSampler::InitTask() try {
LOG(info) << "Number of defined output channels: " << noChannel;
for (auto const& entry : fChannels) {
/// Catches and ignores the channels for missing TS indices and commands
if (entry.first == fsChannelNameMissedTs
|| entry.first == fsChannelNameCommands) {
/// Same for the histogram channels
if (entry.first == fsChannelNameMissedTs || entry.first == fsChannelNameCommands
|| ( 0 < fuPublishFreqTs && ( entry.first == fsChannelNameHistosInput ||
entry.first == fsChannelNameHistosConfig || entry.first == fsChannelNameCanvasConfig ) ) ) {
continue;
} // if( entry.first == fsChannelNameMissedTs || entry.first == fsChannelNameCommands )
} // if( entry.first == fsChannelNameMissedTs || entry.first == fsChannelNameCommands || histo channels name)
LOG(info) << "Channel name: " << entry.first;
if (!IsChannelNameAllowed(entry.first))
......@@ -252,23 +261,80 @@ void CbmMQTsaMultiSampler::InitTask() try {
else if (fbSendTsPerChannel) {
LOG(info) << "Sending components in separate TS per channel";
} // else if( fbSendTsPerSysId && fbSendTsPerSysId ) of if( fbNoSplitTs )
/*
LOG(info) << "Histograms publication frequency in TS: " << fuPublishFreqTs;
LOG(info) << "Histograms publication min. interval in s: " << fdMinPublishTime;
LOG(info) << "Histograms publication max. interval in s: " << fdMaxPublishTime;
*/
/*
/// Histos creation and obtain pointer on them
/// Trigger histo creation on all associated algos
initOK &= CreateHistograms();
/// Add pointers to each histo in the histo array
/// Create histo config vector
/// ===> Use an std::vector< std::pair< std::string, std::string > > with < Histo name, Folder >
/// and send it through a separate channel using the BoostSerializer
for( UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto )
{
if( 0 < fuPublishFreqTs ) {
LOG(info) << "Histograms publication frequency in TS: " << fuPublishFreqTs;
LOG(info) << "Histograms publication min. interval in s: " << fdMinPublishTime;
LOG(info) << "Histograms publication max. interval in s: " << fdMaxPublishTime;
/// Vector of pointers on each histo (+ optionally desired folder)
std::vector< std::pair< TNamed *, std::string > > vHistos = {};
/// Vector of pointers on each canvas (+ optionally desired folder)
std::vector< std::pair< TCanvas *, std::string > > vCanvases = {};
/// Histos creation and obtain pointer on them
fhTsRate = new TH1I("TsRate", "TS rate; t [s]", 1800, 0., 1800.);
fhTsSize = new TH1I("TsSize", "Size of TS; Size [MB]", 15000, 0., 15000.);
fhTsSizeEvo = new TProfile( "TsSizeEvo", "Evolution of the TS Size; t [s]; Mean size [MB]", 1800, 0., 1800.);
fhTsMaxSizeEvo = new TH1F("TsMaxSizeEvo", "Evolution of maximal TS Size; t [s]; Max size [MB]", 1800, 0., 1800.);
fhMissedTS = new TH1I("Missed_TS", "Missed TS", 2, 0., 2.);
fhMissedTSEvo = new TProfile( "Missed_TS_Evo", "Missed TS evolution; t [s]", 1800, 0., 1800.);
/// Add histo pointers to the histo vector
vHistos.push_back( std::pair< TNamed *, std::string >( fhTsRate, "Sampler" ) );
vHistos.push_back( std::pair< TNamed *, std::string >( fhTsSize, "Sampler" ) );
vHistos.push_back( std::pair< TNamed *, std::string >( fhTsSizeEvo, "Sampler" ) );
vHistos.push_back( std::pair< TNamed *, std::string >( fhTsMaxSizeEvo, "Sampler" ) );
vHistos.push_back( std::pair< TNamed *, std::string >( fhMissedTS, "Sampler" ) );
vHistos.push_back( std::pair< TNamed *, std::string >( fhMissedTSEvo, "Sampler" ) );
/// Canvases creation
Double_t w = 10;
Double_t h = 10;
fcSummary = new TCanvas( "cSampSummary", "Sampler monitoring plots", w, h);
fcSummary->Divide(2, 3);
fcSummary->cd(1);
gPad->SetGridx();
gPad->SetGridy();
fhTsRate->Draw("hist");
fcSummary->cd(2);
gPad->SetGridx();
gPad->SetGridy();
gPad->SetLogx();
gPad->SetLogy();
fhTsSize->Draw("hist");
fcSummary->cd(3);
gPad->SetGridx();
gPad->SetGridy();
fhTsSizeEvo->Draw("hist");
fcSummary->cd(4);
gPad->SetGridx();
gPad->SetGridy();
fhTsMaxSizeEvo->Draw("hist");
fcSummary->cd(5);
gPad->SetGridx();
gPad->SetGridy();
fhMissedTS->Draw("hist");
fcSummary->cd(6);
gPad->SetGridx();
gPad->SetGridy();
fhMissedTSEvo->Draw("el");
/// Add canvas pointers to the canvas vector
vCanvases.push_back( std::pair< TCanvas *, std::string >( fcSummary, "canvases") );
/// Add pointers to each histo in the histo array
/// Create histo config vector
/// ===> Use an std::vector< std::pair< std::string, std::string > > with < Histo name, Folder >
/// and send it through a separate channel using the BoostSerializer
for( UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto )
{
// LOG(info) << "Registering " << vHistos[ uHisto ].first->GetName()
// << " in " << vHistos[ uHisto ].second.data()
// ;
......@@ -284,19 +350,18 @@ void CbmMQTsaMultiSampler::InitTask() try {
/// Send message to the common histogram config messages queue
if( Send( messageHist, fsChannelNameHistosConfig ) < 0 )
{
LOG(error) << "Problem sending histo config";
return false;
LOG(fatal) << "Problem sending histo config";
} // if( Send( messageHist, fsChannelNameHistosConfig ) < 0 )
LOG(info) << "Config of hist " << psHistoConfig.first.data()
<< " in folder " << psHistoConfig.second.data() ;
} // for( UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto )
} // for( UInt_t uHisto = 0; uHisto < vHistos.size(); ++uHisto )
/// Create canvas config vector
/// ===> Use an std::vector< std::pair< std::string, std::string > > with < Canvas name, config >
/// and send it through a separate channel using the BoostSerializer
for( UInt_t uCanv = 0; uCanv < vCanvases.size(); ++uCanv )
{
/// Create canvas config vector
/// ===> Use an std::vector< std::pair< std::string, std::string > > with < Canvas name, config >
/// and send it through a separate channel using the BoostSerializer
for( UInt_t uCanv = 0; uCanv < vCanvases.size(); ++uCanv )
{
// LOG(info) << "Registering " << vCanvases[ uCanv ].first->GetName()
// << " in " << vCanvases[ uCanv ].second.data();
std::string sCanvName = (vCanvases[ uCanv ].first)->GetName();
......@@ -313,20 +378,18 @@ void CbmMQTsaMultiSampler::InitTask() try {
/// Send message to the common canvas config messages queue
if( Send( messageCan, fsChannelNameCanvasConfig ) < 0 )
{
LOG(error) << "Problem sending canvas config";
return false;
LOG(fatal) << "Problem sending canvas config";
} // if( Send( messageCan, fsChannelNameCanvasConfig ) < 0 )
LOG(info) << "Config string of Canvas " << psCanvConfig.first.data()
<< " is " << psCanvConfig.second.data() ;
} // for( UInt_t uCanv = 0; uCanv < vCanvases.size(); ++uCanv )
*/
} // for( UInt_t uCanv = 0; uCanv < vCanvases.size(); ++uCanv )
} // if( 0 < fuPublishFreqTs )
fTime = std::chrono::steady_clock::now();
} catch (InitTaskError& e) {
LOG(error) << e.what();
// Wrapper defined in CbmMQDefs.h to support different FairMQ versions
cbm::mq::ChangeState(this, cbm::mq::Transition::ErrorFound);
ChangeState(fair::mq::Transition::ErrorFound);
}
bool CbmMQTsaMultiSampler::IsChannelNameAllowed(std::string channelName) {
......@@ -374,7 +437,6 @@ bool CbmMQTsaMultiSampler::IsChannelNameAllowed(std::string channelName) {
bool CbmMQTsaMultiSampler::ConditionalRun() {
auto timeslice = fSource->get();
if (timeslice) {
if (fTSCounter < fMaxTimeslices) {
......@@ -383,6 +445,38 @@ bool CbmMQTsaMultiSampler::ConditionalRun() {
const fles::Timeslice& ts = *timeslice;
uint64_t uTsIndex = ts.index();
if( 0 < fuPublishFreqTs ) {
uint64_t uTsTime = ts.descriptor(0, 0).idx;
if( 0 == fuStartTime ) {
fuStartTime = uTsTime;
} // if( 0 == fuStartTime )
fdTimeToStart = static_cast< double_t >(uTsTime - fuStartTime)/1e9;
uint64_t uSizeMb = 0;
for( uint64_t uComp = 0; uComp < ts.num_components(); ++uComp ) {
uSizeMb += ts.size_component( uComp ) / (1024 * 1024);
} // for( uint_t uComp = 0; uComp < ts.num_components(); ++uComp )
fhTsRate->Fill( fdTimeToStart );
fhTsSize->Fill( uSizeMb );
fhTsSizeEvo->Fill( fdTimeToStart, uSizeMb );
/// Fill max size per s (assumes the histo binning is 1 second!)
if( 0. == fdLastMaxTime ) {
fdLastMaxTime = fdTimeToStart;
fdTsMaxSize = uSizeMb;
} // if( 0. == fdLastMaxTime )
else if( 1. <= fdTimeToStart - fdLastMaxTime ) {
fhTsMaxSizeEvo->Fill( fdLastMaxTime, fdTsMaxSize );
fdLastMaxTime = fdTimeToStart;
fdTsMaxSize = uSizeMb;
} // else if if( 1 <= fdTimeToStart - fdLastMaxTime )
else if( fdTsMaxSize < uSizeMb ) {
fdTsMaxSize = uSizeMb;
} // else if( fdTsMaxSize < uSizeMb )
} // if( 0 < fuPublishFreqTs )
/// Missed TS detection (only if output channel name defined by user)
if ((uTsIndex != (fuPrevTsIndex + 1))
&& (0 != fuPrevTsIndex && 0 != uTsIndex)
......@@ -404,7 +498,18 @@ bool CbmMQTsaMultiSampler::ConditionalRun() {
return false;
} // if( !SendMissedTsIdx( vulMissedIndices ) )
if( 0 < fuPublishFreqTs ) {
fhMissedTS->Fill(1, uTsIndex - fuPrevTsIndex);
fhMissedTSEvo->Fill(fdTimeToStart, 1, uTsIndex - fuPrevTsIndex);
} // if( 0 < fuPublishFreqTs )
} // if( ( uTsIndex != ( fuPrevTsIndex + 1 ) ) && ( 0 != fuPrevTsIndex && 0 != uTsIndex ) && "" != fsChannelNameMissedTs )
else if( 0 < fuPublishFreqTs ) {
fhMissedTS->Fill(0);
fhMissedTSEvo->Fill(fdTimeToStart, 0, 1);
} // else if( 0 < fuPublishFreqTs )
fuPrevTsIndex = uTsIndex;
if (fTSCounter % 10000 == 0) {
......@@ -473,8 +578,23 @@ bool CbmMQTsaMultiSampler::ConditionalRun() {
} // if( !CreateAndSendComponent(ts, nrComp) )
} // for (unsigned int nrComp = 0; nrComp < ts.num_components(); ++nrComp)
} // else of if( fbSendTsPerSysId )
if( 0 < fuPublishFreqTs ) {
/// Send histograms periodically.
/// Use also runtime checker to trigger sending after M s if
/// processing too slow or delay sending if processing too fast
std::chrono::system_clock::time_point currentTime = std::chrono::system_clock::now();
std::chrono::duration<double_t> elapsedSeconds = currentTime - fLastPublishTime;
if ((fdMaxPublishTime < elapsedSeconds.count()) ||
(0 == fTSCounter % fuPublishFreqTs && fdMinPublishTime < elapsedSeconds.count())) {
SendHistograms();
fLastPublishTime = std::chrono::system_clock::now();
} // if( ( fdMaxPublishTime < elapsedSeconds.count() ) || ( 0 == fTSCounter % fuPublishFreqTs && fdMinPublishTime < elapsedSeconds.count() ) )
} // if( 0 < fuPublishFreqTs )
return true;
} else {
} // if (fTSCounter < fMaxTimeslices)
else {
CalcRuntime();
/// If command channel defined, send command to all "slaves"
......@@ -489,8 +609,9 @@ bool CbmMQTsaMultiSampler::ConditionalRun() {
} // if( "" != fsChannelNameCommands )
return false;
}
} else {
} // else of if (fTSCounter < fMaxTimeslices)
} // if (timeslice)
else {
CalcRuntime();
/// If command channel defined, send command to all "slaves"
......@@ -505,20 +626,7 @@ bool CbmMQTsaMultiSampler::ConditionalRun() {
} // if( "" != fsChannelNameCommands )
return false;
}
/*
/// Send histograms each 100 time slices. Should be each ~1s
/// Use also runtime checker to trigger sending after M s if
/// processing too slow or delay sending if processing too fast
std::chrono::system_clock::time_point currentTime = std::chrono::system_clock::now();
std::chrono::duration<double_t> elapsedSeconds = currentTime - fLastPublishTime;
if( ( fdMaxPublishTime < elapsedSeconds.count() ) ||
( 0 == fulNumMessages % fuPublishFreqTs && fdMinPublishTime < elapsedSeconds.count() ) )
{
SendHistograms();
fLastPublishTime = std::chrono::system_clock::now();
} // if( ( fdMaxPublishTime < elapsedSeconds.count() ) || ( 0 == fulNumMessages % fuPublishFreqTs && fdMinPublishTime < elapsedSeconds.count() ) )
*/
} // else of if (timeslice)
}
bool CbmMQTsaMultiSampler::CreateAndSendComponent(const fles::Timeslice& ts,
......@@ -892,26 +1000,37 @@ bool CbmMQTsaMultiSampler::SendCommand(std::string sCommand) {
return true;
}
/*
bool CbmMQTsaMultiSampler::SendHistograms()
{
/// Serialize the array of histos into a single MQ message
FairMQMessagePtr message( NewMessage() );
Serialize<RootSerializer>( *message, &fArrayHisto );
/// Send message to the common histogram messages queue
if( Send( message, fsChannelNameHistosInput ) < 0 )
{
LOG(error) << "Problem sending data";
return false;
} // if( Send( message, fsChannelNameHistosInput ) < 0 )
/// Serialize the array of histos into a single MQ message
FairMQMessagePtr message( NewMessage() );
Serialize<RootSerializer>( *message, &fArrayHisto );
/// Send message to the common histogram messages queue
if( Send( message, fsChannelNameHistosInput ) < 0 )
{
LOG(error) << "Problem sending data";
return false;
} // if( Send( message, fsChannelNameHistosInput ) < 0 )
/// Reset the histograms after sending them (but do not reset the time)
ResetHistograms();
/// Reset the histograms after sending them (but do not reset the time)
ResetHistograms();
return true;
}
return true;
bool CbmMQTsaMultiSampler::ResetHistograms()
{
fhTsRate->Reset();
fhTsSize->Reset();
fhTsSizeEvo->Reset();
fhTsMaxSizeEvo->Reset();
fhMissedTS->Reset();
fhMissedTSEvo->Reset();
return true;
}
*/
CbmMQTsaMultiSampler::~CbmMQTsaMultiSampler() {}
......
......@@ -16,8 +16,15 @@
#include "FairMQDevice.h"
class TCanvas;
class TH1F;
class TH1I;
class TProfile;
#include <TObjArray.h>
#include <ctime>
#include <string>
#include <utility>
#include <vector>
class CbmMQTsaMultiSampler : public FairMQDevice {
......@@ -40,14 +47,14 @@ protected:
bool fbNoSplitTs = false;
bool fbSendTsPerSysId = false;
bool fbSendTsPerChannel = false;
/*
std::string fsChannelNameHistosInput = "histogram-in";
std::string fsChannelNameHistosConfig = "histo-conf";
std::string fsChannelNameCanvasConfig = "canvas-conf";
uint32_t fuPublishFreqTs = 100;
double_t fdMinPublishTime = 0.5;
double_t fdMaxPublishTime = 5;
*/
std::string fsChannelNameHistosInput = "histogram-in";
std::string fsChannelNameHistosConfig = "histo-conf";
std::string fsChannelNameCanvasConfig = "canvas-conf";
uint32_t fuPublishFreqTs = 0;
double_t fdMinPublishTime = 0.5;
double_t fdMaxPublishTime = 5;
uint64_t fuPrevTsIndex = 0;
uint64_t fTSCounter;
uint64_t fMessageCounter;
......@@ -73,12 +80,12 @@ private:
bool SendData(const fles::StorableTimeslice&, std::string);
bool SendMissedTsIdx(std::vector<uint64_t> vIndices);
bool SendCommand(std::string sCommand);
/*
bool SendHistograms();
*/
bool ResetHistograms();
fles::TimesliceSource* fSource; //!
std::chrono::steady_clock::time_point fTime;
std::chrono::system_clock::time_point fLastPublishTime;
// The vector fAllowedChannels contain the list of defined channel names
......@@ -115,21 +122,29 @@ private:
std::string fsChannelNameMissedTs = "";
std::string fsChannelNameCommands = "";
/*
/// Obtain vector of pointers on each histo from the algo (+ optionally desired folder)
std::vector< std::pair< TNamed *, std::string > > vHistos = fMonitorAlgo->GetHistoVector();
/// Obtain vector of pointers on each canvas from the algo (+ optionally desired folder)
std::vector< std::pair< TCanvas *, std::string > > vCanvases = fMonitorAlgo->GetCanvasVector();
/// Array of histograms to send to the histogram server
TObjArray fArrayHisto = {};
/// Vector of string pairs with ( HistoName, FolderPath ) to send to the histogram server
std::vector< std::pair< std::string, std::string > > fvpsHistosFolder = {};
/// Vector of string pairs with ( CanvasName, CanvasConfig ) to send to the histogram server
/// Format of Can config is "NbPadX(U);NbPadY(U);ConfigPad1(s);....;ConfigPadXY(s)"
/// Format of Pad config is "GrixX(b),GridY(b),LogX(b),LogY(b),LogZ(b),HistoName(s),DrawOptions(s)"
std::vector< std::pair< std::string, std::string > > fvpsCanvasConfig = {};
*/
/// Array of histograms to send to the histogram server
TObjArray fArrayHisto = {};
/// Vector of string pairs with ( HistoName, FolderPath ) to send to the histogram server
std::vector< std::pair< std::string, std::string > > fvpsHistosFolder = {};
/// Vector of string pairs with ( CanvasName, CanvasConfig ) to send to the histogram server
/// Format of Can config is "NbPadX(U);NbPadY(U);ConfigPad1(s);....;ConfigPadXY(s)"
/// Format of Pad config is "GrixX(b),GridY(b),LogX(b),LogY(b),LogZ(b),HistoName(s),DrawOptions(s)"
std::vector< std::pair< std::string, std::string > > fvpsCanvasConfig = {};
/// Histograms
TH1I* fhTsRate = nullptr;
TH1I* fhTsSize = nullptr;
TProfile* fhTsSizeEvo = nullptr;
TH1F* fhTsMaxSizeEvo = nullptr;
TH1I* fhMissedTS = nullptr;
TProfile* fhMissedTSEvo = nullptr;
TCanvas* fcSummary = nullptr;
uint64_t fuStartTime = 0;
double_t fdTimeToStart = 0.;
double_t fdLastMaxTime = 0.;
double_t fdTsMaxSize = 0.;
};
#endif /* CBMMQTSASAMPLER_H_ */
......@@ -41,14 +41,20 @@ void addCustomOptions(bpo::options_description& options) {
options.add_options()("ChNameCmds",
bpo::value<std::string>()->default_value(""),
"MQ channel name for commands to slaves");
/*
options.add_options() ( "ChNameIn", bpo::value< std::string >()->default_value( "histogram-in" ),
"MQ channel name for histos");
options.add_options() ( "ChNameHistCfg", bpo::value< std::string >()->default_value( "histo-conf" ),
"MQ channel name for histos config");
options.add_options() ( "ChNameCanvCfg", bpo::value< std::string >()->default_value( "canvas-conf" ),
"MQ channel name for canvases config");
*/
options.add_options()("PubFreqTs", bpo::value<uint32_t>()->default_value(0),
"Histo publishing frequency in TS");
options.add_options()("PubTimeMin", bpo::value<double_t>()->default_value(1.0),
"Minimal time between two publishing");
options.add_options()("PubTimeMax", bpo::value<double_t>()->default_value(10.0),
"Maximal time between two publishing");
options.add_options()("ChNameIn", bpo::value< std::string >()->default_value( "histogram-in" ),
"MQ channel name for histos");
options.add_options()("ChNameHistCfg", bpo::value< std::string >()->default_value( "histo-conf" ),
"MQ channel name for histos config");
options.add_options()("ChNameCanvCfg", bpo::value< std::string >()->default_value( "canvas-conf" ),
"MQ channel name for canvases config");
}
FairMQDevicePtr getDevice(const FairMQProgOptions& /*config*/) {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment