8#include "daq/slc/runcontrol/RCCallback.h"
10#include <daq/slc/database/DBHandlerException.h>
11#include <daq/slc/database/DBInterface.h>
12#include <daq/slc/database/DBObjectLoader.h>
14#include <daq/slc/runcontrol/RCCommand.h>
15#include <daq/slc/runcontrol/RCHandlerException.h>
16#include <daq/slc/runcontrol/RCHandlerFatalException.h>
18#include <daq/slc/system/LogFile.h>
19#include <daq/slc/system/TCPSocket.h>
20#include <daq/slc/system/TCPSocketReader.h>
21#include <daq/slc/system/TCPSocketWriter.h>
23#include <daq/slc/nsm/NSMCommunicator.h>
39 const std::string& name,
const std::string& val)
41 bool handleGetText(std::string& val)
override
43 const DBObject& obj(m_callback.getDBObject());
47 bool handleSetText(
const std::string& val)
override
49 RCState state(m_callback.getNode().getState());
50 RCState tstate(RCCommand::CONFIGURE.nextTState());
51 m_callback.setState(tstate);
54 m_callback.dbload(val.size(), val.c_str());
58 const DBObject& obj(m_callback.getDBObject());
60 m_callback.configure(obj);
61 m_callback.setState(state);
73RCCallback::RCCallback(
int timeout)
76 reg(RCCommand::CONFIGURE);
79 reg(RCCommand::START);
81 reg(RCCommand::RECOVER);
82 reg(RCCommand::RESUME);
83 reg(RCCommand::PAUSE);
84 reg(RCCommand::ABORT);
85 reg(RCCommand::STATUS);
86 reg(NSMCommand::FATAL);
90 m_expno = m_runno = 0;
95 LogFile::debug(
"init");
100 LogFile::fatal(
"Failed to initialize. %s. terminating process (84)", e.what());
104 LogFile::debug(
"init done");
105 setState(RCState::NOTREADY_S);
106 tabort =
Date().get();
112 const RCCommand cmd = msg.getRequestName();
113 const RCState state_org(getNode().getState());
114 RCState state(getNode().getState());
115 if (NSMCallback::perform(com))
return true;
116 if (cmd.isAvailable(state) == NSMCommand::DISABLED) {
119 addNode(
NSMNode(msg.getNodeName()));
121 set(
"rcrequest", msg.getRequestName());
122 }
catch (
const std::exception& e) {
123 LogFile::error(e.what());
125 RCState tstate(cmd.nextTState());
127 if (tstate != Enum::UNKNOWN) {
128 log(LogFile::DEBUG,
"RC request %s from %s", msg.getRequestName(), msg.getNodeName());
130 std::string nodename = getNode().getName();
131 bool ismaster = nodename ==
"RUNCONTROL" ||
132 (StringUtil::find(nodename,
"RC_") && !StringUtil::find(nodename,
"HLT"));
133 if (cmd == RCCommand::CONFIGURE) {
134 m_runcontrol.setName(msg.getNodeName());
135 configure_raw(msg.getLength(), msg.getData());
136 }
else if (cmd == RCCommand::BOOT) {
137 m_runcontrol.setName(msg.getNodeName());
139 std::string opt = msg.getLength() > 0 ? msg.getData() :
"";
141 }
else if (cmd == RCCommand::LOAD) {
144 m_runcontrol.setName(msg.getNodeName());
145 std::string runtype = (msg.getLength() > 0 ? msg.getData() :
"");
146 if (runtype.size() == 0) {
147 get(
"runtype", runtype);
149 set(
"runtype", runtype);
152 load(m_obj, runtype);
153 }
else if (cmd == RCCommand::START) {
154 m_runcontrol.setName(msg.getNodeName());
155 m_expno = (msg.getNParams() > 0) ? msg.getParam(0) : 0;
156 m_runno = (msg.getNParams() > 1) ? msg.getParam(1) : 0;
158 log(LogFile::NOTICE,
"Run start by %s (exp=%05d, run=%06d)",
159 msg.getNodeName(), m_runno, m_expno);
161 start(m_expno, m_runno);
162 }
else if (cmd == RCCommand::STOP) {
164 log(LogFile::NOTICE,
"Run stop by %s (exp=%05d, run=%06d)",
165 msg.getNodeName(), m_runno, m_expno);
168 }
else if (cmd == RCCommand::RESUME) {
170 log(LogFile::NOTICE,
"Run resume by %s (exp=%05d, run=%06d)",
171 msg.getNodeName(), m_runno, m_expno);
173 if (!resume(msg.getParam(0))) {
174 setState(RCState::NOTREADY_S);
177 }
else if (cmd == RCCommand::PAUSE) {
179 log(LogFile::NOTICE,
"Run pause by %s (exp=%05d, run=%06d)",
180 msg.getNodeName(), m_runno, m_expno);
183 setState(RCState::NOTREADY_S);
188 if (cmd == RCCommand::ABORT) {
189 double t =
Date().get();
190 if (t - tabort > 3) {
192 log(LogFile::NOTICE,
"Run abort by %s (exp=%05d, run=%06d)",
193 msg.getNodeName(), m_runno, m_expno);
195 m_runcontrol.setName(msg.getNodeName());
199 }
else if (cmd == RCCommand::RECOVER) {
201 get(
"runtype", runtype);
202 recover(m_obj, runtype);
205 log(LogFile::FATAL,
"Failed to recover/abort : %s", e.what());
208 RCState State = cmd.nextState();
209 if (getNode().getState() == tstate &&
210 State != Enum::UNKNOWN && m_auto) {
213 State = getNode().getState();
214 if (State != Enum::UNKNOWN) {
215 if ((cmd == RCCommand::START &&
216 (State == RCState::RUNNING_S || State == RCState::STARTING_TS)) ||
217 ((cmd == RCCommand::STOP || cmd == RCCommand::ABORT)
218 && state_org == RCState::RUNNING_S)) {
220 dump(cmd == RCCommand::START);
222 LogFile::error(e.what());
227 log(LogFile::FATAL, e.what());
229 log(LogFile::ERROR, e.what());
230 setState(RCState::ERROR_ES);
231 }
catch (
const std::exception& e) {
232 log(LogFile::FATAL,
"Unknown exception: %s. terminating process (193)", e.what());
237void RCCallback::dump(
bool isstart)
240 get(
"runtype", runtype);
241 std::string rcconfig = getNode().getName() +
"@RC:"
242 + (isstart ?
"start:" :
"end:") + runtype
243 + StringUtil::form(
":%05d:%04d", m_expno, m_runno);
244 std::stringstream ss;
245 ss << dbdump() << std::endl;
246 ss <<
"config : " << rcconfig << std::endl;
247 LogFile::debug(ss.str());
249 DBObject obj = DBObjectLoader::load(file);
251 std::string table = m_table +
"record";
255 DBObjectLoader::createDB(db, table, obj);
259 }
else if (m_provider_host.size() > 0 && m_provider_port > 0) {
260 TCPSocket socket(m_provider_host, m_provider_port);
265 writer.writeString(table);
266 writer.writeObject(obj);
280 LogFile::fatal(e.what());
281 setState(RCState::ERROR_ES);
282 reply(
NSMMessage(NSMCommand::FATAL, e.what()));
284 LogFile::error(e.what());
285 setState(RCState::ERROR_ES);
286 reply(
NSMMessage(NSMCommand::ERROR, e.what()));
287 }
catch (
const std::exception& e) {
288 LogFile::fatal(
"Unknown exception: %s. terminating process (249)", e.what());
292std::string RCCallback::dbdump()
294 std::stringstream ss;
295 StringList& hnames(getHandlerNames());
296 const NSMVHandlerList& handlers(getHandlers());
297 for (StringList::iterator it = hnames.begin();
298 it != hnames.end(); ++it) {
299 std::string hname = *it;
301 std::string vname = StringUtil::replace(hname,
"@",
"");
302 if (!handler.useGet()) {
305 if (!handler.isDumped()) {
308 if (vname.c_str()[0] ==
'.') {
312 handler.handleGet(var);
313 switch (var.getType()) {
315 ss << vname <<
" : int(" << var.getInt() <<
")" << std::endl;
318 ss << vname <<
" : float(" << var.getFloat() <<
")" << std::endl;
321 ss << vname <<
" : \"" << var.getText() <<
"\"" << std::endl;
327 ss << getDBObject().sprint(
true) << std::endl;
328 ss <<
"nodename : " << std::endl;
332void RCCallback::setState(
const RCState& state)
334 RCState state_org = getNode().getState();
335 if (state_org != state) {
336 LogFile::debug(
"state transit : %s >> %s",
337 state_org.getLabel(), state.getLabel());
339 getNode().setState(state);
340 set(
"rcstate", state.getLabel());
341 }
catch (
const std::exception& e) {
342 LogFile::error(e.what());
347DBObject RCCallback::dbload(
const std::string& path)
350 std::string pathin, table, config;
351 LogFile::debug(path);
352 if (path.find(
"db://") != std::string::npos) {
353 pathin = StringUtil::replace(path,
"db://",
"");
354 StringList s = StringUtil::split(pathin,
'/');
362 }
else if (path.find(
"file://") != std::string::npos) {
363 pathin = StringUtil::replace(path,
"file:/",
"");
366 if (table.size() > 0 && config.size() > 0) {
370 obj = DBObjectLoader::load(db, table, config,
false);
371 if (obj.getName().size() > 0) {
372 config = obj.getName();
379 }
else if (m_provider_host.size() > 0 && m_provider_port > 0) {
380 TCPSocket socket(m_provider_host, m_provider_port);
385 writer.writeString(table +
"/" + config);
387 obj.readObject(reader);
389 if (obj.getName().size() > 0) {
390 config = obj.getName();
394 throw (
IOException(
"Socket connection error : %s ", e.what()));
401void RCCallback::configure_raw(
int length,
const char* data)
404 dbload(length, data);
411void RCCallback::dbload(
int ,
const char* )
413 const NSMNode& node(getNode());
414 m_rcconfig = node.getName() +
"@RC:" + m_rcconfig_org;
415 LogFile::debug(
"Loading '%s'", m_rcconfig.c_str());
416 if (m_file.size() > 0) {
417 StringList files = StringUtil::split(m_file,
',');
419 for (
size_t i = 0; i < files.size(); i++) {
422 m_obj = DBObjectLoader::load(conf);
423 m_obj.print(m_showall);
424 }
else if (getDB()) {
426 std::string rcconfig =
"";
428 if (m_runtype_record.size()) {
429 rcconfig = node.getName() +
"@RC:start:" + m_runtype_record +
":";
430 obj1 = DBObjectLoader::load(db, m_table +
"record", rcconfig, m_showall);
432 obj2 = DBObjectLoader::load(db, m_table, m_rcconfig, m_showall);
433 if (obj1.getDate() < obj2.getDate()) {
437 m_rcconfig = rcconfig;
440 m_obj.print(m_showall);
441 }
else if (m_provider_host.size() > 0 && m_provider_port > 0) {
442 TCPSocket socket(m_provider_host, m_provider_port);
445 std::string rcconfig =
"";
446 if (m_runtype_record.size() > 0) {
447 rcconfig = node.getName() +
"@RC:start:" + m_runtype_record +
":";
451 writer.writeString(m_table +
"record/" + rcconfig);
453 obj1.readObject(reader);
459 writer.writeString(m_table +
"/" + m_rcconfig);
461 obj2.readObject(reader);
462 if (obj1.getDate() < obj2.getDate()) {
466 m_rcconfig = rcconfig;
468 m_obj.print(m_showall);
471 throw (
IOException(
"Socket connection error : %s ", e.what()));
477 add(
new NSMVHandlerText(
"dbtable",
true,
false, m_table),
false,
true);
478 add(
new NSMVHandlerText(
"rcstate",
true,
false, RCState::NOTREADY_S.getLabel()),
false,
true);
Abstract base class for different kinds of events.