Refactor database cleanups to take the same path for #close and ruby's garbage collection.

FossilOrigin-Name: a2a8d99136cfa9e98e75cc262b8f9aefa5ed576d7af804416b8c8c7f4d4f4bdb
This commit is contained in:
Mahlon E. Smith 2020-12-01 07:58:49 +00:00
parent 2b745bc756
commit 0093c49b91
2 changed files with 42 additions and 12 deletions

View file

@ -45,19 +45,36 @@ static const rb_data_type_t rmdbx_db_data = {
VALUE VALUE
rmdbx_alloc( VALUE klass ) rmdbx_alloc( VALUE klass )
{ {
int *data = malloc( sizeof(rmdbx_db_t) ); rmdbx_db_t *data;
return TypedData_Wrap_Struct( klass, &rmdbx_db_data, 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. * Cleanup a previously allocated DB environment.
* FIXME: ... this should also close if not already closed?
*/ */
void void
rmdbx_free( void *db ) rmdbx_free( void *db )
{ {
if ( db ) free( db ); if ( db ) {
rmdbx_destroy( db );
free( db );
}
} }
@ -68,14 +85,7 @@ VALUE
rmdbx_close( VALUE self ) rmdbx_close( VALUE self )
{ {
UNWRAP_DB( self, db ); UNWRAP_DB( self, db );
if ( db->cursor ) mdbx_cursor_close( db->cursor ); rmdbx_destroy( db );
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?
return Qtrue; return Qtrue;
} }

View file

@ -17,5 +17,25 @@ RSpec.describe( MDBX::Database ) do
expect( db.closed? ).to be_truthy expect( db.closed? ).to be_truthy
end 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 end