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.
@@ -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
  */
@@ -4,12 +4,23 @@
4
4
 
5
5
  #include "mdbx.h"
6
6
 
7
- #ifndef MDBX_EXT_0_9_3
8
- #define MDBX_EXT_0_9_3
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
- extern void rmdbx_free( void *db ); /* forward declaration for the allocator */
55
+
44
56
 
45
57
  /* ------------------------------------------------------------
46
- * Globals
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 MDBX_EXT_0_9_3 */
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
- reader_list_callback(
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, reader_list_callback, (void*)readers );
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
- ### [: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.
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
- ### [: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.
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
- ### [:compat]
60
- ### Skip compatibility checks when opening an in-use database with
61
- ### unknown or mismatched flag values.
69
+ ### [:no_memory_init]
70
+ ### Skip initializing malloc'ed memory to zeroes before writing.
62
71
  ###
63
- ### [:writemap]
64
- ### Trade safety for speed for databases that fit within available
65
- ### memory. (See MDBX documentation for details.)
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
- ### [:no_threadlocal]
68
- ### Parallelize read-only transactions across threads. Writes are
69
- ### always thread local. (See MDBX documentatoin for details.)
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
- ### [: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.
86
+ ### [:no_threadlocal]
87
+ ### Parallelize read-only transactions across threads. Writes are
88
+ ### always thread local. (See MDBX documentatoin for details.)
83
89
  ###
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.
90
+ ### [:readonly]
91
+ ### Reject any write attempts while using this database handle.
88
92
  ###
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.
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.collection( nil )
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.2.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.2.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-03-19 00:00:00.000000000 Z
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