Jpp  18.0.0-rc.4
the software that should make you happy
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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
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  public:
303  /**
304  * Constructor.
305  *
306  * This constructor should be used in normal mode.\n
307  * The following methods methods should subsequently be called.
308  * - enter();
309  * - run().
310  *
311  * \param name name of client
312  * \param server name of command message server
313  * \param logger pointer to logger
314  * \param level debug level
315  */
317  const std::string& server,
318  JLogger* logger,
319  const int level) :
320  JDAQStateMachine(name),
322  {
323  this->logger = JMessageLogger(logger, name, level);
324 
325  try {
326  this->server.reset(new JControlHost(server));
327  }
328  catch(JControlHostException& error) {
329  JErrorStream(this->logger) << error;
330  }
331 
332  std::string buffer;
333 
334  JControlHost::WhereIs(server, getFullName(), buffer);
335 
336  if (buffer != "") {
337  JErrorStream(this->logger) << "Process with nick name \"" << getFullName() << "\" already running on host(s) " << buffer;
338  }
339  }
340 
341 
342  /**
343  * Constructor.
344  *
345  * This constructor should be used when running stand-alone.\n
346  * The following methods methods should subsequently be called.
347  * - CHSM::machine::enter();
348  * - run(std::istream& in);
349  *
350  * \param name name of client
351  * \param logger pointer to logger
352  * \param level debug level
353  */
355  JLogger* logger,
356  const int level) :
357  JDAQStateMachine(name),
359  {
360  this->logger = JMessageLogger(logger, name, level);
361  }
362 
363 
364  /**
365  * Constructor.
366  *
367  * This constructor should be used when running forever.\n
368  * The following method should subsequently be called.
369  * - run(const int port);
370  *
371  * \param name name of client
372  */
374  JDAQStateMachine(name),
376  {}
377 
378 
379  /**
380  * Enter the state machine.
381  *
382  * This overloaded method enter reproduces the constructor.
383  * All necessary input is parsed from the list of arguments.
384  * In case of an error, the state machine is not entered.
385  *
386  * \param args array of command line arguments
387  * \return true if okay; else false
388  */
389  virtual bool enter(const JArgs& args)
390  {
391  using namespace std;
392 
393  string server;
394  string logger;
395  int level;
396  bool use_cout;
397 
398  try {
399 
400  parser['H'] = make_field(server) = "localhost";
401  parser['M'] = make_field(logger) = "localhost";
402  parser['d'] = make_field(level) = 0;
403  parser['c'] = make_field(use_cout);
404 
405  if (parser.read(args) != 0) {
406  return false;
407  }
408  }
409  catch(const exception &error) {
410  cerr << error.what() << endl;
411  return false;
412  }
413 
414  try {
415 
416  JLogger* out = NULL;
417 
418  if (use_cout)
419  out = new JStreamLogger(cout);
420  else
421  out = new JControlHostLogger(logger);
422 
423  this->logger = JMessageLogger(out, getName(), level);
424 
425  this->server.reset(new JControlHost(server));
426 
427  return enter();
428  }
429  catch(const JControlHostException& error) {
430  cerr << error << endl;
431  return false;
432  }
433  }
434 
435 
436  /**
437  * Enter the state machine.
438  *
439  * This method activates the subscription to JNET::JControlHost messages.
440  * In case of an error, the state machine is not entered.
441  *
442  * \return true if okay; else false
443  */
444  virtual bool enter()
445  {
446  using namespace std;
447  using namespace JPP;
448 
449  if (server.is_valid() && logger.is_valid()) {
450 
451  const JSubscriptionList buffer = getSubscription(eventTable) + subscription;
452 
453  try {
454 
455  server->Subscribe(buffer);
456  server->SendMeAlways();
457  server->MyId(getFullName());
458 
459  JStatusStream(logger) << "Process with nick name \"" << getFullName() << "\" version \"" << getGITVersion() << "\" subscription: " << buffer.toString();
460 
461  return CHSM::machine::enter();
462  }
463  catch(const JControlHostException& error) {
464  JErrorStream(logger) << error;
465  }
466 
467  } else {
468  cerr << "Message server or logger not properly initialised." << endl;
469  }
470 
471  return false;
472  }
473 
474 
475  /**
476  * Exit the state machine.
477  *
478  * This method releases the various resources.
479  *
480  * \return true if okay; else false
481  */
482  virtual bool exit()
483  {
484  try {
485  if (server.is_valid()) { server.reset(NULL); }
486  }
487  catch(const JControlHostException& error) {
488  }
489 
490  try {
491  if (logger.is_valid()) { logger.reset(NULL); }
492  }
493  catch(const JControlHostException& error) {
494  }
495 
496  return CHSM::machine::exit();
497  }
498 
499 
500  /**
501  * Check if this client is in runnig state.
502  *
503  * \return true if running; else false
504  */
505  bool isRunning() const
506  {
507  return Main.RunControl.Operational.Running.active();
508  }
509 
510 
511  /**
512  * Replace tag of given event in event table.
513  *
514  * \param oldTag old tag
515  * \param newTag new tag
516  * \param event event
517  */
518  void replaceEvent(const JTag& oldTag,
519  const JTag& newTag,
520  JDAQEvent_t& event)
521  {
522  eventTable.replace(oldTag, newTag, event);
523  }
524 
525 
526  /**
527  * Find event in event table.
528  *
529  * \param tag tag
530  * \param event_name event name
531  * \return pointer to event or NULL
532  */
533  JDAQEvent_t* findEvent(const JTag& tag, const std::string& event_name)
534  {
535  JEventTable::const_iterator i = eventTable.find(tag, event_name);
536 
537  if (i != eventTable.end())
538  return i->second;
539  else
540  return NULL;
541  }
542 
543 
544  /**
545  * Add custom subscription.
546  *
547  * \param subscription subscription
548  */
549  void addSubscription(const JSubscription& subscription)
550  {
551  this->subscription.add(subscription);
552  }
553 
554 
555  /**
556  * Add parameter to parser used in method enter().
557  *
558  * \param option option
559  * \param parameter parameter
560  */
561  template<class T>
562  void addParameter(const char option, T& parameter)
563  {
564  parser[option] = make_field(parameter);
565  }
566 
567 
568  /**
569  * Add parameter to parser used in method enter().
570  *
571  * \param option option
572  * \param parameter parameter
573  * \param value default value
574  */
575  template<class T>
576  void addParameter(const char option, T& parameter, const T& value)
577  {
578  parser[option] = make_field(parameter) = value;
579  }
580 
581 
582  /**
583  * Set the file descriptor mask for the select call.
584  */
585  void setSelect()
586  {
587  select.reset();
588 
589  setSelect(select.getReaderMask());
590 
591  select.setReaderMask(*server);
592  }
593 
594 
595  /**
596  * Set the file descriptor mask for the select call.
597  * This implementation does nothing but may be redefined by the derived class.
598  *
599  * \param mask file descriptor mask
600  */
601  virtual void setSelect(JFileDescriptorMask& mask) const
602  {}
603 
604 
605  /**
606  * Action method following last select call.
607  * This implementation does nothing but may be redefined by the derived class.
608  *
609  * \param mask file descriptor mask
610  */
611  virtual void actionSelect(const JFileDescriptorMask& mask)
612  {}
613 
614 
615  /**
616  * This method is repeatedly called when this client machine is in state Running
617  * and the clock interval time is non-zero.
618  * This implementation does nothing but may be redefined by the derived class.
619  * Care has to be taken so that the time needed to execute this method should be
620  * less than the specified clock interval time (see method setClockInterval()).
621  */
622  virtual void actionRunning()
623  {}
624 
625 
626  /**
627  * This method is called at <tt>ev_input</tt>.
628  *
629  * \param length length of data
630  * \param buffer pointer to data
631  */
632  virtual void actionInput(int length, const char* buffer)
633  {
634  using namespace std;
635 
636  JProperties properties(JEquationParameters("=", ";", "", ""), 1);
637 
638  int level = this->logger.getLevel();
639 
640  properties["debug"] = level;
641 
642  properties.read(string(buffer, length));
643 
644  this->logger.setLevel(level);
645  }
646 
647 
648  /**
649  * Filter message.
650  * The filter method can be overwritten so that a specific action is made
651  * before the corresponding message is processed by the state machine.
652  * The message is ignored if true is returned, else it is normally processed.
653  *
654  * \param tag tag
655  * \param length number of characters
656  * \param buffer message
657  * \return skip message or not
658  */
659  virtual bool filter(const JTag& tag, int length, const char* buffer)
660  {
661  return false;
662  }
663 
664 
665  /**
666  * This method is called when a custom tag is encountered.
667  *
668  * \param tag tag
669  * \param length length of data
670  * \param buffer pointer to data
671  */
672  virtual void actionTagged(const JTag& tag, int length, const char* buffer)
673  {
674  }
675 
676 
677  /**
678  * Run as run control client following command messages via JNET::JControlHost.
679  * This method can be called once the state machine is entered.
680  * It returns when the state machine is exited.
681  * If the clock interval is non-zero, the method actionRunning() is
682  * repeatedly called when this client machine is in state Running.
683  * The file descriptor mask can be set to interrupt the timeout of
684  * the select call and clock method wait() in this calling sequence
685  * (see methods setSelect() and actionSelect()).
686  */
687  void run()
688  {
689  using namespace std;
690 
691  while (active()) {
692 
693  try {
694 
695  setSelect();
696 
697  if (select(JTimeval(TIMEOUT_S,0)) > 0) {
698 
699  if (select.hasReaderMask(*server)) {
700  update();
701  }
702 
703  actionSelect(select.getReaderMask());
704 
705  } else {
706 
707  continue;
708  }
709 
710 
711  if (isRunning() && clock.getInterval() != 0LL) {
712 
713  long long int numberOfCalls = 0;
714 
715  clock.reset();
716 
717  do {
718 
719  ++numberOfCalls;
720 
721  setSelect();
722 
723  if (clock.wait(select.getReaderMask())) {
724 
725  if (select.hasReaderMask(*server)) {
726  update();
727  }
728 
729  actionSelect(select.getReaderMask());
730 
731  } else {
732 
733  try {
734  actionRunning();
735  }
736  catch(const exception& error) {
737  logger.error(error.what());
738  }
739  }
740 
741  } while (isRunning());
742 
743  if (numberOfCalls != 0) {
744  JNoticeStream(logger) << "Delay per call " << clock.getDelay() / numberOfCalls / 1000 << " ms";
745  }
746  }
747  }
748  catch(const exception& error) {
749  JErrorStream(logger) << "method run(): " << error.what();
750  }
751  }
752  }
753 
754 
755  /**
756  * Run for ever.
757  * This method can be used when the run control client is started before the run control
758  * (e.g.\ at boot time of the host processor).
759  * This method should be called before the state machine is entered.
760  * It launches a server which accepts a JNET::JControlHost connection from
761  * a designated application e.g.\ the JDAQClientStarter.cc program.
762  * The state machine is entered using the available data in the JNET::JControlHost message.
763  * After the state machine is exited, it accepts a new a JNET::JControlHost connection.
764  *
765  * \param port port number
766  */
767  void run(const int port)
768  {
769  JControlHostServer local_server(port);
770 
771  for ( ; ; ) {
772 
773  JControlHost* ps = local_server.AcceptClient();
774 
775  ps->Connected();
776 
777  JNET::JPrefix prefix;
778 
779  ps->WaitHead(prefix);
780 
781  const int length = prefix.getSize();
782 
783  char* buffer = new char[length];
784 
785  ps->GetFullData(buffer, length);
786  ps->PutFullData(prefix.toString(), buffer, length);
787 
788  delete ps;
789 
790  enter(JArgs(std::string(buffer, length)));
791 
792  delete [] buffer;
793 
794  run();
795 
796  exit();
797  }
798  }
799 
800 
801  /**
802  * Run client with commands from input stream (e.g.\ for debugging).
803  *
804  * Example input format:
805  * <pre>
806  * <tag> <event name>[\#data];
807  * <tag> <event name>[\#data];
808  * </pre>
809  *
810  * \param in input stream
811  */
812  void run(std::istream& in)
813  {
814  using namespace std;
815 
816  string tag;
817  string buffer;
818 
819  while (in >> tag && in >> skipws && getline(in, buffer, ';')) {
820  update(tag, buffer.length(), buffer.data());
821  }
822  }
823 
824  protected:
825 
827  JMessageLogger logger; //!< message logger
828 
829  private:
830  /**
831  * Update state machine.
832  * This method waits for a message from JNET::JControlHost server.
833  */
834  void update()
835  {
836  JNET::JPrefix prefix;
837 
838  server->WaitHead(prefix);
839 
840  const int length = prefix.getSize();
841 
842  char* buffer = new char[length];
843 
844  server->GetFullData(buffer, length);
845 
846  update(prefix.getTag(), length, buffer);
847 
848  delete [] buffer;
849  }
850 
851 
852  /**
853  * Update state machine.
854  *
855  * \param tag tag
856  * \param length number of characters
857  * \param buffer message
858  */
859  void update(const JTag& tag, int length, const char* buffer)
860  {
861  using namespace std;
862  using namespace JPP;
863 
864  if (filter(tag, length, buffer)) {
865  return;
866  }
867 
868  if (getSubscription(eventTable)->count(JSubscriptionAny(tag)) == 0 &&
869  getSubscription(eventTable)->count(JSubscriptionAll(tag)) == 0) {
870 
871  actionTagged(tag, length, buffer);
872 
873  return;
874  }
875 
876 
877  string::size_type pos = 0;
878 
879  while (pos != (string::size_type) length && TOKEN_DELIMETER.find(*(buffer + pos)) == string::npos) {
880  ++pos;
881  }
882 
883  const JEvent_t event = JEvent_t::toValue(string(buffer, pos));
884 
885  if (event.hasInfo()) {
886  setEventInfo(event.getInfo());
887  }
888 
889  while (pos != (string::size_type) length && TOKEN_DELIMETER.find(*(buffer + pos)) != string::npos) {
890  ++pos;
891  }
892 
893 
894  JEventTable::const_iterator i = eventTable.find(tag, event.getName());
895 
896  if (i != eventTable.end()) {
897 
898  const CHSM::state* const s0 = getState();
899 
900  if (!i->second->active()) {
901 
902  JWarningStream(logger) << "Event " << i->second->name() << " not active (" << (s0 != NULL ? s0->name() : "") << ")";
903 
904  if (server.is_valid() && s0 != NULL) {
905  server->PutFullString(RC_FAIL, getMessage(*s0, *i->second));
906  }
907  }
908 
909  // redirect all I/O
910 
911  {
912  JDebugStream debug(logger);
913  JErrorStream error(logger);
914 
915  JRedirectStream rs_cin (cin, JLANG::null);
916  JRedirectStream rs_cout(cout, debug);
917  JRedirectStream rs_cerr(cerr, error);
918 
919  if (rs_cin &&
920  rs_cout &&
921  rs_cerr) {
922 
923  (*(i->second))(length - pos, buffer + pos);
924  }
925  }
926 
927  const CHSM::state* const s1 = getState();
928 
929  JStatusStream(logger) << "Transition "
930  << (s0 != NULL ? s0->name() : "")
931  << "->(" << i->second->name() << ")->"
932  << (s1 != NULL ? s1->name() : "");
933  } else {
934 
935  JErrorStream(logger) << "Unknown key <" << tag << "," << event.getName() << ">";
936  }
937  }
938 
939 
940  /**
941  * Configure client.
942  * This method is used to setup the event table.
943  */
944  void configure()
945  {
946  }
947 
948 
949  /**
950  * Get event message.
951  *
952  * \param state state
953  * \param event event
954  * \return message
955  */
956  std::string getMessage(const CHSM::state& state, const CHSM::event& event) const
957  {
958  std::ostringstream os;
959 
960  os << getFullName()
961  << getTokenDelimeter()
962  << (getEventInfo() != "" ?
963  JEvent_t(event.name(), getEventInfo()) :
964  JEvent_t(event.name()))
965  << getTokenDelimeter()
966  << getStateName(state.name());
967 
968  return os.str();
969  }
970 
971 
972  /**
973  * Action when entering state.
974  * This method provides for the hand shaking with the run control program.
975  *
976  * \param state entered state
977  * \param event event that triggered transition
978  */
979  virtual void enterState(const CHSM::state& state, const CHSM::event& event)
980  {
981  if (server.is_valid()) {
982  server->PutFullString(RC_REPLY, getMessage(state, event));
983  }
984  }
985 
986 
987  /**
988  * This method is called at <tt>ev_check</tt> and reports a system check by mimicing an enter state action.
989  *
990  * \param length number of characters
991  * \param buffer message
992  */
993  virtual void actionCheck(int length, const char* buffer)
994  {
995  if (Main.RunControl.Error.active()) {
996 
997  enterState(Main.RunControl.Error, ev_check);
998 
999  } else {
1000 
1001  for (CHSM::parent::iterator state = Main.RunControl.Operational.begin(); state != Main.RunControl.Operational.end(); ++state) {
1002 
1003  if (state->active()) {
1004 
1005  // mimic enter state
1006 
1007  enterState(*state, ev_check);
1008  }
1009  }
1010  }
1011  }
1012 
1013 
1014  /**
1015  * The method to execute the action.
1016  *
1017  * \param __action pointer to action method
1018  * \param __event event that triggered the action
1019  */
1020  void execute(action __action, const CHSM::event& __event)
1021  {
1022  try {
1023 
1024  const JDAQStateMachine::ev_daq_event& event = dynamic_cast<const JDAQStateMachine::ev_daq_event&>(__event);
1025 
1026  (this->*__action)(event->length, event->buffer);
1027  }
1028  catch(const std::exception& error) {
1029  JErrorStream(logger) << "Error at event " << __event.name() << " \"" << error.what() << "\"; trigger ev_error.";
1030  ev_error();
1031  }
1032  }
1033 
1034 
1035  /**
1036  * Get current state.
1037  *
1038  * \return state
1039  */
1040  const CHSM::state* getState() const
1041  {
1042  for (CHSM::parent::const_iterator state = Main.RunControl.Operational.begin(); state != Main.RunControl.Operational.end(); ++state) {
1043  if (state->active()) {
1044  return &(*state);
1045  }
1046  }
1047 
1048  if (Main.RunControl.Error.active()) {
1049  return &Main.RunControl.Error;
1050  }
1051 
1052  return NULL;
1053  }
1054 
1055 
1056  JSelectReader select; //!< select call
1057  JParser<> parser; //!< parser method enter()
1058  JSubscriptionList subscription; //!< custom subscription
1059  };
1060 }
1061 
1062 #endif
set Main(RunControl, Responder) is
Definition: JDAQCHSM.chsm:188
JParser parser
parser method enter()
Definition: JDAQClient.hh:1057
ControlHost prefix.
Definition: JPrefix.hh:31
Utility class to parse command line options.
Definition: JParser.hh:1514
long long int getClockDelay() const
Get total delay time.
Definition: JDAQClient.hh:142
bool read(const JEquation &equation)
Read equation.
Definition: JProperties.hh:677
JDAQStateMachine::ev_start_event ev_start
JDAQEvent_t * findEvent(const JTag &tag, const std::string &event_name)
Find event in event table.
Definition: JDAQClient.hh:533
JDAQStateMachine::ev_configure_event ev_configure
JTimekeeper clock
central clock
Definition: JDAQClient.hh:207
ControlHost class.
void resetClock()
Reset clock.
Definition: JDAQClient.hh:174
JDAQStateMachine::ev_pause_event ev_pause
Message logging based on std::ostream.
JDAQStateMachine::ev_continue_event ev_continue
virtual void setSelect(JFileDescriptorMask &mask) const
Set the file descriptor mask for the select call.
Definition: JDAQClient.hh:601
int Connected()
Send version.
JTag getUniqueTag(const std::string &hostname, const std::string &name)
Get unique tag of run control client.
JDAQStateMachine::ev_reset_event ev_reset
JSelectReader select
select call
Definition: JDAQClient.hh:1056
Message reporting compatible with STL output stream operations.
long long int getClockInterval() const
Get interval time.
Definition: JDAQClient.hh:154
void setEventInfo(const std::string &info)
Set last event information.
Definition: JDAQClient.hh:196
Auxiliary data structure for DAQ client data.
Definition: JDAQClient.hh:61
std::string toString() const
Convert subscription list to string.
Interface for logging messages.
Definition: JLogger.hh:22
Message logging based on ControlHost.
then echo Enter input within $TIMEOUT_S seconds echo n User name
Definition: JCookie.sh:42
Utility class to parse parameter values.
Definition: JProperties.hh:496
void setClockInterval(const long long int interval_us)
Set interval time.
Definition: JDAQClient.hh:165
JDAQClient(const std::string &name)
Constructor.
Definition: JDAQClient.hh:373
exit
Definition: JPizza.sh:36
Simple data structure to support I/O of equations (see class JLANG::JEquation).
Time keeper.
Definition: JTimekeeper.hh:34
then usage $script< detector file >< detectorfile > nIf the range of floors is the first detector file is aligned to the second before the comparison nIn this
Jpp environment information.
const std::string & getEventInfo() const
Get last event information.
Definition: JDAQClient.hh:185
virtual void enterState(const CHSM::state &state, const CHSM::event &event)
Action when entering state.
Definition: JDAQClient.hh:979
void configure()
Configure client.
Definition: JDAQClient.hh:944
JSharedPointer< JControlHost > server
message server
Definition: JDAQClient.hh:826
void replaceEvent(const JTag &oldTag, const JTag &newTag, JDAQEvent_t &event)
Replace tag of given event in event table.
Definition: JDAQClient.hh:518
static const std::string TOKEN_DELIMETER
Definition: JDAQTags.hh:50
void execute(action __action, const CHSM::event &__event)
The method to execute the action.
Definition: JDAQClient.hh:1020
void run()
Run as run control client following command messages via JNET::JControlHost.
Definition: JDAQClient.hh:687
std::string event_info
event information
Definition: JDAQClient.hh:208
JDAQStateMachine::ev_init_event ev_init
virtual bool filter(const JTag &tag, int length, const char *buffer)
Filter message.
Definition: JDAQClient.hh:659
bool is_valid() const
Check validity of pointer.
int getSize() const
Get size.
Definition: JPrefix.hh:62
Subscription list.
Utility class to parse parameter values.
JDAQClient_t(JDAQStateMachine *chsm)
Constructor.
Definition: JDAQClient.hh:71
static JEvent_t toValue(const std::string &buffer)
Convert string to event.
Definition: JEvent_t.hh:99
Auxiliary class for time values.
Definition: JTimeval.hh:26
void run(const int port)
Run for ever.
Definition: JDAQClient.hh:767
JDAQStateMachine::ev_stop_event ev_stop
std::string getStateName(const std::string &name)
Get name of state.
const CHSM::state * getState() const
Get current state.
Definition: JDAQClient.hh:1040
Scheduling of actions via fixed latency intervals.
std::string getGITVersion(const std::string &tag)
Get GIT version for given GIT tag.
The template JSharedPointer class can be used to share a pointer to an object.
This class can be used to temporarily redirect one output (input) stream to another output (input) st...
static const JNET::JTag RC_REPLY
Definition: JDAQTags.hh:59
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
Definition: JParser.hh:1989
virtual bool enter()
Enter the state machine.
Definition: JDAQClient.hh:444
do set_variable OUTPUT_DIRECTORY $WORKDIR T
virtual void actionRunning()
This method is repeatedly called when this client machine is in state Running and the clock interval ...
Definition: JDAQClient.hh:622
Auxiliary class for method select.
Wrapper class for select call.
Auxiliary class for any subscription.
then awk string
virtual void actionTagged(const JTag &tag, int length, const char *buffer)
This method is called when a custom tag is encountered.
Definition: JDAQClient.hh:672
std::istream & getline(std::istream &in, JString &object)
Read string from input stream until end of line.
Definition: JString.hh:478
static const JTag DISPTAG_UNDEFINED(0)
Auxiliary class for handling event name and optional static information.
Definition: JEvent_t.hh:23
Level specific message streamers.
Exception for ControlHost.
Definition: JException.hh:468
virtual bool exit()
Exit the state machine.
Definition: JDAQClient.hh:482
Data structure to store command line arguments.
Definition: JArgs.hh:24
char getTokenDelimeter()
Get the token delimeter for command messages.
bool isRunning() const
Check if this client is in runnig state.
Definition: JDAQClient.hh:505
Auxiliary class for all subscription.
Definition: JControlHost.hh:97
void update(const JTag &tag, int length, const char *buffer)
Update state machine.
Definition: JDAQClient.hh:859
JSubscriptionList subscription
custom subscription
Definition: JDAQClient.hh:1058
JControlHost * AcceptClient(JTimeval timeout=JTimeval::max())
Accept new client.
const std::string & getHostname() const
Get hostname.
Definition: JDAQClient.hh:109
const JTag & getTag() const
Get tag.
Definition: JTag.hh:86
std::string getHostname()
Get host name.
Definition: JNetwork.hh:77
void update()
Update state machine.
Definition: JDAQClient.hh:834
JDAQStateMachine::ev_check_event ev_check
int WaitHead(JPrefix &prefix)
Wait for header.
void addParameter(const char option, T &parameter, const T &value)
Add parameter to parser used in method enter().
Definition: JDAQClient.hh:576
void addParameter(const char option, T &parameter)
Add parameter to parser used in method enter().
Definition: JDAQClient.hh:562
virtual void actionInput(int length, const char *buffer)
This method is called at ev_input.
Definition: JDAQClient.hh:632
std::string toString() const
Convert tag to string.
Definition: JTag.hh:171
General purpose message reporting.
JEventTable eventTable
event table
Definition: JDAQClient.hh:203
JDAQStateMachine::ev_quit_event ev_quit
int GetFullData(void *buffer, long long int length)
Receive data.
const std::string & getFullName() const
Get full name of this run control client.
Definition: JDAQClient.hh:120
JDAQStateMachine::ev_input_event ev_input
Control unit client base class.
Definition: JDAQClient.hh:298
Utility class to parse command line options.
event< ev_daq > ev_check
Definition: JDAQCHSM.chsm:183
void run(std::istream &in)
Run client with commands from input stream (e.g. for debugging).
Definition: JDAQClient.hh:812
ControlHost subscription.
Definition: JControlHost.hh:50
std::string getMessage(const CHSM::state &state, const CHSM::event &event) const
Get event message.
Definition: JDAQClient.hh:956
JSubscriptionList getSubscription(const JEventTable &event_table)
Convert event table to ControlHost subscription.
Definition: JEventTable.hh:129
virtual bool enter(const JArgs &args)
Enter the state machine.
Definition: JDAQClient.hh:389
const JTag & getUniqueTag() const
Get unique tag of this run control client.
Definition: JDAQClient.hh:131
JDAQClient(const std::string &name, const std::string &server, JLogger *logger, const int level)
Constructor.
Definition: JDAQClient.hh:316
const char * getName()
Get ROOT name of given data type.
Definition: JRootToolkit.hh:57
JMessageLogger logger
message logger
Definition: JDAQClient.hh:827
Fixed parameters and ControlHost tags for KM3NeT DAQ.
static const JNET::JTag RC_CMD
Definition: JDAQTags.hh:58
static int WhereIs(const std::string &host_name, const std::string &nick_name, std::string &answer)
Locate ControlHost client(s).
ControlHost tag.
Definition: JTag.hh:38
JDAQStateMachine::ev_off_event ev_off
const std::string & getName() const
Get name of state machine.
Definition: JDAQCHSM.chsm:78
std::string getFullName(const std::string &hostname, const std::string &name)
Get full name of run control client.
static JNullStream null
Null I/O stream.
Definition: JNullStream.hh:51
void setSelect()
Set the file descriptor mask for the select call.
Definition: JDAQClient.hh:585
then fatal Wrong number of arguments fi set_variable DETECTOR $argv[1] set_variable INPUT_FILE $argv[2] eval JPrintDetector a $DETECTOR O IDENTIFIER eval JPrintDetector a $DETECTOR O SUMMARY JAcoustics sh $DETECTOR_ID source JAcousticsToolkit sh CHECK_EXIT_CODE typeset A EMITTERS get_tripods $WORKDIR tripod txt EMITTERS get_transmitters $WORKDIR transmitter txt EMITTERS for EMITTER in
Definition: JCanberra.sh:46
static const JNET::JTag RC_FAIL
Definition: JDAQTags.hh:60
int PutFullData(const JTag &tag, const void *buffer, const long long int length)
Send data.
Hostname and IP address functions.
virtual void actionSelect(const JFileDescriptorMask &mask)
Action method following last select call.
Definition: JDAQClient.hh:611
void addSubscription(const JSubscription &subscription)
Add custom subscription.
Definition: JDAQClient.hh:549
virtual void actionCheck(int length, const char *buffer)
This method is called at ev_check and reports a system check by mimicing an enter state action...
Definition: JDAQClient.hh:993
static void Throw(const bool option)
Enable/disable throw option.
Definition: JThrow.hh:37
int debug
debug level
Light-weight wrapper class around server socket.
JDAQStateMachine::ev_recover_event ev_recover
JDAQClient(const std::string &name, JLogger *logger, const int level)
Constructor.
Definition: JDAQClient.hh:354