Belle II Software  release-08-01-10
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 char logprefix[1024];
45  char logfile[2048];
46  time_t now = time(0);
47  tm* cur = localtime(&now);
48  struct stat statbuf;
49 
50  if (! logprefix[0]) {
51  strcpy(logprefix, master_logdir);
52  if (! logprefix[0]) strcpy(logprefix, ".");
53  if (logprefix[strlen(logprefix) - 1] == '/') {
54  logprefix[strlen(logprefix) - 1] = 0;
55  }
56  if (stat(logprefix, &statbuf) >= 0 && S_ISDIR(statbuf.st_mode)) {
57  strcat(logprefix, "/master");
58  }
59  }
60 
61  sprintf(logfile, "%s.%04d%02d%02d.log", logprefix,
62  cur->tm_year + 1900, cur->tm_mon + 1, cur->tm_mday);
63  if (master_logfp != stdout) {
64  if (master_logfp) fclose(master_logfp);
65  if (!(master_logfp = fopen(logfile, "a"))) {
66  printf("cannot open logfile %s\n", logfile);
67  exit(1);
68  }
69  }
70 }
71 // -- xprintlog ---------------------------------------------------------
72 // printlog
73 // ----------------------------------------------------------------------
74 void
75 xprintlog(const char* fmt, ...)
76 {
77  void xlogtime(char* buf);
78 
79  if (master_logfp) {
80  va_list ap;
81  va_start(ap, fmt);
82  char datebuf[32];
83  xlogtime(datebuf);
84  fputs(datebuf, master_logfp);
85  vfprintf(master_logfp, fmt, ap);
86  fputc('\n', master_logfp);
87  va_end(ap);
88 
89  fflush(master_logfp);
90  }
91 }
92 // -- xlogtime ----------------------------------------------------------
93 // logtime
94 // ----------------------------------------------------------------------
95 void
96 xlogtime(char* buf)
97 {
98  timeval now;
99  tm* cur;
100 
101  gettimeofday(&now, 0);
102  cur = localtime((time_t*)&now.tv_sec);
103  /*
104  static int lastday = -1;
105  if (lastday != cur->tm_yday) {
106  char datebuf[128];
107  lastday = cur->tm_yday;
108  xreopenlog();
109  xprintlog(
110  "------------------------------------------------------------------");
111  sprintf(datebuf, "Date: %04d.%02d.%02d",
112  cur->tm_year + 1900, cur->tm_mon + 1, cur->tm_mday);
113  xprintlog(datebuf);
114  }
115  */
116  sprintf(buf, "%02d:%02d:%02d.%03d ",
117  cur->tm_hour, cur->tm_min, cur->tm_sec, (int)now.tv_usec / 1000);
118 }
119 // -- xgetargs ----------------------------------------------------------
120 int
121 xgetargs(char* buf, char* argv[])
122 {
123  int argc = 0, inword = 0, inquote = 0;
124  char* p = buf;
125 
126  while (*p) {
127  if (*p == '\\') {
128  if (*(p + 1) == 'n') {
129  memmove(p, p + 1, strlen(p));
130  *p = '\n';
131  } else {
132  memmove(p, p + 1, strlen(p));
133  }
134  } else if (*p == '"') {
135  inquote = !inquote;
136  memmove(p, p + 1, strlen(p));
137  if (! inword) {
138  argc++;
139  *argv++ = p;
140  inword = 1;
141  }
142  p--;
143  } else if (isspace(*p) && !inquote && inword) {
144  *p = 0;
145  inword = 0;
146  } else if (! isspace(*p) && !inword) {
147  inword = 1;
148  argc++;
149  *argv++ = p;
150  }
151  p++;
152  }
153  if (inquote) return -1;
154  return argc;
155 }
156 // -- ok_handler --------------------------------------------------------
157 //
158 // ----------------------------------------------------------------------
159 void
160 ok_handler(NSMmsg* /*msg*/, NSMcontext*)
161 {
162  xprintlog("OK received");
163 }
164 // -- error_handler -----------------------------------------------------
165 //
166 // ----------------------------------------------------------------------
167 void
168 error_handler(NSMmsg* /*msg*/, NSMcontext*)
169 {
170  xprintlog("ERROR received");
171 }
172 
173 // -- msg_handler -----------------------------------------------------
174 //
175 // ----------------------------------------------------------------------
176 void
177 msg_handler(NSMmsg* /*msg*/, NSMcontext*)
178 {
179  xprintlog("MSG received");
180 }
181 // -- main --------------------------------------------------------------
182 // main does everything except callback functions
183 // ----------------------------------------------------------------------
184 int
185 main(int argc, char** argv)
186 {
187  const char* program = argv[0];
188  const char* nodename = argv[1]; // need to check before using
189  const char myname[] = "rfctl";
190 
191  char* buf = 0;
192  char* av[128];
193  char* prompt;
194 
195  // xreopenlog();
196  master_logfp = stdout;
197 
198  // ARGV check
199  if (argc < 2) {
200  nodename = myname;
201  }
202 
203  // INIT
204  if (! b2nsm_init(nodename)) {
205  xprintlog("%s: INIT %s", program, b2nsm_strerror());
206  return 1;
207  }
208  xprintlog("%s: INIT", program);
209  b2nsm_logging(master_logfp);
210 
211  // handlers
212  if (b2nsm_callback("OK", ok_handler) < 0) {
213  xprintlog("%s: CALLBACK(OK) %s", program, b2nsm_strerror());
214  return 1;
215  }
216  if (b2nsm_callback("ERROR", ok_handler) < 0) {
217  xprintlog("%s: CALLBACK(ERROR) %s", program, b2nsm_strerror());
218  return 1;
219  }
220 
221  /*
222  if ( b2nsm_callback("MSG", msg_handler ) < 0) {
223  xprintlog("%s: CALLBACK(MSG) %s", program, b2nsm_strerror());
224  }
225  */
226  // prompt
227  prompt = (char*)malloc(strlen(nodename) + 2);
228  strcpy(prompt, nodename);
229  strcat(prompt, ">");
230 
231 
232 #ifdef USE_READLINE
233  char* input = 0;
234  char* prev = 0;
235 #endif
236 
237  // infinite loop
238  while (1) {
239 #ifdef USE_READLINE
240  /* On solaris, fgets returns without changing buf when it receives
241  a network message (it doesn't happen on linux). If the buffer
242  is not initialized, it will produce a faulty input.
243  */
244  if (buf) free(buf);
245  if (input) free(input);
246  if (!(input = readline(prompt)))
247  exit(1);
248  buf = (char*)malloc(strlen(input) + 1);
249  strcpy(buf, input);
250 
251  if (!prev || (*input && strcmp(prev, input) != 0)) {
252  add_history(input);
253  if (prev) free(prev);
254  prev = (char*)malloc(strlen(input) + 1);
255  strcpy(prev, input);
256  }
257 #else
258  static char buffer[1024];
259  buffer[0] = 0;
260  printf("%s", prompt);
261  do {
262  fgets(buffer, sizeof(buffer), stdin);
263  } while (! buffer[0]); /* to cope with EINTR */
264 #endif
265 
266  int ac;
267  if ((ac = xgetargs(buf, av)) <= 0) //TODO should there be buf or buffer?
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:91