drbqs 0.0.14 → 0.0.15
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/bin/drbqs-execute +6 -0
- data/bin/drbqs-manage +2 -2
- data/bin/drbqs-node +2 -2
- data/bin/drbqs-server +2 -2
- data/bin/drbqs-ssh +2 -2
- data/drbqs.gemspec +53 -16
- data/example/error_server/error.rb +6 -0
- data/example/error_server/server_def.rb +7 -0
- data/example/{error → error_task}/error.rb +0 -0
- data/example/{error → error_task}/server_def.rb +0 -0
- data/example/sum2/execute_def.rb +27 -0
- data/lib/drbqs/command_line/argument.rb +29 -0
- data/lib/drbqs/command_line/command_base.rb +81 -0
- data/lib/drbqs/command_line/command_execute.rb +33 -0
- data/lib/drbqs/command_line/command_line.rb +19 -0
- data/lib/drbqs/command_line/command_manage.rb +34 -0
- data/lib/drbqs/command_line/command_node.rb +26 -0
- data/lib/drbqs/command_line/command_server.rb +41 -0
- data/lib/drbqs/command_line/command_ssh.rb +51 -0
- data/lib/drbqs/command_line/option_setting.rb +42 -0
- data/lib/drbqs/execute/process_define.rb +213 -0
- data/lib/drbqs/execute/register.rb +147 -0
- data/lib/drbqs/{utility → execute}/server_define.rb +7 -14
- data/lib/drbqs/manage/execute_node.rb +4 -2
- data/lib/drbqs/manage/manage.rb +23 -16
- data/lib/drbqs/manage/send_signal.rb +31 -4
- data/lib/drbqs/manage/ssh_execute.rb +50 -6
- data/lib/drbqs/manage/ssh_shell.rb +95 -50
- data/lib/drbqs/node/connection.rb +1 -1
- data/lib/drbqs/node/node.rb +67 -17
- data/lib/drbqs/node/state.rb +109 -0
- data/lib/drbqs/node/task_client.rb +7 -7
- data/lib/drbqs/server/history.rb +16 -0
- data/lib/drbqs/server/message.rb +80 -15
- data/lib/drbqs/server/node_list.rb +16 -3
- data/lib/drbqs/server/prof.rb +48 -0
- data/lib/drbqs/server/queue.rb +20 -2
- data/lib/drbqs/server/server.rb +112 -70
- data/lib/drbqs/server/server_hook.rb +26 -6
- data/lib/drbqs/server/test/node.rb +34 -0
- data/lib/drbqs/server/test/server.rb +74 -0
- data/lib/drbqs/setting/base.rb +120 -0
- data/lib/drbqs/setting/data_container.rb +39 -0
- data/lib/drbqs/setting/execute.rb +71 -0
- data/lib/drbqs/setting/manage.rb +163 -0
- data/lib/drbqs/setting/node.rb +84 -0
- data/lib/drbqs/setting/server.rb +230 -0
- data/lib/drbqs/setting/setting.rb +14 -0
- data/lib/drbqs/setting/source.rb +220 -0
- data/lib/drbqs/setting/ssh.rb +165 -0
- data/lib/drbqs/task/task_generator.rb +4 -2
- data/lib/drbqs/utility/misc.rb +15 -1
- data/lib/drbqs/utility/temporary.rb +4 -2
- data/lib/drbqs.rb +3 -2
- data/spec/command_line/command_base_spec.rb +47 -0
- data/spec/{utility/command_line → command_line}/commands_spec.rb +3 -3
- data/spec/command_line/option_setting_spec.rb +29 -0
- data/spec/execute/def/execute1.rb +24 -0
- data/spec/execute/def/no_def.rb +2 -0
- data/spec/execute/process_define_spec.rb +167 -0
- data/spec/execute/register_spec.rb +77 -0
- data/spec/{utility → execute}/server_define_spec.rb +0 -0
- data/spec/integration_test/01_basic_usage_spec.rb +1 -1
- data/spec/integration_test/02_use_generator_spec.rb +1 -1
- data/spec/integration_test/03_use_temporary_file_spec.rb +1 -1
- data/spec/integration_test/04_use_unix_domain_spec.rb +1 -1
- data/spec/integration_test/05_server_exit_signal_spec.rb +1 -1
- data/spec/integration_test/06_node_exit_after_task_spec.rb +1 -1
- data/spec/integration_test/07_command_server_with_node_spec.rb +19 -16
- data/spec/integration_test/08_shutdown_unused_nodes_spec.rb +38 -0
- data/spec/integration_test/09_server_process_data_spec.rb +74 -0
- data/spec/integration_test/10_test_server_spec.rb +18 -0
- data/spec/integration_test/definition/task_obj_definition.rb +14 -0
- data/spec/manage/send_signal_spec.rb +8 -0
- data/spec/manage/ssh_shell_spec.rb +1 -1
- data/spec/node/state_spec.rb +148 -0
- data/spec/node/task_client_spec.rb +15 -0
- data/spec/server/history_spec.rb +51 -20
- data/spec/server/message_spec.rb +7 -2
- data/spec/server/node_list_spec.rb +1 -1
- data/spec/server/queue_spec.rb +93 -4
- data/spec/server/server_hook_spec.rb +62 -0
- data/spec/setting/base_spec.rb +35 -0
- data/spec/setting/data_container_spec.rb +92 -0
- data/spec/setting/execute_spec.rb +51 -0
- data/spec/setting/manage_spec.rb +63 -0
- data/spec/setting/node_spec.rb +43 -0
- data/spec/setting/server_spec.rb +46 -0
- data/spec/setting/source_spec.rb +245 -0
- data/spec/spec_helper.rb +17 -10
- data/spec/utility/argument_spec.rb +7 -7
- metadata +179 -146
- data/lib/drbqs/utility/argument.rb +0 -27
- data/lib/drbqs/utility/command_line/command_base.rb +0 -27
- data/lib/drbqs/utility/command_line/command_manage.rb +0 -121
- data/lib/drbqs/utility/command_line/command_node.rb +0 -103
- data/lib/drbqs/utility/command_line/command_server.rb +0 -165
- data/lib/drbqs/utility/command_line/command_ssh.rb +0 -126
- data/lib/drbqs/utility/command_line.rb +0 -15
- data/spec/utility/command_line/command_base_spec.rb +0 -33
@@ -6,39 +6,81 @@ module DRbQS
|
|
6
6
|
class Manage
|
7
7
|
# Requirements:
|
8
8
|
# bash
|
9
|
-
# nohup
|
10
9
|
class SSHShell
|
10
|
+
class RubyEnvironment
|
11
|
+
DEFAULT_RVM_SCRIPT = '$HOME/.rvm/scripts/rvm'
|
12
|
+
|
13
|
+
attr_reader :directory, :rvm, :rvm_init, :env
|
14
|
+
|
15
|
+
# :directory
|
16
|
+
# :rvm
|
17
|
+
# :rvm_init
|
18
|
+
# :env
|
19
|
+
def initialize(opts = {})
|
20
|
+
@directory = opts[:directory]
|
21
|
+
@rvm = opts[:rvm]
|
22
|
+
@rvm_init = opts[:rvm_init]
|
23
|
+
if (@rvm || @rvm_init) && !(String === @rvm_init)
|
24
|
+
@rvm_init = DEFAULT_RVM_SCRIPT
|
25
|
+
end
|
26
|
+
@env = opts[:env]
|
27
|
+
end
|
28
|
+
|
29
|
+
def commands_to_set_env_on_bash
|
30
|
+
if @env
|
31
|
+
@env.map do |var, val|
|
32
|
+
"export #{var}=#{val}"
|
33
|
+
end
|
34
|
+
else
|
35
|
+
[]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
private :commands_to_set_env_on_bash
|
39
|
+
|
40
|
+
def setup_commands
|
41
|
+
cmds = commands_to_set_env_on_bash
|
42
|
+
cmds << "cd #{@directory}" if @directory
|
43
|
+
cmds << "source #{@rvm_init}" if @rvm_init
|
44
|
+
cmds << "rvm use #{@rvm}" if @rvm
|
45
|
+
cmds
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_environment_commands
|
49
|
+
['echo "directory: " `pwd`',
|
50
|
+
'echo "files:"',
|
51
|
+
'ls',
|
52
|
+
'if which rvm > /dev/null; then rvm info; else ruby -v; fi']
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
11
56
|
class InvalidDestination < StandardError
|
12
57
|
end
|
13
58
|
class GetInvalidExitStatus < StandardError
|
14
59
|
end
|
15
60
|
|
16
|
-
attr_reader :user, :host, :
|
17
|
-
|
18
|
-
DEFAULT_RVM_SCRIPT = '$HOME/.rvm/scripts/rvm'
|
19
|
-
DEFAULT_OUTPUT_FILE = 'drbqs_nohup.log'
|
61
|
+
attr_reader :user, :host, :port, :keys
|
20
62
|
|
21
63
|
# :shell shell to use
|
64
|
+
# :env a hash of environmental variables and their values
|
22
65
|
# :dir base directory of ssh server
|
23
66
|
# :rvm version of ruby on rvm
|
24
67
|
# :rvm_init path of script to initialize rvm
|
25
|
-
# :
|
68
|
+
# :keys path of a ssh key
|
69
|
+
# :io IO to output results of commands
|
26
70
|
def initialize(dest, opts = {})
|
27
71
|
@user, @host, @port = split_destination(dest)
|
28
72
|
if !(@host && @user)
|
29
73
|
raise InvalidDestination, "Invalid destination of ssh server."
|
30
74
|
end
|
75
|
+
@keys = opts.delete(:keys)
|
31
76
|
@shell = opts[:shell] || 'bash'
|
32
|
-
@
|
33
|
-
@
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
@directory
|
39
|
-
@out = $stdout
|
40
|
-
@nice = opts[:nice]
|
41
|
-
@nohup = opts[:nohup]
|
77
|
+
@ruby_environment = DRbQS::Manage::SSHShell::RubyEnvironment.new(opts)
|
78
|
+
@out = opts[:io]
|
79
|
+
@ssh = nil
|
80
|
+
end
|
81
|
+
|
82
|
+
def directory
|
83
|
+
@ruby_environment.directory
|
42
84
|
end
|
43
85
|
|
44
86
|
def split_destination(dest)
|
@@ -62,11 +104,14 @@ module DRbQS
|
|
62
104
|
private :split_destination
|
63
105
|
|
64
106
|
def output_command(cmd, result)
|
65
|
-
|
66
|
-
|
107
|
+
if @out
|
108
|
+
@out.puts "#{@user}@#{@host}$ #{cmd}"
|
109
|
+
@out.print result
|
110
|
+
end
|
67
111
|
end
|
68
112
|
private :output_command
|
69
113
|
|
114
|
+
# Return an array of a Net::SSH::Shell::Process object and a result string.
|
70
115
|
def shell_exec_get_output(sh, cmd)
|
71
116
|
result = ''
|
72
117
|
pr_cmd = sh.execute!(cmd) do |sh_proc|
|
@@ -90,53 +135,53 @@ module DRbQS
|
|
90
135
|
|
91
136
|
def shell_exec_check(sh, cmd)
|
92
137
|
ary = shell_exec(sh, cmd)
|
93
|
-
|
94
|
-
|
138
|
+
n = ary[0].exit_status
|
139
|
+
if n != 0
|
140
|
+
raise GetInvalidExitStatus, "Can not execute properly on #{@host}.\nExit status: #{n}\ncommand: #{cmd}"
|
95
141
|
end
|
96
142
|
ary
|
97
143
|
end
|
98
144
|
private :shell_exec_check
|
99
145
|
|
100
|
-
def
|
101
|
-
|
146
|
+
def exec(cmd, opts = {})
|
147
|
+
unless @ssh
|
148
|
+
raise "Not connect."
|
149
|
+
end
|
150
|
+
if opts[:check]
|
151
|
+
shell_exec_check(@ssh, cmd)
|
152
|
+
else
|
153
|
+
shell_exec(@ssh, cmd)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def start(&block)
|
158
|
+
Net::SSH.start(@host, @user, :port => @port, :keys => @keys) do |ssh|
|
102
159
|
ssh.shell(@shell) do |sh|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
160
|
+
@ruby_environment.setup_commands.each do |cmd|
|
161
|
+
shell_exec_check(sh, cmd)
|
162
|
+
end
|
163
|
+
@ssh = sh
|
164
|
+
yield(self)
|
107
165
|
shell_exec(sh, "exit")
|
108
166
|
end
|
109
167
|
end
|
168
|
+
ensure
|
169
|
+
@ssh = nil
|
110
170
|
end
|
111
|
-
private :execute_command
|
112
171
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
shell_exec(sh, cmd)
|
172
|
+
# :check
|
173
|
+
def execute_all(commands, opts = {})
|
174
|
+
results = []
|
175
|
+
start do |ssh_shell|
|
176
|
+
commands.each do |cmd|
|
177
|
+
results << ssh_shell.exec(cmd, opts)
|
120
178
|
end
|
121
179
|
end
|
180
|
+
results
|
122
181
|
end
|
123
182
|
|
124
|
-
def
|
125
|
-
|
126
|
-
if @nice
|
127
|
-
if Integer === @nice
|
128
|
-
cmd = "nice -n #{@nice.to_s} " + cmd
|
129
|
-
else
|
130
|
-
cmd = "nice " + cmd
|
131
|
-
end
|
132
|
-
end
|
133
|
-
execute_command do |sh|
|
134
|
-
if @nohup
|
135
|
-
pr, path = shell_exec_check(sh, "filename-create new -p middle -D parent -t time #{@nohup_output}")
|
136
|
-
cmd = "nohup #{cmd} > #{path.strip} 2>&1 &"
|
137
|
-
end
|
138
|
-
shell_exec(sh, cmd)
|
139
|
-
end
|
183
|
+
def get_environment
|
184
|
+
execute_all(@ruby_environment.get_environment_commands)
|
140
185
|
end
|
141
186
|
end
|
142
187
|
end
|
@@ -52,7 +52,7 @@ module DRbQS
|
|
52
52
|
when :alive_p
|
53
53
|
@message.write([:server, :alive, @node_number])
|
54
54
|
@logger.info("Send alive signal of node id #{@node_number}")
|
55
|
-
when :exit, :finalize, :exit_after_task
|
55
|
+
when :exit, :finalize, :exit_after_task, :sleep, :wake
|
56
56
|
return sym
|
57
57
|
else
|
58
58
|
raise "Get invalid signal: #{sym.inspect}"
|
data/lib/drbqs/node/node.rb
CHANGED
@@ -1,25 +1,29 @@
|
|
1
1
|
require 'drbqs/task/task'
|
2
2
|
require 'drbqs/utility/transfer/transfer_client'
|
3
|
+
require 'drbqs/utility/temporary'
|
3
4
|
require 'drbqs/node/connection'
|
4
5
|
require 'drbqs/node/task_client'
|
5
|
-
require 'drbqs/
|
6
|
+
require 'drbqs/node/state'
|
6
7
|
|
7
8
|
module DRbQS
|
8
9
|
|
9
10
|
class Node
|
10
11
|
|
11
|
-
WAIT_NEW_TASK = 1
|
12
12
|
PRIORITY_RESPOND = 10
|
13
13
|
PRIORITY_CALCULATE = 0
|
14
14
|
OUTPUT_NOT_SEND_RESULT = 'not_send_result'
|
15
15
|
DEFAULT_LOG_FILE = 'drbqs_client.log'
|
16
|
+
INTERVAL_TIME_DEFAULT = 1
|
16
17
|
|
17
18
|
# :continue
|
19
|
+
# :max_loadavg
|
20
|
+
# :sleep_time
|
18
21
|
def initialize(access_uri, opts = {})
|
19
22
|
@access_uri = access_uri
|
20
23
|
@logger = DRbQS::Misc.create_logger(opts[:log_file] || DEFAULT_LOG_FILE, opts[:log_level])
|
21
24
|
@connection = nil
|
22
25
|
@task_client = nil
|
26
|
+
@state = DRbQS::Node::State.new(:wait, :max_loadavg => opts[:max_loadavg], :sleep_time => opts[:sleep_time])
|
23
27
|
@process_continue = opts[:continue]
|
24
28
|
@signal_queue = Queue.new
|
25
29
|
@config = DRbQS::Config.new
|
@@ -108,19 +112,27 @@ module DRbQS
|
|
108
112
|
end
|
109
113
|
private :send_error
|
110
114
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
flag_finilize_exit = true
|
119
|
-
when :exit_after_task
|
120
|
-
@task_client.set_exit_after_task
|
121
|
-
@process_continue = nil
|
115
|
+
def get_new_task
|
116
|
+
if @state.request?
|
117
|
+
if @state.change_to_sleep_for_busy_system
|
118
|
+
@logger.info("Sleep because system is busy.")
|
119
|
+
elsif @task_client.add_new_task
|
120
|
+
@state.change_to_calculate
|
121
|
+
end
|
122
122
|
end
|
123
|
+
end
|
124
|
+
private :get_new_task
|
125
|
+
|
126
|
+
def send_result
|
123
127
|
flag_finilize_exit = @task_client.send_result
|
128
|
+
if @state.calculate? && !@task_client.calculating_task
|
129
|
+
@state.change_to_finish_calculating
|
130
|
+
end
|
131
|
+
flag_finilize_exit
|
132
|
+
end
|
133
|
+
private :send_result
|
134
|
+
|
135
|
+
def send_signal
|
124
136
|
until @signal_queue.empty?
|
125
137
|
signal, obj = @signal_queue.pop
|
126
138
|
case signal
|
@@ -129,10 +141,38 @@ module DRbQS
|
|
129
141
|
process_exit
|
130
142
|
end
|
131
143
|
end
|
132
|
-
|
144
|
+
end
|
145
|
+
private :send_signal
|
146
|
+
|
147
|
+
def process_signal
|
148
|
+
case @connection.respond_signal
|
149
|
+
when :wake
|
150
|
+
@state.change_to_wait
|
151
|
+
when :sleep
|
152
|
+
@state.change_to_sleep
|
153
|
+
when :exit
|
154
|
+
return :exit
|
155
|
+
when :finalize
|
156
|
+
return :finalize
|
157
|
+
when :exit_after_task
|
158
|
+
@task_client.set_exit_after_task
|
159
|
+
@process_continue = nil
|
160
|
+
end
|
161
|
+
nil
|
162
|
+
end
|
163
|
+
private :process_signal
|
164
|
+
|
165
|
+
def communicate_with_server
|
166
|
+
get_new_task
|
167
|
+
sig = process_signal
|
168
|
+
return nil if sig == :exit
|
169
|
+
flag_finilize_exit = send_result
|
170
|
+
send_signal
|
171
|
+
if sig == :finalize || flag_finilize_exit
|
133
172
|
execute_finalization
|
134
173
|
return nil
|
135
174
|
end
|
175
|
+
@state.wakeup_automatically_for_unbusy_system
|
136
176
|
true
|
137
177
|
end
|
138
178
|
private :communicate_with_server
|
@@ -143,16 +183,26 @@ module DRbQS
|
|
143
183
|
end
|
144
184
|
private :calculate_task
|
145
185
|
|
186
|
+
def clear_node_files
|
187
|
+
DRbQS::Temporary.delete_all
|
188
|
+
@config.list.node.delete(Process.pid)
|
189
|
+
end
|
190
|
+
private :clear_node_files
|
191
|
+
|
192
|
+
def wait_interval_of_connection
|
193
|
+
sleep(INTERVAL_TIME_DEFAULT)
|
194
|
+
end
|
195
|
+
private :wait_interval_of_connection
|
196
|
+
|
146
197
|
def thread_communicate
|
147
198
|
Thread.new do
|
148
199
|
begin
|
149
200
|
loop do
|
150
201
|
unless communicate_with_server
|
151
|
-
|
152
|
-
@config.list.node.delete(Process.pid)
|
202
|
+
clear_node_files
|
153
203
|
break
|
154
204
|
end
|
155
|
-
|
205
|
+
wait_interval_of_connection
|
156
206
|
end
|
157
207
|
rescue => err
|
158
208
|
send_error(err, "Calculating thread")
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module DRbQS
|
2
|
+
class Node
|
3
|
+
# Value of state is :sleep, :wait, or :calculate.
|
4
|
+
class State
|
5
|
+
attr_reader :state
|
6
|
+
|
7
|
+
ALL_STATES = [:sleep, :wait, :calculate]
|
8
|
+
DEFAULT_SLEEP_TIME = 300
|
9
|
+
LOADAVG_PATH = '/proc/loadavg'
|
10
|
+
|
11
|
+
def initialize(state, opts = {})
|
12
|
+
@state = state
|
13
|
+
@sleep_at_calculated = nil
|
14
|
+
@load_average_threshold = opts[:max_loadavg]
|
15
|
+
@sleep_time = opts[:sleep_time] || DEFAULT_SLEEP_TIME
|
16
|
+
@auto_wakeup = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def change(state)
|
20
|
+
unless ALL_STATES.include?(state)
|
21
|
+
raise ArgumentError, "Invalid state of node '#{state}'."
|
22
|
+
end
|
23
|
+
@state = state
|
24
|
+
end
|
25
|
+
|
26
|
+
def calculate?
|
27
|
+
@state == :calculate
|
28
|
+
end
|
29
|
+
|
30
|
+
def rest?
|
31
|
+
!calculate?
|
32
|
+
end
|
33
|
+
|
34
|
+
def stop?
|
35
|
+
@state == :sleep
|
36
|
+
end
|
37
|
+
|
38
|
+
def request?
|
39
|
+
@state == :wait
|
40
|
+
end
|
41
|
+
|
42
|
+
def change_to_wait
|
43
|
+
unless calculate?
|
44
|
+
change(:wait)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def change_to_sleep
|
49
|
+
if calculate?
|
50
|
+
@sleep_at_calculated = true
|
51
|
+
else
|
52
|
+
change(:sleep)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def change_to_calculate
|
57
|
+
change(:calculate)
|
58
|
+
end
|
59
|
+
|
60
|
+
def change_to_finish_calculating
|
61
|
+
if @sleep_at_calculated
|
62
|
+
change(:sleep)
|
63
|
+
else
|
64
|
+
change(:wait)
|
65
|
+
end
|
66
|
+
@sleep_at_calculated = nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def sleep_with_auto_wakeup
|
70
|
+
change(:sleep)
|
71
|
+
@auto_wakeup = Time.now + @sleep_time
|
72
|
+
end
|
73
|
+
|
74
|
+
def wakeup_automatically_for_unbusy_system
|
75
|
+
if @auto_wakeup && Time.now > @auto_wakeup && !system_busy?
|
76
|
+
change(:wait)
|
77
|
+
@auto_wakeup = nil
|
78
|
+
return true
|
79
|
+
end
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
|
83
|
+
def get_load_average
|
84
|
+
File.read(LOADAVG_PATH).split[0..2].map do |s|
|
85
|
+
s.to_f
|
86
|
+
end
|
87
|
+
end
|
88
|
+
private :get_load_average
|
89
|
+
|
90
|
+
def system_busy?
|
91
|
+
if @load_average_threshold && File.exist?(LOADAVG_PATH)
|
92
|
+
avg = get_load_average
|
93
|
+
if (avg[0] + avg[1]) / 2 >= @load_average_threshold
|
94
|
+
return true
|
95
|
+
end
|
96
|
+
end
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
|
100
|
+
def change_to_sleep_for_busy_system
|
101
|
+
if system_busy?
|
102
|
+
sleep_with_auto_wakeup
|
103
|
+
return true
|
104
|
+
end
|
105
|
+
nil
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -53,14 +53,14 @@ module DRbQS
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def add_new_task
|
56
|
-
if !@calculating_task && !@exit_after_task
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
56
|
+
if !@calculating_task && !@exit_after_task && (ary = get_task)
|
57
|
+
task_id, obj, method_sym, args = ary
|
58
|
+
@logger.info("Send accept signal: node #{@node_number} caluclating #{task_id}")
|
59
|
+
@result.write([:accept, task_id, @node_number])
|
60
|
+
queue_task(task_id, [obj, method_sym, args])
|
61
|
+
return true
|
63
62
|
end
|
63
|
+
nil
|
64
64
|
end
|
65
65
|
|
66
66
|
# If the method return true, a node should finilize and exit.
|
data/lib/drbqs/server/history.rb
CHANGED
@@ -28,6 +28,22 @@ module DRbQS
|
|
28
28
|
def each(&block)
|
29
29
|
@data.each(&block)
|
30
30
|
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class TaskHistory < DRbQS::Server::History
|
34
|
+
attr_reader :finished_task_number
|
35
|
+
|
36
|
+
def initialize
|
37
|
+
super
|
38
|
+
@finished_task_number = 0
|
39
|
+
end
|
40
|
+
|
41
|
+
def set(id, *args)
|
42
|
+
if args[0] == :result
|
43
|
+
@finished_task_number += 1
|
44
|
+
end
|
45
|
+
super(id, *args)
|
46
|
+
end
|
31
47
|
|
32
48
|
def log_strings
|
33
49
|
s = ''
|
data/lib/drbqs/server/message.rb
CHANGED
@@ -11,6 +11,14 @@ module DRbQS
|
|
11
11
|
@logger = logger
|
12
12
|
end
|
13
13
|
|
14
|
+
# Returned values:
|
15
|
+
# [:exit_server, nil]
|
16
|
+
# [:request_status, nil]
|
17
|
+
# [:request_history, nil]
|
18
|
+
# [:exit_after_task, node_id]
|
19
|
+
# [:wake_node, node_id]
|
20
|
+
# [:sleep_node, node_id]
|
21
|
+
# [:node_error, [node_id, error_message]]
|
14
22
|
def get_message
|
15
23
|
begin
|
16
24
|
mes = @message.take([:server, Symbol, nil], 0)
|
@@ -36,10 +44,20 @@ module DRbQS
|
|
36
44
|
return [mes, arg]
|
37
45
|
when :request_status
|
38
46
|
@logger.info("Get status request from #{arg.to_s}")
|
47
|
+
when :request_history
|
48
|
+
@logger.info("Get history request from #{arg.to_s}")
|
49
|
+
when :sleep_node
|
50
|
+
@logger.info("Get sleep node message for node #{arg.to_s}")
|
51
|
+
return [mes, arg]
|
52
|
+
when :wake_node
|
53
|
+
@logger.info("Get wake node message for node #{arg.to_s}")
|
54
|
+
return [mes, arg]
|
39
55
|
when :node_error
|
40
|
-
@node_list.delete(arg[0])
|
56
|
+
@node_list.delete(arg[0], :error)
|
41
57
|
@logger.info("Node Error (#{arg[0]})") { arg[1] }
|
42
58
|
return [mes, arg[0]]
|
59
|
+
when :new_data
|
60
|
+
return [mes, arg]
|
43
61
|
else
|
44
62
|
@logger.error("Invalid message from #{arg.to_s}")
|
45
63
|
return nil
|
@@ -59,7 +77,9 @@ module DRbQS
|
|
59
77
|
end
|
60
78
|
|
61
79
|
def send_signal(node_id, signal)
|
62
|
-
|
80
|
+
if node_exist?(node_id)
|
81
|
+
@message.write([node_id, signal])
|
82
|
+
end
|
63
83
|
end
|
64
84
|
private :send_signal
|
65
85
|
|
@@ -75,30 +95,56 @@ module DRbQS
|
|
75
95
|
send_signal_to_all_nodes(:exit)
|
76
96
|
end
|
77
97
|
|
98
|
+
def send_sleep(node_id)
|
99
|
+
send_signal(node_id, :sleep)
|
100
|
+
end
|
101
|
+
|
102
|
+
def send_wake(node_id)
|
103
|
+
send_signal(node_id, :wake)
|
104
|
+
end
|
105
|
+
|
78
106
|
# Send all nodes a message to finalize and exit.
|
79
107
|
def send_finalization
|
80
108
|
send_signal_to_all_nodes(:finalize)
|
81
109
|
end
|
82
110
|
|
83
111
|
def send_exit_after_task(node_id)
|
112
|
+
@node_list.add_to_preparation_to_exit(node_id)
|
84
113
|
send_signal(node_id, :exit_after_task)
|
85
114
|
end
|
86
115
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
116
|
+
# +data+ is a hash including server information.
|
117
|
+
# The keys are :calculating_task_number, :finished_task_number, :stocked_task_number,
|
118
|
+
# :calculating_nodes, and :generator_number.
|
119
|
+
def send_status(data)
|
120
|
+
s = "Nodes:\n"
|
121
|
+
if @node_list.history.size == 0
|
122
|
+
s << " none\n"
|
123
|
+
else
|
124
|
+
@node_list.history.each do |node_id, events|
|
125
|
+
if events.size == 0
|
126
|
+
s << "Empty history of node #{node_id}\n"
|
127
|
+
else
|
128
|
+
connect = events[0]
|
129
|
+
s << sprintf("%4d %s\t", node_id, connect[2])
|
130
|
+
if events.size > 1
|
131
|
+
s << "start:#{time_to_history_string(connect[0])}"
|
132
|
+
events[1..-1].each do |t, key|
|
133
|
+
s << ", #{key}: #{time_to_history_string(t)}"
|
134
|
+
end
|
135
|
+
s << "\n"
|
136
|
+
elsif data[:calculating_nodes]
|
137
|
+
task_ids = data[:calculating_nodes][node_id].to_a
|
138
|
+
s << "task: #{task_ids.map { |num| num.to_s }.join(', ')} (#{time_to_history_string(connect[0])})\n"
|
139
|
+
end
|
140
|
+
end
|
100
141
|
end
|
101
142
|
end
|
143
|
+
s << "Server:\n"
|
144
|
+
s << " calculating tasks: #{data[:calculating_task_number]}\n"
|
145
|
+
s << " finished tasks : #{data[:finished_task_number]}\n"
|
146
|
+
s << " stocked tasks : #{data[:stocked_task_number]}\n"
|
147
|
+
s << " task generator : #{data[:generator_number]}"
|
102
148
|
begin
|
103
149
|
@message.take([:status, nil], 0)
|
104
150
|
rescue Rinda::RequestExpiredError
|
@@ -106,6 +152,14 @@ module DRbQS
|
|
106
152
|
@message.write([:status, s])
|
107
153
|
end
|
108
154
|
|
155
|
+
def send_history(history_string)
|
156
|
+
begin
|
157
|
+
@message.take([:history, nil], 0)
|
158
|
+
rescue Rinda::RequestExpiredError
|
159
|
+
end
|
160
|
+
@message.write([:history, history_string])
|
161
|
+
end
|
162
|
+
|
109
163
|
def get_all_nodes
|
110
164
|
@node_list.list.dup
|
111
165
|
end
|
@@ -136,6 +190,17 @@ module DRbQS
|
|
136
190
|
def set_finalization(task)
|
137
191
|
set_special_task(:finalization, task)
|
138
192
|
end
|
193
|
+
|
194
|
+
def shutdown_unused_nodes(calculating_nodes)
|
195
|
+
shutdown_nodes = []
|
196
|
+
@node_list.each do |node_id, id_str|
|
197
|
+
if !@node_list.prepare_to_exit?(node_id) && !calculating_nodes.include?(node_id)
|
198
|
+
send_exit_after_task(node_id)
|
199
|
+
shutdown_nodes << node_id
|
200
|
+
end
|
201
|
+
end
|
202
|
+
shutdown_nodes
|
203
|
+
end
|
139
204
|
end
|
140
205
|
|
141
206
|
end
|