Belle II Software development
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
26extern "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 --------------------------------------------------
35const char* master_logdir = ".";
36FILE* master_logfp = 0;
37
38// -- xreopenlog ----------------------------------------------------
39// log directory
40// ----------------------------------------------------------------------
41void
42xreopenlog()
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// ----------------------------------------------------------------------
74void
75xprintlog(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// ----------------------------------------------------------------------
95void
96xlogtime(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 ----------------------------------------------------------
120int
121xgetargs(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// ----------------------------------------------------------------------
159void
160ok_handler(NSMmsg* /*msg*/, NSMcontext*)
161{
162 xprintlog("OK received");
163}
164// -- error_handler -----------------------------------------------------
165//
166// ----------------------------------------------------------------------
167void
168error_handler(NSMmsg* /*msg*/, NSMcontext*)
169{
170 xprintlog("ERROR received");
171}
172
173// -- msg_handler -----------------------------------------------------
174//
175// ----------------------------------------------------------------------
176void
177msg_handler(NSMmsg* /*msg*/, NSMcontext*)
178{
179 xprintlog("MSG received");
180}
181// -- main --------------------------------------------------------------
182// main does everything except callback functions
183// ----------------------------------------------------------------------
184int
185main(int argc, const 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