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