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