1 #define TRACE_NAME "RoutingReceiver"
2 #include "artdaq/DAQdata/Globals.hh"
5 #include <netinet/in.h>
7 #include <sys/socket.h>
12 #include "artdaq/Application/LoadParameterSet.hh"
14 #include "artdaq/DAQrate/detail/RoutingPacket.hh"
15 #include "artdaq/DAQrate/detail/TableReceiver.hh"
16 #include "canvas/Utilities/Exception.h"
17 #include "fhiclcpp/types/Atom.h"
18 #include "fhiclcpp/types/OptionalTable.h"
19 #include "fhiclcpp/types/TableFragment.h"
20 #include "proto/artdaqapp.hh"
29 fhicl::Atom<size_t>
collection_time_ms{fhicl::Name{
"collection_time_ms"}, fhicl::Comment{
"Time to collect routing table updates between printing summaries"}, 1000};
31 fhicl::Atom<bool>
print_verbose_info{fhicl::Name{
"print_verbose_info"}, fhicl::Comment{
"Print verbose information about each receiver detected in routing tables"},
true};
33 fhicl::Atom<size_t>
graph_width{fhicl::Name{
"graph_width"}, fhicl::Comment{
"Width of the summary graph"}, 40};
35 fhicl::OptionalTable<artdaq::TableReceiver::Config>
routingTableConfig{fhicl::Name{
"routing_table_config"}, fhicl::Comment{
"Configuration for the TableReceiver"}};
41 static bool sighandler_init =
false;
42 static bool should_stop =
false;
43 static void signal_handler(
int signum)
46 #if TRACE_REVNUM < 1459
47 TRACE_STREAMER(TLVL_ERROR, &(
"routingReceiver")[0], 0, 0, 0)
49 TRACE_STREAMER(TLVL_ERROR, TLOG2(
"routingReceiver", 0), 0)
51 <<
"A signal of type " << signum <<
" was caught by routingReceiver. Stopping receive loop!";
56 pthread_sigmask(SIG_UNBLOCK,
nullptr, &set);
57 pthread_sigmask(SIG_UNBLOCK, &set,
nullptr);
60 int main(
int argc,
char* argv[])
try
62 artdaq::configureMessageFacility(
"RoutingReceiver",
false,
false);
63 static std::mutex sighandler_mutex;
64 std::unique_lock<std::mutex> lk(sighandler_mutex);
68 sighandler_init =
true;
69 std::vector<int> signals = {SIGINT, SIGTERM, SIGUSR1, SIGUSR2};
70 for (
auto signal : signals)
72 struct sigaction old_action;
73 sigaction(signal,
nullptr, &old_action);
77 if (old_action.sa_handler != SIG_IGN)
79 struct sigaction action;
80 action.sa_handler = signal_handler;
81 sigemptyset(&action.sa_mask);
82 for (
auto sigblk : signals)
84 sigaddset(&action.sa_mask, sigblk);
89 sigaction(signal, &action,
nullptr);
94 fhicl::ParameterSet init_ps = LoadParameterSet<artdaq::RoutingReceiverConfig>(argc, argv,
"routingReceiver",
"This application receives Routing Tables, and calculates statistics about the usage of the receivers");
95 auto config_ps = init_ps.get<fhicl::ParameterSet>(
"daq", init_ps);
96 auto metric_ps = config_ps.get<fhicl::ParameterSet>(
"metrics", config_ps);
97 auto fr_ps = config_ps.get<fhicl::ParameterSet>(
"fragment_receiver", config_ps);
98 auto rmConfig = fr_ps.get<fhicl::ParameterSet>(
"routing_table_config", fhicl::ParameterSet());
103 auto collection_time_ms = init_ps.get<
size_t>(
"collection_time_ms", 1000);
104 auto max_graph_width = init_ps.get<
size_t>(
"max_graph_width", 100);
105 bool print_verbose = init_ps.get<
bool>(
"print_verbose_info",
true);
106 bool verbose_clear_screen = init_ps.get<
bool>(
"clear_screen",
true);
108 auto blue =
"\033[34m";
109 auto cyan =
"\033[36m";
110 auto green =
"\033[32m";
111 auto yellow =
"\033[93m";
112 auto red =
"\033[31m";
114 metricMan->initialize(metric_ps,
"RoutingReceiver");
115 metricMan->do_start();
116 if (print_verbose && verbose_clear_screen)
118 std::cout <<
"\033[2J";
121 std::map<int, int> receiver_table = std::map<int, int>();
125 auto start_time = std::chrono::steady_clock::now();
127 auto this_table = rr.GetAndClearRoutingTable();
129 if (!this_table.empty())
131 auto graph_width = this_table.size();
133 auto graph_width_orig = graph_width;
134 while (graph_width > max_graph_width)
137 graph_width = graph_width_orig / n;
140 for (
auto& entry : this_table)
142 receiver_table[entry.second]++;
145 auto average_entries_per_receiver = this_table.size() / receiver_table.size();
148 auto cyan_threshold = ((average_entries_per_receiver - offset) / 2) / n;
149 auto green_threshold = (average_entries_per_receiver - offset) / n;
150 auto yellow_threshold = (average_entries_per_receiver + offset) / n;
151 auto red_threshold = (2 * average_entries_per_receiver) / n;
153 TLOG(TLVL_TRACE) <<
"CT: " << cyan_threshold <<
", GT: " << green_threshold <<
", YT: " << yellow_threshold <<
", RT: " << red_threshold;
155 std::ostringstream report;
156 std::ostringstream verbose_report;
158 if (print_verbose && verbose_clear_screen)
160 std::cout <<
"\033[;H\033[J";
163 report << artdaq::TimeUtils::gettimeofday_us() <<
": " << this_table.size() <<
" Entries, ";
164 for (
auto& receiver : receiver_table)
166 auto percent =
static_cast<int>(receiver.second * 100 / this_table.size());
167 report << receiver.first <<
": " << receiver.second <<
" (" << percent <<
"%), ";
170 verbose_report << receiver.first <<
": " << receiver.second <<
" (" << percent <<
"%)\t[";
172 size_t graph_characters = receiver.second / n;
174 for (
size_t ii = 0; ii < graph_characters; ++ii)
176 if (ii < cyan_threshold)
178 verbose_report << blue;
180 else if (ii < green_threshold)
182 verbose_report << cyan;
184 else if (ii < yellow_threshold)
186 verbose_report << green;
188 else if (ii < red_threshold)
190 verbose_report << yellow;
194 verbose_report << red;
196 verbose_report <<
"|";
198 std::string spaces = std::string(graph_width - graph_characters,
' ');
199 verbose_report <<
"\033[0m" << spaces <<
"]" << std::endl;
203 TLOG(TLVL_INFO) << report.str();
204 std::cout << report.str() << std::endl;
207 std::cout << verbose_report.str() << std::endl;
210 std::this_thread::sleep_until(start_time + std::chrono::milliseconds(collection_time_ms));
213 metricMan->do_stop();
fhicl::Atom< size_t > collection_time_ms
"collection_time_ms": Time to collect routing table updates between printing summaries ...
static void CleanUpGlobals()
Clean up statically-allocated Manager class instances.
fhicl::TableFragment< artdaq::artdaqapp::Config > artdaqAppConfig
Configuration for artdaq Application (BoardReader, etc)
Class which receives routing tables and prints updates.
fhicl::Atom< size_t > graph_width
"graph_width": Width of the summary graph
fhicl::OptionalTable< artdaq::TableReceiver::Config > routingTableConfig
Configuration for the TableReceiver. See artdaq::TableReceiver::Config.
Sends Fragment objects using TransferInterface plugins. Uses Routing Tables if confgiured, otherwise will Round-Robin Fragments to the destinations.
hostMap_t MakeHostMap(fhicl::ParameterSet const &pset, hostMap_t map=hostMap_t())
Make a hostMap_t from a HostMap::Config ParameterSet
fhicl::Atom< bool > print_verbose_info
"print_verbose_info" (Default: true): Print verbose information about each receiver detected in routi...