Belle II Software  release-06-00-14
rfctl.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 // ----------------------------------------------------------------------
9 // master.cc
10 //
11 // A simple-minded NSM2 master program which does:
12 // - text-base command line input with readline
13 // - log message storage in a file
14 // (no screen output as it conflicts with readline)
15 // ----------------------------------------------------------------------
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <ctype.h>
20 #include <stdarg.h>
21 #include <time.h>
22 #include <sys/time.h>
23 #include <sys/stat.h>
24 #include "nsm2/belle2nsm.h"
25 
26 extern "C" {
27 #ifdef USE_READLINE
28 #include <readline/readline.h>
29 #undef CTRL /* also defined in sys/ioctl.h in solaris */
30  extern int add_history(char*);
31 #endif
32 }
33 
34 // -- global variables --------------------------------------------------
35 const char* master_logdir = ".";
36 FILE* master_logfp = 0;
37 
38 // -- xreopenlog ----------------------------------------------------
39 // log directory
40 // ----------------------------------------------------------------------
41 void
42 xreopenlog()
43 {
44  static int logid = -1;
45  static char logprefix[1024];
46  static int isdirprefix = 0;
47  char logfile[1024];
48  time_t now = time(0);
49  tm* cur = localtime(&now);
50  struct stat statbuf;
51 
52  if (! logprefix[0]) {
53  strcpy(logprefix, master_logdir);
54  if (! logprefix[0]) strcpy(logprefix, ".");
55  if (logprefix[strlen(logprefix) - 1] == '/') {
56  logprefix[strlen(logprefix) - 1] = 0;
57  }
58  if (stat(logprefix, &statbuf) >= 0 && S_ISDIR(statbuf.st_mode)) {
59  strcat(logprefix, "/master");
60  }
61  }
62 
63  sprintf(logfile, "%s.%04d%02d%02d.log", logprefix,
64  cur->tm_year + 1900, cur->tm_mon + 1, cur->tm_mday);
65  if (master_logfp != stdout) {
66  if (master_logfp) fclose(master_logfp);
67  if (!(master_logfp = fopen(logfile, "a"))) {
68  printf("cannot open logfile %s\n", logfile);
69  exit(1);
70  }
71  }
72 }
73 // -- xprintlog ---------------------------------------------------------
74 // printlog
75 // ----------------------------------------------------------------------
76 void
77 xprintlog(const char* fmt, ...)
78 {
79  va_list ap;
80  char datebuf[32];
81  void xlogtime(char* buf);
82 
83  if (master_logfp) {
84  va_start(ap, fmt);
85  xlogtime(datebuf);
86  fputs(datebuf, master_logfp);
87  vfprintf(master_logfp, fmt, ap);
88  fputc('\n', master_logfp);
89  va_end(ap);
90 
91  fflush(master_logfp);
92  }
93 }
94 // -- xlogtime ----------------------------------------------------------
95 // logtime
96 // ----------------------------------------------------------------------
97 void
98 xlogtime(char* buf)
99 {
100  timeval now;
101  tm* cur;
102  static int lastday = -1;
103 
104  gettimeofday(&now, 0);
105  cur = localtime((time_t*)&now.tv_sec);
106  /*
107  if (lastday != cur->tm_yday) {
108  char datebuf[128];
109  lastday = cur->tm_yday;
110  xreopenlog();
111  xprintlog(
112  "------------------------------------------------------------------");
113  sprintf(datebuf, "Date: %04d.%02d.%02d",
114  cur->tm_year + 1900, cur->tm_mon + 1, cur->tm_mday);
115  xprintlog(datebuf);
116  }
117  */
118  sprintf(buf, "%02d:%02d:%02d.%03d ",
119  cur->tm_hour, cur->tm_min, cur->tm_sec, (int)now.tv_usec / 1000);
120 }
121 // -- xgetargs ----------------------------------------------------------
122 int
123 xgetargs(char* buf, char* argv[])
124 {
125  int i, argc = 0, inword = 0, inquote = 0;
126  char* p = buf;
127 
128  while (*p) {
129  if (*p == '\\') {
130  if (*(p + 1) == 'n') {
131  memmove(p, p + 1, strlen(p));
132  *p = '\n';
133  } else {
134  memmove(p, p + 1, strlen(p));
135  }
136  } else if (*p == '"') {
137  inquote = !inquote;
138  memmove(p, p + 1, strlen(p));
139  if (! inword) {
140  argc++;
141  *argv++ = p;
142  inword = 1;
143  }
144  p--;
145  } else if (isspace(*p) && !inquote && inword) {
146  *p = 0;
147  inword = 0;
148  } else if (! isspace(*p) && !inword) {
149  inword = 1;
150  argc++;
151  *argv++ = p;
152  }
153  p++;
154  }
155  if (inquote) return -1;
156  return argc;
157 }
158 // -- ok_handler --------------------------------------------------------
159 //
160 // ----------------------------------------------------------------------
161 void
162 ok_handler(NSMmsg* msg, NSMcontext*)
163 {
164  xprintlog("OK received");
165 }
166 // -- error_handler -----------------------------------------------------
167 //
168 // ----------------------------------------------------------------------
169 void
170 error_handler(NSMmsg* msg, NSMcontext*)
171 {
172  xprintlog("ERROR received");
173 }
174 
175 // -- msg_handler -----------------------------------------------------
176 //
177 // ----------------------------------------------------------------------
178 void
179 msg_handler(NSMmsg* msg, NSMcontext*)
180 {
181  xprintlog("MSG received");
182 }
183 // -- main --------------------------------------------------------------
184 // main does everything except callback functions
185 // ----------------------------------------------------------------------
186 int
187 main(int argc, char** argv)
188 {
189  const char* program = argv[0];
190  const char* nodename = argv[1]; // need to check before using
191  const char myname[] = "rfctl";
192 
193  char* buf = 0;
194  char* input = 0;
195  char* prev = 0;
196  char* av[128];
197  int ac;
198  char* prompt;
199 
200  int ret;
201 
202  // xreopenlog();
203  master_logfp = stdout;
204 
205  // ARGV check
206  if (argc < 2) {
207  nodename = myname;
208  }
209 
210  // INIT
211  if (! b2nsm_init(nodename)) {
212  xprintlog("%s: INIT %s", program, b2nsm_strerror());
213  return 1;
214  }
215  xprintlog("%s: INIT", program);
216  b2nsm_logging(master_logfp);
217 
218  // handlers
219  if (b2nsm_callback("OK", ok_handler) < 0) {
220  xprintlog("%s: CALLBACK(OK) %s", program, b2nsm_strerror());
221  return 1;
222  }
223  if (b2nsm_callback("ERROR", ok_handler) < 0) {
224  xprintlog("%s: CALLBACK(ERROR) %s", program, b2nsm_strerror());
225  return 1;
226  }
227 
228  /*
229  if ( b2nsm_callback("MSG", msg_handler ) < 0) {
230  xprintlog("%s: CALLBACK(MSG) %s", program, b2nsm_strerror());
231  }
232  */
233  // prompt
234  prompt = (char*)malloc(strlen(nodename) + 2);
235  strcpy(prompt, nodename);
236  strcat(prompt, ">");
237 
238  // infinite loop
239  while (1) {
240 #ifdef USE_READLINE
241  /* On solaris, fgets returns without changing buf when it receives
242  a network message (it doesn't happen on linux). If the buffer
243  is not initialized, it will produce a faulty input.
244  */
245  if (buf) free(buf);
246  if (input) free(input);
247  if (!(input = readline(prompt)))
248  exit(1);
249  buf = (char*)malloc(strlen(input) + 1);
250  strcpy(buf, input);
251 
252  if (!prev || (*input && strcmp(prev, input) != 0)) {
253  add_history(input);
254  if (prev) free(prev);
255  prev = (char*)malloc(strlen(input) + 1);
256  strcpy(prev, input);
257  }
258 #else
259  static char buf[1024];
260  buf[0] = 0;
261  printf("%s", prompt);
262  do {
263  fgets(buf, sizeof(buf), stdin);
264  } while (! buf[0]); /* to cope with EINTR */
265 #endif
266 
267  if ((ac = xgetargs(buf, av)) <= 0)
268  continue;
269  printf("ac=%d av[0]=%s\n", ac, av[0]);
270 
271  if (strcasecmp(av[0], "q") == 0 || strcasecmp(av[0], "quit") == 0) {
272  break;
273  } else if (strcasecmp(av[0], "start") == 0) {
274  if (ac < 4 || ! isdigit(av[2][0])) {
275  printf("usage: start <node> <exp-number> <run-number>\n");
276  } else {
277  int pars[2];
278  pars[0] = atoi(av[2]);
279  pars[1] = atoi(av[3]);
280  b2nsm_sendreq(av[1], "RC_START", 2, pars);
281  }
282  } else if (strcasecmp(av[0], "stop") == 0) {
283  if (ac < 4) {
284  printf("usage: start <node> <exp-number> <run-number>\n");
285  } else {
286  int pars[10];
287  pars[0] = atoi(av[2]);
288  pars[1] = atoi(av[3]);
289  b2nsm_sendreq(av[1], "RC_STOP", 2, pars);
290  }
291  } else if (strcasecmp(av[0], "config") == 0) {
292  if (ac < 2) {
293  printf("usage: config <node>\n");
294  } else {
295  // b2nsm_sendreq(av[1], "RC_LOAD", 0, 0);
296  char scrfile[256];
297  strcpy(scrfile, "run_processor.py");
298  b2nsm_sendany(av[1], "RC_LOAD", 0, 0, sizeof(scrfile) + 1, scrfile, "sendreq");
299  }
300  } else if (strcasecmp(av[0], "unconfig") == 0) {
301  if (ac < 2) {
302  printf("usage: unconfig <node>\n");
303  } else {
304  b2nsm_sendreq(av[1], "RC_ABORT", 0, 0);
305  }
306  } else if (strcasecmp(av[0], "restart") == 0) {
307  if (ac < 2) {
308  printf("usage: restart <node>\n");
309  } else {
310  b2nsm_sendreq(av[1], "RC_RECOVER", 0, 0);
311  }
312  } else {
313  printf("unknown request %s\n", av[0]);
314  }
315  }
316 
317  return 0; // never reached
318 }
319 // ----------------------------------------------------------------------
320 // -- (emacs outline mode setup)
321 // Local Variables: ***
322 // mode:outline-minor ***
323 // outline-regexp:"^// --[+ ]" ***
324 // End: ***
Definition: nsm2.h:224
int main(int argc, char **argv)
Run all tests.
Definition: test_main.cc:75