rocksdb-ruby 0.2.3 → 1.0.0

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: e63a830799d975bd61b019413c022b2dd2c2b996
4
- data.tar.gz: 4629fb74bd9ff28fdcc4654656410b729033d3e0
3
+ metadata.gz: ff03f629257fdb8ac8848e41458d5d1eb585f815
4
+ data.tar.gz: acec6cb4441abdd687337be38eec30be8c74fb49
5
5
  SHA512:
6
- metadata.gz: 8cd31b6afd9fc8c84638b1e37325a753e1f2a4bde49e48697f993bcf65b71c6c480b89fde2ee303a3ec1ec9b52339081508809aef6be0a31ede97cf8747191da
7
- data.tar.gz: 4dec517e5bcc0d8c6b82c1c5a02c43643a9e0bd8e4fa1174d62730ed6c91e950e395957249e6adeb0b4bdb451faffe300b997c8ffe70a6b99c6f5c2337918cbc
6
+ metadata.gz: 7688c4b6bcbe355a87e23a4a28923ac9d6fac529330be380b3c7fbebec5b9b6517ae311bc52e7cc6dc85eb2f6954c5014e1c530b8e11b1729ea12561c1751a2a
7
+ data.tar.gz: fc91395d2ddee8543e1dcd438658ab147c21f9414855ece7649ef12ad87dc552cc5f2d46f3ef25653e701bdf420636712da4efb1131ce8b9ddc97e57d4f9a0c3
data/.gitignore CHANGED
@@ -15,3 +15,7 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ ext/**/*.o
19
+ ext/**/Makefile
20
+ ext/**/*.log
21
+ ext/**/*.bundle
@@ -1,22 +1,60 @@
1
1
  language: ruby
2
+ script: bundle exec rake spec
3
+
2
4
  rvm:
3
- - 2.4.0
4
- script: bundle exec rake spec || ( cat ext/rocksdb/mkmf.log && /bin/false )
5
+ - 2.4
6
+ - 2.5
7
+ - 2.6
8
+
9
+ os:
10
+ - linux
11
+ - osx
12
+
13
+ # We can use this matrix to pick supported versions
14
+ # https://repology.org/project/rocksdb/versions
15
+ jobs:
16
+ include:
17
+ - os: linux
18
+ env: ROCKSDB_VERSION=6.3.6
19
+ - os: linux
20
+ env: ROCKSDB_VERSION=5.17.2
21
+ - os: linux
22
+ env: ROCKSDB_VERSION=4.5.1
23
+ - os: osx
24
+ env: ROCKSDB_VERSION=5.18.3 ROCKSDB_VERSION_COMMIT=d38e4b445ea1525fba69b1d7b88dc63e9faaa21b
25
+ - os: osx
26
+ env: ROCKSDB_VERSION=6.1.2 ROCKSDB_VERSION_COMMIT=6e35266c1f6b7bab9ed4371e5cf9f1cfca0566b7
27
+
28
+ cache:
29
+ ccache: true
30
+ bundler: true
31
+ directories:
32
+ - /home/travis/.ccache
33
+
34
+ addons:
35
+ apt:
36
+ sources:
37
+ - sourceline: 'ppa:ubuntu-toolchain-r/test'
38
+ packages:
39
+ - gdb
40
+ - gcc-8
41
+ - g++-8
42
+ - libbz2-dev
43
+ - zlib1g-dev
44
+ - libgflags-dev
45
+ - libsnappy-dev
46
+
47
+ before_script:
48
+ # enable core dumps
49
+ - ulimit -c unlimited -S
5
50
 
6
51
  before_install:
7
- - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
8
- - sudo apt-get update -qq
9
- - sudo apt-get install gcc-6 g++-6 libsnappy-dev zlib1g-dev libbz2-dev -qq
10
- - export CXX="g++-6" CC="gcc-6"
11
- - sudo ln -s /usr/bin/gcc-6 /usr/local/bin/gcc
12
- - sudo ln -s /usr/bin/g++-6 /usr/local/bin/g++
13
52
  - gem install bundler
14
53
 
15
54
  install:
16
- - git clone https://github.com/facebook/rocksdb.git /tmp/rocksdb
17
- - pushd /tmp/rocksdb
18
- - make clean
19
- - make shared_lib
20
- - popd
21
- - export ROCKSDB_RUBY_BUILD_PARAMS="--with-rocksdb-dir=/tmp/rocksdb --with-rocksdb-lib=/tmp/rocksdb"
22
- - bundle install
55
+ - export ROCKSDB_FOLDER=/tmp/rocksdb/
56
+ - export ROCKSDB_RUBY_BUILD_PARAMS="--with-rocksdb-dir=$ROCKSDB_FOLDER --with-rocksdb-lib=$ROCKSDB_FOLDER"
57
+ - ./.travis/install.sh
58
+
59
+ after_failure:
60
+ - ./.travis/after_failure.sh
@@ -0,0 +1,16 @@
1
+ echo "---- mmkf.log ----"
2
+ cat ext/rocksdb/mkmf.log
3
+ echo "---- makefile ----"
4
+ cat ext/rocksdb/Makefile
5
+
6
+ if [ $TRAVIS_OS_NAME = 'linux' ]; then
7
+ # Show core dump contents and build configuration if any
8
+ COREFILE=$(find . -maxdepth 1 -name "core*" | head -n 1)
9
+ CORE_PROG=$(which ruby)
10
+ echo "---- gdb $CORE_PROG -c "$COREFILE" ----"
11
+ if [[ -f "$COREFILE" ]]; then
12
+ gdb $CORE_PROG -c "$COREFILE" -ex "thread apply all bt full" -ex "set pagination 0" -batch
13
+ fi
14
+ else
15
+ echo "Can't inspect coredump on ${TRAVIS_OS_NAME}"
16
+ fi
@@ -0,0 +1,55 @@
1
+ #!/bin/bash
2
+
3
+ # Fail if anything fails
4
+ set -e
5
+
6
+ if [[ $TRAVIS_OS_NAME == 'osx' ]]; then
7
+ # BUG: https://discourse.brew.sh/t/octave-require-relative-problem/6043
8
+ # BUG: https://travis-ci.community/t/homebrew-syntax-error/5623
9
+ export HOMEBREW_NO_AUTO_UPDATE=1
10
+
11
+ if [[ -z "${ROCKSDB_VERSION}" ]]; then
12
+ echo "Brewing latest available version"
13
+ brew install "rocksdb"
14
+ else
15
+ BREW_CORE_URI="https://raw.githubusercontent.com/Homebrew/homebrew-core"
16
+ FORMULA_URI="${BREW_CORE_URI}/${ROCKSDB_VERSION_COMMIT}/Formula/rocksdb.rb"
17
+ echo "Installing ${ROCKSDB_VERSION} from ${ROCKSDB_VERSION_COMMIT}"
18
+ brew install "${FORMULA_URI}"
19
+ brew switch rocksdb "${ROCKSDB_VERSION}"
20
+ fi
21
+
22
+ echo "Building bundle"
23
+ bundle install
24
+ elif [[ $TRAVIS_OS_NAME == 'linux' ]]; then
25
+ export PATH="/usr/lib/ccache/:$PATH"
26
+
27
+ if [[ -z "${ROCKSDB_VERSION}" ]]; then
28
+ echo "Building from rocksdb master in ${ROCKSDB_FOLDER}"
29
+ git clone -b "master" --single-branch --depth 1 https://github.com/facebook/rocksdb.git $ROCKSDB_FOLDER
30
+ else
31
+ echo "Building ${ROCKSDB_VERSION} in ${ROCKSDB_FOLDER}"
32
+ git clone -b "v$ROCKSDB_VERSION" --single-branch --depth 1 https://github.com/facebook/rocksdb.git $ROCKSDB_FOLDER
33
+ fi
34
+
35
+ pushd $ROCKSDB_FOLDER
36
+ ccache -s
37
+
38
+ if [[ $DEBUG_LEVEL == '1' ]]; then
39
+ echo "Building with DEBUG_LEVEL=1"
40
+ # TODO: I think it's better to try to satisfy all the rocksdb checks
41
+ make -j4 shared_lib DEBUG_LEVEL=1
42
+ else
43
+ make -j4 shared_lib
44
+ fi
45
+
46
+ ccache -s
47
+ popd
48
+
49
+ echo "Building bundle with params:"
50
+ echo "${ROCKSDB_RUBY_BUILD_PARAMS}"
51
+ bundle install
52
+ else
53
+ echo "Unsupported OS ${TRAVIS_OS_NAME}"
54
+ exit 1
55
+ fi
data/README.md CHANGED
@@ -11,7 +11,7 @@ This gem contains Ruby bindings so that you can use it from your Ruby process.
11
11
 
12
12
  ## Installation
13
13
 
14
- First install rocksdb.
14
+ First, install rocksdb: https://github.com/facebook/rocksdb/blob/master/INSTALL.md
15
15
 
16
16
  Add this line to your application's Gemfile:
17
17
 
@@ -31,49 +31,410 @@ Or install it yourself as:
31
31
  $ gem install rocksdb-ruby
32
32
  ```
33
33
 
34
+ `rocksdb-ruby` is tested against Ruby 2.4, 2.5 and 2.6 on Linux and macOS platforms. However, it might work on other platforms.
35
+
36
+ `rocksdb-ruby` supports rocksb 4.5.1 and later. It is tested against master branch with all supported ruby version. It is also tested against few specific version, available in popular distributions. Check `.travis.yml` for details.
37
+
38
+ JRuby, TruffleRuby and Rubinius are not supported at the moment.
39
+
34
40
  ## Usage
35
41
 
42
+
43
+ ### Open database
44
+
45
+ First, you need to open database. Use `open` method and pass path to database
46
+ root as first argument. By default, it will create path if missing.
47
+
48
+ ```ruby
49
+
50
+ require "rocksdb"
51
+
52
+ # Open for reads and writes
53
+ rocksdb = RocksDB.open "/tmp/file1"
54
+ ```
55
+
56
+ You can pass RocksDB options as second argument:
57
+
58
+ ```ruby
59
+
60
+ require "rocksdb"
61
+
62
+ # Open for reads and writes
63
+ rocksdb = RocksDB.open "/tmp/file2", compression: "kNoCompression"
64
+ ```
65
+
66
+ Or you can pass raw Option String:
67
+
68
+ ```ruby
69
+
70
+ require "rocksdb"
71
+
72
+ # Open for reads and writes
73
+ rocksdb = RocksDB.open "/tmp/file2", "compression=kNoCompression"
74
+ ```
75
+
76
+ Read more about Option Sting: https://github.com/facebook/rocksdb/wiki/Option-String-and-Option-Map#option-string
77
+
78
+ ### Basic reads and writes
79
+
80
+ You can read and write keys using `put` and `get` methods:
81
+
36
82
  ```ruby
37
- require "rocksdb"
38
83
 
39
- # Reads And Writes
40
- key = "test"
41
- value = "1"
42
- rocksdb = RocksDB::DB.new "/tmp/file"
43
- rocksdb.put(key, value)
44
- new_value = rocksdb.get(key)
45
- rocksdb.delete(key)
84
+ require "rocksdb"
46
85
 
47
- # Atomic Updates
48
- batch = RocksDB::Batch.new
49
- batch.delete("test:batch1")
50
- batch.put("test:batch2", "b")
51
- rocksdb.write(batch)
86
+ # Open for reads and writes
87
+ rocksdb = RocksDB.open "/tmp/file3"
52
88
 
53
- # Iteration
54
- iterator = rocksdb.new_iterator
89
+ # Store string `World` under key `Hello`
90
+ rocksdb.put "Hello", "World"
55
91
 
56
- iterator.seek_to_first
57
- while(iterator.valid)
58
- iterator.value
59
- iterator.key
60
- iterator.next
61
- end
62
- iterator.close
92
+ # Read a value stored under key `Hello`
93
+ puts rocksdb.get "Hello"
94
+ # => World
95
+ ```
63
96
 
64
- # Block
65
- rocksdb.each do |data|
66
- puts data
67
- end
97
+ You can also use Hash-like methods `[]` and `[]=`
68
98
 
69
- # Hash access
70
- rocksdb['key'] = data
71
- puts rocksdb['key']
99
+ ```ruby
100
+
101
+ require "rocksdb"
102
+
103
+ # Open for reads and writes
104
+ rocksdb = RocksDB.open "/tmp/file4"
72
105
 
106
+ # Store string `World` under key `Hello`
107
+ rocksdb["Hello"] = "World"
73
108
 
74
- rocksdb.close
109
+ # Read a value stored under key `Hello`
110
+ puts rocksdb["Hello"]
111
+ # => World
75
112
  ```
76
113
 
114
+ If key does not exists, RocksDB will return nil:
115
+
116
+ ```ruby
117
+
118
+ require "rocksdb"
119
+
120
+ # Open for reads and writes
121
+ rocksdb = RocksDB.open "/tmp/file5"
122
+
123
+ # Try to read a key, that does not exists
124
+ result = rocksdb.get "Missing Key"
125
+
126
+ if !result
127
+ puts "Key not found!"
128
+ end
129
+
130
+ # => Key not found
131
+ ```
132
+
133
+ If you want to get multiple keys at the same time, you can use `get` with multiple arguments:
134
+
135
+ ```ruby
136
+
137
+ require "rocksdb"
138
+
139
+ # Open for reads and writes
140
+ rocksdb = RocksDB.open "/tmp/file6"
141
+
142
+ rocksdb.put "First Key", "First Value"
143
+ rocksdb.put "Second Key", "Second Value"
144
+ rocksdb.put "Third Key", "Third Value"
145
+
146
+ # If key does not exists, you'll get nil
147
+ values = rocksdb.get "Second Key", "Imaginary Key", "Third Key"
148
+
149
+ puts values
150
+ # => ["Second Value", nil, "Third Value"]
151
+ ```
152
+
153
+ You can check, if key exists:
154
+
155
+ ```ruby
156
+
157
+ require "rocksdb"
158
+
159
+ # Open for reads and writes
160
+ rocksdb = RocksDB.open "/tmp/file7"
161
+
162
+ rocksdb.put "Real Key", "Real Value"
163
+
164
+ rocksdb.exists? "Real Key"
165
+ # => true
166
+
167
+ rocksdb.exists? "Imaginary Key"
168
+ # => false
169
+ ```
170
+
171
+ And you can delete keys, when not needed:
172
+
173
+ ```ruby
174
+
175
+ require "rocksdb"
176
+
177
+ # Open for reads and writes
178
+ rocksdb = RocksDB.open "/tmp/file8"
179
+
180
+ rocksdb.put "Delete Me", "Memory"
181
+ rocksdb.exists? "Delete Me"
182
+ # => true
183
+ rocksdb.delete "Delete Me"
184
+ rocksdb.exists? "Delete Me"
185
+ # => false
186
+
187
+ rocksdb.get "Delete Me"
188
+ # => nil
189
+ ```
190
+
191
+ You can open RocksDB only for reading:
192
+
193
+ ```ruby
194
+
195
+ require "rocksdb"
196
+
197
+ # Open only for reading
198
+ rocksdb = RocksDB.open_readonly "/tmp/file9"
199
+
200
+ puts rocksdb.writable?
201
+ # => false
202
+
203
+ rocksdb.put "First Key", "First Value"
204
+
205
+ # => RocksDB::ReadOnly (database is read-only)
206
+ ```
207
+
208
+
209
+ ### Enumerable
210
+
211
+ You can enumerate over all values using `each` method. Note how values are sorted lexicographically by their keys:
212
+
213
+ ```ruby
214
+
215
+ require "rocksdb"
216
+
217
+ # Open for reads and writes
218
+ rocksdb = RocksDB.open "/tmp/file10"
219
+
220
+ rocksdb.put "One", "1"
221
+ rocksdb.put "Two", "2"
222
+ rocksdb.put "Three", "3"
223
+
224
+ rocksdb.each do |value|
225
+ puts value
226
+ end
227
+
228
+ # => 1
229
+ # => 3
230
+ # => 2
231
+ ```
232
+
233
+ Additionally, you can enumerate in reverse order with `reverse_each`:
234
+
235
+ ```ruby
236
+
237
+ require "rocksdb"
238
+
239
+ # Open for reads and writes
240
+ rocksdb = RocksDB.open "/tmp/file11"
241
+
242
+ rocksdb.put "One", "1"
243
+ rocksdb.put "Two", "2"
244
+ rocksdb.put "Three", "3"
245
+
246
+ rocksdb.reverse_each do |value|
247
+ puts value
248
+ end
249
+
250
+ # => 2
251
+ # => 3
252
+ # => 1
253
+ ```
254
+
255
+ You can enumerate over keys with `each_key` or in reverse order with `reverse_each_key`:
256
+
257
+ ```ruby
258
+
259
+ require "rocksdb"
260
+
261
+ # Open for reads and writes
262
+ rocksdb = RocksDB.open "/tmp/file12"
263
+
264
+ rocksdb.put "One", "1"
265
+ rocksdb.put "Two", "2"
266
+ rocksdb.put "Three", "3"
267
+
268
+ rocksdb.each_key do |key|
269
+ puts key
270
+ end
271
+
272
+ # => One
273
+ # => Three
274
+ # => Two
275
+
276
+ rocksdb.reverse_each_key do |key|
277
+ puts key
278
+ end
279
+
280
+ # => Two
281
+ # => Three
282
+ # => One
283
+ ```
284
+
285
+ You can enumerate over both keys and values with `each_pair` and in reverse order with `reverse_each_pair`:
286
+
287
+ ```ruby
288
+
289
+ require "rocksdb"
290
+
291
+ # Open for reads and writes
292
+ rocksdb = RocksDB.open "/tmp/file13"
293
+
294
+ rocksdb.put "One", "1"
295
+ rocksdb.put "Two", "2"
296
+ rocksdb.put "Three", "3"
297
+
298
+ rocksdb.each_pair do |key, value|
299
+ puts "#{key} = #{value}"
300
+ end
301
+
302
+ # => One = 1
303
+ # => Three = 3
304
+ # => Two = 2
305
+ ```
306
+
307
+ Additionally, you can enumerate over keys that start with a specific prefix with `each_prefix`:
308
+
309
+ ```ruby
310
+
311
+ require "rocksdb"
312
+
313
+ # Open for reads and writes
314
+ rocksdb = RocksDB.open "/tmp/file14"
315
+
316
+ rocksdb.put "my:1", "1"
317
+ rocksdb.put "my:2", "2"
318
+ rocksdb.put "your:3", "3"
319
+
320
+ rocksdb.each_prefix("my") do |key, value|
321
+ puts "#{key} = #{value}"
322
+ end
323
+
324
+ # => my:1 = 1
325
+ # => my:2 = 2
326
+ ```
327
+
328
+ Or you can scan over the ranges of keys with `each_range`. Note, range is `[start, limit]`:
329
+
330
+ ```ruby
331
+
332
+ require "rocksdb"
333
+
334
+ # Open for reads and writes
335
+ rocksdb = RocksDB.open "/tmp/file15"
336
+
337
+ 10.times do |count|
338
+ rocksdb.put "key:#{count}", "#{count}"
339
+ end
340
+
341
+ rocksdb.each_range("key:5", "key:7") do |key, value|
342
+ puts "#{key} = #{value}"
343
+ end
344
+
345
+ # => key:5 = 5
346
+ # => key:6 = 6
347
+ # => key:7 = 7
348
+ ```
349
+
350
+ ### Atomic Batches
351
+
352
+ You can use `RocksDB::Batch` to atomically insert big chunks of data.
353
+
354
+ ```ruby
355
+
356
+ require "rocksdb"
357
+
358
+ # Open for reads and writes
359
+ rocksdb = RocksDB.open "/tmp/file16"
360
+
361
+ batch = RocksDB::Batch.new
362
+
363
+ batch.delete("test:batch1")
364
+ batch.put("test:batch2", "b")
365
+
366
+ rocksdb.write(batch)
367
+
368
+ rocksdb.each_pair do |key, value|
369
+ puts "#{key} = #{value}"
370
+ end
371
+
372
+ # => test:batch2 = b
373
+ ```
374
+
375
+ Read more about RocksDB batches: https://github.com/facebook/rocksdb/wiki/Basic-Operations#atomic-updates
376
+
377
+ # Iterator
378
+
379
+ You can get RocksDB Iterator with `to_iterator` method to iterate over your data:
380
+
381
+ ```ruby
382
+
383
+ require "rocksdb"
384
+
385
+ # Open for reads and writes
386
+ rocksdb = RocksDB.open "/tmp/file16"
387
+
388
+ 10.times do |count|
389
+ rocksdb.put "key:#{count}", "#{count}"
390
+ end
391
+
392
+ # Get Iterator
393
+ iterator = rocksdb.to_iterator
394
+ # Seek to some position. You can also use seek("key") to
395
+ iterator.seek_to_first
396
+
397
+ while iterator.valid?
398
+ puts "#{iterator.value} = #{iterator.key}"
399
+ iterator.next
400
+ end
401
+
402
+ iterator.close
403
+ ```
404
+
405
+ Supported methods:
406
+
407
+ * `seek(key)` seeks to closest key to given prefix at beginning
408
+ * `seek_to_first` seeks to the first key
409
+ * `seek_to_last` seeks to the last key
410
+ * `next` seeks to the next key
411
+ * `previous` seeks to the previous key
412
+ * `valid?` returns true if iterator can be iterated
413
+ * `close` closes iterator
414
+ * `key` returns current key
415
+ * `value` returns current value
416
+
417
+ Methods supported by rocksdb 4.11 and later:
418
+
419
+ * `seek_for_previous(key)`seeks to closest key to given prefix at end
420
+
421
+ ## Upgrade
422
+
423
+ When upgrading from `0.2` version, please note the following breaking changes:
424
+
425
+ * `multi_get` will return `nil` instead of empty string
426
+ * `RocksDB::DB.get_instance` is removed. Implement your own DB instance cache if needed
427
+ * `each_` methods now returns `Enumerator` instead of `RocksDB::Iterator`
428
+
429
+ Also, there some things that are now deprecated and will be removed in future versions:
430
+
431
+ * `RocksDB::DBError` was deprecated and replaced with `RocksDB::Error`. Specific errors now have their own exception class: `ReadOnly`, `DatabaseClosed`, `IteratorClosed`, `StatusError`
432
+ * `is_open?` was replaced with `open?`
433
+ * `is_readonly?` was replaced with `writable?`
434
+ * `multi_get` was replaced with `get_many`
435
+ * `new_iterator` was replaced with `to_iterator`
436
+ * `Iterator#valid` was replaced with `Iterator#valid?`
437
+
77
438
  ## Contributing
78
439
 
79
440
  1. Fork it