135 #include <boost/asio.hpp>
136 #include <boost/program_options.hpp>
138 #include <sys/ioctl.h>
144 #if BOOST_VERSION >= 107000
145 #define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context())
147 #define GET_IO_SERVICE(s) ((s).get_io_service())
150 #include "structs.hpp"
151 #include "datatypes.hpp"
152 #include "version.hpp"
153 #include "ligier_helper.hpp"
154 #include "consumers.hpp"
155 #include "dom_map.hpp"
159 static bool const is_a_tty = isatty(1);
166 ioctl(1, TIOCGWINSZ, &sz);
171 namespace po = boost::program_options;
182 boost::asio::signal_set& set,
184 boost::system::error_code
const& error,
188 template<
class Consumer>
205 boost::system::error_code
const& error
209 if (error && error != boost::asio::error::operation_aborted) {
212 }
else if (error == boost::asio::error::operation_aborted) {
216 boost::asio::async_read(
222 , boost::asio::placeholders::error
223 , boost::asio::placeholders::bytes_transferred
237 , boost::asio::placeholders::error
245 if (error && error != boost::asio::error::operation_aborted) {
247 m_timer.expires_from_now(boost::posix_time::seconds(1));
253 , boost::asio::placeholders::error
256 }
else if (error == boost::asio::error::operation_aborted) {
260 boost::asio::async_write(
262 , boost::asio::buffer(
m_buffer, size)
266 , boost::asio::placeholders::error
267 , boost::asio::placeholders::bytes_transferred
274 boost::system::error_code
const& error
275 , std::size_t bytes_transferred
277 if (error && error != boost::asio::error::operation_aborted) {
280 }
else if (error == boost::asio::error::operation_aborted) {
282 boost::asio::async_read(
288 , boost::asio::placeholders::error
289 , boost::asio::placeholders::bytes_transferred
296 boost::system::error_code
const& error
297 , std::size_t bytes_transferred
299 if (error && error != boost::asio::error::operation_aborted) {
302 }
else if (error == boost::asio::error::operation_aborted) {
306 boost::asio::async_read(
308 , boost::asio::buffer(
m_buffer + 16, size)
312 , boost::asio::placeholders::error
313 , boost::asio::placeholders::bytes_transferred
321 boost::system::error_code ec;
323 m_socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
331 , boost::asio::placeholders::error
342 boost::asio::io_service& service
343 , std::string
const& tag
344 , boost::asio::ip::tcp::endpoint
const& endpoint
347 , Consumer
const& consumer
361 , boost::asio::placeholders::error
367 template<
class Consumer>
378 boost::system::error_code
const& error
379 , std::size_t bytes_transferred
392 , boost::asio::placeholders::error
393 , boost::asio::placeholders::bytes_transferred
401 boost::asio::io_service& service
405 , Consumer
const& consumer
408 , boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), port)
414 boost::asio::ip::udp::socket::receive_buffer_size option(33554432);
422 , boost::asio::placeholders::error
423 , boost::asio::placeholders::bytes_transferred
431 std::string
const& address
433 boost::asio::io_service service;
434 boost::asio::ip::tcp::resolver resolver(service);
436 std::string::size_type
const pos = address.find(
":");
438 std::string
const host = pos == std::string::npos ? address : address.substr(0, pos);
439 std::string
const port = pos == std::string::npos ?
"5553" : address.substr(pos + 1);
441 boost::asio::ip::tcp::resolver::query query(
442 boost::asio::ip::tcp::v4()
447 return *resolver.resolve(query);
450 int main(
int argc,
char* argv[])
454 bool uses_roy =
false;
455 bool use_gui =
false;
456 bool lm_mode =
false;
458 std::string dom_names = std::getenv(
"HOME") + std::string(
"/.doms.csk");
459 dom_map_type dom_names_map;
461 std::ofstream output_file;
463 unsigned int port = 0;
465 std::string filename;
466 std::string roy_setup;
468 std::string lserver =
"localhost:5553";
470 boost::asio::ip::tcp::endpoint endpoint;
472 po::options_description desc(
"Generic options");
474 (
"help,h",
"Print this help and exit.")
475 (
"version,v",
"Print the version and exit.")
478 , po::value<std::string>(&dom_names)->value_name(
"filename")
479 ,
"File that specifies a conversion from DOM IDs to a human readable name."
482 (
"gui,g",
"Use GUI (avalilable in UDP-monitoring and Ligier modes only).")
484 (
"ligier,l",
"Set Ligier mode.")
485 (
"udp,u",
"Force UDP mode (default).");
487 po::options_description lmdesc(
"Ligier-mode options");
491 , po::value<std::string>(&lserver)
492 ->default_value(
"localhost:5553")
493 ->value_name(
"server:[port]")
494 ,
"Set the Ligier server endpoint to read data from."
498 , po::value<std::string>(&tag)
499 ->default_value(
"IO_MONIT")
501 ,
"Set the Ligier tag to read data from."
504 po::options_description umdesc(
"UDP-mode options");
507 po::value<unsigned int>(&port)
509 ->value_name(
"port"),
510 "Set the expected data type to optical. If a port is not \
511 provided the default one is used (56015).")
513 po::value<unsigned int>(&port)
515 ->value_name(
"port"),
516 "Set the expected data type to acoustic. If a port is not \
517 provided the default one is used (56016).")
519 po::value<unsigned int>(&port)
521 ->value_name(
"port"),
522 "Set the expected data type to monitoring. If a port is \
523 not provided the default one is used (56017).")
525 po::value<unsigned int>(&port)->value_name(
"port"),
526 "Listen on the specified port, automatically determining the \
529 po::value<std::string>(&filename)->value_name(
"filename"),
530 "Dumps the acquired data to a file.")
532 po::value<std::string>(&roy_setup)
533 ->implicit_value(
"HR_%n.%c:localhost:9999")
534 ->value_name(
"format:host:port"),
535 "Send the monitoring hit rates to the specified ROyWeb \
536 server. The syntax is format:server_ip:server_port. \
537 The format parameter can contain the following placeholders: %d for \
538 DOM ID, %n for DOM name (if available, otherwise the DOM ID is used) \
539 and %c for channel ID.");
542 std::string roy_server;
546 po::options_description global;
547 global.add(desc).add(lmdesc).add(umdesc);
549 po::variables_map vm;
551 po::command_line_parser(argc, argv).
options(global).run()
555 if (vm.count(
"help")) {
563 if (vm.count(
"version")) {
571 use_gui = vm.count(
"gui");
574 lm_mode = vm.count(
"ligier");
576 if (lm_mode && vm.count(
"udp")) {
577 throw std::runtime_error(
"You can specify only one mode. Both provided.");
580 if (vm.count(
"map")) {
581 std::ifstream
map(dom_names.c_str());
584 throw std::runtime_error(
585 std::string(
"Error reading map file: ")
586 + std::strerror(errno)
592 std::ifstream
map(dom_names.c_str());
598 po::variables_map vm;
599 po::options_description
options;
600 options.add(lmdesc).add(desc);
603 po::command_line_parser(argc, argv).
options(options).run()
613 po::variables_map vm;
614 po::options_description
options;
615 options.add(desc).add(umdesc);
618 po::command_line_parser(argc, argv).
options(options).run()
624 unsigned int counter = 0;
625 if (vm.count(
"port")) {
629 if (vm.count(
"optical")) {
633 if (vm.count(
"acoustic")) {
637 if (vm.count(
"monitoring")) {
644 throw std::runtime_error(
"More than one port provided.");
646 throw std::runtime_error(
"You must specify at least one port.");
650 if (use_gui && type !=
tmch) {
651 throw std::runtime_error(
"GUI is only available in monitoring mode");
654 if (vm.count(
"royweb")) {
656 throw std::runtime_error(
"you can use ROyWeb only with the"
657 " monitoring channel");
661 std::replace(roy_setup.begin(), roy_setup.end(),
':',
' ');
662 std::istringstream ss(roy_setup);
667 if (ss >> roy_server) {
670 if (ss >> roy_port) {
674 if (param_count != 3) {
675 throw std::runtime_error(
"you must specify all the parameters"
676 " or accept all the default one to use with ROyWeb.");
680 if (vm.count(
"dumpfile")) {
681 output_file.open(filename.c_str(), std::ios::binary);
683 throw std::runtime_error(
684 "Unable to open file "
693 }
catch (
const po::error& e) {
695 <<
"CLBSwissKnife: Error: " << e.what() <<
'\n'
701 }
catch (
const std::runtime_error& e) {
702 std::cerr <<
"CLBSwissKnife: Error: " << e.what() << std::endl;
706 boost::asio::io_service io_service;
717 boost::asio::deadline_timer timer(io_service, boost::posix_time::seconds(1));
719 boost::asio::posix::stream_descriptor keyb(io_service, ::dup(STDIN_FILENO));
721 boost::asio::signal_set window_resize(io_service, SIGWINCH);
724 gui::ScreenInitialiser init;
726 gui::Screen screen(io_service, lserver, stats);
728 keyb.async_read_some(
729 boost::asio::buffer(&key,
sizeof(key)),
735 boost::asio::placeholders::error,
736 boost::asio::placeholders::bytes_transferred
745 boost::asio::placeholders::error
755 , clbsk::consumer::Gui(terminal_width, dom_names_map, stats, screen)
758 window_resize.async_wait(
761 boost::ref(window_resize),
763 boost::asio::placeholders::error,
764 boost::asio::placeholders::signal_number
771 std::cout <<
"Listening from: " << endpoint <<
':' << tag <<
'\n';
772 boost::asio::signal_set signals_handler(io_service, SIGWINCH, SIGINT);
774 signals_handler.async_wait(
777 boost::ref(signals_handler),
778 boost::ref(terminal_width),
779 boost::asio::placeholders::error,
780 boost::asio::placeholders::signal_number
790 , clbsk::consumer::Scrollback(terminal_width,
tmch, dom_names_map)
796 std::cout <<
"Listening port: " << port <<
'\n' <<
"Data type: ";
799 std::cout <<
"Acoustic\n";
800 }
else if (type ==
ttdc) {
801 std::cout <<
"Optical\n";
802 }
else if (type ==
tmch) {
803 std::cout <<
"Monitoring\n";
805 std::cout <<
"Automatically determined\n";
808 clbsk::consumer::ConsumerSet consumer_set;
810 trm::MonStreamer ms(roy_server, roy_port);
818 <<
") with tag format "
819 << templ << std::endl;
822 clbsk::consumer::Roy(
831 consumer_set.add(clbsk::consumer::File(output_file));
838 boost::asio::deadline_timer timer(io_service, boost::posix_time::seconds(1));
840 boost::asio::posix::stream_descriptor keyb(io_service, ::dup(STDIN_FILENO));
842 boost::asio::signal_set window_resize(io_service, SIGWINCH);
845 gui::ScreenInitialiser init;
847 std::string
const heading
848 =
"UDP " + boost::lexical_cast<std::string>(port);
850 gui::Screen screen(io_service, heading, stats);
852 keyb.async_read_some(
853 boost::asio::buffer(&key,
sizeof(key)),
859 boost::asio::placeholders::error,
860 boost::asio::placeholders::bytes_transferred
869 boost::asio::placeholders::error
873 window_resize.async_wait(
876 boost::ref(window_resize),
878 boost::asio::placeholders::error,
879 boost::asio::placeholders::signal_number
884 clbsk::consumer::Gui(
904 clbsk::consumer::Scrollback(
911 boost::asio::signal_set signals_handler(io_service, SIGWINCH, SIGINT);
913 signals_handler.async_wait(
916 , boost::ref(signals_handler)
917 , boost::ref(terminal_width)
918 , boost::asio::placeholders::error
919 , boost::asio::placeholders::signal_number
937 boost::asio::signal_set& set,
939 boost::system::error_code
const& error,
944 if (signum == SIGINT) {
949 std::cout <<
"\033]2;thank you for flying with CLBSwissKnife!\007";
950 std::cout <<
"\rBye bye!\n";
953 }
else if (signum == SIGWINCH) {
961 boost::ref(terminal_width),
962 boost::asio::placeholders::error,
963 boost::asio::placeholders::signal_number
static int terminal_width
void data_handle(boost::system::error_code const &error, std::size_t bytes_transferred)
void handle_signal(boost::asio::signal_set &set, int &terminal_width, boost::system::error_code const &error, int signum)
struct __attribute__((__packed__)) InfoWord
void async_win_resize(boost::asio::signal_set &window_resize, gui::Screen &screen, boost::system::error_code const &error, int signum)
int main(int argc, char *argv[])
TString replace(const TString &target, const TRegexp ®exp, const T &replacement)
Replace regular expression in input by given replacement.
std::size_t m_buffer_size
void timeout_handle(boost::system::error_code const &error)
LigierDataHandler(LigierDataHandler const &)
UdpDataHandler(boost::asio::io_service &service, int port, char *buffer, std::size_t buffer_size, Consumer const &consumer)
std::size_t const m_buffer_size
LigierDataHandler(boost::asio::io_service &service, std::string const &tag, boost::asio::ip::tcp::endpoint const &endpoint, char *buffer, std::size_t buffer_size, Consumer const &consumer)
then set_variable PMT_FILE set_variable DAQ_FILE set_variable OUTPUT_FILE set_variable DETECTOR else fatal Wrong number of arguments fi JPrintTree f $DAQ_FILE type
void data_handle(boost::system::error_code const &error, std::size_t size)
then usage $script[port]< option > nPossible options
LigierDataHandler & operator=(LigierDataHandler const &)
static const size_t buffer_size
void store(const std::string &file_name, const JDetector &detector)
Store detector to output file.
std::size_t prepare_tag(char *buffer, std::size_t max_size, std::string const &tag)
void subscribe_handle(boost::system::error_code const &error, std::size_t bytes_transferred)
void connect_handle(boost::system::error_code const &error)
boost::asio::ip::tcp::endpoint m_endpoint
void header_handle(boost::system::error_code const &error, std::size_t bytes_transferred)
static const unsigned int default_opto_port
boost::asio::deadline_timer m_timer
boost::asio::ip::tcp::endpoint make_endpoint(const std::string &address)
void async_cin(boost::asio::posix::stream_descriptor &keyb, char &key, gui::Screen &screen, const boost::system::error_code &error, std::size_t bytes_transferred)
std::size_t read_data_size(char const *const buffer)
void async_commit(boost::asio::deadline_timer &timer, gui::Screen &screen, boost::system::error_code const &error)
dom_map_type load_dom_map(std::istream &map)
boost::asio::ip::udp::socket m_socket
boost::asio::ip::tcp::socket m_socket
LigierDataHandler< Consumer > this_type
UdpDataHandler< Consumer > this_type
#define GET_IO_SERVICE(s)
Program name: CLBSwissKnife.
static const unsigned int default_acou_port
static const unsigned int default_moni_port