abundance 1.2.1 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/abundance.rb +2 -2
- data/lib/garden.rb +17 -214
- data/lib/garden_cycles.rb +166 -0
- data/lib/garden_rows.rb +94 -0
- data/lib/gardener.rb +4 -4
- data/test/tc_high_api.rb +1 -1
- data/test/tc_multi_gardener.rb +3 -2
- data/test/tc_robustness.rb +1 -1
- metadata +4 -2
data/lib/abundance.rb
CHANGED
@@ -47,11 +47,11 @@ class Abundance
|
|
47
47
|
# with its garden supplied as a block. The invocation block must include
|
48
48
|
# the +grow+ class method and a preceeding optional initialisation section that may include and +init_status+ return message.
|
49
49
|
# === Parameters
|
50
|
-
# * :wheelbarrow = the socket size for the garden communication packets, in bytes,
|
50
|
+
# * :wheelbarrow = the socket size for the garden communication packets, in bytes, up to 8192, defaults to 124
|
51
51
|
# * :rows = garden rows number, the number of concurent threads
|
52
52
|
# * :init_timeout = allow to pause execution to allow for larger gardens to initialize
|
53
53
|
# === Example
|
54
|
-
# gardener = Abundance.gardener( :wheelbarrow =>
|
54
|
+
# gardener = Abundance.gardener( :wheelbarrow => 124, :rows => 2, :init_timeout => 2) do
|
55
55
|
#
|
56
56
|
# processor = SpecialProcess.new
|
57
57
|
# if processor.started_successfully?
|
data/lib/garden.rb
CHANGED
@@ -15,6 +15,9 @@
|
|
15
15
|
# :title:Garden
|
16
16
|
|
17
17
|
class Garden
|
18
|
+
require 'garden_rows'
|
19
|
+
require 'garden_cycles'
|
20
|
+
include Cycles
|
18
21
|
require 'toolshed'
|
19
22
|
include Toolshed
|
20
23
|
|
@@ -31,239 +34,39 @@ class Garden
|
|
31
34
|
|
32
35
|
def initialize
|
33
36
|
@pid = fork do
|
34
|
-
|
35
|
-
@harvest = []; @rows_socket_paths = []; @init_done = []; @seed_all_done = []; @seed_all_crop = []
|
36
|
-
@seeds = []; @sprouts = []; @crops = []; @id = 0
|
37
|
+
set_my_containers
|
37
38
|
set_my_socket_as_a(:garden)
|
39
|
+
|
38
40
|
loop do
|
39
|
-
|
40
|
-
|
41
|
-
if ! @seed_all.nil? && ! @rows_socket_paths.empty? && @seed_all_done.size != @seed_all[0]
|
42
|
-
row_socket_path = @rows_socket_paths.shift
|
43
|
-
unless @seed_all_done.include?( row_socket_path )
|
44
|
-
socket_send(:seed_all,@seed_all[1],row_socket_path)
|
45
|
-
@seed_all_done << row_socket_path
|
46
|
-
else
|
47
|
-
@rows_socket_paths << row_socket_path
|
48
|
-
end
|
49
|
-
elsif ! @do_init.nil? && ! @rows_socket_paths.empty? && @init_done.size != @do_init
|
50
|
-
row_socket_path = @rows_socket_paths.shift
|
51
|
-
unless @init_done.include?( row_socket_path )
|
52
|
-
socket_send(:init,'init_status',row_socket_path)
|
53
|
-
@init_done << row_socket_path
|
54
|
-
else
|
55
|
-
@rows_socket_paths << row_socket_path
|
56
|
-
end
|
57
|
-
elsif ! @seeds.empty? && ! @rows_socket_paths.empty?
|
58
|
-
seed = @seeds.shift
|
59
|
-
@sprouts[seed[:id]] = seed
|
60
|
-
row_socket_path = @rows_socket_paths.shift
|
61
|
-
socket_send(:sprout,seed,row_socket_path)
|
62
|
-
elsif @quit && ! @rows_socket_paths.empty?
|
63
|
-
seed = nil
|
64
|
-
row_socket_path = @rows_socket_paths.shift
|
65
|
-
socket_send(:quit,seed,row_socket_path)
|
66
|
-
else
|
67
|
-
throw :fill_rows
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
41
|
+
seed_if_row_available
|
42
|
+
|
71
43
|
command, data, client_socket_path = socket_recv
|
72
44
|
case command
|
73
45
|
when :seed
|
74
|
-
|
75
|
-
socket_send(command,@id,client_socket_path)
|
46
|
+
place_seed_in_queue(command,data,client_socket_path)
|
76
47
|
when :row
|
77
|
-
|
78
|
-
command = :quit
|
79
|
-
seed = nil
|
80
|
-
elsif @seeds.empty?
|
81
|
-
seed = nil
|
82
|
-
@rows_socket_paths << data
|
83
|
-
else
|
84
|
-
seed = @seeds.shift
|
85
|
-
@sprouts[seed[:id]] = seed
|
86
|
-
end
|
87
|
-
socket_send(command,seed,client_socket_path)
|
48
|
+
this_row_is_available(command,data,client_socket_path)
|
88
49
|
when :crop
|
89
|
-
|
90
|
-
@crops[data[:id]] = data
|
91
|
-
if @harvest[data[:id]]
|
92
|
-
socket_send(command,data, @harvest[data[:id]][:client_socket_path])
|
93
|
-
@crops[data[:id]] = @harvest[data[:id]] = nil
|
94
|
-
elsif @full_crop && @seeds.compact.empty? && @sprouts.compact.empty?
|
95
|
-
socket_send(command,@crops.compact,@mem_client_socket_path)
|
96
|
-
@crops.clear; @full_crop = false
|
97
|
-
end
|
50
|
+
save_crop_for(command,data,client_socket_path)
|
98
51
|
when :growth
|
99
|
-
|
100
|
-
when :progress
|
101
|
-
value = @crops.size.to_f / (@crops.size + @sprouts.compact.size + @seeds.size)
|
102
|
-
value = 1 if value.nan?; progress = sprintf( "%.2f", value)
|
103
|
-
socket_send(command,progress,client_socket_path)
|
104
|
-
when :seed
|
105
|
-
socket_send(command,@seeds.size,client_socket_path)
|
106
|
-
when :sprout
|
107
|
-
socket_send(command,@sprouts.compact.size,client_socket_path)
|
108
|
-
when :crop
|
109
|
-
socket_send(command,@crops.size,client_socket_path)
|
110
|
-
else
|
111
|
-
socket_send(command,false,client_socket_path)
|
112
|
-
end
|
52
|
+
report_growth(command,data,client_socket_path)
|
113
53
|
when :harvest
|
114
|
-
|
115
|
-
when :all
|
116
|
-
socket_send(command,{:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops.compact},client_socket_path)
|
117
|
-
when :seed
|
118
|
-
socket_send(command,@seeds,client_socket_path)
|
119
|
-
when :sprout
|
120
|
-
socket_send(command,@sprouts.compact,client_socket_path)
|
121
|
-
when :crop
|
122
|
-
socket_send(command,@crops.compact,client_socket_path)
|
123
|
-
@crops.clear
|
124
|
-
when :full_crop
|
125
|
-
if @seeds.compact.empty? && @sprouts.compact.empty?
|
126
|
-
socket_send(command,@crops.compact,client_socket_path)
|
127
|
-
@crops.clear
|
128
|
-
else
|
129
|
-
@full_crop = true
|
130
|
-
@mem_client_socket_path = client_socket_path
|
131
|
-
end
|
132
|
-
else
|
133
|
-
if data.is_a? Integer
|
134
|
-
if @crops[data]
|
135
|
-
socket_send(command,@crops[data],client_socket_path)
|
136
|
-
@crops[data] = nil
|
137
|
-
else
|
138
|
-
@harvest[data] = {:client_socket_path => client_socket_path}
|
139
|
-
end
|
140
|
-
else
|
141
|
-
socket_send(command,false,client_socket_path)
|
142
|
-
end
|
143
|
-
end
|
54
|
+
harvest_some(command,data,client_socket_path)
|
144
55
|
when :init
|
145
|
-
|
146
|
-
@init_return = {:client_socket_path => client_socket_path}
|
56
|
+
ask_for_init_status(command,data,client_socket_path)
|
147
57
|
when :init_crop
|
148
|
-
|
149
|
-
if @init_all_crop.size == @do_init
|
150
|
-
socket_send(command,@init_all_crop, @init_return[:client_socket_path])
|
151
|
-
@init_return = Hash.new; @init_done = Array.new; @do_init = nil; @init_all_crop = Array.new
|
152
|
-
end
|
58
|
+
answer_init_status(command,data,client_socket_path)
|
153
59
|
when :seed_all
|
154
|
-
|
155
|
-
@seed_all_return = {:client_socket_path => client_socket_path, :data => []}
|
60
|
+
seed_for_all_rows(command,data,client_socket_path)
|
156
61
|
when :seed_all_crop
|
157
|
-
|
158
|
-
if @seed_all_crop.size == @seed_all[0]
|
159
|
-
socket_send(command,@seed_all_crop, @seed_all_return[:client_socket_path])
|
160
|
-
@seed_all = nil; @seed_all_return = Hash.new; @seed_all_done = Array.new; @seed_all_crop = Array.new
|
161
|
-
end
|
62
|
+
special_crop_seed_all(command,data,client_socket_path)
|
162
63
|
when :close
|
163
|
-
|
164
|
-
@seeds_pid = data[:pid]
|
165
|
-
@quit = true
|
166
|
-
@mem_client_socket_path = client_socket_path
|
167
|
-
else
|
168
|
-
@seeds_pid.delete(data[:pid].to_i)
|
169
|
-
if @seeds_pid.empty?
|
170
|
-
socket_send(:close,{:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops.compact}, @mem_client_socket_path)
|
171
|
-
exit
|
172
|
-
end
|
173
|
-
end
|
64
|
+
close_all(command,data,client_socket_path)
|
174
65
|
else
|
175
66
|
socket_send(command,false,client_socket_path)
|
176
67
|
end
|
177
68
|
end
|
178
69
|
end
|
179
|
-
return pid
|
180
|
-
end
|
181
|
-
|
182
|
-
# The +rows+ method for the Garden instance allow instantiation of its child Rows.
|
183
|
-
# As part of the Abundance lib, Garden.rows is not invoked directly,
|
184
|
-
# but rather as a side effect of the Gardener's initialization.
|
185
|
-
# Its in reality an indirect initializer for the Rows class.
|
186
|
-
# === Parameter
|
187
|
-
# * _rows_ = garden rows number, the number of concurent threads
|
188
|
-
# * _init_timeout_ = allow to pause execution to allow for larger garden rows to initialize
|
189
|
-
# === Example
|
190
|
-
# rows = garden.rows(4,2) { grow_block }
|
191
|
-
#
|
192
|
-
|
193
|
-
def rows(rows,init_timeout,grow_block)
|
194
|
-
Rows.new(rows,init_timeout,@pid,grow_block)
|
195
70
|
end
|
196
|
-
|
197
|
-
# :title:Rows
|
198
|
-
|
199
|
-
class Rows
|
200
|
-
include Toolshed
|
201
|
-
attr_reader :pids
|
202
|
-
|
203
|
-
# The +new+ class method initializes the Rows.
|
204
|
-
# As part of the Abundance lib, Rows is not initialized directly,
|
205
|
-
# but rather as a side effect of the Gardener's initialization,
|
206
|
-
# through the +rows+ Garden instance method.
|
207
|
-
# Its instance resides in the @garden_rows Gardener's instance variable.
|
208
|
-
# Its real muscles are inaccessibles from instance method intervention,
|
209
|
-
# because of its nature as a forked Ruby process.
|
210
|
-
# === Parameter
|
211
|
-
# * _rows_ = garden rows number, the number of concurent threads
|
212
|
-
# * _init_timeout_ = allow to pause execution to allow for larger garden rows to initialize
|
213
|
-
# * _garden_pid_ = the parent Garden's pid, for loopback communication purpose
|
214
|
-
# === Example
|
215
|
-
# rows = Rows.new(4,2) { grow_block }
|
216
|
-
|
217
|
-
def initialize(rows,init_timeout,garden_pid,gardener_block)
|
218
|
-
@pids = []
|
219
|
-
rows.times do
|
220
|
-
@pids << fork do
|
221
|
-
@seed_all = false
|
222
|
-
set_my_socket_as_a(:row,garden_pid)
|
223
|
-
t1 = Thread.new do
|
224
|
-
gardener_block.call
|
225
|
-
end
|
226
71
|
|
227
|
-
t2 = Thread.new do
|
228
|
-
loop do
|
229
|
-
if $seed.nil?
|
230
|
-
command, data = socket_duplex(:row,my_socket_path)
|
231
|
-
if command == :quit
|
232
|
-
pid = Process.pid
|
233
|
-
socket_send(:close,{:level => :seed, :pid => pid})
|
234
|
-
exit
|
235
|
-
end
|
236
|
-
$seed = data
|
237
|
-
if $seed.nil?
|
238
|
-
command, data, client_socket_path = socket_recv
|
239
|
-
case command
|
240
|
-
when :sprout
|
241
|
-
$seed = data
|
242
|
-
when :seed_all
|
243
|
-
@seed_all = true
|
244
|
-
$seed = {:id => Process.pid, :seed => data}
|
245
|
-
when :init
|
246
|
-
$init = {:seed => 'init_status', :message => 'No Init Message', :id => Process.pid} if $init.nil?
|
247
|
-
socket_send(:init_crop,$init)
|
248
|
-
end
|
249
|
-
end
|
250
|
-
elsif ! $seed[:success].nil?
|
251
|
-
if @seed_all
|
252
|
-
socket_send(:seed_all_crop,$seed)
|
253
|
-
@seed_all = false
|
254
|
-
else
|
255
|
-
socket_send(:crop,$seed)
|
256
|
-
end
|
257
|
-
$seed = nil;
|
258
|
-
else
|
259
|
-
t1.run
|
260
|
-
end
|
261
|
-
end
|
262
|
-
end
|
263
|
-
t2.join
|
264
|
-
end
|
265
|
-
end
|
266
|
-
sleep init_timeout
|
267
|
-
end
|
268
|
-
end
|
269
72
|
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
class Garden
|
2
|
+
# Author:: lp (mailto:lp@spiralix.org)
|
3
|
+
# Copyright:: 2008 Louis-Philippe Perron - Released under the terms of the MIT license
|
4
|
+
# :title:Cycles
|
5
|
+
module Cycles
|
6
|
+
|
7
|
+
def set_my_containers
|
8
|
+
@quit = false; @full_crop = false; @do_init = nil; @seed_all = nil; @init_all_crop = []
|
9
|
+
@harvest = []; @rows_socket_paths = []; @init_done = []; @seed_all_done = []; @seed_all_crop = []
|
10
|
+
@seeds = []; @sprouts = []; @crops = []; @id = 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def seed_if_row_available
|
14
|
+
catch :fill_rows do
|
15
|
+
loop do
|
16
|
+
if ! @seed_all.nil? && ! @rows_socket_paths.empty? && @seed_all_done.size != @seed_all[0]
|
17
|
+
row_socket_path = @rows_socket_paths.shift
|
18
|
+
unless @seed_all_done.include?( row_socket_path )
|
19
|
+
socket_send(:seed_all,@seed_all[1],row_socket_path)
|
20
|
+
@seed_all_done << row_socket_path
|
21
|
+
else
|
22
|
+
@rows_socket_paths << row_socket_path
|
23
|
+
end
|
24
|
+
elsif ! @do_init.nil? && ! @rows_socket_paths.empty? && @init_done.size != @do_init
|
25
|
+
row_socket_path = @rows_socket_paths.shift
|
26
|
+
unless @init_done.include?( row_socket_path )
|
27
|
+
socket_send(:init,'init_status',row_socket_path)
|
28
|
+
@init_done << row_socket_path
|
29
|
+
else
|
30
|
+
@rows_socket_paths << row_socket_path
|
31
|
+
end
|
32
|
+
elsif ! @seeds.empty? && ! @rows_socket_paths.empty?
|
33
|
+
seed = @seeds.shift
|
34
|
+
@sprouts[seed[:id]] = seed
|
35
|
+
row_socket_path = @rows_socket_paths.shift
|
36
|
+
socket_send(:sprout,seed,row_socket_path)
|
37
|
+
elsif @quit && ! @rows_socket_paths.empty?
|
38
|
+
seed = nil
|
39
|
+
row_socket_path = @rows_socket_paths.shift
|
40
|
+
socket_send(:quit,seed,row_socket_path)
|
41
|
+
else
|
42
|
+
throw :fill_rows
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def place_seed_in_queue(command,data,client_socket_path)
|
49
|
+
@id += 1; @seeds << {:id => @id , :seed => data}
|
50
|
+
socket_send(command,@id,client_socket_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
def this_row_is_available(command,data,client_socket_path)
|
54
|
+
if @quit
|
55
|
+
command = :quit; seed = nil
|
56
|
+
elsif @seeds.empty?
|
57
|
+
seed = nil; @rows_socket_paths << data
|
58
|
+
else
|
59
|
+
seed = @seeds.shift; @sprouts[seed[:id]] = seed
|
60
|
+
end
|
61
|
+
socket_send(command,seed,client_socket_path)
|
62
|
+
end
|
63
|
+
|
64
|
+
def save_crop_for(command,data,client_socket_path)
|
65
|
+
@sprouts[data[:id]] = nil; @crops[data[:id]] = data
|
66
|
+
if @harvest[data[:id]]
|
67
|
+
socket_send(command,data, @harvest[data[:id]][:client_socket_path])
|
68
|
+
@crops[data[:id]] = @harvest[data[:id]] = nil
|
69
|
+
elsif @full_crop && @seeds.compact.empty? && @sprouts.compact.empty?
|
70
|
+
socket_send(command,@crops.compact,@mem_client_socket_path)
|
71
|
+
@crops.clear; @full_crop = false
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def report_growth(command,data,client_socket_path)
|
76
|
+
case data
|
77
|
+
when :progress
|
78
|
+
value = @crops.size.to_f / (@crops.size + @sprouts.compact.size + @seeds.size)
|
79
|
+
value = 1 if value.nan?; progress = sprintf( "%.2f", value)
|
80
|
+
socket_send(command,progress,client_socket_path)
|
81
|
+
when :seed
|
82
|
+
socket_send(command,@seeds.size,client_socket_path)
|
83
|
+
when :sprout
|
84
|
+
socket_send(command,@sprouts.compact.size,client_socket_path)
|
85
|
+
when :crop
|
86
|
+
socket_send(command,@crops.size,client_socket_path)
|
87
|
+
else
|
88
|
+
socket_send(command,false,client_socket_path)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def harvest_some(command,data,client_socket_path)
|
93
|
+
case data
|
94
|
+
when :all
|
95
|
+
socket_send(command,{:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops.compact},client_socket_path)
|
96
|
+
when :seed
|
97
|
+
socket_send(command,@seeds,client_socket_path)
|
98
|
+
when :sprout
|
99
|
+
socket_send(command,@sprouts.compact,client_socket_path)
|
100
|
+
when :crop
|
101
|
+
socket_send(command,@crops.compact,client_socket_path)
|
102
|
+
@crops.clear
|
103
|
+
when :full_crop
|
104
|
+
if @seeds.compact.empty? && @sprouts.compact.empty?
|
105
|
+
socket_send(command,@crops.compact,client_socket_path)
|
106
|
+
@crops.clear
|
107
|
+
else
|
108
|
+
@full_crop = true
|
109
|
+
@mem_client_socket_path = client_socket_path
|
110
|
+
end
|
111
|
+
else
|
112
|
+
if data.is_a? Integer
|
113
|
+
if @crops[data]
|
114
|
+
socket_send(command,@crops[data],client_socket_path)
|
115
|
+
@crops[data] = nil
|
116
|
+
else
|
117
|
+
@harvest[data] = {:client_socket_path => client_socket_path}
|
118
|
+
end
|
119
|
+
else
|
120
|
+
socket_send(command,false,client_socket_path)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def ask_for_init_status(command,data,client_socket_path)
|
126
|
+
@do_init = data
|
127
|
+
@init_return = {:client_socket_path => client_socket_path}
|
128
|
+
end
|
129
|
+
|
130
|
+
def answer_init_status(command,data,client_socket_path)
|
131
|
+
@init_all_crop << data
|
132
|
+
if @init_all_crop.size == @do_init
|
133
|
+
socket_send(command,@init_all_crop, @init_return[:client_socket_path])
|
134
|
+
@init_return = Hash.new; @init_done = Array.new; @do_init = nil; @init_all_crop = Array.new
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def seed_for_all_rows(command,data,client_socket_path)
|
139
|
+
@seed_all = data
|
140
|
+
@seed_all_return = {:client_socket_path => client_socket_path, :data => []}
|
141
|
+
end
|
142
|
+
|
143
|
+
def special_crop_seed_all(command,data,client_socket_path)
|
144
|
+
@seed_all_crop << data
|
145
|
+
if @seed_all_crop.size == @seed_all[0]
|
146
|
+
socket_send(command,@seed_all_crop, @seed_all_return[:client_socket_path])
|
147
|
+
@seed_all = nil; @seed_all_return = Hash.new; @seed_all_done = Array.new; @seed_all_crop = Array.new
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def close_all(command,data,client_socket_path)
|
152
|
+
if data[:level] == :garden
|
153
|
+
@seeds_pid = data[:pid]
|
154
|
+
@quit = true
|
155
|
+
@mem_client_socket_path = client_socket_path
|
156
|
+
else
|
157
|
+
@seeds_pid.delete(data[:pid].to_i)
|
158
|
+
if @seeds_pid.empty?
|
159
|
+
socket_send(:close,{:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops.compact}, @mem_client_socket_path)
|
160
|
+
exit
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
data/lib/garden_rows.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
class Garden
|
2
|
+
|
3
|
+
# The +rows+ method for the Garden instance allow instantiation of its child Rows.
|
4
|
+
# As part of the Abundance lib, Garden.rows is not invoked directly,
|
5
|
+
# but rather as a side effect of the Gardener's initialization.
|
6
|
+
# Its in reality an indirect initializer for the Rows class.
|
7
|
+
# === Parameter
|
8
|
+
# * _rows_ = garden rows number, the number of concurent threads
|
9
|
+
# * _init_timeout_ = allow to pause execution to allow for larger garden rows to initialize
|
10
|
+
# === Example
|
11
|
+
# rows = garden.rows(4,2) { grow_block }
|
12
|
+
#
|
13
|
+
|
14
|
+
def rows(rows,init_timeout,grow_block)
|
15
|
+
Rows.new(rows,init_timeout,@pid,grow_block)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Author:: lp (mailto:lp@spiralix.org)
|
19
|
+
# Copyright:: 2008 Louis-Philippe Perron - Released under the terms of the MIT license
|
20
|
+
# :title:Rows
|
21
|
+
|
22
|
+
class Rows
|
23
|
+
require 'toolshed'
|
24
|
+
include Toolshed
|
25
|
+
attr_reader :pids
|
26
|
+
|
27
|
+
# The +new+ class method initializes the Rows.
|
28
|
+
# As part of the Abundance lib, Rows is not initialized directly,
|
29
|
+
# but rather as a side effect of the Gardener's initialization,
|
30
|
+
# through the +rows+ Garden instance method.
|
31
|
+
# Its instance resides in the @garden_rows Gardener's instance variable.
|
32
|
+
# Its real muscles are inaccessibles from instance method intervention,
|
33
|
+
# because of its nature as a forked Ruby process.
|
34
|
+
# === Parameter
|
35
|
+
# * _rows_ = garden rows number, the number of concurent threads
|
36
|
+
# * _init_timeout_ = allow to pause execution to allow for larger garden rows to initialize
|
37
|
+
# * _garden_pid_ = the parent Garden's pid, for loopback communication purpose
|
38
|
+
# === Example
|
39
|
+
# rows = Rows.new(4,2) { grow_block }
|
40
|
+
|
41
|
+
def initialize(rows,init_timeout,garden_pid,gardener_block)
|
42
|
+
@pids = []
|
43
|
+
rows.times do
|
44
|
+
@pids << fork do
|
45
|
+
@seed_all = false
|
46
|
+
set_my_socket_as_a(:row,garden_pid)
|
47
|
+
t1 = Thread.new do
|
48
|
+
gardener_block.call
|
49
|
+
end
|
50
|
+
|
51
|
+
t2 = Thread.new do
|
52
|
+
loop do
|
53
|
+
if $seed.nil?
|
54
|
+
command, data = socket_duplex(:row,my_socket_path)
|
55
|
+
if command == :quit
|
56
|
+
pid = Process.pid
|
57
|
+
socket_send(:close,{:level => :seed, :pid => pid})
|
58
|
+
exit
|
59
|
+
end
|
60
|
+
$seed = data
|
61
|
+
if $seed.nil?
|
62
|
+
command, data, client_socket_path = socket_recv
|
63
|
+
case command
|
64
|
+
when :sprout
|
65
|
+
$seed = data
|
66
|
+
when :seed_all
|
67
|
+
@seed_all = true
|
68
|
+
$seed = {:id => Process.pid, :seed => data}
|
69
|
+
when :init
|
70
|
+
$init = {:seed => 'init_status', :message => 'No Init Message', :id => Process.pid} if $init.nil?
|
71
|
+
socket_send(:init_crop,$init)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
elsif ! $seed[:success].nil?
|
75
|
+
if @seed_all
|
76
|
+
socket_send(:seed_all_crop,$seed)
|
77
|
+
@seed_all = false
|
78
|
+
else
|
79
|
+
socket_send(:crop,$seed)
|
80
|
+
end
|
81
|
+
$seed = nil;
|
82
|
+
else
|
83
|
+
t1.run
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
t2.join
|
88
|
+
end
|
89
|
+
end
|
90
|
+
sleep init_timeout
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
data/lib/gardener.rb
CHANGED
@@ -23,16 +23,16 @@ class Gardener
|
|
23
23
|
# As part of the Abundance lib, Gardener is not initialized directly,
|
24
24
|
# but rather through Abundance.gardener.
|
25
25
|
# === Parameters
|
26
|
-
# * :wheelbarrow = the socket size for the garden communication packets, in bytes,
|
26
|
+
# * :wheelbarrow = the socket size for the garden communication packets, in bytes, up to 8192, defaults to 124
|
27
27
|
# * :rows = garden rows number, the number of concurent threads
|
28
28
|
# * :init_timeout = allow to pause execution to allow for larger gardens to initialize
|
29
29
|
# === Example
|
30
|
-
# gardener = Gardener.new({:wheelbarrow =>
|
30
|
+
# gardener = Gardener.new({:wheelbarrow => 124, :rows => 6, :init_timeout}) { your_special_garden function }
|
31
31
|
#
|
32
32
|
|
33
33
|
def initialize(options,gardener_block)
|
34
|
-
Toolshed::block_size = if options[:wheelbarrow].nil?
|
35
|
-
elsif options[:wheelbarrow]
|
34
|
+
Toolshed::block_size = if options[:wheelbarrow].nil? then 124
|
35
|
+
elsif options[:wheelbarrow] > 8192 then 8192
|
36
36
|
else options[:wheelbarrow]
|
37
37
|
end
|
38
38
|
|
data/test/tc_high_api.rb
CHANGED
@@ -34,7 +34,7 @@ class TestHighAPI < Test::Unit::TestCase
|
|
34
34
|
private
|
35
35
|
|
36
36
|
def set_gardener
|
37
|
-
@g = Abundance.gardener(:
|
37
|
+
@g = Abundance.gardener(:rows => @rows, :init_timeout => 3) do
|
38
38
|
Abundance.init_status(true,Process.pid)
|
39
39
|
Abundance.grow do |seed|
|
40
40
|
seed.crop(true, "gardener: #{seed.sprout}")
|
data/test/tc_multi_gardener.rb
CHANGED
@@ -19,7 +19,7 @@ class TestHighAPI < Test::Unit::TestCase
|
|
19
19
|
private
|
20
20
|
|
21
21
|
def set_gardener1
|
22
|
-
@g1 = Abundance.gardener(:
|
22
|
+
@g1 = Abundance.gardener(:rows => @rows, :init_timeout => 3) do
|
23
23
|
Abundance.init_status(true,Process.pid)
|
24
24
|
Abundance.grow do |seed|
|
25
25
|
seed.crop(true, "gardener1: #{seed.sprout}")
|
@@ -28,7 +28,7 @@ class TestHighAPI < Test::Unit::TestCase
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def set_gardener2
|
31
|
-
@g2 = Abundance.gardener(:
|
31
|
+
@g2 = Abundance.gardener(:rows => @rows, :init_timeout => 3) do
|
32
32
|
Abundance.init_status(true,Process.pid)
|
33
33
|
Abundance.grow do |seed|
|
34
34
|
seed.crop(true, "gardener2: #{seed.sprout}")
|
@@ -43,6 +43,7 @@ class TestHighAPI < Test::Unit::TestCase
|
|
43
43
|
answer1 = @g1.harvest(id1)
|
44
44
|
answer2 = @g2.harvest(id2)
|
45
45
|
|
46
|
+
assert(answer1[:message] != answer2[:message])
|
46
47
|
assert(answer1[:message] =~ /gardener1.*/)
|
47
48
|
assert(answer2[:message] =~ /gardener2.*/)
|
48
49
|
end
|
data/test/tc_robustness.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: abundance
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Louis-Philippe Perron
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-01-
|
12
|
+
date: 2009-01-13 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -24,6 +24,8 @@ extra_rdoc_files: []
|
|
24
24
|
files:
|
25
25
|
- lib/abundance.rb
|
26
26
|
- lib/garden.rb
|
27
|
+
- lib/garden_cycles.rb
|
28
|
+
- lib/garden_rows.rb
|
27
29
|
- lib/gardener.rb
|
28
30
|
- lib/seed.rb
|
29
31
|
- lib/toolshed.rb
|