mdbx 0.1.0.pre.20201217111933 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/History.md +5 -1
- data/README.md +305 -35
- data/ext/mdbx_ext/database.c +383 -138
- data/ext/mdbx_ext/mdbx_ext.c +8 -2
- data/ext/mdbx_ext/mdbx_ext.h +41 -3
- data/ext/mdbx_ext/stats.c +191 -0
- data/lib/mdbx.rb +1 -5
- data/lib/mdbx/database.rb +274 -9
- metadata +44 -29
- metadata.gz.sig +0 -0
- data/lib/mdbx_ext.so +0 -0
data/ext/mdbx_ext/mdbx_ext.c
CHANGED
@@ -14,12 +14,18 @@ Init_mdbx_ext()
|
|
14
14
|
{
|
15
15
|
rmdbx_mMDBX = rb_define_module( "MDBX" );
|
16
16
|
|
17
|
-
/* The backend library version. */
|
18
17
|
VALUE version = rb_str_new_cstr( mdbx_version.git.describe );
|
18
|
+
/* The backend MDBX library version. */
|
19
19
|
rb_define_const( rmdbx_mMDBX, "LIBRARY_VERSION", version );
|
20
20
|
|
21
|
+
/* A generic exception class for internal Database errors. */
|
21
22
|
rmdbx_eDatabaseError = rb_define_class_under( rmdbx_mMDBX, "DatabaseError", rb_eRuntimeError );
|
22
|
-
|
23
|
+
|
24
|
+
/*
|
25
|
+
* Raising an MDBX::Rollback exception from within a transaction
|
26
|
+
* discards all changes and closes the transaction.
|
27
|
+
*/
|
28
|
+
rmdbx_eRollback = rb_define_class_under( rmdbx_mMDBX, "Rollback", rb_eRuntimeError );
|
23
29
|
|
24
30
|
rmdbx_init_database();
|
25
31
|
}
|
data/ext/mdbx_ext/mdbx_ext.h
CHANGED
@@ -4,9 +4,43 @@
|
|
4
4
|
|
5
5
|
#include "mdbx.h"
|
6
6
|
|
7
|
-
#ifndef
|
8
|
-
#define
|
7
|
+
#ifndef MDBX_EXT_0_9_3
|
8
|
+
#define MDBX_EXT_0_9_3
|
9
9
|
|
10
|
+
#define RMDBX_TXN_ROLLBACK 0
|
11
|
+
#define RMDBX_TXN_COMMIT 1
|
12
|
+
|
13
|
+
/*
|
14
|
+
* A struct encapsulating an instance's DB
|
15
|
+
* state and settings.
|
16
|
+
*/
|
17
|
+
struct rmdbx_db {
|
18
|
+
MDBX_env *env;
|
19
|
+
MDBX_dbi dbi;
|
20
|
+
MDBX_txn *txn;
|
21
|
+
MDBX_cursor *cursor;
|
22
|
+
|
23
|
+
struct {
|
24
|
+
int env_flags;
|
25
|
+
int mode;
|
26
|
+
int open;
|
27
|
+
int max_collections;
|
28
|
+
int max_readers;
|
29
|
+
uint64_t max_size;
|
30
|
+
} settings;
|
31
|
+
|
32
|
+
struct {
|
33
|
+
int open;
|
34
|
+
int retain_txn;
|
35
|
+
} state;
|
36
|
+
|
37
|
+
char *path;
|
38
|
+
char *subdb;
|
39
|
+
};
|
40
|
+
typedef struct rmdbx_db rmdbx_db_t;
|
41
|
+
|
42
|
+
static const rb_data_type_t rmdbx_db_data;
|
43
|
+
extern void rmdbx_free( void *db ); /* forward declaration for the allocator */
|
10
44
|
|
11
45
|
/* ------------------------------------------------------------
|
12
46
|
* Globals
|
@@ -23,7 +57,11 @@ extern VALUE rmdbx_eRollback;
|
|
23
57
|
* ------------------------------------------------------------ */
|
24
58
|
extern void Init_rmdbx ( void );
|
25
59
|
extern void rmdbx_init_database ( void );
|
60
|
+
extern void rmdbx_open_txn( rmdbx_db_t*, int );
|
61
|
+
extern void rmdbx_close_txn( rmdbx_db_t*, int );
|
62
|
+
|
63
|
+
extern VALUE rmdbx_gather_stats( rmdbx_db_t* );
|
26
64
|
|
27
65
|
|
28
|
-
#endif /* define
|
66
|
+
#endif /* define MDBX_EXT_0_9_3 */
|
29
67
|
|
@@ -0,0 +1,191 @@
|
|
1
|
+
/* vim: set noet sta sw=4 ts=4 :
|
2
|
+
*
|
3
|
+
* Expose a bunch of mdbx internals to ruby.
|
4
|
+
* This is all largely stolen from mdbx_stat.c.
|
5
|
+
*
|
6
|
+
* Entry point is rmdbx_stats() in database.c.
|
7
|
+
*
|
8
|
+
*/
|
9
|
+
|
10
|
+
#include "mdbx_ext.h"
|
11
|
+
|
12
|
+
|
13
|
+
/*
|
14
|
+
* Metadata specific to the mdbx build.
|
15
|
+
*/
|
16
|
+
void
|
17
|
+
rmdbx_gather_build_stats( VALUE stat )
|
18
|
+
{
|
19
|
+
rb_hash_aset( stat, ID2SYM(rb_intern("build_compiler")),
|
20
|
+
rb_str_new_cstr(mdbx_build.compiler) );
|
21
|
+
rb_hash_aset( stat, ID2SYM(rb_intern("build_flags")),
|
22
|
+
rb_str_new_cstr(mdbx_build.flags) );
|
23
|
+
rb_hash_aset( stat, ID2SYM(rb_intern("build_options")),
|
24
|
+
rb_str_new_cstr(mdbx_build.options) );
|
25
|
+
rb_hash_aset( stat, ID2SYM(rb_intern("build_target")),
|
26
|
+
rb_str_new_cstr(mdbx_build.target) );
|
27
|
+
return;
|
28
|
+
}
|
29
|
+
|
30
|
+
|
31
|
+
/*
|
32
|
+
* Metadata for the database file.
|
33
|
+
*/
|
34
|
+
void
|
35
|
+
rmdbx_gather_datafile_stats(
|
36
|
+
VALUE environ,
|
37
|
+
MDBX_stat mstat,
|
38
|
+
MDBX_envinfo menvinfo )
|
39
|
+
{
|
40
|
+
VALUE datafile = rb_hash_new();
|
41
|
+
rb_hash_aset( environ, ID2SYM(rb_intern("datafile")), datafile );
|
42
|
+
|
43
|
+
rb_hash_aset( datafile, ID2SYM(rb_intern("size_current")),
|
44
|
+
INT2NUM(menvinfo.mi_geo.current) );
|
45
|
+
rb_hash_aset( datafile, ID2SYM(rb_intern("pages")),
|
46
|
+
INT2NUM(menvinfo.mi_geo.current / mstat.ms_psize) );
|
47
|
+
|
48
|
+
if ( menvinfo.mi_geo.lower != menvinfo.mi_geo.upper ) {
|
49
|
+
rb_hash_aset( datafile, ID2SYM(rb_intern("type")),
|
50
|
+
rb_str_new_cstr("dynamic") );
|
51
|
+
rb_hash_aset( datafile, ID2SYM(rb_intern("size_lower")),
|
52
|
+
INT2NUM( menvinfo.mi_geo.lower ) );
|
53
|
+
rb_hash_aset( datafile, ID2SYM(rb_intern("size_upper")),
|
54
|
+
LONG2FIX( menvinfo.mi_geo.upper ) );
|
55
|
+
rb_hash_aset( datafile, ID2SYM(rb_intern("growth_step")),
|
56
|
+
INT2NUM( menvinfo.mi_geo.grow ) );
|
57
|
+
rb_hash_aset( datafile, ID2SYM(rb_intern("shrink_threshold")),
|
58
|
+
INT2NUM( menvinfo.mi_geo.shrink ) );
|
59
|
+
}
|
60
|
+
else {
|
61
|
+
rb_hash_aset( datafile, ID2SYM(rb_intern("type")),
|
62
|
+
rb_str_new_cstr("fixed") );
|
63
|
+
}
|
64
|
+
|
65
|
+
return;
|
66
|
+
}
|
67
|
+
|
68
|
+
|
69
|
+
/*
|
70
|
+
* Metadata for the database environment.
|
71
|
+
*/
|
72
|
+
void
|
73
|
+
rmdbx_gather_environment_stats(
|
74
|
+
VALUE stat,
|
75
|
+
MDBX_stat mstat,
|
76
|
+
MDBX_envinfo menvinfo )
|
77
|
+
{
|
78
|
+
VALUE environ = rb_hash_new();
|
79
|
+
rb_hash_aset( stat, ID2SYM(rb_intern("environment")), environ );
|
80
|
+
|
81
|
+
rb_hash_aset( environ, ID2SYM(rb_intern("pagesize")),
|
82
|
+
INT2NUM(mstat.ms_psize) );
|
83
|
+
rb_hash_aset( environ, ID2SYM(rb_intern("last_txnid")),
|
84
|
+
INT2NUM(menvinfo.mi_recent_txnid) );
|
85
|
+
rb_hash_aset( environ, ID2SYM(rb_intern("last_reader_txnid")),
|
86
|
+
INT2NUM(menvinfo.mi_latter_reader_txnid) );
|
87
|
+
rb_hash_aset( environ, ID2SYM(rb_intern("max_readers")),
|
88
|
+
INT2NUM(menvinfo.mi_maxreaders) );
|
89
|
+
rb_hash_aset( environ, ID2SYM(rb_intern("readers_in_use")),
|
90
|
+
INT2NUM(menvinfo.mi_numreaders) );
|
91
|
+
|
92
|
+
rmdbx_gather_datafile_stats( environ, mstat, menvinfo );
|
93
|
+
|
94
|
+
return;
|
95
|
+
}
|
96
|
+
|
97
|
+
|
98
|
+
/*
|
99
|
+
* Callback iterator for pulling each reader's current state.
|
100
|
+
* See: https://erthink.github.io/libmdbx/group__c__statinfo.html#gad1ab5cf54d4a9f7d4c2999078920e8b0
|
101
|
+
*
|
102
|
+
*/
|
103
|
+
int
|
104
|
+
reader_list_callback(
|
105
|
+
void *ctx,
|
106
|
+
int num,
|
107
|
+
int slot,
|
108
|
+
mdbx_pid_t pid,
|
109
|
+
mdbx_tid_t thread,
|
110
|
+
uint64_t txnid,
|
111
|
+
uint64_t lag,
|
112
|
+
size_t bytes_used,
|
113
|
+
size_t bytes_retired )
|
114
|
+
{
|
115
|
+
VALUE reader = rb_hash_new();
|
116
|
+
|
117
|
+
rb_hash_aset( reader, ID2SYM(rb_intern("slot")),
|
118
|
+
INT2NUM( slot ) );
|
119
|
+
rb_hash_aset( reader, ID2SYM(rb_intern("pid")),
|
120
|
+
LONG2FIX( pid ) );
|
121
|
+
rb_hash_aset( reader, ID2SYM(rb_intern("thread")),
|
122
|
+
LONG2FIX( thread ) );
|
123
|
+
rb_hash_aset( reader, ID2SYM(rb_intern("txnid")),
|
124
|
+
LONG2FIX( txnid ) );
|
125
|
+
rb_hash_aset( reader, ID2SYM(rb_intern("lag")),
|
126
|
+
LONG2FIX( lag ) );
|
127
|
+
rb_hash_aset( reader, ID2SYM(rb_intern("bytes_used")),
|
128
|
+
LONG2FIX( bytes_used ) );
|
129
|
+
rb_hash_aset( reader, ID2SYM(rb_intern("bytes_retired")),
|
130
|
+
LONG2FIX( bytes_retired ) );
|
131
|
+
|
132
|
+
rb_ary_push( (VALUE)ctx, reader );
|
133
|
+
|
134
|
+
return 0;
|
135
|
+
}
|
136
|
+
|
137
|
+
|
138
|
+
/*
|
139
|
+
* Metadata for current reader slots.
|
140
|
+
* Initialize an array and populate it with each reader's statistics.
|
141
|
+
*/
|
142
|
+
void
|
143
|
+
rmdbx_gather_reader_stats(
|
144
|
+
rmdbx_db_t *db,
|
145
|
+
VALUE stat,
|
146
|
+
MDBX_stat mstat,
|
147
|
+
MDBX_envinfo menvinfo )
|
148
|
+
{
|
149
|
+
VALUE readers = rb_ary_new();
|
150
|
+
|
151
|
+
mdbx_reader_list( db->env, reader_list_callback, (void*)readers );
|
152
|
+
rb_hash_aset( stat, ID2SYM(rb_intern("readers")), readers );
|
153
|
+
|
154
|
+
return;
|
155
|
+
}
|
156
|
+
|
157
|
+
|
158
|
+
/*
|
159
|
+
* Build and return a hash of various statistic/metadata
|
160
|
+
* for the open +db+ handle.
|
161
|
+
*/
|
162
|
+
VALUE
|
163
|
+
rmdbx_gather_stats( rmdbx_db_t *db )
|
164
|
+
{
|
165
|
+
VALUE stat = rb_hash_new();
|
166
|
+
|
167
|
+
int rc;
|
168
|
+
MDBX_stat mstat;
|
169
|
+
MDBX_envinfo menvinfo;
|
170
|
+
|
171
|
+
rmdbx_gather_build_stats( stat );
|
172
|
+
|
173
|
+
rmdbx_open_txn( db, MDBX_TXN_RDONLY );
|
174
|
+
rc = mdbx_env_info_ex( db->env, db->txn, &menvinfo, sizeof(menvinfo) );
|
175
|
+
if ( rc != MDBX_SUCCESS )
|
176
|
+
rb_raise( rmdbx_eDatabaseError, "mdbx_env_info_ex: (%d) %s", rc, mdbx_strerror(rc) );
|
177
|
+
|
178
|
+
rc = mdbx_env_stat_ex( db->env, db->txn, &mstat, sizeof(mstat) );
|
179
|
+
if ( rc != MDBX_SUCCESS )
|
180
|
+
rb_raise( rmdbx_eDatabaseError, "mdbx_env_stat_ex: (%d) %s", rc, mdbx_strerror(rc) );
|
181
|
+
rmdbx_close_txn( db, RMDBX_TXN_ROLLBACK );
|
182
|
+
|
183
|
+
rmdbx_gather_environment_stats( stat, mstat, menvinfo );
|
184
|
+
rmdbx_gather_reader_stats( db, stat, mstat, menvinfo );
|
185
|
+
|
186
|
+
/* TODO: database and subdatabase stats */
|
187
|
+
|
188
|
+
return stat;
|
189
|
+
}
|
190
|
+
|
191
|
+
|
data/lib/mdbx.rb
CHANGED
@@ -10,11 +10,7 @@ require 'mdbx_ext'
|
|
10
10
|
module MDBX
|
11
11
|
|
12
12
|
# The version of this gem.
|
13
|
-
|
14
|
-
# Note: the MDBX library version this gem was built
|
15
|
-
# against can be found in the 'LIBRARY_VERSION' constant.
|
16
|
-
#
|
17
|
-
VERSION = '0.0.1'
|
13
|
+
VERSION = '0.1.0'
|
18
14
|
|
19
15
|
end # module MDBX
|
20
16
|
|
data/lib/mdbx/database.rb
CHANGED
@@ -5,20 +5,91 @@
|
|
5
5
|
require 'mdbx' unless defined?( MDBX )
|
6
6
|
|
7
7
|
|
8
|
-
#
|
8
|
+
# The primary class for interacting with an MDBX database.
|
9
9
|
#
|
10
10
|
class MDBX::Database
|
11
11
|
|
12
|
+
### call-seq:
|
13
|
+
### MDBX::Database.open( path ) => db
|
14
|
+
### MDBX::Database.open( path, options ) => db
|
15
|
+
###
|
12
16
|
### Open an existing (or create a new) mdbx database at filesystem
|
13
|
-
### +path+. In block form, the database is automatically closed
|
17
|
+
### +path+. In block form, the database is automatically closed
|
18
|
+
### when the block exits.
|
14
19
|
###
|
15
|
-
### MDBX::Database.open( path ) -> db
|
16
|
-
### MDBX::Database.open( path, options ) -> db
|
17
20
|
### MDBX::Database.open( path, options ) do |db|
|
18
|
-
### db[ 'key' ]
|
19
|
-
### end
|
21
|
+
### db[ 'key' ] = value
|
22
|
+
### end # closed!
|
23
|
+
###
|
24
|
+
### Passing options modify various database behaviors. See the libmdbx
|
25
|
+
### documentation for detailed information.
|
26
|
+
###
|
27
|
+
### ==== Options
|
28
|
+
###
|
29
|
+
### Unless otherwise mentioned, option keys are symbols, and values
|
30
|
+
### are boolean.
|
31
|
+
###
|
32
|
+
### [:mode]
|
33
|
+
### Whe creating a new database, set permissions to this 4 digit
|
34
|
+
### octal number. Defaults to `0644`. Set to `0` to never automatically
|
35
|
+
### create a new file, only opening existing databases.
|
36
|
+
###
|
37
|
+
### [:max_collections]
|
38
|
+
### Set the maximum number of "subdatabase" collections allowed. By
|
39
|
+
### default, collection support is disabled.
|
40
|
+
###
|
41
|
+
### [:max_readers]
|
42
|
+
### Set the maximum number of allocated simultaneous reader slots.
|
43
|
+
###
|
44
|
+
### [:max_size]
|
45
|
+
### Set an upper boundary (in bytes) for the database map size.
|
46
|
+
### The default is 10485760 bytes.
|
47
|
+
###
|
48
|
+
### [:nosubdir]
|
49
|
+
### When creating a new database, don't put the data and lock file
|
50
|
+
### under a dedicated subdirectory.
|
51
|
+
###
|
52
|
+
### [:readonly]
|
53
|
+
### Reject any write attempts while using this database handle.
|
54
|
+
###
|
55
|
+
### [:exclusive]
|
56
|
+
### Access is restricted to the first opening process. Other attempts
|
57
|
+
### to use this database (even in readonly mode) are denied.
|
58
|
+
###
|
59
|
+
### [:compat]
|
60
|
+
### Skip compatibility checks when opening an in-use database with
|
61
|
+
### unknown or mismatched flag values.
|
62
|
+
###
|
63
|
+
### [:writemap]
|
64
|
+
### Trade safety for speed for databases that fit within available
|
65
|
+
### memory. (See MDBX documentation for details.)
|
20
66
|
###
|
21
|
-
###
|
67
|
+
### [:no_threadlocal]
|
68
|
+
### Parallelize read-only transactions across threads. Writes are
|
69
|
+
### always thread local. (See MDBX documentatoin for details.)
|
70
|
+
###
|
71
|
+
### [:no_readahead]
|
72
|
+
### Disable all use of OS readahead. Potentially useful for
|
73
|
+
### random reads wunder low memory conditions. Default behavior
|
74
|
+
### is to dynamically choose when to use or omit readahead.
|
75
|
+
###
|
76
|
+
### [:no_memory_init]
|
77
|
+
### Skip initializing malloc'ed memory to zeroes before writing.
|
78
|
+
###
|
79
|
+
### [:coalesce]
|
80
|
+
### Attempt to coalesce items for the garbage collector,
|
81
|
+
### potentialy increasing the chance of unallocating storage
|
82
|
+
### earlier.
|
83
|
+
###
|
84
|
+
### [:lifo_reclaim]
|
85
|
+
### Recycle garbage collected items via LIFO, instead of FIFO.
|
86
|
+
### Depending on underlying hardware (disk write-back cache), this
|
87
|
+
### could increase write performance.
|
88
|
+
###
|
89
|
+
### [:no_metasync]
|
90
|
+
### A system crash may sacrifice the last commit for a potentially
|
91
|
+
### large write performance increase. Database integrity is
|
92
|
+
### maintained.
|
22
93
|
###
|
23
94
|
def self::open( *args, &block )
|
24
95
|
db = new( *args )
|
@@ -42,16 +113,18 @@ class MDBX::Database
|
|
42
113
|
private_class_method :new
|
43
114
|
|
44
115
|
|
45
|
-
#
|
116
|
+
# Options used when instantiating this database handle.
|
46
117
|
attr_reader :options
|
47
118
|
|
48
119
|
# The path on disk of the database.
|
49
120
|
attr_reader :path
|
50
121
|
|
51
122
|
# A Proc for automatically serializing values.
|
123
|
+
# Defaults to +Marshal.dump+.
|
52
124
|
attr_accessor :serializer
|
53
125
|
|
54
126
|
# A Proc for automatically deserializing values.
|
127
|
+
# Defaults to +Marshal.load+.
|
55
128
|
attr_accessor :deserializer
|
56
129
|
|
57
130
|
|
@@ -61,8 +134,200 @@ class MDBX::Database
|
|
61
134
|
return self.collection( nil )
|
62
135
|
end
|
63
136
|
|
64
|
-
# Allow for some common nomenclature.
|
65
137
|
alias_method :namespace, :collection
|
138
|
+
alias_method :size, :length
|
139
|
+
alias_method :each, :each_pair
|
140
|
+
|
141
|
+
|
142
|
+
#
|
143
|
+
# Transaction methods
|
144
|
+
#
|
145
|
+
|
146
|
+
### Open a new mdbx read/write transaction. In block form,
|
147
|
+
### the transaction is automatically committed when the block ends.
|
148
|
+
###
|
149
|
+
### Raising a MDBX::Rollback exception from within the block
|
150
|
+
### automatically rolls the transaction back.
|
151
|
+
###
|
152
|
+
def transaction( commit: true, &block )
|
153
|
+
self.open_transaction( commit )
|
154
|
+
yield self if block_given?
|
155
|
+
|
156
|
+
return self
|
157
|
+
|
158
|
+
rescue MDBX::Rollback
|
159
|
+
commit = false
|
160
|
+
self.rollback
|
161
|
+
rescue
|
162
|
+
commit = false
|
163
|
+
self.rollback
|
164
|
+
raise
|
165
|
+
ensure
|
166
|
+
if block_given?
|
167
|
+
commit ? self.commit : self.rollback
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
### Open a new mdbx read only snapshot. In block form,
|
173
|
+
### the snapshot is automatically closed when the block ends.
|
174
|
+
###
|
175
|
+
def snapshot( &block )
|
176
|
+
self.transaction( commit: false, &block )
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
### Close any open transaction, abandoning all changes.
|
181
|
+
###
|
182
|
+
def rollback
|
183
|
+
return self.close_transaction( false )
|
184
|
+
end
|
185
|
+
alias_method :abort, :rollback
|
186
|
+
|
187
|
+
|
188
|
+
### Close any open transaction, writing all changes.
|
189
|
+
###
|
190
|
+
def commit
|
191
|
+
return self.close_transaction( true )
|
192
|
+
end
|
193
|
+
alias_method :save, :commit
|
194
|
+
|
195
|
+
|
196
|
+
#
|
197
|
+
# Hash-alike methods
|
198
|
+
#
|
199
|
+
|
200
|
+
### Return the entirety of database contents as an Array of array
|
201
|
+
### pairs.
|
202
|
+
###
|
203
|
+
def to_a
|
204
|
+
self.snapshot do
|
205
|
+
return self.each_pair.to_a
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
|
210
|
+
### Return the entirety of database contents as a Hash.
|
211
|
+
###
|
212
|
+
def to_h
|
213
|
+
self.snapshot do
|
214
|
+
return self.each_pair.to_h
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
### Returns +true+ if the current collection has no data.
|
220
|
+
###
|
221
|
+
def empty?
|
222
|
+
return self.size.zero?
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
### Returns the value for the given key, if found.
|
227
|
+
### If key is not found and no block was given, returns nil.
|
228
|
+
### If key is not found and a block was given, yields key to the
|
229
|
+
### block and returns the block's return value.
|
230
|
+
###
|
231
|
+
def fetch( key, &block )
|
232
|
+
val = self[ key ]
|
233
|
+
if block_given?
|
234
|
+
return block.call( key ) if val.nil?
|
235
|
+
else
|
236
|
+
return val if val
|
237
|
+
raise KeyError, "key not found: %p" % [ key ]
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
|
242
|
+
### Deletes the entry for the given key and returns its associated
|
243
|
+
### value. If no block is given and key is found, deletes the entry
|
244
|
+
### and returns the associated value. If no block given and key is
|
245
|
+
### not found, returns nil.
|
246
|
+
###
|
247
|
+
### If a block is given and key is found, ignores the block, deletes
|
248
|
+
### the entry, and returns the associated value. If a block is given
|
249
|
+
### and key is not found, calls the block and returns the block's
|
250
|
+
### return value.
|
251
|
+
###
|
252
|
+
def delete( key, &block )
|
253
|
+
val = self[ key ]
|
254
|
+
return block.call( key ) if block_given? && val.nil?
|
255
|
+
|
256
|
+
self[ key ] = nil
|
257
|
+
return val
|
258
|
+
end
|
259
|
+
|
260
|
+
|
261
|
+
### Returns a new Array containing all keys in the collection.
|
262
|
+
###
|
263
|
+
def keys
|
264
|
+
self.snapshot do
|
265
|
+
return self.each_key.to_a
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
|
270
|
+
### Returns a new Hash object containing the entries for the given
|
271
|
+
### keys. Any given keys that are not found are ignored.
|
272
|
+
###
|
273
|
+
def slice( *keys )
|
274
|
+
self.snapshot do
|
275
|
+
return keys.each_with_object( {} ) do |key, acc|
|
276
|
+
val = self[ key ]
|
277
|
+
acc[ key ] = val if val
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
|
283
|
+
### Returns a new Array containing all values in the collection.
|
284
|
+
###
|
285
|
+
def values
|
286
|
+
self.snapshot do
|
287
|
+
return self.each_value.to_a
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
|
292
|
+
### Returns a new Array containing values for the given +keys+.
|
293
|
+
###
|
294
|
+
def values_at( *keys )
|
295
|
+
self.snapshot do
|
296
|
+
return keys.each_with_object( [] ) do |key, acc|
|
297
|
+
acc << self[ key ]
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
|
303
|
+
#
|
304
|
+
# Utility methods
|
305
|
+
#
|
306
|
+
|
307
|
+
### Return a hash of various metadata for the current database.
|
308
|
+
###
|
309
|
+
def statistics
|
310
|
+
raw = self.raw_stats
|
311
|
+
|
312
|
+
# Place build options in their own hash.
|
313
|
+
#
|
314
|
+
build_opts = raw.delete( :build_options ).split.each_with_object( {} ) do |opt, acc|
|
315
|
+
key, val = opt.split( '=' )
|
316
|
+
acc[ key.to_sym ] = Integer( val ) rescue val
|
317
|
+
end
|
318
|
+
|
319
|
+
stats = {
|
320
|
+
build: {
|
321
|
+
compiler: raw.delete( :build_compiler ),
|
322
|
+
flags: raw.delete( :build_flags ),
|
323
|
+
options: build_opts,
|
324
|
+
target: raw.delete( :build_target )
|
325
|
+
}
|
326
|
+
}
|
327
|
+
stats.merge!( raw )
|
328
|
+
|
329
|
+
return stats
|
330
|
+
end
|
66
331
|
|
67
332
|
end # class MDBX::Database
|
68
333
|
|