persistence-adapter-kyotocabinet 0.0.1
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.
- data/CHANGELOG.rdoc +4 -0
- data/README.md +65 -0
- data/lib/persistence/adapter/kyotocabinet.rb +18 -0
- data/lib/persistence/adapter/kyotocabinet/adapter_interface.rb +196 -0
- data/lib/persistence/adapter/kyotocabinet/bucket.rb +6 -0
- data/lib/persistence/adapter/kyotocabinet/bucket/bucket_interface.rb +435 -0
- data/lib/persistence/adapter/kyotocabinet/bucket/index.rb +6 -0
- data/lib/persistence/adapter/kyotocabinet/bucket/index/index_interface.rb +165 -0
- data/lib/persistence/adapter/kyotocabinet/cursor.rb +6 -0
- data/lib/persistence/adapter/kyotocabinet/cursor/cursor_interface.rb +163 -0
- data/lib/persistence/adapter/kyotocabinet/database_support.rb +122 -0
- data/lib/persistence/adapter/kyotocabinet/marshal.rb +14 -0
- data/lib/persistence/adapter/kyotocabinet/yaml.rb +14 -0
- data/lib/persistence/adapter/namespaces.rb +10 -0
- data/lib/persistence/adapter/requires.rb +28 -0
- data/spec/Persistence/Adapter/kyotocabinet/cursor_spec.rb +25 -0
- data/spec/Persistence/Adapter/kyotocabinet/marshal_spec.rb +15 -0
- data/spec/Persistence/Adapter/kyotocabinet/yaml_spec.rb +15 -0
- data/spec/Persistence/Adapter/kyotocabinet_spec.rb +25 -0
- metadata +80 -0
@@ -0,0 +1,165 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module ::Persistence::Adapter::KyotoCabinet::Bucket::Index::IndexInterface
|
4
|
+
|
5
|
+
include ::Persistence::Adapter::KyotoCabinet::DatabaseSupport
|
6
|
+
|
7
|
+
################
|
8
|
+
# initialize #
|
9
|
+
################
|
10
|
+
|
11
|
+
def initialize( index_name, parent_bucket, permits_duplicates )
|
12
|
+
|
13
|
+
@name = index_name
|
14
|
+
|
15
|
+
@parent_bucket = parent_bucket
|
16
|
+
|
17
|
+
@permits_duplicates = permits_duplicates
|
18
|
+
|
19
|
+
# get path info for index databases
|
20
|
+
bucket_name = @bucket_name
|
21
|
+
|
22
|
+
@database__index = ::KyotoCabinet::DB.new
|
23
|
+
@database__index.open( file__index_database( bucket_name, index_name ),
|
24
|
+
parent_bucket.parent_adapter.class::DatabaseFlags )
|
25
|
+
|
26
|
+
@database__reverse_index = ::KyotoCabinet::DB.new
|
27
|
+
@database__reverse_index.open( file__reverse_index_database( bucket_name, index_name ),
|
28
|
+
parent_bucket.parent_adapter.class::DatabaseFlags )
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
###########
|
33
|
+
# count #
|
34
|
+
###########
|
35
|
+
|
36
|
+
def count
|
37
|
+
|
38
|
+
return @database__index.count
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
###########
|
43
|
+
# close #
|
44
|
+
###########
|
45
|
+
|
46
|
+
def close
|
47
|
+
|
48
|
+
@database__index.close
|
49
|
+
@database__reverse_index.close
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
############
|
54
|
+
# delete #
|
55
|
+
############
|
56
|
+
|
57
|
+
def delete
|
58
|
+
|
59
|
+
# remove reverse index
|
60
|
+
File.delete( @database__reverse_index.path )
|
61
|
+
|
62
|
+
# remove index
|
63
|
+
File.delete( @database__index.path )
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
############
|
68
|
+
# cursor #
|
69
|
+
############
|
70
|
+
|
71
|
+
def cursor
|
72
|
+
|
73
|
+
return ::Persistence::Adapter::KyotoCabinet::Cursor.new( @parent_bucket, self, @database__index.cursor )
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
#########################
|
78
|
+
# permits_duplicates? #
|
79
|
+
#########################
|
80
|
+
|
81
|
+
def permits_duplicates?
|
82
|
+
|
83
|
+
return @permits_duplicates
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
###################
|
88
|
+
# get_object_id #
|
89
|
+
###################
|
90
|
+
|
91
|
+
def get_object_id( key )
|
92
|
+
|
93
|
+
serialized_index_key = @parent_bucket.parent_adapter.class::SerializationClass.__send__( @parent_bucket.parent_adapter.class::SerializationMethod, key )
|
94
|
+
|
95
|
+
global_id = @database__index.get( serialized_index_key )
|
96
|
+
|
97
|
+
return global_id ? global_id.to_i : nil
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
#####################
|
102
|
+
# index_object_id #
|
103
|
+
#####################
|
104
|
+
|
105
|
+
def index_object_id( global_id, key )
|
106
|
+
|
107
|
+
serialized_index_key = @parent_bucket.parent_adapter.class::SerializationClass.__send__( @parent_bucket.parent_adapter.class::SerializationMethod, key )
|
108
|
+
|
109
|
+
# we point to object.persistence_id rather than primary key because the object.persistence_id is the object header
|
110
|
+
@database__index.set( serialized_index_key, global_id )
|
111
|
+
@database__reverse_index.set( global_id, serialized_index_key )
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
################################
|
116
|
+
# delete_keys_for_object_id! #
|
117
|
+
################################
|
118
|
+
|
119
|
+
def delete_keys_for_object_id!( global_id )
|
120
|
+
|
121
|
+
serialized_key = @database__reverse_index.get( global_id )
|
122
|
+
@database__reverse_index.remove( global_id )
|
123
|
+
@database__index.remove( serialized_key )
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
##################################################################################################
|
128
|
+
private ######################################################################################
|
129
|
+
##################################################################################################
|
130
|
+
|
131
|
+
##########################
|
132
|
+
# file__index_database #
|
133
|
+
##########################
|
134
|
+
|
135
|
+
def file__index_database( bucket_name, index_name )
|
136
|
+
|
137
|
+
index_file_name = bucket_name.to_s + '__index_' + index_name.to_s + '__' + extension__bucket_index_database
|
138
|
+
|
139
|
+
return File.join( @parent_bucket.parent_adapter.home_directory, index_file_name )
|
140
|
+
|
141
|
+
end
|
142
|
+
|
143
|
+
##################################
|
144
|
+
# file__reverse_index_database #
|
145
|
+
##################################
|
146
|
+
|
147
|
+
def file__reverse_index_database( bucket_name, index_name )
|
148
|
+
|
149
|
+
index_file_name = bucket_name.to_s + '__reverse_index_' + index_name.to_s + '__' + extension__bucket_index_database
|
150
|
+
|
151
|
+
return File.join( @parent_bucket.parent_adapter.home_directory, index_file_name )
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
######################################
|
156
|
+
# extension__bucket_index_database #
|
157
|
+
######################################
|
158
|
+
|
159
|
+
def extension__bucket_index_database
|
160
|
+
|
161
|
+
return extension__database( :tree )
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
|
2
|
+
module ::Persistence::Adapter::KyotoCabinet::Cursor::CursorInterface
|
3
|
+
|
4
|
+
################
|
5
|
+
# initialize #
|
6
|
+
################
|
7
|
+
|
8
|
+
def initialize( parent_bucket, parent_index, cursor_instance )
|
9
|
+
|
10
|
+
@parent_bucket = parent_bucket
|
11
|
+
@parent_index = parent_index
|
12
|
+
|
13
|
+
@cursor_instance = cursor_instance
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
############################
|
18
|
+
# supports_bucket_order? #
|
19
|
+
############################
|
20
|
+
|
21
|
+
def supports_bucket_order?
|
22
|
+
|
23
|
+
return true
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
###########################
|
28
|
+
# supports_index_order? #
|
29
|
+
###########################
|
30
|
+
|
31
|
+
def supports_index_order?
|
32
|
+
|
33
|
+
return true
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
###########
|
38
|
+
# close #
|
39
|
+
###########
|
40
|
+
|
41
|
+
def close
|
42
|
+
|
43
|
+
@cursor_instance.disable
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
################
|
48
|
+
# persisted? #
|
49
|
+
################
|
50
|
+
|
51
|
+
# persisted? is responsible for setting the cursor position
|
52
|
+
def persisted?( *args )
|
53
|
+
|
54
|
+
has_key = false
|
55
|
+
no_key = false
|
56
|
+
key = nil
|
57
|
+
case args.count
|
58
|
+
when 1
|
59
|
+
key = args[0]
|
60
|
+
when 0
|
61
|
+
no_key = true
|
62
|
+
end
|
63
|
+
|
64
|
+
# if we have no args we are asking whether any keys exist
|
65
|
+
if no_key
|
66
|
+
|
67
|
+
has_key = true unless ( @parent_index || @parent_bucket ).count == 0
|
68
|
+
|
69
|
+
else
|
70
|
+
|
71
|
+
serialized_key = nil
|
72
|
+
if @parent_index
|
73
|
+
serialized_key = @parent_bucket.parent_adapter.class::SerializationClass.__send__( @parent_bucket.parent_adapter.class::SerializationMethod, key )
|
74
|
+
else
|
75
|
+
serialized_key = key
|
76
|
+
end
|
77
|
+
|
78
|
+
has_key = @cursor_instance.jump( serialized_key )
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
return has_key
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
###########
|
87
|
+
# first #
|
88
|
+
###########
|
89
|
+
|
90
|
+
# first should set the cursor position and return the first ID or object hash
|
91
|
+
def first
|
92
|
+
@cursor_instance.jump( nil )
|
93
|
+
return current
|
94
|
+
end
|
95
|
+
|
96
|
+
###############
|
97
|
+
# first_key #
|
98
|
+
###############
|
99
|
+
|
100
|
+
# first should set the cursor position and return the first ID or object hash
|
101
|
+
def first_key
|
102
|
+
@cursor_instance.jump( nil )
|
103
|
+
return current_key
|
104
|
+
end
|
105
|
+
|
106
|
+
#############
|
107
|
+
# current #
|
108
|
+
#############
|
109
|
+
|
110
|
+
# current should return the current ID or object hash
|
111
|
+
def current
|
112
|
+
if global_id = @cursor_instance.get_value
|
113
|
+
global_id = global_id.to_i
|
114
|
+
end
|
115
|
+
# return ID
|
116
|
+
return global_id
|
117
|
+
end
|
118
|
+
|
119
|
+
#################
|
120
|
+
# current_key #
|
121
|
+
#################
|
122
|
+
|
123
|
+
# current should return the current ID or object hash
|
124
|
+
def current_key
|
125
|
+
|
126
|
+
unserialized_key = nil
|
127
|
+
|
128
|
+
if serialized_key_or_id_string = @cursor_instance.get_key
|
129
|
+
|
130
|
+
# if we have an index we have serialized key
|
131
|
+
if @parent_index
|
132
|
+
unserialized_key = @parent_bucket.parent_adapter.class::SerializationClass.__send__( @parent_bucket.parent_adapter.class::UnserializationMethod, serialized_key_or_id_string )
|
133
|
+
# if not we just have an ID string
|
134
|
+
else
|
135
|
+
unserialized_key = serialized_key_or_id_string.to_i
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
# return ID
|
141
|
+
return unserialized_key
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
##########
|
146
|
+
# next #
|
147
|
+
##########
|
148
|
+
|
149
|
+
def next
|
150
|
+
@cursor_instance.step
|
151
|
+
return current
|
152
|
+
end
|
153
|
+
|
154
|
+
##############
|
155
|
+
# next_key #
|
156
|
+
##############
|
157
|
+
|
158
|
+
def next_key
|
159
|
+
@cursor_instance.step
|
160
|
+
return current_key
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# ::Persistence::Adapter::KyotoCabinet::Locations
|
2
|
+
#
|
3
|
+
# DatabaseSupport for ::Persistence Adapter for Kyoto Cabinet
|
4
|
+
|
5
|
+
module ::Persistence::Adapter::KyotoCabinet::DatabaseSupport
|
6
|
+
|
7
|
+
##################################################################################################
|
8
|
+
private ######################################################################################
|
9
|
+
##################################################################################################
|
10
|
+
|
11
|
+
#########################
|
12
|
+
# extension__database #
|
13
|
+
#########################
|
14
|
+
|
15
|
+
def extension__database( db_type )
|
16
|
+
|
17
|
+
extension = nil
|
18
|
+
|
19
|
+
case db_type
|
20
|
+
when :hash
|
21
|
+
# ".kch" - hash database (HashDB)
|
22
|
+
extension = '.kch'
|
23
|
+
when :tree
|
24
|
+
# ".kct" - tree database (TreeDB)
|
25
|
+
extension = '.kct'
|
26
|
+
when :dir
|
27
|
+
# ".kcd" - directory hash database (DirDB)
|
28
|
+
extension = '.kcd'
|
29
|
+
when :forest
|
30
|
+
# ".kcf" - directory tree database (ForestDB)
|
31
|
+
extension = '.kcf'
|
32
|
+
else
|
33
|
+
raise 'Unknown database type. Expected :hash, :tree, :dir, or :forest.'
|
34
|
+
end
|
35
|
+
|
36
|
+
return extension
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
#######################
|
41
|
+
# options__database #
|
42
|
+
#######################
|
43
|
+
|
44
|
+
def options__database()
|
45
|
+
|
46
|
+
# Compression:
|
47
|
+
|
48
|
+
# All databases support:
|
49
|
+
# * "opts"
|
50
|
+
# * "zcomp"
|
51
|
+
# * "zkey"
|
52
|
+
# HashDB and TreeDB database also support:
|
53
|
+
# * "apow"
|
54
|
+
# * "fpow"
|
55
|
+
# * "bnum"
|
56
|
+
# * "msiz"
|
57
|
+
# * "dfunit"
|
58
|
+
# TreeDB and ForestDB also support:
|
59
|
+
# * "psiz"
|
60
|
+
# * "rcomp"
|
61
|
+
# * "pccap"
|
62
|
+
case db_type
|
63
|
+
when :hash, :tree, :dir, :forest
|
64
|
+
when :hash, :tree
|
65
|
+
when :tree, :forest
|
66
|
+
end
|
67
|
+
|
68
|
+
# Tuning Parameters:
|
69
|
+
|
70
|
+
# * "log" is for the original "tune_logger" and the value specifies:
|
71
|
+
# - the path of the log file
|
72
|
+
# - "-" for stdout
|
73
|
+
# - "+" for stderr
|
74
|
+
|
75
|
+
# * "logkinds" specifies kinds of logged messages and the value can be:
|
76
|
+
# - "debug"
|
77
|
+
# - "info"
|
78
|
+
# - "warn"
|
79
|
+
# - "error"
|
80
|
+
|
81
|
+
# * "logpx" specifies the prefix of each log message.
|
82
|
+
|
83
|
+
# * "opts" is for "tune_options" and the value can contain:
|
84
|
+
# - "s" for the small option
|
85
|
+
# - "l" for the linear option
|
86
|
+
# - "c" for the compress option
|
87
|
+
|
88
|
+
# * "bnum" corresponds to "tune_bucket".
|
89
|
+
|
90
|
+
# * "zcomp" is for "tune_compressor":
|
91
|
+
# - "zlib" for the ZLIB raw compressor
|
92
|
+
# - "def" for the ZLIB deflate compressor
|
93
|
+
# - "gz" for the ZLIB gzip compressor
|
94
|
+
# - "lzo" for the LZO compressor
|
95
|
+
# - "lzma" for the LZMA compressor
|
96
|
+
# - "arc" for the Arcfour cipher
|
97
|
+
|
98
|
+
# * "zkey" specifies the cipher key of the compressor.
|
99
|
+
|
100
|
+
# * "capcnt" is for "cap_count".
|
101
|
+
|
102
|
+
# * "capsiz" is for "cap_size".
|
103
|
+
|
104
|
+
# * "psiz" is for "tune_page".
|
105
|
+
|
106
|
+
# * "rcomp" is for "tune_comparator" and the value can be:
|
107
|
+
# - "lex" for the lexical comparator
|
108
|
+
# - "dec" for the decimal comparator
|
109
|
+
|
110
|
+
# * "pccap" is for "tune_page_cache".
|
111
|
+
|
112
|
+
# * "apow" is for "tune_alignment".
|
113
|
+
|
114
|
+
# * "fpow" is for "tune_fbp".
|
115
|
+
|
116
|
+
# * "msiz" is for "tune_map".
|
117
|
+
|
118
|
+
# * "dfunit" is for "tune_defrag".
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|