mdbx 0.2.0 → 0.3.3
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/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
|