Announcing the release of version 0.6.0
by Angus Salkeld
Hi
I have just released 0.6.0 to make the logging improvements
available.
* 750d6e2 (HEAD, tag: v0.6.0, origin/maint-0.5, maint-0.5) Bump the
* library version.
* bfe0c8f defs: better define va_copy
* 95a737e LOG: fix ansi build
* 8f954cd Add a stop watch
* 835eefe docs: add utils to the mainpage
* 1591075 LOG: serialize the va_list, don't snprintf
* 523922b LOG: change active list into array access
* 96f5fad TEST: add int arguments to log bench
* e3b1678 atomic: fix qb_atomic_pointer macros
* ea8dfea LOG: allow the thread priority to be set.
* 453dd31 Fix splint warning on ubuntu 11.04
Regards
Angus
12 years, 8 months
[PATCH 1/3] hashtable: Fix a lint warning
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
lib/hashtable.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 7fdf6b0..408f98f 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -156,7 +156,7 @@ hashtable_put(struct qb_map *map, const void* key, const void* value)
struct hash_node *hash_node;
hash_entry = hash_table->hash_fn(key, hash_table->order);
- hashtable_rm_with_hash(map, key, hash_entry);
+ (void)hashtable_rm_with_hash(map, key, hash_entry);
hash_node = malloc(sizeof(struct hash_node));
if (hash_node == NULL) {
errno = ENOMEM;
--
1.7.6
12 years, 8 months
Incorrect definition of va_copy
by Виноградов Василий
In qbdefs.h there's the following definition:
#if defined (__GNUC__) && defined (__STRICT_ANSI__)
#define va_copy(_a, _b) *_a = *_b
#endif /* ANSI */
As a result libqb fails with segmentation fault on Debian wheezy. I think it would be more correct to define va_copy as follows:
#if ! defined (va_copy) && defined (__va_copy)
#define va_copy(_a, _b) __va_copy(_a, _b)
#else
#define va_copy(_a, _b) *_a = *_b
#endif
12 years, 8 months
[PATCH 1/3] docs: add utils to the mainpage
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
docs/mainpage.h | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/docs/mainpage.h b/docs/mainpage.h
index 05754d8..337b8f4 100644
--- a/docs/mainpage.h
+++ b/docs/mainpage.h
@@ -20,6 +20,7 @@
* - @subpage qb_loop_overview
* - @subpage qb_log_overview
* - @subpage qb_ipc_overview
+ * - @subpage qb_util_overview
*/
/**
@@ -96,9 +97,14 @@
*
*/
-
/**
* @page qb_atomic_overview Atomic operations
* @copydoc qbatomic.h
* @see qbatomic.h
*/
+
+/**
+ * @page qb_util_overview Common Utilities
+ * @copydoc qbutil.h
+ * @see qbutil.h
+ */
--
1.7.6
12 years, 8 months
[PATCH] LOG: serialize the va_list, don't snprintf
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
configure.ac | 2 +-
include/qb/qblog.h | 24 +++-
lib/Makefile.am | 4 +-
lib/log.c | 89 ++++++++++----
lib/log_blackbox.c | 39 ++++---
lib/log_format.c | 333 ++++++++++++++++++++++++++++++++++++++++++++++++++++
lib/log_int.h | 3 +
tests/check_log.c | 61 ++++++++++
tests/simple-log.c | 2 +
9 files changed, 507 insertions(+), 50 deletions(-)
diff --git a/configure.ac b/configure.ac
index 4aff2fa..c425e94 100644
--- a/configure.ac
+++ b/configure.ac
@@ -352,7 +352,7 @@ WARNLIST="
missing-format-attribute
format=2
format-security
- format-nonliteral
+ no-format-nonliteral
no-long-long
unsigned-char
gnu89-inline
diff --git a/include/qb/qblog.h b/include/qb/qblog.h
index 32a070f..15e1316 100644
--- a/include/qb/qblog.h
+++ b/include/qb/qblog.h
@@ -251,6 +251,7 @@ extern struct qb_log_callsite __stop___verbose[];
* Internal function: use qb_log() or qb_logt()
*/
void qb_log_real_(struct qb_log_callsite *cs, ...);
+void qb_log_real_va_(struct qb_log_callsite *cs, va_list ap);
#define QB_LOG_TAG_LIBQB_MSG_BIT 31
#define QB_LOG_TAG_LIBQB_MSG (1 << QB_LOG_TAG_LIBQB_MSG_BIT)
@@ -270,7 +271,6 @@ void qb_log_real_(struct qb_log_callsite *cs, ...);
* @param lineno file line number
* @param tags This MUST have QB_LOG_EXTERNAL_TAG or'ed in
* so that it gets free'ed.
- * @param msg the log message text
*/
void qb_log_from_external_source(const char *function,
const char *filename,
@@ -278,8 +278,15 @@ void qb_log_from_external_source(const char *function,
uint8_t priority,
uint32_t lineno,
uint32_t tags,
- const char *msg);
+ ...);
+void qb_log_from_external_source_va(const char *function,
+ const char *filename,
+ const char *format,
+ uint8_t priority,
+ uint32_t lineno,
+ uint32_t tags,
+ va_list ap);
/**
* This is the function to generate a log message if you want to
@@ -301,10 +308,11 @@ void qb_log_from_external_source(const char *function,
qb_log_real_(&descriptor, ##args); \
} while(0)
#else
-#define qb_logt(priority, tags, fmt, args...) do { \
- char _log_buf_[QB_LOG_MAX_LEN]; \
- snprintf(_log_buf_, QB_LOG_MAX_LEN, fmt, ##args); \
- qb_log_from_external_source( __func__, __FILE__, fmt, priority, __LINE__, tags, _log_buf_); \
+#define qb_logt(priority, tags, fmt, args...) do { \
+ char _log_buf_[QB_LOG_MAX_LEN]; \
+ snprintf(_log_buf_, QB_LOG_MAX_LEN, fmt, ##args); \
+ qb_log_from_external_source(__func__, __FILE__, fmt, priority, \
+ __LINE__, tags, _log_buf_); \
} while(0)
#endif /* QB_HAVE_ATTRIBUTE_SECTION */
@@ -369,6 +377,10 @@ typedef void (*qb_log_logger_fn)(int32_t t,
struct qb_log_callsite *cs,
time_t timestamp,
const char *msg);
+typedef void (*qb_log_vlogger_fn)(int32_t t,
+ struct qb_log_callsite *cs,
+ time_t timestamp,
+ va_list ap);
typedef void (*qb_log_close_fn)(int32_t t);
typedef void (*qb_log_reload_fn)(int32_t t);
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 8ed2763..b6ea3f1 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -41,8 +41,8 @@ libqb_la_LDFLAGS = -version-info 5:0:5
source_to_lint = util.c hdb.c ringbuffer.c ringbuffer_helper.c array.c \
loop.c loop_poll.c loop_job.c \
ipcc.c ipcs.c ipc_posix_mq.c ipc_sysv_mq.c ipc_shm.c ipc_us.c \
- log.c log_thread.c log_blackbox.c log_file.c log_syslog.c \
- log_format.c log_dcs.c
+ log.c log_thread.c log_blackbox.c log_file.c \
+ log_syslog.c log_dcs.c log_format.c
libqb_la_SOURCES = $(source_to_lint)
if USE_TIMERFD
else
diff --git a/lib/log.c b/lib/log.c
index ae35f20..0832f4f 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -24,6 +24,7 @@
#include <stdarg.h>
#include <pthread.h>
#include <dlfcn.h>
+#include <stdarg.h>
#include <qb/qbdefs.h>
#include <qb/qblist.h>
@@ -96,28 +97,40 @@ _cs_matches_filter_(struct qb_log_callsite *cs,
return match;
}
-static void
-_log_real_msg(struct qb_log_callsite *cs, const char *msg)
+void
+qb_log_real_va_(struct qb_log_callsite *cs, va_list ap)
{
int32_t found_threaded;
struct qb_log_target *t;
struct timeval tv;
int32_t pos;
+ int len;
+ int32_t formatted = QB_FALSE;
+ char buf[QB_LOG_MAX_LEN];
+ char *str = buf;
+ va_list ap_copy;
if (in_logger) {
return;
}
in_logger = QB_TRUE;
- gettimeofday(&tv, NULL);
-
if (old_internal_log_fn) {
if (qb_bit_is_set(cs->tags, QB_LOG_TAG_LIBQB_MSG_BIT)) {
+ if (!formatted) {
+ va_copy(ap_copy, ap);
+ len = vsnprintf(str, QB_LOG_MAX_LEN, cs->format, ap_copy);
+ va_end(ap_copy);
+ if (str[len - 1] == '\n') str[len - 1] = '\0';
+ formatted = QB_TRUE;
+ }
old_internal_log_fn(cs->filename, cs->lineno,
- cs->priority, msg);
+ cs->priority, str);
}
}
+ gettimeofday(&tv, NULL);
+
/*
* 1 if we can find a threaded target that needs this log then post it
* 2 foreach non-threaded target call it's logger function
@@ -133,21 +146,51 @@ _log_real_msg(struct qb_log_callsite *cs, const char *msg)
if (!found_threaded
&& qb_bit_is_set(cs->targets, t->pos)) {
found_threaded = QB_TRUE;
+ if (!formatted) {
+ va_copy(ap_copy, ap);
+ len = vsnprintf(str, QB_LOG_MAX_LEN, cs->format, ap_copy);
+ va_end(ap_copy);
+ if (str[len - 1] == '\n') str[len - 1] = '\0';
+ formatted = QB_TRUE;
+ }
}
} else {
- if (qb_bit_is_set(cs->targets, t->pos) && t->logger) {
- t->logger(t->pos, cs, tv.tv_sec, msg);
+ if (qb_bit_is_set(cs->targets, t->pos)) {
+ if (t->vlogger) {
+ va_copy(ap_copy, ap);
+ t->vlogger(t->pos, cs, tv.tv_sec, ap_copy);
+ va_end(ap_copy);
+ } else if (t->logger) {
+ if (!formatted) {
+ va_copy(ap_copy, ap);
+ len = vsnprintf(str, QB_LOG_MAX_LEN, cs->format, ap_copy);
+ va_end(ap_copy);
+ if (str[len - 1] == '\n') str[len - 1] = '\0';
+ formatted = QB_TRUE;
+ }
+ t->logger(t->pos, cs, tv.tv_sec, str);
+ }
}
}
}
if (found_threaded) {
- qb_log_thread_log_post(cs, tv.tv_sec, msg);
+ qb_log_thread_log_post(cs, tv.tv_sec, str);
}
in_logger = QB_FALSE;
}
void
+qb_log_real_(struct qb_log_callsite *cs, ...)
+{
+ va_list ap;
+
+ va_start(ap, cs);
+ qb_log_real_va_(cs, ap);
+ va_end(ap);
+}
+
+void
qb_log_thread_log_write(struct qb_log_callsite *cs,
time_t timestamp, const char *buffer)
{
@@ -168,12 +211,12 @@ qb_log_thread_log_write(struct qb_log_callsite *cs,
}
}
-void
-qb_log_from_external_source(const char *function,
+void qb_log_from_external_source_va(const char *function,
const char *filename,
const char *format,
uint8_t priority,
- uint32_t lineno, uint32_t tags, const char *msg)
+ uint32_t lineno, uint32_t tags,
+ va_list ap)
{
struct qb_log_target *t;
struct qb_log_filter *flt;
@@ -210,25 +253,22 @@ qb_log_from_external_source(const char *function,
}
pthread_rwlock_unlock(&_listlock);
}
- _log_real_msg(cs, msg);
+ qb_log_real_va_(cs, ap);
}
void
-qb_log_real_(struct qb_log_callsite *cs, ...)
+qb_log_from_external_source(const char *function,
+ const char *filename,
+ const char *format,
+ uint8_t priority,
+ uint32_t lineno, uint32_t tags, ...)
{
va_list ap;
- char buf[QB_LOG_MAX_LEN];
- size_t len;
- va_start(ap, cs);
- len = vsnprintf(buf, sizeof(buf), cs->format, ap);
+ va_start(ap, tags);
+ qb_log_from_external_source_va(function, filename, format, priority,
+ lineno, tags, ap);
va_end(ap);
-
- if (buf[len - 1] == '\n') {
- buf[len - 1] = '\0';
- len -= 1;
- }
- _log_real_msg(cs, buf);
}
int32_t
@@ -480,7 +520,7 @@ qb_log_filter_ctl(int32_t t, enum qb_log_filter_conf c,
type > QB_LOG_FILTER_FORMAT || c > QB_LOG_TAG_CLEAR_ALL) {
return -EINVAL;
}
- pthread_rwlock_wrlock(&_listlock);
+ pthread_rwlock_rdlock(&_listlock);
rc = _log_filter_store(t, c, type, text, priority);
if (rc < 0) {
pthread_rwlock_unlock(&_listlock);
@@ -714,6 +754,7 @@ qb_log_custom_open(qb_log_logger_fn log_fn,
snprintf(t->name, PATH_MAX, "custom-%d", t->pos);
t->logger = log_fn;
+ t->vlogger = NULL;
t->reload = reload_fn;
t->close = close_fn;
diff --git a/lib/log_blackbox.c b/lib/log_blackbox.c
index 9a4ae45..a9011ad 100644
--- a/lib/log_blackbox.c
+++ b/lib/log_blackbox.c
@@ -43,13 +43,13 @@ _blackbox_reload(int32_t target)
* <string> buffer
*/
static void
-_blackbox_logger(int32_t target,
+_blackbox_vlogger(int32_t target,
struct qb_log_callsite *cs,
- time_t timestamp, const char *buffer)
+ time_t timestamp, va_list ap)
{
- size_t size = sizeof(uint32_t);
+ size_t max_size;
+ size_t actual_size;
size_t fn_size;
- size_t buf_size;
char *chunk;
struct qb_log_target *t = qb_log_target_get(target);
@@ -58,11 +58,11 @@ _blackbox_logger(int32_t target,
}
fn_size = strlen(cs->function) + 1;
- buf_size = strlen(buffer) + 1;
- size += 2 * sizeof(uint32_t) + fn_size + buf_size + sizeof(time_t);
+ actual_size = 2 * sizeof(uint32_t) + fn_size + sizeof(time_t);
+ max_size = actual_size + QB_LOG_MAX_LEN;
- chunk = qb_rb_chunk_alloc(t->instance, size);
+ chunk = qb_rb_chunk_alloc(t->instance, max_size);
/* line number */
memcpy(chunk, &cs->lineno, sizeof(uint32_t));
@@ -79,11 +79,9 @@ _blackbox_logger(int32_t target,
chunk += sizeof(time_t);
/* log message */
- memcpy(chunk, &buf_size, sizeof(uint32_t));
- chunk += sizeof(uint32_t);
- memcpy(chunk, buffer, buf_size);
+ actual_size += qb_vsprintf_serialize(chunk, cs->format, ap);
- (void)qb_rb_chunk_commit(t->instance, size);
+ (void)qb_rb_chunk_commit(t->instance, actual_size);
}
static void
@@ -109,7 +107,9 @@ qb_log_blackbox_open(struct qb_log_target *t)
if (t->instance == NULL) {
return -errno;
}
- t->logger = _blackbox_logger;
+
+ t->logger = NULL;
+ t->vlogger = _blackbox_vlogger;
t->reload = _blackbox_reload;
t->close = _blackbox_close;
return 0;
@@ -161,8 +161,9 @@ qb_log_blackbox_print_from_file(const char *bb_filename)
uint32_t lineno;
uint32_t fn_size;
char *function;
+ uint32_t len;
time_t timestamp;
- /* uint32_t *log_size; */
+ char message[QB_LOG_MAX_LEN];
bytes_read = qb_rb_chunk_read(instance, chunk, 512, 0);
ptr = chunk;
@@ -191,11 +192,15 @@ qb_log_blackbox_print_from_file(const char *bb_filename)
snprintf(time_buf, sizeof(time_buf), "%ld",
(long int) timestamp);
}
- /* message size & content */
- /* log_size = (uint32_t *) ptr; */
- ptr += sizeof(uint32_t);
+ /* message content */
+ len = qb_vsnprintf_deserialize(message, QB_LOG_MAX_LEN, ptr);
+ len--;
+ while (message[len] == '\n' || message[len] == '\0') {
+ message[len] = '\0';
+ len--;
+ }
printf("%s %s():%d %s\n",
- time_buf, function, lineno, ptr);
+ time_buf, function, lineno, message);
}
} while (bytes_read > 0);
}
diff --git a/lib/log_format.c b/lib/log_format.c
index a052596..c370880 100644
--- a/lib/log_format.c
+++ b/lib/log_format.c
@@ -201,3 +201,336 @@ qb_log_target_format(int32_t target,
output_buffer[output_buffer_idx] = '\0';
}
}
+
+size_t
+qb_vsprintf_serialize(char *serialize, const char *fmt, va_list ap)
+{
+ char *format;
+ char *p;
+ uint32_t location = 0;
+ int type_long = 0;
+ int type_longlong = 0;
+
+ p = stpcpy(serialize, fmt);
+ location = p - serialize + 1;
+
+ format = (char *)fmt;
+ for (;;) {
+ type_long = 0;
+ type_longlong = 0;
+ p = strchrnul ((const char *)format, '%');
+ if (*p == '\0') {
+ break;
+ }
+ format = p + 1;
+reprocess:
+ switch (format[0]) {
+ case '#': /* alternate form conversion, ignore */
+ case '-': /* left adjust, ignore */
+ case ' ': /* a space, ignore */
+ case '+': /* a sign should be used, ignore */
+ case '\'': /* group in thousands, ignore */
+ case 'I': /* glibc-ism locale alternative, ignore */
+ case '.': /* precision, ignore */
+ case '0': /* field width, ignore */
+ case '1': /* field width, ignore */
+ case '2': /* field width, ignore */
+ case '3': /* field width, ignore */
+ case '4': /* field width, ignore */
+ case '5': /* field width, ignore */
+ case '6': /* field width, ignore */
+ case '7': /* field width, ignore */
+ case '8': /* field width, ignore */
+ case '9': /* field width, ignore */
+ format++;
+ goto reprocess;
+
+ case '*': /* variable field width, save */ {
+ int arg_int = va_arg(ap, int);
+ memcpy(&serialize[location], &arg_int, sizeof (int));
+ location += sizeof(int);
+ format++;
+ goto reprocess;
+ }
+ case 'l':
+ format++;
+ type_long = 1;
+ if (*format == 'l') {
+ type_long = 0;
+ type_longlong = 1;
+ }
+ goto reprocess;
+ case 'd': /* int argument */
+ case 'i': /* int argument */
+ case 'o': /* unsigned int argument */
+ case 'u':
+ case 'x':
+ case 'X':
+ if (type_long) {
+ long int arg_int;
+
+ arg_int = va_arg(ap, long int);
+ memcpy (&serialize[location], &arg_int, sizeof (long int));
+ location += sizeof(long int);
+ format++;
+ break;
+ } else
+ if (type_longlong) {
+ long long int arg_int;
+
+ arg_int = va_arg(ap, long long int);
+ memcpy (&serialize[location], &arg_int, sizeof (long long int));
+ location += sizeof(long long int);
+ format++;
+ break;
+ } else {
+ int arg_int;
+
+ arg_int = va_arg(ap, int);
+ memcpy (&serialize[location], &arg_int, sizeof (int));
+ location += sizeof(int);
+ format++;
+ break;
+ }
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ case 'a':
+ case 'A':
+ {
+ double arg_double;
+
+ arg_double = va_arg(ap, double);
+ memcpy (&serialize[location], &arg_double, sizeof (double));
+ location += sizeof(double);
+ format++;
+ break;
+ }
+ case 'c':
+ {
+ int arg_int;
+ unsigned char arg_char;
+
+ arg_int = va_arg(ap, unsigned int);
+ arg_char = (unsigned char)arg_int;
+ memcpy (&serialize[location], &arg_char, sizeof (unsigned char));
+ location += sizeof(unsigned char);
+ break;
+ }
+ case 's':
+ {
+ char *arg_string;
+ arg_string = va_arg(ap, char *);
+ p = stpcpy(&serialize[location], arg_string);
+ location += p - &serialize[location] + 1;
+ break;
+ }
+ case 'p':
+ {
+ void *arg_pointer;
+ arg_pointer = va_arg(ap, void *);
+ memcpy (&serialize[location], &arg_pointer, sizeof (void *));
+ location += sizeof (arg_pointer);
+ break;
+ }
+ case '%':
+ serialize[location++] = '%';
+ break;
+
+ }
+ }
+ return (location);
+}
+
+#define MINI_FORMAT_STR_LEN 20
+
+size_t
+qb_vsnprintf_deserialize(char *string, size_t str_len, const char *buf)
+{
+ char *p;
+ char *format;
+ char fmt[MINI_FORMAT_STR_LEN];
+ int fmt_pos;
+
+ uint32_t location = 0;
+ uint32_t data_pos = strlen(buf) + 1;
+ int type_long = 0;
+ int type_longlong = 0;
+ int len;
+
+ format = (char *)buf;
+ for (;;) {
+ type_long = 0;
+ type_longlong = 0;
+ p = strchrnul((const char *)format, '%');
+ if (*p == '\0') {
+ p = stpcpy(&string[location], format);
+ location += p - &string[location] + 1;
+ break;
+ }
+ // copy from current to the next %
+ len = p - format;
+ strncpy(&string[location], format, len);
+ location += len;
+ format = p;
+
+ // start building up the format for snprintf
+ fmt_pos = 0;
+ fmt[fmt_pos++] = *format;
+ format++;
+reprocess:
+ switch (format[0]) {
+ case '#': /* alternate form conversion, ignore */
+ case '-': /* left adjust, ignore */
+ case ' ': /* a space, ignore */
+ case '+': /* a sign should be used, ignore */
+ case '\'': /* group in thousands, ignore */
+ case 'I': /* glibc-ism locale alternative, ignore */
+ case '.': /* precision, ignore */
+ case '0': /* field width, ignore */
+ case '1': /* field width, ignore */
+ case '2': /* field width, ignore */
+ case '3': /* field width, ignore */
+ case '4': /* field width, ignore */
+ case '5': /* field width, ignore */
+ case '6': /* field width, ignore */
+ case '7': /* field width, ignore */
+ case '8': /* field width, ignore */
+ case '9': /* field width, ignore */
+ fmt[fmt_pos++] = *format;
+ format++;
+ goto reprocess;
+
+ case '*': {
+ int *arg_int = (int *)&buf[data_pos];
+ data_pos += sizeof(int);
+ fmt_pos += snprintf(&fmt[fmt_pos],
+ MINI_FORMAT_STR_LEN - fmt_pos,
+ "%d", *arg_int);
+ format++;
+ goto reprocess;
+ }
+ case 'l':
+ fmt[fmt_pos++] = *format;
+ format++;
+ type_long = 1;
+ if (*format == 'l') {
+ type_long = 0;
+ type_longlong = 1;
+ }
+ goto reprocess;
+ case 'd': /* int argument */
+ case 'i': /* int argument */
+ case 'o': /* unsigned int argument */
+ case 'u':
+ case 'x':
+ case 'X':
+ if (type_long) {
+ long int *arg_int;
+
+ fmt[fmt_pos++] = *format;
+ fmt[fmt_pos++] = '\0';
+ arg_int = (long int *)&buf[data_pos];
+ location += snprintf(&string[location],
+ str_len - location,
+ fmt, *arg_int);
+ data_pos += sizeof(long int);
+ format++;
+ break;
+ } else
+ if (type_longlong) {
+ long long int *arg_int;
+
+ fmt[fmt_pos++] = *format;
+ fmt[fmt_pos++] = '\0';
+ arg_int = (long long int *)&buf[data_pos];
+ location += snprintf(&string[location],
+ str_len - location,
+ fmt, *arg_int);
+ data_pos += sizeof(long long int);
+ format++;
+ break;
+ } else {
+ int *arg_int;
+
+ fmt[fmt_pos++] = *format;
+ fmt[fmt_pos++] = '\0';
+ arg_int = (int *)&buf[data_pos];
+ location += snprintf(&string[location],
+ str_len - location,
+ fmt, *arg_int);
+ data_pos += sizeof(int);
+ format++;
+ break;
+ }
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ case 'a':
+ case 'A':
+ {
+ double *arg_double;
+
+ fmt[fmt_pos++] = *format;
+ fmt[fmt_pos++] = '\0';
+ arg_double = (double *)&buf[data_pos];
+ location += snprintf(&string[location],
+ str_len - location,
+ fmt, *arg_double);
+ data_pos += sizeof(double);
+ format++;
+ break;
+ }
+ case 'c':
+ {
+ unsigned char *arg_char;
+
+ fmt[fmt_pos++] = *format;
+ fmt[fmt_pos++] = '\0';
+ arg_char = (unsigned char*)&buf[data_pos];
+ location += snprintf(&string[location],
+ str_len - location,
+ fmt, *arg_char);
+ data_pos += sizeof(unsigned char);
+ format++;
+ break;
+ }
+ case 's':
+ {
+ fmt[fmt_pos++] = *format;
+ fmt[fmt_pos++] = '\0';
+ len = snprintf(&string[location],
+ str_len - location,
+ fmt, &buf[data_pos]);
+ location += len;
+ data_pos += len + 1;
+ format++;
+ break;
+ }
+ case 'p':
+ {
+ fmt[fmt_pos++] = *format;
+ fmt[fmt_pos++] = '\0';
+ location = snprintf(&string[location],
+ str_len - location,
+ fmt, &buf[data_pos]);
+ data_pos += sizeof(void*);
+ format++;
+ break;
+ }
+ case '%':
+ string[location++] = '%';
+ format++;
+ break;
+
+ }
+ }
+ return location;
+}
+
diff --git a/lib/log_int.h b/lib/log_int.h
index 6d84eed..f8cb033 100644
--- a/lib/log_int.h
+++ b/lib/log_int.h
@@ -49,6 +49,7 @@ struct qb_log_target {
qb_log_reload_fn reload;
qb_log_close_fn close;
qb_log_logger_fn logger;
+ qb_log_vlogger_fn vlogger;
};
struct qb_log_filter {
@@ -96,6 +97,8 @@ struct qb_log_callsite *qb_log_dcs_get(int32_t *newly_created,
uint32_t lineno,
uint32_t tags);
+size_t qb_vsprintf_serialize(char *serialize, const char *fmt, va_list ap);
+size_t qb_vsnprintf_deserialize(char *string, size_t str_len, const char *buf);
#endif /* _QB_LOG_INT_H_ */
diff --git a/tests/check_log.c b/tests/check_log.c
index 8326111..c17b787 100644
--- a/tests/check_log.c
+++ b/tests/check_log.c
@@ -29,6 +29,63 @@
#include <qb/qbutil.h>
#include <qb/qblog.h>
+extern size_t qb_vsprintf_serialize(char *serialize, const char *fmt, va_list ap);
+extern size_t qb_vsnprintf_deserialize(char *string, size_t strlen, const char *buf);
+
+
+static void
+format_this(char *out, const char *fmt, ...)
+{
+ char buf[QB_LOG_MAX_LEN];
+ va_list ap;
+
+ va_start(ap, fmt);
+ qb_vsprintf_serialize(buf, fmt, ap);
+ qb_vsnprintf_deserialize(out, QB_LOG_MAX_LEN, buf);
+ va_end(ap);
+}
+
+
+START_TEST(test_va_serialize)
+{
+ char buf[QB_LOG_MAX_LEN];
+ format_this(buf, "one line");
+ ck_assert_str_eq(buf, "one line");
+
+ format_this(buf, "s1:%s, s2:%s", "Yes", "Never");
+ ck_assert_str_eq(buf, "s1:Yes, s2:Never");
+
+ format_this(buf, "s1:%s, s2:%s", "Yes", "Never");
+ ck_assert_str_eq(buf, "s1:Yes, s2:Never");
+
+ format_this(buf, "d1:%d, d2:%5i, d3:%04i", 23, 37, 84);
+ ck_assert_str_eq(buf, "d1:23, d2: 37, d3:0084");
+
+ format_this(buf, "f1:%.5f, f2:%.2f", 23.34109, 23.34109);
+ ck_assert_str_eq(buf, "f1:23.34109, f2:23.34");
+
+ format_this(buf, ":%s:", "Hello, world!");
+ ck_assert_str_eq(buf, ":Hello, world!:");
+ format_this(buf, ":%15s:", "Hello, world!");
+ ck_assert_str_eq(buf, ": Hello, world!:");
+ format_this(buf, ":%.10s:", "Hello, world!");
+ ck_assert_str_eq(buf, ":Hello, wor:");
+ format_this(buf, ":%-10s:", "Hello, world!");
+ ck_assert_str_eq(buf, ":Hello, world!:");
+ format_this(buf, ":%-15s:", "Hello, world!");
+ ck_assert_str_eq(buf, ":Hello, world! :");
+ format_this(buf, ":%.15s:", "Hello, world!");
+ ck_assert_str_eq(buf, ":Hello, world!:");
+ format_this(buf, ":%15.10s:", "Hello, world!");
+ ck_assert_str_eq(buf, ": Hello, wor:");
+ format_this(buf, ":%-15.10s:", "Hello, world!");
+ ck_assert_str_eq(buf, ":Hello, wor :");
+
+ format_this(buf, ":%*d:", 8, 96);
+ ck_assert_str_eq(buf, ": 96:");
+}
+END_TEST
+
START_TEST(test_log_stupid_inputs)
{
int32_t rc;
@@ -362,6 +419,10 @@ static Suite *log_suite(void)
TCase *tc;
Suite *s = suite_create("logging");
+ tc = tcase_create("va_serialize");
+ tcase_add_test(tc, test_va_serialize);
+ suite_add_tcase(s, tc);
+
tc = tcase_create("limits");
tcase_add_test(tc, test_log_stupid_inputs);
suite_add_tcase(s, tc);
diff --git a/tests/simple-log.c b/tests/simple-log.c
index 100136f..617c658 100644
--- a/tests/simple-log.c
+++ b/tests/simple-log.c
@@ -192,6 +192,8 @@ int32_t main(int32_t argc, char *argv[])
logfile[5] = 'a';
#endif
if (do_blackbox) {
+ qb_log_blackbox_write_to_file("simple-log.fdata");
+ qb_log_blackbox_print_from_file("simple-log.fdata");
qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
}
qb_log_fini();
--
1.7.6
12 years, 8 months
[PATCH 1/2] TEST: add int arguments to log bench
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
tests/bench-log.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/tests/bench-log.c b/tests/bench-log.c
index ca32486..7bb7607 100644
--- a/tests/bench-log.c
+++ b/tests/bench-log.c
@@ -85,12 +85,17 @@ int main (void)
for (i = 0; i < ITERATIONS; i++) {
qb_log(LOG_DEBUG, "%s%s", "RecordA", "RecordB");
}
- bm_finish ("qb_log 2 arguments:");
+ bm_finish ("qb_log 2 args(str):");
bm_start();
for (i = 0; i < ITERATIONS; i++) {
qb_log(LOG_DEBUG, "%s%s%s", "RecordA", "RecordB", "RecordC");
}
- bm_finish ("qb_log 3 arguments:");
+ bm_finish ("qb_log 3 args(str):");
+ bm_start();
+ for (i = 0; i < ITERATIONS; i++) {
+ qb_log(LOG_DEBUG, "%i %u %p", -534, 4508, &i);
+ }
+ bm_finish ("qb_log 3 args(int):");
#ifdef HAVE_DICT_WORDS
bm_start();
log_dict_words();
--
1.7.6
12 years, 8 months
[PATCH] atomic: fix qb_atomic_pointer macros
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
include/qb/qbatomic.h | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/include/qb/qbatomic.h b/include/qb/qbatomic.h
index 968fe31..424d9c0 100644
--- a/include/qb/qbatomic.h
+++ b/include/qb/qbatomic.h
@@ -164,7 +164,7 @@ void qb_atomic_pointer_set(volatile void* QB_GNUC_MAY_ALIAS * atomic,
#define qb_atomic_int_get(atomic) ((int32_t)*(atomic))
#define qb_atomic_int_set(atomic, newval) ((void) (*(atomic) = (newval)))
#define qb_atomic_pointer_get(atomic) ((void*)*(atomic))
-#define qb_atomic_pointer_set(atomic, newval) ((void) (*(atomic) = (newval)))
+#define qb_atomic_pointer_set(atomic, newval) ((void*) (*(atomic) = (newval)))
#else
#define qb_atomic_int_get(atomic) \
((void) sizeof (char* [sizeof (*(atomic)) == sizeof (int32_t) ? 1 : -1]), \
@@ -174,10 +174,10 @@ void qb_atomic_pointer_set(volatile void* QB_GNUC_MAY_ALIAS * atomic,
(qb_atomic_int_set) ((volatile int32_t QB_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (newval)))
#define qb_atomic_pointer_get(atomic) \
((void) sizeof (char* [sizeof (*(atomic)) == sizeof (void*) ? 1 : -1]), \
- (qb_atomic_pointer_get) ((volatile void QB_GNUC_MAY_ALIAS *) (volatile void *) (atomic)))
+ (qb_atomic_pointer_get) ((volatile void* QB_GNUC_MAY_ALIAS *) (volatile void *) (atomic)))
#define qb_atomic_pointer_set(atomic, newval) \
((void) sizeof (char* [sizeof (*(atomic)) == sizeof (void*) ? 1 : -1]), \
- (qb_atomic_pointer_set) ((volatile void QB_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (newval)))
+ (qb_atomic_pointer_set) ((volatile void* QB_GNUC_MAY_ALIAS *) (volatile void *) (atomic), (newval)))
#endif /* QB_ATOMIC_OP_MEMORY_BARRIER_NEEDED */
/**
--
1.7.6
12 years, 8 months
question re qb_log + blackbox
by Steven Dake
Angus,
Is there any way to record the VA args and formatting string in the
blackbox rather then pre-formatting it via sprintf? Then the blackbox
replay would do the expensive sprintf operation. This would reduce
corosync's cpu utilization by approximately 12%...
Regards
-steve
12 years, 8 months
[PATCH] LOG: allow the thread priority to be set.
by Angus Salkeld
Signed-off-by: Angus Salkeld <asalkeld(a)redhat.com>
---
configure.ac | 3 ++-
include/qb/qblog.h | 8 ++++++++
lib/log_thread.c | 49 ++++++++++++++++++++++++++++---------------------
3 files changed, 38 insertions(+), 22 deletions(-)
diff --git a/configure.ac b/configure.ac
index ba7ad7f..4aff2fa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -140,7 +140,8 @@ AC_FUNC_REALLOC
AC_CHECK_FUNCS([alarm clock_gettime ftruncate gettimeofday localtime_r memset munmap \
socket strchr strdup strerror strrchr strstr \
epoll_create epoll_create1 \
- pthread_spin_lock timerfd_create])
+ pthread_spin_lock timerfd_create pthread_setschedparam \
+ sched_get_priority_max sched_setscheduler])
## local defines
PACKAGE_FEATURES=""
diff --git a/include/qb/qblog.h b/include/qb/qblog.h
index 781b060..32a070f 100644
--- a/include/qb/qblog.h
+++ b/include/qb/qblog.h
@@ -464,6 +464,14 @@ int32_t qb_log_file_open(const char *filename);
void qb_log_file_close(int32_t t);
/**
+ * When using threaded logging set the pthread policy and priority.
+ *
+ * @retval -errno on error
+ * @retval 0 success
+ */
+int32_t qb_log_thread_priority_set(int32_t policy, int32_t priority);
+
+/**
* Start the logging pthread.
*/
void qb_log_thread_start(void);
diff --git a/lib/log_thread.c b/lib/log_thread.c
index 0d245ed..c2995aa 100644
--- a/lib/log_thread.c
+++ b/lib/log_thread.c
@@ -46,11 +46,13 @@ static sem_t logt_thread_start;
static sem_t logt_print_finished;
-static int logt_sched_param_queued = 0;
+static int logt_sched_param_queued = QB_FALSE;
static int logt_sched_policy;
+#if defined(HAVE_PTHREAD_SETSCHEDPARAM) && defined(HAVE_SCHED_GET_PRIORITY_MAX)
static struct sched_param logt_sched_param;
+#endif /* HAVE_PTHREAD_SETSCHEDPARAM && HAVE_SCHED_GET_PRIORITY_MAX */
static int logt_after_log_ops_yield = 10;
@@ -111,27 +113,33 @@ retry_sem_wait:
}
}
-static int
-logt_thread_priority_set(int policy,
- const struct sched_param *param,
- unsigned int after_log_ops_yield)
+int32_t
+qb_log_thread_priority_set(int32_t policy, int32_t priority)
{
int res = 0;
- if (param == NULL) {
- return 0;
- }
+
#if defined(HAVE_PTHREAD_SETSCHEDPARAM) && defined(HAVE_SCHED_GET_PRIORITY_MAX)
+
+ logt_sched_policy = policy;
+
+ if (policy == SCHED_OTHER ||
+ policy == SCHED_IDLE ||
+ policy == SCHED_BATCH) {
+ logt_sched_param.sched_priority = 0;
+ } else {
+ logt_sched_param.sched_priority = priority;
+ }
if (wthread_active == 0) {
- logsys_sched_policy = policy;
- memcpy(&logsys_sched_param, param, sizeof(struct sched_param));
- logsys_sched_param_queued = 1;
+ logt_sched_param_queued = QB_TRUE;
} else {
- res = pthread_setschedparam(logsys_thread_id, policy, param);
+ res = pthread_setschedparam(logt_thread_id, policy,
+ &logt_sched_param);
}
#endif
-
- if (after_log_ops_yield > 0) {
- logt_after_log_ops_yield = after_log_ops_yield;
+ if (policy == SCHED_OTHER) {
+ logt_after_log_ops_yield = 1;
+ } else {
+ logt_after_log_ops_yield = 10;
}
return res;
@@ -156,15 +164,14 @@ wthread_create(void)
sem_wait(&logt_thread_start);
if (res == 0) {
- if (logt_sched_param_queued == 1) {
+ if (logt_sched_param_queued) {
/*
- * TODO: propagate qb_logt_thread_priority_set errors back to
+ * TODO: propagate qb_log_thread_priority_set errors back to
* the caller
*/
- res = logt_thread_priority_set(logt_sched_policy,
- &logt_sched_param,
- logt_after_log_ops_yield);
- logt_sched_param_queued = 0;
+ res = qb_log_thread_priority_set(logt_sched_policy,
+ logt_sched_param.sched_priority);
+ logt_sched_param_queued = QB_FALSE;
}
} else {
wthread_active = 0;
--
1.7.6
12 years, 8 months