drbqs 0.0.17 → 0.0.18

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.
Files changed (50) hide show
  1. data/docs/FormatExecute.md +44 -2
  2. data/example/group/execute.rb +19 -0
  3. data/example/group/server.rb +27 -0
  4. data/example/group/sum.rb +9 -0
  5. data/example/mandelbrot/README.md +8 -0
  6. data/example/mandelbrot/execute.rb +4 -0
  7. data/lib/drbqs/command_line/command_node.rb +1 -0
  8. data/lib/drbqs/execute/execute_node.rb +4 -21
  9. data/lib/drbqs/node/connection.rb +1 -2
  10. data/lib/drbqs/node/node.rb +163 -102
  11. data/lib/drbqs/node/state.rb +100 -35
  12. data/lib/drbqs/node/task_client.rb +46 -33
  13. data/lib/drbqs/server/message.rb +13 -7
  14. data/lib/drbqs/server/server.rb +57 -29
  15. data/lib/drbqs/server/server_hook.rb +19 -5
  16. data/lib/drbqs/server/test/node.rb +31 -6
  17. data/lib/drbqs/setting/node.rb +11 -2
  18. data/lib/drbqs/setting/server.rb +1 -1
  19. data/lib/drbqs/task/task.rb +26 -6
  20. data/lib/drbqs/task/task_generator.rb +2 -1
  21. data/lib/drbqs/utility/temporary.rb +27 -6
  22. data/lib/drbqs/utility/transfer/transfer_client.rb +10 -12
  23. data/lib/drbqs/version.rb +1 -1
  24. data/lib/drbqs/worker.rb +2 -0
  25. data/lib/drbqs/worker/forked_process.rb +100 -0
  26. data/lib/drbqs/worker/serialize.rb +66 -0
  27. data/lib/drbqs/worker/worker.rb +133 -0
  28. data/lib/drbqs/worker/worker_process_set.rb +219 -0
  29. data/spec/integration_test/01_basic_usage_spec.rb +3 -2
  30. data/spec/integration_test/06_node_exit_after_task_spec.rb +3 -2
  31. data/spec/integration_test/07_command_server_with_node_spec.rb +1 -0
  32. data/spec/integration_test/08_shutdown_unused_nodes_spec.rb +3 -2
  33. data/spec/integration_test/10_test_server_spec.rb +2 -2
  34. data/spec/integration_test/11_special_tasks_spec.rb +61 -0
  35. data/spec/integration_test/12_multiple_workers_spec.rb +43 -0
  36. data/spec/integration_test/definition/task_obj_definition.rb +33 -6
  37. data/spec/node/connection_spec.rb +6 -6
  38. data/spec/node/node_spec.rb +10 -2
  39. data/spec/node/state_spec.rb +146 -62
  40. data/spec/node/task_client_spec.rb +58 -53
  41. data/spec/server/message_spec.rb +10 -6
  42. data/spec/server/queue_spec.rb +7 -4
  43. data/spec/server/server_hook_spec.rb +28 -1
  44. data/spec/task/task_spec.rb +43 -6
  45. data/spec/utility/temporary_spec.rb +32 -9
  46. data/spec/worker/forked_process_spec.rb +66 -0
  47. data/spec/worker/serialize_spec.rb +73 -0
  48. data/spec/worker/worker_process_set_spec.rb +104 -0
  49. data/spec/worker/worker_spec.rb +127 -0
  50. metadata +34 -19
@@ -24,6 +24,7 @@ describe DRbQS do
24
24
  end
25
25
 
26
26
  it "should raise error in server." do
27
+ puts "**** This test output errors to stdout ****"
27
28
  @path = File.expand_path(File.join(File.dirname(__FILE__), 'definition/server02.rb'))
28
29
  @port = 14071
29
30
  lambda do
@@ -12,8 +12,9 @@ describe DRbQS::Server do
12
12
 
13
13
  it "should send node exit" do
14
14
  execute_node = DRbQS::Execution::ExecuteNode.new(@uri, nil, nil)
15
- execute_node.execute(1)
16
- client_process_id = execute_node.pid[0]
15
+ client_process_id = fork do
16
+ execute_node.execute(1)
17
+ end
17
18
  th = Process.detach(client_process_id)
18
19
  lambda do
19
20
  @max_wait_time.times do |i|
@@ -7,12 +7,12 @@ describe DRbQS::Test::Server do
7
7
  it "should execute as test." do
8
8
  DRbQS.define_server do |server, argv, opts|
9
9
  5.times do |i|
10
- server.queue.add(DRbQS::Task.new(TestCount.new, :calc))
10
+ server.queue.add(DRbQS::Task.new(TestCountCalc.new, :calc))
11
11
  end
12
12
  end
13
13
  server = DRbQS.create_test_server({})
14
14
  data = server.test_exec
15
15
  data.should be_an_instance_of Hash
16
- TestCount.get.should == 5
16
+ TestCountCalc.get.should == 5
17
17
  end
18
18
  end
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ require 'drbqs/task/task'
4
+ require_relative 'definition/task_obj_definition.rb'
5
+
6
+ describe DRbQS do
7
+ class TestValue
8
+ @file = File.join(File.dirname(__FILE__), 'value.txt')
9
+
10
+ def self.set(k, v)
11
+ open(@file, 'a+') do |f|
12
+ f.puts "#{k.to_s}\t#{v.to_s}"
13
+ end
14
+ end
15
+
16
+ def self.get(val)
17
+ if File.exist?(@file)
18
+ File.read(@file).each_line do |l|
19
+ if /^#{val.to_s}/ =~ l
20
+ return l.split[1].to_i
21
+ end
22
+ end
23
+ end
24
+ nil
25
+ end
26
+
27
+ def self.clear
28
+ FileUtils.rm(@file) if File.exist?(@file)
29
+ end
30
+ end
31
+
32
+ before(:all) do
33
+ @process_id, @uri = drbqs_fork_server(14110, :task => DRbQS::Task.new(Test1.new, :echo, args: [0])) do |server|
34
+ server.set_initialization_task(DRbQS::Task.new(TestValue, :set, args: [:first, 1]),
35
+ DRbQS::Task.new(TestValue, :set, args: [:second, 2]))
36
+ server.set_finalization_task(DRbQS::Task.new(TestValue, :set, args: [:third, 3]),
37
+ DRbQS::Task.new(TestValue, :set, args: [:fourth, 4]))
38
+ end
39
+ @node = DRbQS::Node.new(@uri, :log_file => $stdout, :continue => true)
40
+ end
41
+
42
+ it "should execute initialization tasks." do
43
+ @node.connect
44
+ TestValue.get(:first).should == 1
45
+ TestValue.get(:second).should == 2
46
+ end
47
+
48
+ it "should execute finalization tasks" do
49
+ @node.calculate
50
+ sleep(1) # Wait finish of task.
51
+ TestValue.get(:third).should == 3
52
+ TestValue.get(:fourth).should == 4
53
+ end
54
+
55
+ after(:all) do
56
+ TestValue.clear
57
+ lambda do
58
+ drbqs_wait_kill_server(@process_id, 30)
59
+ end.should_not raise_error
60
+ end
61
+ end
@@ -0,0 +1,43 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ require 'drbqs/task/task'
4
+ require_relative 'definition/task_obj_definition.rb'
5
+
6
+ describe DRbQS do
7
+ before(:all) do
8
+ @dir = 'test_pid_dir'
9
+ FileUtils.mkdir(@dir) unless File.exist?(@dir)
10
+ @number_of_task = 10
11
+ @tasks = @number_of_task.times.map do |i|
12
+ DRbQS::Task.new(TestPID.new, :save, args: [@dir])
13
+ end
14
+ @process_number = 3
15
+ @process_id, @uri = drbqs_fork_server(14120, :task => @tasks)
16
+ @node = DRbQS::Node.new(@uri, :log_file => $stdout, :continue => true, :process => @process_number)
17
+ end
18
+
19
+ it "should calculate" do
20
+ @node.connect
21
+ lambda do
22
+ @node.calculate
23
+ end.should_not raise_error
24
+ paths = Dir.glob(File.join(@dir, '*')).select do |file|
25
+ /^\d+$/ =~ File.basename(file)
26
+ end
27
+ paths.uniq.should have(@process_number).items
28
+ n = 0
29
+ paths.each do |path|
30
+ n += File.read(path).to_i
31
+ end
32
+ n.should == @number_of_task
33
+ end
34
+
35
+ after(:all) do
36
+ TestCount.clear
37
+ lambda do
38
+ drbqs_wait_kill_server(@process_id)
39
+ end.should_not raise_error
40
+ FileUtils.rm_r(@dir) if File.exist?(@dir)
41
+ end
42
+
43
+ end
@@ -1,14 +1,26 @@
1
- class Test1
2
- @@execute_echo_number = 0
1
+ class TestCount
2
+ @@file = File.join(File.dirname(__FILE__), 'count.txt')
3
3
 
4
4
  def echo(*args)
5
- puts "execute Test1#echo(*#{args.inspect.strip})"
6
- @@execute_echo_number += 1
5
+ open(@@file, 'a+') do |f|
6
+ f.puts "count"
7
+ end
7
8
  args
8
9
  end
9
10
 
10
11
  def self.get_execute_echo_number
11
- @@execute_echo_number
12
+ File.read(@@file).lines.to_a.size
13
+ end
14
+
15
+ def self.clear
16
+ FileUtils.rm(@@file) if File.exist?(@@file)
17
+ end
18
+ end
19
+
20
+ class Test1
21
+ def echo(*args)
22
+ puts "execute Test1#echo(*#{args.inspect.strip})"
23
+ args
12
24
  end
13
25
  end
14
26
 
@@ -48,7 +60,7 @@ class TestSum
48
60
  end
49
61
  end
50
62
 
51
- class TestCount
63
+ class TestCountCalc
52
64
  @@count = 0
53
65
 
54
66
  def calc
@@ -61,3 +73,18 @@ class TestCount
61
73
  n
62
74
  end
63
75
  end
76
+
77
+ class TestPID
78
+ def save(dir)
79
+ path = File.join(dir, "#{Process.pid}")
80
+ if File.exist?(path)
81
+ n = File.read(path).to_i + 1
82
+ else
83
+ n = 1
84
+ end
85
+ Kernel.open(path, 'w') do |f|
86
+ f.print n.to_s
87
+ end
88
+ true
89
+ end
90
+ end
@@ -20,9 +20,9 @@ describe DRbQS::Node::Connection do
20
20
  end
21
21
 
22
22
  it "should get initialization." do
23
- ary = [:initialize, [1, 2], :size, []]
24
- @message.write(ary)
25
- @connection.get_initialization.should == ary[1..-1]
23
+ ary = DRbQS::Task.new([1, 2], :size).simple_drb_args
24
+ @message.write([:initialize, ary])
25
+ @connection.get_initialization.should == ary
26
26
  end
27
27
 
28
28
  it "should get no finalization method." do
@@ -30,9 +30,9 @@ describe DRbQS::Node::Connection do
30
30
  end
31
31
 
32
32
  it "should get finalization." do
33
- ary = [:finalize, [1, 2], :size, []]
34
- @message.write(ary)
35
- @connection.get_finalization.should == ary[1..-1]
33
+ ary = DRbQS::Task.new([1, 2], :size).simple_drb_args
34
+ @message.write([:finalize, ary])
35
+ @connection.get_finalization.should == ary
36
36
  end
37
37
 
38
38
  it "should raise error for invalid signal." do
@@ -22,12 +22,20 @@ describe DRbQS::Node do
22
22
  end
23
23
 
24
24
  it "should connect to server." do
25
+ node_number = 10
25
26
  DRb::DRbObject.should_receive(:new_with_uri).and_return(@drb_object)
26
27
  node_connection = mock('node connection')
27
- node_connection.stub(:node_number).and_return(10)
28
+ node_connection.stub(:node_number).and_return(node_number)
28
29
  node_connection.stub(:get_initialization).and_return(nil)
30
+ task_client = mock('task client')
31
+ task_client.stub(:node_number).and_return(node_number)
32
+ worker = mock('worker')
33
+ worker.stub(:create_process)
34
+ worker.stub(:on_error)
35
+ worker.stub(:on_result)
29
36
  DRbQS::Node::Connection.should_receive(:new).and_return(node_connection)
30
- DRbQS::Node::TaskClient.should_receive(:new)
37
+ DRbQS::Node::TaskClient.should_receive(:new).and_return(task_client)
38
+ DRbQS::Worker::ProcessSet.should_receive(:new).and_return(worker)
31
39
  subject.connect
32
40
  end
33
41
  end
@@ -1,79 +1,178 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  describe DRbQS::Node::State do
4
+ def make_all_processes_wait
5
+ @process_number.times do |i|
6
+ subject.change(i, :wait)
7
+ end
8
+ end
9
+
10
+ before(:all) do
11
+ @process_number = 3
12
+ end
13
+
4
14
  subject do
5
- DRbQS::Node::State.new(:wait)
15
+ DRbQS::Node::State.new(:wait, @process_number)
6
16
  end
7
17
 
8
- context "when state is :wait" do
18
+ context "when getting process number" do
19
+ it "should yield each process number." do
20
+ wids = []
21
+ subject.each_worker_id do |wid|
22
+ wids << wid
23
+ end
24
+ wids.sort.should == @process_number.times.to_a.sort
25
+ end
26
+
27
+ it "should get waiting process number." do
28
+ subject.waiting_worker_id.sort.should == @process_number.times.to_a.sort
29
+ end
30
+
31
+ it "should get waiting process number with not waiting process." do
32
+ waiting = []
33
+ @process_number.times do |i|
34
+ if i == 2
35
+ subject.change(i, :calculate)
36
+ else
37
+ waiting << i
38
+ end
39
+ end
40
+ subject.waiting_worker_id.sort.should == waiting
41
+ end
42
+ end
43
+
44
+ context "when requesting new tasks" do
9
45
  before(:each) do
10
- subject.change(:wait)
46
+ make_all_processes_wait
11
47
  end
12
48
 
13
- it "should change to :wait." do
14
- lambda do
15
- subject.change_to_wait
16
- end.should_not change { subject.state }
49
+ it "should request." do
50
+ subject.request?.should be_true
51
+ end
52
+
53
+ it "should request for all processes." do
54
+ subject.request_task_number.should == @process_number
55
+ end
56
+
57
+ it "should request except for one process." do
58
+ subject.change(0, :calculate)
59
+ subject.request_task_number.should == @process_number - 1
60
+ end
61
+ end
62
+
63
+ context "when state is :wait" do
64
+ before(:each) do
65
+ @process_number.times do |i|
66
+ subject.change(i, :wait)
67
+ end
17
68
  end
18
69
 
19
70
  it "should change to :sleep." do
20
- lambda do
21
- subject.change_to_sleep
22
- end.should change { subject.state }.from(:wait).to(:sleep)
71
+ subject.change_to_sleep
72
+ @process_number.times do |i|
73
+ subject.get_state(i).should == :sleep
74
+ end
23
75
  end
24
76
 
25
- it "should change to :calculate." do
26
- lambda do
27
- subject.change_to_calculate
28
- end.should change { subject.state }.from(:wait).to(:calculate)
77
+ it "should sleep." do
78
+ subject.sleep_with_auto_wakeup
79
+ @process_number.times do |i|
80
+ subject.get_state(i).should == :sleep
81
+ end
82
+ end
83
+
84
+ it "should wakeup." do
85
+ subject.wakeup_sleeping_worker
86
+ @process_number.times do |i|
87
+ subject.get_state(i).should == :wait
88
+ end
29
89
  end
30
90
  end
31
91
 
32
92
  context "when state is :sleep" do
33
93
  before(:each) do
34
- subject.change(:sleep)
94
+ @process_number.times do |i|
95
+ subject.change(i, :sleep)
96
+ end
35
97
  end
36
98
 
37
99
  it "should change to :sleep." do
38
- lambda do
39
- subject.change_to_wait
40
- end.should change { subject.state }.from(:sleep).to(:wait)
100
+ subject.change_to_sleep
101
+ @process_number.times do |i|
102
+ subject.get_state(i).should == :sleep
103
+ end
41
104
  end
42
105
 
43
- it "should change to :sleep." do
44
- lambda do
45
- subject.change_to_sleep
46
- end.should_not change { subject.state }
106
+ it "should sleep." do
107
+ subject.sleep_with_auto_wakeup
108
+ @process_number.times do |i|
109
+ subject.get_state(i).should == :sleep
110
+ end
47
111
  end
48
112
 
49
- it "should change to :calculate." do
50
- lambda do
51
- subject.change_to_calculate
52
- end.should change { subject.state }.from(:sleep).to(:calculate)
113
+ it "should wakeup." do
114
+ subject.wakeup_sleeping_worker
115
+ @process_number.times do |i|
116
+ subject.get_state(i).should == :wait
117
+ end
53
118
  end
54
119
  end
55
120
 
56
121
  context "when state is :calculate" do
57
122
  before(:each) do
58
- subject.change(:calculate)
123
+ @process_number.times do |i|
124
+ subject.change(i, :calculate)
125
+ end
59
126
  end
60
127
 
61
128
  it "should change to :sleep." do
62
- lambda do
63
- subject.change_to_wait
64
- end.should_not change { subject.state }
129
+ subject.change_to_sleep
130
+ @process_number.times do |i|
131
+ subject.get_state(i).should == :calculate
132
+ end
133
+ end
134
+
135
+ it "should sleep." do
136
+ subject.sleep_with_auto_wakeup
137
+ @process_number.times do |i|
138
+ subject.get_state(i).should == :calculate
139
+ end
140
+ end
141
+
142
+ it "should wakeup." do
143
+ subject.wakeup_sleeping_worker
144
+ @process_number.times do |i|
145
+ subject.get_state(i).should == :calculate
146
+ end
147
+ end
148
+ end
149
+
150
+ context "when state is :calculate" do
151
+ before(:each) do
152
+ @process_number.times do |i|
153
+ subject.change(i, :exit)
154
+ end
65
155
  end
66
156
 
67
157
  it "should change to :sleep." do
68
- lambda do
69
- subject.change_to_sleep
70
- end.should_not change { subject.state }
158
+ subject.change_to_sleep
159
+ @process_number.times do |i|
160
+ subject.get_state(i).should == :exit
161
+ end
71
162
  end
72
163
 
73
- it "should change to :calculate." do
74
- lambda do
75
- subject.change_to_calculate
76
- end.should_not change { subject.state }
164
+ it "should sleep." do
165
+ subject.sleep_with_auto_wakeup
166
+ @process_number.times do |i|
167
+ subject.get_state(i).should == :exit
168
+ end
169
+ end
170
+
171
+ it "should wakeup." do
172
+ subject.wakeup_sleeping_worker
173
+ @process_number.times do |i|
174
+ subject.get_state(i).should == :exit
175
+ end
77
176
  end
78
177
  end
79
178
 
@@ -91,50 +190,35 @@ describe DRbQS::Node::State do
91
190
 
92
191
  context "when setting load average" do
93
192
  subject do
94
- DRbQS::Node::State.new(:wait, :max_loadavg => 2)
193
+ DRbQS::Node::State.new(:wait, 1, :max_loadavg => 2)
95
194
  end
96
195
 
97
196
  it "should be true" do
98
197
  subject.stub(:get_load_average).and_return([2.0, 2,0, 2.0])
99
- subject.system_busy?.should be_true
198
+ subject.__send__(:system_busy?).should be_true
100
199
  end
101
200
 
102
201
  it "should be nil" do
103
202
  subject.stub(:get_load_average).and_return([1.0, 1,0, 1.0])
104
- subject.system_busy?.should be_nil
203
+ subject.__send__(:system_busy?).should be_nil
105
204
  end
106
205
  end
107
206
 
108
- context "when changing state to finish calculating" do
109
- before(:each) do
110
- subject.change(:calculate)
111
- end
112
-
113
- it "should change to :wait." do
114
- lambda do
115
- subject.change_to_finish_calculating
116
- end.should change { subject.state }.from(:calculate).to(:wait)
117
- end
118
-
119
- it "should change to :sleep." do
120
- subject.change_to_sleep
121
- lambda do
122
- subject.change_to_finish_calculating
123
- end.should change { subject.state }.from(:calculate).to(:sleep)
207
+ context "when setting auto wakeup" do
208
+ before(:all) do
209
+ @check_worker_id = 0
124
210
  end
125
- end
126
211
 
127
- context "when setting auto wakeup" do
128
212
  subject do
129
- DRbQS::Node::State.new(:wait, :sleep_time => 0)
213
+ DRbQS::Node::State.new(:wait, 1, :sleep_time => 0)
130
214
  end
131
215
 
132
216
  it "should do nothing." do
217
+ make_all_processes_wait
133
218
  subject.stub(:system_busy?).and_return(nil)
134
- subject.change(:wait)
135
219
  lambda do
136
220
  subject.wakeup_automatically_for_unbusy_system
137
- end.should_not change { subject.state }
221
+ end.should_not change { subject.get_state(@check_worker_id) }
138
222
  end
139
223
 
140
224
  it "should do nothing." do
@@ -142,7 +226,7 @@ describe DRbQS::Node::State do
142
226
  subject.sleep_with_auto_wakeup
143
227
  lambda do
144
228
  subject.wakeup_automatically_for_unbusy_system
145
- end.should change { subject.state }.from(:sleep).to(:wait)
229
+ end.should change { subject.get_state(@check_worker_id) }.from(:sleep).to(:wait)
146
230
  end
147
231
  end
148
232
  end