persistence-adapter-kyotocabinet 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|