kyotocabinet-ffi 0.1.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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/lib/kyotocabinet_ffi.rb +6 -0
- data/lib/kyotocabinet_ffi/db/db.rb +120 -0
- data/lib/kyotocabinet_ffi/db/file_hash_db.rb +22 -0
- data/lib/kyotocabinet_ffi/db/memory_hash_db.rb +12 -0
- data/lib/kyotocabinet_ffi/db/polymorphic_db.rb +69 -0
- data/lib/kyotocabinet_ffi/libkyotocabinet_ffi.rb +91 -0
- data/lib/kyotocabinet_ffi/version.rb +3 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7a217d689172b77a9ed48327116644b3d5d2e8bb
|
4
|
+
data.tar.gz: f7777511183cac42863b3ab84035d932c36ad5cd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6f8c12f2f832e8d849bc3587e3d8fcb285adf4bebdd0fa12d77beb97d6ac24da0961768351d5931e80d06e561adb1a4ac8ee557dc200b2be9c744b43433f6c4a
|
7
|
+
data.tar.gz: 10fbcc82c5907afe1c6c509942d59c72b4e1a1d05c19fe3c9e8f1afe7c3ab7d5360272cfb26c2f475c91f252b846c1d83fac07573d072f93dcb40c792410258b
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014-2015 Anthony Bargnesi
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all 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,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require_relative 'kyotocabinet_ffi/libkyotocabinet_ffi'
|
2
|
+
require_relative 'kyotocabinet_ffi/db/db'
|
3
|
+
require_relative 'kyotocabinet_ffi/db/polymorphic_db'
|
4
|
+
require_relative 'kyotocabinet_ffi/db/memory_hash_db'
|
5
|
+
require_relative 'kyotocabinet_ffi/db/file_hash_db'
|
6
|
+
require_relative 'kyotocabinet_ffi/version'
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require_relative '../libkyotocabinet_ffi'
|
2
|
+
|
3
|
+
module KyotoCabinet
|
4
|
+
|
5
|
+
# in-memory (or prototype) database types
|
6
|
+
MEMORY_HASH = :-
|
7
|
+
MEMORY_TREE = :+
|
8
|
+
MEMORY_STASH = :':'
|
9
|
+
MEMORY_CACHE_HASH = :*
|
10
|
+
MEMORY_CACHE_TREE = :%
|
11
|
+
|
12
|
+
# on-disk database types
|
13
|
+
FILE_HASH = :".kch"
|
14
|
+
FILE_TREE = :".kct"
|
15
|
+
FILE_PLAIN_TEXT = :".kcx"
|
16
|
+
DIR_HASH = :".kcd"
|
17
|
+
DIR_TREE = :".kcf"
|
18
|
+
|
19
|
+
MEMORY_DB_TYPE = [
|
20
|
+
MEMORY_HASH,
|
21
|
+
MEMORY_TREE,
|
22
|
+
MEMORY_STASH,
|
23
|
+
MEMORY_CACHE_HASH,
|
24
|
+
MEMORY_CACHE_TREE
|
25
|
+
]
|
26
|
+
|
27
|
+
FILE_DB_TYPE = [
|
28
|
+
FILE_HASH,
|
29
|
+
FILE_TREE,
|
30
|
+
FILE_PLAIN_TEXT,
|
31
|
+
DIR_HASH,
|
32
|
+
DIR_TREE
|
33
|
+
]
|
34
|
+
|
35
|
+
DEFAULT_TEMP_PREFIX = 'kyoto-db'
|
36
|
+
|
37
|
+
def self.match_memorydb_type? value
|
38
|
+
return false unless value
|
39
|
+
value_s = value.to_s
|
40
|
+
MEMORY_DB_TYPE.any? { |ext| value_s == ext.to_s }
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.match_filedb_type? value
|
44
|
+
return false unless value
|
45
|
+
value_s = value.to_s
|
46
|
+
FILE_DB_TYPE.any? { |ext| value_s.end_with? ext.to_s }
|
47
|
+
end
|
48
|
+
|
49
|
+
module Db
|
50
|
+
|
51
|
+
def new
|
52
|
+
@kc_db_pointer = LibKyotoCabinet::kcdbnew
|
53
|
+
end
|
54
|
+
|
55
|
+
def last_error_code
|
56
|
+
LibKyotoCabinet::kcdbecode(@kc_db_pointer)
|
57
|
+
end
|
58
|
+
|
59
|
+
def last_error_message
|
60
|
+
LibKyotoCabinet::kcdbemsg(@kc_db_pointer)
|
61
|
+
end
|
62
|
+
|
63
|
+
def last_error
|
64
|
+
SystemCallError.new(last_error_message, last_error_code)
|
65
|
+
end
|
66
|
+
|
67
|
+
def open(path, *options)
|
68
|
+
mode = (options & LibKyotoCabinet::MODES.keys).map { |k|
|
69
|
+
LibKyotoCabinet::MODES[k]
|
70
|
+
}.reduce(0, :|)
|
71
|
+
bool_return(LibKyotoCabinet::kcdbopen(@kc_db_pointer, path.to_s, mode))
|
72
|
+
end
|
73
|
+
|
74
|
+
def open!(path, *options)
|
75
|
+
fail last_error if not open(path, *options)
|
76
|
+
end
|
77
|
+
|
78
|
+
def size
|
79
|
+
LibKyotoCabinet::kcdbcount(@kc_db_pointer)
|
80
|
+
end
|
81
|
+
|
82
|
+
def get(key)
|
83
|
+
key_string = key.to_s
|
84
|
+
value_size_ptr = LibKyotoCabinet::FFI::MemoryPointer.new :pointer
|
85
|
+
LibKyotoCabinet::kcdbget(@kc_db_pointer, key_string, key_string.length, value_size_ptr)
|
86
|
+
end
|
87
|
+
|
88
|
+
def set(key, value)
|
89
|
+
key_string = key.to_s
|
90
|
+
value_string = value.to_s
|
91
|
+
bool_return(LibKyotoCabinet::kcdbset(@kc_db_pointer, key_string, key_string.length, value_string, value_string.length))
|
92
|
+
end
|
93
|
+
|
94
|
+
def set!(key, value)
|
95
|
+
fail last_error if not set(key, value)
|
96
|
+
end
|
97
|
+
|
98
|
+
def clear
|
99
|
+
bool_return(LibKyotoCabinet::kcdbclear(@kc_db_pointer))
|
100
|
+
end
|
101
|
+
|
102
|
+
def clear!
|
103
|
+
fail last_error if not clear
|
104
|
+
end
|
105
|
+
|
106
|
+
def close
|
107
|
+
bool_return(LibKyotoCabinet::kcdbclose(@kc_db_pointer))
|
108
|
+
end
|
109
|
+
|
110
|
+
def close!
|
111
|
+
fail last_error if not close
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def bool_return(int_value)
|
117
|
+
int_value != 0
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module KyotoCabinet
|
2
|
+
module Db
|
3
|
+
|
4
|
+
# deprecated - use PolymorphicDb directly
|
5
|
+
class FileHash < PolymorphicDb
|
6
|
+
attr_reader :file_path
|
7
|
+
|
8
|
+
def initialize(file_path, *options)
|
9
|
+
fail ArgumentError.new('file_path must be set') unless file_path
|
10
|
+
|
11
|
+
if not file_path.end_with? KyotoCabinet::FILE_HASH.to_s
|
12
|
+
file_path << KyotoCabinet::FILE_HASH.to_s
|
13
|
+
end
|
14
|
+
|
15
|
+
@file_path = file_path
|
16
|
+
|
17
|
+
self.new
|
18
|
+
self.open!(@file_path, *options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module KyotoCabinet
|
5
|
+
module Db
|
6
|
+
class PolymorphicDb
|
7
|
+
include Db
|
8
|
+
|
9
|
+
def initialize(path, options = {})
|
10
|
+
path_s = path.to_s
|
11
|
+
db_options = options.delete(:db_options) || []
|
12
|
+
unless KyotoCabinet::match_filedb_type? (path_s) or
|
13
|
+
KyotoCabinet::match_memorydb_type? (path_s)
|
14
|
+
msg = %Q{
|
15
|
+
The path value \"#{path || '(nil)'}\" does not match one of the memory
|
16
|
+
db types #{KyotoCabinet::MEMORY_DB_TYPE.map(&:to_s).join(', ')} or
|
17
|
+
one of the file db types #{KyotoCabinet::FILE_DB_TYPE.map(&:to_s).join(', ')}.
|
18
|
+
}.gsub(%r{^\s+}, ' ').gsub(%r{\n}, '')
|
19
|
+
fail ArgumentError.new(msg)
|
20
|
+
end
|
21
|
+
|
22
|
+
self.new
|
23
|
+
self.open!(path, *db_options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.tmp_filedb(type, options = {})
|
27
|
+
prefix = options[:prefix]
|
28
|
+
path = make_temp(type, prefix)
|
29
|
+
|
30
|
+
self.new(path, {
|
31
|
+
:db_options => [:create, :reader, :writer]
|
32
|
+
})
|
33
|
+
end
|
34
|
+
|
35
|
+
def [](key)
|
36
|
+
self.get(key)
|
37
|
+
end
|
38
|
+
|
39
|
+
def []=(key, value)
|
40
|
+
self.set(key, value)
|
41
|
+
end
|
42
|
+
|
43
|
+
def empty?
|
44
|
+
self.size <= 0
|
45
|
+
end
|
46
|
+
|
47
|
+
def clear
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def self.make_temp(ext, prefix)
|
54
|
+
unless KyotoCabinet::match_filedb_type?(ext)
|
55
|
+
msg = %Q{
|
56
|
+
The ext value \"#{ext || '(nil)'}\" does not match one of the file
|
57
|
+
db types #{KyotoCabinet::FILE_DB_TYPE.map(&:to_s).join(', ')}.
|
58
|
+
}.gsub(%r{^\s+}, ' ').gsub(%r{\n}, '')
|
59
|
+
msg = "The extension \"#{ext || '(nil)'}\" does not match one of #{KyotoCabinet::FILE_DB_TYPE}"
|
60
|
+
fail ArgumentError.new(msg)
|
61
|
+
end
|
62
|
+
|
63
|
+
epoch_millis = (Time.now.to_f * 1000).to_i
|
64
|
+
prefix = prefix || DEFAULT_TEMP_PREFIX
|
65
|
+
(Pathname(Dir.tmpdir) + "#{prefix}-#{epoch_millis}#{ext}").to_s
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# @api private
|
2
|
+
# FFI bindings
|
3
|
+
module LibKyotoCabinet
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def mri?
|
8
|
+
defined?(RUBY_DESCRIPTION) && (/^ruby/ =~ RUBY_DESCRIPTION)
|
9
|
+
end
|
10
|
+
|
11
|
+
def jruby?
|
12
|
+
defined?(RUBY_PLATFORM) && ("java" == RUBY_PLATFORM)
|
13
|
+
end
|
14
|
+
|
15
|
+
def rubinius?
|
16
|
+
defined?(RUBY_ENGINE) && ("rbx" == RUBY_ENGINE)
|
17
|
+
end
|
18
|
+
|
19
|
+
# @api_private
|
20
|
+
# Determine FFI constant for this ruby engine.
|
21
|
+
def find_ffi
|
22
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == "rbx"
|
23
|
+
if const_defined? "::Rubinius::FFI"
|
24
|
+
::Rubinius::FFI
|
25
|
+
elsif const_defined? "::FFI"
|
26
|
+
::FFI
|
27
|
+
else
|
28
|
+
require "ffi"
|
29
|
+
::FFI
|
30
|
+
end
|
31
|
+
else # mri, jruby, etc
|
32
|
+
require "ffi"
|
33
|
+
::FFI
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @api_private
|
38
|
+
# Extend with the correct ffi implementation.
|
39
|
+
def load_ffi
|
40
|
+
ffi_module = LibKyotoCabinet::find_ffi
|
41
|
+
extend ffi_module::Library
|
42
|
+
ffi_module
|
43
|
+
end
|
44
|
+
|
45
|
+
# @api_private
|
46
|
+
# Loads the libkyotocabinet shared library.
|
47
|
+
def load_libkyotocabinet
|
48
|
+
ffi_module = find_ffi
|
49
|
+
extend ffi_module::Library
|
50
|
+
|
51
|
+
begin
|
52
|
+
ffi_lib "kyotocabinet"
|
53
|
+
rescue LoadError
|
54
|
+
begin
|
55
|
+
ffi_lib "libkyotocabinet.so"
|
56
|
+
rescue LoadError
|
57
|
+
ffi_lib "libkyotocabinet.so.16"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Constant holding the FFI module for this ruby engine.
|
64
|
+
FFI = LibKyotoCabinet::load_ffi
|
65
|
+
LibKyotoCabinet::load_libkyotocabinet
|
66
|
+
|
67
|
+
# mode options
|
68
|
+
MODES = {
|
69
|
+
:reader => (1 << 0),
|
70
|
+
:writer => (1 << 1),
|
71
|
+
:create => (1 << 2),
|
72
|
+
:truncate => (1 << 3),
|
73
|
+
:auto_transaction => (1 << 4),
|
74
|
+
:auto_synchronize => (1 << 5),
|
75
|
+
:no_file_locking => (1 << 6),
|
76
|
+
:non_blocking_lock => (1 << 7),
|
77
|
+
:no_file_repair => (1 << 8)
|
78
|
+
}
|
79
|
+
|
80
|
+
attach_function :kcdbecode, [:pointer], :int32
|
81
|
+
attach_function :kcdbemsg, [:pointer], :string
|
82
|
+
attach_function :kcdbnew, [], :pointer
|
83
|
+
attach_function :kcdbopen, [:pointer, :string, :uint32], :int32
|
84
|
+
attach_function :kcdbcount, [:pointer], :int64
|
85
|
+
attach_function :kcdbset, [:pointer, :string, :size_t, :string, :size_t], :int32
|
86
|
+
attach_function :kcdbadd, [:pointer, :string, :size_t, :string, :size_t], :int32
|
87
|
+
attach_function :kcdbget, [:pointer, :string, :size_t, :pointer], :string
|
88
|
+
attach_function :kcdbclear, [:pointer], :int32
|
89
|
+
attach_function :kcdbclose, [:pointer], :int32
|
90
|
+
attach_function :kcdbdel, [:pointer], :void
|
91
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kyotocabinet-ffi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anthony Bargnesi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ffi
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.9'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.9'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.4'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.4'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.4'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.4'
|
55
|
+
description: Kyoto Cabinet provided DBM interface to efficient key value stores both
|
56
|
+
in-memory and on-disk. This gem wraps Kyoto Cabinet's C API using FFI (foregin function
|
57
|
+
interface) to support MRI, JRuby, and Rubinius.
|
58
|
+
email: abargnesi@gmail.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- LICENSE
|
64
|
+
- lib/kyotocabinet_ffi.rb
|
65
|
+
- lib/kyotocabinet_ffi/db/db.rb
|
66
|
+
- lib/kyotocabinet_ffi/db/file_hash_db.rb
|
67
|
+
- lib/kyotocabinet_ffi/db/memory_hash_db.rb
|
68
|
+
- lib/kyotocabinet_ffi/db/polymorphic_db.rb
|
69
|
+
- lib/kyotocabinet_ffi/libkyotocabinet_ffi.rb
|
70
|
+
- lib/kyotocabinet_ffi/version.rb
|
71
|
+
homepage: https://github.com/abargnesi/kyotocabinet-ffi
|
72
|
+
licenses:
|
73
|
+
- MIT
|
74
|
+
metadata: {}
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 2.4.5
|
92
|
+
signing_key:
|
93
|
+
specification_version: 4
|
94
|
+
summary: FFI wrapper to Kyoto Cabinet's C API.
|
95
|
+
test_files: []
|
96
|
+
has_rdoc:
|