vlog: Remove unused function vlog_get_log_file().
[sliver-openvswitch.git] / lib / vlog.c
1 /*
2  * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <config.h>
18 #include "vlog.h"
19 #include <assert.h>
20 #include <ctype.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <syslog.h>
29 #include <time.h>
30 #include <unistd.h>
31 #include "coverage.h"
32 #include "dirs.h"
33 #include "dynamic-string.h"
34 #include "ofpbuf.h"
35 #include "sat-math.h"
36 #include "svec.h"
37 #include "timeval.h"
38 #include "unixctl.h"
39 #include "util.h"
40
41 VLOG_DEFINE_THIS_MODULE(vlog);
42
43 COVERAGE_DEFINE(vlog_recursive);
44
45 /* ovs_assert() logs the assertion message, so using ovs_assert() in this
46  * source file could cause recursion. */
47 #undef ovs_assert
48 #define ovs_assert use_assert_instead_of_ovs_assert_in_this_module
49
50 /* Name for each logging level. */
51 static const char *const level_names[VLL_N_LEVELS] = {
52 #define VLOG_LEVEL(NAME, SYSLOG_LEVEL) #NAME,
53     VLOG_LEVELS
54 #undef VLOG_LEVEL
55 };
56
57 /* Syslog value for each logging level. */
58 static const int syslog_levels[VLL_N_LEVELS] = {
59 #define VLOG_LEVEL(NAME, SYSLOG_LEVEL) SYSLOG_LEVEL,
60     VLOG_LEVELS
61 #undef VLOG_LEVEL
62 };
63
64 /* The log modules. */
65 #if USE_LINKER_SECTIONS
66 extern struct vlog_module *__start_vlog_modules[];
67 extern struct vlog_module *__stop_vlog_modules[];
68 #define vlog_modules __start_vlog_modules
69 #define n_vlog_modules (__stop_vlog_modules - __start_vlog_modules)
70 #else
71 #define VLOG_MODULE VLOG_DEFINE_MODULE__
72 #include "vlog-modules.def"
73 #undef VLOG_MODULE
74
75 struct vlog_module *vlog_modules[] = {
76 #define VLOG_MODULE(NAME) &VLM_##NAME,
77 #include "vlog-modules.def"
78 #undef VLOG_MODULE
79 };
80 #define n_vlog_modules ARRAY_SIZE(vlog_modules)
81 #endif
82
83 /* Information about each facility. */
84 struct facility {
85     const char *name;           /* Name. */
86     char *pattern;              /* Current pattern. */
87     bool default_pattern;       /* Whether current pattern is the default. */
88 };
89 static struct facility facilities[VLF_N_FACILITIES] = {
90 #define VLOG_FACILITY(NAME, PATTERN) {#NAME, PATTERN, true},
91     VLOG_FACILITIES
92 #undef VLOG_FACILITY
93 };
94
95 /* VLF_FILE configuration. */
96 static char *log_file_name;
97 static int log_fd = -1;
98
99 /* vlog initialized? */
100 static bool vlog_inited;
101
102 static void format_log_message(const struct vlog_module *, enum vlog_level,
103                                enum vlog_facility, unsigned int msg_num,
104                                const char *message, va_list, struct ds *)
105     PRINTF_FORMAT(5, 0);
106
107 /* Searches the 'n_names' in 'names'.  Returns the index of a match for
108  * 'target', or 'n_names' if no name matches. */
109 static size_t
110 search_name_array(const char *target, const char *const *names, size_t n_names)
111 {
112     size_t i;
113
114     for (i = 0; i < n_names; i++) {
115         assert(names[i]);
116         if (!strcasecmp(names[i], target)) {
117             break;
118         }
119     }
120     return i;
121 }
122
123 /* Returns the name for logging level 'level'. */
124 const char *
125 vlog_get_level_name(enum vlog_level level)
126 {
127     assert(level < VLL_N_LEVELS);
128     return level_names[level];
129 }
130
131 /* Returns the logging level with the given 'name', or VLL_N_LEVELS if 'name'
132  * is not the name of a logging level. */
133 enum vlog_level
134 vlog_get_level_val(const char *name)
135 {
136     return search_name_array(name, level_names, ARRAY_SIZE(level_names));
137 }
138
139 /* Returns the name for logging facility 'facility'. */
140 const char *
141 vlog_get_facility_name(enum vlog_facility facility)
142 {
143     assert(facility < VLF_N_FACILITIES);
144     return facilities[facility].name;
145 }
146
147 /* Returns the logging facility named 'name', or VLF_N_FACILITIES if 'name' is
148  * not the name of a logging facility. */
149 enum vlog_facility
150 vlog_get_facility_val(const char *name)
151 {
152     size_t i;
153
154     for (i = 0; i < VLF_N_FACILITIES; i++) {
155         if (!strcasecmp(facilities[i].name, name)) {
156             break;
157         }
158     }
159     return i;
160 }
161
162 /* Returns the name for logging module 'module'. */
163 const char *
164 vlog_get_module_name(const struct vlog_module *module)
165 {
166     return module->name;
167 }
168
169 /* Returns the logging module named 'name', or NULL if 'name' is not the name
170  * of a logging module. */
171 struct vlog_module *
172 vlog_module_from_name(const char *name)
173 {
174     struct vlog_module **mp;
175
176     for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
177         if (!strcasecmp(name, (*mp)->name)) {
178             return *mp;
179         }
180     }
181     return NULL;
182 }
183
184 /* Returns the current logging level for the given 'module' and 'facility'. */
185 enum vlog_level
186 vlog_get_level(const struct vlog_module *module, enum vlog_facility facility)
187 {
188     assert(facility < VLF_N_FACILITIES);
189     return module->levels[facility];
190 }
191
192 static void
193 update_min_level(struct vlog_module *module)
194 {
195     enum vlog_facility facility;
196
197     module->min_level = VLL_OFF;
198     for (facility = 0; facility < VLF_N_FACILITIES; facility++) {
199         if (log_fd >= 0 || facility != VLF_FILE) {
200             enum vlog_level level = module->levels[facility];
201             if (level > module->min_level) {
202                 module->min_level = level;
203             }
204         }
205     }
206 }
207
208 static void
209 set_facility_level(enum vlog_facility facility, struct vlog_module *module,
210                    enum vlog_level level)
211 {
212     assert(facility >= 0 && facility < VLF_N_FACILITIES);
213     assert(level < VLL_N_LEVELS);
214
215     if (!module) {
216         struct vlog_module **mp;
217
218         for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
219             (*mp)->levels[facility] = level;
220             update_min_level(*mp);
221         }
222     } else {
223         module->levels[facility] = level;
224         update_min_level(module);
225     }
226 }
227
228 /* Sets the logging level for the given 'module' and 'facility' to 'level'.  A
229  * null 'module' or a 'facility' of VLF_ANY_FACILITY is treated as a wildcard
230  * across all modules or facilities, respectively. */
231 void
232 vlog_set_levels(struct vlog_module *module, enum vlog_facility facility,
233                 enum vlog_level level)
234 {
235     assert(facility < VLF_N_FACILITIES || facility == VLF_ANY_FACILITY);
236     if (facility == VLF_ANY_FACILITY) {
237         for (facility = 0; facility < VLF_N_FACILITIES; facility++) {
238             set_facility_level(facility, module, level);
239         }
240     } else {
241         set_facility_level(facility, module, level);
242     }
243 }
244
245 static void
246 do_set_pattern(enum vlog_facility facility, const char *pattern)
247 {
248     struct facility *f = &facilities[facility];
249     if (!f->default_pattern) {
250         free(f->pattern);
251     } else {
252         f->default_pattern = false;
253     }
254     f->pattern = xstrdup(pattern);
255 }
256
257 /* Sets the pattern for the given 'facility' to 'pattern'. */
258 void
259 vlog_set_pattern(enum vlog_facility facility, const char *pattern)
260 {
261     assert(facility < VLF_N_FACILITIES || facility == VLF_ANY_FACILITY);
262     if (facility == VLF_ANY_FACILITY) {
263         for (facility = 0; facility < VLF_N_FACILITIES; facility++) {
264             do_set_pattern(facility, pattern);
265         }
266     } else {
267         do_set_pattern(facility, pattern);
268     }
269 }
270
271 /* Sets the name of the log file used by VLF_FILE to 'file_name', or to the
272  * default file name if 'file_name' is null.  Returns 0 if successful,
273  * otherwise a positive errno value. */
274 int
275 vlog_set_log_file(const char *file_name)
276 {
277     char *old_log_file_name;
278     struct vlog_module **mp;
279     int error;
280
281     /* Close old log file. */
282     if (log_fd >= 0) {
283         VLOG_INFO("closing log file");
284         close(log_fd);
285         log_fd = -1;
286     }
287
288     /* Update log file name and free old name.  The ordering is important
289      * because 'file_name' might be 'log_file_name' or some suffix of it. */
290     old_log_file_name = log_file_name;
291     log_file_name = (file_name
292                      ? xstrdup(file_name)
293                      : xasprintf("%s/%s.log", ovs_logdir(), program_name));
294     free(old_log_file_name);
295     file_name = NULL;           /* Might have been freed. */
296
297     /* Open new log file and update min_levels[] to reflect whether we actually
298      * have a log_file. */
299     log_fd = open(log_file_name, O_WRONLY | O_CREAT | O_APPEND, 0666);
300     for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
301         update_min_level(*mp);
302     }
303
304     /* Log success or failure. */
305     if (log_fd < 0) {
306         VLOG_WARN("failed to open %s for logging: %s",
307                   log_file_name, ovs_strerror(errno));
308         error = errno;
309     } else {
310         VLOG_INFO("opened log file %s", log_file_name);
311         error = 0;
312     }
313
314     return error;
315 }
316
317 /* Closes and then attempts to re-open the current log file.  (This is useful
318  * just after log rotation, to ensure that the new log file starts being used.)
319  * Returns 0 if successful, otherwise a positive errno value. */
320 int
321 vlog_reopen_log_file(void)
322 {
323     struct stat old, new;
324
325     /* Skip re-opening if there's nothing to reopen. */
326     if (!log_file_name) {
327         return 0;
328     }
329
330     /* Skip re-opening if it would be a no-op because the old and new files are
331      * the same.  (This avoids writing "closing log file" followed immediately
332      * by "opened log file".) */
333     if (log_fd >= 0
334         && !fstat(log_fd, &old)
335         && !stat(log_file_name, &new)
336         && old.st_dev == new.st_dev
337         && old.st_ino == new.st_ino) {
338         return 0;
339     }
340
341     return vlog_set_log_file(log_file_name);
342 }
343
344 /* Set debugging levels.  Returns null if successful, otherwise an error
345  * message that the caller must free(). */
346 char *
347 vlog_set_levels_from_string(const char *s_)
348 {
349     char *s = xstrdup(s_);
350     char *save_ptr = NULL;
351     char *msg = NULL;
352     char *word;
353
354     word = strtok_r(s, " ,:\t", &save_ptr);
355     if (word && !strcasecmp(word, "PATTERN")) {
356         enum vlog_facility facility;
357
358         word = strtok_r(NULL, " ,:\t", &save_ptr);
359         if (!word) {
360             msg = xstrdup("missing facility");
361             goto exit;
362         }
363
364         facility = (!strcasecmp(word, "ANY")
365                     ? VLF_ANY_FACILITY
366                     : vlog_get_facility_val(word));
367         if (facility == VLF_N_FACILITIES) {
368             msg = xasprintf("unknown facility \"%s\"", word);
369             goto exit;
370         }
371         vlog_set_pattern(facility, save_ptr);
372     } else {
373         struct vlog_module *module = NULL;
374         enum vlog_level level = VLL_N_LEVELS;
375         enum vlog_facility facility = VLF_N_FACILITIES;
376
377         for (; word != NULL; word = strtok_r(NULL, " ,:\t", &save_ptr)) {
378             if (!strcasecmp(word, "ANY")) {
379                 continue;
380             } else if (vlog_get_facility_val(word) != VLF_N_FACILITIES) {
381                 if (facility != VLF_N_FACILITIES) {
382                     msg = xstrdup("cannot specify multiple facilities");
383                     goto exit;
384                 }
385                 facility = vlog_get_facility_val(word);
386             } else if (vlog_get_level_val(word) != VLL_N_LEVELS) {
387                 if (level != VLL_N_LEVELS) {
388                     msg = xstrdup("cannot specify multiple levels");
389                     goto exit;
390                 }
391                 level = vlog_get_level_val(word);
392             } else if (vlog_module_from_name(word)) {
393                 if (module) {
394                     msg = xstrdup("cannot specify multiple modules");
395                     goto exit;
396                 }
397                 module = vlog_module_from_name(word);
398             } else {
399                 msg = xasprintf("no facility, level, or module \"%s\"", word);
400                 goto exit;
401             }
402         }
403
404         if (facility == VLF_N_FACILITIES) {
405             facility = VLF_ANY_FACILITY;
406         }
407         if (level == VLL_N_LEVELS) {
408             level = VLL_DBG;
409         }
410         vlog_set_levels(module, facility, level);
411     }
412
413 exit:
414     free(s);
415     return msg;
416 }
417
418 /* Set debugging levels.  Abort with an error message if 's' is invalid. */
419 void
420 vlog_set_levels_from_string_assert(const char *s)
421 {
422     char *error = vlog_set_levels_from_string(s);
423     if (error) {
424         ovs_fatal(0, "%s", error);
425     }
426 }
427
428 /* If 'arg' is null, configure maximum verbosity.  Otherwise, sets
429  * configuration according to 'arg' (see vlog_set_levels_from_string()). */
430 void
431 vlog_set_verbosity(const char *arg)
432 {
433     if (arg) {
434         char *msg = vlog_set_levels_from_string(arg);
435         if (msg) {
436             ovs_fatal(0, "processing \"%s\": %s", arg, msg);
437         }
438     } else {
439         vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_DBG);
440     }
441 }
442
443 static void
444 vlog_unixctl_set(struct unixctl_conn *conn, int argc, const char *argv[],
445                  void *aux OVS_UNUSED)
446 {
447     int i;
448
449     for (i = 1; i < argc; i++) {
450         char *msg = vlog_set_levels_from_string(argv[i]);
451         if (msg) {
452             unixctl_command_reply_error(conn, msg);
453             free(msg);
454             return;
455         }
456     }
457     unixctl_command_reply(conn, NULL);
458 }
459
460 static void
461 vlog_unixctl_list(struct unixctl_conn *conn, int argc OVS_UNUSED,
462                   const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
463 {
464     char *msg = vlog_get_levels();
465     unixctl_command_reply(conn, msg);
466     free(msg);
467 }
468
469 static void
470 vlog_unixctl_reopen(struct unixctl_conn *conn, int argc OVS_UNUSED,
471                     const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
472 {
473     if (log_file_name) {
474         int error = vlog_reopen_log_file();
475         if (error) {
476             unixctl_command_reply_error(conn, ovs_strerror(errno));
477         } else {
478             unixctl_command_reply(conn, NULL);
479         }
480     } else {
481         unixctl_command_reply_error(conn, "Logging to file not configured");
482     }
483 }
484
485 static void
486 set_all_rate_limits(bool enable)
487 {
488     struct vlog_module **mp;
489
490     for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
491         (*mp)->honor_rate_limits = enable;
492     }
493 }
494
495 static void
496 set_rate_limits(struct unixctl_conn *conn, int argc,
497                 const char *argv[], bool enable)
498 {
499     if (argc > 1) {
500         int i;
501
502         for (i = 1; i < argc; i++) {
503             if (!strcasecmp(argv[i], "ANY")) {
504                 set_all_rate_limits(enable);
505             } else {
506                 struct vlog_module *module = vlog_module_from_name(argv[i]);
507                 if (!module) {
508                     unixctl_command_reply_error(conn, "unknown module");
509                     return;
510                 }
511                 module->honor_rate_limits = enable;
512             }
513         }
514     } else {
515         set_all_rate_limits(enable);
516     }
517     unixctl_command_reply(conn, NULL);
518 }
519
520 static void
521 vlog_enable_rate_limit(struct unixctl_conn *conn, int argc,
522                        const char *argv[], void *aux OVS_UNUSED)
523 {
524     set_rate_limits(conn, argc, argv, true);
525 }
526
527 static void
528 vlog_disable_rate_limit(struct unixctl_conn *conn, int argc,
529                        const char *argv[], void *aux OVS_UNUSED)
530 {
531     set_rate_limits(conn, argc, argv, false);
532 }
533
534 /* Initializes the logging subsystem and registers its unixctl server
535  * commands. */
536 void
537 vlog_init(void)
538 {
539     static char *program_name_copy;
540     time_t now;
541
542     if (vlog_inited) {
543         return;
544     }
545     vlog_inited = true;
546
547     /* openlog() is allowed to keep the pointer passed in, without making a
548      * copy.  The daemonize code sometimes frees and replaces 'program_name',
549      * so make a private copy just for openlog().  (We keep a pointer to the
550      * private copy to suppress memory leak warnings in case openlog() does
551      * make its own copy.) */
552     program_name_copy = program_name ? xstrdup(program_name) : NULL;
553     openlog(program_name_copy, LOG_NDELAY, LOG_DAEMON);
554
555     now = time_wall();
556     if (now < 0) {
557         char *s = xastrftime("%a, %d %b %Y %H:%M:%S", now, true);
558         VLOG_ERR("current time is negative: %s (%ld)", s, (long int) now);
559         free(s);
560     }
561
562     unixctl_command_register(
563         "vlog/set", "{spec | PATTERN:facility:pattern}",
564         1, INT_MAX, vlog_unixctl_set, NULL);
565     unixctl_command_register("vlog/list", "", 0, 0, vlog_unixctl_list, NULL);
566     unixctl_command_register("vlog/enable-rate-limit", "[module]...",
567                              0, INT_MAX, vlog_enable_rate_limit, NULL);
568     unixctl_command_register("vlog/disable-rate-limit", "[module]...",
569                              0, INT_MAX, vlog_disable_rate_limit, NULL);
570     unixctl_command_register("vlog/reopen", "", 0, 0,
571                              vlog_unixctl_reopen, NULL);
572 }
573
574 /* Closes the logging subsystem. */
575 void
576 vlog_exit(void)
577 {
578     if (vlog_inited) {
579         closelog();
580         vlog_inited = false;
581     }
582 }
583
584 /* Print the current logging level for each module. */
585 char *
586 vlog_get_levels(void)
587 {
588     struct ds s = DS_EMPTY_INITIALIZER;
589     struct vlog_module **mp;
590     struct svec lines = SVEC_EMPTY_INITIALIZER;
591     char *line;
592     size_t i;
593
594     ds_put_format(&s, "                 console    syslog    file\n");
595     ds_put_format(&s, "                 -------    ------    ------\n");
596
597     for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
598         struct ds line;
599
600         ds_init(&line);
601         ds_put_format(&line, "%-16s  %4s       %4s       %4s",
602                       vlog_get_module_name(*mp),
603                       vlog_get_level_name(vlog_get_level(*mp, VLF_CONSOLE)),
604                       vlog_get_level_name(vlog_get_level(*mp, VLF_SYSLOG)),
605                       vlog_get_level_name(vlog_get_level(*mp, VLF_FILE)));
606         if (!(*mp)->honor_rate_limits) {
607             ds_put_cstr(&line, "    (rate limiting disabled)");
608         }
609         ds_put_char(&line, '\n');
610
611         svec_add_nocopy(&lines, ds_steal_cstr(&line));
612     }
613
614     svec_sort(&lines);
615     SVEC_FOR_EACH (i, line, &lines) {
616         ds_put_cstr(&s, line);
617     }
618     svec_destroy(&lines);
619
620     return ds_cstr(&s);
621 }
622
623 /* Returns true if a log message emitted for the given 'module' and 'level'
624  * would cause some log output, false if that module and level are completely
625  * disabled. */
626 bool
627 vlog_is_enabled(const struct vlog_module *module, enum vlog_level level)
628 {
629     return module->min_level >= level;
630 }
631
632 static const char *
633 fetch_braces(const char *p, const char *def, char *out, size_t out_size)
634 {
635     if (*p == '{') {
636         size_t n = strcspn(p + 1, "}");
637         size_t n_copy = MIN(n, out_size - 1);
638         memcpy(out, p + 1, n_copy);
639         out[n_copy] = '\0';
640         p += n + 2;
641     } else {
642         ovs_strlcpy(out, def, out_size);
643     }
644     return p;
645 }
646
647 static void
648 format_log_message(const struct vlog_module *module, enum vlog_level level,
649                    enum vlog_facility facility, unsigned int msg_num,
650                    const char *message, va_list args_, struct ds *s)
651 {
652     char tmp[128];
653     va_list args;
654     const char *p;
655
656     ds_clear(s);
657     for (p = facilities[facility].pattern; *p != '\0'; ) {
658         const char *subprogram_name;
659         enum { LEFT, RIGHT } justify = RIGHT;
660         int pad = '0';
661         size_t length, field, used;
662
663         if (*p != '%') {
664             ds_put_char(s, *p++);
665             continue;
666         }
667
668         p++;
669         if (*p == '-') {
670             justify = LEFT;
671             p++;
672         }
673         if (*p == '0') {
674             pad = '0';
675             p++;
676         }
677         field = 0;
678         while (isdigit((unsigned char)*p)) {
679             field = (field * 10) + (*p - '0');
680             p++;
681         }
682
683         length = s->length;
684         switch (*p++) {
685         case 'A':
686             ds_put_cstr(s, program_name);
687             break;
688         case 'c':
689             p = fetch_braces(p, "", tmp, sizeof tmp);
690             ds_put_cstr(s, vlog_get_module_name(module));
691             break;
692         case 'd':
693             p = fetch_braces(p, "%Y-%m-%d %H:%M:%S", tmp, sizeof tmp);
694             ds_put_strftime(s, tmp, time_wall(), false);
695             break;
696         case 'D':
697             p = fetch_braces(p, "%Y-%m-%d %H:%M:%S", tmp, sizeof tmp);
698             ds_put_strftime(s, tmp, time_wall(), true);
699             break;
700         case 'm':
701             /* Format user-supplied log message and trim trailing new-lines. */
702             length = s->length;
703             va_copy(args, args_);
704             ds_put_format_valist(s, message, args);
705             va_end(args);
706             while (s->length > length && s->string[s->length - 1] == '\n') {
707                 s->length--;
708             }
709             break;
710         case 'N':
711             ds_put_format(s, "%u", msg_num);
712             break;
713         case 'n':
714             ds_put_char(s, '\n');
715             break;
716         case 'p':
717             ds_put_cstr(s, vlog_get_level_name(level));
718             break;
719         case 'P':
720             ds_put_format(s, "%ld", (long int) getpid());
721             break;
722         case 'r':
723             ds_put_format(s, "%lld", time_msec() - time_boot_msec());
724             break;
725         case 't':
726             subprogram_name = get_subprogram_name();
727             ds_put_cstr(s, subprogram_name[0] ? subprogram_name : "main");
728             break;
729         case 'T':
730             subprogram_name = get_subprogram_name();
731             if (subprogram_name[0]) {
732                 ds_put_format(s, "(%s)", subprogram_name);
733             }
734             break;
735         default:
736             ds_put_char(s, p[-1]);
737             break;
738         }
739         used = s->length - length;
740         if (used < field) {
741             size_t n_pad = field - used;
742             if (justify == RIGHT) {
743                 ds_put_uninit(s, n_pad);
744                 memmove(&s->string[length + n_pad], &s->string[length], used);
745                 memset(&s->string[length], pad, n_pad);
746             } else {
747                 ds_put_char_multiple(s, pad, n_pad);
748             }
749         }
750     }
751 }
752
753 /* Writes 'message' to the log at the given 'level' and as coming from the
754  * given 'module'.
755  *
756  * Guaranteed to preserve errno. */
757 void
758 vlog_valist(const struct vlog_module *module, enum vlog_level level,
759             const char *message, va_list args)
760 {
761     bool log_to_console = module->levels[VLF_CONSOLE] >= level;
762     bool log_to_syslog = module->levels[VLF_SYSLOG] >= level;
763     bool log_to_file = module->levels[VLF_FILE] >= level && log_fd >= 0;
764     if (log_to_console || log_to_syslog || log_to_file) {
765         int save_errno = errno;
766         static unsigned int msg_num;
767         struct ds s;
768
769         vlog_init();
770
771         ds_init(&s);
772         ds_reserve(&s, 1024);
773         msg_num++;
774
775         if (log_to_console) {
776             format_log_message(module, level, VLF_CONSOLE, msg_num,
777                                message, args, &s);
778             ds_put_char(&s, '\n');
779             fputs(ds_cstr(&s), stderr);
780         }
781
782         if (log_to_syslog) {
783             int syslog_level = syslog_levels[level];
784             char *save_ptr = NULL;
785             char *line;
786
787             format_log_message(module, level, VLF_SYSLOG, msg_num,
788                                message, args, &s);
789             for (line = strtok_r(s.string, "\n", &save_ptr); line;
790                  line = strtok_r(NULL, "\n", &save_ptr)) {
791                 syslog(syslog_level, "%s", line);
792             }
793         }
794
795         if (log_to_file) {
796             format_log_message(module, level, VLF_FILE, msg_num,
797                                message, args, &s);
798             ds_put_char(&s, '\n');
799             ignore(write(log_fd, s.string, s.length));
800         }
801
802         ds_destroy(&s);
803         errno = save_errno;
804     }
805 }
806
807 void
808 vlog(const struct vlog_module *module, enum vlog_level level,
809      const char *message, ...)
810 {
811     va_list args;
812
813     va_start(args, message);
814     vlog_valist(module, level, message, args);
815     va_end(args);
816 }
817
818 /* Logs 'message' to 'module' at maximum verbosity, then exits with a failure
819  * exit code.  Always writes the message to stderr, even if the console
820  * facility is disabled.
821  *
822  * Choose this function instead of vlog_abort_valist() if the daemon monitoring
823  * facility shouldn't automatically restart the current daemon.  */
824 void
825 vlog_fatal_valist(const struct vlog_module *module_,
826                   const char *message, va_list args)
827 {
828     struct vlog_module *module = CONST_CAST(struct vlog_module *, module_);
829
830     /* Don't log this message to the console to avoid redundancy with the
831      * message written by the later ovs_fatal_valist(). */
832     module->levels[VLF_CONSOLE] = VLL_OFF;
833
834     vlog_valist(module, VLL_EMER, message, args);
835     ovs_fatal_valist(0, message, args);
836 }
837
838 /* Logs 'message' to 'module' at maximum verbosity, then exits with a failure
839  * exit code.  Always writes the message to stderr, even if the console
840  * facility is disabled.
841  *
842  * Choose this function instead of vlog_abort() if the daemon monitoring
843  * facility shouldn't automatically restart the current daemon.  */
844 void
845 vlog_fatal(const struct vlog_module *module, const char *message, ...)
846 {
847     va_list args;
848
849     va_start(args, message);
850     vlog_fatal_valist(module, message, args);
851     va_end(args);
852 }
853
854 /* Logs 'message' to 'module' at maximum verbosity, then calls abort().  Always
855  * writes the message to stderr, even if the console facility is disabled.
856  *
857  * Choose this function instead of vlog_fatal_valist() if the daemon monitoring
858  * facility should automatically restart the current daemon.  */
859 void
860 vlog_abort_valist(const struct vlog_module *module_,
861                   const char *message, va_list args)
862 {
863     struct vlog_module *module = (struct vlog_module *) module_;
864
865     /* Don't log this message to the console to avoid redundancy with the
866      * message written by the later ovs_abort_valist(). */
867     module->levels[VLF_CONSOLE] = VLL_OFF;
868
869     vlog_valist(module, VLL_EMER, message, args);
870     ovs_abort_valist(0, message, args);
871 }
872
873 /* Logs 'message' to 'module' at maximum verbosity, then calls abort().  Always
874  * writes the message to stderr, even if the console facility is disabled.
875  *
876  * Choose this function instead of vlog_fatal() if the daemon monitoring
877  * facility should automatically restart the current daemon.  */
878 void
879 vlog_abort(const struct vlog_module *module, const char *message, ...)
880 {
881     va_list args;
882
883     va_start(args, message);
884     vlog_abort_valist(module, message, args);
885     va_end(args);
886 }
887
888 bool
889 vlog_should_drop(const struct vlog_module *module, enum vlog_level level,
890                  struct vlog_rate_limit *rl)
891 {
892     if (!module->honor_rate_limits) {
893         return false;
894     }
895
896     if (!vlog_is_enabled(module, level)) {
897         return true;
898     }
899
900     xpthread_mutex_lock(&rl->mutex);
901     if (!token_bucket_withdraw(&rl->token_bucket, VLOG_MSG_TOKENS)) {
902         time_t now = time_now();
903         if (!rl->n_dropped) {
904             rl->first_dropped = now;
905         }
906         rl->last_dropped = now;
907         rl->n_dropped++;
908         xpthread_mutex_unlock(&rl->mutex);
909         return true;
910     }
911
912     if (!rl->n_dropped) {
913         xpthread_mutex_unlock(&rl->mutex);
914     } else {
915         time_t now = time_now();
916         unsigned int n_dropped = rl->n_dropped;
917         unsigned int first_dropped_elapsed = now - rl->first_dropped;
918         unsigned int last_dropped_elapsed = now - rl->last_dropped;
919         rl->n_dropped = 0;
920         xpthread_mutex_unlock(&rl->mutex);
921
922         vlog(module, level,
923              "Dropped %u log messages in last %u seconds (most recently, "
924              "%u seconds ago) due to excessive rate",
925              n_dropped, first_dropped_elapsed, last_dropped_elapsed);
926     }
927
928     return false;
929 }
930
931 void
932 vlog_rate_limit(const struct vlog_module *module, enum vlog_level level,
933                 struct vlog_rate_limit *rl, const char *message, ...)
934 {
935     if (!vlog_should_drop(module, level, rl)) {
936         va_list args;
937
938         va_start(args, message);
939         vlog_valist(module, level, message, args);
940         va_end(args);
941     }
942 }
943
944 void
945 vlog_usage(void)
946 {
947     printf("\nLogging options:\n"
948            "  -v, --verbose=[SPEC]    set logging levels\n"
949            "  -v, --verbose           set maximum verbosity level\n"
950            "  --log-file[=FILE]       enable logging to specified FILE\n"
951            "                          (default: %s/%s.log)\n",
952            ovs_logdir(), program_name);
953 }