diff --git a/ext/mdbx_ext/database.c b/ext/mdbx_ext/database.c index 8506204..38e1c2a 100644 --- a/ext/mdbx_ext/database.c +++ b/ext/mdbx_ext/database.c @@ -45,19 +45,36 @@ static const rb_data_type_t rmdbx_db_data = { VALUE rmdbx_alloc( VALUE klass ) { - int *data = malloc( sizeof(rmdbx_db_t) ); - return TypedData_Wrap_Struct( klass, &rmdbx_db_data, data ); + rmdbx_db_t *data; + return TypedData_Make_Struct( klass, rmdbx_db_t, &rmdbx_db_data, data ); +} + + +/* + * Ensure all database file descriptors are collected and + * removed. + */ +void +rmdbx_destroy( rmdbx_db_t* db ) +{ + if ( db->cursor ) mdbx_cursor_close( db->cursor ); + if ( db->txn ) mdbx_txn_abort( db->txn ); + if ( db->dbi ) mdbx_dbi_close( db->env, db->dbi ); + if ( db->env ) mdbx_env_close( db->env ); + db->open = 0; } /* * Cleanup a previously allocated DB environment. - * FIXME: ... this should also close if not already closed? */ void rmdbx_free( void *db ) { - if ( db ) free( db ); + if ( db ) { + rmdbx_destroy( db ); + free( db ); + } } @@ -68,14 +85,7 @@ VALUE rmdbx_close( VALUE self ) { UNWRAP_DB( self, db ); - if ( db->cursor ) mdbx_cursor_close( db->cursor ); - if ( db->txn ) mdbx_txn_abort( db->txn ); - if ( db->dbi ) mdbx_dbi_close( db->env, db->dbi ); - if ( db->env ) mdbx_env_close( db->env ); - db->open = 0; - - // FIXME: or rather, maybe free() from here? - + rmdbx_destroy( db ); return Qtrue; } diff --git a/spec/mdbx/database_spec.rb b/spec/mdbx/database_spec.rb index d05d7ee..d636eb6 100644 --- a/spec/mdbx/database_spec.rb +++ b/spec/mdbx/database_spec.rb @@ -17,5 +17,25 @@ RSpec.describe( MDBX::Database ) do expect( db.closed? ).to be_truthy end + context 'an opened database' do + + before( :each ) do + @db = described_class.open( TEST_DATABASE.to_s ) + end + + after( :each ) do + @db.close + end + + it "fails if opened again within the same process" do + # This is a function of libmdbx internals, just testing + # here for behaviorals. + expect { + described_class.open( TEST_DATABASE.to_s ) + }. + to raise_exception( MDBX::DatabaseError, /environment is already used/ ) + end + + end end