mdbx 0.1.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|