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,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