Belle II Software  release-08-01-10
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 
23 using namespace Belle2;
24 using 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 
30 RFLogManager::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 
48 RFLogManager::~RFLogManager()
49 {
50  close(m_fd);
51 }
52 
53 // Basic Function
54 
55 int 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 
66 int 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 
90 int 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 
102 int 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 
112 void 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 
125 char* 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 
144 void 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 
154 void 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 
170 void 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 
186 void 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 
202 void 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 
218 void 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 
232 int 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.