Jpp  debug
the software that should make you happy
JDAQClient.hh
Go to the documentation of this file.
1 #ifndef __JRUNCONTROL__JDAQCLIENT__
2 #define __JRUNCONTROL__JDAQCLIENT__
3 
4 #include <string>
5 #include <iostream>
6 #include <sstream>
7 #include <iomanip>
8 #include <exception>
9 #include <typeinfo>
10 #include <ctype.h>
11 
12 #include "JSystem/JNetwork.hh"
13 #include "JNet/JControlHost.hh"
15 #include "JNet/JSelectReader.hh"
16 #include "JLang/Jpp.hh"
17 #include "JLang/JSharedPointer.hh"
19 #include "JLang/JTimeval.hh"
20 #include "JLang/JRedirectStream.hh"
21 #include "JLang/JNullStream.hh"
22 #include "Jeep/JParser.hh"
23 #include "Jeep/JProperties.hh"
24 #include "Jeep/JArgs.hh"
25 #include "Jeep/JTimekeeper.hh"
27 #include "JLogger/JStreamLogger.hh"
30 #include "JDAQ/JDAQTags.hh"
32 #include "JRuncontrol/JEvent_t.hh"
34 #include "JRuncontrol/JDAQCHSM.hh"
35 
36 
37 /**
38  * \author mdejong
39  */
40 
41 namespace KM3NETDAQ {
42 
43  using namespace JLOGGER;
44  using JNET::JTag;
45  using JNET::JControlHost;
47  using JNET::JSubscription;
49  using JNET::JSelectReader;
52  using JLANG::JTimeval;
54  using JEEP::JArgs;
55  using JEEP::JTimekeeper;
56 
57 
58  /**
59  * Auxiliary data structure for DAQ client data.
60  */
61  struct JDAQClient_t {
62 
63  static const int TIMEOUT_S = 1; //!< time out of update [s]
64 
65 
66  /**
67  * Constructor.
68  *
69  * \param chsm state machine
70  */
72  {
73  using namespace std;
74  using namespace JPP;
75 
76  hostname = getHostname();
77  fullname = KM3NETDAQ::getFullName (hostname, chsm->getName());
78  unique_tag = KM3NETDAQ::getUniqueTag(hostname, chsm->getName());
79 
80  for (JTag buffer[] = { RC_CMD, unique_tag, DISPTAG_UNDEFINED }, *tag = buffer; *tag != DISPTAG_UNDEFINED; ++tag) {
81 
82  eventTable.insert(*tag, chsm->ev_init);
83  eventTable.insert(*tag, chsm->ev_configure);
84  eventTable.insert(*tag, chsm->ev_start);
85  eventTable.insert(*tag, chsm->ev_pause);
86  eventTable.insert(*tag, chsm->ev_continue);
87  eventTable.insert(*tag, chsm->ev_stop);
88  eventTable.insert(*tag, chsm->ev_reset);
89  eventTable.insert(*tag, chsm->ev_quit);
90  eventTable.insert(*tag, chsm->ev_off);
91 
92  eventTable.insert(*tag, chsm->ev_check);
93  eventTable.insert(*tag, chsm->ev_input);
94 
95  eventTable.insert(*tag, chsm->ev_recover);
96  }
97 
98  JControlHost::Throw(true);
99 
100  setClockInterval(TIMEOUT_S * 1000000LL);
101  }
102 
103 
104  /**
105  * Get hostname.
106  *
107  * \return host name
108  */
109  const std::string& getHostname() const
110  {
111  return hostname;
112  }
113 
114 
115  /**
116  * Get full name of this run control client.
117  *
118  * \return full name
119  */
120  const std::string& getFullName() const
121  {
122  return fullname;
123  }
124 
125 
126  /**
127  * Get unique tag of this run control client.
128  *
129  * \return unique tag
130  */
131  const JTag& getUniqueTag() const
132  {
133  return unique_tag;
134  }
135 
136 
137  /**
138  * Get total delay time.
139  *
140  * \return delay time [us]
141  */
142  long long int getClockDelay() const
143  {
144  return clock.getDelay();
145  }
146 
147 
148 
149  /**
150  * Get interval time.
151  *
152  * \return interval time [us]
153  */
154  long long int getClockInterval() const
155  {
156  return clock.getInterval();
157  }
158 
159 
160  /**
161  * Set interval time.
162  *
163  * \param interval_us interval time [us]
164  */
165  void setClockInterval(const long long int interval_us)
166  {
167  clock.setInterval(interval_us);
168  }
169 
170 
171  /**
172  * Reset clock.
173  */
174  void resetClock()
175  {
176  clock.reset();
177  }
178 
179 
180  /**
181  * Get last event information.
182  *
183  * \return event information
184  */
185  const std::string& getEventInfo() const
186  {
187  return event_info;
188  }
189 
190 
191  /**
192  * Set last event information.
193  *
194  * \param info event information
195  */
196  void setEventInfo(const std::string& info)
197  {
198  this->event_info = info;
199  }
200 
201 
202  protected:
203  JEventTable eventTable; //!< event table
204  std::string hostname;
205  std::string fullname;
207  JTimekeeper clock; //!< central clock
208  std::string event_info; //!< event information
209  };
210 
211 
212  /**
213  * Control unit client base class.
214  *
215  * This base class implements the protocol for the communication with the control unit.\n
216  * This protocol is based on ControlHost tags and CHSM event names.\n
217  * Normally, the primary input is provided to the constructor of this base class,
218  * e.g.\ via command line options of the application based on a derived class hereof.\n
219  * By calling the default method enter(),
220  * - the internal parameters will be configured; and
221  * - the client's state machine entered.
222  *
223  * The method run() can then be used to process command messages which will acoordingly update the state machine.\n
224  * For each state transition, a corresponding action method is called
225  * which could be re-implemented in the derived class (see JDAQCHSM).\n
226  * Optionally, a designated action method is repeatedly called in state <tt>Running</tt>.
227  *
228  * A state transition is triggered by a valid command message.\n
229  * The command message consists of a tag and some contents.\n
230  * The tag can be used to address all processes, a group of processes or an individual process.\n
231  * The contents of a command message must start with the name on the event and
232  * can contain additional data (separated by KM3NETDAQ::TOKEN_DELIMETER).\n
233  * A successful transition is certified by a reply message which is sent upon entering the targeted state.\n
234  * The reply message has tag "RC_REPLY" and the contents include the names of the original event as well as that of the final state.\n
235  * Optionally, information can be added to an event (separated by KM3NETDAQ::EVENTNAME_DELIMETER).\n
236  * This information is included in the following reply messages,
237  * until there is a command message with (other) information.
238  *
239  * Following a request for a state transition via a command message,
240  * four scenarios should be anticipated, namely:
241  *
242  * -# the process successfully completed the transition,
243  * a corresponding reply message is then send back;
244  * -# the process couldn't make the transition and goes to error state,
245  * a corresponding reply message is then send back,
246  * -# the process crashed,
247  * the process disappears from the process list and
248  * the server broadcasts a corresponding died message;
249  * -# the process takes longer than foreseen, leading to a timeout.
250  *
251  * The followup action after a timeout should be customised.\n
252  * In case of an invalid command message (e.g.\ request for a state transition that does not exist), no reply message will be sent.\n
253  * Instead, a message with tag "RC_FAIL" is sent.
254  *
255  * The default list of tags includes "RC_CMD" and a client specific tag.\n
256  * The latter is composed of the hexadecimal formatted IP sub-address of the client's host CPU (see JSYSTEM::getSubaddress(const int)) and \n
257  * the client's name extension (part following KM3NETDAQ::CLIENTNAME_DELIMETER), if any.\n
258  * The list of tags and the various delimiters are maintained in include file JDAQTags.hh.
259  *
260  * For client specific events requiring a different tag,
261  * the corresponding entry in the event table should be replaced.\n
262  * This should be done in the constructor of the derived class using method replaceEvent().
263  *
264  * The virtual method filter() can be re-implemented so that a specific action
265  * is made before the corresponding message is processed.\n
266  * The message is ignored if this method returns true, else it is normally processed.
267  *
268  * The method setSelect() can be used to set the file descriptor mask of the general select call.\n
269  * In conjunction, the method actionSelect() can be used
270  * to take client specific actions following the select call.
271  *
272  * If the clock interval is non-zero, the method actionRunning() is repeatedly called
273  * according the specified interval time when the client is in state <tt>Running</tt>.\n
274  * The clock interval can be set using method setClockInterval().
275  *
276  * Some input can be redefined during operation.\n
277  * For example the debug level can be set via the following command message.
278  * <pre>
279  * JPutMessage -H <host name> -t <tag> -m "debug=<level>;"
280  * </pre>
281  * where
282  * - <tt>host name</tt> is the name of the host of the command message server;
283  * - <tt>tag</tt> the tag; and
284  * - <tt>level</tt> the new debug level.
285  *
286  * In this, the tag "RC_CMD" applies to all applications and the client specific tag to an individual application.
287  *
288  * Additional custom tags can be added to the general list using method addSubscription().\n
289  * The method actionTagged() is then called when a command message is received with the specified tag.
290  *
291  * For tests and possible other setups, the base class can be configured to run stand-alone or forever.\n
292  * In stand-alone mode, the client can be steered from an regular input stream.\n
293  * When the client runs forever, it waits for a connection before going to the normal mode of operation.\n
294  * The primary input should then be sent via this connection.\n
295  * The method addParameter() can be used to add parameters of
296  * the derived class to the list that is parsed in method enter().
297  */
298  class JDAQClient :
299  public JDAQStateMachine,
300  public JDAQClient_t
301  {
302  using CHSM::machine::enter;
303  using CHSM::machine::exit;
304 
305  public:
306  /**
307  * Constructor.
308  *
309  * This constructor should be used in normal mode.\n
310  * The following methods methods should subsequently be called.
311  * - enter();
312  * - run().
313  *
314  * \param name name of client
315  * \param server name of command message server
316  * \param logger pointer to logger
317  * \param level debug level
318  */
319  JDAQClient(const std::string& name,
320  const std::string& server,
321  JLogger* logger,
322  const int level) :
323  JDAQStateMachine(name),
324  JDAQClient_t (this)
325  {
326  this->logger = JMessageLogger(logger, name, level);
327 
328  try {
329  this->server.reset(new JControlHost(server));
330  }
331  catch(const std::exception& error) {
332  JErrorStream(this->logger) << error.what();
333  }
334 
335  std::string buffer;
336 
337  JControlHost::WhereIs(server, getFullName(), buffer);
338 
339  if (buffer != "") {
340  JErrorStream(this->logger) << "Process with nick name \"" << getFullName() << "\" already running on host(s) " << buffer;
341  }
342  }
343 
344 
345  /**
346  * Constructor.
347  *
348  * This constructor should be used when running stand-alone.\n
349  * The following methods methods should subsequently be called.
350  * - CHSM::machine::enter();
351  * - run(std::istream& in);
352  *
353  * \param name name of client
354  * \param logger pointer to logger
355  * \param level debug level
356  */
357  JDAQClient(const std::string& name,
358  JLogger* logger,
359  const int level) :
360  JDAQStateMachine(name),
361  JDAQClient_t (this)
362  {
363  this->logger = JMessageLogger(logger, name, level);
364  }
365 
366 
367  /**
368  * Constructor.
369  *
370  * This constructor should be used when running forever.\n
371  * The following method should subsequently be called.
372  * - run(const int port);
373  *
374  * \param name name of client
375  */
376  JDAQClient(const std::string& name) :
377  JDAQStateMachine(name),
378  JDAQClient_t (this)
379  {}
380 
381 
382  /**
383  * Enter the state machine.
384  *
385  * This overloaded method enter reproduces the constructor.
386  * All necessary input is parsed from the list of arguments.
387  * In case of an error, the state machine is not entered.
388  *
389  * \param args array of command line arguments
390  * \return true if okay; else false
391  */
392  virtual bool enter(const JArgs& args)
393  {
394  using namespace std;
395 
396  string server;
397  string logger;
398  int level;
399  bool use_cout;
400 
401  try {
402 
403  parser['H'] = make_field(server) = "localhost";
404  parser['M'] = make_field(logger) = "localhost";
405  parser['d'] = make_field(level) = 0;
406  parser['c'] = make_field(use_cout);
407 
408  if (parser.read(args) != 0) {
409  return false;
410  }
411  }
412  catch(const std::exception &error) {
413  cerr << error.what() << endl;
414  return false;
415  }
416 
417  try {
418 
419  JLogger* out = NULL;
420 
421  if (use_cout)
422  out = new JStreamLogger(cout);
423  else
424  out = new JControlHostLogger(logger);
425 
426  this->logger = JMessageLogger(out, getName(), level);
427 
428  this->server.reset(new JControlHost(server));
429 
430  return enter();
431  }
432  catch(const std::exception& error) {
433  cerr << error.what() << endl;
434  return false;
435  }
436  }
437 
438 
439  /**
440  * Enter the state machine.
441  *
442  * This method activates the subscription to JNET::JControlHost messages.
443  * In case of an error, the state machine is not entered.
444  *
445  * \return true if okay; else false
446  */
447  virtual bool enter() override
448  {
449  using namespace std;
450  using namespace JPP;
451 
452  if (server.is_valid() && logger.is_valid()) {
453 
454  const JSubscriptionList buffer = getSubscription(eventTable) + subscription;
455 
456  try {
457 
458  server->Subscribe(buffer);
459  server->SendMeAlways();
460  server->MyId(getFullName());
461 
462  JStatusStream(logger) << "Process with nick name \"" << getFullName() << "\" version \"" << getGITVersion() << "\" subscription: " << buffer.toString();
463 
464  return CHSM::machine::enter();
465  }
466  catch(const std::exception& error) {
467  JErrorStream(logger) << error.what();
468  }
469 
470  } else {
471  cerr << "Message server or logger not properly initialised." << endl;
472  }
473 
474  return false;
475  }
476 
477 
478  /**
479  * Exit the state machine.
480  *
481  * This method releases the various resources.
482  *
483  * \return true if okay; else false
484  */
485  virtual bool exit() override
486  {
487  try {
488  if (server.is_valid()) { server.reset(NULL); }
489  }
490  catch(const std::exception& error) {
491  }
492 
493  try {
494  if (logger.is_valid()) { logger.reset(NULL); }
495  }
496  catch(const std::exception& error) {
497  }
498 
499  return CHSM::machine::exit();
500  }
501 
502 
503  /**
504  * Check if this client is in runnig state.
505  *
506  * \return true if running; else false
507  */
508  bool isRunning() const
509  {
510  return Main.RunControl.Operational.Running.active();
511  }
512 
513 
514  /**
515  * Replace tag of given event in event table.
516  *
517  * \param oldTag old tag
518  * \param newTag new tag
519  * \param event event
520  */
521  void replaceEvent(const JTag& oldTag,
522  const JTag& newTag,
523  JDAQEvent_t& event)
524  {
525  eventTable.replace(oldTag, newTag, event);
526  }
527 
528 
529  /**
530  * Find event in event table.
531  *
532  * \param tag tag
533  * \param event_name event name
534  * \return pointer to event or NULL
535  */
536  JDAQEvent_t* findEvent(const JTag& tag, const std::string& event_name)
537  {
538  JEventTable::const_iterator i = eventTable.find(tag, event_name);
539 
540  if (i != eventTable.end())
541  return i->second;
542  else
543  return NULL;
544  }
545 
546 
547  /**
548  * Add custom subscription.
549  *
550  * \param subscription subscription
551  */
552  void addSubscription(const JSubscription& subscription)
553  {
554  this->subscription.add(subscription);
555  }
556 
557 
558  /**
559  * Add parameter to parser used in method enter().
560  *
561  * \param option option
562  * \param parameter parameter
563  */
564  template<class T>
565  void addParameter(const char option, T& parameter)
566  {
567  parser[option] = make_field(parameter);
568  }
569 
570 
571  /**
572  * Add parameter to parser used in method enter().
573  *
574  * \param option option
575  * \param parameter parameter
576  * \param value default value
577  */
578  template<class T>
579  void addParameter(const char option, T& parameter, const T& value)
580  {
581  parser[option] = make_field(parameter) = value;
582  }
583 
584 
585  /**
586  * Set the file descriptor mask for the select call.
587  */
588  void setSelect()
589  {
590  select.reset();
591 
592  setSelect(select.getReaderMask());
593 
594  select.setReaderMask(*server);
595  }
596 
597 
598  /**
599  * Set the file descriptor mask for the select call.
600  * This implementation does nothing but may be redefined by the derived class.
601  *
602  * \param mask file descriptor mask
603  */
604  virtual void setSelect(JFileDescriptorMask& mask) const
605  {}
606 
607 
608  /**
609  * Action method following last select call.
610  * This implementation does nothing but may be redefined by the derived class.
611  *
612  * \param mask file descriptor mask
613  */
614  virtual void actionSelect(const JFileDescriptorMask& mask)
615  {}
616 
617 
618  /**
619  * This method is repeatedly called when this client machine is in state Running
620  * and the clock interval time is non-zero.
621  * This implementation does nothing but may be redefined by the derived class.
622  * Care has to be taken so that the time needed to execute this method should be
623  * less than the specified clock interval time (see method setClockInterval()).
624  */
625  virtual void actionRunning()
626  {}
627 
628 
629  /**
630  * This method is called at <tt>ev_input</tt>.
631  *
632  * \param length length of data
633  * \param buffer pointer to data
634  */
635  virtual void actionInput(int length, const char* buffer) override
636  {
637  using namespace std;
638 
639  JProperties properties(JEquationParameters("=", ";", "", ""), 1);
640 
641  int level = this->logger.getLevel();
642 
643  properties["debug"] = level;
644 
645  properties.read(string(buffer, length));
646 
647  this->logger.setLevel(level);
648  }
649 
650 
651  /**
652  * Filter message.
653  * The filter method can be overwritten so that a specific action is made
654  * before the corresponding message is processed by the state machine.
655  * The message is ignored if true is returned, else it is normally processed.
656  *
657  * \param tag tag
658  * \param length number of characters
659  * \param buffer message
660  * \return skip message or not
661  */
662  virtual bool filter(const JTag& tag, int length, const char* buffer)
663  {
664  return false;
665  }
666 
667 
668  /**
669  * This method is called when a custom tag is encountered.
670  *
671  * \param tag tag
672  * \param length length of data
673  * \param buffer pointer to data
674  */
675  virtual void actionTagged(const JTag& tag, int length, const char* buffer)
676  {
677  }
678 
679 
680  /**
681  * Run as run control client following command messages via JNET::JControlHost.
682  * This method can be called once the state machine is entered.
683  * It returns when the state machine is exited.
684  * If the clock interval is non-zero, the method actionRunning() is
685  * repeatedly called when this client machine is in state Running.
686  * The file descriptor mask can be set to interrupt the timeout of
687  * the select call and clock method wait() in this calling sequence
688  * (see methods setSelect() and actionSelect()).
689  */
690  void run()
691  {
692  using namespace std;
693  using namespace JPP;
694 
695  while (active()) {
696 
697  try {
698 
699  setSelect();
700 
701  if (select(JTimeval(TIMEOUT_S,0)) > 0) {
702 
703  if (select.hasReaderMask(*server)) {
704  update();
705  }
706 
707  actionSelect(select.getReaderMask());
708 
709  } else {
710 
711  continue;
712  }
713 
714 
715  if (isRunning() && clock.getInterval() != 0LL) {
716 
717  long long int numberOfCalls = 0;
718 
719  clock.reset();
720 
721  do {
722 
723  ++numberOfCalls;
724 
725  setSelect();
726 
727  if (clock.wait(select.getReaderMask())) {
728 
729  if (select.hasReaderMask(*server)) {
730  update();
731  }
732 
733  actionSelect(select.getReaderMask());
734 
735  } else {
736 
737  try {
738  actionRunning();
739  }
740  catch(const std::exception& error) {
741  logger.error(error.what());
742  }
743  }
744 
745  } while (isRunning());
746 
747  if (numberOfCalls != 0) {
748  JNoticeStream(logger) << "Delay per call " << clock.getDelay() / numberOfCalls / 1000 << " ms";
749  }
750  }
751  }
752  catch(const JPP::JSocketException& error) {
753  JErrorStream(logger) << "method run(): \"" << error.what() << "\" -> trigger ev_error.";
754  ev_error();
755  }
756  catch(const std::exception& error) {
757  JErrorStream(logger) << "method run(): \"" << error.what() << "\"";
758  }
759  }
760  }
761 
762 
763  /**
764  * Run for ever.
765  * This method can be used when the run control client is started before the run control
766  * (e.g.\ at boot time of the host processor).
767  * This method should be called before the state machine is entered.
768  * It launches a server which accepts a JNET::JControlHost connection from
769  * a designated application e.g.\ the JDAQClientStarter.cc program.
770  * The state machine is entered using the available data in the JNET::JControlHost message.
771  * After the state machine is exited, it accepts a new a JNET::JControlHost connection.
772  *
773  * \param port port number
774  */
775  void run(const int port)
776  {
777  JControlHostServer local_server(port);
778 
779  for ( ; ; ) {
780 
781  JControlHost* ps = local_server.AcceptClient();
782 
783  ps->Connected();
784 
785  JNET::JPrefix prefix;
786 
787  ps->WaitHead(prefix);
788 
789  const int length = prefix.getSize();
790 
791  char* buffer = new char[length];
792 
793  ps->GetFullData(buffer, length);
794  ps->PutFullData(prefix.toString(), buffer, length);
795 
796  delete ps;
797 
798  enter(JArgs(std::string(buffer, length)));
799 
800  delete [] buffer;
801 
802  run();
803 
804  exit();
805  }
806  }
807 
808 
809  /**
810  * Run client with commands from input stream (e.g.\ for debugging).
811  *
812  * Example input format:
813  * <pre>
814  * <tag> <event name>[\#data];
815  * <tag> <event name>[\#data];
816  * </pre>
817  *
818  * \param in input stream
819  */
820  void run(std::istream& in)
821  {
822  using namespace std;
823 
824  string tag;
825  string buffer;
826 
827  while (in >> tag && in >> skipws && getline(in, buffer, ';')) {
828  update(tag, buffer.length(), buffer.data());
829  }
830  }
831 
832  protected:
833 
835  JMessageLogger logger; //!< message logger
836 
837  private:
838  /**
839  * Update state machine.
840  * This method waits for a message from JNET::JControlHost server.
841  */
842  void update()
843  {
844  JNET::JPrefix prefix;
845 
846  server->WaitHead(prefix);
847 
848  const int length = prefix.getSize();
849 
850  char* buffer = new char[length];
851 
852  server->GetFullData(buffer, length);
853 
854  update(prefix.getTag(), length, buffer);
855 
856  delete [] buffer;
857  }
858 
859 
860  /**
861  * Update state machine.
862  *
863  * \param tag tag
864  * \param length number of characters
865  * \param buffer message
866  */
867  void update(const JTag& tag, int length, const char* buffer)
868  {
869  using namespace std;
870  using namespace JPP;
871 
872  if (filter(tag, length, buffer)) {
873  return;
874  }
875 
876  if (getSubscription(eventTable)->count(JSubscriptionAny(tag)) == 0 &&
877  getSubscription(eventTable)->count(JSubscriptionAll(tag)) == 0) {
878 
879  actionTagged(tag, length, buffer);
880 
881  return;
882  }
883 
884 
885  string::size_type pos = 0;
886 
887  while (pos != (string::size_type) length && TOKEN_DELIMETER.find(*(buffer + pos)) == string::npos) {
888  ++pos;
889  }
890 
891  const JEvent_t event = JEvent_t::toValue(string(buffer, pos));
892 
893  if (event.hasInfo()) {
894  setEventInfo(event.getInfo());
895  }
896 
897  while (pos != (string::size_type) length && TOKEN_DELIMETER.find(*(buffer + pos)) != string::npos) {
898  ++pos;
899  }
900 
901 
902  JEventTable::const_iterator i = eventTable.find(tag, event.getName());
903 
904  if (i != eventTable.end()) {
905 
906  const CHSM::state* const s0 = getState();
907 
908  if (!i->second->active()) {
909 
910  JWarningStream(logger) << "Event " << i->second->name() << " not active (" << (s0 != NULL ? s0->name() : "") << ")";
911 
912  if (server.is_valid() && s0 != NULL) {
913  server->PutFullString(RC_FAIL, getMessage(*s0, *i->second));
914  }
915  }
916 
917  // redirect all I/O
918 
919  {
920  JDebugStream debug(logger);
921  JErrorStream error(logger);
922 
923  JRedirectStream rs_cin (cin, JLANG::null);
924  JRedirectStream rs_cout(cout, debug);
925  JRedirectStream rs_cerr(cerr, error);
926 
927  if (rs_cin &&
928  rs_cout &&
929  rs_cerr) {
930 
931  (*(i->second))(length - pos, buffer + pos);
932  }
933  }
934 
935  const CHSM::state* const s1 = getState();
936 
937  JStatusStream(logger) << "Transition "
938  << (s0 != NULL ? s0->name() : "")
939  << "->(" << i->second->name() << ")->"
940  << (s1 != NULL ? s1->name() : "");
941  } else {
942 
943  JErrorStream(logger) << "Unknown key <" << tag << "," << event.getName() << ">";
944  }
945  }
946 
947 
948  /**
949  * Configure client.
950  * This method is used to setup the event table.
951  */
952  void configure()
953  {
954  }
955 
956 
957  /**
958  * Get event message.
959  *
960  * \param state state
961  * \param event event
962  * \return message
963  */
964  std::string getMessage(const CHSM::state& state, const CHSM::event& event) const
965  {
966  std::ostringstream os;
967 
968  os << getFullName()
969  << getTokenDelimeter()
970  << (getEventInfo() != "" ?
971  JEvent_t(event.name(), getEventInfo()) :
972  JEvent_t(event.name()))
973  << getTokenDelimeter()
974  << getStateName(state.name());
975 
976  return os.str();
977  }
978 
979 
980  /**
981  * Action when entering state.
982  * This method provides for the hand shaking with the run control program.
983  *
984  * \param state entered state
985  * \param event event that triggered transition
986  */
987  virtual void enterState(const CHSM::state& state, const CHSM::event& event) override
988  {
989  if (server.is_valid()) {
990  server->PutFullString(RC_REPLY, getMessage(state, event));
991  }
992  }
993 
994 
995  /**
996  * This method is called at <tt>ev_check</tt> and reports a system check by mimicing an enter state action.
997  *
998  * \param length number of characters
999  * \param buffer message
1000  */
1001  virtual void actionCheck(int length, const char* buffer) override
1002  {
1003  if (Main.RunControl.Error.active()) {
1004 
1005  enterState(Main.RunControl.Error, ev_check);
1006 
1007  } else {
1008 
1009  for (CHSM::parent::iterator state = Main.RunControl.Operational.begin(); state != Main.RunControl.Operational.end(); ++state) {
1010 
1011  if (state->active()) {
1012 
1013  // mimic enter state
1014 
1015  enterState(*state, ev_check);
1016  }
1017  }
1018  }
1019  }
1020 
1021 
1022  /**
1023  * The method to execute the action.
1024  *
1025  * \param __action pointer to action method
1026  * \param __event event that triggered the action
1027  */
1028  void execute(action __action, const CHSM::event& __event) override
1029  {
1030  try {
1031 
1032  const JDAQStateMachine::ev_daq_event& event = dynamic_cast<const JDAQStateMachine::ev_daq_event&>(__event);
1033 
1034  (this->*__action)(event->length, event->buffer);
1035  }
1036  catch(const std::exception& error) {
1037  JErrorStream(logger) << "Error at event " << __event.name() << " \"" << error.what() << "\"; trigger ev_error.";
1038  ev_error();
1039  }
1040  }
1041 
1042 
1043  /**
1044  * Get current state.
1045  *
1046  * \return state
1047  */
1048  const CHSM::state* getState() const
1049  {
1050  for (CHSM::parent::const_iterator state = Main.RunControl.Operational.begin(); state != Main.RunControl.Operational.end(); ++state) {
1051  if (state->active()) {
1052  return &(*state);
1053  }
1054  }
1055 
1056  if (Main.RunControl.Error.active()) {
1057  return &Main.RunControl.Error;
1058  }
1059 
1060  return NULL;
1061  }
1062 
1063 
1064  JSelectReader select; //!< select call
1065  JParser<> parser; //!< parser method enter()
1066  JSubscriptionList subscription; //!< custom subscription
1067  };
1068 }
1069 
1070 #endif
Fixed parameters and ControlHost tags for KM3NeT DAQ.
General purpose message reporting.
Message reporting compatible with STL output stream operations.
int debug
debug level
Definition: JSirene.cc:69
Hostname and IP address functions.
Utility class to parse command line options.
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:2158
Utility class to parse parameter values.
Scheduling of actions via fixed latency intervals.
Jpp environment information.
const std::string & getName() const
Get name of state machine.
Definition: JDAQCHSM.hh:89
JDAQStateMachine::ev_recover_event ev_recover
JDAQStateMachine::ev_continue_event ev_continue
JDAQStateMachine::ev_stop_event ev_stop
JDAQStateMachine::ev_off_event ev_off
JDAQStateMachine::ev_init_event ev_init
JDAQStateMachine::ev_start_event ev_start
JDAQStateMachine::ev_pause_event ev_pause
JDAQStateMachine::ev_check_event ev_check
JDAQStateMachine::ev_reset_event ev_reset
JDAQStateMachine::ev_configure_event ev_configure
JDAQStateMachine::ev_input_event ev_input
JDAQStateMachine::ev_quit_event ev_quit
Data structure to store command line arguments.
Definition: JArgs.hh:26
Utility class to parse parameter values.
Definition: JProperties.hh:501
bool read(const JEquation &equation)
Read equation.
Definition: JProperties.hh:679
Time keeper.
Definition: JTimekeeper.hh:34
bool is_valid() const
Check validity of pointer.
Exception for ControlHost.
Definition: JException.hh:486
Simple data structure to support I/O of equations (see class JLANG::JEquation).
virtual const char * what() const override
Get error message.
Definition: JException.hh:64
Auxiliary class for method select.
This class can be used to temporarily redirect one output (input) stream to another output (input) st...
The template JSharedPointer class can be used to share a pointer to an object.
Exception for socket.
Definition: JException.hh:468
static void Throw(const bool option)
Enable/disable throw option.
Definition: JThrow.hh:37
Auxiliary class for time values.
Definition: JTimeval.hh:29
Message logging based on ControlHost.
Interface for logging messages.
Definition: JLogger.hh:22
Message logging based on std::ostream.
Light-weight wrapper class around server socket.
JControlHost * AcceptClient(JTimeval timeout=JTimeval::max())
Accept new client.
ControlHost class.
static int WhereIs(const std::string &host_name, const std::string &nick_name, std::string &answer)
Locate ControlHost client(s).
int WaitHead(JPrefix &prefix)
Wait for header.
int GetFullData(void *buffer, long long int length)
Receive data.
int PutFullData(const JTag &tag, const void *buffer, const long long int length)
Send data.
int Connected()
Send version.
ControlHost prefix.
Definition: JPrefix.hh:33
int getSize() const
Get size.
Definition: JPrefix.hh:62
Wrapper class for select call.
Subscription list.
std::string toString() const
Convert subscription list to string.
ControlHost subscription.
Definition: JControlHost.hh:52
ControlHost tag.
Definition: JTag.hh:38
std::string toString() const
Convert tag to string.
Definition: JTag.hh:171
const JTag & getTag() const
Get tag.
Definition: JTag.hh:86
Utility class to parse command line options.
Definition: JParser.hh:1714
Control unit client base class.
Definition: JDAQClient.hh:301
JDAQEvent_t * findEvent(const JTag &tag, const std::string &event_name)
Find event in event table.
Definition: JDAQClient.hh:536
virtual void enterState(const CHSM::state &state, const CHSM::event &event) override
Action when entering state.
Definition: JDAQClient.hh:987
void update(const JTag &tag, int length, const char *buffer)
Update state machine.
Definition: JDAQClient.hh:867
JSharedPointer< JControlHost > server
message server
Definition: JDAQClient.hh:834
virtual void actionInput(int length, const char *buffer) override
This method is called at ev_input.
Definition: JDAQClient.hh:635
bool isRunning() const
Check if this client is in runnig state.
Definition: JDAQClient.hh:508
void update()
Update state machine.
Definition: JDAQClient.hh:842
virtual bool filter(const JTag &tag, int length, const char *buffer)
Filter message.
Definition: JDAQClient.hh:662
JDAQClient(const std::string &name)
Constructor.
Definition: JDAQClient.hh:376
JParser parser
parser method enter()
Definition: JDAQClient.hh:1065
virtual void actionTagged(const JTag &tag, int length, const char *buffer)
This method is called when a custom tag is encountered.
Definition: JDAQClient.hh:675
JDAQClient(const std::string &name, JLogger *logger, const int level)
Constructor.
Definition: JDAQClient.hh:357
virtual void actionSelect(const JFileDescriptorMask &mask)
Action method following last select call.
Definition: JDAQClient.hh:614
void replaceEvent(const JTag &oldTag, const JTag &newTag, JDAQEvent_t &event)
Replace tag of given event in event table.
Definition: JDAQClient.hh:521
void execute(action __action, const CHSM::event &__event) override
The method to execute the action.
Definition: JDAQClient.hh:1028
std::string getMessage(const CHSM::state &state, const CHSM::event &event) const
Get event message.
Definition: JDAQClient.hh:964
virtual bool exit() override
Exit the state machine.
Definition: JDAQClient.hh:485
void addParameter(const char option, T &parameter)
Add parameter to parser used in method enter().
Definition: JDAQClient.hh:565
void run(std::istream &in)
Run client with commands from input stream (e.g. for debugging).
Definition: JDAQClient.hh:820
void run(const int port)
Run for ever.
Definition: JDAQClient.hh:775
void run()
Run as run control client following command messages via JNET::JControlHost.
Definition: JDAQClient.hh:690
const CHSM::state * getState() const
Get current state.
Definition: JDAQClient.hh:1048
void configure()
Configure client.
Definition: JDAQClient.hh:952
virtual void setSelect(JFileDescriptorMask &mask) const
Set the file descriptor mask for the select call.
Definition: JDAQClient.hh:604
JSelectReader select
select call
Definition: JDAQClient.hh:1064
JMessageLogger logger
message logger
Definition: JDAQClient.hh:835
virtual void actionRunning()
This method is repeatedly called when this client machine is in state Running and the clock interval ...
Definition: JDAQClient.hh:625
void addParameter(const char option, T &parameter, const T &value)
Add parameter to parser used in method enter().
Definition: JDAQClient.hh:579
void setSelect()
Set the file descriptor mask for the select call.
Definition: JDAQClient.hh:588
virtual bool enter() override
Enter the state machine.
Definition: JDAQClient.hh:447
JSubscriptionList subscription
custom subscription
Definition: JDAQClient.hh:1066
virtual bool enter(const JArgs &args)
Enter the state machine.
Definition: JDAQClient.hh:392
JDAQClient(const std::string &name, const std::string &server, JLogger *logger, const int level)
Constructor.
Definition: JDAQClient.hh:319
virtual void actionCheck(int length, const char *buffer) override
This method is called at ev_check and reports a system check by mimicing an enter state action.
Definition: JDAQClient.hh:1001
void addSubscription(const JSubscription &subscription)
Add custom subscription.
Definition: JDAQClient.hh:552
bool select(const Trk &trk, const Evt &evt)
Event selection.
std::string getGITVersion(const std::string &tag)
Get GIT version for given GIT tag.
static JNullStream null
Null I/O stream.
Definition: JNullStream.hh:51
std::istream & getline(std::istream &in, JString &object)
Read string from input stream until end of line.
Definition: JString.hh:478
Message logging.
static const JTag DISPTAG_UNDEFINED(0)
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
bool filter(const JDAQEvent &tev, const JEvt &evt, const Evt *const pE)
Event selection.
const char * getName()
Get ROOT name of given data type.
Definition: JRootToolkit.hh:62
std::string getHostname()
Get host name.
Definition: JNetwork.hh:77
KM3NeT DAQ data structures and auxiliaries.
Definition: DataQueue.cc:39
static const JNET::JTag RC_REPLY
Definition: JDAQTags.hh:67
std::string getFullName(const std::string &hostname, const std::string &name)
Get full name of run control client.
JSubscriptionList getSubscription(const JEventTable &event_table)
Convert event table to ControlHost subscription.
Definition: JEventTable.hh:129
static const std::string TOKEN_DELIMETER
Definition: JDAQTags.hh:58
JTag getUniqueTag(const std::string &hostname, const std::string &name)
Get unique tag of run control client.
static const JNET::JTag RC_CMD
Definition: JDAQTags.hh:66
std::string getStateName(const std::string &name)
Get name of state.
char getTokenDelimeter()
Get the token delimeter for command messages.
static const JNET::JTag RC_FAIL
Definition: JDAQTags.hh:68
Definition: JSTDTypes.hh:14
Level specific message streamers.
Auxiliary class for all subscription.
Definition: JControlHost.hh:99
Auxiliary class for any subscription.
Auxiliary data structure for DAQ client data.
Definition: JDAQClient.hh:61
const std::string & getEventInfo() const
Get last event information.
Definition: JDAQClient.hh:185
JTimekeeper clock
central clock
Definition: JDAQClient.hh:207
void setEventInfo(const std::string &info)
Set last event information.
Definition: JDAQClient.hh:196
void setClockInterval(const long long int interval_us)
Set interval time.
Definition: JDAQClient.hh:165
long long int getClockDelay() const
Get total delay time.
Definition: JDAQClient.hh:142
void resetClock()
Reset clock.
Definition: JDAQClient.hh:174
const std::string & getFullName() const
Get full name of this run control client.
Definition: JDAQClient.hh:120
JEventTable eventTable
event table
Definition: JDAQClient.hh:203
const std::string & getHostname() const
Get hostname.
Definition: JDAQClient.hh:109
JDAQClient_t(JDAQStateMachine *chsm)
Constructor.
Definition: JDAQClient.hh:71
std::string event_info
event information
Definition: JDAQClient.hh:208
long long int getClockInterval() const
Get interval time.
Definition: JDAQClient.hh:154
const JTag & getUniqueTag() const
Get unique tag of this run control client.
Definition: JDAQClient.hh:131
Auxiliary class for handling event name and optional static information.
Definition: JEvent_t.hh:23
static JEvent_t toValue(const std::string &buffer)
Convert string to event.
Definition: JEvent_t.hh:99