lmdb 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
metadata CHANGED
@@ -1,11 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lmdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Mendler
8
- - Black Square Media
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
@@ -61,6 +60,7 @@ extensions:
61
60
  extra_rdoc_files: []
62
61
  files:
63
62
  - .gitignore
63
+ - .travis.yml
64
64
  - CHANGES
65
65
  - CONTRIBUTORS
66
66
  - Gemfile
@@ -77,16 +77,13 @@ files:
77
77
  - ext/lmdb_ext/liblmdb/midl.c
78
78
  - ext/lmdb_ext/liblmdb/midl.h
79
79
  - ext/lmdb_ext/lmdb_ext.c
80
+ - ext/lmdb_ext/lmdb_ext.h
81
+ - ext/lmdb_ext/prototypes.sh
80
82
  - lib/lmdb.rb
81
- - lib/lmdb/database.rb
82
- - lib/lmdb/environment.rb
83
83
  - lmdb.gemspec
84
- - spec/lmdb/database_spec.rb
85
- - spec/lmdb/environment_spec.rb
86
- - spec/lmdb/lmdb_ext_spec.rb
84
+ - spec/helper.rb
87
85
  - spec/lmdb_spec.rb
88
- - spec/spec_helper.rb
89
- homepage: https://github.com/minad/mdb
86
+ homepage: https://github.com/minad/lmdb
90
87
  licenses:
91
88
  - MIT
92
89
  metadata: {}
@@ -111,8 +108,5 @@ signing_key:
111
108
  specification_version: 4
112
109
  summary: Ruby bindings to Lightning MDB
113
110
  test_files:
114
- - spec/lmdb/database_spec.rb
115
- - spec/lmdb/environment_spec.rb
116
- - spec/lmdb/lmdb_ext_spec.rb
111
+ - spec/helper.rb
117
112
  - spec/lmdb_spec.rb
118
- - spec/spec_helper.rb
@@ -1,66 +0,0 @@
1
- class LMDB::Database
2
-
3
- class << self
4
- private :new
5
- end
6
-
7
- # @attr_reader [String] name
8
- attr_reader :name
9
-
10
- # @attr_reader [LMDB::Environment] env
11
- attr_reader :env
12
-
13
- # @param [LMDB::Environment] env
14
- # @param [String] name the DB name
15
- def initialize(env, name)
16
- @env = env
17
- @name = name.to_s
18
- end
19
-
20
- # Closes the DB, doesn't fail if already closed
21
- def close
22
- raw.close if loaded?
23
- end
24
-
25
- # Reads a key
26
- # @param [String] key
27
- def get(key)
28
- ensure_db!
29
- rtxn {|txn| raw.get(txn, key) }
30
- rescue LMDB::Ext::Error::NOTFOUND
31
- end
32
- alias_method :[], :get
33
-
34
- # Sets a key to a new value
35
- # @param [String] key
36
- # @param [String] value
37
- def set(key, value)
38
- ensure_db!
39
- rtxn {|txn| raw.put(txn, key, value) }
40
- end
41
- alias_method :put, :set
42
- alias_method :[]=, :set
43
-
44
- private
45
-
46
- def raw
47
- @raw ||= rtxn {|txn| renv.open(txn, name, LMDB::CREATE) }
48
- end
49
-
50
- def renv
51
- @renv ||= env.send(:raw)
52
- end
53
-
54
- def rtxn(&block)
55
- env.send(:rtxn, &block)
56
- end
57
-
58
- def loaded?
59
- !!@raw
60
- end
61
-
62
- def ensure_db!
63
- raw unless loaded?
64
- end
65
-
66
- end
@@ -1,135 +0,0 @@
1
- class LMDB::Environment
2
-
3
- DEFAULT_OPTS = {
4
- path: ".",
5
- mode: 0755,
6
- max_size: (2**28-1), # 4G
7
- # max_size: 1_000_000,
8
- max_dbs: 16,
9
- max_readers: 126,
10
- sub_dirs: true,
11
- read_only: false,
12
- mmap: false,
13
- sync: true,
14
- meta_sync: false
15
- }.freeze
16
-
17
- INFO_MAP = {
18
- mapaddr: :address,
19
- mapsize: :max_size,
20
- last_pgno: :last_page,
21
- last_txnid: :last_transaction_id,
22
- maxreaders: :maxreaders,
23
- numreaders: :readers
24
- }.freeze
25
-
26
- STAT_MAP = {
27
- psize: :page_size,
28
- depth: :depth,
29
- branch_pages: :branch_pages,
30
- leaf_pages: :leaf_pages,
31
- overflow_pages: :overflow_pages,
32
- entries: :entries
33
- }.freeze
34
-
35
- # @attr_reader [String] path environment path
36
- attr_reader :path
37
-
38
- # Constructor, opens an environment
39
- #
40
- # @param [Hash] opts options
41
- # @option opts [String] :path
42
- # the environment path, defaults to current path
43
- # @option opts [String] :mode
44
- # the file mode, defaults to 0755
45
- # @option opts [Integer] :max_size
46
- # the maximum environment size in bytes, defaults to 4G
47
- # @option opts [Integer] :max_dbs
48
- # the maximum number of databases, defaults to 16
49
- # @option opts [Integer] :max_readers
50
- # the maximum number of readers, defaults to 126
51
- # @option opts [Boolean] :sub_dirs
52
- # allow subdirectories, defaults to true
53
- # @option opts [Boolean] :read_only
54
- # open in read-only mode, defaults to false
55
- # @option opts [Boolean] :mmap
56
- # use memory map, faster, but less durable, incompatible with nested transactions, defaults to false
57
- # @option opts [Boolean] :sync
58
- # flushes system buffers at the end of a transaction; slower, but more durable, defaults to true
59
- # @option opts [Boolean] :meta_sync
60
- # flush system buffers on every write and not only at the end of a transaction; slower, but more durable, defaults to false
61
- # @raises [LMDB::Error] on errors
62
- def initialize(opts = {})
63
- opts = DEFAULT_OPTS.merge(opts)
64
- @path = opts[:path].to_s
65
- @raw = LMDB::Ext::Environment.open path, parse(opts)
66
- end
67
-
68
- # Manually sync the environment
69
- #
70
- # @param [Hash] opts options
71
- # @option opts [Boolean] :force force sync, default false
72
- # @return [Boolean] true if successful
73
- # @raises [LMDB::Error] on errors
74
- def sync(opts = {})
75
- @raw.sync !!opts[:force]
76
- true
77
- end
78
-
79
- # @return [Hash] environment info & stats
80
- def info
81
- info, stat = @raw.info, @raw.stat
82
- hash = {}
83
- INFO_MAP.each {|m, f| hash[f] = info.send(m) }
84
- STAT_MAP.each {|m, f| hash[f] = stat.send(m) }
85
- hash
86
- end
87
-
88
- # TODO: Thread-safe global transactions
89
- #
90
- # Executes a transaction
91
- # @yield a transaction
92
- # @yieldparam [LMDB::Transaction] txn the transaction instance
93
- # def transaction(&block)
94
- # LMDB::Transaction.send(:new, self, &block)
95
- # end
96
-
97
- # Opens a database
98
- # @param [String] name
99
- # @return [LMDB::Database] the database
100
- def database(name)
101
- LMDB::Database.send(:new, self, name)
102
- end
103
- alias_method :db, :database
104
-
105
- # @return [String] introspection
106
- def inspect
107
- "#<#{self.class.name} @path=#{path.inspect}>"
108
- end
109
-
110
- private
111
-
112
- def raw
113
- @raw
114
- end
115
-
116
- def rtxn(&block)
117
- @raw.transaction(&block)
118
- end
119
-
120
- def parse(opts)
121
- flags = 0
122
- flags |= LMDB::NOSUBDIR unless opts[:sub_dirs]
123
- flags |= LMDB::RDONLY if opts[:read_only]
124
- flags |= LMDB::WRITEMAP if opts[:mmap]
125
- flags |= LMDB::NOSYNC unless opts[:sync]
126
- flags |= LMDB::NOMETASYNC unless opts[:meta_sync]
127
-
128
- { flags: flags,
129
- mode: opts[:mode],
130
- maxreaders: opts[:max_readers].to_i,
131
- mapsize: opts[:max_size].to_i,
132
- maxdbs: opts[:max_dbs].to_i }
133
- end
134
-
135
- end
@@ -1,23 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe LMDB::Database do
4
-
5
- subject { env.db(:pets) }
6
- after { subject.close }
7
-
8
- its(:name) { should == "pets" }
9
- its(:env) { should == env }
10
-
11
- it 'should get/set data' do
12
- subject.get("cat").should be_nil
13
- subject.set("cat", "garfield").should be_nil
14
- subject.get("cat").should == "garfield"
15
- end
16
-
17
- it 'should get/set data' do
18
- subject.get("cat").should be_nil
19
- subject.set("cat", "garfield").should be_nil
20
- subject.get("cat").should == "garfield"
21
- end
22
-
23
- end
@@ -1,22 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe LMDB::Environment do
4
-
5
- subject { env }
6
-
7
- it { should be_instance_of(described_class) }
8
- its(:path) { should be_instance_of(String) }
9
- its(:info) { should be_instance_of(Hash) }
10
- its("info.keys") { should =~ [:address, :branch_pages, :depth, :entries, :last_page, :last_transaction_id, :leaf_pages, :max_size, :maxreaders, :overflow_pages, :page_size, :readers] }
11
-
12
- it 'should sync' do
13
- subject.sync.should be(true)
14
- subject.sync(force: true).should be(true)
15
- end
16
-
17
- it 'should open databases' do
18
- subject.database(:pets).should be_instance_of(LMDB::Database)
19
- subject.db(:pets).should be_instance_of(LMDB::Database)
20
- end
21
-
22
- end
@@ -1,253 +0,0 @@
1
- require 'spec_helper'
2
-
3
- shared_examples "an environment" do
4
- describe 'open' do
5
- it 'returns environment' do
6
- env = subject.open(path)
7
- env.should be_instance_of(described_class::Environment)
8
- env.close
9
- end
10
-
11
- it 'accepts block' do
12
- subject.open(path) do |env|
13
- env.should be_instance_of(described_class::Environment)
14
- 42
15
- end.should == 42
16
- end
17
-
18
- it 'accepts options' do
19
- env = subject.open(path, :flags => LMDB::NOSYNC, :mode => 0777, :maxreaders => 777, :mapsize => 111111, :maxdbs => 666)
20
- env.should be_instance_of(described_class::Environment)
21
- env.info.maxreaders.should == 777
22
- env.info.mapsize.should == 111111
23
- env.close
24
- end
25
- end
26
- end
27
-
28
- describe LMDB::Ext do
29
-
30
- let(:env) { LMDB::Ext.open(path) }
31
- after { env.close }
32
-
33
- it_behaves_like "an environment" do
34
- subject { LMDB::Ext }
35
- end
36
-
37
- describe "Stat" do
38
- subject { env.stat }
39
-
40
- it { should be_instance_of(described_class::Stat) }
41
- its(:psize) { should be_instance_of(Fixnum) }
42
- its(:depth) { should be_instance_of(Fixnum) }
43
- its(:branch_pages) { should be_instance_of(Fixnum) }
44
- its(:leaf_pages) { should be_instance_of(Fixnum) }
45
- its(:overflow_pages) { should be_instance_of(Fixnum) }
46
- its(:entries) { should be_instance_of(Fixnum) }
47
- end
48
-
49
- describe "Info" do
50
- subject { env.info }
51
-
52
- it { should be_instance_of(described_class::Info) }
53
- its(:mapaddr) { should be_instance_of(Fixnum) }
54
- its(:mapsize) { should be_instance_of(Fixnum) }
55
- its(:last_pgno) { should be_instance_of(Fixnum) }
56
- its(:last_txnid) { should be_instance_of(Fixnum) }
57
- its(:maxreaders) { should be_instance_of(Fixnum) }
58
- its(:numreaders) { should be_instance_of(Fixnum) }
59
- end
60
-
61
- describe "Environment" do
62
- it_behaves_like "an environment" do
63
- subject { described_class::Environment }
64
- end
65
-
66
- subject { env }
67
-
68
- its(:path) { should == path }
69
- its(:flags) { should == 0 }
70
-
71
- it 'should copy' do
72
- target = mkpath('copy')
73
- subject.copy(target).should be_nil
74
- end
75
-
76
- it 'should sync' do
77
- subject.sync.should be_nil
78
- end
79
-
80
- it 'should force-sync' do
81
- subject.sync(true).should be_nil
82
- end
83
-
84
- it 'should accept custom flags' do
85
- (subject.flags = LMDB::NOSYNC).should == LMDB::NOSYNC
86
- subject.flags.should == LMDB::NOSYNC
87
-
88
- (subject.flags = 0).should == 0
89
- subject.flags.should == 0
90
- end
91
-
92
- it 'should create transactions' do
93
- txn = subject.transaction
94
- txn.should be_instance_of(described_class::Transaction)
95
- txn.parent.should be_nil
96
- txn.environment.should == subject
97
- txn.abort
98
- end
99
-
100
- it 'should create read-only transactions' do
101
- txn = subject.transaction(true)
102
- txn.should be_instance_of(described_class::Transaction)
103
- txn.abort
104
- end
105
-
106
- it 'should create transactions blocks' do
107
- subject.transaction do |txn|
108
- txn.should be_instance_of(described_class::Transaction)
109
- txn.environment.should == subject
110
- txn.parent.should be_nil
111
- end
112
- end
113
- end
114
-
115
- describe "Transaction" do
116
- subject { env.transaction }
117
- after { subject.abort rescue nil }
118
-
119
- its(:environment) { should == env }
120
- its(:parent) { should be_nil }
121
-
122
- it 'can create child transactions' do
123
- txn = subject.transaction
124
- txn.should be_instance_of(described_class::Transaction)
125
- txn.parent.should == subject
126
- txn.environment.should == env
127
- txn.abort
128
- end
129
-
130
- it 'can create block transactions' do
131
- subject.transaction do |txn|
132
- txn.should be_instance_of(described_class::Transaction)
133
- txn.parent.should == subject
134
- end
135
- end
136
- end
137
-
138
- describe "Database" do
139
-
140
- subject do
141
- env.transaction do |txn|
142
- env.open(txn, 'db', LMDB::CREATE)
143
- end
144
- end
145
- let!(:db) { subject }
146
- after { subject.close rescue nil }
147
-
148
- it 'stores key/values in same transaction' do
149
- env.transaction do |txn|
150
- db.put(txn, 'key', 'value').should be_nil
151
- db.get(txn, 'key').should == 'value'
152
- end
153
- end
154
-
155
- it 'stores key/values in different transactions' do
156
- env.transaction do |txn|
157
- db.put(txn, 'key', 'value').should be_nil
158
- end
159
-
160
- env.transaction do |txn|
161
- db.get(txn, 'key').should == 'value'
162
- end
163
- end
164
-
165
- it 'should return cursor' do
166
- env.transaction do |txn|
167
- cursor = db.cursor(txn)
168
- cursor.should be_instance_of(described_class::Cursor)
169
- cursor.close
170
- end
171
- end
172
-
173
- it 'should return stat' do
174
- env.transaction do |txn|
175
- db.stat(txn).should be_instance_of(described_class::Stat)
176
- end
177
- end
178
-
179
- it 'should close' do
180
- db.close.should be_nil
181
- -> { db.close }.should raise_error(LMDB::Ext::Error, /closed/)
182
- end
183
-
184
- it "should be correctly GC'd", segfault: true do
185
- db = env.transaction {|t| env.open(t, 'db', LMDB::CREATE) }
186
- db = nil
187
- GC.start
188
- db = env.transaction {|t| env.open(t, 'db', LMDB::CREATE) }
189
- end
190
-
191
- end
192
-
193
- describe "Cursor" do
194
-
195
- let! :db do
196
- env.transaction {|txn| env.open(txn, 'db', LMDB::CREATE) }
197
- end
198
-
199
- before do
200
- env.transaction do |txn|
201
- db.put(txn, 'key1', 'value1')
202
- db.put(txn, 'key2', 'value2')
203
- end
204
- end
205
-
206
- after do
207
- db.close
208
- end
209
-
210
- def with_cursor
211
- env.transaction do |txn|
212
- cursor = db.cursor(txn)
213
- begin
214
- yield cursor
215
- ensure
216
- cursor.close
217
- end
218
- end
219
- end
220
-
221
- it 'should get next key/value' do
222
- with_cursor do |c|
223
- c.first.should == ['key1', 'value1']
224
- end
225
- end
226
-
227
- it 'should get next key/value' do
228
- with_cursor do |c|
229
- c.first
230
- c.next.should == ['key2', 'value2']
231
- end
232
- end
233
-
234
- it 'should seek to key' do
235
- with_cursor do |c|
236
- c.set('key1').should == ['key1', 'value1']
237
- end
238
- end
239
-
240
- it 'should seek to closest key' do
241
- with_cursor do |c|
242
- c.set_range('key0').should == ['key1', 'value1']
243
- end
244
- end
245
-
246
- it 'should seek to key with nuls' do
247
- with_cursor do |c|
248
- c.set_range("\x00").should == ['key1', 'value1']
249
- end
250
- end
251
-
252
- end
253
- end