abundance 1.2.1 → 1.2.2
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/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
|