lmdb 0.3.1 → 0.4.0

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.
@@ -59,7 +59,7 @@ unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id )
59
59
  return cursor;
60
60
  }
61
61
  }
62
-
62
+
63
63
  if( val > 0 ) {
64
64
  ++cursor;
65
65
  }
@@ -89,7 +89,7 @@ int mdb_midl_insert( MDB_IDL ids, MDB_ID id )
89
89
  /* no room */
90
90
  --ids[0];
91
91
  return -2;
92
-
92
+
93
93
  } else {
94
94
  /* insert id */
95
95
  for (i=ids[0]; i>x; i--)
@@ -203,7 +203,7 @@ int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n )
203
203
  /* Quicksort + Insertion sort for small arrays */
204
204
 
205
205
  #define SMALL 8
206
- #define SWAP(a,b) { itmp=(a); (a)=(b); (b)=itmp; }
206
+ #define MIDL_SWAP(a,b) { itmp=(a); (a)=(b); (b)=itmp; }
207
207
 
208
208
  void
209
209
  mdb_midl_sort( MDB_IDL ids )
@@ -231,15 +231,15 @@ mdb_midl_sort( MDB_IDL ids )
231
231
  l = istack[jstack--];
232
232
  } else {
233
233
  k = (l + ir) >> 1; /* Choose median of left, center, right */
234
- SWAP(ids[k], ids[l+1]);
234
+ MIDL_SWAP(ids[k], ids[l+1]);
235
235
  if (ids[l] < ids[ir]) {
236
- SWAP(ids[l], ids[ir]);
236
+ MIDL_SWAP(ids[l], ids[ir]);
237
237
  }
238
238
  if (ids[l+1] < ids[ir]) {
239
- SWAP(ids[l+1], ids[ir]);
239
+ MIDL_SWAP(ids[l+1], ids[ir]);
240
240
  }
241
241
  if (ids[l] < ids[l+1]) {
242
- SWAP(ids[l], ids[l+1]);
242
+ MIDL_SWAP(ids[l], ids[l+1]);
243
243
  }
244
244
  i = l+1;
245
245
  j = ir;
@@ -248,7 +248,7 @@ mdb_midl_sort( MDB_IDL ids )
248
248
  do i++; while(ids[i] > a);
249
249
  do j--; while(ids[j] < a);
250
250
  if (j < i) break;
251
- SWAP(ids[i],ids[j]);
251
+ MIDL_SWAP(ids[i],ids[j]);
252
252
  }
253
253
  ids[l+1] = ids[j];
254
254
  ids[j] = a;
@@ -39,7 +39,7 @@ extern "C" {
39
39
  /** @defgroup idls ID List Management
40
40
  * @{
41
41
  */
42
- /** A generic ID number. These were entryIDs in back-bdb.
42
+ /** A generic unsigned ID number. These were entryIDs in back-bdb.
43
43
  * Preferably it should have the same size as a pointer.
44
44
  */
45
45
  typedef size_t MDB_ID;
@@ -16,20 +16,12 @@ static void check(int code) {
16
16
  rb_raise(cError, "%s", err); /* fallback */
17
17
  }
18
18
 
19
- static void transaction_deref(Transaction* transaction) {
20
- if (--transaction->refcount == 0) {
21
- Environment* env = (Environment*)DATA_PTR(transaction->env);
22
- environment_deref(env);
23
- if (!NIL_P(transaction->parent)) {
24
- Transaction* parent = (Transaction*)DATA_PTR(transaction->parent);
25
- transaction_deref(parent);
26
- }
27
- if (transaction->txn) {
28
- rb_warn("Garbage collecting active transaction!");
29
- mdb_txn_abort(transaction->txn);
30
- }
31
- free(transaction);
19
+ static void transaction_free(Transaction* transaction) {
20
+ if (transaction->txn) {
21
+ rb_warn("Memory leak - Garbage collecting active transaction");
22
+ //mdb_txn_abort(transaction->txn);
32
23
  }
24
+ free(transaction);
33
25
  }
34
26
 
35
27
  static void transaction_mark(Transaction* transaction) {
@@ -71,6 +63,7 @@ static void transaction_finish(VALUE self, int commit) {
71
63
  else
72
64
  mdb_txn_abort(transaction->txn);
73
65
 
66
+ // Mark child transactions as closed
74
67
  p = environment_active_txn(transaction->env);
75
68
  while (p != self) {
76
69
  TRANSACTION(p, txn);
@@ -108,21 +101,13 @@ static VALUE with_transaction(VALUE venv, VALUE(*fn)(VALUE), VALUE arg, int flag
108
101
  check(mdb_txn_begin(environment->env, active_txn(venv), flags, &txn));
109
102
 
110
103
  Transaction* transaction;
111
- VALUE vtxn = Data_Make_Struct(cTransaction, Transaction, transaction_mark, transaction_deref, transaction);
112
- transaction->refcount = 1;
104
+ VALUE vtxn = Data_Make_Struct(cTransaction, Transaction, transaction_mark, transaction_free, transaction);
113
105
  transaction->parent = environment_active_txn(venv);
114
106
  transaction->env = venv;
115
107
  transaction->txn = txn;
116
108
  transaction->thread = rb_thread_current();
117
109
  environment_set_active_txn(venv, transaction->thread, vtxn);
118
110
 
119
- if (!NIL_P(transaction->parent)) {
120
- TRANSACTION(transaction->parent, parent);
121
- ++parent->refcount;
122
- }
123
-
124
- ++environment->refcount;
125
-
126
111
  int exception;
127
112
  VALUE ret = rb_protect(fn, NIL_P(arg) ? vtxn : arg, &exception);
128
113
 
@@ -141,12 +126,12 @@ static void environment_check(Environment* environment) {
141
126
  rb_raise(cError, "Environment is closed");
142
127
  }
143
128
 
144
- static void environment_deref(Environment *environment) {
145
- if (--environment->refcount == 0) {
146
- if (environment->env)
147
- mdb_env_close(environment->env);
148
- free(environment);
129
+ static void environment_free(Environment *environment) {
130
+ if (environment->env) {
131
+ rb_warn("Memory leak - Garbage collecting open environment");
132
+ //mdb_env_close(environment->env);
149
133
  }
134
+ free(environment);
150
135
  }
151
136
 
152
137
 
@@ -262,9 +247,8 @@ static VALUE environment_new(int argc, VALUE *argv, VALUE klass) {
262
247
  check(mdb_env_create(&env));
263
248
 
264
249
  Environment* environment;
265
- VALUE venv = Data_Make_Struct(cEnvironment, Environment, environment_mark, environment_deref, environment);
250
+ VALUE venv = Data_Make_Struct(cEnvironment, Environment, environment_mark, environment_free, environment);
266
251
  environment->env = env;
267
- environment->refcount = 1;
268
252
  environment->thread_txn_hash = rb_hash_new();
269
253
  environment->txn_thread_hash = rb_hash_new();
270
254
 
@@ -379,14 +363,6 @@ static VALUE environment_transaction(int argc, VALUE *argv, VALUE self) {
379
363
  return with_transaction(self, rb_yield, Qnil, flags);
380
364
  }
381
365
 
382
- static void database_deref(Database* database) {
383
- if (--database->refcount == 0) {
384
- Environment* env = (Environment*)DATA_PTR(database->env);
385
- environment_deref(env);
386
- free(database);
387
- }
388
- }
389
-
390
366
  static void database_mark(Database* database) {
391
367
  rb_gc_mark(database->env);
392
368
  }
@@ -413,11 +389,9 @@ static VALUE environment_database(int argc, VALUE *argv, VALUE self) {
413
389
  check(mdb_dbi_open(need_txn(self), NIL_P(name) ? 0 : StringValueCStr(name), flags, &dbi));
414
390
 
415
391
  Database* database;
416
- VALUE vdb = Data_Make_Struct(cDatabase, Database, database_mark, database_deref, database);
392
+ VALUE vdb = Data_Make_Struct(cDatabase, Database, database_mark, free, database);
417
393
  database->dbi = dbi;
418
394
  database->env = self;
419
- database->refcount = 1;
420
- ++environment->refcount;
421
395
 
422
396
  return vdb;
423
397
  }
@@ -524,10 +498,11 @@ static VALUE database_delete(int argc, VALUE *argv, VALUE self) {
524
498
  }
525
499
 
526
500
  static void cursor_free(Cursor* cursor) {
527
- if (cursor->cur)
528
- mdb_cursor_close(cursor->cur);
501
+ if (cursor->cur) {
502
+ rb_warn("Memory leak - Garbage collecting open cursor");
503
+ //mdb_cursor_close(cursor->cur);
504
+ }
529
505
 
530
- database_deref((Database*)DATA_PTR(cursor->db));
531
506
  free(cursor);
532
507
  }
533
508
 
@@ -559,7 +534,6 @@ static VALUE database_cursor(VALUE self) {
559
534
  VALUE vcur = Data_Make_Struct(cCursor, Cursor, cursor_mark, cursor_free, cursor);
560
535
  cursor->cur = cur;
561
536
  cursor->db = self;
562
- ++database->refcount;
563
537
 
564
538
  if (rb_block_given_p()) {
565
539
  int exception;
@@ -583,6 +557,14 @@ static VALUE cursor_first(VALUE self) {
583
557
  return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
584
558
  }
585
559
 
560
+ static VALUE cursor_last(VALUE self) {
561
+ CURSOR(self, cursor);
562
+ MDB_val key, value;
563
+
564
+ check(mdb_cursor_get(cursor->cur, &key, &value, MDB_LAST));
565
+ return rb_assoc_new(rb_str_new(key.mv_data, key.mv_size), rb_str_new(value.mv_data, value.mv_size));
566
+ }
567
+
586
568
  static VALUE cursor_prev(VALUE self) {
587
569
  CURSOR(self, cursor);
588
570
  MDB_val key, value;
@@ -738,7 +720,7 @@ void Init_lmdb_ext() {
738
720
  rb_define_method(cDatabase, "cursor", database_cursor, 0);
739
721
 
740
722
  cTransaction = rb_define_class_under(mLMDB, "Transaction", rb_cObject);
741
- rb_undef_method(rb_singleton_class(cCursor), "new");
723
+ rb_undef_method(rb_singleton_class(cTransaction), "new");
742
724
  rb_define_method(cTransaction, "commit", transaction_commit, 0);
743
725
  rb_define_method(cTransaction, "abort", transaction_abort, 0);
744
726
 
@@ -747,6 +729,7 @@ void Init_lmdb_ext() {
747
729
  rb_define_method(cCursor, "close", cursor_close, 0);
748
730
  rb_define_method(cCursor, "get", cursor_get, 0);
749
731
  rb_define_method(cCursor, "first", cursor_first, 0);
732
+ rb_define_method(cCursor, "last", cursor_last, 0);
750
733
  rb_define_method(cCursor, "next", cursor_next, 0);
751
734
  rb_define_method(cCursor, "prev", cursor_prev, 0);
752
735
  rb_define_method(cCursor, "set", cursor_set, 1);
@@ -42,25 +42,22 @@
42
42
  Data_Get_Struct(var, Cursor, var_cur); \
43
43
  cursor_check(var_cur)
44
44
 
45
- typedef struct Transaction {
45
+ typedef struct {
46
46
  VALUE env;
47
47
  VALUE parent;
48
48
  VALUE thread;
49
49
  MDB_txn* txn;
50
- int refcount;
51
50
  } Transaction;
52
51
 
53
52
  typedef struct {
54
53
  MDB_env* env;
55
54
  VALUE thread_txn_hash;
56
55
  VALUE txn_thread_hash;
57
- int refcount;
58
56
  } Environment;
59
57
 
60
58
  typedef struct {
61
59
  VALUE env;
62
60
  MDB_dbi dbi;
63
- int refcount;
64
61
  } Database;
65
62
 
66
63
  typedef struct {
@@ -102,6 +99,7 @@ static VALUE cursor_delete(int argc, VALUE *argv, VALUE self);
102
99
  static VALUE cursor_first(VALUE self);
103
100
  static void cursor_free(Cursor* cursor);
104
101
  static VALUE cursor_get(VALUE self);
102
+ static VALUE cursor_last(VALUE self);
105
103
  static void cursor_mark(Cursor* cursor);
106
104
  static VALUE cursor_next(VALUE self);
107
105
  static VALUE cursor_prev(VALUE self);
@@ -111,7 +109,6 @@ static VALUE cursor_set_range(VALUE self, VALUE vkey);
111
109
  static VALUE database_clear(VALUE self);
112
110
  static VALUE database_cursor(VALUE self);
113
111
  static VALUE database_delete(int argc, VALUE *argv, VALUE self);
114
- static void database_deref(Database* database);
115
112
  static VALUE database_drop(VALUE self);
116
113
  static VALUE database_get(VALUE self, VALUE vkey);
117
114
  static void database_mark(Database* database);
@@ -124,8 +121,8 @@ static VALUE environment_clear_flags(int argc, VALUE* argv, VALUE self);
124
121
  static VALUE environment_close(VALUE self);
125
122
  static VALUE environment_copy(VALUE self, VALUE path);
126
123
  static VALUE environment_database(int argc, VALUE *argv, VALUE self);
127
- static void environment_deref(Environment *environment);
128
124
  static VALUE environment_flags(VALUE self);
125
+ static void environment_free(Environment *environment);
129
126
  static VALUE environment_info(VALUE self);
130
127
  static void environment_mark(Environment* environment);
131
128
  static VALUE environment_new(int argc, VALUE *argv, VALUE klass);
@@ -140,8 +137,8 @@ static MDB_txn* need_txn(VALUE self);
140
137
  static VALUE stat2hash(const MDB_stat* stat);
141
138
  static VALUE transaction_abort(VALUE self);
142
139
  static VALUE transaction_commit(VALUE self);
143
- static void transaction_deref(Transaction* transaction);
144
140
  static void transaction_finish(VALUE self, int commit);
141
+ static void transaction_free(Transaction* transaction);
145
142
  static void transaction_mark(Transaction* transaction);
146
143
  static VALUE with_transaction(VALUE venv, VALUE(*fn)(VALUE), VALUE arg, int flags);
147
144
  // END PROTOTYPES
data/lib/lmdb/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module LMDB
2
- VERSION = '0.3.1'
2
+ VERSION = '0.4.0'
3
3
  end
data/spec/lmdb_spec.rb CHANGED
@@ -251,12 +251,18 @@ describe LMDB do
251
251
  db.put('key2', 'value2')
252
252
  end
253
253
 
254
- it 'should get next key/value' do
254
+ it 'should get first key/value' do
255
255
  db.cursor do |c|
256
256
  c.first.should == ['key1', 'value1']
257
257
  end
258
258
  end
259
259
 
260
+ it 'should get last key/value' do
261
+ db.cursor do |c|
262
+ c.last.should == ['key2', 'value2']
263
+ end
264
+ end
265
+
260
266
  it 'should get next key/value' do
261
267
  db.cursor do |c|
262
268
  c.first
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lmdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Mendler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-01 00:00:00.000000000 Z
11
+ date: 2014-01-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -111,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
111
  version: '0'
112
112
  requirements: []
113
113
  rubyforge_project:
114
- rubygems_version: 2.0.3
114
+ rubygems_version: 2.0.14
115
115
  signing_key:
116
116
  specification_version: 4
117
117
  summary: Ruby bindings to Lightning MDB