ls4 0.9.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/AUTHORS +1 -0
- data/COPYING +661 -0
- data/ChangeLog +9 -0
- data/NOTICE +8 -0
- data/README.rdoc +61 -0
- data/bin/ls4-cs +3 -0
- data/bin/ls4-ds +3 -0
- data/bin/ls4-gw +3 -0
- data/bin/ls4-standalone +3 -0
- data/bin/ls4cmd +3 -0
- data/bin/ls4ctl +3 -0
- data/bin/ls4rpc +3 -0
- data/bin/ls4stat +3 -0
- data/bin/ls4top +3 -0
- data/lib/ls4/command/cmd.rb +241 -0
- data/lib/ls4/command/cs.rb +190 -0
- data/lib/ls4/command/ctl.rb +278 -0
- data/lib/ls4/command/ds.rb +335 -0
- data/lib/ls4/command/gw.rb +256 -0
- data/lib/ls4/command/rpc.rb +172 -0
- data/lib/ls4/command/standalone.rb +318 -0
- data/lib/ls4/command/stat.rb +244 -0
- data/lib/ls4/command/top.rb +291 -0
- data/lib/ls4/default.rb +26 -0
- data/lib/ls4/lib/cclog.rb +220 -0
- data/lib/ls4/lib/ebus.rb +553 -0
- data/lib/ls4/lib/vbcode.rb +228 -0
- data/lib/ls4/logic/fault_detector.rb +212 -0
- data/lib/ls4/logic/membership.rb +253 -0
- data/lib/ls4/logic/node.rb +66 -0
- data/lib/ls4/logic/okey.rb +45 -0
- data/lib/ls4/logic/tsv_data.rb +81 -0
- data/lib/ls4/logic/weight.rb +166 -0
- data/lib/ls4/service/balance.rb +62 -0
- data/lib/ls4/service/base.rb +29 -0
- data/lib/ls4/service/bus.rb +37 -0
- data/lib/ls4/service/config.rb +63 -0
- data/lib/ls4/service/config_cs.rb +33 -0
- data/lib/ls4/service/config_ds.rb +56 -0
- data/lib/ls4/service/config_gw.rb +42 -0
- data/lib/ls4/service/data_client.rb +122 -0
- data/lib/ls4/service/data_server.rb +168 -0
- data/lib/ls4/service/data_server_url.rb +83 -0
- data/lib/ls4/service/gateway.rb +375 -0
- data/lib/ls4/service/gateway_ro.rb +91 -0
- data/lib/ls4/service/gw_http.rb +821 -0
- data/lib/ls4/service/heartbeat.rb +182 -0
- data/lib/ls4/service/log.rb +81 -0
- data/lib/ls4/service/master_select.rb +148 -0
- data/lib/ls4/service/mds.rb +292 -0
- data/lib/ls4/service/mds_cache.rb +294 -0
- data/lib/ls4/service/mds_cache_mem.rb +63 -0
- data/lib/ls4/service/mds_cache_memcached.rb +65 -0
- data/lib/ls4/service/mds_ha.rb +176 -0
- data/lib/ls4/service/mds_memcache.rb +209 -0
- data/lib/ls4/service/mds_tc.rb +508 -0
- data/lib/ls4/service/mds_tt.rb +472 -0
- data/lib/ls4/service/membership.rb +331 -0
- data/lib/ls4/service/process.rb +90 -0
- data/lib/ls4/service/rpc.rb +50 -0
- data/lib/ls4/service/rpc_cs.rb +101 -0
- data/lib/ls4/service/rpc_ds.rb +96 -0
- data/lib/ls4/service/rpc_gw.rb +255 -0
- data/lib/ls4/service/rts.rb +94 -0
- data/lib/ls4/service/rts_file.rb +76 -0
- data/lib/ls4/service/rts_memory.rb +55 -0
- data/lib/ls4/service/slave.rb +132 -0
- data/lib/ls4/service/stat.rb +91 -0
- data/lib/ls4/service/stat_cs.rb +25 -0
- data/lib/ls4/service/stat_ds.rb +40 -0
- data/lib/ls4/service/stat_gw.rb +25 -0
- data/lib/ls4/service/storage.rb +116 -0
- data/lib/ls4/service/storage_dir.rb +201 -0
- data/lib/ls4/service/sync.rb +206 -0
- data/lib/ls4/service/time_check.rb +80 -0
- data/lib/ls4/service/ulog.rb +159 -0
- data/lib/ls4/service/ulog_file.rb +398 -0
- data/lib/ls4/service/ulog_memory.rb +53 -0
- data/lib/ls4/service/weight.rb +134 -0
- data/lib/ls4/version.rb +5 -0
- data/test/01_add_get_remove.rt +84 -0
- data/test/02_read.rt +61 -0
- data/test/03_getd_readd.rt +69 -0
- data/test/04_version_time.rt +170 -0
- data/test/05_version_name.rt +161 -0
- data/test/06_http_get_set_remove_1.rt +119 -0
- data/test/07_http_get_set_remove_2.rt +116 -0
- data/test/08_read_only_time.rt +177 -0
- data/test/09_read_only_name.rt +173 -0
- data/test/10_http_get_set_remove_3.rt +73 -0
- data/test/11_mds_cache_memcached.rt +88 -0
- data/test/12_mds_cache_local_memory.rt +86 -0
- data/test/13_memcache_mds.rt +84 -0
- data/test/14_delete.rt +63 -0
- data/test/15_standalone.rt +71 -0
- data/test/chukan.rb +516 -0
- data/test/common.rb +250 -0
- data/test/load_test.rb +79 -0
- data/test/load_test_offload.rb +86 -0
- metadata +295 -0
@@ -0,0 +1,244 @@
|
|
1
|
+
#
|
2
|
+
# LS4
|
3
|
+
# Copyright (C) 2010-2011 FURUHASHI Sadayuki
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Affero General Public License as
|
7
|
+
# published by the Free Software Foundation, either version 3 of the
|
8
|
+
# License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Affero General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#
|
18
|
+
require 'msgpack/rpc'
|
19
|
+
require 'optparse'
|
20
|
+
|
21
|
+
op = OptionParser.new
|
22
|
+
|
23
|
+
(class<<self;self;end).module_eval do
|
24
|
+
define_method(:usage) do |msg|
|
25
|
+
puts op.to_s
|
26
|
+
puts "error: #{msg}" if msg
|
27
|
+
exit 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
CS_PARAMS = %w[
|
32
|
+
nid address name rsid rsids location
|
33
|
+
]
|
34
|
+
|
35
|
+
DS_PARAMS = %w[
|
36
|
+
read write delete items
|
37
|
+
time uptime pid version
|
38
|
+
]
|
39
|
+
|
40
|
+
EXT_PARAMS = %w[
|
41
|
+
state
|
42
|
+
]
|
43
|
+
|
44
|
+
ALL_PARAMS = CS_PARAMS + EXT_PARAMS + DS_PARAMS
|
45
|
+
|
46
|
+
DEFAULT_PARAMS = %w[
|
47
|
+
nid address name read write delete time
|
48
|
+
]
|
49
|
+
|
50
|
+
conf = {
|
51
|
+
:array => false,
|
52
|
+
:format => 'tsv',
|
53
|
+
:only => [],
|
54
|
+
}
|
55
|
+
|
56
|
+
op.banner = <<EOF
|
57
|
+
Usage: #{File.basename($0)} host[:port] [options] params...
|
58
|
+
params:
|
59
|
+
nid address name rsid location
|
60
|
+
state time uptime pid version
|
61
|
+
read write delete items
|
62
|
+
default params:
|
63
|
+
#{DEFAULT_PARAMS.join(' ')}
|
64
|
+
options:
|
65
|
+
EOF
|
66
|
+
|
67
|
+
op.on('-a', '--array', 'print as arrays instead of a maps', TrueClass) {|b|
|
68
|
+
conf[:array] = true
|
69
|
+
}
|
70
|
+
|
71
|
+
op.on('-o', '--only NID_OR_NAMES', 'get status of these servers only') {|s|
|
72
|
+
only = s.split(',').map {|str|
|
73
|
+
num = str.to_i
|
74
|
+
if num.to_s == str
|
75
|
+
num # nid
|
76
|
+
else
|
77
|
+
str # name
|
78
|
+
end
|
79
|
+
}
|
80
|
+
conf[:only].concat(only)
|
81
|
+
}
|
82
|
+
|
83
|
+
op.on('-t', '--tsv', 'use Tab-Separated-Values format (default)', TrueClass) {|b|
|
84
|
+
conf[:format] = 'tsv'
|
85
|
+
}
|
86
|
+
|
87
|
+
op.on('-j', '--json', 'use JSON format', TrueClass) {|b|
|
88
|
+
conf[:format] = 'json'
|
89
|
+
}
|
90
|
+
|
91
|
+
op.on('-m', '--msgpack', 'use MessagePack format', TrueClass) {|b|
|
92
|
+
conf[:format] = 'msgpack'
|
93
|
+
}
|
94
|
+
|
95
|
+
op.on('-y', '--yaml', 'use YAML format', TrueClass) {|b|
|
96
|
+
conf[:format] = 'yaml'
|
97
|
+
}
|
98
|
+
|
99
|
+
op.on('-a', '--array', 'show as array instead of map', TrueClass) {|b|
|
100
|
+
conf[:array] = true
|
101
|
+
}
|
102
|
+
|
103
|
+
begin
|
104
|
+
op.parse!(ARGV)
|
105
|
+
|
106
|
+
if ARGV.empty?
|
107
|
+
usage nil
|
108
|
+
end
|
109
|
+
|
110
|
+
host, port = ARGV.shift.split(':',2)
|
111
|
+
port ||= 18700
|
112
|
+
|
113
|
+
ARGV.each {|arg|
|
114
|
+
unless ALL_PARAMS.include?(arg)
|
115
|
+
raise "unknown parameter: #{arg.dump}"
|
116
|
+
end
|
117
|
+
}
|
118
|
+
params = ARGV
|
119
|
+
|
120
|
+
if params.empty?
|
121
|
+
params = DEFAULT_PARAMS
|
122
|
+
end
|
123
|
+
|
124
|
+
rescue
|
125
|
+
usage $!.to_s
|
126
|
+
end
|
127
|
+
|
128
|
+
sp = MessagePack::RPC::SessionPool.new
|
129
|
+
cs = sp.get_session(host, port)
|
130
|
+
|
131
|
+
Node = Struct.new('Node', *ALL_PARAMS.map{|s|s.to_sym})
|
132
|
+
|
133
|
+
nodes = cs.call(:stat, 'nodes').map {|nid,address,name,rsids,location|
|
134
|
+
address = MessagePack::RPC::Address.load(address)
|
135
|
+
n = Node.new
|
136
|
+
n.nid = nid
|
137
|
+
n.address = address.to_s
|
138
|
+
n.name = name
|
139
|
+
n.rsids = rsids
|
140
|
+
n.rsid = rsids[0]
|
141
|
+
n.location = location
|
142
|
+
n
|
143
|
+
}.sort_by {|node|
|
144
|
+
node.nid
|
145
|
+
}
|
146
|
+
|
147
|
+
only = conf[:only]
|
148
|
+
unless only.empty?
|
149
|
+
nodes.select! {|n|
|
150
|
+
only.include?(n.nid) || only.include?(n.name)
|
151
|
+
}
|
152
|
+
end
|
153
|
+
|
154
|
+
if params.include?('state')
|
155
|
+
fault_nids = cs.call(:stat, 'fault')
|
156
|
+
nodes.each {|n|
|
157
|
+
if fault_nids.include?(n.nid)
|
158
|
+
n.state = 'FAULT'
|
159
|
+
else
|
160
|
+
n.state = 'active'
|
161
|
+
end
|
162
|
+
}
|
163
|
+
end
|
164
|
+
|
165
|
+
ds_params = params.select {|pa| DS_PARAMS.include?(pa) }
|
166
|
+
unless ds_params.empty?
|
167
|
+
stats = nodes.map {|n|
|
168
|
+
fs = []
|
169
|
+
s = sp.get_session(*n.address.split(':',2))
|
170
|
+
ds_params.each {|pa|
|
171
|
+
case pa
|
172
|
+
when "read"
|
173
|
+
fs << s.call_async(:stat, 'cmd_read')
|
174
|
+
when "write"
|
175
|
+
fs << s.call_async(:stat, 'cmd_write')
|
176
|
+
when "delete"
|
177
|
+
fs << s.call_async(:stat, 'cmd_delete')
|
178
|
+
when "items"
|
179
|
+
fs << s.call_async(:stat, 'db_items')
|
180
|
+
when "time"
|
181
|
+
fs << s.call_async(:stat, 'time')
|
182
|
+
when "uptime"
|
183
|
+
fs << s.call_async(:stat, 'uptime')
|
184
|
+
when "pid"
|
185
|
+
fs << s.call_async(:stat, 'pid')
|
186
|
+
when "version"
|
187
|
+
fs << s.call_async(:stat, 'version')
|
188
|
+
end
|
189
|
+
}
|
190
|
+
fs
|
191
|
+
}.map {|fs|
|
192
|
+
fs.map {|f|
|
193
|
+
f.get rescue nil
|
194
|
+
}
|
195
|
+
}
|
196
|
+
|
197
|
+
nodes.zip(stats) {|n,stat|
|
198
|
+
ds_params.each {|pa|
|
199
|
+
n.__send__(pa+"=", stat.shift)
|
200
|
+
}
|
201
|
+
}
|
202
|
+
end
|
203
|
+
|
204
|
+
if conf[:array]
|
205
|
+
results = nodes.map {|n|
|
206
|
+
params.map {|pa|
|
207
|
+
n.__send__(pa)
|
208
|
+
}
|
209
|
+
}
|
210
|
+
else
|
211
|
+
results = nodes.map {|n|
|
212
|
+
h = []
|
213
|
+
params.map {|pa|
|
214
|
+
h << pa << n.__send__(pa)
|
215
|
+
}
|
216
|
+
Hash[*h]
|
217
|
+
}
|
218
|
+
end
|
219
|
+
|
220
|
+
case conf[:format]
|
221
|
+
when 'tsv'
|
222
|
+
if conf[:array]
|
223
|
+
results.each {|a|
|
224
|
+
$stdout.puts a.join("\t")
|
225
|
+
}
|
226
|
+
else
|
227
|
+
$stdout.puts params.join("\t")
|
228
|
+
results.each {|h|
|
229
|
+
$stdout.puts h.values.join("\t")
|
230
|
+
}
|
231
|
+
end
|
232
|
+
|
233
|
+
when 'msgpack'
|
234
|
+
$stdout.print results.to_msgpack
|
235
|
+
|
236
|
+
when 'yaml'
|
237
|
+
require 'yaml'
|
238
|
+
$stdout.print results.to_yaml
|
239
|
+
|
240
|
+
when 'json'
|
241
|
+
require 'json'
|
242
|
+
$stdout.print results.to_json
|
243
|
+
end
|
244
|
+
|
@@ -0,0 +1,291 @@
|
|
1
|
+
#
|
2
|
+
# LS4
|
3
|
+
# Copyright (C) 2010 FURUHASHI Sadayuki
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU Affero General Public License as
|
7
|
+
# published by the Free Software Foundation, either version 3 of the
|
8
|
+
# License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Affero General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
#
|
18
|
+
|
19
|
+
begin
|
20
|
+
require 'rubygems'
|
21
|
+
rescue LoadError
|
22
|
+
end
|
23
|
+
require 'msgpack/rpc'
|
24
|
+
require 'optparse'
|
25
|
+
require "curses"
|
26
|
+
require 'pp'
|
27
|
+
|
28
|
+
op = OptionParser.new
|
29
|
+
op.banner += " <cs address[:port]>"
|
30
|
+
|
31
|
+
(class<<self;self;end).module_eval do
|
32
|
+
define_method(:usage) do |msg|
|
33
|
+
puts op.to_s
|
34
|
+
puts "error: #{msg}" if msg
|
35
|
+
exit 1
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
if ARGV.length < 1
|
40
|
+
usage(nil)
|
41
|
+
end
|
42
|
+
|
43
|
+
$net = MessagePack::RPC::SessionPool.new
|
44
|
+
addr = ARGV.shift
|
45
|
+
host, port = addr.split(':', 2)
|
46
|
+
port = port.to_i
|
47
|
+
port = 18700 if port == 0
|
48
|
+
cs_addr = [host,port]#Address.new(host, port)
|
49
|
+
|
50
|
+
begin
|
51
|
+
op.parse!(ARGV)
|
52
|
+
|
53
|
+
if ARGV.length != 0
|
54
|
+
raise "unknown option: #{ARGV[0].dump}"
|
55
|
+
end
|
56
|
+
|
57
|
+
rescue
|
58
|
+
usage $!.to_s
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
TITLES =
|
63
|
+
# 1 2 3 4 5 6 7 8 9 10 11 12
|
64
|
+
%w[nid name address location replset #Read #Write Read/s Write/s QPS items time]
|
65
|
+
|
66
|
+
FORMAT_LARGE =
|
67
|
+
%[%1$3s %2$12s %3$23s %4$23s %5$8s %6$8s %7$8s %8$7s %9$7s %10$7s %11$10s %12$20s]
|
68
|
+
|
69
|
+
FORMAT_LARGE_SIMPLE =
|
70
|
+
%[%1$3s %2$12s%4$22s %5$8s %8$7s %9$7s %10$7s %11$10s]
|
71
|
+
|
72
|
+
|
73
|
+
FORMAT_SMALL =
|
74
|
+
# 1 2 5 6 7 11 4
|
75
|
+
%[%1$3s%2$13s %5$7s%6$9s%7$9s%11$9s%4$21s] +
|
76
|
+
%[\n %3$23s%8$9s%9$9s%10$9s%12$21s]
|
77
|
+
# 3 8 9 10 12
|
78
|
+
|
79
|
+
FORMAT_SMALL_SIMPLE =
|
80
|
+
# 1 2 5 6 7 11 4
|
81
|
+
%[%1$3s%2$13s %5$7s%6$9s%7$9s%11$9s%4$21s] +
|
82
|
+
%[\n %8$9s%9$9s%10$9s]
|
83
|
+
# 8 9 10
|
84
|
+
|
85
|
+
TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
|
86
|
+
|
87
|
+
|
88
|
+
class TargetNode
|
89
|
+
def initialize(nid, address, name, rsids, location, fault)
|
90
|
+
@nid = nid
|
91
|
+
@address = address
|
92
|
+
@name = name
|
93
|
+
@rsids = rsids
|
94
|
+
@location = location
|
95
|
+
@fault = fault
|
96
|
+
@time = Time.at(0)
|
97
|
+
@before_read = 0
|
98
|
+
@before_write = 0
|
99
|
+
@futures = []
|
100
|
+
end
|
101
|
+
|
102
|
+
attr_reader :nid
|
103
|
+
|
104
|
+
def update_info(address, name, rsids, location, fault)
|
105
|
+
@address = address
|
106
|
+
@name = name
|
107
|
+
@rsids = rsids
|
108
|
+
@location = location
|
109
|
+
@fault = fault
|
110
|
+
end
|
111
|
+
|
112
|
+
def refresh_async
|
113
|
+
s = $net.get_session(*@address)
|
114
|
+
s.timeout = 3
|
115
|
+
@futures = []
|
116
|
+
@futures[0] = s.call_async(:stat, 'cmd_read')
|
117
|
+
@futures[1] = s.call_async(:stat, 'cmd_write')
|
118
|
+
@futures[2] = s.call_async(:stat, 'time')
|
119
|
+
@futures[3] = s.call_async(:stat, 'db_items')
|
120
|
+
|
121
|
+
now = Time.now
|
122
|
+
@elapse = now - @time
|
123
|
+
@time = now
|
124
|
+
|
125
|
+
self
|
126
|
+
end
|
127
|
+
|
128
|
+
def refresh_async_get
|
129
|
+
ar = Array.new(12)
|
130
|
+
ar[0] = @nid
|
131
|
+
ar[1] = @name
|
132
|
+
ar[2] = @address.to_s
|
133
|
+
ar[3] = @location
|
134
|
+
ar[4] = @rsids.join(',')
|
135
|
+
|
136
|
+
if @fault
|
137
|
+
ar[5] = "FAULT node"
|
138
|
+
return ar
|
139
|
+
end
|
140
|
+
|
141
|
+
begin
|
142
|
+
nread = @futures[0].get
|
143
|
+
nwrite = @futures[1].get
|
144
|
+
time = @futures[2].get
|
145
|
+
db_items = @futures[3].get
|
146
|
+
psread = (nread - @before_read ) / @elapse
|
147
|
+
pswrite = (nwrite - @before_write) / @elapse
|
148
|
+
|
149
|
+
@before_read = nread
|
150
|
+
@before_write = nwrite
|
151
|
+
|
152
|
+
ar[5] = nread
|
153
|
+
ar[6] = nwrite
|
154
|
+
ar[7] = psread.to_i
|
155
|
+
ar[8] = pswrite.to_i
|
156
|
+
ar[9] = (psread + pswrite).to_i
|
157
|
+
ar[10] = db_items
|
158
|
+
ar[11] = time_format(time)
|
159
|
+
|
160
|
+
rescue
|
161
|
+
@before_read = 0
|
162
|
+
@before_write = 0
|
163
|
+
ar[5] = "error: #{$!.to_s}"
|
164
|
+
end
|
165
|
+
|
166
|
+
ar
|
167
|
+
end
|
168
|
+
|
169
|
+
def time_format(t)
|
170
|
+
if t
|
171
|
+
Time.at(t).strftime(TIME_FORMAT)
|
172
|
+
else
|
173
|
+
""
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
class Top
|
180
|
+
def initialize(cs_addr)
|
181
|
+
@cs_addr = cs_addr
|
182
|
+
@nodes = {} # { nid => TargetNode }
|
183
|
+
@nodes_sorted = [] # [TargetNode]
|
184
|
+
update_nodes
|
185
|
+
@simple = false
|
186
|
+
end
|
187
|
+
|
188
|
+
def toggle_simple
|
189
|
+
if @simple
|
190
|
+
@simple = false
|
191
|
+
else
|
192
|
+
@simple = true
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def update_nodes
|
197
|
+
s = $net.get_session(*@cs_addr)
|
198
|
+
s.timeout = 20
|
199
|
+
|
200
|
+
fault_nids = s.call(:stat, 'fault')
|
201
|
+
s.call(:stat, 'nodes').each {|nid,address,name,rsids,location|
|
202
|
+
address = MessagePack::RPC::Address.load(address)
|
203
|
+
fault = fault_nids.include?(nid)
|
204
|
+
if node = @nodes[nid]
|
205
|
+
node.update_info(address, name, rsids, location, fault)
|
206
|
+
else
|
207
|
+
@nodes[nid] = TargetNode.new(nid, address, name, rsids, location, fault)
|
208
|
+
end
|
209
|
+
}
|
210
|
+
@nodes_sorted = @nodes.values.sort_by {|node| node.nid }
|
211
|
+
end
|
212
|
+
|
213
|
+
def refresh
|
214
|
+
Curses.clear
|
215
|
+
if @simple
|
216
|
+
if Curses.stdscr.maxx >= 82
|
217
|
+
format = FORMAT_LARGE_SIMPLE
|
218
|
+
else
|
219
|
+
format = FORMAT_SMALL_SIMPLE
|
220
|
+
end
|
221
|
+
else
|
222
|
+
if Curses.stdscr.maxx >= 147
|
223
|
+
format = FORMAT_LARGE
|
224
|
+
else
|
225
|
+
format = FORMAT_SMALL
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
Curses.setpos(0, 0)
|
230
|
+
title_line = format % TITLES
|
231
|
+
nlines = title_line.count("\n")+1
|
232
|
+
Curses.addstr(title_line)
|
233
|
+
|
234
|
+
@nodes_sorted.each {|node|
|
235
|
+
node.refresh_async
|
236
|
+
}
|
237
|
+
@nodes_sorted.each_with_index {|node, i|
|
238
|
+
Curses.setpos((1+i)*nlines, 0)
|
239
|
+
params = node.refresh_async_get
|
240
|
+
line = format % params
|
241
|
+
Curses.addstr(line)
|
242
|
+
}
|
243
|
+
|
244
|
+
Curses.refresh
|
245
|
+
end
|
246
|
+
|
247
|
+
def run
|
248
|
+
i = 0
|
249
|
+
while true
|
250
|
+
before = Time.now
|
251
|
+
|
252
|
+
refresh
|
253
|
+
|
254
|
+
i += 1
|
255
|
+
if i > 5
|
256
|
+
i = 0
|
257
|
+
update_nodes
|
258
|
+
end
|
259
|
+
|
260
|
+
elapse = Time.now - before
|
261
|
+
if elapse < 0.5
|
262
|
+
sleep 0.5 - elapse
|
263
|
+
end
|
264
|
+
end
|
265
|
+
rescue
|
266
|
+
$stderr.puts $!.inspect
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
top = Top.new(cs_addr)
|
271
|
+
|
272
|
+
Curses.init_screen
|
273
|
+
|
274
|
+
begin
|
275
|
+
th = Thread.start(&top.method(:run))
|
276
|
+
|
277
|
+
while true
|
278
|
+
ch = Curses.getch
|
279
|
+
case ch
|
280
|
+
when ?s
|
281
|
+
top.toggle_simple
|
282
|
+
when ?q
|
283
|
+
break
|
284
|
+
end
|
285
|
+
#top.refresh
|
286
|
+
end
|
287
|
+
|
288
|
+
ensure
|
289
|
+
Curses.close_screen
|
290
|
+
end
|
291
|
+
|