leveldb-native 0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 239b4f05b8dfe841e93f81d3c173a0eed17c6c5a
4
+ data.tar.gz: 5fa95a754b9c3b86912e2564b6f93e62b43bf5c6
5
+ SHA512:
6
+ metadata.gz: 2578c6532e99ccfb04b1111fc04d148f1ed5959c56d6ff3c10452b42f964d09ea813171662146782e2db35f647fa9e61a162192da84900cdf1927dcacb252613
7
+ data.tar.gz: 67f52e24344fb62ee720c680bb78eccb03b2044cdfd3e2f393a8e14493e8bada443d7ab8f6e0b5b327e1a8d2d4bab00658341c9a34dcd64818dcd256d4c3b1ab
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Joel VanderWerf
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ ruby-leveldb-native
2
+ ===================
3
+
4
+ A ruby binding to levelDB. It is native in two senses:
5
+
6
+ 1. Uses libleveldb as a C/C++ ruby extension, rather than through FFI.
7
+
8
+ 2. Uses the natively installed libleveldb, rather than trying to build and install libleveldb as part of the gem.
9
+
10
+ LevelDB
11
+ -------
12
+
13
+ [LevelDB] (http://code.google.com/p/leveldb/) is a persistent key-value store developed at Google.
14
+
15
+ Installation
16
+ ------------
17
+
18
+ The gem installs in the normal way:
19
+
20
+ gem install leveldb-native
21
+
22
+ However, you need to have libleveldb installed. It may be available as part of your OS (from debian repos, for example), or you may prefer to install from source. The source packages from google do not have install scripts, but that is easy to fix. Here is a git repo with the necessary fixes to the makefile:
23
+
24
+ https://github.com/vjoel/leveldb
25
+
26
+ Just follow the instructions in that repo's README to build and install.
27
+
28
+ FAQ
29
+ ---
30
+
31
+ 1. Why not use the [leveldb gem] (https://github.com/DAddYE/leveldb) instead?
32
+
33
+ 1. Doesn't support the full functionality of snapshots. Snapshots in this gem can only be used to switch the state of the DB object, but not act as independent and concurrent readable views of the database at different points in time.
34
+
35
+ 2. Tries to maintain its own installation of libleveldb, which may be a different version from the system-wide installation.
36
+
37
+ 3. Accesses the lib using FFI, which is slower than ruby's native extension architecture. (See benchmarks at the link above.)
38
+
39
+ 2. Why not use the [leveldb-ruby gem] (https://github.com/wmorgan/leveldb-ruby) instead?
40
+
41
+ 1. Not maintained regularly.
42
+
43
+ 2. Tries to maintain its own installation of libleveldb.
44
+
45
+ 3. No snapshots.
46
+
47
+ This gem attempts to maintain compatibility with the leveldb-ruby gem, while adding more features.
48
+
49
+ Acknowledgement
50
+ ---------------
51
+
52
+ This gem owes much to William Morgan's gem, https://github.com/wmorgan/leveldb-ruby.
53
+
54
+ Contact
55
+ -------
56
+
57
+ This project is hosted at https://github.com/vjoel/leveldb-native.
58
+
59
+ Joel VanderWerf, vjoel@users.sourceforge.net.
60
+
61
+ License and Copyright
62
+ ---------------------
63
+
64
+ Copyright (c) 2013, Joel VanderWerf.
65
+
66
+ Portions of ext/leveldb-native/leveldb-native.cc are copyright William Morgan.
67
+
68
+ License for this project is MIT. See the LICENSE file for the standard MIT license.
data/Rakefile ADDED
@@ -0,0 +1,65 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ PRJ = "leveldb-native"
5
+
6
+ def version
7
+ @version ||= begin
8
+ require 'leveldb-native/version'
9
+ warn "LevelDBNative::VERSION not a string" unless
10
+ LevelDBNative::VERSION.kind_of? String
11
+ LevelDBNative::VERSION
12
+ end
13
+ end
14
+
15
+ def tag
16
+ @tag ||= "#{PRJ}-#{version}"
17
+ end
18
+
19
+ desc "Run unit tests"
20
+ Rake::TestTask.new :test do |t|
21
+ t.libs << "lib"
22
+ t.libs << "ext"
23
+ t.test_files = FileList["test/*.rb"]
24
+ end
25
+
26
+ desc "Commit, tag, and push repo; build and push gem"
27
+ task :release => "release:is_new_version" do
28
+ require 'tempfile'
29
+
30
+ sh "gem build #{PRJ}.gemspec"
31
+
32
+ file = Tempfile.new "template"
33
+ begin
34
+ file.puts "release #{version}"
35
+ file.close
36
+ sh "git commit --allow-empty -a -v -t #{file.path}"
37
+ ensure
38
+ file.close unless file.closed?
39
+ file.unlink
40
+ end
41
+
42
+ sh "git tag #{tag}"
43
+ sh "git push"
44
+ sh "git push --tags"
45
+
46
+ sh "gem push #{tag}.gem"
47
+ end
48
+
49
+ namespace :release do
50
+ desc "Diff to latest release"
51
+ task :diff do
52
+ latest = `git describe --abbrev=0 --tags --match '#{PRJ}-*'`.chomp
53
+ sh "git diff #{latest}"
54
+ end
55
+
56
+ desc "Log to latest release"
57
+ task :log do
58
+ latest = `git describe --abbrev=0 --tags --match '#{PRJ}-*'`.chomp
59
+ sh "git log #{latest}.."
60
+ end
61
+
62
+ task :is_new_version do
63
+ abort "#{tag} exists; update version!" unless `git tag -l #{tag}`.empty?
64
+ end
65
+ end
@@ -0,0 +1,33 @@
1
+ require 'leveldb-native'
2
+
3
+ db = LevelDBNative::DB.new '/tmp/leveldb-example-snapshot'
4
+
5
+ db["a"] = "1"
6
+ db["b"] = "1"
7
+ db.delete "c"
8
+ puts "initialized database to #{db.to_a}"
9
+ puts
10
+
11
+ puts "snapshot:"
12
+ db.snapshot do |sn|
13
+ puts "value at a is #{sn["a"]}"
14
+ sn.each {|k,v| puts " #{k} => #{v}"}
15
+ end
16
+ puts
17
+
18
+ sn = db.snapshot
19
+ puts "taking new snapshot"
20
+ db["b"] = "2"
21
+ puts "put 'b' => #{db["b"].inspect}"
22
+ db["c"] = "2"
23
+ puts "put 'c' => #{db["c"].inspect}"
24
+
25
+ puts "snapshot is: #{sn.to_a}"
26
+ puts "database is: #{db.to_a}"
27
+ puts
28
+
29
+ sn.release
30
+ puts "relasing snapshot (will now reflect current db state)"
31
+ puts "snapshot is: #{sn.to_a}"
32
+ puts "database is: #{db.to_a}"
33
+ puts
@@ -0,0 +1,5 @@
1
+ require 'mkmf'
2
+
3
+ have_library "leveldb" or abort "Can't find leveldb library."
4
+
5
+ create_makefile "leveldb_native"
@@ -0,0 +1,156 @@
1
+ require 'leveldb-native/leveldb_native'
2
+
3
+ module LevelDBNative
4
+ class DB
5
+ include Enumerable
6
+
7
+ class << self
8
+ # Loads or creates a database as necessary, stored on disk at
9
+ # +pathname+.
10
+ #
11
+ # See #make for possible options.
12
+ def new pathname, options={}
13
+ make path_string(pathname),
14
+ options.merge(:create_if_missing => true,
15
+ :error_if_exists => false)
16
+ end
17
+
18
+ # Creates a new database stored on disk at +pathname+. Raises
19
+ # LevelDBNative::Error if the database already exists.
20
+ #
21
+ # See #make for possible options.
22
+ def create pathname, options={}
23
+ make path_string(pathname),
24
+ options.merge(:create_if_missing => true,
25
+ :error_if_exists => true)
26
+ end
27
+
28
+ # Loads a database stored on disk at +pathname+. Raises
29
+ # LevelDBNative::Error unless the database already exists.
30
+ def load pathname
31
+ make path_string(pathname),
32
+ :create_if_missing => false, :error_if_exists => false
33
+ end
34
+
35
+ private
36
+
37
+ # Coerces the argument into a String for use as a filename/-path
38
+ def path_string pathname
39
+ File.respond_to?(:path) ? File.path(pathname) : pathname.to_str
40
+ end
41
+ end
42
+
43
+ attr_reader :pathname
44
+ attr_reader :options
45
+
46
+ alias :includes? :exists?
47
+ alias :contains? :exists?
48
+ alias :member? :exists?
49
+ alias :[] :get
50
+ alias :[]= :put
51
+ alias :close! :close
52
+
53
+ def each(*args, &block)
54
+ i = iterator(*args)
55
+ i.each(&block) if block
56
+ i
57
+ end
58
+
59
+ def iterator(*args); Iterator.new self, *args; end
60
+ def keys; map {|k, v| k} end
61
+ def values; map {|k, v| v} end
62
+
63
+ # If called with a block, yields a snapshot to the caller, and the
64
+ # snapshot is released after the block finishes. Otherwise, returns a
65
+ # snapshot and caller must call #release on the snapshot.
66
+ def snapshot(*args)
67
+ sn = Snapshot.new self, *args
68
+ if block_given?
69
+ begin
70
+ yield sn
71
+ ensure
72
+ sn.release
73
+ end
74
+ else
75
+ sn
76
+ end
77
+ end
78
+
79
+ def inspect
80
+ "<#{self.class} #{@pathname.inspect}>"
81
+ end
82
+ end
83
+
84
+ class Iterator
85
+ include Enumerable
86
+
87
+ attr_reader :db, :from, :to
88
+
89
+ def self.new(db, opts={})
90
+ make db, opts
91
+ end
92
+
93
+ def keys; map {|k, v| k} end
94
+ def values; map {|k, v| v} end
95
+
96
+ def reversed?; @reversed end
97
+ def inspect
98
+ "<#{self.class} #{db.inspect} " +
99
+ "@from=#{@from.inspect} @to=#{@to.inspect}#{' (reversed)' if @reversed}>"
100
+ end
101
+ end
102
+
103
+ class WriteBatch
104
+ class << self
105
+ private :new
106
+ end
107
+
108
+ alias :[]= :put
109
+ end
110
+
111
+ # Snapshot has the same API as DB, restricted to read access.
112
+ class Snapshot
113
+ include Enumerable
114
+
115
+ def self.new(db)
116
+ make db
117
+ end
118
+
119
+ def each(*args, &block)
120
+ i = iterator(*args)
121
+ i.each(&block) if block
122
+ i
123
+ end
124
+
125
+ def get(*args)
126
+ db.get(*args, snapshot: self)
127
+ end
128
+
129
+ alias :[] :get
130
+ alias :includes? :exists?
131
+ alias :contains? :exists?
132
+ alias :member? :exists?
133
+
134
+ def iterator(*args); db.iterator *args, snapshot: self; end
135
+ def keys; map {|k, v| k} end
136
+ def values; map {|k, v| v} end
137
+
138
+ def inspect
139
+ "<#{self.class} #{db.inspect} #{' (released)' if released?}>"
140
+ end
141
+ end
142
+
143
+ class Options
144
+ DEFAULT_MAX_OPEN_FILES = 1000
145
+ DEFAULT_WRITE_BUFFER_SIZE = 4 * 1024 * 1024
146
+ DEFAULT_BLOCK_SIZE = 4 * 1024
147
+ DEFAULT_BLOCK_RESTART_INTERVAL = 16
148
+ DEFAULT_COMPRESSION = LevelDBNative::CompressionType::SnappyCompression
149
+
150
+ attr_reader :create_if_missing, :error_if_exists,
151
+ :block_cache_size, :paranoid_checks,
152
+ :write_buffer_size, :max_open_files,
153
+ :block_size, :block_restart_interval,
154
+ :compression
155
+ end
156
+ end
@@ -0,0 +1,3 @@
1
+ module LevelDBNative
2
+ VERSION = "0.1"
3
+ end
@@ -0,0 +1,156 @@
1
+ require 'leveldb-native'
2
+ require 'tmpdir'
3
+ require 'minitest/autorun'
4
+
5
+ class TestDBOptions < Minitest::Test
6
+ include LevelDBNative
7
+
8
+ attr_reader :dir
9
+
10
+ def setup
11
+ @dir = Dir.mktmpdir "leveldb-test-db-options-"
12
+ end
13
+
14
+ def teardown
15
+ FileUtils.remove_entry @dir
16
+ end
17
+
18
+ def test_create_if_missing_behavior
19
+ assert_raises(Error) do
20
+ DB.make(dir, {}) # create_if_missing is false
21
+ end
22
+ db = DB.make dir, :create_if_missing => true
23
+ assert db.options.create_if_missing
24
+ db.close!
25
+
26
+ db2 = DB.make dir, {}
27
+ refute db2.options.create_if_missing
28
+ db2.close!
29
+
30
+ FileUtils.rm_rf dir
31
+
32
+ DB.new dir # by default should set create_if_missing to true
33
+ end
34
+
35
+ def test_error_if_exists_behavior
36
+ db = DB.make dir, :create_if_missing => true
37
+ refute db.options.error_if_exists
38
+ db.close!
39
+
40
+ assert_raises(Error) do
41
+ DB.make dir, :create_if_missing => true, :error_if_exists => true
42
+ end
43
+ end
44
+
45
+ def test_paranoid_check_default
46
+ db = DB.new dir
47
+ refute db.options.paranoid_checks
48
+ end
49
+
50
+ def test_paranoid_check_on
51
+ db = DB.new dir, :paranoid_checks => true
52
+ assert db.options.paranoid_checks
53
+ end
54
+
55
+ def test_paranoid_check_off
56
+ db = DB.new dir, :paranoid_checks => false
57
+ refute db.options.paranoid_checks
58
+ end
59
+
60
+ def test_write_buffer_size_default
61
+ db = DB.new dir
62
+ assert_equal Options::DEFAULT_WRITE_BUFFER_SIZE,
63
+ db.options.write_buffer_size
64
+ end
65
+
66
+ def test_write_buffer_size
67
+ db = DB.new dir, :write_buffer_size => 10 * 1042
68
+ assert_equal (10 * 1042), db.options.write_buffer_size
69
+ end
70
+
71
+ def test_write_buffer_size_invalid
72
+ assert_raises(TypeError) do
73
+ DB.new dir, :write_buffer_size => "1234"
74
+ end
75
+ end
76
+
77
+ def test_max_open_files_default
78
+ db = DB.new dir
79
+ assert_equal Options::DEFAULT_MAX_OPEN_FILES, db.options.max_open_files
80
+ end
81
+
82
+ def test_max_open_files
83
+ db = DB.new(dir, :max_open_files => 2000)
84
+ assert_equal db.options.max_open_files, 2000
85
+ end
86
+
87
+ def test_max_open_files_invalid
88
+ assert_raises(TypeError) do
89
+ DB.new dir, :max_open_files => "2000"
90
+ end
91
+ end
92
+
93
+ def test_cache_size_default
94
+ db = DB.new dir
95
+ assert_nil db.options.block_cache_size
96
+ end
97
+
98
+ def test_cache_size
99
+ db = DB.new dir, :block_cache_size => 10 * 1024 * 1024
100
+ assert_equal (10 * 1024 * 1024), db.options.block_cache_size
101
+ end
102
+
103
+ def test_cache_size_invalid
104
+ assert_raises(TypeError) do
105
+ DB.new dir, :block_cache_size => false
106
+ end
107
+ end
108
+
109
+ def test_block_size_default
110
+ db = DB.new dir
111
+ assert_equal Options::DEFAULT_BLOCK_SIZE, db.options.block_size
112
+ end
113
+
114
+ def test_block_size
115
+ db = DB.new dir, :block_size => (2 * 1024)
116
+ assert_equal (2 * 1024), db.options.block_size
117
+ end
118
+
119
+ def test_block_size_invalid
120
+ assert_raises(TypeError) do
121
+ DB.new dir, :block_size => true
122
+ end
123
+ end
124
+
125
+ def test_block_restart_interval_default
126
+ db = DB.new dir
127
+ assert_equal Options::DEFAULT_BLOCK_RESTART_INTERVAL,
128
+ db.options.block_restart_interval
129
+ end
130
+
131
+ def test_block_restart_interval
132
+ db = DB.new dir, :block_restart_interval => 32
133
+ assert_equal 32, db.options.block_restart_interval
134
+ end
135
+
136
+ def test_block_restart_interval_invalid
137
+ assert_raises(TypeError) do
138
+ DB.new dir, :block_restart_interval => "abc"
139
+ end
140
+ end
141
+
142
+ def test_compression_default
143
+ db = DB.new dir
144
+ assert_equal Options::DEFAULT_COMPRESSION, db.options.compression
145
+ end
146
+
147
+ def test_compression
148
+ db = DB.new dir, :compression => CompressionType::NoCompression
149
+ assert_equal CompressionType::NoCompression, db.options.compression
150
+ end
151
+
152
+ def test_compression_invalid_type
153
+ assert_raises(TypeError) { DB.new dir, :compression => "1234" }
154
+ assert_raises(TypeError) { DB.new dir, :compression => 999 }
155
+ end
156
+ end
data/test/test-db.rb ADDED
@@ -0,0 +1,53 @@
1
+ require 'leveldb-native'
2
+ require 'tmpdir'
3
+ require 'minitest/autorun'
4
+
5
+ class TestDB < Minitest::Test
6
+ include LevelDBNative
7
+
8
+ attr_reader :db
9
+
10
+ def setup
11
+ @dir = Dir.mktmpdir "leveldb-test-db-"
12
+ @db = DB.new @dir
13
+ end
14
+
15
+ def teardown
16
+ FileUtils.remove_entry @dir
17
+ end
18
+
19
+ def test_size
20
+ 1000.times { |x| db.put x.to_s, "foo" }
21
+ assert_equal 1000, db.size
22
+ 1000.times { |x| db.delete x.to_s}
23
+ assert_equal 0, db.size
24
+ end
25
+
26
+ def test_operations
27
+ refute db.exists?("k")
28
+
29
+ db["k"] = "v"
30
+ assert_equal "v", db["k"]
31
+ assert db.exists?("k")
32
+
33
+ db.delete "k"
34
+ assert_equal nil, db["k"]
35
+ refute db.exists?("k")
36
+ end
37
+
38
+ ## how to test that fill_cache, verify_checksums, sync are getting passed to
39
+ ## the C++ lib?
40
+
41
+ def test_batch
42
+ db['k0'] = '0'
43
+ db['k1'] = '0'
44
+
45
+ db.batch do |batch|
46
+ batch['k0'] = '1'
47
+ batch.delete 'k1'
48
+ end
49
+
50
+ assert_equal '1', db['k0']
51
+ refute db.exists? 'k1'
52
+ end
53
+ end
@@ -0,0 +1,104 @@
1
+ require 'leveldb-native'
2
+ require 'tmpdir'
3
+ require 'minitest/autorun'
4
+
5
+ class TestIterator < Minitest::Test
6
+ include LevelDBNative
7
+
8
+ attr_reader :db
9
+
10
+ KEYS = (0..9).map {|ki| ki.to_s}
11
+
12
+ def setup
13
+ @dir = Dir.mktmpdir "leveldb-test-iterator-"
14
+ @db = DB.new @dir
15
+
16
+ KEYS.each_with_index do |k, vi|
17
+ db[k] = vi.to_s
18
+ end
19
+ end
20
+
21
+ def teardown
22
+ FileUtils.remove_entry @dir
23
+ end
24
+
25
+ def test_each
26
+ db.each_with_index do |(k, v), i|
27
+ assert_equal i.to_s, k
28
+ assert_equal i.to_s, v
29
+ end
30
+ end
31
+
32
+ def test_from
33
+ k = 5
34
+ a = db.each(:from => k.to_s).keys
35
+ assert_equal KEYS[k..-1], a
36
+ end
37
+
38
+ def test_to
39
+ k = 5
40
+ a = db.each(:to => k.to_s).keys
41
+ assert_equal KEYS[0..k], a
42
+ end
43
+
44
+ def test_from_to
45
+ k0 = 5; k1 = 8
46
+ a = db.each(:from => k0.to_s, :to => k1.to_s).keys
47
+ assert_equal KEYS[k0..k1], a
48
+ end
49
+
50
+ def test_reverse_each
51
+ assert_equal KEYS.reverse, db.each(:reversed => true).keys
52
+ end
53
+
54
+ def test_reverse_from
55
+ k = 5
56
+ a = db.each(:reversed => true, :from => k.to_s).keys
57
+ assert_equal KEYS[0..k].reverse, a
58
+ end
59
+
60
+ def test_reverse_to
61
+ k = 5
62
+ a = db.each(:reversed => true, :to => k.to_s).keys
63
+ assert_equal KEYS[k..-1].reverse, a
64
+ end
65
+
66
+ def test_reverse_from_to
67
+ k0 = 5; k1 = 8
68
+ a = db.each(:reversed => true, :from => k1.to_s, :to => k0.to_s).keys
69
+ assert_equal KEYS[k0..k1].reverse, a
70
+ end
71
+
72
+ def test_iterator_peek
73
+ iter = db.iterator
74
+ assert_equal %w(0 0), iter.peek, iter.invalid_reason
75
+ assert_equal %w(0 0), iter.peek, iter.invalid_reason
76
+ assert_nil iter.scan
77
+ assert_equal %w(1 1), iter.peek, iter.invalid_reason
78
+ end
79
+
80
+ def test_iterator_init_with_default_options
81
+ iter = db.iterator
82
+ assert_equal db, iter.db
83
+ assert_nil iter.from
84
+ assert_nil iter.to
85
+ refute iter.reversed?
86
+ end
87
+
88
+ def test_iterator_init_with_options
89
+ iter = db.iterator :from => 'abc', :to => 'def', :reversed => true
90
+ assert_equal db,iter.db
91
+ assert_equal 'abc', iter.from
92
+ assert_equal 'def', iter.to
93
+ assert iter.reversed?
94
+ end
95
+
96
+ def test_iterator_not_valid
97
+ iter = db.iterator from: KEYS[-1]
98
+ assert_nil iter.invalid_reason
99
+ assert_equal %w{9 9}, iter.next
100
+ assert_equal -1, iter.invalid_reason
101
+ assert_equal nil, iter.next
102
+ assert_equal -1, iter.invalid_reason
103
+ end
104
+ end
@@ -0,0 +1,77 @@
1
+ require 'leveldb-native'
2
+ require 'tmpdir'
3
+ require 'minitest/autorun'
4
+
5
+ class TestSnapshot < Minitest::Test
6
+ include LevelDBNative
7
+
8
+ attr_reader :db
9
+
10
+ KEYS = %w{ k1 k2 k3 }
11
+
12
+ def setup
13
+ @dir = Dir.mktmpdir "leveldb-test-snapshot-"
14
+ @db = DB.new @dir
15
+
16
+ KEYS.each do |k|
17
+ db[k] = "0"
18
+ end
19
+ end
20
+
21
+ def teardown
22
+ FileUtils.remove_entry @dir
23
+ end
24
+
25
+ def test_get
26
+ sn = db.snapshot
27
+ KEYS.each do |k|
28
+ db[k] = "1"
29
+ end
30
+ KEYS.each do |k|
31
+ assert_equal "0", sn[k]
32
+ end
33
+ end
34
+
35
+ def test_iterator
36
+ sn = db.snapshot
37
+ KEYS.each do |k|
38
+ db[k] = "1"
39
+ end
40
+ sn.each do |k,v|
41
+ assert_equal "0", v
42
+ end
43
+ assert_equal KEYS, sn.keys
44
+ assert_equal ["0"], sn.values.uniq
45
+ end
46
+
47
+ def test_exists
48
+ sn = db.snapshot
49
+ db["new"] = "new"
50
+ db.delete "k1"
51
+ assert_equal false, sn.exists?( "new" )
52
+ assert_equal true, sn.exists?( "k1" )
53
+ assert_equal true, db.exists?( "new" )
54
+ assert_equal false, db.exists?( "k1" )
55
+
56
+ sn.release
57
+ assert_equal true, sn.exists?( "new" )
58
+ assert_equal false, sn.exists?( "k1" )
59
+ assert_equal true, db.exists?( "new" )
60
+ assert_equal false, db.exists?( "k1" )
61
+ end
62
+
63
+ def test_release
64
+ sn = db.snapshot
65
+ KEYS.each do |k|
66
+ db[k] = "1"
67
+ end
68
+
69
+ assert_equal false, sn.released?
70
+ sn.release
71
+ assert_equal true, sn.released?
72
+
73
+ sn.each do |k,v|
74
+ assert_equal "1", v
75
+ end
76
+ end
77
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: leveldb-native
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Joel VanderWerf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-07 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Ruby binding to LevelDB.
14
+ email: vjoel@users.sourceforge.net
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files:
18
+ - README.md
19
+ - LICENSE
20
+ files:
21
+ - README.md
22
+ - LICENSE
23
+ - Rakefile
24
+ - lib/leveldb-native.rb
25
+ - lib/leveldb-native/version.rb
26
+ - ext/leveldb-native/extconf.rb
27
+ - example/snapshot.rb
28
+ - test/test-db.rb
29
+ - test/test-db-options.rb
30
+ - test/test-snapshot.rb
31
+ - test/test-iterator.rb
32
+ homepage: https://github.com/vjoel/ruby-leveldb-native
33
+ licenses:
34
+ - MIT
35
+ metadata: {}
36
+ post_install_message:
37
+ rdoc_options:
38
+ - "--quiet"
39
+ - "--line-numbers"
40
+ - "--inline-source"
41
+ - "--title"
42
+ - LevelDB Native
43
+ - "--main"
44
+ - README.md
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ requirements: []
58
+ rubyforge_project:
59
+ rubygems_version: 2.1.10
60
+ signing_key:
61
+ specification_version: 4
62
+ summary: Ruby binding to LevelDB.
63
+ test_files:
64
+ - test/test-db.rb
65
+ - test/test-db-options.rb
66
+ - test/test-snapshot.rb
67
+ - test/test-iterator.rb
68
+ has_rdoc: