From c73bbfdab1e7f22f4a3cc74757406da498d902d0 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sat, 30 Nov 2024 12:31:43 +0100 Subject: [PATCH 01/13] filterx/test_expr_regexp: fix heap corruption The references for these variables in _search() are already dropped as filterx_generator_create_container_new() takes those references over. Signed-off-by: Balazs Scheidler --- lib/filterx/tests/test_expr_regexp.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/filterx/tests/test_expr_regexp.c b/lib/filterx/tests/test_expr_regexp.c index b60009a6c..6fab5a51f 100644 --- a/lib/filterx/tests/test_expr_regexp.c +++ b/lib/filterx/tests/test_expr_regexp.c @@ -100,8 +100,6 @@ _search(const gchar *lhs, const gchar *pattern) filterx_object_unref(result_obj); filterx_expr_unref(cc_expr); - filterx_expr_unref(parent_fillable_expr_new); - filterx_expr_unref(expr); return fillable; } From c66b80b1a6d1398747cccaa287f6fbd2c1d7e728 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sat, 30 Nov 2024 20:49:30 +0100 Subject: [PATCH 02/13] filterx/expr-compound: move filterx_eval_get_context() out of the loop Signed-off-by: Balazs Scheidler --- lib/filterx/expr-compound.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/filterx/expr-compound.c b/lib/filterx/expr-compound.c index 35f6d7d83..e4ba3ca1f 100644 --- a/lib/filterx/expr-compound.c +++ b/lib/filterx/expr-compound.c @@ -84,15 +84,18 @@ _eval_expr(FilterXExpr *expr, FilterXObject **result) static gboolean _eval_exprs(FilterXCompoundExpr *self, FilterXObject **result) { + FilterXEvalContext *context = filterx_eval_get_context(); + *result = NULL; for (gint i = 0; i < self->exprs->len; i++) { filterx_object_unref(*result); - FilterXEvalContext *context = filterx_eval_get_context(); if (G_UNLIKELY(context->eval_control_modifier == FXC_DROP || context->eval_control_modifier == FXC_DONE)) - /* code flow modifier detected, short circuiting */ - return TRUE; + { + /* code flow modifier detected, short circuiting */ + return TRUE; + } FilterXExpr *expr = g_ptr_array_index(self->exprs, i); if (!_eval_expr(expr, result)) From 0c4ad228cf8fee20336f6bab8fca90bb230ef817 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sat, 30 Nov 2024 13:15:00 +0100 Subject: [PATCH 03/13] filterx/filterx-object: inline filterx_object_is_frozen() Signed-off-by: Balazs Scheidler --- lib/filterx/filterx-object.c | 8 -------- lib/filterx/filterx-object.h | 9 ++++++++- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/filterx/filterx-object.c b/lib/filterx/filterx-object.c index 0faa2912d..5c962e1e7 100644 --- a/lib/filterx/filterx-object.c +++ b/lib/filterx/filterx-object.c @@ -91,8 +91,6 @@ filterx_type_init(FilterXType *type) msg_error("Reregistering filterx type", evt_tag_str("name", type->name)); } -#define FILTERX_OBJECT_MAGIC_BIAS G_MAXINT32 - void filterx_object_free_method(FilterXObject *self) { @@ -125,12 +123,6 @@ filterx_object_freeze(FilterXObject *self) return TRUE; } -gboolean -filterx_object_is_frozen(FilterXObject *self) -{ - return g_atomic_counter_get(&self->ref_cnt) == FILTERX_OBJECT_MAGIC_BIAS; -} - void filterx_object_unfreeze_and_free(FilterXObject *self) { diff --git a/lib/filterx/filterx-object.h b/lib/filterx/filterx-object.h index 4ba32e902..2faee0049 100644 --- a/lib/filterx/filterx-object.h +++ b/lib/filterx/filterx-object.h @@ -74,6 +74,8 @@ void _filterx_type_init_methods(FilterXType *type); __VA_ARGS__ \ } +#define FILTERX_OBJECT_MAGIC_BIAS G_MAXINT32 + FILTERX_DECLARE_TYPE(object); @@ -103,11 +105,16 @@ FilterXObject *filterx_object_new(FilterXType *type); FilterXObject *filterx_object_ref(FilterXObject *self); void filterx_object_unref(FilterXObject *self); gboolean filterx_object_freeze(FilterXObject *self); -gboolean filterx_object_is_frozen(FilterXObject *self); void filterx_object_unfreeze_and_free(FilterXObject *self); void filterx_object_init_instance(FilterXObject *self, FilterXType *type); void filterx_object_free_method(FilterXObject *self); +static inline gboolean +filterx_object_is_frozen(FilterXObject *self) +{ + return g_atomic_counter_get(&self->ref_cnt) == FILTERX_OBJECT_MAGIC_BIAS; +} + static inline void filterx_object_make_readonly(FilterXObject *self) { From 20d19128eba7816296e7960c9c604e50516a2267 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sat, 30 Nov 2024 22:24:09 +0100 Subject: [PATCH 04/13] filterx/filterx-eval: make filterx_eval_store_weak_ref() inline Signed-off-by: Balazs Scheidler --- lib/filterx/filterx-eval.c | 31 ------------------------------- lib/filterx/filterx-eval.h | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/lib/filterx/filterx-eval.c b/lib/filterx/filterx-eval.c index 505cf5095..9d510a993 100644 --- a/lib/filterx/filterx-eval.c +++ b/lib/filterx/filterx-eval.c @@ -118,37 +118,6 @@ filterx_format_last_error_location(void) return filterx_error_format_location(&context->error); } - -/* - * This is not a real weakref implementation as we will never get rid off - * weak references until the very end of a scope. If this wasn't the case - * we would have to: - * 1) run a proper GC - * 2) notify weak references once the object is detroyed - * - * None of that exists now and I doubt ever will (but never say never). - * Right now a weak ref is destroyed as a part of the scope finalization - * process at which point circular references will be broken so the rest can - * go too. - */ -void -filterx_eval_store_weak_ref(FilterXObject *object) -{ - /* Frozen objects do not need weak refs. */ - if (object && filterx_object_is_frozen(object)) - return; - - FilterXEvalContext *context = filterx_eval_get_context(); - - if (object && !object->weak_referenced) - { - /* avoid putting object to the list multiple times */ - object->weak_referenced = TRUE; - g_assert(context->weak_refs); - g_ptr_array_add(context->weak_refs, filterx_object_ref(object)); - } -} - FilterXEvalResult filterx_eval_exec(FilterXEvalContext *context, FilterXExpr *expr, LogMessage *msg) { diff --git a/lib/filterx/filterx-eval.h b/lib/filterx/filterx-eval.h index d8f96f0f7..8c995cbf0 100644 --- a/lib/filterx/filterx-eval.h +++ b/lib/filterx/filterx-eval.h @@ -69,8 +69,6 @@ EVTTAG *filterx_format_last_error_location(void); void filterx_eval_clear_errors(void); EVTTAG *filterx_format_eval_result(FilterXEvalResult result); -void filterx_eval_store_weak_ref(FilterXObject *object); - void filterx_eval_init_context(FilterXEvalContext *context, FilterXEvalContext *previous_context); void filterx_eval_deinit_context(FilterXEvalContext *context); @@ -95,4 +93,34 @@ filterx_eval_prepare_for_fork(FilterXEvalContext *context, LogMessage **pmsg, co filterx_scope_write_protect(context->scope); } +/* + * This is not a real weakref implementation as we will never get rid off + * weak references until the very end of a scope. If this wasn't the case + * we would have to: + * 1) run a proper GC + * 2) notify weak references once the object is detroyed + * + * None of that exists now and I doubt ever will (but never say never). + * Right now a weak ref is destroyed as a part of the scope finalization + * process at which point circular references will be broken so the rest can + * go too. + */ +static inline void +filterx_eval_store_weak_ref(FilterXObject *object) +{ + /* Frozen objects do not need weak refs. */ + if (object && filterx_object_is_frozen(object)) + return; + + if (object && !object->weak_referenced) + { + FilterXEvalContext *context = filterx_eval_get_context(); + /* avoid putting object to the list multiple times */ + object->weak_referenced = TRUE; + g_assert(context->weak_refs); + g_ptr_array_add(context->weak_refs, filterx_object_ref(object)); + } +} + + #endif From cc5563665190bce034bcc732ea93728fc54999ab Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sat, 30 Nov 2024 22:40:34 +0100 Subject: [PATCH 05/13] filterx/object-extractor: make object extractor functions inline Signed-off-by: Balazs Scheidler --- lib/filterx/CMakeLists.txt | 1 - lib/filterx/Makefile.am | 1 - lib/filterx/object-extractor.c | 178 --------------------------------- lib/filterx/object-extractor.h | 165 ++++++++++++++++++++++++++++-- 4 files changed, 154 insertions(+), 191 deletions(-) delete mode 100644 lib/filterx/object-extractor.c diff --git a/lib/filterx/CMakeLists.txt b/lib/filterx/CMakeLists.txt index c7af787e1..9dbdc550b 100644 --- a/lib/filterx/CMakeLists.txt +++ b/lib/filterx/CMakeLists.txt @@ -112,7 +112,6 @@ set(FILTERX_SOURCES filterx/func-vars.c filterx/object-datetime.c filterx/object-dict-interface.c - filterx/object-extractor.c filterx/object-json-array.c filterx/object-json-object.c filterx/object-json.c diff --git a/lib/filterx/Makefile.am b/lib/filterx/Makefile.am index bdf0a756c..880496194 100644 --- a/lib/filterx/Makefile.am +++ b/lib/filterx/Makefile.am @@ -114,7 +114,6 @@ filterx_sources = \ lib/filterx/func-vars.c \ lib/filterx/object-datetime.c \ lib/filterx/object-dict-interface.c \ - lib/filterx/object-extractor.c \ lib/filterx/object-json-array.c \ lib/filterx/object-json-object.c \ lib/filterx/object-json.c \ diff --git a/lib/filterx/object-extractor.c b/lib/filterx/object-extractor.c deleted file mode 100644 index 4ddaa12e3..000000000 --- a/lib/filterx/object-extractor.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2024 Axoflow - * Copyright (c) 2024 Attila Szakacs - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * As an additional exemption you are allowed to compile & link against the - * OpenSSL libraries as published by the OpenSSL project. See the file - * COPYING for details. - * - */ -#include "filterx/object-extractor.h" -#include "filterx/object-message-value.h" -#include "filterx/object-string.h" -#include "filterx/object-primitive.h" -#include "filterx/object-datetime.h" -#include "filterx/object-null.h" -#include "filterx/object-json.h" -#include "filterx/filterx-object-istype.h" - -gboolean -filterx_object_extract_string_ref(FilterXObject *obj, const gchar **value, gsize *len) -{ - if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) - return filterx_message_value_get_string_ref(obj, value, len); - - *value = filterx_string_get_value_ref(obj, len); - return !!(*value); -} - -gboolean -filterx_object_extract_bytes_ref(FilterXObject *obj, const gchar **value, gsize *len) -{ - if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) - return filterx_message_value_get_bytes_ref(obj, value, len); - - *value = filterx_bytes_get_value_ref(obj, len); - return !!(*value); -} - -gboolean -filterx_object_extract_protobuf_ref(FilterXObject *obj, const gchar **value, gsize *len) -{ - if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) - return filterx_message_value_get_protobuf_ref(obj, value, len); - - *value = filterx_protobuf_get_value_ref(obj, len); - return !!(*value); -} - -gboolean -filterx_object_extract_boolean(FilterXObject *obj, gboolean *value) -{ - if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) - return filterx_message_value_get_boolean(obj, value); - - return filterx_boolean_unwrap(obj, value); -} - -gboolean -filterx_object_extract_integer(FilterXObject *obj, gint64 *value) -{ - if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) - return filterx_message_value_get_integer(obj, value); - - return filterx_integer_unwrap(obj, value); -} - -gboolean -filterx_object_extract_double(FilterXObject *obj, gdouble *value) -{ - if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) - return filterx_message_value_get_double(obj, value); - - return filterx_double_unwrap(obj, value); -} - -gboolean -filterx_object_extract_generic_number(FilterXObject *obj, GenericNumber *value) -{ - if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(primitive))) - { - *value = filterx_primitive_get_value(obj); - return TRUE; - } - - if (!filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) - return FALSE; - - gint64 i; - if (filterx_message_value_get_integer(obj, &i)) - { - gn_set_int64(value, i); - return TRUE; - } - - gdouble d; - if (filterx_message_value_get_double(obj, &d)) - { - gn_set_double(value, d, -1); - return TRUE; - } - - gboolean b; - if (filterx_message_value_get_boolean(obj, &b)) - { - gn_set_int64(value, (gint64) b); - return TRUE; - } - - return FALSE; -} - -gboolean -filterx_object_extract_datetime(FilterXObject *obj, UnixTime *value) -{ - if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) - return filterx_message_value_get_datetime(obj, value); - - if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(datetime))) - { - *value = filterx_datetime_get_value(obj); - return TRUE; - } - - return FALSE; -} - -gboolean -filterx_object_extract_null(FilterXObject *obj) -{ - if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) - return filterx_message_value_get_null(obj); - - return filterx_object_is_type(obj, &FILTERX_TYPE_NAME(null)); -} - -gboolean -filterx_object_extract_json_array(FilterXObject *obj, struct json_object **value) -{ - if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) - { - if (!filterx_message_value_get_json(obj, value)) - return FALSE; - - if (json_object_is_type(*value, json_type_array)) - return TRUE; - - json_object_put(*value); - *value = NULL; - return FALSE; - } - - *value = filterx_json_array_get_value(obj); - return !!(*value); -} - -gboolean -filterx_object_extract_json_object(FilterXObject *obj, struct json_object **value) -{ - if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) - return filterx_message_value_get_json(obj, value); - - *value = filterx_json_object_get_value(obj); - return !!(*value); -} diff --git a/lib/filterx/object-extractor.h b/lib/filterx/object-extractor.h index e6dbe80cf..133eed8e6 100644 --- a/lib/filterx/object-extractor.h +++ b/lib/filterx/object-extractor.h @@ -25,19 +25,162 @@ #define FILTERX_OBJECT_EXTRACTOR_H_INCLUDED #include "filterx/filterx-object.h" +#include "filterx/object-message-value.h" +#include "filterx/object-string.h" +#include "filterx/object-primitive.h" +#include "filterx/object-datetime.h" +#include "filterx/object-null.h" +#include "filterx/object-json.h" +#include "filterx/filterx-object-istype.h" + #include "generic-number.h" #include "compat/json.h" -gboolean filterx_object_extract_string_ref(FilterXObject *obj, const gchar **value, gsize *len); -gboolean filterx_object_extract_bytes_ref(FilterXObject *obj, const gchar **value, gsize *len); -gboolean filterx_object_extract_protobuf_ref(FilterXObject *obj, const gchar **value, gsize *len); -gboolean filterx_object_extract_boolean(FilterXObject *obj, gboolean *value); -gboolean filterx_object_extract_integer(FilterXObject *obj, gint64 *value); -gboolean filterx_object_extract_double(FilterXObject *obj, gdouble *value); -gboolean filterx_object_extract_generic_number(FilterXObject *obj, GenericNumber *value); -gboolean filterx_object_extract_datetime(FilterXObject *obj, UnixTime *value); -gboolean filterx_object_extract_null(FilterXObject *obj); -gboolean filterx_object_extract_json_array(FilterXObject *obj, struct json_object **value); -gboolean filterx_object_extract_json_object(FilterXObject *obj, struct json_object **value); +static inline gboolean +filterx_object_extract_string_ref(FilterXObject *obj, const gchar **value, gsize *len) +{ + if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) + return filterx_message_value_get_string_ref(obj, value, len); + + *value = filterx_string_get_value_ref(obj, len); + return !!(*value); +} + +static inline gboolean +filterx_object_extract_bytes_ref(FilterXObject *obj, const gchar **value, gsize *len) +{ + if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) + return filterx_message_value_get_bytes_ref(obj, value, len); + + *value = filterx_bytes_get_value_ref(obj, len); + return !!(*value); +} + +static inline gboolean +filterx_object_extract_protobuf_ref(FilterXObject *obj, const gchar **value, gsize *len) +{ + if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) + return filterx_message_value_get_protobuf_ref(obj, value, len); + + *value = filterx_protobuf_get_value_ref(obj, len); + return !!(*value); +} + +static inline gboolean +filterx_object_extract_boolean(FilterXObject *obj, gboolean *value) +{ + if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) + return filterx_message_value_get_boolean(obj, value); + + return filterx_boolean_unwrap(obj, value); +} + +static inline gboolean +filterx_object_extract_integer(FilterXObject *obj, gint64 *value) +{ + if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) + return filterx_message_value_get_integer(obj, value); + + return filterx_integer_unwrap(obj, value); +} + +static inline gboolean +filterx_object_extract_double(FilterXObject *obj, gdouble *value) +{ + if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) + return filterx_message_value_get_double(obj, value); + + return filterx_double_unwrap(obj, value); +} + +static inline gboolean +filterx_object_extract_generic_number(FilterXObject *obj, GenericNumber *value) +{ + if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(primitive))) + { + *value = filterx_primitive_get_value(obj); + return TRUE; + } + + if (!filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) + return FALSE; + + gint64 i; + if (filterx_message_value_get_integer(obj, &i)) + { + gn_set_int64(value, i); + return TRUE; + } + + gdouble d; + if (filterx_message_value_get_double(obj, &d)) + { + gn_set_double(value, d, -1); + return TRUE; + } + + gboolean b; + if (filterx_message_value_get_boolean(obj, &b)) + { + gn_set_int64(value, (gint64) b); + return TRUE; + } + + return FALSE; +} + +static inline gboolean +filterx_object_extract_datetime(FilterXObject *obj, UnixTime *value) +{ + if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) + return filterx_message_value_get_datetime(obj, value); + + if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(datetime))) + { + *value = filterx_datetime_get_value(obj); + return TRUE; + } + + return FALSE; +} + +static inline gboolean +filterx_object_extract_null(FilterXObject *obj) +{ + if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) + return filterx_message_value_get_null(obj); + + return filterx_object_is_type(obj, &FILTERX_TYPE_NAME(null)); +} + +static inline gboolean +filterx_object_extract_json_array(FilterXObject *obj, struct json_object **value) +{ + if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) + { + if (!filterx_message_value_get_json(obj, value)) + return FALSE; + + if (json_object_is_type(*value, json_type_array)) + return TRUE; + + json_object_put(*value); + *value = NULL; + return FALSE; + } + + *value = filterx_json_array_get_value(obj); + return !!(*value); +} + +static inline gboolean +filterx_object_extract_json_object(FilterXObject *obj, struct json_object **value) +{ + if (filterx_object_is_type(obj, &FILTERX_TYPE_NAME(message_value))) + return filterx_message_value_get_json(obj, value); + + *value = filterx_json_object_get_value(obj); + return !!(*value); +} #endif From 6d204f4c962d081e476d84fac9c9b8f49076e17e Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sat, 30 Nov 2024 22:53:57 +0100 Subject: [PATCH 06/13] filterx/filterx-variable: make variable helper functions inline Signed-off-by: Balazs Scheidler --- lib/filterx/filterx-variable.c | 52 ------------------------------ lib/filterx/filterx-variable.h | 59 +++++++++++++++++++++++++++++----- 2 files changed, 51 insertions(+), 60 deletions(-) diff --git a/lib/filterx/filterx-variable.c b/lib/filterx/filterx-variable.c index f8b30f77f..e2e24a6fd 100644 --- a/lib/filterx/filterx-variable.c +++ b/lib/filterx/filterx-variable.c @@ -25,58 +25,6 @@ #include "filterx-variable.h" -#define FILTERX_HANDLE_FLOATING_BIT (1UL << 31) - -gboolean -filterx_variable_handle_is_floating(FilterXVariableHandle handle) -{ - return !!(handle & FILTERX_HANDLE_FLOATING_BIT); -} - -gboolean -filterx_variable_is_floating(FilterXVariable *v) -{ - return filterx_variable_handle_is_floating(v->handle); -} - -NVHandle -filterx_variable_get_nv_handle(FilterXVariable *v) -{ - return v->handle & ~FILTERX_HANDLE_FLOATING_BIT; -} - -const gchar * -filterx_variable_get_name(FilterXVariable *v, gssize *len) -{ - return log_msg_get_handle_name(filterx_variable_get_nv_handle(v), len); -} - -FilterXObject * -filterx_variable_get_value(FilterXVariable *v) -{ - return filterx_object_ref(v->value); -} - -void -filterx_variable_set_value(FilterXVariable *v, FilterXObject *new_value) -{ - filterx_object_unref(v->value); - v->value = filterx_object_ref(new_value); - v->assigned = TRUE; -} - -void -filterx_variable_unset_value(FilterXVariable *v) -{ - filterx_variable_set_value(v, NULL); -} - -gboolean -filterx_variable_is_set(FilterXVariable *v) -{ - return v->value != NULL; -} - FilterXVariableHandle filterx_map_varname_to_handle(const gchar *name, FilterXVariableType type) { diff --git a/lib/filterx/filterx-variable.h b/lib/filterx/filterx-variable.h index 38754dad0..68ec3cc3d 100644 --- a/lib/filterx/filterx-variable.h +++ b/lib/filterx/filterx-variable.h @@ -60,14 +60,57 @@ void filterx_variable_init_instance(FilterXVariable *v, FilterXVariableHandle ha FilterXObject *initial_value, guint32 generation); void filterx_variable_free_method(FilterXVariable *v); -gboolean filterx_variable_is_floating(FilterXVariable *v); -gboolean filterx_variable_handle_is_floating(FilterXVariableHandle handle); -const gchar *filterx_variable_get_name(FilterXVariable *v, gssize *len); -NVHandle filterx_variable_get_nv_handle(FilterXVariable *v); -FilterXObject *filterx_variable_get_value(FilterXVariable *v); -void filterx_variable_set_value(FilterXVariable *v, FilterXObject *new_value); -void filterx_variable_unset_value(FilterXVariable *v); -gboolean filterx_variable_is_set(FilterXVariable *v); +#define FILTERX_HANDLE_FLOATING_BIT (1UL << 31) + +static inline gboolean +filterx_variable_handle_is_floating(FilterXVariableHandle handle) +{ + return !!(handle & FILTERX_HANDLE_FLOATING_BIT); +} + +static inline gboolean +filterx_variable_is_floating(FilterXVariable *v) +{ + return filterx_variable_handle_is_floating(v->handle); +} + +static inline NVHandle +filterx_variable_get_nv_handle(FilterXVariable *v) +{ + return v->handle & ~FILTERX_HANDLE_FLOATING_BIT; +} + +static inline const gchar * +filterx_variable_get_name(FilterXVariable *v, gssize *len) +{ + return log_msg_get_handle_name(filterx_variable_get_nv_handle(v), len); +} + +static inline FilterXObject * +filterx_variable_get_value(FilterXVariable *v) +{ + return filterx_object_ref(v->value); +} + +static inline void +filterx_variable_set_value(FilterXVariable *v, FilterXObject *new_value) +{ + filterx_object_unref(v->value); + v->value = filterx_object_ref(new_value); + v->assigned = TRUE; +} + +static inline void +filterx_variable_unset_value(FilterXVariable *v) +{ + filterx_variable_set_value(v, NULL); +} + +static inline gboolean +filterx_variable_is_set(FilterXVariable *v) +{ + return v->value != NULL; +} static inline gboolean filterx_variable_is_declared(FilterXVariable *v) From ee9eb41348865ed6da9bf4320a5ca93ab1433456 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sat, 30 Nov 2024 12:46:48 +0100 Subject: [PATCH 07/13] filterx/filterx-expr: move lloc to a heap allocated structure To avoid it using almost an entire cacheline in FilterXExpr. Signed-off-by: Balazs Scheidler --- lib/filterx/filterx-expr.c | 14 ++++++++++---- lib/filterx/filterx-expr.h | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/filterx/filterx-expr.c b/lib/filterx/filterx-expr.c index 61af438c2..88e181a7d 100644 --- a/lib/filterx/filterx-expr.c +++ b/lib/filterx/filterx-expr.c @@ -32,7 +32,10 @@ void filterx_expr_set_location_with_text(FilterXExpr *self, CfgLexer *lexer, CFG_LTYPE *lloc, const gchar *text) { - self->lloc = *lloc; + if (!self->lloc) + self->lloc = g_new0(CFG_LTYPE, 1); + *self->lloc = *lloc; + if (debug_flag) self->expr_text = g_strdup(text); } @@ -40,7 +43,9 @@ filterx_expr_set_location_with_text(FilterXExpr *self, CfgLexer *lexer, CFG_LTYP void filterx_expr_set_location(FilterXExpr *self, CfgLexer *lexer, CFG_LTYPE *lloc) { - self->lloc = *lloc; + if (!self->lloc) + self->lloc = g_new0(CFG_LTYPE, 1); + *self->lloc = *lloc; if (debug_flag) { GString *res = g_string_sized_new(0); @@ -52,9 +57,9 @@ filterx_expr_set_location(FilterXExpr *self, CfgLexer *lexer, CFG_LTYPE *lloc) EVTTAG * filterx_expr_format_location_tag(FilterXExpr *self) { - if (self) + if (self && self->lloc) return evt_tag_printf("expr", "%s:%d:%d|\t%s", - self->lloc.name, self->lloc.first_line, self->lloc.first_column, + self->lloc->name, self->lloc->first_line, self->lloc->first_column, self->expr_text ? : "n/a"); else return evt_tag_str("expr", "n/a"); @@ -74,6 +79,7 @@ filterx_expr_deinit_method(FilterXExpr *self, GlobalConfig *cfg) void filterx_expr_free_method(FilterXExpr *self) { + g_free(self->lloc); g_free(self->expr_text); } diff --git a/lib/filterx/filterx-expr.h b/lib/filterx/filterx-expr.h index f67227fd8..a7b4a8e52 100644 --- a/lib/filterx/filterx-expr.h +++ b/lib/filterx/filterx-expr.h @@ -58,7 +58,7 @@ struct _FilterXExpr gboolean inited; - CFG_LTYPE lloc; + CFG_LTYPE *lloc; gchar *expr_text; }; From 1a2b4f912704dff55b227791c9cf71eaa70172f9 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sun, 1 Dec 2024 13:44:36 +0100 Subject: [PATCH 08/13] filterx/filterx-object: inline filterx_object_ref/unref() Signed-off-by: Balazs Scheidler --- lib/filterx/filterx-object.c | 31 ------------------------------- lib/filterx/filterx-object.h | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/lib/filterx/filterx-object.c b/lib/filterx/filterx-object.c index 5c962e1e7..260ca1286 100644 --- a/lib/filterx/filterx-object.c +++ b/lib/filterx/filterx-object.c @@ -131,37 +131,6 @@ filterx_object_unfreeze_and_free(FilterXObject *self) filterx_object_unref(self); } -FilterXObject * -filterx_object_ref(FilterXObject *self) -{ - if (!self) - return NULL; - - if (filterx_object_is_frozen(self)) - return self; - - g_atomic_counter_inc(&self->ref_cnt); - - return self; -} - -void -filterx_object_unref(FilterXObject *self) -{ - if (!self) - return; - - if (filterx_object_is_frozen(self)) - return; - - g_assert(g_atomic_counter_get(&self->ref_cnt) > 0); - if (g_atomic_counter_dec_and_test(&self->ref_cnt)) - { - self->type->free_fn(self); - g_free(self); - } -} - FilterXType FILTERX_TYPE_NAME(object) = { .super_type = NULL, diff --git a/lib/filterx/filterx-object.h b/lib/filterx/filterx-object.h index 2faee0049..e321cf16c 100644 --- a/lib/filterx/filterx-object.h +++ b/lib/filterx/filterx-object.h @@ -102,8 +102,6 @@ FilterXObject *filterx_object_getattr_string(FilterXObject *self, const gchar *a gboolean filterx_object_setattr_string(FilterXObject *self, const gchar *attr_name, FilterXObject **new_value); FilterXObject *filterx_object_new(FilterXType *type); -FilterXObject *filterx_object_ref(FilterXObject *self); -void filterx_object_unref(FilterXObject *self); gboolean filterx_object_freeze(FilterXObject *self); void filterx_object_unfreeze_and_free(FilterXObject *self); void filterx_object_init_instance(FilterXObject *self, FilterXType *type); @@ -115,6 +113,37 @@ filterx_object_is_frozen(FilterXObject *self) return g_atomic_counter_get(&self->ref_cnt) == FILTERX_OBJECT_MAGIC_BIAS; } +static inline FilterXObject * +filterx_object_ref(FilterXObject *self) +{ + if (!self) + return NULL; + + if (filterx_object_is_frozen(self)) + return self; + + g_atomic_counter_inc(&self->ref_cnt); + + return self; +} + +static inline void +filterx_object_unref(FilterXObject *self) +{ + if (!self) + return; + + if (filterx_object_is_frozen(self)) + return; + + g_assert(g_atomic_counter_get(&self->ref_cnt) > 0); + if (g_atomic_counter_dec_and_test(&self->ref_cnt)) + { + self->type->free_fn(self); + g_free(self); + } +} + static inline void filterx_object_make_readonly(FilterXObject *self) { From 6e3c96288de1974942201922ba2775930d5f79b3 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Mon, 2 Dec 2024 08:42:47 +0100 Subject: [PATCH 09/13] filterx/expr-compound: don't fetch "len" from self->exprs array for every iteration Signed-off-by: Balazs Scheidler --- lib/filterx/expr-compound.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/filterx/expr-compound.c b/lib/filterx/expr-compound.c index e4ba3ca1f..041a7b242 100644 --- a/lib/filterx/expr-compound.c +++ b/lib/filterx/expr-compound.c @@ -87,7 +87,8 @@ _eval_exprs(FilterXCompoundExpr *self, FilterXObject **result) FilterXEvalContext *context = filterx_eval_get_context(); *result = NULL; - for (gint i = 0; i < self->exprs->len; i++) + gint len = self->exprs->len; + for (gint i = 0; i < len; i++) { filterx_object_unref(*result); From 6ca5e879d3983ae1a1932d81ec92f534165d1d8c Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Mon, 2 Dec 2024 08:44:18 +0100 Subject: [PATCH 10/13] filterx/filterx-expr: move often used members in FilterXExpr to the front Signed-off-by: Balazs Scheidler --- lib/filterx/filterx-expr.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/filterx/filterx-expr.h b/lib/filterx/filterx-expr.h index a7b4a8e52..1864c4b37 100644 --- a/lib/filterx/filterx-expr.h +++ b/lib/filterx/filterx-expr.h @@ -31,15 +31,14 @@ struct _FilterXExpr { - /* not thread-safe */ - guint32 ref_cnt; - const gchar *type; - guint32 ignore_falsy_result:1, suppress_from_trace:1; - StatsCounterItem *eval_count; - /* evaluate expression */ FilterXObject *(*eval)(FilterXExpr *self); + + /* not thread-safe */ + guint32 ref_cnt; + guint32 ignore_falsy_result:1, suppress_from_trace:1, inited:1; + /* not to be used except for FilterXMessageRef, replace any cached values * with the unmarshaled version */ void (*_update_repr)(FilterXExpr *self, FilterXObject *new_repr); @@ -56,8 +55,7 @@ struct _FilterXExpr void (*deinit)(FilterXExpr *self, GlobalConfig *cfg); void (*free_fn)(FilterXExpr *self); - gboolean inited; - + const gchar *type; CFG_LTYPE *lloc; gchar *expr_text; }; From 96dfe859f4cab1cd292d276d12edd4c724cd7e02 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Mon, 2 Dec 2024 08:44:59 +0100 Subject: [PATCH 11/13] filterx/filterx-weakrefs: make weakref related functions inline Signed-off-by: Balazs Scheidler --- lib/filterx/filterx-weakrefs.c | 49 ------------------------------- lib/filterx/filterx-weakrefs.h | 53 ++++++++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 51 deletions(-) diff --git a/lib/filterx/filterx-weakrefs.c b/lib/filterx/filterx-weakrefs.c index 49ac4416b..0dd988879 100644 --- a/lib/filterx/filterx-weakrefs.c +++ b/lib/filterx/filterx-weakrefs.c @@ -23,58 +23,9 @@ #include "filterx/filterx-weakrefs.h" #include "filterx/filterx-eval.h" -/* - * Weakrefs can be used to break up circular references between objects - * without having to do expensive loop discovery. Although we are not - * implementing complete weakref support, the interface mimics that, so we - * could eventually implement it. - * - * Weakrefs work as follows: - * - each object can have a combination of hard refs and weak refs - * - the object can be freed when the hard references are gone - * - all weak refs will be cleared (e.g. set to NULL) when the object is freed - * - * This means that if we have circular references between a objects (not - * necessarily two), the circle can be broken by just one weakref in the loop. - * - * Our weakref implementation is limited, as we don't have a GC mechanism. - * We will destroy lingering objects at the end of our current scope and - * weakrefs don't outlive scopes. - * - * With this assumption, our end-of-scope disposal of objects will work like this: - * - we get rid of all weakrefs - * - we get rid of all hardrefs - * - * Which should just get rid of all loops. We currently _do not_ set the - * weakref back to NULL at disposal, since no code is to be executed _after_ - * the disposal is done, e.g. the invalidated pointers should not be - * dereferenced. - */ - void filterx_weakref_set(FilterXWeakRef *self, FilterXObject *object) { filterx_eval_store_weak_ref(object); self->object = object; } - -void -filterx_weakref_clear(FilterXWeakRef *self) -{ - /* we do nothing with our ref here as that should be disposed at the end of the scope automatically */ - self->object = NULL; -} - -/* NOTE: returns a hard reference if the weakref is still valid */ -FilterXObject * -filterx_weakref_get(FilterXWeakRef *self) -{ - /* deref is now just returning the pointer, we don't have a means to - * validate if it's valid, we just assume it is until our Scope has not - * been terminated yet */ - - if (!self) - return NULL; - - return filterx_object_ref(self->object); -} diff --git a/lib/filterx/filterx-weakrefs.h b/lib/filterx/filterx-weakrefs.h index cb7c0f312..91a8889ca 100644 --- a/lib/filterx/filterx-weakrefs.h +++ b/lib/filterx/filterx-weakrefs.h @@ -30,8 +30,57 @@ typedef struct _FilterXWeakRef FilterXObject *object; } FilterXWeakRef; +/* + * Weakrefs can be used to break up circular references between objects + * without having to do expensive loop discovery. Although we are not + * implementing complete weakref support, the interface mimics that, so we + * could eventually implement it. + * + * Weakrefs work as follows: + * - each object can have a combination of hard refs and weak refs + * - the object can be freed when the hard references are gone + * - all weak refs will be cleared (e.g. set to NULL) when the object is freed + * + * This means that if we have circular references between a objects (not + * necessarily two), the circle can be broken by just one weakref in the loop. + * + * Our weakref implementation is limited, as we don't have a GC mechanism. + * We will destroy lingering objects at the end of our current scope and + * weakrefs don't outlive scopes. + * + * With this assumption, our end-of-scope disposal of objects will work like this: + * - we get rid of all weakrefs + * - we get rid of all hardrefs + * + * Which should just get rid of all loops. We currently _do not_ set the + * weakref back to NULL at disposal, since no code is to be executed _after_ + * the disposal is done, e.g. the invalidated pointers should not be + * dereferenced. + */ + void filterx_weakref_set(FilterXWeakRef *self, FilterXObject *object); -void filterx_weakref_clear(FilterXWeakRef *self); -FilterXObject *filterx_weakref_get(FilterXWeakRef *self); + + +static inline void +filterx_weakref_clear(FilterXWeakRef *self) +{ + /* we do nothing with our ref here as that should be disposed at the end of the scope automatically */ + self->object = NULL; +} + +/* NOTE: returns a hard reference if the weakref is still valid */ +static inline FilterXObject * +filterx_weakref_get(FilterXWeakRef *self) +{ + /* deref is now just returning the pointer, we don't have a means to + * validate if it's valid, we just assume it is until our Scope has not + * been terminated yet */ + + if (!self) + return NULL; + + return filterx_object_ref(self->object); +} + #endif From 1db315a62f2c917b34f336a8efdae6654cddea94 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sat, 30 Nov 2024 23:22:00 +0100 Subject: [PATCH 12/13] dnscache: use timeutils/cache.c instead of iv_now Otherwise we had a lot of clock_gettime() calls. Signed-off-by: Balazs Scheidler --- lib/dnscache.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/dnscache.c b/lib/dnscache.c index a640e6eee..5960dc291 100644 --- a/lib/dnscache.c +++ b/lib/dnscache.c @@ -161,7 +161,7 @@ dns_cache_store(DNSCache *self, gboolean persistent, gint family, void *addr, co INIT_IV_LIST_HEAD(&entry->list); if (!persistent) { - entry->resolved = iv_now.tv_sec; + entry->resolved = get_cached_realtime_sec(); iv_list_add(&entry->list, &self->cache_list); } else @@ -304,8 +304,7 @@ dns_cache_lookup(DNSCache *self, gint family, void *addr, const gchar **hostname DNSCacheEntry *entry; time_t now; - iv_validate_now(); - now = iv_now.tv_sec; + now = get_cached_realtime_sec(); dns_cache_check_hosts(self, now); dns_cache_fill_key(&key, family, addr); From 2c30b3f64fb394a3cf28761eae0542eec5f130e6 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sat, 30 Nov 2024 23:32:27 +0100 Subject: [PATCH 13/13] scratch-buffers: use timeutils/cache instead of iv_now Signed-off-by: Balazs Scheidler --- lib/scratch-buffers.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/scratch-buffers.c b/lib/scratch-buffers.c index 6c5b6fa52..433330d5a 100644 --- a/lib/scratch-buffers.c +++ b/lib/scratch-buffers.c @@ -230,8 +230,8 @@ _thread_maintenance_period_elapsed(void) if (!scratch_buffers_time_of_last_maintenance) return TRUE; - iv_validate_now(); - if (scratch_buffers_time_of_last_maintenance - iv_now.tv_sec >= SCRATCH_BUFFERS_MAINTENANCE_PERIOD) + time_t now = get_cached_realtime_sec(); + if (scratch_buffers_time_of_last_maintenance - now >= SCRATCH_BUFFERS_MAINTENANCE_PERIOD) return TRUE; return FALSE; } @@ -239,7 +239,7 @@ _thread_maintenance_period_elapsed(void) static void _thread_maintenance_update_time(void) { - scratch_buffers_time_of_last_maintenance = iv_now.tv_sec; + scratch_buffers_time_of_last_maintenance = get_cached_realtime_sec(); } void