[syslog-ng] [PATCH 1/4] scratch-buffers: Support any number of stacks

Gergely Nagy algernon at balabit.hu
Fri Feb 15 16:26:02 CET 2013


From: Gergely Nagy <algernon at madhouse-project.org>

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 <algernon at madhouse-project.org>
---
 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 2d7383f..6dd1979 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 2debca9..481ce73 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 <algernon at balabit.hu>
+ * Copyright (c) 2011-2013 BalaBit IT Ltd, Budapest, Hungary
+ * Copyright (c) 2011-2013 Gergely Nagy <algernon at balabit.hu>
  *
  * 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 c61e518..72ab40a 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 <algernon at balabit.hu>
+ * Copyright (c) 2011-2013 BalaBit IT Ltd, Budapest, Hungary
+ * Copyright (c) 2011-2013 Gergely Nagy <algernon at balabit.hu>
  *
  * 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 <glib.h>
 
+/* 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 ee22b73..e78fc58 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 <algernon at balabit.hu>
+ * Copyright (c) 2011-2013 BalaBit IT Ltd, Budapest, Hungary
+ * Copyright (c) 2011-2013 Gergely Nagy <algernon at balabit.hu>
  *
  * 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 43699a0..89f71bc 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 <algernon at balabit.hu>
+ * Copyright (c) 2011-2013 BalaBit IT Ltd, Budapest, Hungary
+ * Copyright (c) 2011-2013 Gergely Nagy <algernon at balabit.hu>
  *
  * 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 <string.h>
 
-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 70fd3e8..923f90b 100644
--- a/modules/afamqp/afamqp.c
+++ b/modules/afamqp/afamqp.c
@@ -1,7 +1,7 @@
 /*
  * Copyright (c) 2012 Nagy, Attila <bra at fsn.hu>
- * Copyright (c) 2012 BalaBit IT Ltd, Budapest, Hungary
- * Copyright (c) 2012 Gergely Nagy <algernon at balabit.hu>
+ * Copyright (c) 2012-2013 BalaBit IT Ltd, Budapest, Hungary
+ * Copyright (c) 2012-2013 Gergely Nagy <algernon at balabit.hu>
  *
  * 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 6246fe0..82c7d1f 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 <algernon at balabit.hu>
+ * Copyright (c) 2011-2013 BalaBit IT Ltd, Budapest, Hungary
+ * Copyright (c) 2011-2013 Gergely Nagy <algernon at balabit.hu>
  *
  * 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
-- 
1.7.10.4




More information about the syslog-ng mailing list