Belle II Software development
RFLogManager.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#include "daq/rfarm/manager/RFLogManager.h"
10#include "daq/rfarm/manager/RFNSM.h"
11
12#include <nsm2/belle2nsm.h>
13
14#include <fcntl.h>
15#include <sys/time.h>
16#include <time.h>
17#include <unistd.h>
18
19#include <cstdarg>
20#include <cstring>
21#include <iostream>
22
23using namespace Belle2;
24using namespace std;
25
26#define VSNPRINTF(s,l,f,a) va_start(a,f);vsnprintf(s,l,f,a);va_end(a)
27
28// Constructor/Destructor
29
30RFLogManager::RFLogManager(const char* id, const char* lognode, const char* logdir)
31{
32 strcpy(m_id, id);
33
34 if (lognode != NULL)
35 strcpy(m_lognode, lognode);
36 else
37 strcpy(m_lognode, "LOGC");
38
39 if (logdir != NULL)
40 strcpy(m_logdir, logdir);
41 else
42 m_logdir[0] = 0;
43
44 m_logdate = today();
45 OpenLogFile(m_logdate);
46}
47
48RFLogManager::~RFLogManager()
49{
50 close(m_fd);
51}
52
53// Basic Function
54
55int RFLogManager::today()
56{
57 time_t today = time(NULL);
58 struct tm* tmtoday = gmtime(&today);
59 int day = tmtoday->tm_mday;
60 int month = tmtoday->tm_mon + 1;
61 int year = tmtoday->tm_year - 100;
62 // printf ( "RFLogManager: day = %d, month = %d, year = %d\n", day, month, year );
63 return day + month * 100 + year * 10000;
64}
65
66int RFLogManager::OpenLogFile(int today)
67{
68 char filename[2048];
69 if (m_logdir[0] != 0)
70 sprintf(filename, "%s/%s_d%6.6d.log", m_logdir, m_id, today);
71 else
72 sprintf(filename, "%s_d%6.6d.log", m_id, today);
73
74 m_fd = open(filename, O_RDWR | O_CREAT | O_APPEND, 0644);
75 if (m_fd < 0) {
76 fprintf(stderr, "RfLogManager(%s) : error to open file %s\n",
77 m_id, filename);
78 perror("RFLogManager");
79 } else {
80 // Make symbolic link to "latest.log"
81 char slinkname[1024];
82 sprintf(slinkname, "latest.log");
83 unlink(slinkname);
84 symlink(filename, slinkname);
85 printf("RFLogManager: symbolic link to %s\n", slinkname);
86 }
87 return m_fd;
88}
89
90int RFLogManager::SwitchLogFile()
91{
92 int myday = today();
93 if (myday != m_logdate) {
94 close(m_fd);
95 OpenLogFile(myday);
96 m_logdate = myday;
97 }
98 return 0;
99}
100
101
102int RFLogManager::WriteLog(const char* prefix, const char* msg)
103{
104 SwitchLogFile();
105 char wbuf[1024];
106 timestamp(wbuf);
107 sprintf(&wbuf[strlen(wbuf) - 1], "%s %s\n", prefix, msg);
108 int st = write(m_fd, wbuf, strlen(wbuf));
109 return st;
110}
111
112void RFLogManager::timestamp(char* buf)
113{
114 struct timeval tb;
115 struct tm* tp;
116 // struct tm result;
117 gettimeofday(&tb, NULL);
118 tp = localtime(&tb.tv_sec);
119 sprintf(buf, "[%04d-%02d-%02d %02d:%02d:%02d.%03d] ",
120 tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday,
121 tp->tm_hour, tp->tm_min, tp->tm_sec, (int)(tb.tv_usec / 1000));
122 return;
123}
124
125char* RFLogManager::BuildMessage(const char* fmt, ...)
126{
127 va_list arg;
128
129 m_strbuf[sizeof(m_strbuf) - 1] = 0;
130
131 VSNPRINTF(m_strbuf, sizeof(m_strbuf), fmt, arg);
132
133 return m_strbuf;
134
135 /*
136 int len = strlen(m_strbuf);
137 while(m_strbuf[len-1] == '\n' ) m_strbuf[--len] = 0;
138 m_strbuf[len++] = '\n';
139 m_strbuf[len] = 0;
140 return m_strbuf;
141 */
142}
143
144void RFLogManager::Log(const char* fmt, ...)
145{
146 va_list ap;
147 char msg[1000];
148
149 msg[sizeof(msg) - 1] = 0;
150 VSNPRINTF(msg, sizeof(msg), fmt, ap);
151 WriteLog("", msg);
152}
153
154void RFLogManager::Info(const char* fmt, ...)
155{
156 va_list ap;
157 char msg[1000];
158
159 msg[sizeof(msg) - 1] = 0;
160 VSNPRINTF(msg, sizeof(msg), fmt, ap);
161 WriteLog("[INFO]", msg);
162 if (RFNSM_Status::Instance().get_state() == RFSTATE_RUNNING) {
163 int pars[2];
164 pars[0] = 2;
165 pars[1] = (int)time(NULL);
166 b2nsm_sendany(m_lognode, "LOG", 2, pars, strlen(msg) + 1, msg, NULL);
167 }
168}
169
170void RFLogManager::Warning(const char* fmt, ...)
171{
172 va_list ap;
173 char msg[1000];
174
175 msg[sizeof(msg) - 1] = 0;
176 VSNPRINTF(msg, sizeof(msg), fmt, ap);
177 WriteLog("[WARNING]", msg);
178 if (RFNSM_Status::Instance().get_state() == RFSTATE_RUNNING) {
179 int pars[2];
180 pars[0] = 4;
181 pars[1] = (int)time(NULL);
182 b2nsm_sendany(m_lognode, "LOG", 2, pars, strlen(msg) + 1, msg, NULL);
183 }
184}
185
186void RFLogManager::Error(const char* fmt, ...)
187{
188 va_list ap;
189 char msg[1000];
190
191 msg[sizeof(msg) - 1] = 0;
192 VSNPRINTF(msg, sizeof(msg), fmt, ap);
193 WriteLog("[ERROR]", msg);
194 if (RFNSM_Status::Instance().get_state() == RFSTATE_RUNNING) {
195 int pars[2];
196 pars[0] = 5;
197 pars[1] = (int)time(NULL);
198 b2nsm_sendany(m_lognode, "LOG", 2, pars, strlen(msg) + 1, msg, NULL);
199 }
200}
201
202void RFLogManager::Fatal(const char* fmt, ...)
203{
204 va_list ap;
205 char msg[1000];
206
207 msg[sizeof(msg) - 1] = 0;
208 VSNPRINTF(msg, sizeof(msg), fmt, ap);
209 WriteLog("[FATAL]", msg);
210 if (RFNSM_Status::Instance().get_state() == RFSTATE_RUNNING) {
211 int pars[2];
212 pars[0] = 6;
213 pars[1] = (int)time(NULL);
214 b2nsm_sendany(m_lognode, "LOG", 2, pars, strlen(msg) + 1, msg, NULL);
215 }
216}
217
218void RFLogManager::Abort(const char* fmt, ...)
219{
220 va_list ap;
221 char msg[1000];
222
223 msg[sizeof(msg) - 1] = 0;
224 VSNPRINTF(msg, sizeof(msg), fmt, ap);
225 WriteLog("[ABORT]", msg);
226 b2nsm_sendany(m_lognode, "LOG", 0, NULL, strlen(msg), msg, NULL);
227 abort();
228}
229
230// Process Log
231
232int RFLogManager::ProcessLog(int fd)
233{
234 const int bufSize = 4000000;
235 char* p, *q;
236 char* const buf = new char[bufSize];
237 int len;
238 int siz = bufSize * sizeof(char) - 1;
239 int toolong = 0;
240
241 p = buf;
242 fd_set fdset;
243 do {
244 FD_ZERO(&fdset);
245 if (fd <= 0) {
246 printf("Pipe for log is not availablle\n");
247 Abort("No pipe available");
248 }
249 FD_SET(fd, &fdset);
250 struct timeval tv;
251 tv.tv_sec = 0;
252 tv.tv_usec = 0;
253 if (select(fd + 1, &fdset, NULL, NULL, &tv) < 0) {
254 switch (errno) {
255 case EINTR: continue;
256 case EAGAIN: continue;
257 default:
258 perror("select");
259 return -1;
260 }
261 return -1;
262 } else if (!(fd > 0 && FD_ISSET(fd, &fdset))) {
263 return 0;
264 }
265 if ((len = read(fd, p, siz)) < 0) {
266 if (errno == EINTR) continue;
267 if (errno == EPIPE) {
268 Log("broken pipe fd=%d", fd);
269 close(fd);
270 return -1;
271 } else if (errno == EBADF) {
272 Log("bad fd=%d", fd);
273 return -1;
274 }
275 perror("read");
276 Abort("read");
277 } else if (len == 0) {
278 close(fd);
279 return -1;
280 } else {
281 p[len] = 0;
282 len += p - buf;
283 p = buf;
284 do {
285 if (!(q = strchr(p, '\n'))) {
286 if (p == buf && len == siz) {
287 if (! toolong)
288 Warning("too long message from fd=%d", fd);
289 toolong = 1;
290 } else {
291 len -= p - buf;
292 memmove(buf, p, len);
293 siz = bufSize * sizeof(char) - len;
294 p = buf + len;
295 }
296 break;
297 }
298 *q++ = 0;
299 if (! toolong) {
300 if (strlen(p) > 13 &&
301 p[2] == ':' && p[5] == ':' && p[8] == '.' && p[12] == ' ') {
302 p += 13;
303 }
304 if (strncmp(p, "[FATAL] ", 8) == 0) {
305 Fatal("%s", p + 8);
306 } else if (strncmp(p, "[ERROR] ", 8) == 0) {
307 Error("%s", p + 8);
308 } else if (strncmp(p, "[WARNING] ", 10) == 0) {
309 Warning("%s", p + 10);
310 } else if (strncmp(p, "[INFO] ", 7) == 0) {
311 Info("%s", p + 7);
312 } else if (strncmp(p, "[ABORT] ", 8) == 0) {
313 Fatal("abort - %s", p + 8);
314 } else if (strncmp(p, "[sysexit] ", 10) == 0) {
315 Fatal("sysexit - %s", p + 10);
316 } else {
317 Log("%s", p);
318 }
319 }
320 toolong = 0;
321 p = q;
322 if (! *p) return 0;
323 } while (*p);
324 }
325 } while (1);
326}
327
328
329
330
331
332
Abstract base class for different kinds of events.
STL namespace.