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.
@@ -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,12 @@
1
+ module KyotoCabinet
2
+ module Db
3
+
4
+ # deprecated - use PolymorphicDb directly
5
+ class MemoryHash < PolymorphicDb
6
+ def initialize(*options)
7
+ self.new
8
+ self.open!(KyotoCabinet::MEMORY_HASH, *options)
9
+ end
10
+ end
11
+ end
12
+ 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
@@ -0,0 +1,3 @@
1
+ module KyotoCabinet
2
+ VERSION = '0.1.0'
3
+ 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: