From 48e21845706fd0e2e6300c2b8004b6b7781b684b Mon Sep 17 00:00:00 2001 From: mahlon Date: Wed, 30 Apr 2025 23:51:45 +0000 Subject: [PATCH] Checkpoint work trying to make transactions thread safe. FossilOrigin-Name: 3d7c96d03c58839bc6402ca0c69f8405edbdfde24c2cefdf8caa2bfdc8136625 --- ext/mdbx_ext/database.c | 38 +++++++++++++++++++++++++++++++++++++- ext/mdbx_ext/mdbx_ext.h | 1 + 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/ext/mdbx_ext/database.c b/ext/mdbx_ext/database.c index 9d6fe7a..63a8707 100644 --- a/ext/mdbx_ext/database.c +++ b/ext/mdbx_ext/database.c @@ -465,6 +465,32 @@ rmdbx_in_transaction_p( VALUE self ) } +struct txn_open_args_s { + rmdbx_db_t *db; + int rwflag; +}; + + +/* Opens a transaction outside of th GVL. */ +void * +rmdbx_open_txn_without_gvl( void *ptr ) +{ + // struct query_call *qcall = (struct query_call *)ptr; + struct txn_open_args_s *txn_open_args = (struct txn_open_args_s *)ptr; + + rmdbx_db_t *db = txn_open_args->db; + + int rc = mdbx_txn_begin( + db->env, + NULL, + txn_open_args->rwflag, + &db->txn + ); + + return (void *)rc; +} + + /* * Open a new database transaction. If a transaction is already * open, this is a no-op. @@ -476,7 +502,17 @@ rmdbx_open_txn( rmdbx_db_t *db, int rwflag ) { if ( db->txn ) return; - int rc = mdbx_txn_begin( db->env, NULL, rwflag, &db->txn ); + struct txn_open_args_s txn_open_args; + txn_open_args.db = db; + txn_open_args.rwflag = rwflag; + + void *result_ptr = rb_thread_call_without_gvl( + rmdbx_open_txn_without_gvl, (void *)&txn_open_args, + NULL, NULL + ); + + int rc = (int)result_ptr; + if ( rc != MDBX_SUCCESS ) { rmdbx_close_all( db ); rb_raise( rmdbx_eDatabaseError, "mdbx_txn_begin: (%d) %s", rc, mdbx_strerror(rc) ); diff --git a/ext/mdbx_ext/mdbx_ext.h b/ext/mdbx_ext/mdbx_ext.h index 872e245..99376f7 100644 --- a/ext/mdbx_ext/mdbx_ext.h +++ b/ext/mdbx_ext/mdbx_ext.h @@ -3,6 +3,7 @@ #include "extconf.h" #include "mdbx.h" +#include "ruby/thread.h" #ifndef RBMDBX_EXT #define RBMDBX_EXT