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,241 @@
1
+ require 'yaml'
2
+
3
+ module Roma
4
+ module Routing
5
+
6
+ class RoutingData
7
+ attr_accessor :dgst_bits
8
+ attr_accessor :div_bits
9
+ attr_accessor :rn
10
+ attr_accessor :nodes
11
+ attr_accessor :v_idx
12
+ attr_accessor :v_clk
13
+
14
+ def initialize(dgst_bits,div_bits,rn)
15
+ @dgst_bits=dgst_bits
16
+ @div_bits=div_bits
17
+ @rn=rn
18
+ @nodes=[]
19
+ @v_idx={}
20
+ @v_clk={}
21
+ end
22
+
23
+ def save(fname)
24
+ @nodes.sort!
25
+ open(fname,'wb'){|io|
26
+ io.write(YAML.dump(self))
27
+ }
28
+ end
29
+
30
+ def self.load(fname)
31
+ rd=load_snapshot(fname)
32
+ rd.load_log_all(fname)
33
+ rd
34
+ end
35
+
36
+ def self.load_snapshot(fname)
37
+ rd=nil
38
+ open(fname,'rb'){|io|
39
+ rd = YAML.load(io.read)
40
+ }
41
+ rd
42
+ end
43
+
44
+ def self.snapshot(fname)
45
+ rd=load_snapshot(fname)
46
+ loglist=rd.get_file_list(fname)
47
+ if loglist.length<2
48
+ return false
49
+ end
50
+ loglist.delete(loglist.last)
51
+ loglist.each{|i,f|
52
+ rd.load_log_one(f)
53
+ File.rename(f,"#{f}~")
54
+ }
55
+ File.rename(fname,"#{fname}~")
56
+ rd.save(fname)
57
+ true
58
+ end
59
+
60
+ def each_log_all(fname)
61
+ loglist=get_file_list(fname)
62
+ loglist.each{|i,f|
63
+ each_log_one(f){|t,l| yield t,l}
64
+ }
65
+ end
66
+
67
+ def each_log_one(fname)
68
+ File.open(fname,"r"){|f|
69
+ while((line=f.gets)!=nil)
70
+ line.chomp!
71
+ next if line[0]=="#" || line.length==0
72
+ if line =~ /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.\d+\s(.+)/
73
+ yield Time.mktime($1, $2, $3, $4, $5, $6), $7
74
+ end
75
+ end
76
+ }
77
+ end
78
+
79
+ def load_log_all(fname)
80
+ each_log_all(fname){|t,line|
81
+ parse_log(t,line)
82
+ }
83
+ @nodes.sort!
84
+ end
85
+
86
+ def load_log_one(fname)
87
+ each_log_one(fname){|t,line|
88
+ parse_log(t,line)
89
+ }
90
+ @nodes.sort!
91
+ end
92
+
93
+ def parse_log(t,line)
94
+ s=line.split(' ')
95
+ case s[0]
96
+ when 'setroute'
97
+ # setroute <vnode-id> <clock> <node-id> ...
98
+ nids=[]
99
+ s[3..-1].each{ |nid| nids << nid }
100
+ @v_idx[s[1].to_i]=nids
101
+ @v_clk[s[1].to_i]=s[2].to_i
102
+ when 'join'
103
+ # join <node-id>
104
+ @nodes << s[1] unless @nodes.include?(s[1])
105
+ when 'leave'
106
+ # leave <node-id>
107
+ @nodes.delete(s[1])
108
+ else
109
+ raise "RoutingData.parse_log:parse error #{line}"
110
+ end
111
+ end
112
+
113
+ def search_mask
114
+ 2**@div_bits-1<<(@dgst_bits-@div_bits)
115
+ end
116
+
117
+ def next_vnode(vn)
118
+ n = (vn >> (@dgst_bits-@div_bits)) + 1
119
+ n = 0 if n == (2**@div_bits)
120
+ n << (@dgst_bits-@div_bits)
121
+ end
122
+
123
+ def create_nodes_from_v_idx
124
+ buf_nodes={}
125
+ v_idx.each_value{|nids|
126
+ nids.each{|nid| buf_nodes[nid]=nid }
127
+ }
128
+ @nodes=buf_nodes.values.sort
129
+ end
130
+
131
+ # Returns the losted vnode-id list.
132
+ def get_lost_vnodes
133
+ ret=[]
134
+ v_idx.each_pair{|vn,nids|
135
+ ret << vn if nids.length == 0
136
+ }
137
+ ret
138
+ end
139
+
140
+ def self.create(dgst_bits,div_bits,rn,nodes,repethost=false)
141
+ ret=RoutingData.new(dgst_bits,div_bits,rn)
142
+ ret.nodes=nodes.clone
143
+
144
+ rnlm=RandomNodeListMaker.new(nodes,repethost)
145
+
146
+ (2**div_bits).times{|i|
147
+ vn=i<<(dgst_bits-div_bits)
148
+ ret.v_clk[vn]=0
149
+ ret.v_idx[vn]=rnlm.list(rn)
150
+ }
151
+ ret
152
+ end
153
+
154
+ # Returns the log file list by old ordered.
155
+ # +fname+:: Prefix of a log file.(ex.roma0_3300.route)
156
+ # One of the following example:
157
+ # [[1, "roma0_3300.route.1"], [2, "roma0_3300.route.2"]]
158
+ def get_file_list(fname)
159
+ l={}
160
+ files=Dir.glob("#{fname}*")
161
+ files.each{ |file|
162
+ if /#{fname}\.(\d+)$/=~file
163
+ l[$1.to_i]=$&
164
+ end
165
+ }
166
+ # sorted by old order
167
+ l.to_a.sort{|a,b| a[0]<=>b[0]}
168
+ end
169
+
170
+ def get_histgram
171
+ ret = {}
172
+ nodes.each{|nid|
173
+ ret[nid] = Array.new(rn,0)
174
+ }
175
+ v_idx.each_pair{|vn,nids|
176
+ nids.each_with_index{|nid,i|
177
+ ret[nid][i] += 1
178
+ }
179
+ }
180
+ ret
181
+ end
182
+
183
+ private
184
+
185
+ class RandomNodeListMaker
186
+ def initialize(nodes,repethost)
187
+ @repethost=repethost
188
+ @nodes=nodes
189
+ @host_idx={}
190
+ nodes.each{|nid|
191
+ h,p=nid.split('_')
192
+ if @host_idx.key?(h)
193
+ @host_idx[h] << nid
194
+ else
195
+ @host_idx[h]=[nid]
196
+ end
197
+ }
198
+ end
199
+
200
+ # Returns the random node-list without repetition.
201
+ # +n+:: list length
202
+ def list(n)
203
+ ret=[]
204
+ hosts=[]
205
+ proc_other_one = :get_other_one
206
+ proc_other_one = :get_other_one_repethost if @repethost
207
+ n.times{
208
+ nid=nil
209
+ nid=send(proc_other_one,hosts,ret)
210
+ break unless nid
211
+ hosts << nid.split('_')[0]
212
+ ret << nid
213
+ }
214
+ ret
215
+ end
216
+
217
+ # +exp_hosts+:: ignore
218
+ # +exp_nodes+:: exceptional nodes(ex.['roma0_11211'])
219
+ def get_other_one_repethost(exp_hosts,exp_nodes)
220
+ buf=@nodes.clone
221
+ buf.delete_if{|nid| exp_nodes.include?(nid)}
222
+ buf[rand(buf.length)]
223
+ end
224
+
225
+ # +exp_hosts+:: exceptional hosts(ex.['roma0','roma1'])
226
+ # +exp_nodes+:: ignore
227
+ def get_other_one(exp_hosts,exp_nodes)
228
+ hidx=@host_idx.clone
229
+ exp_hosts.each{|h| hidx.delete(h) }
230
+ return nil if hidx.length == 0
231
+
232
+ rh=hidx.keys[rand(hidx.keys.length)]
233
+ nodes=hidx[rh]
234
+ nodes[rand(nodes.length)]
235
+ end
236
+ end # class RandomNodeListMaker
237
+
238
+ end # class RoutingData
239
+
240
+ end # module Routing
241
+ end # module Roma
@@ -0,0 +1,155 @@
1
+ require 'timeout'
2
+ require 'yaml'
3
+ require 'roma/client/con_pool'
4
+
5
+ module Roma
6
+ module Client
7
+
8
+ class Sender
9
+
10
+ def initialize
11
+ end
12
+
13
+ def send_route_mklhash_command(node_id)
14
+ timeout(1){
15
+ conn = ConPool.instance.get_connection(node_id)
16
+ conn.write "mklhash 0\r\n"
17
+ ret = conn.gets
18
+ ConPool.instance.return_connection(node_id, conn)
19
+ return ret.chomp if ret
20
+ }
21
+ rescue =>e
22
+ STDERR.puts "#{node_id} #{e.inspect}"
23
+ return nil
24
+ end
25
+
26
+ def send_routedump_command(node_id)
27
+ timeout(1){
28
+ buf = RUBY_VERSION.split('.')
29
+ if buf[0].to_i == 1 && buf[1].to_i == 8
30
+ return send_routedump_yaml_command(node_id)
31
+ end
32
+ conn = ConPool.instance.get_connection(node_id)
33
+ conn.write "routingdump\r\n"
34
+ routes_length = conn.gets.to_i
35
+ if (routes_length <= 0)
36
+ conn.close
37
+ return :error if routes_length < 0
38
+ return nil
39
+ end
40
+
41
+ routes = ''
42
+ while (routes.length != routes_length)
43
+ routes = routes + conn.read(routes_length - routes.length)
44
+ end
45
+ conn.read(2) # "\r\n"
46
+ conn.gets
47
+ rd = Marshal.load(routes)
48
+ ConPool.instance.return_connection(node_id, conn)
49
+ return rd
50
+ }
51
+ rescue =>e
52
+ STDERR.puts "#{node_id} #{e.inspect}"
53
+ nil
54
+ end
55
+
56
+ def send_routedump_yaml_command(node_id)
57
+ conn = ConPool.instance.get_connection(node_id)
58
+ conn.write "routingdump yaml\r\n"
59
+
60
+ yaml = ''
61
+ while( (line = conn.gets) != "END\r\n" )
62
+ yaml << line
63
+ end
64
+
65
+ rd = YAML.load(yaml)
66
+ ConPool.instance.return_connection(node_id, conn)
67
+ return rd
68
+ end
69
+
70
+ def send_stats_command
71
+ # TODO
72
+ end
73
+
74
+ def send_version_command(ap)
75
+ conn = ConPool.instance.get_connection(ap)
76
+ conn.write("version\r\n")
77
+ res = conn.gets.chomp
78
+ ConPool.instance.return_connection(ap, conn)
79
+ raise unless res
80
+ return res
81
+ end
82
+
83
+ def send_verbosity_command(ap)
84
+ conn = ConPool.instance.get_connection(ap)
85
+ # TODO
86
+ ConPool.instance.return_connection(ap, conn)
87
+ end
88
+
89
+ def send_command(nid, cmd, value = nil, receiver = :oneline_receiver)
90
+ con = ConPool.instance.get_connection(nid)
91
+ raise unless con
92
+ if value
93
+ con.write "#{cmd}\r\n#{value}\r\n"
94
+ else
95
+ con.write "#{cmd}\r\n"
96
+ end
97
+ ret = send(receiver, con)
98
+ ConPool.instance.return_connection(nid, con)
99
+ if ret && ret.instance_of?(String) &&
100
+ (ret =~ /^SERVER_ERROR/ || ret =~ /^CLIENT_ERROR/)
101
+ raise ret
102
+ end
103
+ ret
104
+ end
105
+
106
+ private
107
+
108
+ def oneline_receiver(con)
109
+ ret = con.gets
110
+ raise "connection closed" if ret.nil?
111
+ ret.chomp
112
+ end
113
+
114
+ def value_list_receiver(con)
115
+ ret = []
116
+ while (line = con.gets) != "END\r\n"
117
+ s = line.split(' ')
118
+ return line.chomp if s[0] == 'SERVER_ERROR' || s[0] == 'CLIENT_ERROR'
119
+ ret << read_bytes(con, s[3].to_i)
120
+ read_bytes(con, 2)
121
+ end
122
+ ret
123
+ end
124
+
125
+ def value_hash_receiver(con)
126
+ ret = {}
127
+ while (line = con.gets) != "END\r\n"
128
+ s = line.split(' ')
129
+ return line.chomp if s[0] == 'SERVER_ERROR' || s[0] == 'CLIENT_ERROR'
130
+ ret[s[1]] = read_bytes(con, s[3].to_i)
131
+ read_bytes(con, 2)
132
+ end
133
+ ret
134
+ end
135
+
136
+ def multiplelines_receiver(con)
137
+ ret = []
138
+ while (line = con.gets) != "END\r\n"
139
+ ret << line.chomp
140
+ end
141
+ ret
142
+ end
143
+
144
+ def read_bytes(con, len)
145
+ ret = ''
146
+ until (ret.length == len)
147
+ ret = ret + con.read(len - ret.length)
148
+ end
149
+ ret
150
+ end
151
+
152
+ end
153
+
154
+ end
155
+ end
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'roma/client/sender'
4
+ require 'roma/client/routing/routing_data'
5
+
6
+ if ARGV.length < 1
7
+ STDERR.puts "usage:#{$0} node-id"
8
+ exit
9
+ end
10
+
11
+ sender = Roma::Client::Sender.new
12
+ rd = sender.send_routedump_command(ARGV[0])
13
+ hist = rd.get_histgram
14
+
15
+ # max length of node-id string
16
+ len_nid = 0
17
+ rd.nodes.each{|nid|
18
+ len_nid = nid.length if nid.length > len_nid
19
+ }
20
+
21
+ csum = Array.new(rd.rn, 0)
22
+ rd.nodes.each{|nid|
23
+ puts sprintf("%-#{len_nid}s %s %d",
24
+ nid,
25
+ hist[nid].inspect,
26
+ hist[nid].inject{|r,n| r + n})
27
+ hist[nid].each_with_index{|n,i|
28
+ csum[i] += n
29
+ }
30
+ }
31
+
32
+ puts sprintf("%#{len_nid}s %s","sum",csum.inspect)
33
+
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # = roma/client/version.rb
4
+ # This file is derived from roma client.
5
+ #
6
+ module Roma #:nodoc:
7
+ module Client #:nodoc:
8
+ # == What Is This Library?
9
+ # ROMA クライアントバージョン情報モジュール
10
+ #
11
+ module VERSION
12
+ # メジャーバージョン
13
+ MAJOR = 0
14
+
15
+ # マイナバージョン
16
+ MINOR = 3
17
+
18
+ # TINY version
19
+ TINY = 7
20
+
21
+ # バージョン文字列
22
+ STRING = [MAJOR, MINOR, TINY].join('.')
23
+ end
24
+ end
25
+ end