mdbx 0.2.0 → 0.3.3
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/History.md +67 -0
- data/README.md +0 -7
- data/ext/mdbx_ext/database.c +482 -354
- data/ext/mdbx_ext/mdbx_ext.c +54 -0
- data/ext/mdbx_ext/mdbx_ext.h +36 -7
- data/ext/mdbx_ext/stats.c +39 -7
- data/lib/mdbx/database.rb +101 -43
- data/lib/mdbx.rb +8 -1
- data.tar.gz.sig +0 -0
- metadata +16 -2
- metadata.gz.sig +0 -0
data/ext/mdbx_ext/mdbx_ext.c
CHANGED
@@ -6,6 +6,60 @@ VALUE rmdbx_mMDBX;
|
|
6
6
|
VALUE rmdbx_eDatabaseError;
|
7
7
|
VALUE rmdbx_eRollback;
|
8
8
|
|
9
|
+
/*
|
10
|
+
* Log a message to the given +context+ object's logger.
|
11
|
+
*/
|
12
|
+
void
|
13
|
+
#ifdef HAVE_STDARG_PROTOTYPES
|
14
|
+
rmdbx_log_obj( VALUE context, const char *level, const char *fmt, ... )
|
15
|
+
#else
|
16
|
+
rmdbx_log_obj( VALUE context, const char *level, const char *fmt, va_dcl )
|
17
|
+
#endif
|
18
|
+
{
|
19
|
+
char buf[BUFSIZ];
|
20
|
+
va_list args;
|
21
|
+
VALUE logger = Qnil;
|
22
|
+
VALUE message = Qnil;
|
23
|
+
|
24
|
+
va_init_list( args, fmt );
|
25
|
+
vsnprintf( buf, BUFSIZ, fmt, args );
|
26
|
+
message = rb_str_new2( buf );
|
27
|
+
|
28
|
+
logger = rb_funcall( context, rb_intern("log"), 0 );
|
29
|
+
rb_funcall( logger, rb_intern(level), 1, message );
|
30
|
+
|
31
|
+
va_end( args );
|
32
|
+
}
|
33
|
+
|
34
|
+
|
35
|
+
/*
|
36
|
+
* Log a message to the global logger.
|
37
|
+
*/
|
38
|
+
void
|
39
|
+
#ifdef HAVE_STDARG_PROTOTYPES
|
40
|
+
rmdbx_log( const char *level, const char *fmt, ... )
|
41
|
+
#else
|
42
|
+
rmdbx_log( const char *level, const char *fmt, va_dcl )
|
43
|
+
#endif
|
44
|
+
{
|
45
|
+
char buf[BUFSIZ];
|
46
|
+
va_list args;
|
47
|
+
VALUE logger = Qnil;
|
48
|
+
VALUE message = Qnil;
|
49
|
+
|
50
|
+
va_init_list( args, fmt );
|
51
|
+
vsnprintf( buf, BUFSIZ, fmt, args );
|
52
|
+
message = rb_str_new2( buf );
|
53
|
+
|
54
|
+
logger = rb_funcall( rmdbx_mMDBX, rb_intern("logger"), 0 );
|
55
|
+
rb_funcall( logger, rb_intern(level), 1, message );
|
56
|
+
|
57
|
+
va_end( args );
|
58
|
+
}
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
|
9
63
|
/*
|
10
64
|
* MDBX initialization
|
11
65
|
*/
|
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,27 @@ 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
|
+
* Logging
|
47
59
|
* ------------------------------------------------------------ */
|
60
|
+
#ifdef HAVE_STDARG_PROTOTYPES
|
61
|
+
#include <stdarg.h>
|
62
|
+
#define va_init_list(a,b) va_start(a,b)
|
63
|
+
void rmdbx_log_obj( VALUE, const char *, const char *, ... );
|
64
|
+
void rmdbx_log( const char *, const char *, ... );
|
65
|
+
#else
|
66
|
+
#include <varargs.h>
|
67
|
+
#define va_init_list(a,b) va_start(a)
|
68
|
+
void rmdbx_log_obj( VALUE, const char *, const char *, va_dcl );
|
69
|
+
void rmdbx_log( const char *, const char *, va_dcl );
|
70
|
+
#endif
|
48
71
|
|
72
|
+
|
73
|
+
/* ------------------------------------------------------------
|
74
|
+
* Globals
|
75
|
+
* ------------------------------------------------------------ */
|
49
76
|
extern VALUE rmdbx_mMDBX;
|
50
77
|
extern VALUE rmdbx_cDatabase;
|
51
78
|
extern VALUE rmdbx_eDatabaseError;
|
@@ -55,13 +82,15 @@ extern VALUE rmdbx_eRollback;
|
|
55
82
|
/* ------------------------------------------------------------
|
56
83
|
* Functions
|
57
84
|
* ------------------------------------------------------------ */
|
85
|
+
extern void rmdbx_free( void *db ); /* forward declaration for the allocator */
|
58
86
|
extern void Init_rmdbx ( void );
|
59
87
|
extern void rmdbx_init_database ( void );
|
88
|
+
extern void rmdbx_close_all( rmdbx_db_t* );
|
60
89
|
extern void rmdbx_open_txn( rmdbx_db_t*, int );
|
61
90
|
extern void rmdbx_close_txn( rmdbx_db_t*, int );
|
62
|
-
|
91
|
+
extern void rmdbx_open_cursor( rmdbx_db_t* );
|
63
92
|
extern VALUE rmdbx_gather_stats( rmdbx_db_t* );
|
64
93
|
|
65
94
|
|
66
|
-
#endif /* define
|
95
|
+
#endif /* define RBMDBX_EXT */
|
67
96
|
|
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
|
-
mdbx_reader_list( db->env,
|
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/database.rb
CHANGED
@@ -8,6 +8,9 @@ require 'mdbx' unless defined?( MDBX )
|
|
8
8
|
# The primary class for interacting with an MDBX database.
|
9
9
|
#
|
10
10
|
class MDBX::Database
|
11
|
+
extend Loggability
|
12
|
+
|
13
|
+
log_to :mdbx
|
11
14
|
|
12
15
|
### call-seq:
|
13
16
|
### MDBX::Database.open( path ) => db
|
@@ -29,10 +32,23 @@ class MDBX::Database
|
|
29
32
|
### Unless otherwise mentioned, option keys are symbols, and values
|
30
33
|
### are boolean.
|
31
34
|
###
|
32
|
-
### [:
|
33
|
-
###
|
34
|
-
###
|
35
|
-
###
|
35
|
+
### [:coalesce]
|
36
|
+
### Attempt to coalesce items for the garbage collector,
|
37
|
+
### potentialy increasing the chance of unallocating storage
|
38
|
+
### earlier.
|
39
|
+
###
|
40
|
+
### [:compatible]
|
41
|
+
### Skip compatibility checks when opening an in-use database with
|
42
|
+
### unknown or mismatched flag values.
|
43
|
+
###
|
44
|
+
### [:exclusive]
|
45
|
+
### Access is restricted to the first opening process. Other attempts
|
46
|
+
### to use this database (even in readonly mode) are denied.
|
47
|
+
###
|
48
|
+
### [:lifo_reclaim]
|
49
|
+
### Recycle garbage collected items via LIFO, instead of FIFO.
|
50
|
+
### Depending on underlying hardware (disk write-back cache), this
|
51
|
+
### could increase write performance.
|
36
52
|
###
|
37
53
|
### [:max_collections]
|
38
54
|
### Set the maximum number of "subdatabase" collections allowed. By
|
@@ -45,51 +61,38 @@ class MDBX::Database
|
|
45
61
|
### Set an upper boundary (in bytes) for the database map size.
|
46
62
|
### The default is 10485760 bytes.
|
47
63
|
###
|
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.
|
64
|
+
### [:mode]
|
65
|
+
### Whe creating a new database, set permissions to this 4 digit
|
66
|
+
### octal number. Defaults to `0644`. Set to `0` to never automatically
|
67
|
+
### create a new file, only opening existing databases.
|
58
68
|
###
|
59
|
-
### [:
|
60
|
-
### Skip
|
61
|
-
### unknown or mismatched flag values.
|
69
|
+
### [:no_memory_init]
|
70
|
+
### Skip initializing malloc'ed memory to zeroes before writing.
|
62
71
|
###
|
63
|
-
### [:
|
64
|
-
###
|
65
|
-
###
|
72
|
+
### [:no_metasync]
|
73
|
+
### A system crash may sacrifice the last commit for a potentially
|
74
|
+
### large write performance increase. Database integrity is
|
75
|
+
### maintained.
|
66
76
|
###
|
67
|
-
### [:
|
68
|
-
###
|
69
|
-
###
|
77
|
+
### [:no_subdir]
|
78
|
+
### When creating a new database, don't put the data and lock file
|
79
|
+
### under a dedicated subdirectory.
|
70
80
|
###
|
71
81
|
### [:no_readahead]
|
72
82
|
### Disable all use of OS readahead. Potentially useful for
|
73
83
|
### random reads wunder low memory conditions. Default behavior
|
74
84
|
### is to dynamically choose when to use or omit readahead.
|
75
85
|
###
|
76
|
-
### [:
|
77
|
-
###
|
78
|
-
###
|
79
|
-
### [:coalesce]
|
80
|
-
### Attempt to coalesce items for the garbage collector,
|
81
|
-
### potentialy increasing the chance of unallocating storage
|
82
|
-
### earlier.
|
86
|
+
### [:no_threadlocal]
|
87
|
+
### Parallelize read-only transactions across threads. Writes are
|
88
|
+
### always thread local. (See MDBX documentatoin for details.)
|
83
89
|
###
|
84
|
-
### [:
|
85
|
-
###
|
86
|
-
### Depending on underlying hardware (disk write-back cache), this
|
87
|
-
### could increase write performance.
|
90
|
+
### [:readonly]
|
91
|
+
### Reject any write attempts while using this database handle.
|
88
92
|
###
|
89
|
-
### [:
|
90
|
-
###
|
91
|
-
###
|
92
|
-
### maintained.
|
93
|
+
### [:writemap]
|
94
|
+
### Trade safety for speed for databases that fit within available
|
95
|
+
### memory. (See MDBX documentation for details.)
|
93
96
|
###
|
94
97
|
def self::open( *args, &block )
|
95
98
|
db = new( *args )
|
@@ -128,16 +131,43 @@ class MDBX::Database
|
|
128
131
|
attr_accessor :deserializer
|
129
132
|
|
130
133
|
|
134
|
+
alias_method :size, :length
|
135
|
+
alias_method :each, :each_pair
|
136
|
+
alias_method :has_key?, :include?
|
137
|
+
|
138
|
+
|
139
|
+
### Gets or sets the sub-database "collection" that read/write
|
140
|
+
### operations apply to. If a block is passed, the collection
|
141
|
+
### automatically reverts to the prior collection when it exits.
|
142
|
+
###
|
143
|
+
### db.collection #=> (collection name, or nil if in main)
|
144
|
+
### db.collection( 'collection_name' ) #=> db
|
145
|
+
###
|
146
|
+
### db.collection( 'collection_name' ) do
|
147
|
+
### [ ... ]
|
148
|
+
### end # reverts to the previous collection name
|
149
|
+
###
|
150
|
+
def collection( name=nil )
|
151
|
+
current = self.get_subdb
|
152
|
+
return current unless name
|
153
|
+
|
154
|
+
self.set_subdb( name.to_s )
|
155
|
+
yield( self ) if block_given?
|
156
|
+
|
157
|
+
return self
|
158
|
+
|
159
|
+
ensure
|
160
|
+
self.set_subdb( current ) if name && block_given?
|
161
|
+
end
|
162
|
+
alias_method :namespace, :collection
|
163
|
+
|
164
|
+
|
131
165
|
### Switch to the top-level collection.
|
132
166
|
###
|
133
167
|
def main
|
134
|
-
return self.
|
168
|
+
return self.set_subdb( nil )
|
135
169
|
end
|
136
170
|
|
137
|
-
alias_method :namespace, :collection
|
138
|
-
alias_method :size, :length
|
139
|
-
alias_method :each, :each_pair
|
140
|
-
|
141
171
|
|
142
172
|
#
|
143
173
|
# Transaction methods
|
@@ -334,6 +364,34 @@ class MDBX::Database
|
|
334
364
|
protected
|
335
365
|
#########
|
336
366
|
|
367
|
+
|
368
|
+
### Safely serialize a value, closing any open transaction and re-raising
|
369
|
+
### if necessary.
|
370
|
+
###
|
371
|
+
def serialize( val )
|
372
|
+
return val unless self.serializer
|
373
|
+
return self.serializer.call( val )
|
374
|
+
|
375
|
+
rescue => err
|
376
|
+
self.close_transaction( false )
|
377
|
+
raise err
|
378
|
+
end
|
379
|
+
|
380
|
+
|
381
|
+
### Safely deserialize a value, closing any open transaction and re-raising
|
382
|
+
### if necessary.
|
383
|
+
###
|
384
|
+
def deserialize( val )
|
385
|
+
return val unless self.deserializer
|
386
|
+
return self.deserializer.call( val )
|
387
|
+
|
388
|
+
rescue => err
|
389
|
+
self.close_transaction( false )
|
390
|
+
raise err
|
391
|
+
end
|
392
|
+
|
393
|
+
|
394
|
+
|
337
395
|
### Yield and return the block, opening a snapshot first if
|
338
396
|
### there isn't already a transaction in progress. Closes
|
339
397
|
### the snapshot if this method opened it.
|
data/lib/mdbx.rb
CHANGED
@@ -2,15 +2,22 @@
|
|
2
2
|
# vim: set nosta noet ts=4 sw=4 ft=ruby:
|
3
3
|
# encoding: utf-8
|
4
4
|
|
5
|
+
require 'loggability'
|
6
|
+
|
5
7
|
require 'mdbx_ext'
|
6
8
|
|
7
9
|
|
8
10
|
# Top level namespace for MDBX.
|
9
11
|
#
|
10
12
|
module MDBX
|
13
|
+
extend Loggability
|
11
14
|
|
12
15
|
# The version of this gem.
|
13
|
-
VERSION = '0.
|
16
|
+
VERSION = '0.3.3'
|
17
|
+
|
18
|
+
|
19
|
+
log_as :mdbx
|
20
|
+
|
14
21
|
|
15
22
|
end # module MDBX
|
16
23
|
|
data.tar.gz.sig
CHANGED
Binary file
|
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.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mahlon E. Smith
|
@@ -34,8 +34,22 @@ cert_chain:
|
|
34
34
|
49pOzX5KHZLTS9DKeaP/xcGPz6C8MiwQdYrZarr2SHRASX1zFa79rkItO8kE6RDr
|
35
35
|
b6WDF79UvZ55ajtE00TiwqjQL/ZPEtbd
|
36
36
|
-----END CERTIFICATE-----
|
37
|
-
date: 2021-
|
37
|
+
date: 2021-10-22 00:00:00.000000000 Z
|
38
38
|
dependencies:
|
39
|
+
- !ruby/object:Gem::Dependency
|
40
|
+
name: loggability
|
41
|
+
requirement: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - "~>"
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0.17'
|
46
|
+
type: :runtime
|
47
|
+
prerelease: false
|
48
|
+
version_requirements: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - "~>"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0.17'
|
39
53
|
- !ruby/object:Gem::Dependency
|
40
54
|
name: pry
|
41
55
|
requirement: !ruby/object:Gem::Requirement
|
metadata.gz.sig
CHANGED
Binary file
|