mdbx 0.1.1 → 0.3.2
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 +62 -0
- data/README.md +0 -7
- data/ext/mdbx_ext/database.c +552 -384
- data/ext/mdbx_ext/mdbx_ext.h +20 -7
- data/ext/mdbx_ext/stats.c +39 -7
- data/lib/mdbx.rb +1 -1
- data/lib/mdbx/database.rb +109 -82
- metadata +2 -2
- metadata.gz.sig +0 -0
data/ext/mdbx_ext/mdbx_ext.h
CHANGED
@@ -4,12 +4,23 @@
|
|
4
4
|
|
5
5
|
#include "mdbx.h"
|
6
6
|
|
7
|
-
#ifndef
|
8
|
-
#define
|
7
|
+
#ifndef RBMDBX_EXT
|
8
|
+
#define RBMDBX_EXT
|
9
9
|
|
10
10
|
#define RMDBX_TXN_ROLLBACK 0
|
11
11
|
#define RMDBX_TXN_COMMIT 1
|
12
12
|
|
13
|
+
/* Shortcut for fetching wrapped data structure.
|
14
|
+
*/
|
15
|
+
#define UNWRAP_DB( self, db ) \
|
16
|
+
rmdbx_db_t *db; \
|
17
|
+
TypedData_Get_Struct( self, rmdbx_db_t, &rmdbx_db_data, db )
|
18
|
+
|
19
|
+
/* Raise if current DB is not open. */
|
20
|
+
#define CHECK_HANDLE() \
|
21
|
+
if ( ! db->state.open ) rb_raise( rmdbx_eDatabaseError, "Closed database." )
|
22
|
+
|
23
|
+
|
13
24
|
/*
|
14
25
|
* A struct encapsulating an instance's DB
|
15
26
|
* state and settings.
|
@@ -21,7 +32,8 @@ struct rmdbx_db {
|
|
21
32
|
MDBX_cursor *cursor;
|
22
33
|
|
23
34
|
struct {
|
24
|
-
int env_flags;
|
35
|
+
unsigned int env_flags;
|
36
|
+
unsigned int db_flags;
|
25
37
|
int mode;
|
26
38
|
int open;
|
27
39
|
int max_collections;
|
@@ -40,12 +52,11 @@ struct rmdbx_db {
|
|
40
52
|
typedef struct rmdbx_db rmdbx_db_t;
|
41
53
|
|
42
54
|
static const rb_data_type_t rmdbx_db_data;
|
43
|
-
|
55
|
+
|
44
56
|
|
45
57
|
/* ------------------------------------------------------------
|
46
58
|
* Globals
|
47
59
|
* ------------------------------------------------------------ */
|
48
|
-
|
49
60
|
extern VALUE rmdbx_mMDBX;
|
50
61
|
extern VALUE rmdbx_cDatabase;
|
51
62
|
extern VALUE rmdbx_eDatabaseError;
|
@@ -55,13 +66,15 @@ extern VALUE rmdbx_eRollback;
|
|
55
66
|
/* ------------------------------------------------------------
|
56
67
|
* Functions
|
57
68
|
* ------------------------------------------------------------ */
|
69
|
+
extern void rmdbx_free( void *db ); /* forward declaration for the allocator */
|
58
70
|
extern void Init_rmdbx ( void );
|
59
71
|
extern void rmdbx_init_database ( void );
|
72
|
+
extern void rmdbx_close_all( rmdbx_db_t* );
|
60
73
|
extern void rmdbx_open_txn( rmdbx_db_t*, int );
|
61
74
|
extern void rmdbx_close_txn( rmdbx_db_t*, int );
|
62
|
-
|
75
|
+
extern void rmdbx_open_cursor( rmdbx_db_t* );
|
63
76
|
extern VALUE rmdbx_gather_stats( rmdbx_db_t* );
|
64
77
|
|
65
78
|
|
66
|
-
#endif /* define
|
79
|
+
#endif /* define RBMDBX_EXT */
|
67
80
|
|
data/ext/mdbx_ext/stats.c
CHANGED
@@ -3,8 +3,6 @@
|
|
3
3
|
* Expose a bunch of mdbx internals to ruby.
|
4
4
|
* This is all largely stolen from mdbx_stat.c.
|
5
5
|
*
|
6
|
-
* Entry point is rmdbx_stats() in database.c.
|
7
|
-
*
|
8
6
|
*/
|
9
7
|
|
10
8
|
#include "mdbx_ext.h"
|
@@ -28,6 +26,32 @@ rmdbx_gather_build_stats( VALUE stat )
|
|
28
26
|
}
|
29
27
|
|
30
28
|
|
29
|
+
/*
|
30
|
+
* Grab current memory usage. (Available since MDBX 0.10.0).
|
31
|
+
*/
|
32
|
+
void
|
33
|
+
rmdbx_gather_memory_stats( VALUE stat )
|
34
|
+
{
|
35
|
+
if (! ( MDBX_VERSION_MAJOR >= 0 && MDBX_VERSION_MINOR >= 10 ) )
|
36
|
+
return;
|
37
|
+
|
38
|
+
VALUE mem = rb_hash_new();
|
39
|
+
rb_hash_aset( stat, ID2SYM(rb_intern("system_memory")), mem );
|
40
|
+
|
41
|
+
intptr_t page_size;
|
42
|
+
intptr_t total_pages;
|
43
|
+
intptr_t avail_pages;
|
44
|
+
|
45
|
+
mdbx_get_sysraminfo( &page_size, &total_pages, &avail_pages );
|
46
|
+
|
47
|
+
rb_hash_aset( mem, ID2SYM(rb_intern("pagesize")), LONG2FIX( page_size ) );
|
48
|
+
rb_hash_aset( mem, ID2SYM(rb_intern("total_pages")), LONG2FIX( total_pages ) );
|
49
|
+
rb_hash_aset( mem, ID2SYM(rb_intern("avail_pages")), LONG2FIX( avail_pages ) );
|
50
|
+
|
51
|
+
return;
|
52
|
+
}
|
53
|
+
|
54
|
+
|
31
55
|
/*
|
32
56
|
* Metadata for the database file.
|
33
57
|
*/
|
@@ -80,6 +104,16 @@ rmdbx_gather_environment_stats(
|
|
80
104
|
|
81
105
|
rb_hash_aset( environ, ID2SYM(rb_intern("pagesize")),
|
82
106
|
INT2NUM(mstat.ms_psize) );
|
107
|
+
rb_hash_aset( environ, ID2SYM(rb_intern("branch_pages")),
|
108
|
+
LONG2NUM(mstat.ms_branch_pages) );
|
109
|
+
rb_hash_aset( environ, ID2SYM(rb_intern("leaf_pages")),
|
110
|
+
LONG2NUM(mstat.ms_leaf_pages) );
|
111
|
+
rb_hash_aset( environ, ID2SYM(rb_intern("overflow_pages")),
|
112
|
+
LONG2NUM(mstat.ms_overflow_pages) );
|
113
|
+
rb_hash_aset( environ, ID2SYM(rb_intern("btree_depth")),
|
114
|
+
INT2NUM(mstat.ms_depth) );
|
115
|
+
rb_hash_aset( environ, ID2SYM(rb_intern("entries")),
|
116
|
+
LONG2NUM(mstat.ms_entries) );
|
83
117
|
rb_hash_aset( environ, ID2SYM(rb_intern("last_txnid")),
|
84
118
|
INT2NUM(menvinfo.mi_recent_txnid) );
|
85
119
|
rb_hash_aset( environ, ID2SYM(rb_intern("last_reader_txnid")),
|
@@ -101,7 +135,7 @@ rmdbx_gather_environment_stats(
|
|
101
135
|
*
|
102
136
|
*/
|
103
137
|
int
|
104
|
-
|
138
|
+
rmdbx_reader_list_cb(
|
105
139
|
void *ctx,
|
106
140
|
int num,
|
107
141
|
int slot,
|
@@ -148,7 +182,7 @@ rmdbx_gather_reader_stats(
|
|
148
182
|
{
|
149
183
|
VALUE readers = rb_ary_new();
|
150
184
|
|
151
|
-
|
185
|
+
mdbx_reader_list( db->env, rmdbx_reader_list_cb, (void*)readers );
|
152
186
|
rb_hash_aset( stat, ID2SYM(rb_intern("readers")), readers );
|
153
187
|
|
154
188
|
return;
|
@@ -168,6 +202,7 @@ rmdbx_gather_stats( rmdbx_db_t *db )
|
|
168
202
|
MDBX_stat mstat;
|
169
203
|
MDBX_envinfo menvinfo;
|
170
204
|
|
205
|
+
rmdbx_gather_memory_stats( stat );
|
171
206
|
rmdbx_gather_build_stats( stat );
|
172
207
|
|
173
208
|
rmdbx_open_txn( db, MDBX_TXN_RDONLY );
|
@@ -183,9 +218,6 @@ rmdbx_gather_stats( rmdbx_db_t *db )
|
|
183
218
|
rmdbx_gather_environment_stats( stat, mstat, menvinfo );
|
184
219
|
rmdbx_gather_reader_stats( db, stat, mstat, menvinfo );
|
185
220
|
|
186
|
-
/* TODO: database and subdatabase stats */
|
187
|
-
|
188
221
|
return stat;
|
189
222
|
}
|
190
223
|
|
191
|
-
|
data/lib/mdbx.rb
CHANGED
data/lib/mdbx/database.rb
CHANGED
@@ -29,10 +29,23 @@ class MDBX::Database
|
|
29
29
|
### Unless otherwise mentioned, option keys are symbols, and values
|
30
30
|
### are boolean.
|
31
31
|
###
|
32
|
-
### [:
|
33
|
-
###
|
34
|
-
###
|
35
|
-
###
|
32
|
+
### [:coalesce]
|
33
|
+
### Attempt to coalesce items for the garbage collector,
|
34
|
+
### potentialy increasing the chance of unallocating storage
|
35
|
+
### earlier.
|
36
|
+
###
|
37
|
+
### [:compatible]
|
38
|
+
### Skip compatibility checks when opening an in-use database with
|
39
|
+
### unknown or mismatched flag values.
|
40
|
+
###
|
41
|
+
### [:exclusive]
|
42
|
+
### Access is restricted to the first opening process. Other attempts
|
43
|
+
### to use this database (even in readonly mode) are denied.
|
44
|
+
###
|
45
|
+
### [:lifo_reclaim]
|
46
|
+
### Recycle garbage collected items via LIFO, instead of FIFO.
|
47
|
+
### Depending on underlying hardware (disk write-back cache), this
|
48
|
+
### could increase write performance.
|
36
49
|
###
|
37
50
|
### [:max_collections]
|
38
51
|
### Set the maximum number of "subdatabase" collections allowed. By
|
@@ -45,51 +58,38 @@ class MDBX::Database
|
|
45
58
|
### Set an upper boundary (in bytes) for the database map size.
|
46
59
|
### The default is 10485760 bytes.
|
47
60
|
###
|
48
|
-
### [:
|
49
|
-
###
|
50
|
-
###
|
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.
|
61
|
+
### [:mode]
|
62
|
+
### Whe creating a new database, set permissions to this 4 digit
|
63
|
+
### octal number. Defaults to `0644`. Set to `0` to never automatically
|
64
|
+
### create a new file, only opening existing databases.
|
58
65
|
###
|
59
|
-
### [:
|
60
|
-
### Skip
|
61
|
-
### unknown or mismatched flag values.
|
66
|
+
### [:no_memory_init]
|
67
|
+
### Skip initializing malloc'ed memory to zeroes before writing.
|
62
68
|
###
|
63
|
-
### [:
|
64
|
-
###
|
65
|
-
###
|
69
|
+
### [:no_metasync]
|
70
|
+
### A system crash may sacrifice the last commit for a potentially
|
71
|
+
### large write performance increase. Database integrity is
|
72
|
+
### maintained.
|
66
73
|
###
|
67
|
-
### [:
|
68
|
-
###
|
69
|
-
###
|
74
|
+
### [:no_subdir]
|
75
|
+
### When creating a new database, don't put the data and lock file
|
76
|
+
### under a dedicated subdirectory.
|
70
77
|
###
|
71
78
|
### [:no_readahead]
|
72
79
|
### Disable all use of OS readahead. Potentially useful for
|
73
80
|
### random reads wunder low memory conditions. Default behavior
|
74
81
|
### is to dynamically choose when to use or omit readahead.
|
75
82
|
###
|
76
|
-
### [:
|
77
|
-
###
|
78
|
-
###
|
79
|
-
### [:coalesce]
|
80
|
-
### Attempt to coalesce items for the garbage collector,
|
81
|
-
### potentialy increasing the chance of unallocating storage
|
82
|
-
### earlier.
|
83
|
+
### [:no_threadlocal]
|
84
|
+
### Parallelize read-only transactions across threads. Writes are
|
85
|
+
### always thread local. (See MDBX documentatoin for details.)
|
83
86
|
###
|
84
|
-
### [:
|
85
|
-
###
|
86
|
-
### Depending on underlying hardware (disk write-back cache), this
|
87
|
-
### could increase write performance.
|
87
|
+
### [:readonly]
|
88
|
+
### Reject any write attempts while using this database handle.
|
88
89
|
###
|
89
|
-
### [:
|
90
|
-
###
|
91
|
-
###
|
92
|
-
### maintained.
|
90
|
+
### [:writemap]
|
91
|
+
### Trade safety for speed for databases that fit within available
|
92
|
+
### memory. (See MDBX documentation for details.)
|
93
93
|
###
|
94
94
|
def self::open( *args, &block )
|
95
95
|
db = new( *args )
|
@@ -128,16 +128,43 @@ class MDBX::Database
|
|
128
128
|
attr_accessor :deserializer
|
129
129
|
|
130
130
|
|
131
|
+
alias_method :size, :length
|
132
|
+
alias_method :each, :each_pair
|
133
|
+
alias_method :has_key?, :include?
|
134
|
+
|
135
|
+
|
136
|
+
### Gets or sets the sub-database "collection" that read/write
|
137
|
+
### operations apply to. If a block is passed, the collection
|
138
|
+
### automatically reverts to the prior collection when it exits.
|
139
|
+
###
|
140
|
+
### db.collection #=> (collection name, or nil if in main)
|
141
|
+
### db.collection( 'collection_name' ) #=> db
|
142
|
+
###
|
143
|
+
### db.collection( 'collection_name' ) do
|
144
|
+
### [ ... ]
|
145
|
+
### end # reverts to the previous collection name
|
146
|
+
###
|
147
|
+
def collection( name=nil )
|
148
|
+
current = self.get_subdb
|
149
|
+
return current unless name
|
150
|
+
|
151
|
+
self.set_subdb( name.to_s )
|
152
|
+
yield( self ) if block_given?
|
153
|
+
|
154
|
+
return self
|
155
|
+
|
156
|
+
ensure
|
157
|
+
self.set_subdb( current ) if name && block_given?
|
158
|
+
end
|
159
|
+
alias_method :namespace, :collection
|
160
|
+
|
161
|
+
|
131
162
|
### Switch to the top-level collection.
|
132
163
|
###
|
133
164
|
def main
|
134
|
-
return self.
|
165
|
+
return self.set_subdb( nil )
|
135
166
|
end
|
136
167
|
|
137
|
-
alias_method :namespace, :collection
|
138
|
-
alias_method :size, :length
|
139
|
-
alias_method :each, :each_pair
|
140
|
-
|
141
168
|
|
142
169
|
#
|
143
170
|
# Transaction methods
|
@@ -201,24 +228,18 @@ class MDBX::Database
|
|
201
228
|
### pairs.
|
202
229
|
###
|
203
230
|
def to_a
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
return self.each_pair.to_a
|
208
|
-
ensure
|
209
|
-
self.abort unless in_txn
|
231
|
+
return self.conditional_snapshot do
|
232
|
+
self.each_pair.to_a
|
233
|
+
end
|
210
234
|
end
|
211
235
|
|
212
236
|
|
213
237
|
### Return the entirety of database contents as a Hash.
|
214
238
|
###
|
215
239
|
def to_h
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
return self.each_pair.to_h
|
220
|
-
ensure
|
221
|
-
self.abort unless in_txn
|
240
|
+
return self.conditional_snapshot do
|
241
|
+
self.each_pair.to_h
|
242
|
+
end
|
222
243
|
end
|
223
244
|
|
224
245
|
|
@@ -267,12 +288,9 @@ class MDBX::Database
|
|
267
288
|
### Returns a new Array containing all keys in the collection.
|
268
289
|
###
|
269
290
|
def keys
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
return self.each_key.to_a
|
274
|
-
ensure
|
275
|
-
self.abort unless in_txn
|
291
|
+
return self.conditional_snapshot do
|
292
|
+
self.each_key.to_a
|
293
|
+
end
|
276
294
|
end
|
277
295
|
|
278
296
|
|
@@ -280,41 +298,32 @@ class MDBX::Database
|
|
280
298
|
### keys. Any given keys that are not found are ignored.
|
281
299
|
###
|
282
300
|
def slice( *keys )
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
acc[ key ] = val if val
|
301
|
+
return self.conditional_snapshot do
|
302
|
+
keys.each_with_object( {} ) do |key, acc|
|
303
|
+
val = self[ key ]
|
304
|
+
acc[ key ] = val if val
|
305
|
+
end
|
289
306
|
end
|
290
|
-
ensure
|
291
|
-
self.abort unless in_txn
|
292
307
|
end
|
293
308
|
|
294
309
|
|
295
310
|
### Returns a new Array containing all values in the collection.
|
296
311
|
###
|
297
312
|
def values
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
return self.each_value.to_a
|
302
|
-
ensure
|
303
|
-
self.abort unless in_txn
|
313
|
+
return self.conditional_snapshot do
|
314
|
+
self.each_value.to_a
|
315
|
+
end
|
304
316
|
end
|
305
317
|
|
306
318
|
|
307
319
|
### Returns a new Array containing values for the given +keys+.
|
308
320
|
###
|
309
321
|
def values_at( *keys )
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
acc << self[ key ]
|
322
|
+
return self.conditional_snapshot do
|
323
|
+
keys.each_with_object( [] ) do |key, acc|
|
324
|
+
acc << self[ key ]
|
325
|
+
end
|
315
326
|
end
|
316
|
-
ensure
|
317
|
-
self.abort unless in_txn
|
318
327
|
end
|
319
328
|
|
320
329
|
|
@@ -347,5 +356,23 @@ class MDBX::Database
|
|
347
356
|
return stats
|
348
357
|
end
|
349
358
|
|
359
|
+
|
360
|
+
#########
|
361
|
+
protected
|
362
|
+
#########
|
363
|
+
|
364
|
+
### Yield and return the block, opening a snapshot first if
|
365
|
+
### there isn't already a transaction in progress. Closes
|
366
|
+
### the snapshot if this method opened it.
|
367
|
+
###
|
368
|
+
def conditional_snapshot
|
369
|
+
in_txn = self.in_transaction?
|
370
|
+
self.snapshot unless in_txn
|
371
|
+
|
372
|
+
return yield
|
373
|
+
ensure
|
374
|
+
self.abort unless in_txn
|
375
|
+
end
|
376
|
+
|
350
377
|
end # class MDBX::Database
|
351
378
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mdbx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mahlon E. Smith
|
@@ -34,7 +34,7 @@ cert_chain:
|
|
34
34
|
49pOzX5KHZLTS9DKeaP/xcGPz6C8MiwQdYrZarr2SHRASX1zFa79rkItO8kE6RDr
|
35
35
|
b6WDF79UvZ55ajtE00TiwqjQL/ZPEtbd
|
36
36
|
-----END CERTIFICATE-----
|
37
|
-
date: 2021-
|
37
|
+
date: 2021-07-13 00:00:00.000000000 Z
|
38
38
|
dependencies:
|
39
39
|
- !ruby/object:Gem::Dependency
|
40
40
|
name: pry
|