Line data Source code
1 : /**
2 : * @file stdinCommandFacility.cpp CommandFacility implementation
3 : * that reads commands from std::cin
4 : *
5 : * This is part of the DUNE DAQ Application Framework, copyright 2020.
6 : * Licensing/copyright details are in the COPYING file that you should have
7 : * received with this code.
8 : */
9 : #include "cmdlib/CommandFacility.hpp"
10 : #include "cmdlib/Issues.hpp"
11 : #include "cmdlib/cmd/Nljs.hpp"
12 :
13 : #include "logging/Logging.hpp" // NOTE: if ISSUES ARE DECLARED BEFORE include logging/Logging.hpp, TLOG_DEBUG<<issue wont work.
14 : #include <nlohmann/json.hpp>
15 : #include <cetlib/BasicPluginFactory.h>
16 :
17 : #include <thread>
18 : #include <chrono>
19 : #include <map>
20 : #include <memory>
21 : #include <string>
22 : #include <fstream>
23 :
24 : namespace dunedaq {
25 :
26 : // Throw if a file can not be opened. Provide "mode" of "reading"
27 : // or "writing" and provide erroneous filename as args.
28 1 : ERS_DECLARE_ISSUE(cmdlib, BadFile,
29 : "Can not open file for " << mode << ": " << filename,
30 : ((std::string)filename)
31 : ((std::string)mode))
32 :
33 : } // namespace dunedaq
34 :
35 : using namespace dunedaq::cmdlib;
36 : using namespace std::chrono_literals;
37 : using json = nlohmann::json;
38 :
39 :
40 :
41 : class stdinCommandFacility : public CommandFacility
42 : {
43 : public:
44 10 : explicit stdinCommandFacility(std::string uri) : CommandFacility(uri) {
45 : // Allocate resources as needed
46 10 : auto col = uri.find_last_of(':');
47 10 : auto sep = uri.find("://");
48 10 : std::string fname;
49 10 : if (col == std::string::npos || sep == std::string::npos) { // assume filename
50 0 : fname = uri;
51 : } else {
52 10 : fname = uri.substr(sep+3);
53 : }
54 :
55 20 : TLOG() <<"Loading commands from file: " << fname;
56 :
57 10 : std::ifstream ifs;
58 10 : ifs.open(fname, std::fstream::in);
59 10 : if (!ifs.is_open()) {
60 0 : throw BadFile(ERS_HERE, fname, "reading");
61 : }
62 :
63 10 : try {
64 10 : m_raw_commands = json::parse(ifs);
65 0 : } catch (const std::exception& ex) {
66 0 : throw CannotParseCommand(ERS_HERE, ex.what());
67 0 : }
68 10 : std::ostringstream avaostr;
69 10 : avaostr << "Available commands:";
70 40 : for (auto it = m_raw_commands.begin(); it != m_raw_commands.end(); ++it) {
71 30 : std::string idstr(it.value()["id"]);
72 30 : m_available_commands[idstr] = it.value();
73 30 : avaostr << " | " << idstr;
74 30 : }
75 10 : m_available_str = avaostr.str();
76 10 : }
77 :
78 : // Implementation of the runner
79 1 : void run(std::atomic<bool>& end_marker) {
80 1 : TLOG_DEBUG(1) << "Entered commands will be launched on CommandedObject...";
81 1 : std::string cmdid;
82 2 : while (end_marker) { //until runmarker
83 0 : TLOG() << m_available_str;
84 : // feed commands from cin
85 0 : std::cin >> cmdid;
86 0 : if (std::cin.eof()) {
87 : break;
88 : }
89 0 : if ( m_available_commands.find(cmdid) == m_available_commands.end() ) {
90 0 : std::ostringstream s;
91 0 : s << "Command " << cmdid << " is not available...";
92 0 : ers::error (CannotParseCommand(ERS_HERE, s.str()));
93 0 : } else {
94 0 : TLOG() << "Executing " << cmdid << " command...";
95 0 : inherited::execute_command(m_available_commands[cmdid], cmd::CommandReply());
96 : }
97 : }
98 1 : TLOG_DEBUG(1) << "Command handling stopped.";
99 1 : }
100 :
101 : protected:
102 : typedef CommandFacility inherited;
103 :
104 : json m_raw_commands;
105 : std::map<std::string, json> m_available_commands;
106 : std::string m_available_str;
107 :
108 : // Implementation of completion_handler interface
109 0 : void completion_callback(const cmdobj_t& cmd, cmd::CommandReply& meta) {
110 0 : cmd::Command command = cmd.get<cmd::Command>();
111 0 : TLOG() << "Application " << meta.appname << " executed command " << command.id << " with result: " << meta.success << " " << meta.result;
112 0 : }
113 :
114 : };
115 :
116 : extern "C" {
117 10 : std::shared_ptr<dunedaq::cmdlib::CommandFacility> make(std::string uri) {
118 10 : return std::shared_ptr<dunedaq::cmdlib::CommandFacility>(new stdinCommandFacility(uri));
119 : }
120 : }
|