okuyama 0.0.1 → 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.
- data/VERSION +1 -1
- data/lib/okuyama/client.rb +132 -37
- data/lib/okuyama/fast_client.rb +222 -0
- data/lib/okuyama/protocol/abstract_protocol.rb +31 -0
- data/lib/okuyama/protocol/version1.rb +306 -0
- data/lib/okuyama.rb +10 -1
- data/okuyama.gemspec +72 -0
- data/spec/okuyama/client/decr_value_spec.rb +99 -0
- data/spec/okuyama/client/incr_value_spec.rb +99 -0
- data/spec/okuyama/client/search_spec.rb +140 -0
- data/spec/okuyama/client_spec.rb +497 -20
- data/spec/okuyama/protocol/version1_spec.rb +24 -0
- data/spec/spec_helper.rb +6 -1
- metadata +12 -5
- data/lib/okuyama/protocol.rb +0 -21
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/lib/okuyama/client.rb
CHANGED
@@ -1,55 +1,150 @@
|
|
1
1
|
module Okuyama
|
2
|
-
class Client
|
2
|
+
class Client < FastClient
|
3
|
+
public
|
4
|
+
attr_accessor :debug, :to_i_flag, :parse_flag
|
5
|
+
|
3
6
|
def initialize(options)
|
4
|
-
|
5
|
-
@
|
7
|
+
super
|
8
|
+
@to_i_flag = options[:to_i_flag]
|
9
|
+
@to_i_flag = true if @to_i_flag.nil?
|
10
|
+
@parse_flag = options[:parse_flag]
|
11
|
+
@parse_flag = true if @parse_flag.nil?
|
6
12
|
end
|
7
13
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
14
|
+
|
15
|
+
def set_value(key, val, *args)
|
16
|
+
tag_list = nil
|
17
|
+
options = nil
|
18
|
+
|
19
|
+
argc = args.length
|
20
|
+
if argc == 1 then
|
21
|
+
arg = args[0]
|
22
|
+
if arg.is_a? Array then
|
23
|
+
tag_list = arg
|
24
|
+
elsif arg.is_a? Hash then
|
25
|
+
options = arg
|
26
|
+
tag_list = options[:tags]
|
27
|
+
else
|
28
|
+
tag_list = [arg.to_s]
|
29
|
+
end
|
30
|
+
elsif 1 < argc then
|
31
|
+
tag_list = args
|
13
32
|
end
|
14
|
-
|
33
|
+
|
34
|
+
# Disable debug message for better performance
|
35
|
+
# Okuyama.logger.debug "Okuyama::Client.protocol.set_value(key=#{key.inspect},val=#{val.inspect},tag_list=#{tag_list.inspect})"
|
36
|
+
|
37
|
+
@protocol.set_value(self.socket, key, val, tag_list)
|
38
|
+
return self.recvs
|
15
39
|
end
|
16
40
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
41
|
+
def set_new_value(key, val, *args)
|
42
|
+
tag_list = nil
|
43
|
+
options = nil
|
44
|
+
|
45
|
+
argc = args.length
|
46
|
+
if argc == 1 then
|
47
|
+
arg = args[0]
|
48
|
+
if arg.is_a? Array then
|
49
|
+
tag_list = arg
|
50
|
+
elsif arg.is_a? Hash then
|
51
|
+
options = arg
|
52
|
+
tag_list = options[:tags]
|
53
|
+
else
|
54
|
+
tag_list = [arg.to_s]
|
55
|
+
end
|
56
|
+
elsif 1 < argc then
|
57
|
+
tag_list = args
|
58
|
+
end
|
59
|
+
|
60
|
+
# Disable debug message for better performance
|
61
|
+
# Okuyama.logger.debug "Okuyama::Client.protocol.set_value(key=#{key.inspect},val=#{val.inspect},tag_list=#{tag_list.inspect})"
|
62
|
+
|
63
|
+
@protocol.set_new_value(self.socket, key, val, tag_list)
|
64
|
+
return self.recvs
|
20
65
|
end
|
21
66
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
|
67
|
+
def set_value_version_check(key, val, version, *args)
|
68
|
+
tag_list = nil
|
69
|
+
options = nil
|
70
|
+
|
71
|
+
argc = args.length
|
72
|
+
if argc == 1 then
|
73
|
+
arg = args[0]
|
74
|
+
if arg.is_a? Array then
|
75
|
+
tag_list = arg
|
76
|
+
elsif arg.is_a? Hash then
|
77
|
+
options = arg
|
78
|
+
tag_list = options[:tags]
|
79
|
+
else
|
80
|
+
tag_list = [arg.to_s]
|
81
|
+
end
|
82
|
+
elsif 1 < argc then
|
83
|
+
tag_list = args
|
84
|
+
end
|
85
|
+
|
86
|
+
# Disable debug message for better performance
|
87
|
+
# Okuyama.logger.debug "Okuyama::Client.protocol.set_value(key=#{key.inspect},val=#{val.inspect},tag_list=#{tag_list.inspect})"
|
88
|
+
|
89
|
+
@protocol.set_value_version_check(self.socket, key, val, version, tag_list)
|
90
|
+
return self.recvs
|
26
91
|
end
|
27
92
|
|
28
|
-
def
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
93
|
+
def get_tag_keys(tag, *args, &block)
|
94
|
+
flag = 'false'
|
95
|
+
options = nil
|
96
|
+
argc = args.length
|
97
|
+
if argc == 1 && args[0].is_a?(Hash) then
|
98
|
+
flag = options[:flag]
|
99
|
+
elsif 0 < argc then
|
100
|
+
flag = args[0]
|
101
|
+
end
|
102
|
+
@protocol.get_tag_keys(self.socket, tag, flag)
|
103
|
+
return self.recvs
|
36
104
|
end
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
105
|
+
|
106
|
+
protected
|
107
|
+
def each(&block)
|
108
|
+
return super(&block) if ! @parse_flag
|
109
|
+
if block_given? then
|
110
|
+
while line = socket.gets do
|
111
|
+
Okuyama.logger.debug "recv: #{line.inspect}" if @debug
|
112
|
+
line.chomp!
|
113
|
+
if line == "END" then
|
114
|
+
break
|
115
|
+
else
|
116
|
+
result = self.parse_result(line)
|
117
|
+
yield(result)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def readlines
|
124
|
+
return super if ! @parse_flag
|
125
|
+
ret = []
|
126
|
+
self.each { |record|
|
127
|
+
ret.push record
|
128
|
+
}
|
129
|
+
return ret
|
43
130
|
end
|
44
131
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
132
|
+
def recvs
|
133
|
+
line = super
|
134
|
+
# Disable debug message for better performance
|
135
|
+
Okuyama.logger.debug "recv: #{line.inspect}" if @debug
|
136
|
+
return self.parse_result(line) if @parse_flag
|
137
|
+
return line
|
138
|
+
end
|
139
|
+
|
140
|
+
def parse_result(result)
|
141
|
+
begin
|
142
|
+
result = @protocol.parse_line_result(result, @to_i_flag)
|
143
|
+
rescue Okuyama::ServerError => e
|
144
|
+
raise Okuyama::ServerError, "#{e.message}, message = #{result.inspect}"
|
51
145
|
end
|
52
|
-
return
|
146
|
+
return result
|
53
147
|
end
|
148
|
+
|
54
149
|
end
|
55
150
|
end
|
@@ -0,0 +1,222 @@
|
|
1
|
+
module Okuyama
|
2
|
+
class FastClient
|
3
|
+
public
|
4
|
+
attr_reader :host, :port, :timeout, :retry_max, :protocol
|
5
|
+
attr_accessor :base64_encode_flag
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@host = options[:host] || 'localhost'
|
9
|
+
@port = options[:port] || 8888
|
10
|
+
@timeout = options[:timeout] || 10
|
11
|
+
@retry_max = options[:retry_max] || 3
|
12
|
+
protocol_version = options[:protocol_version] || '1.0.0'
|
13
|
+
protocol_version = '1.0.0'
|
14
|
+
case protocol_version
|
15
|
+
when '1.0.0'
|
16
|
+
@protocol = Okuyama::Protocol::Version1.new(:base64_encode_flag=>options[:base64_encode_flag])
|
17
|
+
else
|
18
|
+
raise OkuyamaError, "protocol version #{protocol_version.inspect} is invalid"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def protocol_version
|
23
|
+
@protocol.version
|
24
|
+
end
|
25
|
+
|
26
|
+
def close(raise_exception=nil)
|
27
|
+
if @socket then
|
28
|
+
begin
|
29
|
+
@socket.close
|
30
|
+
rescue Exception=>e
|
31
|
+
raise e if raise_exception
|
32
|
+
Okuyama.logger.error "ERROR: #{e.message}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
@socket = nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def init_count
|
39
|
+
@protocol.init_count(self.socket)
|
40
|
+
return self.recvs
|
41
|
+
end
|
42
|
+
|
43
|
+
def set_value(key, val, tag_list=nil)
|
44
|
+
@protocol.set_value(self.socket, key, val, tag_list)
|
45
|
+
return self.recvs
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_value(key)
|
49
|
+
@protocol.get_value(self.socket, key)
|
50
|
+
return self.recvs
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_tag_keys(tag, flag='false')
|
54
|
+
@protocol.get_tag_keys(self.socket, tag, flag)
|
55
|
+
return self.recvs
|
56
|
+
end
|
57
|
+
|
58
|
+
def remove_value(key)
|
59
|
+
@protocol.remove_value(self.socket, key)
|
60
|
+
return self.recvs
|
61
|
+
end
|
62
|
+
|
63
|
+
def set_new_value(key, val, tag_list=nil)
|
64
|
+
@protocol.set_new_value(self.socket, key, val, tag_list)
|
65
|
+
return self.recvs
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_value_version_check(key)
|
69
|
+
@protocol.get_value_version_check(self.socket, key)
|
70
|
+
return self.recvs
|
71
|
+
end
|
72
|
+
|
73
|
+
def set_value_version_check(key, val, version, tag_list=nil)
|
74
|
+
@protocol.set_value_versin_check(self.socket, key, val, version, tag_list)
|
75
|
+
return self.recvs
|
76
|
+
end
|
77
|
+
|
78
|
+
def incr_value(key, val)
|
79
|
+
@protocol.incr_value(self.socket, key, val.to_s)
|
80
|
+
return self.recvs
|
81
|
+
end
|
82
|
+
|
83
|
+
def decr_value(key, val)
|
84
|
+
@protocol.decr_value(self.socket, key, val.to_s)
|
85
|
+
return self.recvs
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_multi_value(key_list, &block)
|
89
|
+
@protocol.get_multi_value(self.socket, key_list)
|
90
|
+
return self.recv_lines(&block)
|
91
|
+
end
|
92
|
+
|
93
|
+
def get_tag_values(tag, &block)
|
94
|
+
@protocol.get_tag_values(self.socket, tag)
|
95
|
+
return self.recv_lines(&block)
|
96
|
+
end
|
97
|
+
|
98
|
+
def remove_tag_from_key(tag, key)
|
99
|
+
@protocol.remove_tag_from_key(self.socket, tag, key)
|
100
|
+
return self.recvs
|
101
|
+
end
|
102
|
+
|
103
|
+
def set_value_and_create_index(key, val, options=nil)
|
104
|
+
if options then
|
105
|
+
tag_list = options[:tags]
|
106
|
+
group = options[:group]
|
107
|
+
min_n = options[:min_n]
|
108
|
+
max_n = options[:max_n]
|
109
|
+
min_n = min_n.to_s if min_n
|
110
|
+
max_n = max_n.to_s if max_n
|
111
|
+
end
|
112
|
+
|
113
|
+
@protocol.set_value_and_create_index(self.socket, key, val, tag_list, group, min_n, max_n)
|
114
|
+
return self.recvs
|
115
|
+
end
|
116
|
+
|
117
|
+
def search_value(query_list, options=nil)
|
118
|
+
if ! query_list.is_a? Array then
|
119
|
+
query_list = [query_list.to_s]
|
120
|
+
end
|
121
|
+
|
122
|
+
if options then
|
123
|
+
condition = options[:condition]
|
124
|
+
group = options[:group]
|
125
|
+
nsize = options[:nsize]
|
126
|
+
nsize = nsize.to_s if nsize
|
127
|
+
case condition
|
128
|
+
when :and
|
129
|
+
condition = '1'
|
130
|
+
else :or
|
131
|
+
condition = '2'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
@protocol.search_value(self.socket, query_list, condition, group, nsize)
|
136
|
+
return self.recvs
|
137
|
+
end
|
138
|
+
|
139
|
+
def method_missiong(method_id, *args, &block)
|
140
|
+
method_name = method_id.to_s
|
141
|
+
if method_name =~ /^message_of_/ then
|
142
|
+
next_method_name = $'
|
143
|
+
result = capture(:stdout) {
|
144
|
+
@protocol.send(method_name, $stdout, *args, &block)
|
145
|
+
}
|
146
|
+
return result
|
147
|
+
else
|
148
|
+
super
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
protected
|
153
|
+
|
154
|
+
def each(&block)
|
155
|
+
while line = socket.gets do
|
156
|
+
line.chomp!
|
157
|
+
if line == "END" then
|
158
|
+
break
|
159
|
+
else
|
160
|
+
yield(line)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def readlines
|
166
|
+
ret = []
|
167
|
+
while line = socket.gets do
|
168
|
+
if line == "END" then
|
169
|
+
break
|
170
|
+
else
|
171
|
+
ret.push line
|
172
|
+
end
|
173
|
+
end
|
174
|
+
return ret
|
175
|
+
end
|
176
|
+
|
177
|
+
def recvs
|
178
|
+
line = self.socket.gets
|
179
|
+
line.chomp!
|
180
|
+
return line
|
181
|
+
end
|
182
|
+
|
183
|
+
def recv_lines(&block)
|
184
|
+
if block_given? then
|
185
|
+
return self.each(&block)
|
186
|
+
else
|
187
|
+
return self.readlines
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def socket
|
192
|
+
if @socket.nil? then
|
193
|
+
retry_count = 0
|
194
|
+
begin
|
195
|
+
@socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
|
196
|
+
sockaddr = Socket.sockaddr_in(@port, @host)
|
197
|
+
if @timeout then
|
198
|
+
secs = Integer(@timeout)
|
199
|
+
usecs = Integer((@timeout - secs) * 1_000_000)
|
200
|
+
optval = [secs, usecs].pack("l_2")
|
201
|
+
@socket.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, optval
|
202
|
+
@socket.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, optval
|
203
|
+
end
|
204
|
+
@socket.connect(sockaddr)
|
205
|
+
rescue Exception => e
|
206
|
+
if retry_count < @retry_max then
|
207
|
+
Okuyama.logger.error "ERROR: #{e.message}"
|
208
|
+
@socket.close if @socket != nil
|
209
|
+
@socket = nil
|
210
|
+
retry_count += 1
|
211
|
+
retry
|
212
|
+
else
|
213
|
+
raise e
|
214
|
+
end
|
215
|
+
@socket = nil
|
216
|
+
raise e
|
217
|
+
end
|
218
|
+
end
|
219
|
+
return @socket
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Okuyama
|
2
|
+
module Protocol
|
3
|
+
class AbstractProtocol
|
4
|
+
def method_missing(method_id, *args, &block)
|
5
|
+
method_name = method_id.to_s
|
6
|
+
if method_name =~ /^message_of_/ then
|
7
|
+
next_method_name = $'
|
8
|
+
result = self.capture(:stdout) {
|
9
|
+
self.send(next_method_name, $stdout, *args, &block)
|
10
|
+
}
|
11
|
+
return result
|
12
|
+
else
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
def capture(*streams)
|
19
|
+
streams.map! { |stream| stream.to_s }
|
20
|
+
begin
|
21
|
+
result = StringIO.new
|
22
|
+
streams.each { |stream| eval "$#{stream} = result" }
|
23
|
+
yield
|
24
|
+
ensure
|
25
|
+
streams.each { |stream| eval("$#{stream} = #{stream.upcase}") }
|
26
|
+
end
|
27
|
+
result.string
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|