]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Update rlm_sql_firebird to use trunk connections
authorNick Porter <nick@portercomputing.co.uk>
Mon, 14 Oct 2024 16:59:33 +0000 (17:59 +0100)
committerNick Porter <nick@portercomputing.co.uk>
Mon, 14 Oct 2024 17:17:43 +0000 (18:17 +0100)
src/modules/rlm_sql/drivers/rlm_sql_firebird/rlm_sql_firebird.c
src/modules/rlm_sql/drivers/rlm_sql_firebird/sql_fbapi.c
src/modules/rlm_sql/drivers/rlm_sql_firebird/sql_fbapi.h

index 6ddbf2947c6dcb2cc558b07915d1e038b518f78a..d73362e7c79632bd0ba6f4d5227f139292d42553 100644 (file)
@@ -24,110 +24,153 @@ RCSID("$Id$")
 
 #include "sql_fbapi.h"
 #include <freeradius-devel/util/debug.h>
+#include "rlm_sql_trunk.h"
 
-static int _sql_socket_destructor(rlm_sql_firebird_conn_t *conn)
+static char tpb[] = {isc_tpb_version3, isc_tpb_wait, isc_tpb_write,
+                    isc_tpb_read_committed, isc_tpb_no_rec_version};
+
+/** Establish connection to the db
+ *
+ */
+CC_NO_UBSAN(function) /* UBSAN: false positive - public vs private connection_t trips --fsanitize=function */
+static connection_state_t _sql_connection_init(void **h, connection_t *conn, void *uctx)
 {
-       DEBUG2("socket destructor called, closing socket");
+       rlm_sql_t const         *sql = talloc_get_type_abort_const(uctx, rlm_sql_t);
+       rlm_sql_firebird_conn_t *c;
 
-       fb_commit(conn);
-       if (conn->dbh) {
-               fb_free_statement(conn);
-               isc_detach_database(conn->status, &(conn->dbh));
+       MEM(c = talloc_zero(conn, rlm_sql_firebird_conn_t));
 
-               if (fb_error(conn)) WARN("Got error when closing socket: %s", conn->error);
-       }
+       /*
+        *      Firebird uses a client assigned structure to write info about output data.
+        *      Based on standard authorize queries, we pre-allocate a structure
+        *      for 5 columns in SELECT queries.
+        */
+       MEM(c->sqlda_out = (XSQLDA *)_talloc_array(conn, 1, XSQLDA_LENGTH(5), "XSQLDA"));
+       c->sqlda_out->sqln = 5;
+       c->sqlda_out->version =  SQLDA_VERSION1;
+       c->sql_dialect = 3;
 
-       talloc_free_children(conn);
+       /*
+        *      Set tpb to read_committed/wait/no_rec_version
+        */
+       c->tpb = tpb;
+       c->tpb_len = NUM_ELEMENTS(tpb);
 
-       return 0;
+       if (fb_connect(c, &sql->config)) {
+               ERROR("Connection failed: %s", c->error);
+               return CONNECTION_STATE_FAILED;
+       }
+
+       *h = c;
+       return CONNECTION_STATE_CONNECTED;
 }
 
-/** Establish connection to the db
- *
- */
-static sql_rcode_t sql_socket_init(rlm_sql_handle_t *handle, rlm_sql_config_t const *config,
-                                  UNUSED fr_time_delta_t timeout)
+static void _sql_connection_close(UNUSED fr_event_list_t *el, void *h, UNUSED void *uctx)
 {
-       rlm_sql_firebird_conn_t *conn;
-
-       long res;
+       rlm_sql_firebird_conn_t *c = talloc_get_type_abort(h, rlm_sql_firebird_conn_t);
 
-       MEM(conn = handle->conn = talloc_zero(handle, rlm_sql_firebird_conn_t));
-       talloc_set_destructor(conn, _sql_socket_destructor);
+       DEBUG2("Socket destructor called, closing socket");
 
-       res = fb_init_socket(conn);
-       if (res) return RLM_SQL_ERROR;
+       fb_commit(c);
+       if (c->dbh) {
+               fb_free_statement(c);
+               isc_detach_database(c->status, &(c->dbh));
 
-       if (fb_connect(conn, config)) {
-               ERROR("Connection failed: %s", conn->error);
-
-               return RLM_SQL_RECONNECT;
+               if (fb_error(c)) WARN("Got error when closing socket: %s", c->error);
        }
 
-       return 0;
+       talloc_free_children(c);
 }
 
-/** Issue a query to the database.
- *
- */
-static unlang_action_t sql_query(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
+SQL_TRUNK_CONNECTION_ALLOC
+
+CC_NO_UBSAN(function) /* UBSAN: false positive - public vs private connection_t trips --fsanitize=function */
+static void sql_trunk_request_mux(UNUSED fr_event_list_t *el, trunk_connection_t *tconn,
+                                 connection_t *conn, UNUSED void *uctx)
 {
-       fr_sql_query_t          *query_ctx = talloc_get_type_abort(uctx, fr_sql_query_t);
-       rlm_sql_firebird_conn_t *conn = query_ctx->handle->conn;
+       rlm_sql_firebird_conn_t *sql_conn = talloc_get_type_abort(conn->h, rlm_sql_firebird_conn_t);
+       trunk_request_t         *treq;
+       request_t               *request;
+       fr_sql_query_t          *query_ctx;
+       bool                    deadlock = false;
 
-       int deadlock = 0;
+       if (trunk_connection_pop_request(&treq, tconn) != 0) return;
+       if (!treq) return;
+
+       query_ctx = talloc_get_type_abort(treq->preq, fr_sql_query_t);
+       request = query_ctx->request;
+       query_ctx->tconn = tconn;
+
+       ROPTIONAL(RDEBUG2, DEBUG2, "Executing query: %s", query_ctx->query_str);
 
        try_again:
        /*
         *      Try again query when deadlock, because in any case it
         *      will be retried.
         */
-       if (fb_sql_query(conn, query_ctx->query_str)) {
+       if (fb_sql_query(sql_conn, query_ctx->query_str)) {
                /* but may be lost for short sessions */
-               if ((conn->sql_code == DEADLOCK_SQL_CODE) &&
-                   !deadlock) {
-                       DEBUG("conn_id deadlock. Retry query %s", query_ctx->query_str);
+               if ((sql_conn->sql_code == DEADLOCK_SQL_CODE) && !deadlock) {
+                       ROPTIONAL(RWARN, WARN, "SQL deadlock. Retry query %s", query_ctx->query_str);
 
                        /*
                         *      @todo For non READ_COMMITED transactions put
                         *      rollback here
                         *      fb_rollback(conn);
                         */
-                       deadlock = 1;
+                       deadlock = true;
                        goto try_again;
                }
 
-               ERROR("conn_id rlm_sql_firebird,sql_query error: sql_code=%li, error='%s', query=%s",
-                     (long int) conn->sql_code, conn->error, query_ctx->query_str);
 
-               if (conn->sql_code == DOWN_SQL_CODE) {
+               ROPTIONAL(RERROR, ERROR, "conn_id rlm_sql_firebird,sql_query error: sql_code=%li, error='%s', query=%s",
+                     (long int) sql_conn->sql_code, sql_conn->error, query_ctx->query_str);
+
+               query_ctx->status = SQL_QUERY_FAILED;
+               trunk_request_signal_fail(treq);
+
+               if (sql_conn->sql_code == DOWN_SQL_CODE) {
+               reconnect:
                        query_ctx->rcode = RLM_SQL_RECONNECT;
-                       RETURN_MODULE_FAIL;
+                       connection_signal_reconnect(conn, CONNECTION_FAILED);
+                       return;
                }
 
                /* Free problem query */
-               if (fb_rollback(conn)) {
+               if (fb_rollback(sql_conn)) {
                        //assume the network is down if rollback had failed
-                       ERROR("Fail to rollback transaction after previous error: %s", conn->error);
+                       ROPTIONAL(RERROR, ERROR, "Fail to rollback transaction after previous error: %s", sql_conn->error);
 
-                       query_ctx->rcode = RLM_SQL_RECONNECT;
-                       RETURN_MODULE_FAIL;
+                       goto reconnect;
                }
-               //   conn->in_use=0;
 
                query_ctx->rcode = RLM_SQL_ERROR;
-               RETURN_MODULE_FAIL;
-       }
-
-       if (conn->statement_type != isc_info_sql_stmt_select) {
-               if (fb_commit(conn)) {
-                       query_ctx->rcode = RLM_SQL_ERROR;
-                       RETURN_MODULE_FAIL;
-               }
+               return;
        }
 
        query_ctx->rcode = RLM_SQL_OK;
-       RETURN_MODULE_OK;
+       query_ctx->status = SQL_QUERY_RETURNED;
+       trunk_request_signal_reapable(treq);
+       if (request) unlang_interpret_mark_runnable(request);
+}
+
+SQL_QUERY_RESUME
+
+static void sql_request_complete(UNUSED request_t *request, void *preq, UNUSED void *rctx, UNUSED void *uctx)
+{
+       fr_sql_query_t          *query_ctx = talloc_get_type_abort(preq, fr_sql_query_t);
+       rlm_sql_firebird_conn_t *conn = talloc_get_type_abort(query_ctx->tconn->conn->h, rlm_sql_firebird_conn_t);
+
+       fb_commit(conn);
+}
+
+static void sql_request_fail(UNUSED request_t *request, void *preq, UNUSED void *rctx,
+                            UNUSED trunk_request_state_t state, UNUSED void *uctx)
+{
+       fr_sql_query_t          *query_ctx = talloc_get_type_abort(preq, fr_sql_query_t);
+
+       query_ctx->treq = NULL;
+       if (query_ctx->rcode == RLM_SQL_OK) query_ctx->rcode = RLM_SQL_ERROR;
 }
 
 /** Returns name of fields.
@@ -135,7 +178,7 @@ static unlang_action_t sql_query(rlm_rcode_t *p_result, UNUSED int *priority, UN
  */
 static sql_rcode_t sql_fields(char const **out[], fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
 {
-       rlm_sql_firebird_conn_t *conn = query_ctx->handle->conn;
+       rlm_sql_firebird_conn_t *conn = talloc_get_type_abort(query_ctx->tconn->conn->h, rlm_sql_firebird_conn_t);
 
        int             fields, i;
        char const      **names;
@@ -157,8 +200,7 @@ static sql_rcode_t sql_fields(char const **out[], fr_sql_query_t *query_ctx, UNU
 static unlang_action_t sql_fetch_row(rlm_rcode_t *p_result, UNUSED int *priority, UNUSED request_t *request, void *uctx)
 {
        fr_sql_query_t          *query_ctx = talloc_get_type_abort(uctx, fr_sql_query_t);
-       rlm_sql_handle_t        *handle = query_ctx->handle;
-       rlm_sql_firebird_conn_t *conn = handle->conn;
+       rlm_sql_firebird_conn_t *conn = talloc_get_type_abort(query_ctx->tconn->conn->h, rlm_sql_firebird_conn_t);
        int res;
 
        query_ctx->row = NULL;
@@ -186,29 +228,16 @@ static unlang_action_t sql_fetch_row(rlm_rcode_t *p_result, UNUSED int *priority
        RETURN_MODULE_OK;
 }
 
-/** End the select query, such as freeing memory or result.
- *
- */
-static sql_rcode_t sql_finish_select_query(fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
-{
-       rlm_sql_firebird_conn_t *conn = (rlm_sql_firebird_conn_t *) query_ctx->handle->conn;
-
-       fb_commit(conn);
-       fb_free_statement(conn);
-       talloc_free_children(conn->sqlda_out);
-
-       return 0;
-}
-
-/** End the query
+/** End the query, such as freeing memory or result.
  *
  */
-static sql_rcode_t sql_finish_query(UNUSED fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
+static sql_rcode_t sql_finish_query(fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
 {
-       rlm_sql_firebird_conn_t *conn = (rlm_sql_firebird_conn_t *) query_ctx->handle->conn;
+       rlm_sql_firebird_conn_t *conn = talloc_get_type_abort(query_ctx->tconn->conn->h, rlm_sql_firebird_conn_t);
 
        fb_free_statement(conn);
        talloc_free_children(conn->sqlda_out);
+       query_ctx->status = SQL_QUERY_PREPARED;
 
        return 0;
 }
@@ -235,7 +264,7 @@ static sql_rcode_t sql_free_result(UNUSED fr_sql_query_t *query_ctx, UNUSED rlm_
 static size_t sql_error(UNUSED TALLOC_CTX *ctx, sql_log_entry_t out[], NDEBUG_UNUSED size_t outlen,
                        fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
 {
-       rlm_sql_firebird_conn_t *conn = query_ctx->handle->conn;
+       rlm_sql_firebird_conn_t *conn = talloc_get_type_abort(query_ctx->tconn->conn->h, rlm_sql_firebird_conn_t);
 
        fr_assert(conn);
        fr_assert(outlen > 0);
@@ -253,7 +282,9 @@ static size_t sql_error(UNUSED TALLOC_CTX *ctx, sql_log_entry_t out[], NDEBUG_UN
  */
 static int sql_affected_rows(fr_sql_query_t *query_ctx, UNUSED rlm_sql_config_t const *config)
 {
-       return fb_affected_rows(query_ctx->handle->conn);
+       rlm_sql_firebird_conn_t *conn = talloc_get_type_abort(query_ctx->tconn->conn->h, rlm_sql_firebird_conn_t);
+
+       return fb_affected_rows(conn);
 }
 
 /* Exported to rlm_sql */
@@ -263,14 +294,20 @@ rlm_sql_driver_t rlm_sql_firebird = {
                .name                           = "sql_firebird",
                .magic                          = MODULE_MAGIC_INIT
        },
-       .sql_socket_init                = sql_socket_init,
-       .sql_query                      = sql_query,
-       .sql_select_query               = sql_query,
+       .sql_query_resume               = sql_query_resume,
+       .sql_select_query_resume        = sql_query_resume,
        .sql_affected_rows              = sql_affected_rows,
        .sql_fetch_row                  = sql_fetch_row,
        .sql_fields                     = sql_fields,
        .sql_free_result                = sql_free_result,
        .sql_error                      = sql_error,
        .sql_finish_query               = sql_finish_query,
-       .sql_finish_select_query        = sql_finish_select_query
+       .sql_finish_select_query        = sql_finish_query,
+       .uses_trunks                    = true,
+       .trunk_io_funcs = {
+               .connection_alloc       = sql_trunk_connection_alloc,
+               .request_mux            = sql_trunk_request_mux,
+               .request_complete       = sql_request_complete,
+               .request_fail           = sql_request_fail
+       }
 };
index 4a5f6baf4ff5184a15d7cff65bc04e943b3087b2..2b69981783082069e37567d8add46e7a3aea6648 100644 (file)
@@ -25,22 +25,6 @@ RCSID("$Id$")
 
 #include <stdarg.h>
 
-static void fb_set_tpb(rlm_sql_firebird_conn_t *conn, int count, ...)
-{
-       int i;
-       va_list arg;
-
-       va_start(arg, count);
-       MEM(conn->tpb = talloc_array(conn, char, count));
-
-       for (i = 0; i < count; i++) conn->tpb[i] = (char) va_arg(arg, int);
-
-       conn->tpb_len = count;
-
-       va_end(arg);
-}
-
-
 static void fb_dpb_add_str(char **dpb, char name, char const *value)
 {
        int l;
@@ -315,23 +299,6 @@ sql_rcode_t fb_store_row(rlm_sql_firebird_conn_t *conn)
        return RLM_SQL_OK;
 }
 
-int fb_init_socket(rlm_sql_firebird_conn_t *conn)
-{
-       MEM(conn->sqlda_out = (XSQLDA *)_talloc_array(conn, 1, XSQLDA_LENGTH(5), "XSQLDA"));
-       conn->sqlda_out->sqln = 5;
-       conn->sqlda_out->version =  SQLDA_VERSION1;
-       conn->sql_dialect = 3;
-
-       /*
-        *      Set tpb to read_committed/wait/no_rec_version
-        */
-       fb_set_tpb(conn, 5, isc_tpb_version3, isc_tpb_wait, isc_tpb_write,
-                  isc_tpb_read_committed, isc_tpb_no_rec_version);
-       if (!conn->tpb) return -1;
-
-       return 0;
-}
-
 int fb_connect(rlm_sql_firebird_conn_t *conn, rlm_sql_config_t const *config)
 {
        char            *p, *buff = NULL;
index c353d975b3f3e68b30d494e54e529129e4259872..8553b54bdf6f5106484f90792543fcd33cb27106 100644 (file)
@@ -67,7 +67,6 @@ typedef struct {
 
 int fb_free_result(rlm_sql_firebird_conn_t *conn);
 int fb_error(rlm_sql_firebird_conn_t *conn);
-int fb_init_socket(rlm_sql_firebird_conn_t *conn);
 int fb_connect(rlm_sql_firebird_conn_t *conn, rlm_sql_config_t const *config);
 int fb_disconnect(rlm_sql_firebird_conn_t *conn);
 int fb_sql_query(rlm_sql_firebird_conn_t *conn, char const *query);