roma-client 0.3.7

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,25 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # = roma/client/proxy/version.rb
4
+ # This file is derived from roma client proxy daemon.
5
+ #
6
+ module Roma #:nodoc:
7
+ module Client #:nodoc:
8
+ # == What Is This Library?
9
+ # ROMA client proxy daemon's version module
10
+ #
11
+ module VERSION
12
+ # メジャーバージョン
13
+ MAJOR = 0
14
+
15
+ # マイナバージョン
16
+ MINOR = 1
17
+
18
+ # TINY version
19
+ TINY = 0
20
+
21
+ # バージョン文字列
22
+ STRING = [MAJOR, MINOR, TINY].join('.')
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,409 @@
1
+ require 'digest/sha1'
2
+ require 'socket'
3
+ require 'singleton'
4
+ require 'roma/client/con_pool'
5
+ require 'roma/client/client_rttable'
6
+ require 'roma/client/sender'
7
+
8
+ module Roma
9
+ module Client
10
+
11
+ # Class to access ROMA .
12
+ class RomaClient
13
+
14
+ # ROMA server connect timeout .
15
+ @@timeout = 5
16
+
17
+ attr_accessor :rttable
18
+ attr_accessor :sender
19
+ attr_accessor :retry_count_write
20
+ attr_accessor :retry_count_read
21
+ attr_accessor :default_hash_name
22
+
23
+ # ROMA client constractor .
24
+ #
25
+ # [ini_nodes] ROMA nodes array
26
+ # [plugin_modules] set plugin modules if you use .
27
+ def initialize(ini_nodes,plugin_modules = nil)
28
+ @retry_count_write = 10
29
+ @retry_count_read = 5
30
+ @default_hash_name = 'roma'
31
+
32
+ if plugin_modules
33
+ plugin_modules.each do|plugin|
34
+ self.extend plugin
35
+ end
36
+ end
37
+
38
+ init_sender
39
+ update_rttable(ini_nodes.map{|n| n.sub(':','_')})
40
+ init_sync_routing_proc
41
+ end
42
+
43
+ def init_sync_routing_proc
44
+ Thread.new {
45
+ begin
46
+ loop {
47
+ sleep 10
48
+ update_rttable(@rttable.nodes)
49
+ }
50
+ rescue => e
51
+ puts "#{e}\n#{$@}"
52
+ end
53
+ }
54
+ end
55
+ private :init_sync_routing_proc
56
+
57
+ def init_sender
58
+ @sender = Sender.new
59
+ end
60
+ private :init_sender
61
+
62
+ def update_rttable(nodes)
63
+ raise RuntimeError.new("nodes must not be nil.") unless nodes
64
+
65
+ nodes.each { |node|
66
+ rt = make_rttable(node)
67
+ if rt
68
+ @rttable = rt
69
+ return
70
+ end
71
+ }
72
+
73
+ raise RuntimeError.new("fatal error")
74
+ end
75
+
76
+ def make_rttable(node)
77
+ mklhash = @sender.send_route_mklhash_command(node)
78
+ return nil unless mklhash
79
+
80
+ if @rttable && @rttable.mklhash == mklhash
81
+ return @rttable
82
+ end
83
+
84
+ rd = @sender.send_routedump_command(node)
85
+ if rd
86
+ ret = ClientRoutingTable.new(rd)
87
+ ret.mklhash = mklhash
88
+ return ret
89
+ end
90
+ nil
91
+ rescue
92
+ nil
93
+ end
94
+
95
+ # Set value to ROMA .
96
+ # please see set method .
97
+ def []=(key, value)
98
+ set(key, value)
99
+ end
100
+
101
+ # Get value from ROMA .
102
+ # [key] key for roma.
103
+ # <tt>returen</tt>
104
+ # value sotored roma .
105
+ # If key don't exit ROMA, return nil .
106
+ # If coneect error, throw Exception .
107
+ def [](key)
108
+ get(key)
109
+ end
110
+
111
+ # Set value to ROMA .
112
+ #
113
+ # Both same same key exists or not exists in ROMA, this method set value .
114
+ #
115
+ # [key] key for store .
116
+ # [value] store value .
117
+ # [exp] expire seconds .
118
+ # [raw] You set this value true, value isn't marshaled .
119
+ #
120
+ # [return] return follow set status .
121
+ # - If method is success, return STORED .
122
+ # - If method is not stored, return NOT_STORED .
123
+ # - If server error, return SERVER_ERROR .
124
+ #
125
+ # If socket error occured, throw Exception .
126
+ #
127
+ # If socket timeout occured, throw TimeoutError .
128
+ def set(key, val, expt = 0, raw = false)
129
+ val = Marshal.dump(val) unless raw
130
+ sender(:oneline_receiver, key, val, "set %s 0 %d %d", expt.to_i, val.length)
131
+ end
132
+
133
+ # Add value to ROMA .
134
+ #
135
+ # If same key exists in ROMA, this method don't overwrite value
136
+ # and return NOT_STORED .
137
+ #
138
+ # [key] key for store .
139
+ # [value] store value .
140
+ # [exp] expire seconds .
141
+ # [raw] You set this value true, value isn't marshaled .
142
+ #
143
+ # [return] return follow set status .
144
+ # - If method is success, return STORED .
145
+ # - If same key exists in ROMA, return NOT_STORED .
146
+ # - If server error, return SERVER_ERROR .
147
+ #
148
+ # If socket error occured, throw Exception .
149
+ #
150
+ # If socket timeout occured, throw TimeoutError .
151
+ def add(key, val, expt = 0, raw = false)
152
+ val = Marshal.dump(val) unless raw
153
+ sender(:oneline_receiver, key, val, "add %s 0 %d %d", expt.to_i, val.length)
154
+ end
155
+
156
+ # Add value to ROMA .
157
+ #
158
+ # If same key exists in ROMA, this method overwrite value .
159
+ # If same key doesn't exist in ROMA this method don't store value and
160
+ # return NOT_STORE .
161
+ #
162
+ # [key] key for store .
163
+ # [value] store value .
164
+ # [exp] expire seconds .
165
+ # [raw] You set this value true, value isn't marshaled .
166
+ #
167
+ # [return] return follow set status .
168
+ # - If method is success, return STORED .
169
+ # - If same key exists in ROMA, return NOT_STORED .
170
+ # - If server error, return SERVER_ERROR .
171
+ #
172
+ # If socket error occured, throw Exception .
173
+ #
174
+ # If socket timeout occured, throw TimeoutError .
175
+ def replace(key, val, expt = 0, raw = false)
176
+ val = Marshal.dump(val) unless raw
177
+ sender(:oneline_receiver, key, val, "replace %s 0 %d %d", expt.to_i, val.length)
178
+ end
179
+
180
+ # Append value to exists string .
181
+ #
182
+ # If same key exists in ROMA, this method append value .
183
+ # If same key doesn't exist in ROMA this method don't store value and
184
+ # return NOT_STORE .
185
+ #
186
+ # [key] key for append .
187
+ # [value] append value .
188
+ # [exp] expire seconds .
189
+ #
190
+ # [return] return follow set status .
191
+ # - If method is success, return STORED .
192
+ # - If same key exists in ROMA, return NOT_STORED .
193
+ # - If server error, return SERVER_ERROR .
194
+ #
195
+ # If socket error occured, throw Exception .
196
+ #
197
+ # If socket timeout occured, throw TimeoutError .
198
+ def append(key, val, expt = 0)
199
+ sender(:oneline_receiver, key, val, "append %s 0 %d %d", expt.to_i, val.length)
200
+ end
201
+
202
+ # Prepend value to exists string .
203
+ #
204
+ # If same key exists in ROMA, this method prepend value .
205
+ # If same key doesn't exist in ROMA this method don't store value and
206
+ # return NOT_STORE .
207
+ #
208
+ # [key] key for prepend .
209
+ # [value] prepend value .
210
+ # [exp] expire seconds .
211
+ #
212
+ # [return] return follow set status .
213
+ # - If method is success, return STORED .
214
+ # - If same key exists in ROMA, return NOT_STORED .
215
+ # - If server error, return SERVER_ERROR .
216
+ #
217
+ # If socket error occured, throw Exception .
218
+ #
219
+ # If socket timeout occured, throw TimeoutError .
220
+ def prepend(key, val, expt = 0)
221
+ sender(:oneline_receiver, key, val, "prepend %s 0 %d %d", expt.to_i, val.length)
222
+ end
223
+
224
+ def cas(key, val, expt = 0)
225
+ raise RuntimeError.new("Unsupported yet") # TODO
226
+ end
227
+
228
+ # Delete value .
229
+ #
230
+ # [key] key for delete .
231
+ #
232
+ # [return] return follow set status .
233
+ # - If method is success, return DELETED .
234
+ # - If same key doesn't exist in ROMA, return NOT_FOUND .
235
+ # - If server error, return SERVER_ERROR .
236
+ #
237
+ # If socket error occured, throw Exception .
238
+ #
239
+ # If socket timeout occured, throw TimeoutError .
240
+ def delete(key)
241
+ sender(:oneline_receiver, key, nil, "delete %s")
242
+ end
243
+
244
+ # Delete value completely .
245
+ #
246
+ # This method delete value completely. "completely" means
247
+ # Don't set delete flag in server, but delete value in storage .
248
+ # Delete method set delete flag, but delete value soon .
249
+ #
250
+ # [key] key for delete .
251
+ #
252
+ # [return] return follow set status .
253
+ # - If method is success, return DELETED .
254
+ # - If same key doesn't exist in ROMA, return NOT_FOUND .
255
+ # - If server error, return SERVER_ERROR .
256
+ #
257
+ # If socket error occured, throw Exception .
258
+ #
259
+ # If socket timeout occured, throw TimeoutError .
260
+ def out(key)
261
+ sender(:oneline_receiver, key, nil, "out %s")
262
+ end
263
+
264
+ # get value
265
+ #
266
+ # [key] key for get .
267
+ # [raw] If you set this value true, value isn't Marshal.load value .
268
+ #
269
+ # [return] return stored value in ROMA .
270
+ # If key doesn't exist in ROMA, this method return nil .
271
+ #
272
+ # If socket error occured, throw Exception .
273
+ #
274
+ # If socket timeout occured, throw TimeoutError .
275
+ def get(key, raw = false)
276
+ val = sender(:value_list_receiver, key, nil, "get %s")[0]
277
+ return nil if val.nil?
278
+ val = Marshal.load(val) unless raw
279
+ val
280
+ end
281
+
282
+ # get values .
283
+ #
284
+ # [keys] key array for get .
285
+ # [raw] If you set this value true, value isn't Marshal.load value .
286
+ #
287
+ # [return] return key and sotored value hash .
288
+ # If all key doesn't exist in ROMA, return empty hash .
289
+ # If some key doesn't exist in ROMA, return exist key and sotred value hash .
290
+ #
291
+ # If socket error occured, throw Exception .
292
+ #
293
+ # If socket timeout occured, throw TimeoutError .
294
+ def gets(keys, raw = false)
295
+ kn = {}
296
+ keys.each{|key|
297
+ nid, d = @rttable.search_node(key)
298
+ kn[nid] ||= []
299
+ kn[nid] << key
300
+ }
301
+
302
+ res = {}
303
+ kn.each_pair{|nid,ks|
304
+ res.merge!(gets_sender(nid, ks))
305
+ }
306
+ unless raw
307
+ res.each do |key, val|
308
+ res[key] = Marshal.load(val)
309
+ end
310
+ end
311
+ res
312
+ end
313
+
314
+ def flush_all()
315
+ raise RuntimeError.new("Unsupported yet") # TODO
316
+ @sender.send_flush_all_command
317
+ end
318
+
319
+ # increment value .
320
+ #
321
+ # [key] key for incremental .
322
+ # [val] incremental value .
323
+ #
324
+ # [return] Fixnum incrementaled value .
325
+ # If same key doesn't exist in ROMA, return NOT_FOUND .
326
+ #
327
+ # If socket error occured, throw Exception .
328
+ #
329
+ # If socket timeout occured, throw TimeoutError .
330
+ def incr(key, val = 1)
331
+ ret = sender(:oneline_receiver, key, nil, "incr %s %d", val.to_i)
332
+ return ret if ret =~ /\D/
333
+ ret.to_i
334
+ end
335
+
336
+ # decrement value .
337
+ #
338
+ # [key] key for decremental .
339
+ # [val] decremental value .
340
+ #
341
+ # [return] Fixnum decrementaled value .
342
+ # If same key doesn't exist in ROMA, return NOT_FOUND .
343
+ #
344
+ # If socket error occured, throw Exception .
345
+ #
346
+ # If socket timeout occured, throw TimeoutError .
347
+ def decr(key, val = 1)
348
+ ret = sender(:oneline_receiver, key, nil, "decr %s %d", val.to_i)
349
+ return ret if ret =~ /\D/
350
+ ret.to_i
351
+ end
352
+
353
+ def stats
354
+ raise RuntimeError.new("Unsupported yet") # TODO
355
+ @sender.send_stats_command
356
+ end
357
+
358
+ def version
359
+ raise RuntimeError.new("Unsupported yet") # TODO
360
+ @sender.send_version_command
361
+ end
362
+
363
+ def verbosity
364
+ raise RuntimeError.new("Unsupported yet") # TODO
365
+ @sender.send_verbosity_command
366
+ end
367
+
368
+ private
369
+
370
+ def sender(receiver, key, value ,cmd, *params)
371
+ nid, d = @rttable.search_node(key)
372
+ cmd2 = sprintf(cmd, "#{key}\e#{@default_hash_name}", *params)
373
+
374
+ timeout(@@timeout){
375
+ return @sender.send_command(nid, cmd2, value, receiver)
376
+ }
377
+ rescue => e
378
+ unless e.instance_of?(RuntimeError)
379
+ @rttable.proc_failed(nid)
380
+ ConPool.instance.delete_connection(nid)
381
+ end
382
+ sleep 0.3
383
+ retry if (cnt ||= 0; cnt += 1) < @retry_count_write
384
+ raise e
385
+ end
386
+
387
+ def gets_sender(nid, keys)
388
+ cmd = "gets"
389
+ keys.each{ |k|
390
+ cmd << " #{k}\e#{@default_hash_name}"
391
+ }
392
+
393
+ timeout(@@timeout){
394
+ return @sender.send_command(nid, cmd, nil, :value_hash_receiver)
395
+ }
396
+ rescue => e
397
+ unless e.instance_of?(RuntimeError)
398
+ @rttable.proc_failed(nid)
399
+ ConPool.instance.delete_connection(nid)
400
+ end
401
+ sleep 0.3
402
+ retry if (cnt ||= 0; cnt += 1) < @retry_count_write
403
+ raise e
404
+ end
405
+
406
+ end # class RomaClient
407
+
408
+ end # module Client
409
+ end # module Roma
@@ -0,0 +1,148 @@
1
+ # ROMA's logger.
2
+ #
3
+ # rlogger.rb - it is an extension to a standard logger for ROMA
4
+ #
5
+ require 'logger'
6
+
7
+ module Roma
8
+ module Logging
9
+
10
+ class RLogger
11
+ VERSION = '0.0.1'
12
+
13
+ module Severity
14
+ TRACE = -1
15
+ DEBUG = 0
16
+ INFO = 1
17
+ WARN = 2
18
+ ERROR = 3
19
+ FATAL = 4
20
+ UNKNOWN = 5
21
+ end
22
+ include Severity
23
+
24
+ module ExtLogDev
25
+ def extendLogDev()
26
+ if @logdev
27
+ @logdev.extend(ExtShiftAge)
28
+ end
29
+ end
30
+ end
31
+
32
+ module ExtShiftAge
33
+ private
34
+ def shift_log_period(now)
35
+ postfix = previous_period_end(now).strftime("%Y%m%d%H%M")
36
+ age_file = "#{@filename}.#{postfix}"
37
+ if FileTest.exist?(age_file)
38
+ raise RuntimeError.new("'#{age_file}' already exists.")
39
+ end
40
+ @dev.close
41
+ File.rename(@filename, age_file)
42
+ @dev = create_logfile(@filename)
43
+ return true
44
+ end
45
+
46
+ def previous_period_end(now)
47
+ ret = nil
48
+ case @shift_age
49
+ when /^min$/
50
+ t = now - 1 * 60
51
+ ret = Time.mktime(t.year, t.month, t.mday, t.hour, t.min, 59)
52
+ when /^hour$/
53
+ t = now - 1 * 60 * 60
54
+ ret = Time.mktime(t.year, t.month, t.mday, t.hour, 59, 59)
55
+ when /^daily$/
56
+ ret = eod(now - 1 * SiD)
57
+ when /^weekly$/
58
+ ret = eod(now - ((now.wday + 1) * SiD))
59
+ when /^monthly$/
60
+ ret = eod(now - now.mday * SiD)
61
+ else
62
+ ret = now
63
+ end
64
+ return ret
65
+ end
66
+ end
67
+
68
+ module ExtTrace
69
+ private
70
+ SEV_LABEL = %w{DEBUG INFO WARN ERROR FATAL ANY}
71
+
72
+ def format_severity(severity)
73
+ if @level <= RLogger::TRACE and severity <= RLogger::TRACE
74
+ return 'TRACE'
75
+ else
76
+ return SEV_LABEL[severity] || 'ANY'
77
+ end
78
+ end
79
+ end
80
+
81
+ @@singleton_instance = nil
82
+
83
+ def self.create_singleton_instance(logdev, shift_age = 0, shift_size = 1048576)
84
+ @@singleton_instance = RLogger.new(logdev, shift_age, shift_size)
85
+ private_class_method :new, :allocate
86
+ end
87
+
88
+ def self.instance
89
+ @@singleton_instance
90
+ end
91
+
92
+ def initialize(logdev, shift_age = 0, shift_size = 1048576)
93
+ @wrap_logger = Logger.new(logdev, shift_age, shift_size)
94
+ @wrap_logger.extend(ExtTrace)
95
+ @wrap_logger.extend(ExtLogDev)
96
+ @wrap_logger.extendLogDev()
97
+ end
98
+
99
+ def level=(severity)
100
+ @wrap_logger.level = severity
101
+ end
102
+
103
+ def trace?; @wrap_logger.level <= TRACE; end
104
+
105
+ def debug?; @wrap_logger.debug?; end
106
+
107
+ def info?; @wrap_logger.info?; end
108
+
109
+ def warn?; @wrap_logger.warn?; end
110
+
111
+ def error?; @wrap_logger.error?; end
112
+
113
+ def fatal?; @wrap_logger.fatal?; end
114
+
115
+ def trace(progname = nil, &block)
116
+ @wrap_logger.add(TRACE, nil, progname, &block)
117
+ end
118
+
119
+ def debug(progname = nil, &block)
120
+ @wrap_logger.debug(progname, &block)
121
+ end
122
+
123
+ def info(progname = nil, &block)
124
+ @wrap_logger.info(progname, &block)
125
+ end
126
+
127
+ def warn(progname = nil, &block)
128
+ @wrap_logger.warn(progname, &block)
129
+ end
130
+
131
+ def error(progname = nil, &block)
132
+ @wrap_logger.error(progname, &block)
133
+ end
134
+
135
+ def fatal(progname = nil, &block)
136
+ @wrap_logger.fatal(progname, &block)
137
+ end
138
+
139
+ def unknown(progname = nil, &block)
140
+ @wrap_logger.unknow(progname, &block)
141
+ end
142
+
143
+ def close; @wrap_logger.close; end
144
+
145
+ end # class RLogger
146
+
147
+ end # module Logging
148
+ end # module Roma