Allow to dynamically set the size of the debug buffer

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
This commit is contained in:
Daniel Veillard 2011-03-08 18:31:20 +08:00
parent 1c5dc4c607
commit b16f47ab61
5 changed files with 113 additions and 16 deletions

View 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();
/*

View File

@ -313,6 +313,13 @@
# 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
##################################################################
#

View File

@ -559,6 +559,7 @@ virLogParseDefaultPriority;
virLogParseFilters;
virLogParseOutputs;
virLogReset;
virLogSetBufferSize;
virLogSetDefaultPriority;
virLogSetFromEnv;
virLogShutdown;

View 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
*/

View 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