lmdb 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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