roma-client 0.3.7

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