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 <cetlib/BasicPluginFactory.h>
15 : #include <nlohmann/json.hpp>
16 :
17 : #include <chrono>
18 : #include <fstream>
19 : #include <map>
20 : #include <memory>
21 : #include <string>
22 : #include <thread>
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,
29 : BadFile,
30 : "Can not open file for " << mode << ": " << filename,
31 : ((std::string)filename)((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 : class stdinCommandFacility : public CommandFacility
40 : {
41 : public:
42 10 : explicit stdinCommandFacility(std::string uri)
43 10 : : CommandFacility(uri)
44 : {
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 : {
81 1 : TLOG_DEBUG(1) << "Entered commands will be launched on CommandedObject...";
82 1 : std::string cmdid;
83 2 : while (end_marker) { // until runmarker
84 0 : TLOG() << m_available_str;
85 : // feed commands from cin
86 0 : std::cin >> cmdid;
87 0 : if (std::cin.eof()) {
88 : break;
89 : }
90 0 : if (m_available_commands.find(cmdid) == m_available_commands.end()) {
91 0 : std::ostringstream s;
92 0 : s << "Command " << cmdid << " is not available...";
93 0 : ers::error(CannotParseCommand(ERS_HERE, s.str()));
94 0 : } else {
95 0 : TLOG() << "Executing " << cmdid << " command...";
96 0 : inherited::execute_command(m_available_commands[cmdid], cmd::CommandReply());
97 : }
98 : }
99 1 : TLOG_DEBUG(1) << "Command handling stopped.";
100 1 : }
101 :
102 : protected:
103 : typedef CommandFacility inherited;
104 :
105 : json m_raw_commands;
106 : std::map<std::string, json> m_available_commands;
107 : std::string m_available_str;
108 :
109 : // Implementation of completion_handler interface
110 0 : void completion_callback(const cmdobj_t& cmd, cmd::CommandReply& meta)
111 : {
112 0 : cmd::Command command = cmd.get<cmd::Command>();
113 0 : TLOG() << "Application " << meta.appname << " executed command " << command.id << " with result: " << meta.success
114 0 : << " " << meta.result;
115 0 : }
116 : };
117 :
118 : extern "C"
119 : {
120 10 : std::shared_ptr<dunedaq::cmdlib::CommandFacility> make(std::string uri)
121 : {
122 10 : return std::shared_ptr<dunedaq::cmdlib::CommandFacility>(new stdinCommandFacility(uri));
123 : }
124 : }
|