vlog: Make the vlog module catalog program-specific.
authorBen Pfaff <blp@nicira.com>
Fri, 16 Jul 2010 17:53:14 +0000 (10:53 -0700)
committerBen Pfaff <blp@nicira.com>
Wed, 21 Jul 2010 22:47:09 +0000 (15:47 -0700)
Until now, the collection of vlog modules supported by a given OVS program
was not specific to that program.  That means that, for example, even
though ovs-dpctl does not have anything to do with jsonrpc, it still has
a vlog module for it.  This is confusing, at best.

This commit fixes the problem on some systems, in particular on ones that
use GCC and the GNU linker.  It uses the feature of the GNU linker
described in its manual as:

    If an orphaned section's name is representable as a C identifier then
    the linker will automatically see PROVIDE two symbols: __start_SECNAME
    and __end_SECNAME, where SECNAME is the name of the section.  These
    indicate the start address and end address of the orphaned section
    respectively.

Systems that don't support these features retain the earlier behavior.

This commit also fixes the annoyance that modifying lib/vlog-modules.def
causes all sources files that #include "vlog.h" to recompile.

16 files changed:
build-aux/check-vlog-modules [new file with mode: 0755]
configure.ac
extras/ezio/ovs-switchui.c
lib/automake.mk
lib/stream.c
lib/stream.h
lib/vlog.c
lib/vlog.h
m4/openvswitch.m4
tests/test-lockfile.c
tests/test-reconnect.c
tests/test-stp.c
tests/test-vconn.c
utilities/nlmon.c
utilities/ovs-vsctl.c
vswitchd/ovs-brcompatd.c

diff --git a/build-aux/check-vlog-modules b/build-aux/check-vlog-modules
new file mode 100755 (executable)
index 0000000..d40c048
--- /dev/null
@@ -0,0 +1,66 @@
+#! /bin/sh
+
+if test "$1" = --help; then
+    cat <<EOF
+$0: cross-check declared and defined vlog modules
+usage: $0 [--help]
+
+Must be run from the top-level source directory.
+
+On systems that don't support user-defined section names, the 'vlog'
+logging subsystem requires the list of modules in lib/vlog-modules.def
+to match the set of vlog modules actually used by the source files.
+However, most Open vSwitch development happens on systems that do
+support user-defined section names and don't have this requirement.
+This utility runs automatically at build time to check this
+requirement "by hand", so that Open vSwitch developers don't
+accidentally break the build for others.
+EOF
+    exit 0
+elif test "$#" != 0; then
+    echo "no arguments accepted (use --help for help)"
+    exit 1
+elif test ! -e lib/vlog-modules.def; then
+    echo "must run from the top-level source directory (use --help for help)"
+    exit 1
+fi
+
+# We can only get a list of source files if this is a Git checkout.
+if test -e .git && (git --version) >/dev/null 2>&1; then
+    :
+else
+    exit 0
+fi
+
+# Get the list of modules declared in lib/vlog-modules.def.
+vlog_modules=`
+    sed -n 's/^VLOG_MODULE(\([_a-zA-Z0-9]\{1,\}\)).*$/\1/p' \
+    lib/vlog-modules.def \
+    | LC_ALL=C sort -u | xargs echo`
+
+# Get the list of modules defined in some source file.
+src_modules=`
+    git grep -h -E '^[         ]*VLOG_DEFINE(_THIS)?_MODULE\([_a-zA-Z0-9]+\)[  ]*$' \
+    | sed 's/.*(\([_a-zA-Z0-9]\{1,\}\)).*/\1/' \
+    | LC_ALL=C sort -u \
+    | xargs echo`
+
+rc=0
+
+for module in $vlog_modules; do
+    case " $src_modules " in
+        *" $module "*) ;;
+        *) echo "vlog module $module is declared in lib/vlog-modules.def but not defined by any source file";
+            rc=1 ;;
+    esac
+done
+
+for module in $src_modules; do
+    case " $vlog_modules " in
+        *" $module "*) ;;
+        *) echo "vlog module $module is defined in a source file but not declared in lib/vlog-modules.def";
+            rc=1 ;;
+    esac
+done
+
+exit $rc
index 5dd6590edea69a752a019547e2aee0bf4711db55..dad2fb9efad577183b768368f86a6ee24ac4f52d 100644 (file)
@@ -66,6 +66,7 @@ OVS_CHECK_MALLOC_HOOKS
 OVS_CHECK_VALGRIND
 OVS_CHECK_TTY_LOCK_DIR
 OVS_CHECK_SOCKET_LIBS
 OVS_CHECK_VALGRIND
 OVS_CHECK_TTY_LOCK_DIR
 OVS_CHECK_SOCKET_LIBS
+OVS_CHECK_LINKER_SECTIONS
 
 AC_CHECK_FUNCS([strsignal])
 
 
 AC_CHECK_FUNCS([strsignal])
 
index 092eb1e5d327243bf4c7b43f656d69a1bfca21b6..6f433a3f63f1024c8618c56be74025aea650fdaf 100644 (file)
@@ -149,7 +149,7 @@ main(int argc, char *argv[])
     set_program_name(argv[0]);
     parse_options(argc, argv);
     signal(SIGPIPE, SIG_IGN);
     set_program_name(argv[0]);
     parse_options(argc, argv);
     signal(SIGPIPE, SIG_IGN);
-    vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_EMER);
+    vlog_set_levels(NULL, VLF_CONSOLE, VLL_EMER);
     init_reboot_notifier();
 
     argc -= optind;
     init_reboot_notifier();
 
     argc -= optind;
index 046e9ab6e56115e853ce098b6bfc011da1874974..3bf9da1ce5a8c45f1ee078078d7a72cd32bba6ab 100644 (file)
@@ -263,30 +263,8 @@ lib/coverage-counters.c: $(COVERAGE_FILES) lib/coverage-scan.pl
        mv $@.tmp $@
 EXTRA_DIST += lib/coverage-scan.pl
 
        mv $@.tmp $@
 EXTRA_DIST += lib/coverage-scan.pl
 
-
-# Make sure that every vlog module listed in vlog-modules.def is
-# actually used somewhere.
-ALL_LOCAL += check-for-unused-vlog-modules
-check-for-unused-vlog-modules:
-       if test -e $(srcdir)/.git && (git --version) >/dev/null 2>&1; then    \
-         cd $(srcdir);                                                       \
-         decl_vlog=`sed -n 's/^VLOG_MODULE(\([_a-z0-9]\{1,\}\)).*$$/\1/p'    \
-                    lib/vlog-modules.def |                                   \
-                     LC_ALL=C sort -u |                                              \
-                     xargs echo`;                                            \
-         used_vlog=`git grep VLOG_DEFINE_THIS_MODULE |                       \
-                    sed -n 's/.*VLOG_DEFINE_THIS_MODULE(\([a-z_0-9]\{1,\}\)).*/\1/p' |       \
-                    LC_ALL=C sort -u |                                       \
-                     xargs echo`;                                            \
-         rc=0;                                                               \
-         for decl in $$decl_vlog; do                                         \
-            case " $$used_vlog " in                                          \
-             *" $$decl "*) ;;                                                \
-             *) echo "vlog module $$decl is declared in lib/vlog-modules.def \
-but not used by any source file";                                            \
-                 rc=1 ;;                                                     \
-            esac                                                             \
-          done;                                                                      \
-         exit $$rc;                                                          \
-       fi
-.PHONY: check-for-unused-vlog-modules
+ALL_LOCAL += check-vlog-modules
+check-vlog-modules:
+       cd $(srcdir) && build-aux/check-vlog-modules
+.PHONY: check-vlog-modules
+EXTRA_DIST += build-aux/check-vlog-modules
index 4d894e7ede743e1640854a83d14589aae97a9eeb..43c95b6bc2836d608d6d4a4d901fb709e93c35ff 100644 (file)
@@ -769,7 +769,7 @@ stream_content_type_to_string(enum stream_content_type type)
 void
 stream_report_content(const void *data, size_t size,
                       enum stream_content_type expected_type,
 void
 stream_report_content(const void *data, size_t size,
                       enum stream_content_type expected_type,
-                      enum vlog_module module, const char *stream_name)
+                      struct vlog_module *module, const char *stream_name)
 {
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
     enum stream_content_type actual_type;
 {
     static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 5);
     enum stream_content_type actual_type;
index 256667e6852039e057dc0cc33a96b1048a658914..5c536c6ae5ff1af0548e4bb5f715ebb9a50cb12b 100644 (file)
@@ -84,6 +84,6 @@ enum stream_content_type {
 };
 
 void stream_report_content(const void *, size_t, enum stream_content_type,
 };
 
 void stream_report_content(const void *, size_t, enum stream_content_type,
-                           enum vlog_module, const char *stream_name);
+                           struct vlog_module *, const char *stream_name);
 
 #endif /* stream.h */
 
 #endif /* stream.h */
index 38871295020fd919b2515ce24dfb9360ee810845..1c6d25bbd52948a38c5120fb1ef152c0b6dd7a5e 100644 (file)
@@ -49,12 +49,24 @@ static int syslog_levels[VLL_N_LEVELS] = {
 #undef VLOG_LEVEL
 };
 
 #undef VLOG_LEVEL
 };
 
-/* Name for each logging module */
-static const char *module_names[VLM_N_MODULES] = { 
-#define VLOG_MODULE(NAME) #NAME,
+/* The log modules. */
+#if USE_LINKER_SECTIONS
+extern struct vlog_module *__start_vlog_modules[];
+extern struct vlog_module *__stop_vlog_modules[];
+#define vlog_modules __start_vlog_modules
+#define n_vlog_modules (__stop_vlog_modules - __start_vlog_modules)
+#else
+#define VLOG_MODULE VLOG_DEFINE_MODULE__
+#include "vlog-modules.def"
+#undef VLOG_MODULE
+
+struct vlog_module *vlog_modules[] = {
+#define VLOG_MODULE(NAME) &VLM_##NAME,
 #include "vlog-modules.def"
 #undef VLOG_MODULE
 };
 #include "vlog-modules.def"
 #undef VLOG_MODULE
 };
+#define n_vlog_modules ARRAY_SIZE(vlog_modules)
+#endif
 
 /* Information about each facility. */
 struct facility {
 
 /* Information about each facility. */
 struct facility {
@@ -68,21 +80,6 @@ static struct facility facilities[VLF_N_FACILITIES] = {
 #undef VLOG_FACILITY
 };
 
 #undef VLOG_FACILITY
 };
 
-/* Current log levels. */
-static int levels[VLM_N_MODULES][VLF_N_FACILITIES] = {
-#define VLOG_MODULE(NAME) { VLL_INFO, VLL_INFO, VLL_INFO },
-#include "vlog-modules.def"
-#undef VLOG_MODULE
-};
-
-/* For fast checking whether we're logging anything for a given module and
- * level.*/
-enum vlog_level min_vlog_levels[VLM_N_MODULES] = {
-#define VLOG_MODULE(NAME) VLL_INFO,
-#include "vlog-modules.def"
-#undef VLOG_MODULE
-};
-
 /* Time at which vlog was initialized, in milliseconds. */
 static long long int boot_time;
 
 /* Time at which vlog was initialized, in milliseconds. */
 static long long int boot_time;
 
@@ -93,7 +90,7 @@ static FILE *log_file;
 /* vlog initialized? */
 static bool vlog_inited;
 
 /* vlog initialized? */
 static bool vlog_inited;
 
-static void format_log_message(enum vlog_module, enum vlog_level,
+static void format_log_message(const struct vlog_module *, enum vlog_level,
                                enum vlog_facility, unsigned int msg_num,
                                const char *message, va_list, struct ds *)
     PRINTF_FORMAT(5, 0);
                                enum vlog_facility, unsigned int msg_num,
                                const char *message, va_list, struct ds *)
     PRINTF_FORMAT(5, 0);
@@ -154,64 +151,76 @@ vlog_get_facility_val(const char *name)
 }
 
 /* Returns the name for logging module 'module'. */
 }
 
 /* Returns the name for logging module 'module'. */
-const char *vlog_get_module_name(enum vlog_module module) 
+const char *
+vlog_get_module_name(const struct vlog_module *module)
 {
 {
-    assert(module < VLM_N_MODULES);
-    return module_names[module];
+    return module->name;
 }
 
 }
 
-/* Returns the logging module named 'name', or VLM_N_MODULES if 'name' is not
- * the name of a logging module. */
-enum vlog_module
-vlog_get_module_val(const char *name) 
+/* Returns the logging module named 'name', or NULL if 'name' is not the name
+ * of a logging module. */
+struct vlog_module *
+vlog_module_from_name(const char *name)
 {
 {
-    return search_name_array(name, module_names, ARRAY_SIZE(module_names));
+    struct vlog_module **mp;
+
+    for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
+        if (!strcasecmp(name, (*mp)->name)) {
+            return *mp;
+        }
+    }
+    return NULL;
 }
 
 /* Returns the current logging level for the given 'module' and 'facility'. */
 enum vlog_level
 }
 
 /* Returns the current logging level for the given 'module' and 'facility'. */
 enum vlog_level
-vlog_get_level(enum vlog_module module, enum vlog_facility facility) 
+vlog_get_level(const struct vlog_module *module, enum vlog_facility facility) 
 {
 {
-    assert(module < VLM_N_MODULES);
     assert(facility < VLF_N_FACILITIES);
     assert(facility < VLF_N_FACILITIES);
-    return levels[module][facility];
+    return module->levels[facility];
 }
 
 static void
 }
 
 static void
-update_min_level(enum vlog_module module)
+update_min_level(struct vlog_module *module)
 {
 {
-    enum vlog_level min_level = VLL_EMER;
     enum vlog_facility facility;
 
     enum vlog_facility facility;
 
+    module->min_level = VLL_EMER;
     for (facility = 0; facility < VLF_N_FACILITIES; facility++) {
         if (log_file || facility != VLF_FILE) {
     for (facility = 0; facility < VLF_N_FACILITIES; facility++) {
         if (log_file || facility != VLF_FILE) {
-            min_level = MAX(min_level, levels[module][facility]); 
+            enum vlog_level level = module->levels[facility];
+            if (level < module->min_level) {
+                module->min_level = level;
+            }
         }
     }
         }
     }
-    min_vlog_levels[module] = min_level;
 }
 
 static void
 }
 
 static void
-set_facility_level(enum vlog_facility facility, enum vlog_module module,
+set_facility_level(enum vlog_facility facility, struct vlog_module *module,
                    enum vlog_level level)
 {
     assert(facility >= 0 && facility < VLF_N_FACILITIES);
     assert(level < VLL_N_LEVELS);
 
                    enum vlog_level level)
 {
     assert(facility >= 0 && facility < VLF_N_FACILITIES);
     assert(level < VLL_N_LEVELS);
 
-    if (module == VLM_ANY_MODULE) {
-        for (module = 0; module < VLM_N_MODULES; module++) {
-            levels[module][facility] = level;
-            update_min_level(module);
+    if (!module) {
+        struct vlog_module **mp;
+
+        for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
+            (*mp)->levels[facility] = level;
+            update_min_level(*mp);
         }
     } else {
         }
     } else {
-        levels[module][facility] = level;
+        module->levels[facility] = level;
         update_min_level(module);
     }
 }
 
         update_min_level(module);
     }
 }
 
-/* Sets the logging level for the given 'module' and 'facility' to 'level'. */
+/* Sets the logging level for the given 'module' and 'facility' to 'level'.  A
+ * null 'module' or a 'facility' of VLF_ANY_FACILITY is treated as a wildcard
+ * across all modules or facilities, respectively. */
 void
 void
-vlog_set_levels(enum vlog_module module, enum vlog_facility facility,
+vlog_set_levels(struct vlog_module *module, enum vlog_facility facility,
                 enum vlog_level level) 
 {
     assert(facility < VLF_N_FACILITIES || facility == VLF_ANY_FACILITY);
                 enum vlog_level level) 
 {
     assert(facility < VLF_N_FACILITIES || facility == VLF_ANY_FACILITY);
@@ -267,7 +276,7 @@ int
 vlog_set_log_file(const char *file_name)
 {
     char *old_log_file_name;
 vlog_set_log_file(const char *file_name)
 {
     char *old_log_file_name;
-    enum vlog_module module;
+    struct vlog_module **mp;
     int error;
 
     /* Close old log file. */
     int error;
 
     /* Close old log file. */
@@ -289,8 +298,8 @@ vlog_set_log_file(const char *file_name)
     /* Open new log file and update min_levels[] to reflect whether we actually
      * have a log_file. */
     log_file = fopen(log_file_name, "a");
     /* Open new log file and update min_levels[] to reflect whether we actually
      * have a log_file. */
     log_file = fopen(log_file_name, "a");
-    for (module = 0; module < VLM_N_MODULES; module++) {
-        update_min_level(module);
+    for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
+        update_min_level(*mp);
     }
 
     /* Log success or failure. */
     }
 
     /* Log success or failure. */
@@ -331,7 +340,7 @@ vlog_set_levels_from_string(const char *s_)
 
     for (module = strtok_r(s, ": \t", &save_ptr); module != NULL;
          module = strtok_r(NULL, ": \t", &save_ptr)) {
 
     for (module = strtok_r(s, ": \t", &save_ptr); module != NULL;
          module = strtok_r(NULL, ": \t", &save_ptr)) {
-        enum vlog_module e_module;
+        struct vlog_module *e_module;
         enum vlog_facility e_facility;
 
         facility = strtok_r(NULL, ":", &save_ptr);
         enum vlog_facility e_facility;
 
         facility = strtok_r(NULL, ":", &save_ptr);
@@ -355,10 +364,10 @@ vlog_set_levels_from_string(const char *s_)
             enum vlog_level e_level;
 
             if (!strcmp(module, "ANY")) {
             enum vlog_level e_level;
 
             if (!strcmp(module, "ANY")) {
-                e_module = VLM_ANY_MODULE;
+                e_module = NULL;
             } else {
             } else {
-                e_module = vlog_get_module_val(module);
-                if (e_module >= VLM_N_MODULES) {
+                e_module = vlog_module_from_name(module);
+                if (!e_module) {
                     char *msg = xasprintf("unknown module \"%s\"", module);
                     free(s);
                     return msg;
                     char *msg = xasprintf("unknown module \"%s\"", module);
                     free(s);
                     return msg;
@@ -391,7 +400,7 @@ vlog_set_verbosity(const char *arg)
             ovs_fatal(0, "processing \"%s\": %s", arg, msg);
         }
     } else {
             ovs_fatal(0, "processing \"%s\": %s", arg, msg);
         }
     } else {
-        vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_DBG);
+        vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_DBG);
     }
 }
 
     }
 }
 
@@ -473,17 +482,17 @@ char *
 vlog_get_levels(void)
 {
     struct ds s = DS_EMPTY_INITIALIZER;
 vlog_get_levels(void)
 {
     struct ds s = DS_EMPTY_INITIALIZER;
-    enum vlog_module module;
+    struct vlog_module **mp;
 
     ds_put_format(&s, "                 console    syslog    file\n");
     ds_put_format(&s, "                 -------    ------    ------\n");
 
 
     ds_put_format(&s, "                 console    syslog    file\n");
     ds_put_format(&s, "                 -------    ------    ------\n");
 
-    for (module = 0; module < VLM_N_MODULES; module++) {
+    for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
         ds_put_format(&s, "%-16s  %4s       %4s       %4s\n",
         ds_put_format(&s, "%-16s  %4s       %4s       %4s\n",
-           vlog_get_module_name(module),
-           vlog_get_level_name(vlog_get_level(module, VLF_CONSOLE)),
-           vlog_get_level_name(vlog_get_level(module, VLF_SYSLOG)),
-           vlog_get_level_name(vlog_get_level(module, VLF_FILE)));
+           vlog_get_module_name(*mp),
+           vlog_get_level_name(vlog_get_level(*mp, VLF_CONSOLE)),
+           vlog_get_level_name(vlog_get_level(*mp, VLF_SYSLOG)),
+           vlog_get_level_name(vlog_get_level(*mp, VLF_FILE)));
     }
 
     return ds_cstr(&s);
     }
 
     return ds_cstr(&s);
@@ -493,9 +502,9 @@ vlog_get_levels(void)
  * would cause some log output, false if that module and level are completely
  * disabled. */
 bool
  * would cause some log output, false if that module and level are completely
  * disabled. */
 bool
-vlog_is_enabled(enum vlog_module module, enum vlog_level level)
+vlog_is_enabled(const struct vlog_module *module, enum vlog_level level)
 {
 {
-    return min_vlog_levels[module] >= level;
+    return module->min_level >= level;
 }
 
 static const char *
 }
 
 static const char *
@@ -514,7 +523,7 @@ fetch_braces(const char *p, const char *def, char *out, size_t out_size)
 }
 
 static void
 }
 
 static void
-format_log_message(enum vlog_module module, enum vlog_level level,
+format_log_message(const struct vlog_module *module, enum vlog_level level,
                    enum vlog_facility facility, unsigned int msg_num,
                    const char *message, va_list args_, struct ds *s)
 {
                    enum vlog_facility facility, unsigned int msg_num,
                    const char *message, va_list args_, struct ds *s)
 {
@@ -609,12 +618,12 @@ format_log_message(enum vlog_module module, enum vlog_level level,
  *
  * Guaranteed to preserve errno. */
 void
  *
  * Guaranteed to preserve errno. */
 void
-vlog_valist(enum vlog_module module, enum vlog_level level,
+vlog_valist(const struct vlog_module *module, enum vlog_level level,
             const char *message, va_list args)
 {
             const char *message, va_list args)
 {
-    bool log_to_console = levels[module][VLF_CONSOLE] >= level;
-    bool log_to_syslog = levels[module][VLF_SYSLOG] >= level;
-    bool log_to_file = levels[module][VLF_FILE] >= level && log_file;
+    bool log_to_console = module->levels[VLF_CONSOLE] >= level;
+    bool log_to_syslog = module->levels[VLF_SYSLOG] >= level;
+    bool log_to_file = module->levels[VLF_FILE] >= level && log_file;
     if (log_to_console || log_to_syslog || log_to_file) {
         int save_errno = errno;
         static unsigned int msg_num;
     if (log_to_console || log_to_syslog || log_to_file) {
         int save_errno = errno;
         static unsigned int msg_num;
@@ -660,7 +669,8 @@ vlog_valist(enum vlog_module module, enum vlog_level level,
 }
 
 void
 }
 
 void
-vlog(enum vlog_module module, enum vlog_level level, const char *message, ...)
+vlog(const struct vlog_module *module, enum vlog_level level,
+     const char *message, ...)
 {
     va_list args;
 
 {
     va_list args;
 
@@ -670,7 +680,7 @@ vlog(enum vlog_module module, enum vlog_level level, const char *message, ...)
 }
 
 bool
 }
 
 bool
-vlog_should_drop(enum vlog_module module, enum vlog_level level,
+vlog_should_drop(const struct vlog_module *module, enum vlog_level level,
                  struct vlog_rate_limit *rl)
 {
     if (!vlog_is_enabled(module, level)) {
                  struct vlog_rate_limit *rl)
 {
     if (!vlog_is_enabled(module, level)) {
@@ -710,7 +720,7 @@ vlog_should_drop(enum vlog_module module, enum vlog_level level,
 }
 
 void
 }
 
 void
-vlog_rate_limit(enum vlog_module module, enum vlog_level level,
+vlog_rate_limit(const struct vlog_module *module, enum vlog_level level,
                 struct vlog_rate_limit *rl, const char *message, ...)
 {
     if (!vlog_should_drop(module, level, rl)) {
                 struct vlog_rate_limit *rl, const char *message, ...)
 {
     if (!vlog_should_drop(module, level, rl)) {
index 53e8f39ac2d10b478c9eb209f0ec9b2f57c8df38..7a55dea92f7d4b551c086ec62284983b3799b5e5 100644 (file)
@@ -60,16 +60,25 @@ enum vlog_facility {
 const char *vlog_get_facility_name(enum vlog_facility);
 enum vlog_facility vlog_get_facility_val(const char *name);
 
 const char *vlog_get_facility_name(enum vlog_facility);
 enum vlog_facility vlog_get_facility_val(const char *name);
 
-/* VLM_ constant for each vlog module. */
-enum vlog_module {
-#define VLOG_MODULE(NAME) VLM_##NAME,
-#include "vlog-modules.def"
-    VLM_N_MODULES,
-    VLM_ANY_MODULE = -1
+/* A log module. */
+struct vlog_module {
+    const char *name;             /* User-visible name. */
+    int levels[VLF_N_FACILITIES]; /* Minimum log level for each facility. */
+    int min_level;                /* Minimum log level for any facility. */
 };
 
 };
 
-const char *vlog_get_module_name(enum vlog_module);
-enum vlog_module vlog_get_module_val(const char *name);
+/* Creates and initializes a global instance of a module named MODULE. */
+#if USE_LINKER_SECTIONS
+#define VLOG_DEFINE_MODULE(MODULE)                                      \
+        VLOG_DEFINE_MODULE__(MODULE)                                    \
+        struct vlog_module *vlog_module_ptr_##MODULE                    \
+            __attribute__((section("vlog_modules"))) = &VLM_##MODULE;
+#else
+#define VLOG_DEFINE_MODULE(MODULE) extern struct vlog_module VLM_##MODULE;
+#endif
+
+const char *vlog_get_module_name(const struct vlog_module *);
+struct vlog_module *vlog_module_from_name(const char *name);
 
 /* Rate-limiter for log messages. */
 struct vlog_rate_limit {
 
 /* Rate-limiter for log messages. */
 struct vlog_rate_limit {
@@ -103,12 +112,13 @@ struct vlog_rate_limit {
         }
 
 /* Configuring how each module logs messages. */
         }
 
 /* Configuring how each module logs messages. */
-enum vlog_level vlog_get_level(enum vlog_module, enum vlog_facility);
-void vlog_set_levels(enum vlog_module, enum vlog_facility, enum vlog_level);
+enum vlog_level vlog_get_level(const struct vlog_module *, enum vlog_facility);
+void vlog_set_levels(struct vlog_module *,
+                     enum vlog_facility, enum vlog_level);
 char *vlog_set_levels_from_string(const char *);
 char *vlog_get_levels(void);
 char *vlog_set_levels_from_string(const char *);
 char *vlog_get_levels(void);
-bool vlog_is_enabled(enum vlog_module, enum vlog_level);
-bool vlog_should_drop(enum vlog_module, enum vlog_level,
+bool vlog_is_enabled(const struct vlog_module *, enum vlog_level);
+bool vlog_should_drop(const struct vlog_module *, enum vlog_level,
                       struct vlog_rate_limit *);
 void vlog_set_verbosity(const char *arg);
 
                       struct vlog_rate_limit *);
 void vlog_set_verbosity(const char *arg);
 
@@ -121,19 +131,25 @@ int vlog_reopen_log_file(void);
 /* Function for actual logging. */
 void vlog_init(void);
 void vlog_exit(void);
 /* Function for actual logging. */
 void vlog_init(void);
 void vlog_exit(void);
-void vlog(enum vlog_module, enum vlog_level, const char *format, ...)
+void vlog(const struct vlog_module *, enum vlog_level, const char *format, ...)
     __attribute__((format(printf, 3, 4)));
     __attribute__((format(printf, 3, 4)));
-void vlog_valist(enum vlog_module, enum vlog_level, const char *, va_list)
+void vlog_valist(const struct vlog_module *, enum vlog_level,
+                 const char *, va_list)
     __attribute__((format(printf, 3, 0)));
     __attribute__((format(printf, 3, 0)));
-void vlog_rate_limit(enum vlog_module, enum vlog_level,
+void vlog_rate_limit(const struct vlog_module *, enum vlog_level,
                      struct vlog_rate_limit *, const char *, ...)
     __attribute__((format(printf, 4, 5)));
 
                      struct vlog_rate_limit *, const char *, ...)
     __attribute__((format(printf, 4, 5)));
 
-/* Defines THIS_MODULE as MODULE, for use with the convenience macros below. */
-#define VLOG_DEFINE_THIS_MODULE(MODULE) enum { THIS_MODULE = VLM_##MODULE };
+/* Creates and initializes a global instance of a module named MODULE, and
+ * defines a static variable named THIS_MODULE that points to it, for use with
+ * the convenience macros below. */
+#define VLOG_DEFINE_THIS_MODULE(MODULE)                                 \
+        VLOG_DEFINE_MODULE(MODULE)                                      \
+        static struct vlog_module *const THIS_MODULE = &VLM_##MODULE;
 
 
-/* Convenience macros.  These assume that THIS_MODULE is defined as the current
- * module, as set up by e.g. the VLOG_DEFINE_MODULE macro above.
+/* Convenience macros.  These assume that THIS_MODULE points to a "struct
+ * vlog_module" for the current module, as set up by e.g. the
+ * VLOG_DEFINE_MODULE macro above.
  *
  * Guaranteed to preserve errno.
  */
  *
  * Guaranteed to preserve errno.
  */
@@ -180,20 +196,26 @@ void vlog_rate_limit(enum vlog_module, enum vlog_level,
 void vlog_usage(void);
 
 /* Implementation details. */
 void vlog_usage(void);
 
 /* Implementation details. */
-#define VLOG(LEVEL, ...)                                \
-    do {                                                \
-        if (min_vlog_levels[THIS_MODULE] >= LEVEL) {    \
-            vlog(THIS_MODULE, LEVEL, __VA_ARGS__);      \
-        }                                               \
+#define VLOG(LEVEL, ...)                            \
+    do {                                            \
+        if (THIS_MODULE->min_level >= LEVEL) {      \
+            vlog(THIS_MODULE, LEVEL, __VA_ARGS__);  \
+        }                                           \
     } while (0)
 #define VLOG_RL(RL, LEVEL, ...)                                     \
     do {                                                            \
     } while (0)
 #define VLOG_RL(RL, LEVEL, ...)                                     \
     do {                                                            \
-        if (min_vlog_levels[THIS_MODULE] >= LEVEL) {                \
+        if (THIS_MODULE->min_level >= LEVEL) {                      \
             vlog_rate_limit(THIS_MODULE, LEVEL, RL, __VA_ARGS__);   \
         }                                                           \
     } while (0)
             vlog_rate_limit(THIS_MODULE, LEVEL, RL, __VA_ARGS__);   \
         }                                                           \
     } while (0)
-extern enum vlog_level min_vlog_levels[VLM_N_MODULES];
+#define VLOG_DEFINE_MODULE__(MODULE)                                    \
+        struct vlog_module VLM_##MODULE =                               \
+        {                                                               \
+            #MODULE,                                      /* name */    \
+            { [ 0 ... VLF_N_FACILITIES - 1] = VLL_INFO }, /* levels */  \
+            VLL_INFO,                                     /* min_level */ \
+        };
+
 #ifdef  __cplusplus
 }
 #endif
 #ifdef  __cplusplus
 }
 #endif
index 0b22f64ebc05a82ac9e36d14709c8ad0738ae00c..6fb860994db04d20a1f9a29d41394fcfc5367bef 100644 (file)
@@ -347,3 +347,78 @@ AC_DEFUN([OVS_CHECK_OVSDBMONITOR],
    AC_MSG_CHECKING([whether to build ovsdbmonitor])
    AC_MSG_RESULT([$BUILD_OVSDBMONITOR])
    AM_CONDITIONAL([BUILD_OVSDBMONITOR], [test $BUILD_OVSDBMONITOR = yes])])
    AC_MSG_CHECKING([whether to build ovsdbmonitor])
    AC_MSG_RESULT([$BUILD_OVSDBMONITOR])
    AM_CONDITIONAL([BUILD_OVSDBMONITOR], [test $BUILD_OVSDBMONITOR = yes])])
+
+# OVS_LINK2_IFELSE(SOURCE1, SOURCE2, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+# -------------------------------------------------------------
+# Based on AC_LINK_IFELSE, but tries to link both SOURCE1 and SOURCE2
+# into a program.
+#
+# This macro is borrowed from acinclude.m4 in GNU PSPP, which has the
+# following license:
+#
+#     Copyright (C) 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+#     This file is free software; the Free Software Foundation
+#     gives unlimited permission to copy and/or distribute it,
+#     with or without modifications, as long as this notice is preserved.
+#
+m4_define([OVS_LINK2_IFELSE],
+[m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl
+mv conftest.$ac_ext conftest1.$ac_ext
+m4_ifvaln([$2], [AC_LANG_CONFTEST([$2])])dnl
+mv conftest.$ac_ext conftest2.$ac_ext
+rm -f conftest1.$ac_objext conftest2.$ac_objext conftest$ac_exeext
+ovs_link2='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest1.$ac_ext conftest2.$ac_ext $LIBS >&5'
+AS_IF([_AC_DO_STDERR($ovs_link2) && {
+        test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        AS_TEST_X([conftest$ac_exeext])
+       }],
+      [$3],
+      [echo "$as_me: failed source file 1 of 2 was:" >&5
+sed 's/^/| /' conftest1.$ac_ext >&5
+echo "$as_me: failed source file 2 of 2 was:" >&5
+sed 's/^/| /' conftest2.$ac_ext >&5
+       $4])
+dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization)
+dnl information created by the PGI compiler (conftest_ipa8_conftest.oo),
+dnl as it would interfere with the next link command.
+rm -rf conftest.dSYM conftest1.dSYM conftest2.dSYM
+rm -f core conftest.err conftest1.err conftest2.err
+rm -f conftest1.$ac_objext conftest2.$ac_objext conftest*_ipa8_conftest*.oo
+rm -f conftest$ac_exeext
+rm -f m4_ifval([$1], [conftest1.$ac_ext]) m4_ifval([$2], [conftest1.$ac_ext])[]dnl
+])# OVS_LINK2_IFELSE
+
+dnl Defines USE_LINKER_SECTIONS to 1 if the compiler supports putting
+dnl variables in sections with user-defined names and the linker
+dnl automatically defines __start_SECNAME and __stop_SECNAME symbols
+dnl that designate the start and end of the sections.
+AC_DEFUN([OVS_CHECK_LINKER_SECTIONS],
+  [AC_CACHE_CHECK(
+    [for user-defined linker section support],
+    [ovs_cv_use_linker_sections],
+    [OVS_LINK2_IFELSE(
+      [AC_LANG_SOURCE(
+        [int a __attribute__((__section__("mysection"))) = 1;
+         int b __attribute__((__section__("mysection"))) = 2;
+         int c __attribute__((__section__("mysection"))) = 3;])],
+      [AC_LANG_PROGRAM(
+        [#include <stdio.h>
+         extern int __start_mysection;
+         extern int __stop_mysection;],
+        [int n_ints = &__stop_mysection - &__start_mysection;
+         int *i;
+         for (i = &__start_mysection; i < &__start_mysection + n_ints; i++) {
+             printf("%d\n", *i);
+         }])],
+      [ovs_cv_use_linker_sections=yes],
+      [ovs_cv_use_linker_sections=no])])
+   if test $ovs_cv_use_linker_sections = yes; then
+     AC_DEFINE([USE_LINKER_SECTIONS], [1],
+               [Define to 1 if the compiler support putting variables
+                into sections with user-defined names and the linker
+                automatically defines __start_SECNAME and __stop_SECNAME
+                symbols that designate the start and end of the section.])
+   fi])
index f18e24e8b61cbb0b22b1e664f060856d661fdaf6..0feb27057d294d39829aee81124fb8e2b7683fc0 100644 (file)
@@ -238,10 +238,11 @@ static const struct test tests[] = {
 int
 main(int argc, char *argv[])
 {
 int
 main(int argc, char *argv[])
 {
+    extern struct vlog_module VLM_lockfile;
     size_t i;
 
     set_program_name(argv[0]);
     size_t i;
 
     set_program_name(argv[0]);
-    vlog_set_levels(VLM_lockfile, VLF_ANY_FACILITY, VLL_ERR);
+    vlog_set_levels(&VLM_lockfile, VLF_ANY_FACILITY, VLL_ERR);
 
     if (argc != 2) {
         ovs_fatal(0, "exactly one argument required; use \"%s help\" for help",
 
     if (argc != 2) {
         ovs_fatal(0, "exactly one argument required; use \"%s help\" for help",
index 2bb59d5fb2474d947aca6938635eef8534099cd0..0f49d7f5847c0bc590a7ca279b35b17d24e76b67 100644 (file)
@@ -40,12 +40,13 @@ static void diff_stats(const struct reconnect_stats *old,
 int
 main(void)
 {
 int
 main(void)
 {
+    extern struct vlog_module VLM_reconnect;
     struct reconnect_stats prev;
     unsigned int old_max_tries;
     int old_time;
     char line[128];
 
     struct reconnect_stats prev;
     unsigned int old_max_tries;
     int old_time;
     char line[128];
 
-    vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_EMER);
+    vlog_set_levels(&VLM_reconnect, VLF_ANY_FACILITY, VLL_EMER);
 
     now = 1000;
     reconnect = reconnect_create(now);
 
     now = 1000;
     reconnect = reconnect_create(now);
index eab13d63afdbab1a08d6208f7a3e73459c3de2e7..83d571defd046a983576daad4fde95869a986289 100644 (file)
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
  * limitations under the License.
  */
 
+#include <config.h>
+
 #include "stp.h"
 #include <assert.h>
 #include <ctype.h>
 #include "stp.h"
 #include <assert.h>
 #include <ctype.h>
index 32228f898ee158a32fee5af0687a0b494f33bfeb..12b69ca0bff41ce5a75e7e97a444e6f0bf2590d3 100644 (file)
@@ -401,8 +401,8 @@ int
 main(int argc, char *argv[])
 {
     set_program_name(argv[0]);
 main(int argc, char *argv[])
 {
     set_program_name(argv[0]);
-    vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_EMER);
-    vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_DBG);
+    vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_EMER);
+    vlog_set_levels(NULL, VLF_CONSOLE, VLL_DBG);
     signal(SIGPIPE, SIG_IGN);
 
     time_alarm(10);
     signal(SIGPIPE, SIG_IGN);
 
     time_alarm(10);
index 699df138497d6d8dd5fc1fd9ce4a5724bd8143c0..672fae47a1e6f029f8e059da9d7f340cebe85bb3 100644 (file)
@@ -42,7 +42,7 @@ main(int argc OVS_UNUSED, char *argv[])
     int error;
 
     set_program_name(argv[0]);
     int error;
 
     set_program_name(argv[0]);
-    vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_DBG);
+    vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_DBG);
 
     error = nl_sock_create(NETLINK_ROUTE, RTNLGRP_LINK, 0, 0, &sock);
     if (error) {
 
     error = nl_sock_create(NETLINK_ROUTE, RTNLGRP_LINK, 0, 0, &sock);
     if (error) {
index c18de47ae6c10edbac5bb262e8c33d22d98f7208..76e896a0a01797a77c3f5b6c73738bb6cff577d5 100644 (file)
@@ -118,6 +118,7 @@ static void set_column(const struct vsctl_table_class *,
 int
 main(int argc, char *argv[])
 {
 int
 main(int argc, char *argv[])
 {
+    extern struct vlog_module VLM_reconnect;
     struct ovsdb_idl *idl;
     struct vsctl_command *commands;
     size_t n_commands;
     struct ovsdb_idl *idl;
     struct vsctl_command *commands;
     size_t n_commands;
@@ -125,8 +126,8 @@ main(int argc, char *argv[])
 
     set_program_name(argv[0]);
     signal(SIGPIPE, SIG_IGN);
 
     set_program_name(argv[0]);
     signal(SIGPIPE, SIG_IGN);
-    vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_WARN);
-    vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
+    vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
+    vlog_set_levels(&VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
     ovsrec_init();
 
     /* Log our arguments.  This is often valuable for debugging systems. */
     ovsrec_init();
 
     /* Log our arguments.  This is often valuable for debugging systems. */
@@ -201,7 +202,7 @@ parse_options(int argc, char *argv[])
             break;
 
         case OPT_NO_SYSLOG:
             break;
 
         case OPT_NO_SYSLOG:
-            vlog_set_levels(VLM_vsctl, VLF_SYSLOG, VLL_WARN);
+            vlog_set_levels(&VLM_vsctl, VLF_SYSLOG, VLL_WARN);
             break;
 
         case OPT_NO_WAIT:
             break;
 
         case OPT_NO_WAIT:
@@ -383,7 +384,7 @@ vsctl_fatal(const char *format, ...)
     message = xvasprintf(format, args);
     va_end(args);
 
     message = xvasprintf(format, args);
     va_end(args);
 
-    vlog_set_levels(VLM_vsctl, VLF_CONSOLE, VLL_EMER);
+    vlog_set_levels(&VLM_vsctl, VLF_CONSOLE, VLL_EMER);
     VLOG_ERR("%s", message);
     ovs_error(0, "%s", message);
     vsctl_exit(EXIT_FAILURE);
     VLOG_ERR("%s", message);
     ovs_error(0, "%s", message);
     vsctl_exit(EXIT_FAILURE);
index 5e59373e0659de633e0fee52bdd9fffc2bff07ef..0b5ebb96c8f38859aeb19507fea967b660c57ee8 100644 (file)
@@ -1287,6 +1287,7 @@ rtnl_recv_update(struct ovsdb_idl *idl,
 int
 main(int argc, char *argv[])
 {
 int
 main(int argc, char *argv[])
 {
+    extern struct vlog_module VLM_reconnect;
     struct unixctl_server *unixctl;
     const char *remote;
     struct ovsdb_idl *idl;
     struct unixctl_server *unixctl;
     const char *remote;
     struct ovsdb_idl *idl;
@@ -1294,8 +1295,8 @@ main(int argc, char *argv[])
 
     proctitle_init(argc, argv);
     set_program_name(argv[0]);
 
     proctitle_init(argc, argv);
     set_program_name(argv[0]);
-    vlog_set_levels(VLM_ANY_MODULE, VLF_CONSOLE, VLL_WARN);
-    vlog_set_levels(VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
+    vlog_set_levels(NULL, VLF_CONSOLE, VLL_WARN);
+    vlog_set_levels(&VLM_reconnect, VLF_ANY_FACILITY, VLL_WARN);
 
     remote = parse_options(argc, argv);
     signal(SIGPIPE, SIG_IGN);
 
     remote = parse_options(argc, argv);
     signal(SIGPIPE, SIG_IGN);