drbqs 0.0.14 → 0.0.15
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/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
|