[PATCH (3.4)] afsql: Add support for specifying custom SQL backend options.
When one is using an SQL backend that supports a set of options that syslog-ng does not set itself, yet, one does want these options set, there was previously no way to accomplish that without changing the source. This patch adds a new option: dbd-option(OPTION_NAME VALUE) (where OPTION_NAME is always a string, and value can be either a string, or a number). The options specified this way will always be set with libdbi whenever we (re)connect to the database. A simple use-case: destination d_slow_sql_test { sql(type("null") dbd-option("null.sleep.connect" 1) dbd-option("null.sleep.query" 5) columns("dummy") values("1") ); }; Signed-off-by: Gergely Nagy <algernon@balabit.hu> --- modules/afsql/afsql-grammar.ym | 3 +++ modules/afsql/afsql-parser.c | 2 ++ modules/afsql/afsql.c | 40 ++++++++++++++++++++++++++++++++++++++++ modules/afsql/afsql.h | 4 ++++ 4 files changed, 49 insertions(+), 0 deletions(-) diff --git a/modules/afsql/afsql-grammar.ym b/modules/afsql/afsql-grammar.ym index 580fb80..d21a3bf 100644 --- a/modules/afsql/afsql-grammar.ym +++ b/modules/afsql/afsql-grammar.ym @@ -54,6 +54,7 @@ extern LogDriver *last_driver; %token KW_DEFAULT %token KW_RETRIES +%token KW_DBD_OPTION %type <ptr> dest_afsql %type <ptr> dest_afsql_params @@ -100,6 +101,8 @@ dest_afsql_option free($3); } | KW_USERNAME '(' string ')' { afsql_dd_set_user(last_driver, $3); free($3); } + | KW_DBD_OPTION '(' string LL_NUMBER ')' { afsql_dd_add_dbd_option_numeric(last_driver, $3, $4); free($3); } + | KW_DBD_OPTION '(' string string ')' { afsql_dd_add_dbd_option(last_driver, $3, $4); free($3); free($4); } | KW_PASSWORD '(' string ')' { afsql_dd_set_password(last_driver, $3); free($3); } | KW_DATABASE '(' string ')' { afsql_dd_set_database(last_driver, $3); free($3); } | KW_TABLE '(' string ')' { afsql_dd_set_table(last_driver, $3); free($3); } diff --git a/modules/afsql/afsql-parser.c b/modules/afsql/afsql-parser.c index 877389a..291e495 100644 --- a/modules/afsql/afsql-parser.c +++ b/modules/afsql/afsql-parser.c @@ -55,6 +55,8 @@ static CfgLexerKeyword afsql_keywords[] = { { "flush_lines", KW_FLUSH_LINES }, { "flush_timeout", KW_FLUSH_TIMEOUT }, { "flags", KW_FLAGS }, + + { "dbd_option", KW_DBD_OPTION }, { NULL } }; diff --git a/modules/afsql/afsql.c b/modules/afsql/afsql.c index b3fec86..a327cdd 100644 --- a/modules/afsql/afsql.c +++ b/modules/afsql/afsql.c @@ -103,6 +103,9 @@ typedef struct _AFSqlDestDriver StatsCounterItem *dropped_messages; StatsCounterItem *stored_messages; + GHashTable *dbd_options; + GHashTable *dbd_options_numeric; + /* shared by the main/db thread */ GThread *db_thread; GMutex *db_thread_mutex; @@ -127,6 +130,22 @@ static const char *s_freetds = "freetds"; #define MAX_FAILED_ATTEMPTS 3 void +afsql_dd_add_dbd_option(LogDriver *s, const gchar *name, const gchar *value) +{ + AFSqlDestDriver *self = (AFSqlDestDriver *) s; + + g_hash_table_insert(self->dbd_options, g_strdup(name), g_strdup(value)); +} + +void +afsql_dd_add_dbd_option_numeric(LogDriver *s, const gchar *name, gint value) +{ + AFSqlDestDriver *self = (AFSqlDestDriver *) s; + + g_hash_table_insert(self->dbd_options_numeric, g_strdup(name), GINT_TO_POINTER(value)); +} + +void afsql_dd_set_type(LogDriver *s, const gchar *type) { AFSqlDestDriver *self = (AFSqlDestDriver *) s; @@ -608,6 +627,19 @@ afsql_dd_disconnect(AFSqlDestDriver *self) g_hash_table_remove_all(self->validated_tables); } +static void +afsql_dd_set_dbd_opt(gpointer key, gpointer value, gpointer user_data) +{ + dbi_conn_set_option((dbi_conn)user_data, (gchar *)key, (gchar *)value); +} + +static void +afsql_dd_set_dbd_opt_numeric(gpointer key, gpointer value, gpointer user_data) +{ + dbi_conn_set_option_numeric((dbi_conn)user_data, (gchar *)key, + GPOINTER_TO_INT(value)); +} + /** * afsql_dd_insert_db: * @@ -645,6 +677,10 @@ afsql_dd_insert_db(AFSqlDestDriver *self) dbi_conn_set_option(self->dbi_ctx, "sqlite_dbdir", ""); dbi_conn_set_option(self->dbi_ctx, "sqlite3_dbdir", ""); + /* Set user-specified options */ + g_hash_table_foreach(self->dbd_options, afsql_dd_set_dbd_opt, self->dbi_ctx); + g_hash_table_foreach(self->dbd_options_numeric, afsql_dd_set_dbd_opt_numeric, self->dbi_ctx); + if (dbi_conn_connect(self->dbi_ctx) < 0) { const gchar *dbi_error; @@ -1200,6 +1236,8 @@ afsql_dd_free(LogPipe *s) string_list_free(self->values); log_template_unref(self->table); g_hash_table_destroy(self->validated_tables); + g_hash_table_destroy(self->dbd_options); + g_hash_table_destroy(self->dbd_options_numeric); if(self->session_statements) string_list_free(self->session_statements); log_dest_driver_free(s); @@ -1235,6 +1273,8 @@ afsql_dd_new(void) self->num_retries = MAX_FAILED_ATTEMPTS; self->validated_tables = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); + self->dbd_options = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + self->dbd_options_numeric = g_hash_table_new_full(g_str_hash, g_int_equal, g_free, NULL); log_template_options_defaults(&self->template_options); init_sequence_number(&self->seq_num); diff --git a/modules/afsql/afsql.h b/modules/afsql/afsql.h index ee2ae68..ce2e18a 100644 --- a/modules/afsql/afsql.h +++ b/modules/afsql/afsql.h @@ -56,6 +56,8 @@ void afsql_dd_set_flags(LogDriver *s, gint flags); LogDriver *afsql_dd_new(); gint afsql_dd_lookup_flag(const gchar *flag); void afsql_dd_set_retries(LogDriver *s, gint num_retries); +void afsql_dd_add_dbd_option(LogDriver *s, const gchar *name, const gchar *value); +void afsql_dd_add_dbd_option_numeric(LogDriver *s, const gchar *name, gint value); #else @@ -69,6 +71,8 @@ void afsql_dd_set_retries(LogDriver *s, gint num_retries); #define afsql_dd_set_columns(s, c) #define afsql_dd_set_values(s, v) #define afsql_dd_set_null_value(s, v) +#define afsql_dd_add_dbd_option(s, n, v) +#define afsql_dd_add_dbd_option_numeric(s, n, v) #define afsql_dd_new() 0 -- 1.7.7.3
On Wed, 2011-12-07 at 12:11 +0100, Gergely Nagy wrote:
When one is using an SQL backend that supports a set of options that syslog-ng does not set itself, yet, one does want these options set, there was previously no way to accomplish that without changing the source.
This patch adds a new option: dbd-option(OPTION_NAME VALUE) (where OPTION_NAME is always a string, and value can be either a string, or a number). The options specified this way will always be set with libdbi whenever we (re)connect to the database.
A simple use-case:
destination d_slow_sql_test { sql(type("null") dbd-option("null.sleep.connect" 1) dbd-option("null.sleep.query" 5) columns("dummy") values("1") ); };
Signed-off-by: Gergely Nagy <algernon@balabit.hu> --- modules/afsql/afsql-grammar.ym | 3 +++ modules/afsql/afsql-parser.c | 2 ++ modules/afsql/afsql.c | 40 ++++++++++++++++++++++++++++++++++++++++ modules/afsql/afsql.h | 4 ++++ 4 files changed, 49 insertions(+), 0 deletions(-)
I would apply this, however the set of dbd-options really depends on the libdbi driver in question. And if once-upon-a-time I'd leave libdbi behind and use something else, these would not work. So I would put a big-fat warning that the meaning of these options can be changed at any time. -- Bazsi
Balazs Scheidler <bazsi@balabit.hu> writes:
On Wed, 2011-12-07 at 12:11 +0100, Gergely Nagy wrote:
When one is using an SQL backend that supports a set of options that syslog-ng does not set itself, yet, one does want these options set, there was previously no way to accomplish that without changing the source.
This patch adds a new option: dbd-option(OPTION_NAME VALUE) (where OPTION_NAME is always a string, and value can be either a string, or a number). The options specified this way will always be set with libdbi whenever we (re)connect to the database.
A simple use-case:
destination d_slow_sql_test { sql(type("null") dbd-option("null.sleep.connect" 1) dbd-option("null.sleep.query" 5) columns("dummy") values("1") ); };
Signed-off-by: Gergely Nagy <algernon@balabit.hu> --- modules/afsql/afsql-grammar.ym | 3 +++ modules/afsql/afsql-parser.c | 2 ++ modules/afsql/afsql.c | 40 ++++++++++++++++++++++++++++++++++++++++ modules/afsql/afsql.h | 4 ++++ 4 files changed, 49 insertions(+), 0 deletions(-)
I would apply this, however the set of dbd-options really depends on the libdbi driver in question. And if once-upon-a-time I'd leave libdbi behind and use something else, these would not work.
So I would put a big-fat warning that the meaning of these options can be changed at any time.
I can prepare a patch that would do two things: rename the option from dbd-option to libdbi-option, to make it clear that it's libdbi-specific. And only enable these when a certain flag is set in the destination. So we'd have something like this: destination d_slow_sql_tet { sql(type("null") flags(libdbi-direct-options) libdbi-option("null.sleep.query" 5) columns("dummy") values("1") ); }; Without the flag, libdbi-option would emit a warning and ignore the setting. Would this be acceptable? The reason behind the rename, is that if you ever change away from libdbi, nothing guarantees that the replacement will support setting custom options, so dbd-option would be pointless there. -- |8]
On Wed, 2011-12-21 at 14:52 +0100, Gergely Nagy wrote:
Balazs Scheidler <bazsi@balabit.hu> writes:
On Wed, 2011-12-07 at 12:11 +0100, Gergely Nagy wrote:
When one is using an SQL backend that supports a set of options that syslog-ng does not set itself, yet, one does want these options set, there was previously no way to accomplish that without changing the source.
This patch adds a new option: dbd-option(OPTION_NAME VALUE) (where OPTION_NAME is always a string, and value can be either a string, or a number). The options specified this way will always be set with libdbi whenever we (re)connect to the database.
A simple use-case:
destination d_slow_sql_test { sql(type("null") dbd-option("null.sleep.connect" 1) dbd-option("null.sleep.query" 5) columns("dummy") values("1") ); };
Signed-off-by: Gergely Nagy <algernon@balabit.hu> --- modules/afsql/afsql-grammar.ym | 3 +++ modules/afsql/afsql-parser.c | 2 ++ modules/afsql/afsql.c | 40 ++++++++++++++++++++++++++++++++++++++++ modules/afsql/afsql.h | 4 ++++ 4 files changed, 49 insertions(+), 0 deletions(-)
I would apply this, however the set of dbd-options really depends on the libdbi driver in question. And if once-upon-a-time I'd leave libdbi behind and use something else, these would not work.
So I would put a big-fat warning that the meaning of these options can be changed at any time.
I can prepare a patch that would do two things: rename the option from dbd-option to libdbi-option, to make it clear that it's libdbi-specific. And only enable these when a certain flag is set in the destination.
So we'd have something like this:
destination d_slow_sql_tet { sql(type("null") flags(libdbi-direct-options) libdbi-option("null.sleep.query" 5) columns("dummy") values("1") ); };
Without the flag, libdbi-option would emit a warning and ignore the setting.
Would this be acceptable?
The reason behind the rename, is that if you ever change away from libdbi, nothing guarantees that the replacement will support setting custom options, so dbd-option would be pointless there.
I've applied the original patch, and I wouldn't play tricks with flags like this. The now think that it is possible to emit that warning once the SQL backend library changes, and possibly point out this future problem in the documentation. -- Bazsi
On Wed, 2011-12-07 at 12:11 +0100, Gergely Nagy wrote:
When one is using an SQL backend that supports a set of options that syslog-ng does not set itself, yet, one does want these options set, there was previously no way to accomplish that without changing the source.
This patch adds a new option: dbd-option(OPTION_NAME VALUE) (where OPTION_NAME is always a string, and value can be either a string, or a number). The options specified this way will always be set with libdbi whenever we (re)connect to the database.
A simple use-case:
destination d_slow_sql_test { sql(type("null") dbd-option("null.sleep.connect" 1) dbd-option("null.sleep.query" 5) columns("dummy") values("1") ); };
Signed-off-by: Gergely Nagy <algernon@balabit.hu>
Applied. -- Bazsi
participants (2)
-
Balazs Scheidler
-
Gergely Nagy