From 96cad95e0f7ee0a639ab8ec4ff16be5b7b568083 Mon Sep 17 00:00:00 2001 From: "mahlon@martini.nu" Date: Fri, 19 Mar 2021 01:15:04 +0000 Subject: [PATCH] Support dup/clone. FossilOrigin-Name: 3e6c6b9213ebbe1d6b5e19e5e2886749b0df46a564f716469be0664ac4602902 --- ext/mdbx_ext/database.c | 29 +++++++++++++++++++++++++++++ spec/mdbx/database_spec.rb | 16 ++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/ext/mdbx_ext/database.c b/ext/mdbx_ext/database.c index f5a8733..35753c7 100644 --- a/ext/mdbx_ext/database.c +++ b/ext/mdbx_ext/database.c @@ -717,6 +717,34 @@ rmdbx_database_initialize( int argc, VALUE *argv, VALUE self ) } +/* + * call-seq: + * db.clone => [copy of db] + * + * Copy the object (clone/dup). The returned copy is closed and needs + * to be reopened before use. This function likely has limited use, + * considering you can't open two handles within the same process. + */ +static VALUE rmdbx_init_copy( VALUE copy, VALUE orig ) +{ + rmdbx_db_t *orig_db; + rmdbx_db_t *copy_db; + + if ( copy == orig ) return copy; + + TypedData_Get_Struct( orig, rmdbx_db_t, &rmdbx_db_data, orig_db ); + TypedData_Get_Struct( copy, rmdbx_db_t, &rmdbx_db_data, copy_db ); + + /* Copy all fields from the original to the copy, and force-close + the copy. + */ + MEMCPY( copy_db, orig_db, rmdbx_db_t, 1 ); + rmdbx_close_all( copy_db ); + + return copy; +} + + /* * Initialization for the MDBX::Database class. */ @@ -732,6 +760,7 @@ rmdbx_init_database() rb_define_alloc_func( rmdbx_cDatabase, rmdbx_alloc ); rb_define_protected_method( rmdbx_cDatabase, "initialize", rmdbx_database_initialize, -1 ); + rb_define_protected_method( rmdbx_cDatabase, "initialize_copy", rmdbx_init_copy, 1 ); rb_define_method( rmdbx_cDatabase, "collection", rmdbx_set_subdb, -1 ); rb_define_method( rmdbx_cDatabase, "close", rmdbx_close, 0 ); rb_define_method( rmdbx_cDatabase, "reopen", rmdbx_open_env, 0 ); diff --git a/spec/mdbx/database_spec.rb b/spec/mdbx/database_spec.rb index 8fb6783..0b62512 100644 --- a/spec/mdbx/database_spec.rb +++ b/spec/mdbx/database_spec.rb @@ -31,6 +31,22 @@ RSpec.describe( MDBX::Database ) do expect( db.closed? ).to be_truthy end + it "can create a closed clone" do + db = described_class.open( TEST_DATABASE.to_s ) + db[1] = "doopydoo" + + clone = db.clone + + expect( db.closed? ).to be_falsey + expect( clone.closed? ).to be_truthy + expect( db.path ).to eq( clone.path ) + db.close + + clone.reopen + expect( clone[1] ).to eq( "doopydoo" ) + clone.close + end + context 'an opened database' do