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