]> xenbits.xensource.com Git - libvirt.git/commitdiff
Allow to dynamically set the size of the debug buffer
authorDaniel Veillard <veillard@redhat.com>
Tue, 8 Mar 2011 10:31:20 +0000 (18:31 +0800)
committerDaniel Veillard <veillard@redhat.com>
Tue, 15 Mar 2011 07:13:21 +0000 (15:13 +0800)
This is the part allowing to dynamically resize the debug log
buffer from it's default 64kB size. The buffer is now dynamically
allocated.
It adds a new API virLogSetBufferSize() which resizes the buffer
If passed a zero size, the buffer is deallocated and we do the small
optimization of not formatting messages which are not output anymore.
On the daemon side, it just adds a new option log_buffer_size to
libvirtd.conf and call virLogSetBufferSize() if needed
* src/util/logging.h src/util/logging.c src/libvirt_private.syms:
  make buffer dynamic and add virLogSetBufferSize() internal API
* daemon/libvirtd.conf: document the new log_buffer_size option
* daemon/libvirtd.c: read and use the new log_buffer_size option

daemon/libvirtd.c
daemon/libvirtd.conf
src/libvirt_private.syms
src/util/logging.c
src/util/logging.h

index 1e41feb1db0e87d08fe7c64a36f7e5dcf23e860d..dc6fab4a51fa5c8417a8bba70ea6d6f6c5f68685 100644 (file)
@@ -2714,18 +2714,22 @@ remoteReadSaslAllowedUsernameList (virConfPtr conf ATTRIBUTE_UNUSED,
  * Set up the logging environment
  * By default if daemonized all errors go to the logfile libvirtd.log,
  * but if verbose or error debugging is asked for then also output
- * informations or debug.
+ * informational and debug messages. Default size if 64 kB.
  */
 static int
 qemudSetLogging(struct qemud_server *server, virConfPtr conf,
                 const char *filename)
 {
     int log_level = 0;
+    int log_buffer_size = 64;
     char *log_filters = NULL;
     char *log_outputs = NULL;
     char *log_file = NULL;
     int ret = -1;
 
+    GET_CONF_INT (conf, filename, log_buffer_size);
+    virLogSetBufferSize(log_buffer_size);
+
     virLogReset();
 
     /*
index 163a80fb03dc932f85e19e4b7dc230382ea8894e..3a071b0fce9879b156e4f011430b83f6da1a1b5b 100644 (file)
 # log_outputs="3:syslog:libvirtd"
 # to log all warnings and errors to syslog under the libvirtd ident
 
+# Log debug buffer size: default 64
+# The daemon keeps an internal debug log buffer which will be dumped in case
+# of crash or upon receiving a SIGUSR2 signal. This setting allows to override
+# the default buffer size in kilobytes.
+# If value is 0 or less the debug log buffer is deactivated
+#log_buffer_size = 64
+
 
 ##################################################################
 #
index c0da78ec5a4e9ade0cf710c277f71bcfeffeffd9..09eb03a356a21a9de06f49e97935f8c6274a33d4 100644 (file)
@@ -559,6 +559,7 @@ virLogParseDefaultPriority;
 virLogParseFilters;
 virLogParseOutputs;
 virLogReset;
+virLogSetBufferSize;
 virLogSetDefaultPriority;
 virLogSetFromEnv;
 virLogShutdown;
index 64903765f6b2622f3acf5640758350ff25a21a3d..4479938fa48d68fcd41f51453a40fd22787aff41 100644 (file)
@@ -36,6 +36,7 @@
 #endif
 
 #include "ignore-value.h"
+#include "virterror_internal.h"
 #include "logging.h"
 #include "memory.h"
 #include "util.h"
@@ -43,6 +44,8 @@
 #include "threads.h"
 #include "files.h"
 
+#define VIR_FROM_THIS VIR_FROM_NONE
+
 /*
  * Macro used to format the message as a string in virLogMessage
  * and borrowed from libxml2 (also used in virRaiseError)
@@ -83,9 +86,9 @@
 /*
  * A logging buffer to keep some history over logs
  */
-#define LOG_BUFFER_SIZE 64000
 
-static char virLogBuffer[LOG_BUFFER_SIZE + 1];
+static int virLogSize = 64 * 1024;
+static char *virLogBuffer = NULL;
 static int virLogLen = 0;
 static int virLogStart = 0;
 static int virLogEnd = 0;
@@ -184,6 +187,8 @@ static int virLogInitialized = 0;
  * Returns 0 if successful, and -1 in case or error
  */
 int virLogStartup(void) {
+    const char *pbm = NULL;
+
     if (virLogInitialized)
         return -1;
 
@@ -192,14 +197,84 @@ int virLogStartup(void) {
 
     virLogInitialized = 1;
     virLogLock();
+    if (VIR_ALLOC_N(virLogBuffer, virLogSize) < 0) {
+        /*
+         * The debug buffer is not a critical component, allow startup
+         * even in case of failure to allocate it in case of a
+         * configuration mistake.
+         */
+        virLogSize = 64 * 1024;
+        if (VIR_ALLOC_N(virLogBuffer, virLogSize) < 0) {
+            pbm = "Failed to allocate debug buffer: deactivating debug log\n";
+            virLogSize = 0;
+        } else {
+            pbm = "Failed to allocate debug buffer: reduced to 64 kB\n";
+        }
+    }
     virLogLen = 0;
     virLogStart = 0;
     virLogEnd = 0;
     virLogDefaultPriority = VIR_LOG_DEFAULT;
     virLogUnlock();
+    if (pbm)
+        VIR_WARN0(pbm);
     return 0;
 }
 
+/**
+ * virLogSetBufferSize:
+ * @size: size of the buffer in kilobytes or <= 0 to deactivate
+ *
+ * Dynamically set the size or deactivate the logging buffer used to keep
+ * a trace of all recent debug output. Note that the content of the buffer
+ * is lost if it gets reallocated.
+ *
+ * Return -1 in case of failure or 0 in case of success
+ */
+extern int
+virLogSetBufferSize(int size) {
+    int ret = 0;
+    int oldsize;
+    char *oldLogBuffer;
+    const char *pbm = NULL;
+
+    if (size < 0)
+        size = 0;
+
+    if ((virLogInitialized == 0) || (size * 1024 == virLogSize))
+        return ret;
+
+    virLogLock();
+
+    oldsize = virLogSize;
+    oldLogBuffer = virLogBuffer;
+
+    if (INT_MAX / 1024 < size) {
+        pbm = "Requested log size of %d kB too large\n";
+        ret = -1;
+        goto error;
+    }
+
+    virLogSize = size * 1024;
+    if (VIR_ALLOC_N(virLogBuffer, virLogSize) < 0) {
+        pbm = "Failed to allocate debug buffer of %d kB\n";
+        virLogBuffer = oldLogBuffer;
+        virLogSize = oldsize;
+        ret = -1;
+        goto error;
+    }
+    VIR_FREE(oldLogBuffer);
+    virLogLen = 0;
+    virLogStart = 0;
+    virLogEnd = 0;
+
+error:
+    virLogUnlock();
+    if (pbm)
+        VIR_ERROR(pbm, size);
+    return ret;
+}
+
 /**
  * virLogReset:
  *
@@ -235,6 +310,7 @@ void virLogShutdown(void) {
     virLogLen = 0;
     virLogStart = 0;
     virLogEnd = 0;
+    VIR_FREE(virLogBuffer);
     virLogUnlock();
     virMutexDestroy(&virLogMutex);
     virLogInitialized = 0;
@@ -246,21 +322,21 @@ void virLogShutdown(void) {
 static void virLogStr(const char *str, int len) {
     int tmp;
 
-    if (str == NULL)
+    if ((str == NULL) || (virLogBuffer == NULL) || (virLogSize <= 0))
         return;
     if (len <= 0)
         len = strlen(str);
-    if (len > LOG_BUFFER_SIZE)
+    if (len > virLogSize)
         return;
     virLogLock();
 
     /*
      * copy the data and reset the end, we cycle over the end of the buffer
      */
-    if (virLogEnd + len >= LOG_BUFFER_SIZE) {
-        tmp = LOG_BUFFER_SIZE - virLogEnd;
+    if (virLogEnd + len >= virLogSize) {
+        tmp = virLogSize - virLogEnd;
         memcpy(&virLogBuffer[virLogEnd], str, tmp);
-        virLogBuffer[LOG_BUFFER_SIZE] = 0;
+        virLogBuffer[virLogSize] = 0;
         memcpy(&virLogBuffer[0], &str[tmp], len - tmp);
         virLogEnd = len - tmp;
     } else {
@@ -271,12 +347,12 @@ static void virLogStr(const char *str, int len) {
      * Update the log length, and if full move the start index
      */
     virLogLen += len;
-    if (virLogLen > LOG_BUFFER_SIZE) {
-        tmp = virLogLen - LOG_BUFFER_SIZE;
-        virLogLen = LOG_BUFFER_SIZE;
+    if (virLogLen > virLogSize) {
+        tmp = virLogLen - virLogSize;
+        virLogLen = virLogSize;
         virLogStart += tmp;
-        if (virLogStart >= LOG_BUFFER_SIZE)
-            virLogStart -= LOG_BUFFER_SIZE;
+        if (virLogStart >= virLogSize)
+            virLogStart -= virLogSize;
     }
     virLogUnlock();
 }
@@ -350,23 +426,28 @@ virLogEmergencyDumpAll(int signum) {
             virLogDumpAllFD( "Caught unexpected signal", -1);
             break;
     }
+    if ((virLogBuffer == NULL) || (virLogSize <= 0)) {
+        virLogDumpAllFD(" internal log buffer deactivated\n", -1);
+        goto done;
+    }
     virLogDumpAllFD(" dumping internal log buffer:\n", -1);
     virLogDumpAllFD("\n\n    ====== start of log =====\n\n", -1);
     while (virLogLen > 0) {
-        if (virLogStart + virLogLen < LOG_BUFFER_SIZE) {
+        if (virLogStart + virLogLen < virLogSize) {
             virLogBuffer[virLogStart + virLogLen] = 0;
             virLogDumpAllFD(&virLogBuffer[virLogStart], virLogLen);
             virLogStart += virLogLen;
             virLogLen = 0;
         } else {
-            len = LOG_BUFFER_SIZE - virLogStart;
-            virLogBuffer[LOG_BUFFER_SIZE] = 0;
+            len = virLogSize - virLogStart;
+            virLogBuffer[virLogSize] = 0;
             virLogDumpAllFD(&virLogBuffer[virLogStart], len);
             virLogLen -= len;
             virLogStart = 0;
         }
     }
     virLogDumpAllFD("\n\n     ====== end of log =====\n\n", -1);
+done:
     virLogUnlock();
 }
 
@@ -643,6 +724,9 @@ void virLogMessage(const char *category, int priority, const char *funcname,
         emit = 0;
     }
 
+    if ((emit == 0) && ((virLogBuffer == NULL) || (virLogSize <= 0)))
+        goto cleanup;
+
     /*
      * serialize the error message, add level and timestamp
      */
index c168dff5c8c6b09efb91befbb0cc27d132cb4732..0dba78cda764b9aae718d906c458f8d19472b16d 100644 (file)
@@ -133,5 +133,6 @@ extern int virLogParseOutputs(const char *output);
 extern void virLogMessage(const char *category, int priority,
                           const char *funcname, long long linenr, int flags,
                           const char *fmt, ...) ATTRIBUTE_FMT_PRINTF(6, 7);
+extern int virLogSetBufferSize(int size);
 extern void virLogEmergencyDumpAll(int signum);
 #endif