FrontISTR 5.2.0
Large-scale structural analysis program with finit element method
Loading...
Searching...
No Matches
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
23static 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
33struct log_ent {
34 FILE *fp;
36 int lv;
37 int opt;
38};
39
40static struct log_ent logent[HECMW_LOG_MAX];
41
42static int useful_logent[HECMW_LOG_MAX];
43
44static int loglevels = USEFUL_LOGLVS(HECMW_LOG_INFO);
45
46static int enable_by_rank = 1;
47
48static 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
57void HECMW_setloglv(int loglv) {
58 if (loglv != HECMW_LOG_NONE && check_loglv(loglv)) {
59 return;
60 }
61 loglevels = USEFUL_LOGLVS(loglv);
62}
63
64int 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
130int 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
152static 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
158
159 /* date */
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
223int 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
260int 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
269void 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
276void 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
287void hecmw_log_if_(int *loglv, char *msg, int len) {
288 hecmw_log_if(loglv, msg, len);
289}
290
291void hecmw_log_if__(int *loglv, char *msg, int len) {
292 hecmw_log_if(loglv, msg, len);
293}
294
295void HECMW_LOG_IF(int *loglv, char *msg, int len) {
296 hecmw_log_if(loglv, msg, len);
297}
298
299/*----------------------------------------------------------------------------*/
300
301void hecmw_setloglv_if(int *loglv) { HECMW_setloglv(*loglv); }
302
303void hecmw_setloglv_if_(int *loglv) { hecmw_setloglv_if(loglv); }
304
305void hecmw_setloglv_if__(int *loglv) { hecmw_setloglv_if(loglv); }
306
307void HECMW_SETLOGLV_IF(int *loglv) { hecmw_setloglv_if(loglv); }
308
309/*----------------------------------------------------------------------------*/
310
311void 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
315void 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
319void 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
323void 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
329void 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
343void 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
348void 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
353void 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
360void hecmw_closelog_if(int *id, int *ierror) {
361 if (HECMW_closelog(*id)) {
362 *ierror = 1;
363 return;
364 }
365 *ierror = 0;
366}
367
368void hecmw_closelog_if_(int *id, int *ierror) { hecmw_closelog_if(id, ierror); }
369
370void hecmw_closelog_if__(int *id, int *ierror) {
371 hecmw_closelog_if(id, ierror);
372}
373
374void HECMW_CLOSELOG_IF(int *id, int *ierror) { hecmw_closelog_if(id, ierror); }
int HECMW_comm_get_rank(void)
Definition: hecmw_comm.c:707
int HECMW_comm_get_size(void)
Definition: hecmw_comm.c:703
#define HECMW_FILENAME_LEN
Definition: hecmw_config.h:72
#define HECMW_MSG_LEN
Definition: hecmw_config.h:74
#define HECMW_NAME_LEN
Definition: hecmw_config.h:70
int HECMW_set_error(int errorno, const char *fmt,...)
Definition: hecmw_error.c:37
#define NULL
char * HECMW_strcpy_f2c_r(const char *fstr, int flen, char *buf, int bufsize)
Definition: hecmw_lib_fc.c:45
void HECMW_log_set_enable(int from, int to, int true_or_false)
Definition: hecmw_log.c:269
void hecmw_log_if__(int *loglv, char *msg, int len)
Definition: hecmw_log.c:291
void hecmw_log_if_(int *loglv, char *msg, int len)
Definition: hecmw_log.c:287
int HECMW_openlog(const char *logfile, int loglv, int options)
Definition: hecmw_log.c:64
#define HECMW_LINE_MAX
Definition: hecmw_log.c:19
void HECMW_setloglv(int loglv)
Definition: hecmw_log.c:57
void hecmw_log_if(int *loglv, char *msg, int len)
Definition: hecmw_log.c:276
void HECMW_SETLOGLV_IF(int *loglv)
Definition: hecmw_log.c:307
void hecmw_openlog_if(char *logfile, int *loglv, int *options, int *id, int *ierror, int len)
Definition: hecmw_log.c:329
#define USEFUL_LOGLVS(lv)
Definition: hecmw_log.c:21
void hecmw_closelog_if(int *id, int *ierror)
Definition: hecmw_log.c:360
int HECMW_closelog(int id)
Definition: hecmw_log.c:130
void hecmw_setloglv_if(int *loglv)
Definition: hecmw_log.c:301
void hecmw_setloglv_if_(int *loglv)
Definition: hecmw_log.c:303
void HECMW_CLOSELOG_IF(int *id, int *ierror)
Definition: hecmw_log.c:374
void HECMW_LOG_IF(int *loglv, char *msg, int len)
Definition: hecmw_log.c:295
void hecmw_closelog_if_(int *id, int *ierror)
Definition: hecmw_log.c:368
int HECMW_vlog(int loglv, const char *fmt, va_list ap)
Definition: hecmw_log.c:223
void hecmw_setloglv_if__(int *loglv)
Definition: hecmw_log.c:305
int HECMW_log(int loglv, const char *fmt,...)
Definition: hecmw_log.c:260
void hecmw_openlog_if_(char *logfile, int *loglv, int *options, int *id, int *ierror, int len)
Definition: hecmw_log.c:343
void hecmw_openlog_if__(char *logfile, int *loglv, int *options, int *id, int *ierror, int len)
Definition: hecmw_log.c:348
void hecmw_log_set_enable_if_(int *from, int *to, int *true_or_false)
Definition: hecmw_log.c:315
void hecmw_log_set_enable_if__(int *from, int *to, int *true_or_false)
Definition: hecmw_log.c:319
void HECMW_LOG_SET_ENABLE_IF(int *from, int *to, int *true_or_false)
Definition: hecmw_log.c:323
void HECMW_OPENLOG_IF(char *logfile, int *loglv, int *options, int *id, int *ierror, int len)
Definition: hecmw_log.c:353
void hecmw_closelog_if__(int *id, int *ierror)
Definition: hecmw_log.c:370
void hecmw_log_set_enable_if(int *from, int *to, int *true_or_false)
Definition: hecmw_log.c:311
#define HECMW_LOG_ERROR
Definition: hecmw_log.h:15
#define HECMW_LOG_ALL
Definition: hecmw_log.h:23
#define HECMW_LOG_OPTALL
Definition: hecmw_log.h:28
#define HECMW_LOG_MAX
Definition: hecmw_log.h:11
#define HECMW_LOG_WARN
Definition: hecmw_log.h:17
#define HECMW_LOG_DEBUG
Definition: hecmw_log.h:21
#define HECMW_LOG_INFO
Definition: hecmw_log.h:19
#define HECMW_LOG_NONE
Definition: hecmw_log.h:13
#define HECMW_LOG_PERROR
Definition: hecmw_log.h:26
#define HECMW_UTIL_E9011
Definition: hecmw_msgno.h:371
#define HECMW_UTIL_E9013
Definition: hecmw_msgno.h:373
#define HECMW_UTIL_E9012
Definition: hecmw_msgno.h:372
char * HECMW_get_date_r(char *buf, int len)
Definition: hecmw_util.c:41
int HECMW_snprintf(char *str, size_t size, const char *format,...)
Definition: hecmw_util.c:153
int HECMW_vsnprintf(char *str, size_t size, const char *format, va_list ap)
Definition: hecmw_util.c:145
#define HECMW_assert(cond)
Definition: hecmw_util.h:40
struct option_rec options[]
specify command line option name and executing function name. \attension list must be terminated with...
Definition: main.c:187
int lv
Definition: hecmw_log.c:36
int opt
Definition: hecmw_log.c:37
char file[HECMW_FILENAME_LEN+1]
Definition: hecmw_log.c:35
FILE * fp
Definition: hecmw_log.c:34