Belle II Software  release-05-01-25
RCCallback.cc
1 #include "daq/slc/runcontrol/RCCallback.h"
2 
3 #include <daq/slc/database/DBHandlerException.h>
4 #include <daq/slc/database/DBInterface.h>
5 #include <daq/slc/database/DBObjectLoader.h>
6 
7 #include <daq/slc/runcontrol/RCCommand.h>
8 #include <daq/slc/runcontrol/RCHandlerException.h>
9 #include <daq/slc/runcontrol/RCHandlerFatalException.h>
10 
11 #include <daq/slc/system/LogFile.h>
12 #include <daq/slc/system/TCPSocket.h>
13 #include <daq/slc/system/TCPSocketReader.h>
14 #include <daq/slc/system/TCPSocketWriter.h>
15 
16 #include <daq/slc/nsm/NSMCommunicator.h>
17 
18 #include <sstream>
19 
20 #include <cstdlib>
21 
22 double tabort = 0;
23 
24 namespace Belle2 {
30  public:
31  RCConfigHandler(RCCallback& callback,
32  const std::string& name, const std::string& val)
33  : NSMVHandlerText(name, true, true, val), m_callback(callback) {}
34  bool handleGetText(std::string& val)
35  {
36  const DBObject& obj(m_callback.getDBObject());
37  val = obj.getName();
38  return true;
39  }
40  bool handleSetText(const std::string& val)
41  {
42  RCState state(m_callback.getNode().getState());
43  RCState tstate(RCCommand::CONFIGURE.nextTState());
44  m_callback.setState(tstate);
45  try {
46  m_callback.abort();
47  m_callback.dbload(val.size(), val.c_str());
48  } catch (const IOException& e) {
49  throw (RCHandlerException(e.what()));
50  }
51  DBObject& obj(m_callback.getDBObject());
52  obj.getName();
53  m_callback.configure(obj);
54  m_callback.setState(state);
55  return true;
56  }
57  private:
58  RCCallback& m_callback;
59  };
60 
62 }
63 
64 using namespace Belle2;
65 
66 RCCallback::RCCallback(int timeout)
67  : NSMCallback(timeout)
68 {
69  reg(RCCommand::CONFIGURE);
70  reg(RCCommand::BOOT);
71  reg(RCCommand::LOAD);
72  reg(RCCommand::START);
73  reg(RCCommand::STOP);
74  reg(RCCommand::RECOVER);
75  reg(RCCommand::RESUME);
76  reg(RCCommand::PAUSE);
77  reg(RCCommand::ABORT);
78  reg(RCCommand::STATUS);
79  reg(NSMCommand::FATAL);
80  m_auto = true;
81  m_db = NULL;
82  m_showall = true;
83  m_expno = m_runno = 0;
84 }
85 
86 void RCCallback::init(NSMCommunicator&)
87 {
88  LogFile::debug("init");
89  dbload(0, 0);
90  try {
91  initialize(m_obj);
92  } catch (const RCHandlerException& e) {
93  LogFile::fatal("Failed to initialize. %s. terminating process (84)", e.what());
94  term();
95  exit(1);
96  }
97  LogFile::debug("init done");
98  setState(RCState::NOTREADY_S);
99  tabort = Date().get();
100 }
101 
102 bool RCCallback::perform(NSMCommunicator& com)
103 {
104  NSMMessage msg(com.getMessage());
105  const RCCommand cmd = msg.getRequestName();
106  const RCState state_org(getNode().getState());
107  RCState state(getNode().getState());
108  if (NSMCallback::perform(com)) return true;
109  if (cmd.isAvailable(state) == NSMCommand::DISABLED) {
110  return false;
111  }
112  addNode(NSMNode(msg.getNodeName()));
113  try {
114  set("rcrequest", msg.getRequestName());
115  } catch (const std::exception& e) {
116  LogFile::error(e.what());
117  }
118  RCState tstate(cmd.nextTState());
119  try {
120  if (tstate != Enum::UNKNOWN) {
121  log(LogFile::DEBUG, "RC request %s from %s", msg.getRequestName(), msg.getNodeName());
122  setState(tstate);
123  std::string nodename = getNode().getName();
124  bool ismaster = nodename == "RUNCONTROL" ||
125  (StringUtil::find(nodename, "RC_") && !StringUtil::find(nodename, "HLT"));
126  if (cmd == RCCommand::CONFIGURE) {
127  m_runcontrol.setName(msg.getNodeName());
128  configure_raw(msg.getLength(), msg.getData());
129  } else if (cmd == RCCommand::BOOT) {
130  m_runcontrol.setName(msg.getNodeName());
131  get(m_obj);
132  std::string opt = msg.getLength() > 0 ? msg.getData() : "";
133  boot(opt, m_obj);
134  } else if (cmd == RCCommand::LOAD) {
135  m_expno = 0;
136  m_runno = 0;
137  m_runcontrol.setName(msg.getNodeName());
138  std::string runtype = (msg.getLength() > 0 ? msg.getData() : "");
139  if (runtype.size() == 0) {
140  get("runtype", runtype);
141  } else if (runtype.size() > 0) {
142  set("runtype", runtype);
143  }
144  get(m_obj);
145  load(m_obj, runtype);
146  } else if (cmd == RCCommand::START) {
147  m_runcontrol.setName(msg.getNodeName());
148  m_expno = (msg.getNParams() > 0) ? msg.getParam(0) : 0;
149  m_runno = (msg.getNParams() > 1) ? msg.getParam(1) : 0;
150  if (ismaster) {
151  log(LogFile::NOTICE, "Run start by %s (exp=%05d, run=%06d)",
152  msg.getNodeName(), m_runno, m_expno);
153  }
154  start(m_expno, m_runno);
155  } else if (cmd == RCCommand::STOP) {
156  if (ismaster) {
157  log(LogFile::NOTICE, "Run stop by %s (exp=%05d, run=%06d)",
158  msg.getNodeName(), m_runno, m_expno);
159  }
160  stop();
161  } else if (cmd == RCCommand::RESUME) {
162  if (ismaster) {
163  log(LogFile::NOTICE, "Run resume by %s (exp=%05d, run=%06d)",
164  msg.getNodeName(), m_runno, m_expno);
165  }
166  if (!resume(msg.getParam(0))) {
167  setState(RCState::NOTREADY_S);
168  return true;
169  }
170  } else if (cmd == RCCommand::PAUSE) {
171  if (ismaster) {
172  log(LogFile::NOTICE, "Run pause by %s (exp=%05d, run=%06d)",
173  msg.getNodeName(), m_runno, m_expno);
174  }
175  if (!pause()) {
176  setState(RCState::NOTREADY_S);
177  return true;
178  }
179  }
180  try {
181  if (cmd == RCCommand::ABORT) {
182  double t = Date().get();
183  if (t - tabort > 3) {
184  if (ismaster) {
185  log(LogFile::NOTICE, "Run abort by %s (exp=%05d, run=%06d)",
186  msg.getNodeName(), m_runno, m_expno);
187  }
188  m_runcontrol.setName(msg.getNodeName());
189  abort();
190  }
191  tabort = t;
192  } else if (cmd == RCCommand::RECOVER) {
193  std::string runtype;
194  get("runtype", runtype);
195  recover(m_obj, runtype);
196  }
197  } catch (const RCHandlerException& e) {
198  log(LogFile::FATAL, "Failed to recover/abort : %s", e.what());
199  }
200  }
201  RCState state = cmd.nextState();
202  if (getNode().getState() == tstate &&
203  state != Enum::UNKNOWN && m_auto) {
204  setState(state);
205  }
206  state = getNode().getState();
207  if (state != Enum::UNKNOWN) {
208  if ((cmd == RCCommand::START &&
209  (state == RCState::RUNNING_S || state == RCState::STARTING_TS)) ||
210  ((cmd == RCCommand::STOP || cmd == RCCommand::ABORT)
211  && state_org == RCState::RUNNING_S)) {
212  try {
213  dump(cmd == RCCommand::START);
214  } catch (const DBHandlerException& e) {
215  LogFile::error(e.what());
216  }
217  }
218  }
219  } catch (const RCHandlerFatalException& e) {
220  log(LogFile::FATAL, e.what());
221  } catch (const RCHandlerException& e) {
222  log(LogFile::ERROR, e.what());
223  setState(RCState::ERROR_ES);
224  } catch (const std::exception& e) {
225  log(LogFile::FATAL, "Unknown exception: %s. terminating process (193)", e.what());
226  }
227  return true;
228 }
229 
230 void RCCallback::dump(bool isstart)
231 {
232  std::string runtype;
233  get("runtype", runtype);
234  std::string rcconfig = getNode().getName() + "@RC:"
235  + (isstart ? "start:" : "end:") + runtype
236  + StringUtil::form(":%05d:%04d", m_expno, m_runno);
237  std::stringstream ss;
238  ss << dbdump() << std::endl;
239  ss << "config : " << rcconfig << std::endl;
240  LogFile::debug(ss.str());
241  ConfigFile file(ss);
242  DBObject obj = DBObjectLoader::load(file);
243  obj.print();
244  std::string table = m_table + "record";
245  if (getDB()) {
246  DBInterface& db(*getDB());
247  try {
248  DBObjectLoader::createDB(db, table, obj);
249  } catch (const IOException& e) {
250  throw (DBHandlerException("Failed to connect to database error : %s ", e.what()));
251  }
252  } else if (m_provider_host.size() > 0 && m_provider_port > 0) {
253  TCPSocket socket(m_provider_host, m_provider_port);
254  try {
255  socket.connect();
256  TCPSocketWriter writer(socket);
257  writer.writeInt(2);
258  writer.writeString(table);
259  writer.writeObject(obj);
260  } catch (const IOException& e) {
261  socket.close();
262  throw (DBHandlerException("Failed to connect to dbprovider error : %s ", e.what()));
263  }
264  socket.close();
265  }
266 }
267 
268 void RCCallback::timeout(NSMCommunicator& /*com*/)
269 {
270  try {
271  monitor();
272  } catch (const RCHandlerFatalException& e) {
273  LogFile::fatal(e.what());
274  setState(RCState::ERROR_ES);
275  reply(NSMMessage(NSMCommand::FATAL, e.what()));
276  } catch (const RCHandlerException& e) {
277  LogFile::error(e.what());
278  setState(RCState::ERROR_ES);
279  reply(NSMMessage(NSMCommand::ERROR, e.what()));
280  } catch (const std::exception& e) {
281  LogFile::fatal("Unknown exception: %s. terminating process (249)", e.what());
282  }
283 }
284 
285 std::string RCCallback::dbdump()
286 {
287  std::stringstream ss;
288  StringList& hnames(getHandlerNames());
289  NSMVHandlerList& handlers(getHandlers());
290  for (StringList::iterator it = hnames.begin();
291  it != hnames.end(); it++) {
292  std::string hname = *it;
293  NSMVHandler& handler(*handlers[hname]);
294  std::string vname = StringUtil::replace(hname, "@", "");
295  if (!handler.useGet()) {
296  continue;
297  }
298  if (!handler.isDumped()) {
299  continue;
300  }
301  if (vname.c_str()[0] == '.') {
302  continue;
303  }
304  NSMVar var;
305  handler.handleGet(var);
306  switch (var.getType()) {
307  case NSMVar::INT:
308  ss << vname << " : int(" << var.getInt() << ")" << std::endl;
309  break;
310  case NSMVar::FLOAT:
311  ss << vname << " : float(" << var.getFloat() << ")" << std::endl;
312  break;
313  case NSMVar::TEXT:
314  ss << vname << " : \"" << var.getText() << "\"" << std::endl;
315  break;
316  default:
317  break;
318  }
319  }
320  ss << getDBObject().sprint(true) << std::endl;
321  ss << "nodename : " << std::endl;
322  return ss.str();
323 }
324 
325 void RCCallback::setState(const RCState& state)
326 {
327  RCState state_org = getNode().getState();
328  if (state_org != state) {
329  LogFile::debug("state transit : %s >> %s",
330  state_org.getLabel(), state.getLabel());
331  try {
332  getNode().setState(state);
333  set("rcstate", state.getLabel());
334  } catch (const std::exception& e) {
335  LogFile::error(e.what());
336  }
337  }
338 }
339 
340 DBObject RCCallback::dbload(const std::string& path)
341 {
342  DBObject obj;
343  std::string pathin, table, config;
344  LogFile::debug(path);
345  if (path.find("db://") != std::string::npos) {
346  pathin = StringUtil::replace(path, "db://", "");
347  StringList s = StringUtil::split(pathin, '/');
348  if (s.size() > 1) {
349  table = s[0];
350  config = s[1];
351  } else {
352  table = m_table;
353  config = s[0];
354  }
355  } else if (path.find("file://") != std::string::npos) {
356  pathin = StringUtil::replace(path, "file:/", "");
357  return obj;
358  }
359  if (table.size() > 0 && config.size() > 0) {
360  if (getDB()) {
361  DBInterface& db(*getDB());
362  try {
363  obj = DBObjectLoader::load(db, table, config, false);
364  if (obj.getName().size() > 0) {
365  config = obj.getName();
366  }
367  db.close();
368  } catch (const DBHandlerException& e) {
369  db.close();
370  throw (e);
371  }
372  } else if (m_provider_host.size() > 0 && m_provider_port > 0) {
373  TCPSocket socket(m_provider_host, m_provider_port);
374  try {
375  socket.connect();
376  TCPSocketWriter writer(socket);
377  writer.writeInt(1);
378  writer.writeString(table + "/" + config);
379  TCPSocketReader reader(socket);
380  obj.readObject(reader);
381  socket.close();
382  if (obj.getName().size() > 0) {
383  config = obj.getName();
384  }
385  } catch (const IOException& e) {
386  socket.close();
387  throw (IOException("Socket connection error : %s ", e.what()));
388  }
389  }
390  }
391  return obj;
392 }
393 
394 void RCCallback::configure_raw(int length, const char* data)
395 {
396  try {
397  dbload(length, data);
398  } catch (const IOException& e) {
399  throw (RCHandlerException(e.what()));
400  }
401  configure(m_obj);
402 }
403 
404 void RCCallback::dbload(int /*length*/, const char* /*data*/)
405 {
406  NSMNode& node(getNode());
407  m_rcconfig = node.getName() + "@RC:" + m_rcconfig_org;
408  LogFile::debug("Loading '%s'", m_rcconfig.c_str());
409  if (m_file.size() > 0) {
410  StringList files = StringUtil::split(m_file, ',');
411  ConfigFile conf;
412  for (size_t i = 0; i < files.size(); i++) {
413  conf.read(files[i]);
414  }
415  m_obj = DBObjectLoader::load(conf);
416  m_obj.print(m_showall);
417  } else if (getDB()) {
418  DBInterface& db(*getDB());
419  std::string rcconfig = "";
420  DBObject obj1, obj2;
421  if (m_runtype_record.size()) {
422  rcconfig = node.getName() + "@RC:start:" + m_runtype_record + ":";
423  obj1 = DBObjectLoader::load(db, m_table + "record", rcconfig, m_showall);
424  }
425  obj2 = DBObjectLoader::load(db, m_table, m_rcconfig, m_showall);
426  if (obj1.getDate() < obj2.getDate()) {
427  m_obj = obj2;
428  } else {
429  m_obj = obj1;
430  m_rcconfig = rcconfig;
431  }
432  db.close();
433  m_obj.print(m_showall);
434  } else if (m_provider_host.size() > 0 && m_provider_port > 0) {
435  TCPSocket socket(m_provider_host, m_provider_port);
436  try {
437  DBObject obj1, obj2;
438  std::string rcconfig = "";
439  if (m_runtype_record.size() > 0) {
440  rcconfig = node.getName() + "@RC:start:" + m_runtype_record + ":";
441  socket.connect();
442  TCPSocketWriter writer(socket);
443  writer.writeInt(1);
444  writer.writeString(m_table + "record/" + rcconfig);
445  TCPSocketReader reader(socket);
446  obj1.readObject(reader);
447  socket.close();
448  }
449  socket.connect();
450  TCPSocketWriter writer(socket);
451  writer.writeInt(1);
452  writer.writeString(m_table + "/" + m_rcconfig);
453  TCPSocketReader reader(socket);
454  obj2.readObject(reader);
455  if (obj1.getDate() < obj2.getDate()) {
456  m_obj = obj2;
457  } else {
458  m_obj = obj1;
459  m_rcconfig = rcconfig;
460  }
461  m_obj.print(m_showall);
462  } catch (const IOException& e) {
463  socket.close();
464  throw (IOException("Socket connection error : %s ", e.what()));
465  }
466  socket.close();
467  }
468  reset();
469  add(new NSMVHandlerText("runtype", true, true, ""), false, true);
470  add(new NSMVHandlerText("dbtable", true, false, m_table), false, true);
471  add(new NSMVHandlerText("rcstate", true, false, RCState::NOTREADY_S.getLabel()), false, true);
472  add(new NSMVHandlerText("rcrequest", true, false, ""), false, true);
473  add(new RCConfigHandler(*this, "rcconfig", m_obj.getName()));
474  addDB(m_obj);
475 }
476 
Belle2::NSMVHandler
Definition: NSMVHandler.h:15
Belle2::DBHandlerException
Definition: DBHandlerException.h:12
Belle2::RCHandlerFatalException
Definition: RCHandlerFatalException.h:12
Belle2::FileWriter
Definition: FileWriter.h:13
Belle2::RCConfigHandler
Definition: RCCallback.cc:29
prepareAsicCrosstalkSimDB.e
e
aux.
Definition: prepareAsicCrosstalkSimDB.py:53
Belle2::RCHandlerException
Definition: RCHandlerException.h:12
Belle2::NSMNode
Definition: NSMNode.h:14
Belle2::DBObject
Definition: DBObject.h:14
Belle2::RCCallback
Definition: RCCallback.h:18
Belle2::IOException
Definition: IOException.h:12
Belle2::NSMCommunicator
Definition: NSMCommunicator.h:25
Belle2::NSMMessage
Definition: NSMMessage.h:29
Belle2::RCCommand
Definition: RCCommand.h:14
alignment.constraints.files
def files
Files.
Definition: constraints.py:559
Belle2::NSMCallback
Definition: NSMCallback.h:24
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::TCPSocket
Definition: TCPSocket.h:14
Belle2::Date
Definition: Date.h:12
Belle2::DBInterface
Definition: DBInterface.h:19
Belle2::ConfigFile
Definition: ConfigFile.h:15
Belle2::NSMVHandlerText
Definition: NSMVHandler.h:151
Belle2::NSMVar
Definition: NSMVar.h:16
Belle2::RCState
Definition: RCState.h:12
Belle2::FileReader
Definition: FileReader.h:13