lmdb 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1e16a42693e5150e076829337a0d44feb46bc3f3
4
- data.tar.gz: ce0bc77de0cf3c7e17df2522c8eab69e760e1221
3
+ metadata.gz: 92f31229585bce51aaa1f94fab800c5f98488869
4
+ data.tar.gz: e57e72dac8a031aeb3163c917252160b2c3c21c2
5
5
  SHA512:
6
- metadata.gz: e02924de6a59386ec215b45baf321a6d098d818900f7816a3805185ab5b7441427cc5af866d2d8141eecfd1d166a659ebc2a87d5ae7626a9a574bd4d1bd4bf44
7
- data.tar.gz: 3ee55c5879fd385e53d25eeffd694dab0de03c5b152fe07562f9b631de25ccd90f09ae886a1d30b7f9abd6ea3a8da3fedac0b1f9d69dbffc3874bfad18570dd9
6
+ metadata.gz: c7fe9fba9eae7efe4c0a15387906dd006e7f1f9659b8df9b8d7459386e9ea833df4b32e3df8d131d060299d6e948212d26dca9cb2b593d3f9106d55530b4c1b8
7
+ data.tar.gz: fc1108b3f94451fd44b29b9f37a30d0cd6641c8c5193552751f970ed46b67f91da32a7da3b044d4443371e515d781b537f6cc2df975169ea1beb6e50bc338514
data/.gitignore CHANGED
@@ -6,3 +6,5 @@
6
6
  Makefile
7
7
  tmp/
8
8
  Gemfile.lock
9
+ doc/
10
+ .yardoc/
data/CHANGES CHANGED
@@ -1,3 +1,7 @@
1
+ 0.4.1
2
+
3
+ * Fix #10
4
+
1
5
  0.4.0
2
6
 
3
7
  * Print warnings if open LMDB objects are found during garbage collection
data/CONTRIBUTORS CHANGED
@@ -1,3 +1,6 @@
1
1
  Daniel Mendler <mail@daniel-mendler.de>
2
2
  Dimitrij Denissenko <dimitrij.denissenko@blacksquaremedia.com>
3
3
  Evgeniy Dolzhenko <evgeniy.dolzhenko@blacksquaremedia.com>
4
+ Julien Ammous <schmurfy@gmail.com>
5
+ Nathaniel Pierce <nwpierce@gmail.com>
6
+ Richard Golding <golding@chrysaetos.org>
data/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  Ruby bindings for the amazing OpenLDAP's Lightning Memory-Mapped Database (LMDB)
7
7
  http://symas.com/mdb/
8
8
 
9
- ### Installation
9
+ ## Installation
10
10
 
11
11
  Install via rubygems:
12
12
 
@@ -14,9 +14,18 @@ Install via rubygems:
14
14
  gem install lmdb
15
15
  ```
16
16
 
17
- ### API
17
+ ## Links
18
18
 
19
- ~~~ ruby
19
+ * Source: <http://github.com/minad/lmdb>
20
+ * Bugs: <http://github.com/minad/lmdb/issues>
21
+ * Tests and benchmarks: <http://travis-ci.org/minad/lmdb>
22
+ * API documentation:
23
+ * Latest Gem: <http://rubydoc.info/gems/lmdb/frames>
24
+ * GitHub master: <http://rubydoc.info/github/minad/lmdb/master/frames>
25
+
26
+ ## API
27
+
28
+ ```ruby
20
29
  require 'lmdb'
21
30
 
22
31
  env = LMDB.new(path)
@@ -32,13 +41,11 @@ env.transaction do
32
41
  end
33
42
 
34
43
  env.close
35
- ~~~
44
+ ```
36
45
 
37
- For details take a look at the specs. If you want to have a simpler interface
38
- to LMDB databases please consider using [Moneta](https://github.com/minad/moneta).
39
- The Moneta gem provides an LMDB adapter which uses this gem.
46
+ If you want to have a simpler interface to LMDB databases please consider using [Moneta](https://github.com/minad/moneta). The Moneta gem provides an LMDB adapter which uses this gem.
40
47
 
41
- ### Licence (MIT)
48
+ ## Licence (MIT)
42
49
 
43
50
  ```
44
51
  Copyright (c) 2013 Daniel Mendler
@@ -5,6 +5,7 @@ $CFLAGS = '-std=c99 -Wall -g'
5
5
  # Embed lmdb if we cannot find it
6
6
  if enable_config("bundled-lmdb", false) || !(find_header('lmdb.h') && have_library('lmdb', 'mdb_env_create'))
7
7
  $INCFLAGS << " -I$(srcdir)/liblmdb"
8
+ $VPATH ||= []
8
9
  $VPATH << "$(srcdir)/liblmdb"
9
10
  $srcs = Dir.glob("#{$srcdir}/{,liblmdb/}*.c").map {|n| File.basename(n) }
10
11
  end
@@ -29,11 +29,58 @@ static void transaction_mark(Transaction* transaction) {
29
29
  rb_gc_mark(transaction->env);
30
30
  }
31
31
 
32
+ /**
33
+ * Commit a transaction in process. Any subtransactions of this
34
+ * transaction will be committed as well.
35
+ *
36
+ * One does not normally need to call commit explicitly; a
37
+ * commit is performed automatically when the block supplied to
38
+ * {Environment#transaction} exits normally.
39
+ *
40
+ * @note After committing a transaction, no further database operations
41
+ * should be done in the block. Any cursors created in the context
42
+ * of the transaction will no longer be valid.
43
+ *
44
+ * @example Single transaction
45
+ * env.transaction do |txn|
46
+ * # ... modify the databases ...
47
+ * txn.commit
48
+ * end
49
+ *
50
+ * @example Child transactions
51
+ * env.transaction do |txn1|
52
+ * env.transaction.do |txn2|
53
+ * txn1.commit # txn1 and txn2 are both committed
54
+ * end
55
+ * end
56
+ */
32
57
  static VALUE transaction_commit(VALUE self) {
33
58
  transaction_finish(self, 1);
34
59
  return Qnil;
35
60
  }
36
61
 
62
+ /**
63
+ * Abort a transaction in process. Any subtransactions of this
64
+ * transaction will be aborted as well.
65
+ *
66
+ * @note After aborting a transaction, no further database operations
67
+ * should be done in the block. Any cursors created in the context
68
+ * of the transaction will no longer be valid.
69
+ *
70
+ * @example Single transaction
71
+ * env.transaction do |txn|
72
+ * # ... modify the databases ...
73
+ * txn.abort
74
+ * # modifications are rolled back
75
+ * end
76
+ *
77
+ * @example Child transactions
78
+ * env.transaction do |txn1|
79
+ * env.transaction.do |txn2|
80
+ * txn1.abort # txn1 and txn2 are both aborted
81
+ * end
82
+ * end
83
+ */
37
84
  static VALUE transaction_abort(VALUE self) {
38
85
  transaction_finish(self, 0);
39
86
  return Qnil;
@@ -140,6 +187,15 @@ static void environment_mark(Environment* environment) {
140
187
  rb_gc_mark(environment->txn_thread_hash);
141
188
  }
142
189
 
190
+ /**
191
+ * @overload close
192
+ * Close an environment, completing all IOs and cleaning up database
193
+ * state if needed.
194
+ * @example
195
+ * env = LMDB.new('abc')
196
+ * # ...various operations on the environment...
197
+ * env.close
198
+ */
143
199
  static VALUE environment_close(VALUE self) {
144
200
  ENVIRONMENT(self, environment);
145
201
  mdb_env_close(environment->env);
@@ -162,6 +218,17 @@ static VALUE stat2hash(const MDB_stat* stat) {
162
218
  return ret;
163
219
  }
164
220
 
221
+ /**
222
+ * @overload stat
223
+ * Return useful statistics about an environment.
224
+ * @return [Hash] the statistics
225
+ * * +:psize+ Size of a database page
226
+ * * +:depth+ Depth (height) of the B-tree
227
+ * * +:branch_pages+ Number of internal (non-leaf) pages
228
+ * * +:leaf_pages+ Number of leaf pages
229
+ * * +:overflow_pages+ Number of overflow pages
230
+ * * +:entries+ Number of data items
231
+ */
165
232
  static VALUE environment_stat(VALUE self) {
166
233
  ENVIRONMENT(self, environment);
167
234
  MDB_stat stat;
@@ -169,6 +236,17 @@ static VALUE environment_stat(VALUE self) {
169
236
  return stat2hash(&stat);
170
237
  }
171
238
 
239
+ /**
240
+ * @overload info
241
+ * Return useful information about an environment.
242
+ * @return [Hash]
243
+ * * +:mapaddr+ The memory address at which the database is mapped, if fixed
244
+ * * +:mapsize+ The size of the data memory map
245
+ * * +:last_pgno+ ID of the last used page
246
+ * * +:last_txnid+ ID of the last committed transaction
247
+ * * +:maxreaders+ Max reader slots in the environment
248
+ * * +:numreaders+ Max readers slots in the environment
249
+ */
172
250
  static VALUE environment_info(VALUE self) {
173
251
  MDB_envinfo info;
174
252
 
@@ -189,12 +267,37 @@ static VALUE environment_info(VALUE self) {
189
267
  return ret;
190
268
  }
191
269
 
270
+ /**
271
+ * @overload copy(path)
272
+ * Create a copy (snapshot) of an environment. The copy can be used
273
+ * as a backup. The copy internally uses a read-only transaction to
274
+ * ensure that the copied data is serialized with respect to database
275
+ * updates.
276
+ * @param [String] path The directory in which the copy will
277
+ * reside. This directory must already exist and be writable but
278
+ * must otherwise be empty.
279
+ * @return nil
280
+ * @raise [Error] when there is an error creating the copy.
281
+ */
192
282
  static VALUE environment_copy(VALUE self, VALUE path) {
193
283
  ENVIRONMENT(self, environment);
194
284
  check(mdb_env_copy(environment->env, StringValueCStr(path)));
195
285
  return Qnil;
196
286
  }
197
287
 
288
+ /**
289
+ * @overload sync(force)
290
+ * Flush the data buffers to disk.
291
+ *
292
+ * Data is always written to disk when {Transaction#commit} is called, but
293
+ * the operating system may keep it buffered. MDB always flushes the
294
+ * OS buffers upon commit as well, unless the environment was opened
295
+ * with +:nosync+ or in part +:nometasync+.
296
+ * @param [Boolean] force If true, force a synchronous
297
+ * flush. Otherwise if the environment has the +:nosync+ flag set
298
+ * the flushes will be omitted, and with +:mapasync+ they will be
299
+ * asynchronous.
300
+ */
198
301
  static VALUE environment_sync(int argc, VALUE *argv, VALUE self) {
199
302
  ENVIRONMENT(self, environment);
200
303
 
@@ -229,6 +332,40 @@ static int environment_options(VALUE key, VALUE value, EnvironmentOptions* optio
229
332
  return 0;
230
333
  }
231
334
 
335
+ /**
336
+ * @overload new(path, opts)
337
+ * Open an LMDB database environment.
338
+ * The database environment is the root object for all operations on
339
+ * a collection of databases. It has to be opened first, before
340
+ * individual databases can be opened or created in the environment.
341
+ * The database should be closed when it is no longer needed.
342
+ *
343
+ * The options hash on this method includes all the flags listed in
344
+ * {Environment#flags} as well as the options documented here.
345
+ * @return [Environment]
346
+ * @param [String] path the path to the files containing the database
347
+ * @param [Hash] opts options for the database environment
348
+ * @option opts [Number] :mode The Posix permissions to set on created files.
349
+ * @option opts [Number] :maxreaders The maximum number of concurrent threads
350
+ * that can be executing transactions at once. Default is 126.
351
+ * @option opts [Number] :maxdbs The maximum number of named databases in the
352
+ * environment. Not needed if only one database is being used.
353
+ * @option opts [Number] :mapsize The size of the memory map to be allocated
354
+ * for this environment, in bytes. The memory map size is the
355
+ * maximum total size of the database. The size should be a
356
+ * multiple of the OS page size. The default size is about
357
+ * 10MiB.
358
+ * @yield [env] The block to be executed with the environment. The environment is closed afterwards.
359
+ * @yieldparam env [Environment] The environment
360
+ * @see #close
361
+ * @see Environment#flags
362
+ * @example Open environment and pass options
363
+ * env = LMDB.new "dbdir", :maxdbs => 30, :mapasync => true, :writemap => true
364
+ * @example Pass environment to block
365
+ * LMDB.new "dbdir" do |env|
366
+ * # ...
367
+ * end
368
+ */
232
369
  static VALUE environment_new(int argc, VALUE *argv, VALUE klass) {
233
370
  VALUE path, option_hash;
234
371
  rb_scan_args(argc, argv, "1:", &path, &option_hash);
@@ -266,6 +403,23 @@ static VALUE environment_new(int argc, VALUE *argv, VALUE klass) {
266
403
  return venv;
267
404
  }
268
405
 
406
+ /**
407
+ * @overload flags
408
+ * Return the flags that are set in this environment.
409
+ * @return [Array] Array of flag symbols
410
+ * The environment flags are:
411
+ * * +:fixedmap+ Use a fixed address for the mmap region.
412
+ * * +:nosubdir+ By default, MDB creates its environment in a directory whose pathname is given in +path+, and creates its data and lock files under that directory. With this option, path is used as-is for the database main data file. The database lock file is the path with "-lock" appended.
413
+ * * +:nosync+ Don't flush system buffers to disk when committing a transaction. This optimization means a system crash can corrupt the database or lose the last transactions if buffers are not yet flushed to disk. The risk is governed by how often the system flushes dirty buffers to disk and how often {Environment#sync} is called. However, if the filesystem preserves write order and the +:writemap+ flag is not used, transactions exhibit ACI (atomicity, consistency, isolation) properties and only lose D (durability). That is, database integrity is maintained, but a system crash may undo the final transactions. Note that +:nosync + :writemap+ leaves the system with no hint for when to write transactions to disk, unless {Environment#sync} is called. +:mapasync + :writemap+ may be preferable.
414
+ * * +:rdonly+ Open the environment in read-only mode. No write operations will be allowed. MDB will still modify the lock file - except on read-only filesystems, where MDB does not use locks.
415
+ * * +:nometasync+ Flush system buffers to disk only once per transaction, omit the metadata flush. Defer that until the system flushes files to disk, or next non-MDB_RDONLY commit or {Environment#sync}. This optimization maintains database integrity, but a system crash may undo the last committed transaction. That is, it preserves the ACI (atomicity, consistency, isolation) but not D (durability) database property.
416
+ * * +:writemap+ Use a writeable memory map unless +:rdonly+ is set. This is faster and uses fewer mallocs, but loses protection from application bugs like wild pointer writes and other bad updates into the database. Incompatible with nested transactions.
417
+ * * +:mapasync+ When using +:writemap+, use asynchronous flushes to disk. As with +:nosync+, a system crash can then corrupt the database or lose the last transactions. Calling {Environment#sync} ensures on-disk database integrity until next commit.
418
+ * * +:notls+ Don't use thread-local storage.
419
+ * @example
420
+ * env = LMDB.new "abc", :writemap => true, :nometasync => true
421
+ * env.flags #=> [:writemap, :nometasync]
422
+ */
269
423
  static VALUE environment_flags(VALUE self) {
270
424
  unsigned int flags;
271
425
  ENVIRONMENT(self, environment);
@@ -279,6 +433,11 @@ static VALUE environment_flags(VALUE self) {
279
433
  return ret;
280
434
  }
281
435
 
436
+ /**
437
+ * @overload path
438
+ * Return the path to the database environment files
439
+ * @return [String] the path that was used to open the environment.
440
+ */
282
441
  static VALUE environment_path(VALUE self) {
283
442
  const char* path;
284
443
  ENVIRONMENT(self, environment);
@@ -303,16 +462,45 @@ static VALUE environment_change_flags(int argc, VALUE* argv, VALUE self, int set
303
462
  return Qnil;
304
463
  }
305
464
 
465
+ /**
466
+ * @overload set_flags(flags)
467
+ * Set one or more flags in the environment. The available flags are defined in {Environment#flags}.
468
+ * @see Environment#flags
469
+ * @param [Array] flags Array of flag names (symbols) to set
470
+ * @return nil
471
+ * @raise [Error] if an invalid flag name is specified
472
+ * @example
473
+ * env.set_flags :nosync, :writemap
474
+ */
306
475
  static VALUE environment_set_flags(int argc, VALUE* argv, VALUE self) {
307
476
  environment_change_flags(argc, argv, self, 1);
308
477
  return Qnil;
309
478
  }
310
479
 
480
+ /**
481
+ * @overload clear_flags(flags)
482
+ * Clear one or more flags in the environment. The available flags are defined in {Environment#flags}.
483
+ * @see Environment#flags
484
+ * @param [Array] flags Array of flag names (symbols) to clear
485
+ * @return nil
486
+ * @raise [Error] if an invalid flag name is specified
487
+ * @example
488
+ * env.clear_flags :nosync, :writemap
489
+ */
311
490
  static VALUE environment_clear_flags(int argc, VALUE* argv, VALUE self) {
312
491
  environment_change_flags(argc, argv, self, 0);
313
492
  return Qnil;
314
493
  }
315
494
 
495
+ /**
496
+ * @overload active_txn
497
+ * @return [Transaction] the current active transaction on this thread in the environment.
498
+ * @example
499
+ * env.transaction do |t|
500
+ * active = env.active_txn
501
+ * # active should equal t
502
+ * end
503
+ */
316
504
  static VALUE environment_active_txn(VALUE self) {
317
505
  ENVIRONMENT(self, environment);
318
506
  return rb_hash_aref(environment->thread_txn_hash, rb_thread_current());
@@ -353,6 +541,34 @@ static MDB_txn* need_txn(VALUE self) {
353
541
  return txn;
354
542
  }
355
543
 
544
+ /**
545
+ * @overload transaction(readonly)
546
+ * Begin a transaction. Takes a block to run the body of the
547
+ * transaction. A transaction commits when it exits the block successfully.
548
+ * A transaction aborts when it raises an exception or calls
549
+ * {Transaction#abort}.
550
+ * @param [Boolean] readonly This transaction will not perform any
551
+ * write operations
552
+ * @note Transactions can be nested.
553
+ * @yield [txn] The block to be executed with the body of the transaction.
554
+ * @yieldparam txn [Transaction] An optional transaction argument
555
+ * @example
556
+ * db = env.database "mydata"
557
+ * env.transaction do |txn1|
558
+ * db['a'] = 1
559
+ * env.transaction do |txn2|
560
+ * # txn2 is nested in txn1
561
+ * db['a'] = 2
562
+ * db['a'] #=> 2
563
+ * txn2.abort
564
+ * end
565
+ * db['a'] #=> 1
566
+ * env.transaction do
567
+ * db['a'] = 3
568
+ * end
569
+ * end
570
+ * db['a'] #=> 3
571
+ */
356
572
  static VALUE environment_transaction(int argc, VALUE *argv, VALUE self) {
357
573
  rb_need_block();
358
574
 
@@ -373,6 +589,43 @@ static void database_mark(Database* database) {
373
589
  #undef METHOD
374
590
  #undef FILE
375
591
 
592
+ /**
593
+ * @overload database(name, options)
594
+ * Opens a database within the environment.
595
+ *
596
+ * Note that a database is opened or created within a transaction. If
597
+ * the open creates a new database, the database is not available for
598
+ * other operations in other transactions until the transaction that
599
+ * is creating the database commits. If the transaction creating the
600
+ * database aborts, the database is not created.
601
+ * @return [Database] newly-opened database
602
+ * @raise [Error] if there is an error opening the database
603
+ * @param [String] name Optional name for the database to be opened.
604
+ * @param [Hash] options Options for the database.
605
+ * @option options [Boolean] :reversekey Keys are strings to be
606
+ * compared in reverse order, from the end of the strings to the
607
+ * beginning. By default, Keys are treated as strings and
608
+ * compared from beginning to end.
609
+ * @option options [Boolean] :dupsort Duplicate keys may be used in
610
+ * the database. (Or, from another perspective, keys may have
611
+ * multiple data items, stored in sorted order.) By default keys
612
+ * must be unique and may have only a single data item.
613
+ * @option options [Boolean] :integerkey Keys are binary integers in
614
+ * native byte order.
615
+ * @option options [Boolean] :dupfixed This flag may only be used in
616
+ * combination with +:dupsort+. This option tells the library
617
+ * that the data items for this database are all the same size,
618
+ * which allows further optimizations in storage and retrieval.
619
+ * @option options [Boolean] :integerdup This option specifies that
620
+ * duplicate data items are also integers, and should be sorted
621
+ * as such.
622
+ * @option options [Boolean] :reversedup This option specifies that
623
+ * duplicate data items should be compared as strings in reverse
624
+ * order.
625
+ * @option options [Boolean] :create Create the named database if it
626
+ * doesn't exist. This option is not allowed in a read-only
627
+ * transaction or a read-only environment.
628
+ */
376
629
  static VALUE environment_database(int argc, VALUE *argv, VALUE self) {
377
630
  ENVIRONMENT(self, environment);
378
631
  if (!active_txn(self))
@@ -396,6 +649,17 @@ static VALUE environment_database(int argc, VALUE *argv, VALUE self) {
396
649
  return vdb;
397
650
  }
398
651
 
652
+ /**
653
+ * @overload stat
654
+ * Return useful statistics about a database.
655
+ * @return [Hash] the statistics
656
+ * * +:psize+ Size of a database page
657
+ * * +:depth+ Depth (height) of the B-tree
658
+ * * +:branch_pages+ Number of internal (non-leaf) pages
659
+ * * +:leaf_pages+ Number of leaf pages
660
+ * * +:overflow_pages+ Number of overflow pages
661
+ * * +:entries+ Number of data items
662
+ */
399
663
  static VALUE database_stat(VALUE self) {
400
664
  DATABASE(self, database);
401
665
  if (!active_txn(database->env))
@@ -406,6 +670,12 @@ static VALUE database_stat(VALUE self) {
406
670
  return stat2hash(&stat);
407
671
  }
408
672
 
673
+ /**
674
+ * @overload drop
675
+ * Remove a database from the environment.
676
+ * @return nil
677
+ * @note The drop happens transactionally.
678
+ */
409
679
  static VALUE database_drop(VALUE self) {
410
680
  DATABASE(self, database);
411
681
  if (!active_txn(database->env))
@@ -414,6 +684,12 @@ static VALUE database_drop(VALUE self) {
414
684
  return Qnil;
415
685
  }
416
686
 
687
+ /**
688
+ * @overload clear
689
+ * Empty out the database
690
+ * @return nil
691
+ * @note The clear happens transactionally.
692
+ */
417
693
  static VALUE database_clear(VALUE self) {
418
694
  DATABASE(self, database);
419
695
  if (!active_txn(database->env))
@@ -422,6 +698,15 @@ static VALUE database_clear(VALUE self) {
422
698
  return Qnil;
423
699
  }
424
700
 
701
+ /**
702
+ * @overload get(key)
703
+ * Retrieves one value associated with this key.
704
+ * This function retrieves key/data pairs from the database. If the
705
+ * database supports duplicate keys (+:dupsort+) then the first data
706
+ * item for the key will be returned. Retrieval of other items
707
+ * requires the use of {#cursor}.
708
+ * @param key The key of the record to retrieve.
709
+ */
425
710
  static VALUE database_get(VALUE self, VALUE vkey) {
426
711
  DATABASE(self, database);
427
712
  if (!active_txn(database->env))
@@ -445,6 +730,33 @@ static VALUE database_get(VALUE self, VALUE vkey) {
445
730
  #undef METHOD
446
731
  #undef FILE
447
732
 
733
+ /**
734
+ * @overload put(key, value, options)
735
+ * Stores items into a database.
736
+ * This function stores key/value pairs in the database. The default
737
+ * behavior is to enter the new key/value pair, replacing any
738
+ * previously existing key if duplicates are disallowed, or adding a
739
+ * duplicate data item if duplicates are allowed (+:dupsort+).
740
+ * @param key The key of the record to set
741
+ * @param value The value to insert for this key
742
+ * @option options [Boolean] :nodupdata Enter the new key/value
743
+ * pair only if it does not already appear in the database. This
744
+ * flag may only be specified if the database was opened with
745
+ * +:dupsort+. The function will raise an {Error} if the
746
+ * key/data pair already appears in the database.
747
+ * @option options [Boolean] :nooverwrite Enter the new key/value
748
+ * pair only if the key does not already appear in the
749
+ * database. The function will raise an {Error] if the key
750
+ * already appears in the database, even if the database
751
+ * supports duplicates (+:dupsort+).
752
+ * @option options [Boolean] :append Append the given key/data pair
753
+ * to the end of the database. No key comparisons are
754
+ * performed. This option allows fast bulk loading when keys are
755
+ * already known to be in the correct order. Loading unsorted
756
+ * keys with this flag will cause data corruption.
757
+ * @option options [Boolean] :appenddup As above, but for sorted dup
758
+ * data.
759
+ */
448
760
  static VALUE database_put(int argc, VALUE *argv, VALUE self) {
449
761
  DATABASE(self, database);
450
762
  if (!active_txn(database->env))
@@ -470,6 +782,21 @@ static VALUE database_put(int argc, VALUE *argv, VALUE self) {
470
782
  return Qnil;
471
783
  }
472
784
 
785
+ /**
786
+ * @overload delete(key, value=nil)
787
+ *
788
+ * Deletes records from the database. This function removes
789
+ * key/data pairs from the database. If the database does not support
790
+ * sorted duplicate data items (+:dupsort+) the value parameter is
791
+ * ignored. If the database supports sorted duplicates and the value
792
+ * parameter is +nil+, all of the duplicate data items for the key will
793
+ * be deleted. Otherwise, if the data parameter is non-nil only the
794
+ * matching data item will be deleted.
795
+ *
796
+ * @param key The key of the record to delete.
797
+ * @param value The optional value of the record to delete.
798
+ * @raise [Error] if the specified key/value pair is not in the database.
799
+ */
473
800
  static VALUE database_delete(int argc, VALUE *argv, VALUE self) {
474
801
  DATABASE(self, database);
475
802
  if (!active_txn(database->env))
@@ -515,6 +842,10 @@ static void cursor_mark(Cursor* cursor) {
515
842
  rb_gc_mark(cursor->db);
516
843
  }
517
844
 
845
+ /**
846
+ * @overload close
847
+ * Close a cursor. The cursor must not be used again after this call.
848
+ */
518
849
  static VALUE cursor_close(VALUE self) {
519
850
  CURSOR(self, cursor);
520
851
  mdb_cursor_close(cursor->cur);
@@ -522,6 +853,20 @@ static VALUE cursor_close(VALUE self) {
522
853
  return Qnil;
523
854
  }
524
855
 
856
+ /**
857
+ * @overload cursor
858
+ * Create a cursor to iterate through a database.
859
+ *
860
+ * @see Cursor
861
+ * @yield [cursor] A block to be executed with the cursor
862
+ * @yieldparam cursor [Cursor] The cursor to be used to iterate
863
+ * @example
864
+ * db = env.database "abc"
865
+ * db.cursor do |c|
866
+ * key, value = c.next
867
+ * puts "#{key}: #{value}"
868
+ * end
869
+ */
525
870
  static VALUE database_cursor(VALUE self) {
526
871
  DATABASE(self, database);
527
872
  if (!active_txn(database->env))
@@ -549,6 +894,13 @@ static VALUE database_cursor(VALUE self) {
549
894
  return vcur;
550
895
  }
551
896
 
897
+ /**
898
+ * @overload first
899
+ * Position the cursor to the first record in the database, and
900
+ * return its value.
901
+ * @return [Array,nil] The [key, value] pair for the first record, or
902
+ * nil if no record
903
+ */
552
904
  static VALUE cursor_first(VALUE self) {
553
905
  CURSOR(self, cursor);
554
906
  MDB_val key, value;
@@ -557,6 +909,13 @@ static VALUE cursor_first(VALUE self) {
557
909
  return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
558
910
  }
559
911
 
912
+ /**
913
+ * @overload last
914
+ * Position the cursor to the last record in the database, and
915
+ * return its value.
916
+ * @return [Array,nil] The [key, value] pair for the last record, or
917
+ * nil if no record.
918
+ */
560
919
  static VALUE cursor_last(VALUE self) {
561
920
  CURSOR(self, cursor);
562
921
  MDB_val key, value;
@@ -565,6 +924,13 @@ static VALUE cursor_last(VALUE self) {
565
924
  return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
566
925
  }
567
926
 
927
+ /**
928
+ * @overload prev
929
+ * Position the cursor to the previous record in the database, and
930
+ * return its value.
931
+ * @return [Array,nil] The [key, value] pair for the previous record, or
932
+ * nil if no previous record.
933
+ */
568
934
  static VALUE cursor_prev(VALUE self) {
569
935
  CURSOR(self, cursor);
570
936
  MDB_val key, value;
@@ -576,6 +942,13 @@ static VALUE cursor_prev(VALUE self) {
576
942
  return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
577
943
  }
578
944
 
945
+ /**
946
+ * @overload next
947
+ * Position the cursor to the next record in the database, and
948
+ * return its value.
949
+ * @return [Array,nil] The [key, value] pair for the next record, or
950
+ * nil if no next record.
951
+ */
579
952
  static VALUE cursor_next(VALUE self) {
580
953
  CURSOR(self, cursor);
581
954
  MDB_val key, value;
@@ -587,6 +960,12 @@ static VALUE cursor_next(VALUE self) {
587
960
  return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
588
961
  }
589
962
 
963
+ /**
964
+ * @overload set(key)
965
+ * Set the cursor to a specified key
966
+ * @param key The key to which the cursor should be positioned
967
+ * @return [Array] The [key, value] pair to which the cursor now points.
968
+ */
590
969
  static VALUE cursor_set(VALUE self, VALUE vkey) {
591
970
  CURSOR(self, cursor);
592
971
  MDB_val key, value;
@@ -598,6 +977,12 @@ static VALUE cursor_set(VALUE self, VALUE vkey) {
598
977
  return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
599
978
  }
600
979
 
980
+ /**
981
+ * @overload set_range(key)
982
+ * Set the cursor at the first key greater than or equal to a specified key.
983
+ * @param key The key to which the cursor should be positioned
984
+ * @return [Array] The [key, value] pair to which the cursor now points.
985
+ */
601
986
  static VALUE cursor_set_range(VALUE self, VALUE vkey) {
602
987
  CURSOR(self, cursor);
603
988
  MDB_val key, value;
@@ -609,6 +994,12 @@ static VALUE cursor_set_range(VALUE self, VALUE vkey) {
609
994
  return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
610
995
  }
611
996
 
997
+ /**
998
+ * @overload get
999
+ * Return the value of the record to which the cursor points.
1000
+ * @return [Array] The [key, value] pair for the current record.
1001
+ */
1002
+
612
1003
  static VALUE cursor_get(VALUE self) {
613
1004
  CURSOR(self, cursor);
614
1005
 
@@ -626,6 +1017,37 @@ static VALUE cursor_get(VALUE self) {
626
1017
  #undef METHOD
627
1018
  #undef FILE
628
1019
 
1020
+ /**
1021
+ * @overload put(key, value, options)
1022
+ * Store by cursor. This function stores key/data pairs into the
1023
+ * database. If the function fails for any reason, the state of
1024
+ * the cursor will be unchanged. If the function succeeds and an
1025
+ * item is inserted into the database, the cursor is always
1026
+ * positioned to refer to the newly inserted item.
1027
+ * @return nil
1028
+ * @param key The key of the record to set
1029
+ * @param value The value to insert for this key
1030
+ * @option options [Boolean] :current Overwrite the data of the
1031
+ * key/data pair to which the cursor refers with the specified
1032
+ * data item. The +key+ parameter is ignored.
1033
+ * @option options [Boolean] :nodupdata Enter the new key/value
1034
+ * pair only if it does not already appear in the database. This
1035
+ * flag may only be specified if the database was opened with
1036
+ * +:dupsort+. The function will raise an {Error} if the
1037
+ * key/data pair already appears in the database.
1038
+ * @option options [Boolean] :nooverwrite Enter the new key/value
1039
+ * pair only if the key does not already appear in the
1040
+ * database. The function will raise an {Error] if the key
1041
+ * already appears in the database, even if the database
1042
+ * supports duplicates (+:dupsort+).
1043
+ * @option options [Boolean] :append Append the given key/data pair
1044
+ * to the end of the database. No key comparisons are
1045
+ * performed. This option allows fast bulk loading when keys are
1046
+ * already known to be in the correct order. Loading unsorted
1047
+ * keys with this flag will cause data corruption.
1048
+ * @option options [Boolean] :appenddup As above, but for sorted dup
1049
+ * data.
1050
+ */
629
1051
  static VALUE cursor_put(int argc, VALUE* argv, VALUE self) {
630
1052
  CURSOR(self, cursor);
631
1053
 
@@ -655,6 +1077,14 @@ static VALUE cursor_put(int argc, VALUE* argv, VALUE self) {
655
1077
  #undef METHOD
656
1078
  #undef FILE
657
1079
 
1080
+ /**
1081
+ * @overload delete(options)
1082
+ * Delete current key/data pair.
1083
+ * This function deletes the key/data pair to which the cursor refers.
1084
+ * @option options [Boolean] :nodupdata Delete all of the data
1085
+ * items for the current key. This flag may only be specified
1086
+ * if the database was opened with +:dupsort+.
1087
+ */
658
1088
  static VALUE cursor_delete(int argc, VALUE *argv, VALUE self) {
659
1089
  CURSOR(self, cursor);
660
1090
 
@@ -669,6 +1099,13 @@ static VALUE cursor_delete(int argc, VALUE *argv, VALUE self) {
669
1099
  return Qnil;
670
1100
  }
671
1101
 
1102
+ /**
1103
+ * @overload count
1104
+ * Return count of duplicates for current key. This call is only
1105
+ * valid on databases that support sorted duplicate data items
1106
+ * +:dupsort+.
1107
+ * @return [Number] count of duplicates
1108
+ */
672
1109
  static VALUE cursor_count(VALUE self) {
673
1110
  CURSOR(self, cursor);
674
1111
  size_t count;
@@ -679,6 +1116,12 @@ static VALUE cursor_count(VALUE self) {
679
1116
  void Init_lmdb_ext() {
680
1117
  VALUE mLMDB;
681
1118
 
1119
+ /**
1120
+ * Document-module: LMDB
1121
+ *
1122
+ * The LMDB module presents a Ruby API to the OpenLDAP Lightning Memory-mapped Database (LMDB).
1123
+ * @see http://symas.com/mdb/
1124
+ */
682
1125
  mLMDB = rb_define_module("LMDB");
683
1126
  rb_define_const(mLMDB, "LIB_VERSION", rb_str_new2(MDB_VERSION_STRING));
684
1127
  rb_define_singleton_method(mLMDB, "new", environment_new, -1);
@@ -689,11 +1132,40 @@ void Init_lmdb_ext() {
689
1132
  VERSION_CONST(PATCH)
690
1133
  #undef VERSION_CONST
691
1134
 
1135
+ /**
1136
+ * Document-class: LMDB::Error
1137
+ *
1138
+ * A general class of exceptions raised within the LMDB gem.
1139
+ */
692
1140
  cError = rb_define_class_under(mLMDB, "Error", rb_eRuntimeError);
693
1141
  #define ERROR(name) cError_##name = rb_define_class_under(cError, #name, cError);
694
1142
  #include "errors.h"
695
1143
  #undef ERROR
696
1144
 
1145
+ /**
1146
+ * Document-class: LMDB::Environment
1147
+ *
1148
+ * The Environment is the root object for all LMDB operations.
1149
+ *
1150
+ * An LMDB "environment" is a collection of one or more "databases"
1151
+ * (key-value tables), along with transactions to modify those
1152
+ * databases and cursors to iterate through them.
1153
+ *
1154
+ * An environment -- and its collection of databases -- is normally
1155
+ * stored in a directory. That directory will contain two files:
1156
+ * * +data.mdb+: all the records in all the databases in the environment
1157
+ * * +lock.mdb+: state of transactions that may be going on in the environment.
1158
+ *
1159
+ * An environment can contain multiple databases. Each of the
1160
+ * databases has a string name ("mydatabase", "db.3.1982"). You use
1161
+ * the database name to open the database within the environment.
1162
+ *
1163
+ * @example The normal pattern for using LMDB in Ruby
1164
+ * env = LMDB.new "databasedir"
1165
+ * db = env.database "databasename"
1166
+ * # ... do things to the database ...
1167
+ * env.close
1168
+ */
697
1169
  cEnvironment = rb_define_class_under(mLMDB, "Environment", rb_cObject);
698
1170
  rb_define_singleton_method(cEnvironment, "new", environment_new, -1);
699
1171
  rb_define_method(cEnvironment, "database", environment_database, -1);
@@ -709,6 +1181,31 @@ void Init_lmdb_ext() {
709
1181
  rb_define_method(cEnvironment, "path", environment_path, 0);
710
1182
  rb_define_method(cEnvironment, "transaction", environment_transaction, -1);
711
1183
 
1184
+ /**
1185
+ * Document-class: LMDB::Database
1186
+ *
1187
+ * An LMDB Database is a table of key-value pairs. It is stored as
1188
+ * part of the {Environment}.
1189
+ *
1190
+ * By default, each key in a Database maps to one value. However, a
1191
+ * Database can be configured at creation to allow duplicate keys, in
1192
+ * which case one key will map to multiple values.
1193
+ *
1194
+ * A Database stores the keys in a sorted order. The order can also
1195
+ * be set with options when the database is created.
1196
+ *
1197
+ * The basic operations on a database are to {#put}, {#get}, and
1198
+ * {#delete} records. One can also iterate through the records in a
1199
+ * database using a {Cursor}.
1200
+ *
1201
+ * @example Typical usage
1202
+ * env = LMDB.new "databasedir"
1203
+ * db = env.database "databasename"
1204
+ * db.put "key1", "value1"
1205
+ * db.put "key2", "value2"
1206
+ * db.get "key1" #=> "value1"
1207
+ * env.close
1208
+ */
712
1209
  cDatabase = rb_define_class_under(mLMDB, "Database", rb_cObject);
713
1210
  rb_undef_method(rb_singleton_class(cDatabase), "new");
714
1211
  rb_define_method(cDatabase, "stat", database_stat, 0);
@@ -719,11 +1216,94 @@ void Init_lmdb_ext() {
719
1216
  rb_define_method(cDatabase, "delete", database_delete, -1);
720
1217
  rb_define_method(cDatabase, "cursor", database_cursor, 0);
721
1218
 
1219
+ /**
1220
+ * Document-class: LMDB::Transaction
1221
+ *
1222
+ * The LMDB environment supports transactional reads and updates. By
1223
+ * default, these provide the standard ACID (atomicity, consistency,
1224
+ * isolation, durability) behaviors.
1225
+ *
1226
+ * Transactions can be committed or aborted. When a transaction is
1227
+ * committed, all its effects take effect in the database atomically.
1228
+ * When a transaction is aborted, none of its effects take effect.
1229
+ *
1230
+ * Transactions span the entire environment. All the updates made in
1231
+ * the course of an update transaction -- writing records across all
1232
+ * databases, creating databases, and destroying databases -- are
1233
+ * either completed atomically or rolled back.
1234
+ *
1235
+ * Transactions can be nested. A child transaction can be started
1236
+ * within a parent transaction. The child transaction can commit or
1237
+ * abort, at which point the effects of the child become visible to
1238
+ * the parent transaction or not. If the parent aborts, all of the
1239
+ * changes performed in the context of the parent -- including the
1240
+ * changes from a committed child transaction -- are rolled back.
1241
+ *
1242
+ * To create a transaction, call {Environment#transaction} and supply
1243
+ * a block for the code to execute in that transaction.
1244
+ *
1245
+ * @example Typical usage
1246
+ * env = LMDB.new "databasedir"
1247
+ * db1 = env.database "database1"
1248
+ * env.transaction do |parent|
1249
+ * db2 = env.database "database2", :create => true
1250
+ * #=> creates a new database, but it isn't
1251
+ * #=> yet committed to storage
1252
+ * db1['x'] #=> nil
1253
+ * env.transaction do |child1|
1254
+ * db2['a'] = 'b'
1255
+ * db1['x'] = 'y'
1256
+ * end
1257
+ * #=> first child transaction commits
1258
+ * #=> changes are visible within the parent transaction
1259
+ * #=> but are not yet permanent
1260
+ * db1['x'] #=> 'y'
1261
+ * db2['a'] #=> 'a'
1262
+ * env.transaction do |child2|
1263
+ * db2['a'] = 'def'
1264
+ * db1['x'] = 'ghi'
1265
+ * child2.abort
1266
+ * #=> second child transaction aborts and rolls
1267
+ * #=> back its changes
1268
+ * end
1269
+ * db1['x'] #=> 'y'
1270
+ * db2['a'] #=> 'a'
1271
+ * end
1272
+ * #=> parent transaction commits and writes database2
1273
+ * #=> and the updates from transaction child1 to
1274
+ * #=> storage.
1275
+ */
722
1276
  cTransaction = rb_define_class_under(mLMDB, "Transaction", rb_cObject);
723
1277
  rb_undef_method(rb_singleton_class(cTransaction), "new");
724
1278
  rb_define_method(cTransaction, "commit", transaction_commit, 0);
725
1279
  rb_define_method(cTransaction, "abort", transaction_abort, 0);
726
1280
 
1281
+ /**
1282
+ * Document-class: LMDB::Cursor
1283
+ *
1284
+ * A Cursor points to records in a database, and is used to iterate
1285
+ * through the records in the database.
1286
+ *
1287
+ * Cursors are created in the context of a transaction, and should
1288
+ * only be used as long as that transaction is active. In other words,
1289
+ * after you {Transaction#commit} or {Transaction#abort} a transaction,
1290
+ * the cursors created while that transaction was active are no longer
1291
+ * usable.
1292
+ *
1293
+ * To create a cursor, call {Database#cursor} and pass it a block for
1294
+ * that should be performed using the cursor.
1295
+ *
1296
+ * @example Typical usage
1297
+ * env = LMDB.new "databasedir"
1298
+ * db = env.database "databasename"
1299
+ * db.cursor do |cursor|
1300
+ * rl = cursor.last #=> content of the last record
1301
+ * r1 = cursor.first #=> content of the first record
1302
+ * r2 = cursor.next #=> content of the second record
1303
+ * cursor.put "x", "y", current: true
1304
+ * #=> replaces the second record with a new value "y"
1305
+ * end
1306
+ */
727
1307
  cCursor = rb_define_class_under(mLMDB, "Cursor", rb_cObject);
728
1308
  rb_undef_method(rb_singleton_class(cCursor), "new");
729
1309
  rb_define_method(cCursor, "close", cursor_close, 0);
@@ -734,7 +1314,7 @@ void Init_lmdb_ext() {
734
1314
  rb_define_method(cCursor, "prev", cursor_prev, 0);
735
1315
  rb_define_method(cCursor, "set", cursor_set, 1);
736
1316
  rb_define_method(cCursor, "set_range", cursor_set_range, 1);
737
- rb_define_method(cCursor, "put", cursor_put, 0);
1317
+ rb_define_method(cCursor, "put", cursor_put, -1);
738
1318
  rb_define_method(cCursor, "count", cursor_count, 0);
739
- rb_define_method(cCursor, "delete", cursor_delete, 0);
1319
+ rb_define_method(cCursor, "delete", cursor_delete, -1);
740
1320
  }
data/lib/lmdb/database.rb CHANGED
@@ -2,6 +2,14 @@ module LMDB
2
2
  class Database
3
3
  include Enumerable
4
4
 
5
+ # Iterate through the records in a database
6
+ # @yield [i] Gives a record [key, value] to the block
7
+ # @yieldparam [Array] i The key, value pair for each record
8
+ # @example
9
+ # db.each do |record|
10
+ # key, value = record
11
+ # puts "at #{key}: #{value}"
12
+ # end
5
13
  def each
6
14
  cursor do |c|
7
15
  while i = c.next
@@ -10,15 +18,30 @@ module LMDB
10
18
  end
11
19
  end
12
20
 
21
+ # Retrieve the value of a record from a database
22
+ # @param key the record key to retrieve
23
+ # @return value of the record for that key, or nil if there is
24
+ # no record with that key
25
+ # @see #get(key)
13
26
  def [](key)
14
27
  get(key)
15
28
  end
16
29
 
30
+ # Set (write or update) a record in a database.
31
+ # @param key key for the record
32
+ # @param value the value of the record
33
+ # @return returns the value of the record
34
+ # @see #put(key, value)
35
+ # @example
36
+ # db['a'] = 'b' #=> 'b'
37
+ # db['b'] = 1234 #=> 1234
38
+ # db['a'] #=> 'b'
17
39
  def []=(key, value)
18
40
  put(key, value)
19
41
  value
20
42
  end
21
43
 
44
+ # @return the number of records in this database
22
45
  def size
23
46
  stat[:entries]
24
47
  end
data/lib/lmdb/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module LMDB
2
- VERSION = '0.4.0'
2
+ VERSION = '0.4.1'
3
3
  end
metadata CHANGED
@@ -1,55 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lmdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Mendler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-05 00:00:00.000000000 Z
11
+ date: 2014-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake-compiler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - <=
31
+ - - "<="
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.8.2
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - <=
38
+ - - "<="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.8.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  description: lmdb is a Ruby binding to OpenLDAP Lightning MDB.
@@ -59,8 +59,8 @@ extensions:
59
59
  - ext/lmdb_ext/extconf.rb
60
60
  extra_rdoc_files: []
61
61
  files:
62
- - .gitignore
63
- - .travis.yml
62
+ - ".gitignore"
63
+ - ".travis.yml"
64
64
  - CHANGES
65
65
  - CONTRIBUTORS
66
66
  - Gemfile
@@ -101,17 +101,17 @@ require_paths:
101
101
  - lib
102
102
  required_ruby_version: !ruby/object:Gem::Requirement
103
103
  requirements:
104
- - - '>='
104
+ - - ">="
105
105
  - !ruby/object:Gem::Version
106
106
  version: '0'
107
107
  required_rubygems_version: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - '>='
109
+ - - ">="
110
110
  - !ruby/object:Gem::Version
111
111
  version: '0'
112
112
  requirements: []
113
113
  rubyforge_project:
114
- rubygems_version: 2.0.14
114
+ rubygems_version: 2.2.0
115
115
  signing_key:
116
116
  specification_version: 4
117
117
  summary: Ruby bindings to Lightning MDB