corosync  2.4.5
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/list.h>
51 #include <corosync/logsys.h>
52 
53 /*
54  * syslog prioritynames, facility names to value mapping
55  * Some C libraries build this in to their headers, but it is non-portable
56  * so logsys supplies its own version.
57  */
58 struct syslog_names {
59  const char *c_name;
60  int c_val;
61 };
62 
63 static struct syslog_names prioritynames[] =
64 {
65  { "alert", LOG_ALERT },
66  { "crit", LOG_CRIT },
67  { "debug", LOG_DEBUG },
68  { "emerg", LOG_EMERG },
69  { "err", LOG_ERR },
70  { "error", LOG_ERR },
71  { "info", LOG_INFO },
72  { "notice", LOG_NOTICE },
73  { "warning", LOG_WARNING },
74  { NULL, -1 }
75 };
76 
77 #define MAX_FILES_PER_SUBSYS 32
78 #ifdef HAVE_SMALL_MEMORY_FOOTPRINT
79 #define IPC_LOGSYS_SIZE 8192*64
80 #else
81 #define IPC_LOGSYS_SIZE 8192*1024
82 #endif
83 
84 /*
85  * need unlogical order to preserve 64bit alignment
86  */
87 struct logsys_logger {
88  char subsys[LOGSYS_MAX_SUBSYS_NAMELEN]; /* subsystem name */
89  char *logfile; /* log to file */
90  unsigned int mode; /* subsystem mode */
91  unsigned int debug; /* debug on|off|trace */
92  int syslog_priority; /* priority */
93  int logfile_priority; /* priority to file */
94  int init_status; /* internal field to handle init queues
95  for subsystems */
96  int32_t target_id;
98  int32_t file_idx;
99  int32_t dirty;
100 };
101 
102 /* values for logsys_logger init_status */
103 #define LOGSYS_LOGGER_INIT_DONE 0
104 #define LOGSYS_LOGGER_NEEDS_INIT 1
105 
106 static int logsys_system_needs_init = LOGSYS_LOGGER_NEEDS_INIT;
107 
108 static struct logsys_logger logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT + 1];
109 
110 static pthread_mutex_t logsys_config_mutex = PTHREAD_MUTEX_INITIALIZER;
111 
112 static int32_t _logsys_config_mode_set_unlocked(int32_t subsysid, uint32_t new_mode);
113 static void _logsys_config_apply_per_file(int32_t s, const char *filename);
114 static void _logsys_config_apply_per_subsys(int32_t s);
115 static void _logsys_subsys_filename_add (int32_t s, const char *filename);
116 static void logsys_file_format_get(char* file_format, int buf_len);
117 
118 static char *format_buffer=NULL;
119 
120 static int logsys_thread_started = 0;
121 
122 static int logsys_blackbox_enabled = 1;
123 
124 static int _logsys_config_subsys_get_unlocked (const char *subsys)
125 {
126  unsigned int i;
127 
128  if (!subsys) {
130  }
131 
132  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
133  if (strcmp (logsys_loggers[i].subsys, subsys) == 0) {
134  return i;
135  }
136  }
137 
138  return (-1);
139 }
140 
141 
142 /*
143  * we need a version that can work when somebody else is already
144  * holding a config mutex lock or we will never get out of here
145  */
146 static int logsys_config_file_set_unlocked (
147  int subsysid,
148  const char **error_string,
149  const char *file)
150 {
151  static char error_string_response[512];
152  int i;
153  char file_format[128];
154 
155  if (logsys_loggers[subsysid].target_id > 0) {
156  int32_t f;
157  for (f = 0; f < logsys_loggers[subsysid].file_idx; f++) {
158  qb_log_filter_ctl(logsys_loggers[subsysid].target_id,
159  QB_LOG_FILTER_REMOVE,
160  QB_LOG_FILTER_FILE,
161  logsys_loggers[subsysid].files[f],
162  LOG_TRACE);
163  }
164  }
165 
166  logsys_loggers[subsysid].dirty = QB_TRUE;
167  if (file == NULL) {
168  return (0);
169  }
170 
171  if (logsys_loggers[subsysid].target_id > 0 &&
172  logsys_loggers[subsysid].logfile != NULL &&
173  strcmp(file, logsys_loggers[subsysid].logfile) == 0) {
174  return (0);
175  }
176 
177  if (strlen(file) >= PATH_MAX) {
178  snprintf (error_string_response,
179  sizeof(error_string_response),
180  "%s: logfile name exceed maximum system filename length",
181  logsys_loggers[subsysid].subsys);
182  *error_string = error_string_response;
183  return (-1);
184  }
185 
186  if (logsys_loggers[subsysid].logfile != NULL) {
187  free(logsys_loggers[subsysid].logfile);
188  logsys_loggers[subsysid].logfile = NULL;
189  }
190 
191  logsys_loggers[subsysid].logfile = strdup(file);
192 
193  if (logsys_loggers[subsysid].logfile == NULL) {
194  snprintf (error_string_response,
195  sizeof(error_string_response),
196  "Unable to allocate memory for logfile '%s'",
197  file);
198  *error_string = error_string_response;
199  return (-1);
200  }
201 
202  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
203  if ((logsys_loggers[i].logfile != NULL) &&
204  (strcmp (logsys_loggers[i].logfile, file) == 0) &&
205  (i != subsysid)) {
206  /* we have found another subsys with this config file
207  * so add a filter
208  */
209  logsys_loggers[subsysid].target_id = logsys_loggers[i].target_id;
210  return (0);
211  }
212  }
213 
214  if (logsys_loggers[subsysid].target_id > 0) {
215  int num_using_current = 0;
216  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
217  if (logsys_loggers[subsysid].target_id ==
218  logsys_loggers[i].target_id) {
219  num_using_current++;
220  }
221  }
222  if (num_using_current == 1) {
223  /* no one else is using this close it */
224  qb_log_file_close(logsys_loggers[subsysid].target_id);
225  }
226  }
227 
228  logsys_loggers[subsysid].target_id = qb_log_file_open(file);
229  if (logsys_loggers[subsysid].target_id < 0) {
230  int err = -logsys_loggers[subsysid].target_id;
231  char error_str[LOGSYS_MAX_PERROR_MSG_LEN];
232  const char *error_ptr;
233  error_ptr = qb_strerror_r(err, error_str, sizeof(error_str));
234 
235  free(logsys_loggers[subsysid].logfile);
236  logsys_loggers[subsysid].logfile = NULL;
237  snprintf (error_string_response,
238  sizeof(error_string_response),
239  "Can't open logfile '%s' for reason: %s (%d)",
240  file, error_ptr, err);
241  *error_string = error_string_response;
242  return (-1);
243  }
244  logsys_file_format_get(file_format, 128);
245  qb_log_format_set(logsys_loggers[subsysid].target_id, file_format);
246 
247  qb_log_ctl(logsys_loggers[subsysid].target_id,
248  QB_LOG_CONF_ENABLED,
249  (logsys_loggers[subsysid].mode & LOGSYS_MODE_OUTPUT_FILE));
250  if (logsys_thread_started) {
251  qb_log_ctl(logsys_loggers[subsysid].target_id, QB_LOG_CONF_THREADED, QB_TRUE);
252  }
253 
254  return (0);
255 }
256 
257 static void logsys_subsys_init (
258  const char *subsys,
259  int subsysid)
260 {
261  if (logsys_system_needs_init == LOGSYS_LOGGER_NEEDS_INIT) {
262  logsys_loggers[subsysid].init_status =
264  } else {
265  logsys_loggers[subsysid].mode = logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode;
266  logsys_loggers[subsysid].debug = logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].debug;
267  logsys_loggers[subsysid].syslog_priority = logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].syslog_priority;
268  logsys_loggers[subsysid].logfile_priority = logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].logfile_priority;
269  logsys_loggers[subsysid].init_status = LOGSYS_LOGGER_INIT_DONE;
270  }
271  strncpy (logsys_loggers[subsysid].subsys, subsys,
272  sizeof (logsys_loggers[subsysid].subsys));
273  logsys_loggers[subsysid].subsys[
274  sizeof (logsys_loggers[subsysid].subsys) - 1] = '\0';
275  logsys_loggers[subsysid].file_idx = 0;
276 }
277 
278 static const char *_logsys_tags_stringify(uint32_t tags)
279 {
280  if (tags == QB_LOG_TAG_LIBQB_MSG) {
281  return "QB";
282  } else {
283  return logsys_loggers[tags].subsys;
284  }
285 }
286 
288 {
289  int i;
290  int f;
291  for (i = 0; i < LOGSYS_MAX_SUBSYS_COUNT; i++) {
292  free(logsys_loggers[i].logfile);
293  for (f = 0; f < logsys_loggers[i].file_idx; f++) {
294  free(logsys_loggers[i].files[f]);
295  }
296  }
297 
298  qb_log_fini ();
299 }
300 
301 /*
302  * Internal API - exported
303  */
304 
306  const char *mainsystem,
307  unsigned int mode,
308  int syslog_facility,
309  int syslog_priority)
310 {
311  int i;
312  int32_t fidx;
313  char tempsubsys[LOGSYS_MAX_SUBSYS_NAMELEN];
314 
315  if ((mainsystem == NULL) ||
316  (strlen(mainsystem) >= LOGSYS_MAX_SUBSYS_NAMELEN)) {
317  return -1;
318  }
319 
320  /*
321  * Setup libqb as a subsys
322  */
323  i = _logsys_subsys_create ("QB", "array.c,log.c,log_syslog.c,log_blackbox.c,log_format.c,"
324  "log_file.c,log_dcs.c,log_thread.c,ipc_shm.c,ipcs.c,ipc_us.c,loop.c,"
325  "loop_poll_epoll.c,loop_job.c,loop_poll_poll.c,loop_poll_kqueue.c,"
326  "loop_timerlist.c,loop_poll.c,ringbuffer.c,ringbuffer_helper.c,trie.c,"
327  "map.c,skiplist.c,rpl_sem.c,hdb.c,unix.c,hashtable.c,strlcpy.c,ipc_socket.c,"
328  "strchrnul.c,ipc_setup.c,strlcat.c");
329  if (i < 0) {
330  return -1;
331  }
332 
333  /*
334  * name clash
335  * _logsys_subsys_filename_add (i, "util.c");
336  */
337 
338  /*
339  * This file (logsys.c) is not exactly QB. We need tag for logsys.c if flightrecorder init
340  * fails, and QB seems to be closest.
341  */
342  _logsys_subsys_filename_add (i, "logsys.c");
343 
345 
346  pthread_mutex_lock (&logsys_config_mutex);
347 
348  snprintf(logsys_loggers[i].subsys,
350  "%s", mainsystem);
351 
352  logsys_loggers[i].mode = mode;
353  logsys_loggers[i].debug = LOGSYS_DEBUG_OFF;
354  logsys_loggers[i].file_idx = 0;
355  logsys_loggers[i].logfile_priority = syslog_priority;
356  logsys_loggers[i].syslog_priority = syslog_priority;
357 
358  qb_log_init(mainsystem, syslog_facility, syslog_priority);
359  if (logsys_loggers[i].mode & LOGSYS_MODE_OUTPUT_STDERR) {
360  qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);
361  } else {
362  qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_FALSE);
363  }
364  if (logsys_loggers[i].mode & LOGSYS_MODE_OUTPUT_SYSLOG) {
365  qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
366  } else {
367  qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
368  }
369  qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_PRIORITY_BUMP, LOG_INFO - LOG_DEBUG);
370 
371  qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
372  QB_LOG_FILTER_FILE, "*", LOG_TRACE);
373  qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, IPC_LOGSYS_SIZE);
374  qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_THREADED, QB_FALSE);
375 
376  /*
377  * Blackbox is disabled at the init and enabled later based
378  * on config (logging.blackbox) value.
379  */
380  qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
381 
382  if (logsys_format_set(NULL) == -1) {
383  return -1;
384  }
385 
386  qb_log_tags_stringify_fn_set(_logsys_tags_stringify);
387 
388  logsys_loggers[i].init_status = LOGSYS_LOGGER_INIT_DONE;
389  logsys_system_needs_init = LOGSYS_LOGGER_INIT_DONE;
390 
391  for (i = 0; i < LOGSYS_MAX_SUBSYS_COUNT; i++) {
392  if ((strcmp (logsys_loggers[i].subsys, "") != 0) &&
393  (logsys_loggers[i].init_status ==
395  fidx = logsys_loggers[i].file_idx;
396  strncpy (tempsubsys, logsys_loggers[i].subsys,
397  sizeof (tempsubsys));
398  tempsubsys[sizeof (tempsubsys) - 1] = '\0';
399  logsys_subsys_init(tempsubsys, i);
400  logsys_loggers[i].file_idx = fidx;
401  _logsys_config_mode_set_unlocked(i, logsys_loggers[i].mode);
402  _logsys_config_apply_per_subsys(i);
403  }
404  }
405 
406  pthread_mutex_unlock (&logsys_config_mutex);
407 
408  return (0);
409 }
410 
411 
412 static void _logsys_subsys_filename_add (int32_t s, const char *filename)
413 {
414  int i;
415 
416  if (filename == NULL) {
417  return;
418  }
419  assert(logsys_loggers[s].file_idx < MAX_FILES_PER_SUBSYS);
420  assert(logsys_loggers[s].file_idx >= 0);
421 
422  for (i = 0; i < logsys_loggers[s].file_idx; i++) {
423  if (strcmp(logsys_loggers[s].files[i], filename) == 0) {
424  return;
425  }
426  }
427  logsys_loggers[s].files[logsys_loggers[s].file_idx++] = strdup(filename);
428 
429  if (logsys_system_needs_init == LOGSYS_LOGGER_INIT_DONE) {
430  _logsys_config_apply_per_file(s, filename);
431  }
432 }
433 
434 int _logsys_subsys_create (const char *subsys, const char *filename)
435 {
436  int i;
437 
438  if ((subsys == NULL) ||
439  (strlen(subsys) >= LOGSYS_MAX_SUBSYS_NAMELEN)) {
440  return -1;
441  }
442 
443  pthread_mutex_lock (&logsys_config_mutex);
444 
445  i = _logsys_config_subsys_get_unlocked (subsys);
446  if ((i > -1) && (i < LOGSYS_MAX_SUBSYS_COUNT)) {
447  _logsys_subsys_filename_add(i, filename);
448  pthread_mutex_unlock (&logsys_config_mutex);
449  return i;
450  }
451 
452  for (i = 0; i < LOGSYS_MAX_SUBSYS_COUNT; i++) {
453  if (strcmp (logsys_loggers[i].subsys, "") == 0) {
454  logsys_subsys_init(subsys, i);
455  _logsys_subsys_filename_add(i, filename);
456  break;
457  }
458  }
459 
460  if (i >= LOGSYS_MAX_SUBSYS_COUNT) {
461  i = -1;
462  }
463 
464  pthread_mutex_unlock (&logsys_config_mutex);
465  return i;
466 }
467 
468 int _logsys_config_subsys_get (const char *subsys)
469 {
470  unsigned int i;
471 
472  pthread_mutex_lock (&logsys_config_mutex);
473 
474  i = _logsys_config_subsys_get_unlocked (subsys);
475 
476  pthread_mutex_unlock (&logsys_config_mutex);
477 
478  return i;
479 }
480 
481 static int32_t _logsys_config_mode_set_unlocked(int32_t subsysid, uint32_t new_mode)
482 {
483  if ( logsys_loggers[subsysid].mode == new_mode) {
484  return 0;
485  }
486  if (logsys_loggers[subsysid].target_id > 0) {
487  qb_log_ctl(logsys_loggers[subsysid].target_id,
488  QB_LOG_CONF_ENABLED,
489  (new_mode & LOGSYS_MODE_OUTPUT_FILE));
490  }
491 
492  if (subsysid == LOGSYS_MAX_SUBSYS_COUNT) {
493  qb_log_ctl(QB_LOG_STDERR,
494  QB_LOG_CONF_ENABLED,
495  (new_mode & LOGSYS_MODE_OUTPUT_STDERR));
496  qb_log_ctl(QB_LOG_SYSLOG,
497  QB_LOG_CONF_ENABLED,
498  (new_mode & LOGSYS_MODE_OUTPUT_SYSLOG));
499  }
500  logsys_loggers[subsysid].mode = new_mode;
501  return 0;
502 }
503 
504 int logsys_config_mode_set (const char *subsys, unsigned int mode)
505 {
506  int i;
507 
508  pthread_mutex_lock (&logsys_config_mutex);
509  if (subsys != NULL) {
510  i = _logsys_config_subsys_get_unlocked (subsys);
511  if (i >= 0) {
512  i = _logsys_config_mode_set_unlocked(i, mode);
513  }
514  } else {
515  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
516  _logsys_config_mode_set_unlocked(i, mode);
517  }
518  i = 0;
519  }
520 
521  pthread_mutex_unlock (&logsys_config_mutex);
522 
523  return i;
524 }
525 
526 unsigned int logsys_config_mode_get (const char *subsys)
527 {
528  int i;
529 
530  i = _logsys_config_subsys_get (subsys);
531  if (i < 0) {
532  return i;
533  }
534 
535  return logsys_loggers[i].mode;
536 }
537 
539  const char *subsys,
540  const char **error_string,
541  const char *file)
542 {
543  int i;
544  int res;
545 
546  pthread_mutex_lock (&logsys_config_mutex);
547 
548  if (subsys != NULL) {
549  i = _logsys_config_subsys_get_unlocked (subsys);
550  if (i < 0) {
551  res = i;
552  } else {
553  res = logsys_config_file_set_unlocked(i, error_string, file);
554  }
555  } else {
556  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
557  res = logsys_config_file_set_unlocked(i, error_string, file);
558  if (res < 0) {
559  break;
560  }
561  }
562  }
563 
564  pthread_mutex_unlock (&logsys_config_mutex);
565  return res;
566 }
567 
568 static void
569 logsys_file_format_get(char* file_format, int buf_len)
570 {
571  char *per_t;
572  file_format[0] = '\0';
573  per_t = strstr(format_buffer, "%t");
574  if (per_t) {
575  strcpy(file_format, "%t [%P] %H %N");
576  per_t += 2;
577  strncat(file_format, per_t, buf_len - strlen("%t [%P] %H %N"));
578  } else {
579  strcpy(file_format, "[%P] %H %N");
580  strncat(file_format, format_buffer, buf_len - strlen("[%P] %H %N"));
581  }
582 }
583 
584 int logsys_format_set (const char *format)
585 {
586  int i;
587  int c;
588  int w;
589  int reminder;
590  char syslog_format[128];
591  char file_format[128];
592 
593  if (format_buffer) {
594  free(format_buffer);
595  format_buffer = NULL;
596  }
597 
598  format_buffer = strdup(format ? format : "%7p [%6g] %b");
599  if (format_buffer == NULL) {
600  return -1;
601  }
602 
603  qb_log_format_set(QB_LOG_STDERR, format_buffer);
604 
605  logsys_file_format_get(file_format, 128);
606  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
607  if (logsys_loggers[i].target_id > 0) {
608  qb_log_format_set(logsys_loggers[i].target_id, file_format);
609  }
610  }
611 
612  /*
613  * This just goes through and remove %t and %p from
614  * the format string for syslog.
615  */
616  w = 0;
617  memset(syslog_format, '\0', sizeof(syslog_format));
618  for (c = 0; c < strlen(format_buffer); c++) {
619  if (format_buffer[c] == '%') {
620  reminder = c;
621  for (c++; c < strlen(format_buffer); c++) {
622  if (isdigit(format_buffer[c])) {
623  continue;
624  }
625  if (format_buffer[c] == 't' ||
626  format_buffer[c] == 'p') {
627  c++;
628  } else {
629  c = reminder;
630  }
631  break;
632  }
633  }
634  syslog_format[w] = format_buffer[c];
635  w++;
636  }
637  qb_log_format_set(QB_LOG_SYSLOG, syslog_format);
638 
639  return 0;
640 }
641 
642 char *logsys_format_get (void)
643 {
644  return format_buffer;
645 }
646 
648  const char *subsys,
649  unsigned int facility)
650 {
651  return qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_FACILITY, facility);
652 }
653 
655  const char *subsys,
656  unsigned int priority)
657 {
658  int i;
659 
660  pthread_mutex_lock (&logsys_config_mutex);
661  if (subsys != NULL) {
662  i = _logsys_config_subsys_get_unlocked (subsys);
663  if (i >= 0) {
664  logsys_loggers[i].syslog_priority = priority;
665  logsys_loggers[i].dirty = QB_TRUE;
666 
667  i = 0;
668  }
669  } else {
670  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
671  logsys_loggers[i].syslog_priority = priority;
672  logsys_loggers[i].dirty = QB_TRUE;
673  }
674  i = 0;
675  }
676  pthread_mutex_unlock (&logsys_config_mutex);
677 
678  return i;
679 }
680 
682  const char *subsys,
683  unsigned int priority)
684 {
685  int i;
686 
687  pthread_mutex_lock (&logsys_config_mutex);
688  if (subsys != NULL) {
689  i = _logsys_config_subsys_get_unlocked (subsys);
690  if (i >= 0) {
691  logsys_loggers[i].logfile_priority = priority;
692  logsys_loggers[i].dirty = QB_TRUE;
693  i = 0;
694  }
695  } else {
696  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
697  logsys_loggers[i].logfile_priority = priority;
698  logsys_loggers[i].dirty = QB_TRUE;
699  }
700  i = 0;
701  }
702  pthread_mutex_unlock (&logsys_config_mutex);
703 
704  return i;
705 }
706 
707 
708 static void _logsys_config_apply_per_file(int32_t s, const char *filename)
709 {
710  uint32_t syslog_priority = logsys_loggers[s].syslog_priority;
711  uint32_t logfile_priority = logsys_loggers[s].logfile_priority;
712 
713  qb_log_filter_ctl(s, QB_LOG_TAG_SET, QB_LOG_FILTER_FILE,
714  filename, LOG_TRACE);
715 
716  qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_REMOVE,
717  QB_LOG_FILTER_FILE, filename, LOG_TRACE);
718  qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_REMOVE,
719  QB_LOG_FILTER_FILE, filename, LOG_TRACE);
720  if (logsys_loggers[s].target_id > 0) {
721  qb_log_filter_ctl(logsys_loggers[s].target_id,
722  QB_LOG_FILTER_REMOVE,
723  QB_LOG_FILTER_FILE, filename, LOG_TRACE);
724  }
725 
726  if (logsys_loggers[s].debug != LOGSYS_DEBUG_OFF) {
727  switch (logsys_loggers[s].debug) {
728  case LOGSYS_DEBUG_ON:
729  syslog_priority = LOG_DEBUG;
730  logfile_priority = LOG_DEBUG;
731  break;
732  case LOGSYS_DEBUG_TRACE:
733  syslog_priority = LOG_TRACE;
734  logfile_priority = LOG_TRACE;
735  break;
736  default:
737  assert(0);
738  }
739  }
740  qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD,
741  QB_LOG_FILTER_FILE, filename,
742  syslog_priority);
743  qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
744  QB_LOG_FILTER_FILE, filename,
745  logfile_priority);
746  if (logsys_loggers[s].target_id > 0) {
747  qb_log_filter_ctl(logsys_loggers[s].target_id,
748  QB_LOG_FILTER_ADD,
749  QB_LOG_FILTER_FILE, filename,
750  logfile_priority);
751  }
752 }
753 
754 static void _logsys_config_apply_per_subsys(int32_t s)
755 {
756  int32_t f;
757  for (f = 0; f < logsys_loggers[s].file_idx; f++) {
758  _logsys_config_apply_per_file(s, logsys_loggers[s].files[f]);
759  }
760  if (logsys_loggers[s].target_id > 0) {
761  qb_log_ctl(logsys_loggers[s].target_id,
762  QB_LOG_CONF_ENABLED,
763  (logsys_loggers[s].mode & LOGSYS_MODE_OUTPUT_FILE));
764  }
765  logsys_loggers[s].dirty = QB_FALSE;
766 }
767 
768 static void _logsys_config_apply_blackbox(void) {
769  int blackbox_enable_res;
770 
771  blackbox_enable_res = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, logsys_blackbox_enabled);
772 
773  if (blackbox_enable_res < 0) {
774  LOGSYS_PERROR (-blackbox_enable_res, LOGSYS_LEVEL_WARNING,
775  "Unable to initialize log flight recorder. "\
776  "The most common cause of this error is " \
777  "not enough space on /dev/shm. Corosync will continue work, " \
778  "but blackbox will not be available");
779  }
780 }
781 
783 {
784  int32_t s;
785 
786  _logsys_config_apply_blackbox();
787 
788  for (s = 0; s <= LOGSYS_MAX_SUBSYS_COUNT; s++) {
789  if (strcmp(logsys_loggers[s].subsys, "") == 0) {
790  continue;
791  }
792  _logsys_config_apply_per_subsys(s);
793  }
794 }
795 
797  const char *subsys,
798  unsigned int debug)
799 {
800  int i;
801 
802  pthread_mutex_lock (&logsys_config_mutex);
803  if (subsys != NULL) {
804  i = _logsys_config_subsys_get_unlocked (subsys);
805  if (i >= 0) {
806  logsys_loggers[i].dirty = QB_TRUE;
807  logsys_loggers[i].debug = debug;
808  i = 0;
809  }
810  } else {
811  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
812  logsys_loggers[i].debug = debug;
813  logsys_loggers[i].dirty = QB_TRUE;
814  }
815  i = 0;
816  }
817  pthread_mutex_unlock (&logsys_config_mutex);
818 
819  return i;
820 }
821 
822 int logsys_priority_id_get (const char *name)
823 {
824  unsigned int i;
825 
826  for (i = 0; prioritynames[i].c_name != NULL; i++) {
827  if (strcasecmp(name, prioritynames[i].c_name) == 0) {
828  return (prioritynames[i].c_val);
829  }
830  }
831  return (-1);
832 }
833 
835 {
836  int i;
837  int err;
838 
839  err = qb_log_thread_start();
840  if (err != 0) {
841  return (err);
842  }
843 
844  qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, QB_TRUE);
845  for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
846  if (logsys_loggers[i].target_id > 0) {
847  qb_log_ctl(logsys_loggers[i].target_id, QB_LOG_CONF_THREADED, QB_TRUE);
848  }
849  }
850 
851  logsys_thread_started = 1;
852 
853  return (0);
854 }
855 
856 void logsys_blackbox_set(int enable)
857 {
858 
859  pthread_mutex_lock (&logsys_config_mutex);
860 
861  logsys_blackbox_enabled = enable;
862 
863  pthread_mutex_unlock (&logsys_config_mutex);
864 }
865 
866 /*
867  * To set correct pid to qb blackbox filename after tty dettach (fork) we have to
868  * close (this function) and (if needed) reopen blackbox (logsys_blackbox_postfork function).
869  */
871 {
872 
873  (void)qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
874 }
875 
877 {
878 
879  _logsys_config_apply_blackbox();
880 }