corosync  3.1.6
logsys.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2002-2004 MontaVista Software, Inc.
3  * Copyright (c) 2006-2012 Red Hat, Inc.
4  *
5  * Author: Steven Dake (sdake@redhat.com)
6  * Author: Lon Hohberger (lhh@redhat.com)
7  * Author: Fabio M. Di Nitto (fdinitto@redhat.com)
8  *
9  * All rights reserved.
10  *
11  * This software licensed under BSD license, the text of which follows:
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions are met:
15  *
16  * - Redistributions of source code must retain the above copyright notice,
17  * this list of conditions and the following disclaimer.
18  * - Redistributions in binary form must reproduce the above copyright notice,
19  * this list of conditions and the following disclaimer in the documentation
20  * and/or other materials provided with the distribution.
21  * - Neither the name of the MontaVista Software, Inc. nor the names of its
22  * contributors may be used to endorse or promote products derived from this
23  * software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35  * THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #include <config.h>
39 
40 #include <stdint.h>
41 #include <ctype.h>
42 #include <assert.h>
43 #include <stdio.h>
44 #include <string.h>
45 
46 #include <qb/qbdefs.h>
47 #include <qb/qbutil.h>
48 #include <qb/qblog.h>
49 
50 #include <corosync/logsys.h>
51 
52 /*
53  * syslog prioritynames, facility names to value mapping
54  * Some C libraries build this in to their headers, but it is non-portable
55  * so logsys supplies its own version.
56  */
57 struct syslog_names {
58  const char *c_name;
59  int c_val;
60 };
61 
62 static struct syslog_names prioritynames[] =
63 {
64  { "alert", LOG_ALERT },
65  { "crit", LOG_CRIT },
66  { "debug", LOG_DEBUG },
67  { "emerg", LOG_EMERG },
68  { "err", LOG_ERR },
69  { "error", LOG_ERR },
70  { "info", LOG_INFO },
71  { "notice", LOG_NOTICE },
72  { "warning", LOG_WARNING },
73  { NULL, -1 }
74 };
75 
76 #define MAX_FILES_PER_SUBSYS 32
77 #ifdef HAVE_SMALL_MEMORY_FOOTPRINT
78 #define IPC_LOGSYS_SIZE 8192*64
79 #else
80 #define IPC_LOGSYS_SIZE 8192*1024
81 #endif
82 
83 /*
84  * need unlogical order to preserve 64bit alignment
85  */
86 struct logsys_logger {
87  char subsys[LOGSYS_MAX_SUBSYS_NAMELEN]; /* subsystem name */
88  char *logfile; /* log to file */
89  unsigned int mode; /* subsystem mode */
90  unsigned int debug; /* debug on|off|trace */
91  int syslog_priority; /* priority */
92  int logfile_priority; /* priority to file */
93  int init_status; /* internal field to handle init queues
94  for subsystems */
95  int32_t target_id;
97  int32_t file_idx;
98  int32_t dirty;
99 };
100 
101 /* values for logsys_logger init_status */
102 #define LOGSYS_LOGGER_INIT_DONE 0
103 #define LOGSYS_LOGGER_NEEDS_INIT 1
104 
105 static int logsys_system_needs_init = LOGSYS_LOGGER_NEEDS_INIT;
106 
107 static struct logsys_logger logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT + 1];
108 
109 static pthread_mutex_t logsys_config_mutex = PTHREAD_MUTEX_INITIALIZER;
110 
111 static int32_t _logsys_config_mode_set_unlocked(int32_t subsysid, uint32_t new_mode);
112 static void _logsys_config_apply_per_file(int32_t s, const char *filename);
113 static void _logsys_config_apply_per_subsys(int32_t s);
114 static void _logsys_subsys_filename_add (int32_t s, const char *filename);
115 static void logsys_file_format_get(char* file_format, int buf_len);
116 
117 static char *format_buffer=NULL;
118 
119 static int logsys_thread_started = 0;
120 
121 static int logsys_blackbox_enabled = 1;
122 
123 static int _logsys_config_subsys_get_unlocked (const char *subsys)
124 {
125  unsigned int i;
126 
127  if (!subsys) {
129  }
130 
131  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
132  if (strcmp (logsys_loggers[i].subsys, subsys) == 0) {
133  return i;
134  }
135  }
136 
137  return (-1);
138 }
139 
140 
141 /*
142  * we need a version that can work when somebody else is already
143  * holding a config mutex lock or we will never get out of here
144  */
145 static int logsys_config_file_set_unlocked (
146  int subsysid,
147  const char **error_string,
148  const char *file)
149 {
150  static char error_string_response[512];
151  int i;
152  char file_format[128];
153 
154  if (logsys_loggers[subsysid].target_id > 0) {
155  int32_t f;
156  for (f = 0; f < logsys_loggers[subsysid].file_idx; f++) {
157  qb_log_filter_ctl(logsys_loggers[subsysid].target_id,
158  QB_LOG_FILTER_REMOVE,
159  QB_LOG_FILTER_FILE,
160  logsys_loggers[subsysid].files[f],
161  LOG_TRACE);
162  }
163  }
164 
165  logsys_loggers[subsysid].dirty = QB_TRUE;
166  if (file == NULL) {
167  return (0);
168  }
169 
170  if (logsys_loggers[subsysid].target_id > 0 &&
171  logsys_loggers[subsysid].logfile != NULL &&
172  strcmp(file, logsys_loggers[subsysid].logfile) == 0) {
173  return (0);
174  }
175 
176  if (strlen(file) >= PATH_MAX) {
177  snprintf (error_string_response,
178  sizeof(error_string_response),
179  "%s: logfile name exceed maximum system filename length",
180  logsys_loggers[subsysid].subsys);
181  *error_string = error_string_response;
182  return (-1);
183  }
184 
185  if (logsys_loggers[subsysid].logfile != NULL) {
186  free(logsys_loggers[subsysid].logfile);
187  logsys_loggers[subsysid].logfile = NULL;
188  }
189 
190  logsys_loggers[subsysid].logfile = strdup(file);
191 
192  if (logsys_loggers[subsysid].logfile == NULL) {
193  snprintf (error_string_response,
194  sizeof(error_string_response),
195  "Unable to allocate memory for logfile '%s'",
196  file);
197  *error_string = error_string_response;
198  return (-1);
199  }
200 
201  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
202  if ((logsys_loggers[i].logfile != NULL) &&
203  (strcmp (logsys_loggers[i].logfile, file) == 0) &&
204  (i != subsysid)) {
205  /* we have found another subsys with this config file
206  * so add a filter
207  */
208  logsys_loggers[subsysid].target_id = logsys_loggers[i].target_id;
209  return (0);
210  }
211  }
212 
213  if (logsys_loggers[subsysid].target_id > 0) {
214  int num_using_current = 0;
215  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
216  if (logsys_loggers[subsysid].target_id ==
217  logsys_loggers[i].target_id) {
218  num_using_current++;
219  }
220  }
221  if (num_using_current == 1) {
222  /* no one else is using this close it */
223  qb_log_file_close(logsys_loggers[subsysid].target_id);
224  }
225  }
226 
227  logsys_loggers[subsysid].target_id = qb_log_file_open(file);
228  if (logsys_loggers[subsysid].target_id < 0) {
229  int err = -logsys_loggers[subsysid].target_id;
230  char error_str[LOGSYS_MAX_PERROR_MSG_LEN];
231  const char *error_ptr;
232  error_ptr = qb_strerror_r(err, error_str, sizeof(error_str));
233 
234  free(logsys_loggers[subsysid].logfile);
235  logsys_loggers[subsysid].logfile = NULL;
236  snprintf (error_string_response,
237  sizeof(error_string_response),
238  "Can't open logfile '%s' for reason: %s (%d)",
239  file, error_ptr, err);
240  *error_string = error_string_response;
241  return (-1);
242  }
243  logsys_file_format_get(file_format, 128);
244  qb_log_format_set(logsys_loggers[subsysid].target_id, file_format);
245 
246  qb_log_ctl(logsys_loggers[subsysid].target_id,
247  QB_LOG_CONF_ENABLED,
248  (logsys_loggers[subsysid].mode & LOGSYS_MODE_OUTPUT_FILE));
249  if (logsys_thread_started) {
250  qb_log_ctl(logsys_loggers[subsysid].target_id, QB_LOG_CONF_THREADED, QB_TRUE);
251  }
252 
253  return (0);
254 }
255 
256 static void logsys_subsys_init (
257  const char *subsys,
258  int subsysid)
259 {
260  if (logsys_system_needs_init == LOGSYS_LOGGER_NEEDS_INIT) {
261  logsys_loggers[subsysid].init_status =
263  } else {
264  logsys_loggers[subsysid].mode = logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode;
265  logsys_loggers[subsysid].debug = logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].debug;
266  logsys_loggers[subsysid].syslog_priority = logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].syslog_priority;
267  logsys_loggers[subsysid].logfile_priority = logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].logfile_priority;
268  logsys_loggers[subsysid].init_status = LOGSYS_LOGGER_INIT_DONE;
269  }
270  strncpy (logsys_loggers[subsysid].subsys, subsys,
271  sizeof (logsys_loggers[subsysid].subsys));
272  logsys_loggers[subsysid].subsys[
273  sizeof (logsys_loggers[subsysid].subsys) - 1] = '\0';
274  logsys_loggers[subsysid].file_idx = 0;
275 }
276 
277 static const char *_logsys_tags_stringify(uint32_t tags)
278 {
279  if (tags == QB_LOG_TAG_LIBQB_MSG) {
280  return "QB";
281  } else {
282  return logsys_loggers[tags].subsys;
283  }
284 }
285 
287 {
288  int i;
289  int f;
290  for (i = 0; i < LOGSYS_MAX_SUBSYS_COUNT; i++) {
291  free(logsys_loggers[i].logfile);
292  for (f = 0; f < logsys_loggers[i].file_idx; f++) {
293  free(logsys_loggers[i].files[f]);
294  }
295  }
296 
297  qb_log_fini ();
298 }
299 
300 /*
301  * Internal API - exported
302  */
303 
305  const char *mainsystem,
306  unsigned int mode,
307  int syslog_facility,
308  int syslog_priority)
309 {
310  int i;
311  int32_t fidx;
312  char tempsubsys[LOGSYS_MAX_SUBSYS_NAMELEN];
313 
314  if ((mainsystem == NULL) ||
315  (strlen(mainsystem) >= LOGSYS_MAX_SUBSYS_NAMELEN)) {
316  return -1;
317  }
318 
319  /*
320  * Setup libqb as a subsys
321  */
322  i = _logsys_subsys_create ("QB", "array.c,log.c,log_syslog.c,log_blackbox.c,log_format.c,"
323  "log_file.c,log_dcs.c,log_thread.c,ipc_shm.c,ipcs.c,ipc_us.c,loop.c,"
324  "loop_poll_epoll.c,loop_job.c,loop_poll_poll.c,loop_poll_kqueue.c,"
325  "loop_timerlist.c,loop_poll.c,ringbuffer.c,ringbuffer_helper.c,trie.c,"
326  "map.c,skiplist.c,rpl_sem.c,hdb.c,unix.c,hashtable.c,strlcpy.c,ipc_socket.c,"
327  "strchrnul.c,ipc_setup.c,strlcat.c");
328  if (i < 0) {
329  return -1;
330  }
331 
332  /*
333  * name clash
334  * _logsys_subsys_filename_add (i, "util.c");
335  */
336 
337  /*
338  * This file (logsys.c) is not exactly QB. We need tag for logsys.c if flightrecorder init
339  * fails, and QB seems to be closest.
340  */
341  _logsys_subsys_filename_add (i, "logsys.c");
342 
344 
345  pthread_mutex_lock (&logsys_config_mutex);
346 
347  snprintf(logsys_loggers[i].subsys,
349  "%s", mainsystem);
350 
351  logsys_loggers[i].mode = mode;
352  logsys_loggers[i].debug = LOGSYS_DEBUG_OFF;
353  logsys_loggers[i].file_idx = 0;
354  logsys_loggers[i].logfile_priority = syslog_priority;
355  logsys_loggers[i].syslog_priority = syslog_priority;
356 
357  qb_log_init(mainsystem, syslog_facility, syslog_priority);
358  if (logsys_loggers[i].mode & LOGSYS_MODE_OUTPUT_STDERR) {
359  qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
360  } else {
361  qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_FALSE);
362  }
363  if (logsys_loggers[i].mode & LOGSYS_MODE_OUTPUT_SYSLOG) {
364  qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
365  } else {
366  qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
367  }
368  qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_PRIORITY_BUMP, LOG_INFO - LOG_DEBUG);
369 
370  qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
371  QB_LOG_FILTER_FILE, "*", LOG_TRACE);
372  qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, IPC_LOGSYS_SIZE);
373  qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_THREADED, QB_FALSE);
374 
375  /*
376  * Blackbox is disabled at the init and enabled later based
377  * on config (logging.blackbox) value.
378  */
379  qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
380 
381  if (logsys_format_set(NULL) == -1) {
382  pthread_mutex_unlock (&logsys_config_mutex);
383 
384  return -1;
385  }
386 
387  qb_log_tags_stringify_fn_set(_logsys_tags_stringify);
388 
389  logsys_loggers[i].init_status = LOGSYS_LOGGER_INIT_DONE;
390  logsys_system_needs_init = LOGSYS_LOGGER_INIT_DONE;
391 
392  for (i = 0; i < LOGSYS_MAX_SUBSYS_COUNT; i++) {
393  if ((strcmp (logsys_loggers[i].subsys, "") != 0) &&
394  (logsys_loggers[i].init_status ==
396  fidx = logsys_loggers[i].file_idx;
397  strncpy (tempsubsys, logsys_loggers[i].subsys,
398  sizeof (tempsubsys));
399  tempsubsys[sizeof (tempsubsys) - 1] = '\0';
400  logsys_subsys_init(tempsubsys, i);
401  logsys_loggers[i].file_idx = fidx;
402  _logsys_config_mode_set_unlocked(i, logsys_loggers[i].mode);
403  _logsys_config_apply_per_subsys(i);
404  }
405  }
406 
407  pthread_mutex_unlock (&logsys_config_mutex);
408 
409  return (0);
410 }
411 
412 
413 static void _logsys_subsys_filename_add (int32_t s, const char *filename)
414 {
415  int i;
416 
417  if (filename == NULL) {
418  return;
419  }
420  assert(logsys_loggers[s].file_idx < MAX_FILES_PER_SUBSYS);
421  assert(logsys_loggers[s].file_idx >= 0);
422 
423  for (i = 0; i < logsys_loggers[s].file_idx; i++) {
424  if (strcmp(logsys_loggers[s].files[i], filename) == 0) {
425  return;
426  }
427  }
428  logsys_loggers[s].files[logsys_loggers[s].file_idx++] = strdup(filename);
429 
430  if (logsys_system_needs_init == LOGSYS_LOGGER_INIT_DONE) {
431  _logsys_config_apply_per_file(s, filename);
432  }
433 }
434 
435 int _logsys_subsys_create (const char *subsys, const char *filename)
436 {
437  int i;
438 
439  if ((subsys == NULL) ||
440  (strlen(subsys) >= LOGSYS_MAX_SUBSYS_NAMELEN)) {
441  return -1;
442  }
443 
444  pthread_mutex_lock (&logsys_config_mutex);
445 
446  i = _logsys_config_subsys_get_unlocked (subsys);
447  if ((i > -1) && (i < LOGSYS_MAX_SUBSYS_COUNT)) {
448  _logsys_subsys_filename_add(i, filename);
449  pthread_mutex_unlock (&logsys_config_mutex);
450  return i;
451  }
452 
453  for (i = 0; i < LOGSYS_MAX_SUBSYS_COUNT; i++) {
454  if (strcmp (logsys_loggers[i].subsys, "") == 0) {
455  logsys_subsys_init(subsys, i);
456  _logsys_subsys_filename_add(i, filename);
457  break;
458  }
459  }
460 
461  if (i >= LOGSYS_MAX_SUBSYS_COUNT) {
462  i = -1;
463  }
464 
465  pthread_mutex_unlock (&logsys_config_mutex);
466  return i;
467 }
468 
470 {
471  unsigned int i;
472 
473  pthread_mutex_lock (&logsys_config_mutex);
474 
475  i = _logsys_config_subsys_get_unlocked (subsys);
476 
477  pthread_mutex_unlock (&logsys_config_mutex);
478 
479  return i;
480 }
481 
482 static int32_t _logsys_config_mode_set_unlocked(int32_t subsysid, uint32_t new_mode)
483 {
484  if ( logsys_loggers[subsysid].mode == new_mode) {
485  return 0;
486  }
487  if (logsys_loggers[subsysid].target_id > 0) {
488  qb_log_ctl(logsys_loggers[subsysid].target_id,
489  QB_LOG_CONF_ENABLED,
490  (new_mode & LOGSYS_MODE_OUTPUT_FILE));
491  }
492 
493  if (subsysid == LOGSYS_MAX_SUBSYS_COUNT) {
494  qb_log_ctl(QB_LOG_STDERR,
495  QB_LOG_CONF_ENABLED,
496  (new_mode & LOGSYS_MODE_OUTPUT_STDERR));
497  qb_log_ctl(QB_LOG_SYSLOG,
498  QB_LOG_CONF_ENABLED,
499  (new_mode & LOGSYS_MODE_OUTPUT_SYSLOG));
500  }
501  logsys_loggers[subsysid].mode = new_mode;
502  return 0;
503 }
504 
505 int logsys_config_mode_set (const char *subsys, unsigned int mode)
506 {
507  int i;
508 
509  pthread_mutex_lock (&logsys_config_mutex);
510  if (subsys != NULL) {
511  i = _logsys_config_subsys_get_unlocked (subsys);
512  if (i >= 0) {
513  i = _logsys_config_mode_set_unlocked(i, mode);
514  }
515  } else {
516  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
517  _logsys_config_mode_set_unlocked(i, mode);
518  }
519  i = 0;
520  }
521 
522  pthread_mutex_unlock (&logsys_config_mutex);
523 
524  return i;
525 }
526 
527 unsigned int logsys_config_mode_get (const char *subsys)
528 {
529  int i;
530 
532  if (i < 0) {
533  return i;
534  }
535 
536  return logsys_loggers[i].mode;
537 }
538 
540  const char *subsys,
541  const char **error_string,
542  const char *file)
543 {
544  int i;
545  int res;
546 
547  pthread_mutex_lock (&logsys_config_mutex);
548 
549  if (subsys != NULL) {
550  i = _logsys_config_subsys_get_unlocked (subsys);
551  if (i < 0) {
552  res = i;
553  } else {
554  res = logsys_config_file_set_unlocked(i, error_string, file);
555  }
556  } else {
557  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
558  res = logsys_config_file_set_unlocked(i, error_string, file);
559  if (res < 0) {
560  break;
561  }
562  }
563  }
564 
565  pthread_mutex_unlock (&logsys_config_mutex);
566  return res;
567 }
568 
569 static void
570 logsys_file_format_get(char* file_format, int buf_len)
571 {
572  char *format_buffer_start;
573  char *str_pos;
574 
575  file_format[0] = '\0';
576 
577  format_buffer_start = format_buffer;
578 
579  if ((str_pos = strstr(format_buffer, "%t"))) {
580  strcpy(file_format, "%t ");
581  format_buffer_start = str_pos + 2;
582  }
583 
584  if ((str_pos = strstr(format_buffer, "%T"))) {
585  strcpy(file_format, "%T ");
586  format_buffer_start = str_pos + 2;
587  }
588 
589  strcat(file_format, "[%P] %H %N");
590  strncat(file_format, format_buffer_start, buf_len - strlen(file_format));
591 }
592 
593 int logsys_format_set (const char *format)
594 {
595  int i;
596  int c;
597  int w;
598  int reminder;
599  char syslog_format[128];
600  char file_format[128];
601 
602  if (format_buffer) {
603  free(format_buffer);
604  format_buffer = NULL;
605  }
606 
607  format_buffer = strdup(format ? format : "%7p [%6g] %b");
608  if (format_buffer == NULL) {
609  return -1;
610  }
611 
612  qb_log_format_set(QB_LOG_STDERR, format_buffer);
613 
614  logsys_file_format_get(file_format, 128);
615  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
616  if (logsys_loggers[i].target_id > 0) {
617  qb_log_format_set(logsys_loggers[i].target_id, file_format);
618  }
619  }
620 
621  /*
622  * This just goes through and remove %t, %T and %p from
623  * the format string for syslog.
624  */
625  w = 0;
626  memset(syslog_format, '\0', sizeof(syslog_format));
627  for (c = 0; c < strlen(format_buffer); c++) {
628  if (format_buffer[c] == '%') {
629  reminder = c;
630  for (c++; c < strlen(format_buffer); c++) {
631  if (isdigit(format_buffer[c])) {
632  continue;
633  }
634  if (format_buffer[c] == 't' ||
635  format_buffer[c] == 'p' ||
636  format_buffer[c] == 'T') {
637  c++;
638  } else {
639  c = reminder;
640  }
641  break;
642  }
643  }
644  syslog_format[w] = format_buffer[c];
645  w++;
646  }
647  qb_log_format_set(QB_LOG_SYSLOG, syslog_format);
648 
649  return 0;
650 }
651 
652 char *logsys_format_get (void)
653 {
654  return format_buffer;
655 }
656 
658  const char *subsys,
659  unsigned int facility)
660 {
661  return qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, facility);
662 }
663 
665  const char *subsys,
666  unsigned int priority)
667 {
668  int i;
669 
670  pthread_mutex_lock (&logsys_config_mutex);
671  if (subsys != NULL) {
672  i = _logsys_config_subsys_get_unlocked (subsys);
673  if (i >= 0) {
674  logsys_loggers[i].syslog_priority = priority;
675  logsys_loggers[i].dirty = QB_TRUE;
676 
677  i = 0;
678  }
679  } else {
680  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
681  logsys_loggers[i].syslog_priority = priority;
682  logsys_loggers[i].dirty = QB_TRUE;
683  }
684  i = 0;
685  }
686  pthread_mutex_unlock (&logsys_config_mutex);
687 
688  return i;
689 }
690 
692  const char *subsys,
693  unsigned int priority)
694 {
695  int i;
696 
697  pthread_mutex_lock (&logsys_config_mutex);
698  if (subsys != NULL) {
699  i = _logsys_config_subsys_get_unlocked (subsys);
700  if (i >= 0) {
701  logsys_loggers[i].logfile_priority = priority;
702  logsys_loggers[i].dirty = QB_TRUE;
703  i = 0;
704  }
705  } else {
706  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
707  logsys_loggers[i].logfile_priority = priority;
708  logsys_loggers[i].dirty = QB_TRUE;
709  }
710  i = 0;
711  }
712  pthread_mutex_unlock (&logsys_config_mutex);
713 
714  return i;
715 }
716 
717 
718 static void _logsys_config_apply_per_file(int32_t s, const char *filename)
719 {
720  uint32_t syslog_priority = logsys_loggers[s].syslog_priority;
721  uint32_t logfile_priority = logsys_loggers[s].logfile_priority;
722 
723  qb_log_filter_ctl(s, QB_LOG_TAG_SET, QB_LOG_FILTER_FILE,
724  filename, LOG_TRACE);
725 
726  qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_REMOVE,
727  QB_LOG_FILTER_FILE, filename, LOG_TRACE);
728  qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_REMOVE,
729  QB_LOG_FILTER_FILE, filename, LOG_TRACE);
730  if (logsys_loggers[s].target_id > 0) {
731  qb_log_filter_ctl(logsys_loggers[s].target_id,
732  QB_LOG_FILTER_REMOVE,
733  QB_LOG_FILTER_FILE, filename, LOG_TRACE);
734  }
735 
736  if (logsys_loggers[s].debug != LOGSYS_DEBUG_OFF) {
737  switch (logsys_loggers[s].debug) {
738  case LOGSYS_DEBUG_ON:
739  syslog_priority = LOG_DEBUG;
740  logfile_priority = LOG_DEBUG;
741  break;
742  case LOGSYS_DEBUG_TRACE:
743  syslog_priority = LOG_TRACE;
744  logfile_priority = LOG_TRACE;
745  break;
746  default:
747  assert(0);
748  }
749  }
750  qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD,
751  QB_LOG_FILTER_FILE, filename,
753  qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
754  QB_LOG_FILTER_FILE, filename,
756  if (logsys_loggers[s].target_id > 0) {
757  qb_log_filter_ctl(logsys_loggers[s].target_id,
758  QB_LOG_FILTER_ADD,
759  QB_LOG_FILTER_FILE, filename,
761  }
762 }
763 
764 static void _logsys_config_apply_per_subsys(int32_t s)
765 {
766  int32_t f;
767  for (f = 0; f < logsys_loggers[s].file_idx; f++) {
768  _logsys_config_apply_per_file(s, logsys_loggers[s].files[f]);
769  }
770  if (logsys_loggers[s].target_id > 0) {
771  qb_log_ctl(logsys_loggers[s].target_id,
772  QB_LOG_CONF_ENABLED,
773  (logsys_loggers[s].mode & LOGSYS_MODE_OUTPUT_FILE));
774  }
775  logsys_loggers[s].dirty = QB_FALSE;
776 }
777 
778 static void _logsys_config_apply_blackbox(void) {
779  int blackbox_enable_res;
780 
781  blackbox_enable_res = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, logsys_blackbox_enabled);
782 
783  if (blackbox_enable_res < 0) {
784  LOGSYS_PERROR (-blackbox_enable_res, LOGSYS_LEVEL_WARNING,
785  "Unable to initialize log flight recorder. "\
786  "The most common cause of this error is " \
787  "not enough space on /dev/shm. Corosync will continue work, " \
788  "but blackbox will not be available");
789  }
790 }
791 
793 {
794  int32_t s;
795 
796  _logsys_config_apply_blackbox();
797 
798  for (s = 0; s <= LOGSYS_MAX_SUBSYS_COUNT; s++) {
799  if (strcmp(logsys_loggers[s].subsys, "") == 0) {
800  continue;
801  }
802  _logsys_config_apply_per_subsys(s);
803  }
804 }
805 
807  const char *subsys,
808  unsigned int debug)
809 {
810  int i;
811 
812  pthread_mutex_lock (&logsys_config_mutex);
813  if (subsys != NULL) {
814  i = _logsys_config_subsys_get_unlocked (subsys);
815  if (i >= 0) {
816  logsys_loggers[i].dirty = QB_TRUE;
817  logsys_loggers[i].debug = debug;
818  i = 0;
819  }
820  } else {
821  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
822  logsys_loggers[i].debug = debug;
823  logsys_loggers[i].dirty = QB_TRUE;
824  }
825  i = 0;
826  }
827  pthread_mutex_unlock (&logsys_config_mutex);
828 
829  return i;
830 }
831 
832 int logsys_priority_id_get (const char *name)
833 {
834  unsigned int i;
835 
836  for (i = 0; prioritynames[i].c_name != NULL; i++) {
837  if (strcasecmp(name, prioritynames[i].c_name) == 0) {
838  return (prioritynames[i].c_val);
839  }
840  }
841  return (-1);
842 }
843 
845 {
846  int i;
847  int err;
848 
849  err = qb_log_thread_start();
850  if (err != 0) {
851  return (err);
852  }
853 
854  qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, QB_TRUE);
855  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
856  if (logsys_loggers[i].target_id > 0) {
857  qb_log_ctl(logsys_loggers[i].target_id, QB_LOG_CONF_THREADED, QB_TRUE);
858  }
859  }
860 
861  logsys_thread_started = 1;
862 
863  return (0);
864 }
865 
866 void logsys_blackbox_set(int enable)
867 {
868 
869  pthread_mutex_lock (&logsys_config_mutex);
870 
871  logsys_blackbox_enabled = enable;
872 
873  pthread_mutex_unlock (&logsys_config_mutex);
874 }
875 
876 /*
877  * To set correct pid to qb blackbox filename after tty dettach (fork) we have to
878  * close (this function) and (if needed) reopen blackbox (logsys_blackbox_postfork function).
879  */
881 {
882 
883  (void)qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
884 }
885 
887 {
888 
889  _logsys_config_apply_blackbox();
890 }
891 
893 {
894  cs_error_t res;
895 
896 #ifdef HAVE_QB_LOG_FILE_REOPEN
897  int i, j;
898  int num_using_current;
899  int32_t rc;
900 
901  res = CS_OK;
902 
903  pthread_mutex_lock (&logsys_config_mutex);
904 
905  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
906  if (logsys_loggers[i].target_id <= 0 || logsys_loggers[i].logfile == NULL) {
907  continue ;
908  }
909 
910  num_using_current = 0;
911  for (j = 0; j <= i; j++) {
912  if (logsys_loggers[i].target_id == logsys_loggers[j].target_id) {
913  num_using_current++;
914  }
915  }
916  if (num_using_current == 1) {
917  /*
918  * First instance of target file. Reopen it.
919  */
920  rc = qb_log_file_reopen(logsys_loggers[i].target_id, NULL);
921  if (rc != 0) {
923  "Unable to reopen log file %s", logsys_loggers[i].logfile);
924  res = qb_to_cs_error(rc);
925  }
926  }
927  }
928 
929  pthread_mutex_unlock (&logsys_config_mutex);
930 #else
931  res = CS_ERR_NOT_SUPPORTED;
932 #endif
933 
934  return (res);
935 }
cs_error_t qb_to_cs_error(int result)
qb_to_cs_error
cs_error_t
The cs_error_t enum.
Definition: corotypes.h:98
@ CS_OK
Definition: corotypes.h:99
@ CS_ERR_NOT_SUPPORTED
Definition: corotypes.h:117
unsigned int logsys_config_mode_get(const char *subsys)
logsys_config_mode_get
Definition: logsys.c:527
int logsys_config_mode_set(const char *subsys, unsigned int mode)
logsys_config_mode_set
Definition: logsys.c:505
void logsys_blackbox_set(int enable)
Definition: logsys.c:866
void logsys_blackbox_prefork(void)
Definition: logsys.c:880
void logsys_system_fini(void)
logsys_system_fini
Definition: logsys.c:286
int logsys_config_file_set(const char *subsys, const char **error_string, const char *file)
to close a logfile, just invoke this function with a NULL file or if you want to change logfile,...
Definition: logsys.c:539
int logsys_config_syslog_priority_set(const char *subsys, unsigned int priority)
logsys_config_syslog_priority_set
Definition: logsys.c:664
char * logsys_format_get(void)
logsys_format_get
Definition: logsys.c:652
void logsys_config_apply(void)
logsys_config_apply
Definition: logsys.c:792
#define IPC_LOGSYS_SIZE
Definition: logsys.c:80
int logsys_priority_id_get(const char *name)
logsys_priority_id_get
Definition: logsys.c:832
#define LOGSYS_LOGGER_INIT_DONE
Definition: logsys.c:102
int logsys_config_logfile_priority_set(const char *subsys, unsigned int priority)
logsys_config_logfile_priority_set
Definition: logsys.c:691
int logsys_thread_start(void)
logsys_thread_start
Definition: logsys.c:844
int logsys_config_debug_set(const char *subsys, unsigned int debug)
enabling debug, disable message priority filtering.
Definition: logsys.c:806
int _logsys_config_subsys_get(const char *subsys)
_logsys_config_subsys_get
Definition: logsys.c:469
int _logsys_subsys_create(const char *subsys, const char *filename)
_logsys_subsys_create
Definition: logsys.c:435
int logsys_config_syslog_facility_set(const char *subsys, unsigned int facility)
per system/subsystem settings.
Definition: logsys.c:657
cs_error_t logsys_reopen_log_files(void)
Definition: logsys.c:892
#define MAX_FILES_PER_SUBSYS
Definition: logsys.c:76
void logsys_blackbox_postfork(void)
Definition: logsys.c:886
int _logsys_system_setup(const char *mainsystem, unsigned int mode, int syslog_facility, int syslog_priority)
_logsys_system_setup
Definition: logsys.c:304
int logsys_format_set(const char *format)
configuration bits that can only be done for the whole system
Definition: logsys.c:593
#define LOGSYS_LOGGER_NEEDS_INIT
Definition: logsys.c:103
#define LOGSYS_MAX_SUBSYS_NAMELEN
Definition: logsys.h:86
#define LOGSYS_DEBUG_OFF
Definition: logsys.h:92
#define LOGSYS_MODE_OUTPUT_STDERR
Definition: logsys.h:61
#define LOGSYS_DEBUG_TRACE
Definition: logsys.h:94
#define LOGSYS_PERROR(err_num, level, fmt, args...)
The LOGSYS_PERROR macro.
Definition: logsys.h:317
#define LOGSYS_DEBUG_ON
Definition: logsys.h:93
#define LOGSYS_LEVEL_WARNING
Definition: logsys.h:73
#define LOGSYS_MAX_PERROR_MSG_LEN
Definition: logsys.h:87
#define LOGSYS_MODE_OUTPUT_FILE
Definition: logsys.h:60
#define LOGSYS_MODE_OUTPUT_SYSLOG
Definition: logsys.h:62
#define LOGSYS_MAX_SUBSYS_COUNT
Definition: logsys.h:85
int logfile_priority
Definition: logsys.c:92
int syslog_priority
Definition: logsys.c:91
int32_t dirty
Definition: logsys.c:98
char * files[MAX_FILES_PER_SUBSYS]
Definition: logsys.c:96
unsigned int mode
Definition: logsys.c:89
char subsys[LOGSYS_MAX_SUBSYS_NAMELEN]
Definition: logsys.c:87
int init_status
Definition: logsys.c:93
int32_t file_idx
Definition: logsys.c:97
int32_t target_id
Definition: logsys.c:95
char * logfile
Definition: logsys.c:88
unsigned int debug
Definition: logsys.c:90
const char * c_name
Definition: logsys.c:58
int c_val
Definition: logsys.c:59