Revamp build system to make it easier to integrate openflowext.
[sliver-openvswitch.git] / lib / vlog.c
index 19590e3..a136e56 100644 (file)
@@ -43,6 +43,7 @@
 #include <syslog.h>
 #include <time.h>
 #include "dynamic-string.h"
+#include "sat-math.h"
 #include "timeval.h"
 #include "util.h"
 
 
 /* Name for each logging level. */
 static const char *level_names[VLL_N_LEVELS] = {
-    [VLL_EMER] = "EMER",
-    [VLL_ERR] = "ERR",
-    [VLL_WARN] = "WARN",
-    [VLL_DBG] = "DBG",
+#define VLOG_LEVEL(NAME) #NAME,
+    VLOG_LEVELS
+#undef VLOG_LEVEL
 };
 
 /* Name for each logging facility. */
 static const char *facility_names[VLF_N_FACILITIES] = { 
-    [VLF_CONSOLE] = "console",
-    [VLF_SYSLOG] = "syslog",
+#define VLOG_FACILITY(NAME) #NAME,
+    VLOG_FACILITIES
+#undef VLOG_FACILITY
 };
 
 /* Name for each logging module */
 static const char *module_names[VLM_N_MODULES] = { 
 #define VLOG_MODULE(NAME) #NAME,
-    VLOG_MODULES
-#undef VLOG_MODULES
+#include "vlog-modules.def"
 };
 
 static int levels[VLM_N_MODULES][VLF_N_FACILITIES];
@@ -240,7 +240,7 @@ vlog_set_verbosity(const char *arg)
     if (arg) {
         char *msg = vlog_set_levels_from_string(arg);
         if (msg) {
-            fatal(0, "processing \"%s\": %s", arg, msg);
+            ofp_fatal(0, "processing \"%s\": %s", arg, msg);
         }
     } else {
         vlog_set_levels(VLM_ANY_MODULE, VLF_ANY_FACILITY, VLL_DBG);
@@ -309,7 +309,8 @@ vlog_is_enabled(enum vlog_module module, enum vlog_level level)
  *
  * Guaranteed to preserve errno. */
 void
-vlog(enum vlog_module module, enum vlog_level level, const char *message, ...)
+vlog_valist(enum vlog_module module, enum vlog_level level,
+            const char *message, va_list args)
 {
     bool log_console = levels[module][VLF_CONSOLE] >= level;
     bool log_syslog = levels[module][VLF_SYSLOG] >= level;
@@ -340,18 +341,20 @@ vlog(enum vlog_module module, enum vlog_level level, const char *message, ...)
         }
 
         if (log_syslog) {
-            static const int syslog_levels[VLL_N_LEVELS] = {
-                [VLL_EMER] = LOG_ALERT,
-                [VLL_ERR] = LOG_ERR,
-                [VLL_WARN] = LOG_WARNING,
-                [VLL_DBG] = LOG_DEBUG,
-            };
+            int syslog_level = LOG_ALERT;
             char *save_ptr = NULL;
             char *line;
 
+            switch (level) {
+            case VLL_EMER: syslog_level = LOG_ALERT; break;
+            case VLL_ERR: syslog_level = LOG_ERR; break;
+            case VLL_WARN: syslog_level = LOG_WARNING; break;
+            case VLL_DBG: syslog_level = LOG_DEBUG; break;
+            case VLL_N_LEVELS: NOT_REACHED();
+            }
             for (line = strtok_r(&s.string[time_len], "\n", &save_ptr); line;
                  line = strtok_r(NULL, "\n", &save_ptr)) {
-                syslog(syslog_levels[level], "%s", line);
+                syslog(syslog_level, "%s", line);
             }
         }
 
@@ -359,3 +362,57 @@ vlog(enum vlog_module module, enum vlog_level level, const char *message, ...)
         errno = save_errno;
     }
 }
+
+void
+vlog(enum vlog_module module, enum vlog_level level, const char *message, ...)
+{
+    va_list args;
+
+    va_start(args, message);
+    vlog_valist(module, level, message, args);
+    va_end(args);
+}
+
+void
+vlog_rate_limit(enum vlog_module module, enum vlog_level level,
+                struct vlog_rate_limit *rl, const char *message, ...)
+{
+    va_list args;
+
+    if (!vlog_is_enabled(module, level)) {
+        return;
+    }
+
+    if (rl->tokens < VLOG_MSG_TOKENS) {
+        time_t now = time_now();
+        if (rl->last_fill > now) {
+            /* Last filled in the future?  Time must have gone backward, or
+             * 'rl' has not been used before. */
+            rl->tokens = rl->burst;
+        } else if (rl->last_fill < now) {
+            unsigned int add = sat_mul(rl->rate, now - rl->last_fill);
+            unsigned int tokens = sat_add(rl->tokens, add);
+            rl->tokens = MIN(tokens, rl->burst);
+            rl->last_fill = now;
+        }
+        if (rl->tokens < VLOG_MSG_TOKENS) {
+            if (!rl->n_dropped) {
+                rl->first_dropped = now;
+            }
+            rl->n_dropped++;
+            return;
+        }
+    }
+    rl->tokens -= VLOG_MSG_TOKENS;
+
+    va_start(args, message);
+    vlog_valist(module, level, message, args);
+    va_end(args);
+
+    if (rl->n_dropped) {
+        vlog(module, level,
+             "Dropped %u messages in last %u seconds due to excessive rate",
+             rl->n_dropped, (unsigned int) (time_now() - rl->first_dropped));
+        rl->n_dropped = 0;
+    }
+}