FrontISTR  5.7.0
Large-scale structural analysis program with finit element method
hecmw_log.c
Go to the documentation of this file.
1 /*****************************************************************************
2  * Copyright (c) 2019 FrontISTR Commons
3  * This software is released under the MIT License, see LICENSE.txt
4  *****************************************************************************/
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <errno.h>
10 #include <stdarg.h>
11 #include "hecmw_config.h"
12 #include "hecmw_util.h"
13 #include "hecmw_log.h"
14 
15 #ifdef _OPENMP
16 #include <omp.h>
17 #endif
18 
19 #define HECMW_LINE_MAX 1023
20 
21 #define USEFUL_LOGLVS(lv) ((lv) ? (lv | (lv - 1)) : 0)
22 
23 static struct loglv_ent {
24  int loglv;
25  char *str;
26 } hecmw_loglv_table[] = {
27  {HECMW_LOG_ERROR, "Error"},
28  {HECMW_LOG_WARN, "Warning"},
29  {HECMW_LOG_INFO, "Info"},
30  {HECMW_LOG_DEBUG, "Debug"},
31 };
32 
33 struct log_ent {
34  FILE *fp;
36  int lv;
37  int opt;
38 };
39 
40 static struct log_ent logent[HECMW_LOG_MAX];
41 
42 static int useful_logent[HECMW_LOG_MAX];
43 
44 static int loglevels = USEFUL_LOGLVS(HECMW_LOG_INFO);
45 
46 static int enable_by_rank = 1;
47 
48 static int check_loglv(int loglv) {
49  int i;
50  for (i = 0; i < sizeof(hecmw_loglv_table) / sizeof(hecmw_loglv_table[0]);
51  i++) {
52  if (loglv == hecmw_loglv_table[i].loglv) return 0;
53  }
54  return -1; /* not found */
55 }
56 
57 void HECMW_setloglv(int loglv) {
58  if (loglv != HECMW_LOG_NONE && check_loglv(loglv)) {
59  return;
60  }
61  loglevels = USEFUL_LOGLVS(loglv);
62 }
63 
64 int HECMW_openlog(const char *logfile, int loglv, int options) {
65  FILE *fp;
66  int i, newent_idx;
67  struct log_ent *newent;
68  char rank[10];
69  char logfilename[HECMW_FILENAME_LEN + 1];
70 
71  if (logfile == NULL) {
72  HECMW_set_error(HECMW_UTIL_E9011, "Not specified log filename");
73  return -1;
74  }
75  HECMW_snprintf(rank, sizeof(rank), ".%d", HECMW_comm_get_rank());
76  if ((strlen(logfile) + strlen(rank)) > HECMW_FILENAME_LEN) {
77  HECMW_set_error(HECMW_UTIL_E9011, "Filename too long");
78  return -1;
79  }
80  sprintf(logfilename, "%s%s", logfile, rank);
81 
82  loglv &= HECMW_LOG_ALL;
83  if (!loglv) {
84  HECMW_set_error(HECMW_UTIL_E9011, "Invalid log level");
85  return -1;
86  }
87 
89 
90  /* search same logfile */
91  for (i = 0; i < HECMW_LOG_MAX; i++) {
92  if (!useful_logent[i]) continue;
93  if (strcmp(logfilename, logent[i].file) == 0) {
94  logent[i].lv = loglv; /* override */
95  logent[i].opt = options; /* override */
96  return 0;
97  }
98  }
99  /* search free entry */
100  newent = NULL;
101  for (i = 0; i < HECMW_LOG_MAX; i++) {
102  if (useful_logent[i]) continue; /* using */
103  newent = &logent[i];
104  newent_idx = i;
105  break;
106  }
107  if (newent == NULL) { /* no free entry */
108  HECMW_set_error(HECMW_UTIL_E9011, "No free entry");
109  return -1;
110  }
111  /* regist new log entry */
112  strcpy(newent->file, logfilename);
113  newent->lv = loglv;
114  newent->opt = options;
115  if (enable_by_rank && loglv & loglevels) {
116  if ((fp = fopen(logfilename, "a")) == NULL) {
117  HECMW_set_error(HECMW_UTIL_E9011, "File %s, %s", logfilename,
118  strerror(errno));
119  return -1;
120  }
121  } else {
122  fp = NULL;
123  }
124  newent->fp = fp;
125  /* mark */
126  useful_logent[newent_idx] = 1;
127  return newent_idx + 1;
128 }
129 
130 int HECMW_closelog(int id) {
131  struct log_ent *p;
132 
133  if (id <= 0 || id > HECMW_LOG_MAX) {
134  HECMW_set_error(HECMW_UTIL_E9013, "No such log file");
135  return -1;
136  }
137 
138  p = (struct log_ent *)&logent[id];
139  if (p->fp == NULL) {
140  if (fclose(p->fp)) {
141  HECMW_set_error(HECMW_UTIL_E9013, "File %s, %s", p->file,
142  strerror(errno));
143  return -1;
144  }
145  }
146  memset(p, 0, sizeof(*p));
147  useful_logent[id] = 0;
148 
149  return 0;
150 }
151 
152 static void output_log(int loglv, const char *fmt, va_list ap, FILE *fp) {
153  int i, len;
154  char p[HECMW_MSG_LEN + 1];
155  char buf[HECMW_LINE_MAX + 1];
156 
157  HECMW_assert(fp);
158 
159  /* date */
160  if (HECMW_get_date_r(p, HECMW_MSG_LEN) == NULL) {
161  strncpy(p, "Could not get date", HECMW_MSG_LEN);
162  }
163  strcpy(buf, p);
164 
165 #ifndef HECMW_SERIAL
166  {
167  /* rank and num_procs */
168  int num_procs = HECMW_comm_get_size();
169  int my_rank = HECMW_comm_get_rank();
170  if (num_procs > 1) {
171  len = strlen(buf);
172  HECMW_snprintf(buf + len, sizeof(buf) - len, " PE[%d/%d]", my_rank,
173  num_procs);
174  }
175  }
176 #endif
177 
178 #ifdef _OPENMP
179  {
180  /* thread ID and num_threads */
181  int thread_num = omp_get_thread_num();
182  int num_threads = omp_get_num_threads();
183  if (num_threads > 1) {
184  len = strlen(buf);
185  HECMW_snprintf(buf + len, sizeof(buf) - len, " TH(%d/%d)", thread_num,
186  num_threads);
187  }
188  }
189 #endif
190 
191  /* log level */
192  for (i = 0; i < sizeof(hecmw_loglv_table) / sizeof(hecmw_loglv_table[0]);
193  i++) {
194  if (hecmw_loglv_table[i].loglv == loglv) {
195  strncpy(p, hecmw_loglv_table[i].str, HECMW_MSG_LEN);
196  break;
197  }
198  }
199  len = strlen(buf);
200  HECMW_snprintf(buf + len, sizeof(buf) - len, " %s: ", p);
201 
202  /* message body */
203  len = strlen(buf);
204  if (fmt == NULL) {
205  HECMW_snprintf(buf + len, sizeof(buf) - len, "\n");
206 
207  } else {
208  HECMW_vsnprintf(buf + len, sizeof(buf) - len, fmt, ap); /* message body */
209 
210  /* add '\n' if needed */
211  len = strlen(buf);
212  if ((len > 0 && buf[len - 1] != '\n') || len == 0) {
213  HECMW_snprintf(buf + len, sizeof(buf) - len, "\n");
214  }
215  }
216 
217  /* output */
218  fputs(buf, fp);
219 
220  fflush(fp);
221 }
222 
223 int HECMW_vlog(int loglv, const char *fmt, va_list ap) {
224  int i, is_output;
225 
226  if (!enable_by_rank) return 0;
227  if (check_loglv(loglv)) {
228  HECMW_set_error(HECMW_UTIL_E9012, "Invalid log level");
229  return -1;
230  }
231 
232  if (!(loglv & loglevels)) return 0;
233 
234  is_output = 0;
235  for (i = 0; i < HECMW_LOG_MAX; i++) {
236  struct log_ent *p = &logent[i];
237  if (!useful_logent[i]) continue;
238  if (loglv & loglevels & p->lv) {
239  if (p->fp == NULL) {
240  if ((p->fp = fopen(p->file, "a")) == NULL) {
241  HECMW_set_error(HECMW_UTIL_E9011, "File %s, %s", p->file,
242  strerror(errno));
243  return -1;
244  }
245  }
246  output_log(loglv, fmt, ap, p->fp);
247  if (p->opt & HECMW_LOG_PERROR) {
248  output_log(loglv, fmt, ap, stderr);
249  }
250  is_output = 1;
251  }
252  }
253  if (!is_output) {
254  output_log(loglv, fmt, ap, stderr);
255  }
256 
257  return 0;
258 }
259 
260 int HECMW_log(int loglv, const char *fmt, ...) {
261  int rc;
262  va_list ap;
263  va_start(ap, fmt);
264  rc = HECMW_vlog(loglv, fmt, ap);
265  va_end(ap);
266  return rc;
267 }
268 
269 void HECMW_log_set_enable(int from, int to, int true_or_false) {
270  if (from > to) return;
271  if (from <= HECMW_comm_get_rank() && HECMW_comm_get_rank() <= to) {
272  enable_by_rank = (true_or_false) ? 1 : 0;
273  }
274 }
275 
276 void hecmw_log_if(int *loglv, char *msg, int len) {
277  char s[HECMW_MSG_LEN + 1];
278 
279  if (len > HECMW_MSG_LEN) {
280  len = HECMW_MSG_LEN;
281  }
282 
283  if (HECMW_strcpy_f2c_r(msg, len, s, sizeof(s)) == NULL) return;
284  HECMW_log(*loglv, s);
285 }
286 
287 void hecmw_log_if_(int *loglv, char *msg, int len) {
288  hecmw_log_if(loglv, msg, len);
289 }
290 
291 void hecmw_log_if__(int *loglv, char *msg, int len) {
292  hecmw_log_if(loglv, msg, len);
293 }
294 
295 void HECMW_LOG_IF(int *loglv, char *msg, int len) {
296  hecmw_log_if(loglv, msg, len);
297 }
298 
299 /*----------------------------------------------------------------------------*/
300 
301 void hecmw_setloglv_if(int *loglv) { HECMW_setloglv(*loglv); }
302 
303 void hecmw_setloglv_if_(int *loglv) { hecmw_setloglv_if(loglv); }
304 
305 void hecmw_setloglv_if__(int *loglv) { hecmw_setloglv_if(loglv); }
306 
307 void HECMW_SETLOGLV_IF(int *loglv) { hecmw_setloglv_if(loglv); }
308 
309 /*----------------------------------------------------------------------------*/
310 
311 void hecmw_log_set_enable_if(int *from, int *to, int *true_or_false) {
312  HECMW_log_set_enable(*from, *to, *true_or_false);
313 }
314 
315 void hecmw_log_set_enable_if_(int *from, int *to, int *true_or_false) {
316  hecmw_log_set_enable_if(from, to, true_or_false);
317 }
318 
319 void hecmw_log_set_enable_if__(int *from, int *to, int *true_or_false) {
320  hecmw_log_set_enable_if(from, to, true_or_false);
321 }
322 
323 void HECMW_LOG_SET_ENABLE_IF(int *from, int *to, int *true_or_false) {
324  hecmw_log_set_enable_if(from, to, true_or_false);
325 }
326 
327 /*----------------------------------------------------------------------------*/
328 
329 void hecmw_openlog_if(char *logfile, int *loglv, int *options, int *id,
330  int *ierror, int len) {
331  char buf[HECMW_NAME_LEN + 1];
332  if (HECMW_strcpy_f2c_r(logfile, len, buf, sizeof(buf)) == NULL) {
333  *ierror = 1;
334  return;
335  }
336  if ((*id = HECMW_openlog(buf, *loglv, *options)) == -1) {
337  *ierror = 1;
338  return;
339  }
340  *ierror = 0;
341 }
342 
343 void hecmw_openlog_if_(char *logfile, int *loglv, int *options, int *id,
344  int *ierror, int len) {
345  hecmw_openlog_if(logfile, loglv, options, id, ierror, len);
346 }
347 
348 void hecmw_openlog_if__(char *logfile, int *loglv, int *options, int *id,
349  int *ierror, int len) {
350  hecmw_openlog_if(logfile, loglv, options, id, ierror, len);
351 }
352 
353 void HECMW_OPENLOG_IF(char *logfile, int *loglv, int *options, int *id,
354  int *ierror, int len) {
355  hecmw_openlog_if(logfile, loglv, options, id, ierror, len);
356 }
357 
358 /*----------------------------------------------------------------------------*/
359 
360 void hecmw_closelog_if(int *id, int *ierror) {
361  if (HECMW_closelog(*id)) {
362  *ierror = 1;
363  return;
364  }
365  *ierror = 0;
366 }
367 
368 void hecmw_closelog_if_(int *id, int *ierror) { hecmw_closelog_if(id, ierror); }
369 
370 void hecmw_closelog_if__(int *id, int *ierror) {
371  hecmw_closelog_if(id, ierror);
372 }
373 
374 void HECMW_CLOSELOG_IF(int *id, int *ierror) { hecmw_closelog_if(id, ierror); }
HECMW_LOG_WARN
#define HECMW_LOG_WARN
Definition: hecmw_log.h:17
HECMW_CLOSELOG_IF
void HECMW_CLOSELOG_IF(int *id, int *ierror)
Definition: hecmw_log.c:374
hecmw_setloglv_if_
void hecmw_setloglv_if_(int *loglv)
Definition: hecmw_log.c:303
HECMW_LOG_ALL
#define HECMW_LOG_ALL
Definition: hecmw_log.h:23
hecmw_openlog_if__
void hecmw_openlog_if__(char *logfile, int *loglv, int *options, int *id, int *ierror, int len)
Definition: hecmw_log.c:348
HECMW_snprintf
int HECMW_snprintf(char *str, size_t size, const char *format,...)
Definition: hecmw_util.c:153
HECMW_LOG_DEBUG
#define HECMW_LOG_DEBUG
Definition: hecmw_log.h:21
hecmw_log_if__
void hecmw_log_if__(int *loglv, char *msg, int len)
Definition: hecmw_log.c:291
HECMW_log
int HECMW_log(int loglv, const char *fmt,...)
Definition: hecmw_log.c:260
HECMW_log_set_enable
void HECMW_log_set_enable(int from, int to, int true_or_false)
Definition: hecmw_log.c:269
HECMW_comm_get_size
int HECMW_comm_get_size(void)
Definition: hecmw_comm.c:703
log_ent
Definition: hecmw_log.c:33
HECMW_UTIL_E9012
#define HECMW_UTIL_E9012
Definition: hecmw_msgno.h:377
HECMW_vlog
int HECMW_vlog(int loglv, const char *fmt, va_list ap)
Definition: hecmw_log.c:223
hecmw_log_set_enable_if
void hecmw_log_set_enable_if(int *from, int *to, int *true_or_false)
Definition: hecmw_log.c:311
hecmw_log_set_enable_if__
void hecmw_log_set_enable_if__(int *from, int *to, int *true_or_false)
Definition: hecmw_log.c:319
HECMW_comm_get_rank
int HECMW_comm_get_rank(void)
Definition: hecmw_comm.c:707
HECMW_openlog
int HECMW_openlog(const char *logfile, int loglv, int options)
Definition: hecmw_log.c:64
hecmw_closelog_if
void hecmw_closelog_if(int *id, int *ierror)
Definition: hecmw_log.c:360
HECMW_get_date_r
char * HECMW_get_date_r(char *buf, int len)
Definition: hecmw_util.c:41
hecmw_setloglv_if
void hecmw_setloglv_if(int *loglv)
Definition: hecmw_log.c:301
HECMW_LOG_OPTALL
#define HECMW_LOG_OPTALL
Definition: hecmw_log.h:28
HECMW_LOG_IF
void HECMW_LOG_IF(int *loglv, char *msg, int len)
Definition: hecmw_log.c:295
hecmw_log_if_
void hecmw_log_if_(int *loglv, char *msg, int len)
Definition: hecmw_log.c:287
USEFUL_LOGLVS
#define USEFUL_LOGLVS(lv)
Definition: hecmw_log.c:21
hecmw_log.h
HECMW_SETLOGLV_IF
void HECMW_SETLOGLV_IF(int *loglv)
Definition: hecmw_log.c:307
HECMW_UTIL_E9013
#define HECMW_UTIL_E9013
Definition: hecmw_msgno.h:378
HECMW_vsnprintf
int HECMW_vsnprintf(char *str, size_t size, const char *format, va_list ap)
Definition: hecmw_util.c:145
HECMW_LOG_ERROR
#define HECMW_LOG_ERROR
Definition: hecmw_log.h:15
HECMW_NAME_LEN
#define HECMW_NAME_LEN
Definition: hecmw_config.h:70
hecmw_config.h
hecmw_openlog_if_
void hecmw_openlog_if_(char *logfile, int *loglv, int *options, int *id, int *ierror, int len)
Definition: hecmw_log.c:343
hecmw_log_set_enable_if_
void hecmw_log_set_enable_if_(int *from, int *to, int *true_or_false)
Definition: hecmw_log.c:315
HECMW_LOG_PERROR
#define HECMW_LOG_PERROR
Definition: hecmw_log.h:26
HECMW_LOG_MAX
#define HECMW_LOG_MAX
Definition: hecmw_log.h:11
log_ent::lv
int lv
Definition: hecmw_log.c:36
HECMW_OPENLOG_IF
void HECMW_OPENLOG_IF(char *logfile, int *loglv, int *options, int *id, int *ierror, int len)
Definition: hecmw_log.c:353
HECMW_closelog
int HECMW_closelog(int id)
Definition: hecmw_log.c:130
log_ent::fp
FILE * fp
Definition: hecmw_log.c:34
HECMW_LOG_INFO
#define HECMW_LOG_INFO
Definition: hecmw_log.h:19
hecmw_log_if
void hecmw_log_if(int *loglv, char *msg, int len)
Definition: hecmw_log.c:276
log_ent::opt
int opt
Definition: hecmw_log.c:37
hecmw_setloglv_if__
void hecmw_setloglv_if__(int *loglv)
Definition: hecmw_log.c:305
HECMW_strcpy_f2c_r
char * HECMW_strcpy_f2c_r(const char *fstr, int flen, char *buf, int bufsize)
Definition: hecmw_lib_fc.c:45
HECMW_set_error
int HECMW_set_error(int errorno, const char *fmt,...)
Definition: hecmw_error.c:37
hecmw_openlog_if
void hecmw_openlog_if(char *logfile, int *loglv, int *options, int *id, int *ierror, int len)
Definition: hecmw_log.c:329
HECMW_LINE_MAX
#define HECMW_LINE_MAX
Definition: hecmw_log.c:19
HECMW_setloglv
void HECMW_setloglv(int loglv)
Definition: hecmw_log.c:57
NULL
#define NULL
Definition: hecmw_io_nastran.c:30
HECMW_assert
#define HECMW_assert(cond)
Definition: hecmw_util.h:40
HECMW_FILENAME_LEN
#define HECMW_FILENAME_LEN
Definition: hecmw_config.h:72
options
struct option_rec options[]
specify command line option name and executing function name.
Definition: main.c:273
hecmw_closelog_if_
void hecmw_closelog_if_(int *id, int *ierror)
Definition: hecmw_log.c:368
HECMW_LOG_SET_ENABLE_IF
void HECMW_LOG_SET_ENABLE_IF(int *from, int *to, int *true_or_false)
Definition: hecmw_log.c:323
HECMW_LOG_NONE
#define HECMW_LOG_NONE
Definition: hecmw_log.h:13
log_ent::file
char file[HECMW_FILENAME_LEN+1]
Definition: hecmw_log.c:35
hecmw_util.h
HECMW_MSG_LEN
#define HECMW_MSG_LEN
Definition: hecmw_config.h:74
HECMW_UTIL_E9011
#define HECMW_UTIL_E9011
Definition: hecmw_msgno.h:376
hecmw_closelog_if__
void hecmw_closelog_if__(int *id, int *ierror)
Definition: hecmw_log.c:370