From 4b462cee0d4ab89b94887fe54d64c9fcf89e80c6 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sat, 16 Feb 2013 13:20:06 +0100 Subject: [PATCH] scratch-buffers: Support any number of stacks Instead of being tied to GStrings only, support registering new kinds of stacks, which will be automatiaclly free'd on thread shutdown. For convenience, wrappers are provided for GString-based scratch buffer acquire and release, and that stack is automatically registered and free'd by the library itself. This fixes #2. Signed-off-by: Gergely Nagy Signed-off-by: Balazs Scheidler --- lib/mainloop.c | 3 +- lib/scratch-buffers.c | 80 ++++++++++++++++++++++++++++++--------- lib/scratch-buffers.h | 41 ++++++++++++++++---- lib/value-pairs.c | 34 +++++++++-------- lib/vptransform.c | 38 ++++++++++--------- modules/afamqp/afamqp.c | 20 +++++----- modules/json/jsonparser.c | 54 +++++++++++++------------- 7 files changed, 174 insertions(+), 96 deletions(-) diff --git a/lib/mainloop.c b/lib/mainloop.c index 2d7383f1bca08..6dd19792c4a3e 100644 --- a/lib/mainloop.c +++ b/lib/mainloop.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2012 BalaBit IT Ltd, Budapest, Hungary + * Copyright (c) 2002-2013 BalaBit IT Ltd, Budapest, Hungary * Copyright (c) 1998-2012 Balázs Scheidler * * This library is free software; you can redistribute it and/or @@ -292,6 +292,7 @@ main_loop_io_worker_thread_start(void *cookie) gint id; dns_cache_init(); + scratch_buffers_init(); g_static_mutex_lock(&main_loop_io_workers_idmap_lock); /* NOTE: this algorithm limits the number of I/O worker threads to 64, * since the ID map is stored in a single 64 bit integer. If we ever need diff --git a/lib/scratch-buffers.c b/lib/scratch-buffers.c index 2debca9b41bff..f6636dee050ed 100644 --- a/lib/scratch-buffers.c +++ b/lib/scratch-buffers.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2011-2012 BalaBit IT Ltd, Budapest, Hungary - * Copyright (c) 2011-2012 Gergely Nagy + * Copyright (c) 2011-2013 BalaBit IT Ltd, Budapest, Hungary + * Copyright (c) 2011-2013 Gergely Nagy * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,42 +28,86 @@ TLS_BLOCK_START { - GTrashStack *scratch_buffers; + GTrashStack *sb_gstrings; + GList *sb_registry; } TLS_BLOCK_END; -#define local_scratch_buffers __tls_deref(scratch_buffers) +/* GStrings */ -ScratchBuffer * -scratch_buffer_acquire(void) +#define local_sb_gstrings __tls_deref(sb_gstrings) + +GTrashStack * +sb_gstring_acquire_buffer(void) { - ScratchBuffer *sb; + SBGString *sb; - sb = g_trash_stack_pop(&local_scratch_buffers); + sb = g_trash_stack_pop(&local_sb_gstrings); if (!sb) { - sb = g_new(ScratchBuffer, 1); - g_string_steal(sb_string(sb)); + sb = g_new(SBGString, 1); + g_string_steal(sb_gstring_string(sb)); } else - g_string_set_size(sb_string(sb), 0); - return sb; + g_string_set_size(sb_gstring_string(sb), 0); + + return (GTrashStack *) sb; } void -scratch_buffer_release(ScratchBuffer *sb) +sb_gstring_release_buffer(GTrashStack *s) { - g_trash_stack_push(&local_scratch_buffers, sb); + SBGString *sb = (SBGString *) s; + + g_trash_stack_push(&local_sb_gstrings, sb); } void -scratch_buffers_free(void) +sb_gstring_free_stack(void) { - ScratchBuffer *sb; + SBGString *sb; - while ((sb = g_trash_stack_pop(&local_scratch_buffers)) != NULL) + while ((sb = g_trash_stack_pop(&local_sb_gstrings)) != NULL) { - g_free(sb_string(sb)->str); + g_free(sb_gstring_string(sb)->str); g_free(sb); } } + +ScratchBufferStack SBGStringStack = { + .acquire_buffer = sb_gstring_acquire_buffer, + .release_buffer = sb_gstring_release_buffer, + .free_stack = sb_gstring_free_stack +}; + +/* Global API */ + +#define local_sb_registry __tls_deref(sb_registry) + +void +scratch_buffers_register(ScratchBufferStack *stack) +{ + local_sb_registry = g_list_append(local_sb_registry, stack); +} + +void +scratch_buffers_init(void) +{ + local_sb_registry = NULL; + scratch_buffers_register(&SBGStringStack); +} + +static void +scratch_buffers_free_stack(gpointer data, gpointer user_data) +{ + ScratchBufferStack *s = (ScratchBufferStack *) data; + + s->free_stack(); +} + +void +scratch_buffers_free(void) +{ + g_list_foreach(local_sb_registry, scratch_buffers_free_stack, NULL); + g_list_free(local_sb_registry); +} diff --git a/lib/scratch-buffers.h b/lib/scratch-buffers.h index c61e51825e1bb..6aeda6fb63252 100644 --- a/lib/scratch-buffers.h +++ b/lib/scratch-buffers.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2011 BalaBit IT Ltd, Budapest, Hungary - * Copyright (c) 2011 Gergely Nagy + * Copyright (c) 2011-2013 BalaBit IT Ltd, Budapest, Hungary + * Copyright (c) 2011-2013 Gergely Nagy * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -27,17 +27,44 @@ #include +/* Global API */ + +typedef struct +{ + GTrashStack *(*acquire_buffer)(void); + void (*release_buffer)(GTrashStack *stack); + void (*free_stack)(void); +} ScratchBufferStack; + +static inline GTrashStack * +scratch_buffer_acquire(ScratchBufferStack *stack) +{ + return stack->acquire_buffer(); +} + +static inline void +scratch_buffer_release(ScratchBufferStack *stack, GTrashStack *buffer) +{ + stack->release_buffer(buffer); +} + +void scratch_buffers_register(ScratchBufferStack *stack); +void scratch_buffers_init(void); +void scratch_buffers_free(void); + +/* GStrings */ + typedef struct { GTrashStack stackp; GString s; -} ScratchBuffer; +} SBGString; -ScratchBuffer *scratch_buffer_acquire(void); -void scratch_buffer_release(ScratchBuffer *sb); +extern ScratchBufferStack SBGStringStack; -#define sb_string(buffer) (&buffer->s) +#define sb_gstring_acquire() ((SBGString *)scratch_buffer_acquire(&SBGStringStack)) +#define sb_gstring_release(b) (scratch_buffer_release(&SBGStringStack, (GTrashStack *)b)) -void scratch_buffers_free(void); +#define sb_gstring_string(buffer) (&buffer->s) #endif diff --git a/lib/value-pairs.c b/lib/value-pairs.c index ee22b7370b71c..e78fc58ada84b 100644 --- a/lib/value-pairs.c +++ b/lib/value-pairs.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2011-2012 BalaBit IT Ltd, Budapest, Hungary - * Copyright (c) 2011-2012 Gergely Nagy + * Copyright (c) 2011-2013 BalaBit IT Ltd, Budapest, Hungary + * Copyright (c) 2011-2013 Gergely Nagy * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -193,22 +193,22 @@ vp_pairs_foreach(gpointer data, gpointer user_data) LogMessage *msg = ((gpointer *)user_data)[2]; gint32 seq_num = GPOINTER_TO_INT (((gpointer *)user_data)[3]); GTree *scope_set = ((gpointer *)user_data)[5]; - ScratchBuffer *sb = scratch_buffer_acquire(); + SBGString *sb = sb_gstring_acquire(); VPPairConf *vpc = (VPPairConf *)data; log_template_format((LogTemplate *)vpc->template, msg, NULL, LTZ_LOCAL, - seq_num, NULL, sb_string(sb)); + seq_num, NULL, sb_gstring_string(sb)); - if (!sb_string(sb)->str[0]) + if (!sb_gstring_string(sb)->str[0]) { - scratch_buffer_release(sb); + sb_gstring_release(sb); return; } g_tree_insert(scope_set, vp_transform_apply(vp, vpc->name), - sb_string(sb)->str); - g_string_steal(sb_string(sb)); - scratch_buffer_release(sb); + sb_gstring_string(sb)->str); + g_string_steal(sb_gstring_string(sb)); + sb_gstring_release(sb); } /* runs over the LogMessage nv-pairs, and inserts them unless excluded */ @@ -246,7 +246,7 @@ static void vp_merge_set(ValuePairs *vp, LogMessage *msg, gint32 seq_num, ValuePairSpec *set, GTree *dest) { gint i; - ScratchBuffer *sb = scratch_buffer_acquire(); + SBGString *sb = sb_gstring_acquire(); for (i = 0; set[i].name; i++) { @@ -265,7 +265,8 @@ vp_merge_set(ValuePairs *vp, LogMessage *msg, gint32 seq_num, ValuePairSpec *set switch (set[i].type) { case VPT_MACRO: - log_macro_expand(sb_string(sb), set[i].id, FALSE, NULL, LTZ_LOCAL, seq_num, NULL, msg); + log_macro_expand(sb_gstring_string(sb), set[i].id, FALSE, + NULL, LTZ_LOCAL, seq_num, NULL, msg); break; case VPT_NVPAIR: { @@ -273,20 +274,21 @@ vp_merge_set(ValuePairs *vp, LogMessage *msg, gint32 seq_num, ValuePairSpec *set gssize len; nv = log_msg_get_value(msg, (NVHandle) set[i].id, &len); - g_string_append_len(sb_string(sb), nv, len); + g_string_append_len(sb_gstring_string(sb), nv, len); break; } default: g_assert_not_reached(); } - if (!sb_string(sb)->str[0]) + if (!sb_gstring_string(sb)->str[0]) continue; - g_tree_insert(dest, vp_transform_apply(vp, set[i].name), sb_string(sb)->str); - g_string_steal(sb_string(sb)); + g_tree_insert(dest, vp_transform_apply(vp, set[i].name), + sb_gstring_string(sb)->str); + g_string_steal(sb_gstring_string(sb)); } - scratch_buffer_release(sb); + sb_gstring_release(sb); } void diff --git a/lib/vptransform.c b/lib/vptransform.c index 43699a07ccb03..89f71bcf96a78 100644 --- a/lib/vptransform.c +++ b/lib/vptransform.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2011-2012 BalaBit IT Ltd, Budapest, Hungary - * Copyright (c) 2011-2012 Gergely Nagy + * Copyright (c) 2011-2013 BalaBit IT Ltd, Budapest, Hungary + * Copyright (c) 2011-2013 Gergely Nagy * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -31,7 +31,7 @@ #include -typedef void (*VPTransFunc)(ValuePairsTransform *t, ScratchBuffer *name); +typedef void (*VPTransFunc)(ValuePairsTransform *t, SBGString *name); typedef void (*VPTransDestroyFunc)(ValuePairsTransform *t); struct _ValuePairsTransformSet @@ -92,7 +92,7 @@ value_pairs_transform_free(ValuePairsTransform *t) } static inline void -value_pairs_transform_apply(ValuePairsTransform *t, ScratchBuffer *key) +value_pairs_transform_apply(ValuePairsTransform *t, SBGString *key) { t->transform(t, key); } @@ -100,11 +100,11 @@ value_pairs_transform_apply(ValuePairsTransform *t, ScratchBuffer *key) /* add_prefix() */ static void -vp_trans_add_prefix(ValuePairsTransform *t, ScratchBuffer *key) +vp_trans_add_prefix(ValuePairsTransform *t, SBGString *key) { VPTransAddPrefix *self = (VPTransAddPrefix *)t; - g_string_prepend(sb_string(key), self->prefix); + g_string_prepend(sb_gstring_string(key), self->prefix); } static void @@ -132,11 +132,11 @@ value_pairs_new_transform_add_prefix (const gchar *prefix) /* shift() */ static void -vp_trans_shift(ValuePairsTransform *t, ScratchBuffer* key) +vp_trans_shift(ValuePairsTransform *t, SBGString* key) { VPTransShift *self = (VPTransShift *)t; - g_string_erase(sb_string(key), 0, self->amount); + g_string_erase(sb_gstring_string(key), 0, self->amount); } ValuePairsTransform * @@ -156,15 +156,17 @@ value_pairs_new_transform_shift (gint amount) /* replace() */ static void -vp_trans_replace(ValuePairsTransform *t, ScratchBuffer *key) +vp_trans_replace(ValuePairsTransform *t, SBGString *key) { VPTransReplace *self = (VPTransReplace *)t; - if (strncmp(self->old_prefix, sb_string(key)->str, self->old_prefix_len) != 0) + if (strncmp(self->old_prefix, sb_gstring_string(key)->str, + self->old_prefix_len) != 0) return; - g_string_erase(sb_string(key), 0, self->old_prefix_len); - g_string_prepend_len(sb_string(key), self->new_prefix, self->new_prefix_len); + g_string_erase(sb_gstring_string(key), 0, self->old_prefix_len); + g_string_prepend_len(sb_gstring_string(key), + self->new_prefix, self->new_prefix_len); } static void @@ -238,11 +240,11 @@ value_pairs_transform_set_apply(ValuePairsTransformSet *vpts, gchar *key) if (g_pattern_match_string(vpts->pattern, key)) { GList *l; - ScratchBuffer *sb; + SBGString *sb; gchar *new_key; - sb = scratch_buffer_acquire (); - g_string_assign(sb_string(sb), key); + sb = sb_gstring_acquire (); + g_string_assign(sb_gstring_string(sb), key); l = vpts->transforms; while (l) @@ -251,9 +253,9 @@ value_pairs_transform_set_apply(ValuePairsTransformSet *vpts, gchar *key) l = l->next; } - new_key = sb_string(sb)->str; - g_string_steal(sb_string(sb)); - scratch_buffer_release (sb); + new_key = sb_gstring_string(sb)->str; + g_string_steal(sb_gstring_string(sb)); + sb_gstring_release (sb); return new_key; } diff --git a/modules/afamqp/afamqp.c b/modules/afamqp/afamqp.c index 70fd3e8fd74a5..923f90bee3adc 100644 --- a/modules/afamqp/afamqp.c +++ b/modules/afamqp/afamqp.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2012 Nagy, Attila - * Copyright (c) 2012 BalaBit IT Ltd, Budapest, Hungary - * Copyright (c) 2012 Gergely Nagy + * Copyright (c) 2012-2013 BalaBit IT Ltd, Budapest, Hungary + * Copyright (c) 2012-2013 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -403,8 +403,8 @@ afamqp_worker_publish(AMQPDestDriver *self, LogMessage *msg) amqp_table_t table; amqp_basic_properties_t props; gboolean success = TRUE; - ScratchBuffer *routing_key = scratch_buffer_acquire(); - ScratchBuffer *body = scratch_buffer_acquire(); + SBGString *routing_key = sb_gstring_acquire(); + SBGString *body = sb_gstring_acquire(); amqp_bytes_t body_bytes = amqp_cstring_bytes(""); gpointer user_data[] = { &self->entries, &pos, &self->max_entries }; @@ -422,21 +422,21 @@ afamqp_worker_publish(AMQPDestDriver *self, LogMessage *msg) props.headers = table; log_template_format(self->routing_key_template, msg, NULL, LTZ_LOCAL, - self->seq_num, NULL, sb_string(routing_key)); + self->seq_num, NULL, sb_gstring_string(routing_key)); if (self->body_template) { log_template_format(self->body_template, msg, NULL, LTZ_LOCAL, - self->seq_num, NULL, sb_string(body)); - body_bytes = amqp_cstring_bytes(sb_string(body)->str); + self->seq_num, NULL, sb_gstring_string(body)); + body_bytes = amqp_cstring_bytes(sb_gstring_string(body)->str); } ret = amqp_basic_publish(self->conn, 1, amqp_cstring_bytes(self->exchange), - amqp_cstring_bytes(sb_string(routing_key)->str), + amqp_cstring_bytes(sb_gstring_string(routing_key)->str), 0, 0, &props, body_bytes); - scratch_buffer_release(routing_key); - scratch_buffer_release(body); + sb_gstring_release(routing_key); + sb_gstring_release(body); if (ret < 0) { diff --git a/modules/json/jsonparser.c b/modules/json/jsonparser.c index 6246fe0d6a03f..82c7d1f8aea35 100644 --- a/modules/json/jsonparser.c +++ b/modules/json/jsonparser.c @@ -1,6 +1,6 @@ /* - * Copyright (c) 2011-2012 BalaBit IT Ltd, Budapest, Hungary - * Copyright (c) 2011-2012 Gergely Nagy + * Copyright (c) 2011-2013 BalaBit IT Ltd, Budapest, Hungary + * Copyright (c) 2011-2013 Gergely Nagy * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published @@ -67,58 +67,58 @@ log_json_parser_process_single (struct json_object *jso, const gchar *obj_key, LogMessage *msg) { - ScratchBuffer *key, *value; + SBGString *key, *value; gboolean parsed = FALSE; - key = scratch_buffer_acquire (); - value = scratch_buffer_acquire (); + key = sb_gstring_acquire (); + value = sb_gstring_acquire (); switch (json_object_get_type (jso)) { case json_type_boolean: parsed = TRUE; if (json_object_get_boolean (jso)) - g_string_assign (sb_string (value), "true"); + g_string_assign (sb_gstring_string (value), "true"); else - g_string_assign (sb_string (value), "false"); + g_string_assign (sb_gstring_string (value), "false"); break; case json_type_double: parsed = TRUE; - g_string_printf (sb_string (value), "%f", + g_string_printf (sb_gstring_string (value), "%f", json_object_get_double (jso)); break; case json_type_int: parsed = TRUE; - g_string_printf (sb_string (value), "%i", + g_string_printf (sb_gstring_string (value), "%i", json_object_get_int (jso)); break; case json_type_string: parsed = TRUE; - g_string_assign (sb_string (value), + g_string_assign (sb_gstring_string (value), json_object_get_string (jso)); break; case json_type_object: if (prefix) - g_string_assign (sb_string (key), prefix); - g_string_append (sb_string (key), obj_key); - g_string_append_c (sb_string (key), '.'); - log_json_parser_process_object (jso, sb_string (key)->str, msg); + g_string_assign (sb_gstring_string (key), prefix); + g_string_append (sb_gstring_string (key), obj_key); + g_string_append_c (sb_gstring_string (key), '.'); + log_json_parser_process_object (jso, sb_gstring_string (key)->str, msg); break; case json_type_array: { gint i, plen; - g_string_assign (sb_string (key), obj_key); + g_string_assign (sb_gstring_string (key), obj_key); - plen = sb_string (key)->len; + plen = sb_gstring_string (key)->len; for (i = 0; i < json_object_array_length (jso); i++) { - g_string_truncate (sb_string (key), plen); - g_string_append_printf (sb_string (key), "[%d]", i); + g_string_truncate (sb_gstring_string (key), plen); + g_string_append_printf (sb_gstring_string (key), "[%d]", i); log_json_parser_process_single (json_object_array_get_idx (jso, i), prefix, - sb_string (key)->str, msg); + sb_gstring_string (key)->str, msg); } break; } @@ -132,20 +132,22 @@ log_json_parser_process_single (struct json_object *jso, { if (prefix) { - g_string_assign (sb_string (key), prefix); - g_string_append (sb_string (key), obj_key); + g_string_assign (sb_gstring_string (key), prefix); + g_string_append (sb_gstring_string (key), obj_key); log_msg_set_value (msg, - log_msg_get_value_handle (sb_string (key)->str), - sb_string (value)->str, sb_string (value)->len); + log_msg_get_value_handle (sb_gstring_string (key)->str), + sb_gstring_string (value)->str, + sb_gstring_string (value)->len); } else log_msg_set_value (msg, log_msg_get_value_handle (obj_key), - sb_string (value)->str, sb_string (value)->len); + sb_gstring_string (value)->str, + sb_gstring_string (value)->len); } - scratch_buffer_release (key); - scratch_buffer_release (value); + sb_gstring_release (key); + sb_gstring_release (value); } static void