abundance 1.2.4 → 1.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/abundance.rb CHANGED
@@ -9,7 +9,7 @@
9
9
  #
10
10
  # And not:
11
11
  # * a replacement for Thread.new invocations
12
- # * a replacement for Thread friendly programming languages like Erlang
12
+ # * a replacement for concurrent programming languages like Erlang
13
13
  #
14
14
  # Its initial implementation uses:
15
15
  # * pure ruby
@@ -71,8 +71,8 @@ class Abundance
71
71
  # id1 = gardener.seed('command1')
72
72
  # id2 = gardener.seed('command2')
73
73
  #
74
- # result1 = gardener.harvest(id1)
75
- # result2 = gardener.harvest(id2)
74
+ # result1 = gardener.harvest(:one,id1)
75
+ # result2 = gardener.harvest(:one,id2)
76
76
  #
77
77
  # # with many more seeds over here
78
78
  #
data/lib/garden.rb CHANGED
@@ -15,7 +15,7 @@
15
15
  # :title:Garden
16
16
 
17
17
  class Garden
18
- require 'garden_rows'
18
+ require 'rows'
19
19
  require 'garden_cycles'
20
20
  include Cycles
21
21
  require 'toolshed'
@@ -52,12 +52,6 @@ class Garden
52
52
  report_growth(message_block)
53
53
  when :harvest
54
54
  harvest_some(message_block)
55
- when :init
56
- ask_for_init_status(message_block)
57
- when :init_crop
58
- answer_init_status(message_block)
59
- when :seed_all_crop
60
- special_crop_seed_all(message_block)
61
55
  when :close
62
56
  close_all(message_block)
63
57
  else
data/lib/garden_cycles.rb CHANGED
@@ -1,43 +1,43 @@
1
1
  class Garden
2
+ # The Cycles module is a set of method used by the Garden's fork.
3
+ # You will not need to use these methods unless you plan on refactoring the Garden.
4
+ #
2
5
  # Author:: lp (mailto:lp@spiralix.org)
3
6
  # Copyright:: 2008 Louis-Philippe Perron - Released under the terms of the MIT license
4
7
  # :title:Cycles
5
8
  module Cycles
6
9
 
7
10
  def set_my_containers
8
- @quit = false; @full_crop = false; @do_init = nil; @seed_all_message_block = nil; @init_all_crop = []
9
- @harvest = []; @rows_socket_paths = []; @init_done = []; @seed_all_done = []; @seed_all_crop = []
10
- @seeds = []; @sprouts = []; @crops = []; @id = 0
11
+ @close_message_block = nil; @full_crop_message_block = nil
12
+ @init_message_block = nil; @seed_all_message_block = nil
13
+ @harvest_queue = []; @waiting_rows = []; @id = 0
14
+ @seeds = []; @sprouts = []; @crops = []
11
15
  end
12
16
 
13
17
  def seed_if_row_available
14
18
  catch :fill_rows do
15
19
  loop do
16
- if ! @seed_all_message_block.nil? && ! @rows_socket_paths.empty? && @seed_all_done.size != @seed_all_message_block[1]
17
- row_socket_path = @rows_socket_paths.shift
18
- unless @seed_all_done.include?( row_socket_path )
20
+ if @seed_all_message_block && ! @waiting_rows.empty? && @seed_all_message_block[4][:row_done].size != @seed_all_message_block[1]
21
+ row_socket_path = @waiting_rows.shift
22
+ unless @seed_all_message_block[4][:row_done].include?( row_socket_path )
19
23
  socket_send([:seed,:all,@seed_all_message_block[2],row_socket_path])
20
- @seed_all_done << row_socket_path
24
+ @seed_all_message_block[4][:row_done] << row_socket_path
21
25
  else
22
- @rows_socket_paths << row_socket_path
26
+ @waiting_rows << row_socket_path
23
27
  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 )
28
+ elsif @init_message_block && ! @waiting_rows.empty? && @init_message_block[4][:row_done].size != @init_message_block[2]
29
+ row_socket_path = @waiting_rows.shift
30
+ unless @init_message_block[4][:row_done].include?( row_socket_path )
27
31
  socket_send([:seed,:init,'init_status',row_socket_path])
28
- @init_done << row_socket_path
32
+ @init_message_block[4][:row_done] << row_socket_path
29
33
  else
30
- @rows_socket_paths << row_socket_path
34
+ @waiting_rows << row_socket_path
31
35
  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([:seed,: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([:seed,:quit,seed,row_socket_path])
36
+ elsif ! @seeds.empty? && ! @waiting_rows.empty?
37
+ seed = @seeds.shift; @sprouts[seed[:id]] = seed
38
+ socket_send([:seed,:sprout,seed,@waiting_rows.shift])
39
+ elsif @close_message_block && ! @waiting_rows.empty?
40
+ socket_send([:seed,:quit,nil,@waiting_rows.shift])
41
41
  else
42
42
  throw :fill_rows
43
43
  end
@@ -49,23 +49,24 @@ class Garden
49
49
  case message_block[1]
50
50
  when :one
51
51
  @id += 1; @seeds << {:id => @id , :seed => message_block[2]}
52
- socket_send([message_block[0],:garden,@id,message_block[3]])
52
+ message_block[2] = @id; socket_send(message_block)
53
53
  else
54
54
  @seed_all_message_block = Array.new(message_block)
55
+ @seed_all_message_block[4] = {:row_done => [], :crops => []}
55
56
  end
56
57
  end
57
58
 
58
59
  def this_row_is_available(message_block)
59
- if @quit
60
+ if @close_message_block
60
61
  message_block = [:row, :quit, nil, message_block[3]]
61
- elsif ! @seed_all_message_block.nil? && @seed_all_done.size != @seed_all_message_block[1] && ! @seed_all_done.include?( message_block[3] )
62
+ elsif @seed_all_message_block && @seed_all_message_block[4][:row_done].size != @seed_all_message_block[1] && ! @seed_all_message_block[4][:row_done].include?( message_block[3] )
62
63
  message_block = [:row, :all, @seed_all_message_block[2], message_block[3]]
63
- @seed_all_done << message_block[3]
64
- elsif ! @do_init.nil? && @init_done.size != @do_init && ! @init_done.include?( message_block[3] )
64
+ @seed_all_message_block[4][:row_done] << message_block[3]
65
+ elsif @init_message_block && @init_message_block[4][:row_done].size != @init_message_block[2] && ! @init_message_block[4][:row_done].include?( message_block[3] )
65
66
  message_block = [:row, :init, 'init_status', message_block[3]]
66
- @init_done << message_block[3]
67
+ @init_message_block[4][:row_done] << message_block[3]
67
68
  elsif @seeds.empty?
68
- @rows_socket_paths << message_block[2]
69
+ @waiting_rows << message_block[2]
69
70
  message_block = [:row, :wait, nil, message_block[3]]
70
71
  else
71
72
  seed = @seeds.shift; @sprouts[seed[:id]] = seed
@@ -75,97 +76,95 @@ class Garden
75
76
  end
76
77
 
77
78
  def save_crop_for(message_block)
78
- @sprouts[message_block[2][:id]] = nil
79
- @crops[message_block[2][:id]] = message_block[2]
80
- if @harvest[message_block[2][:id]]
81
- socket_send([message_block[0],:garden,message_block[2], @harvest[message_block[2][:id]][:client_socket_path]])
82
- @crops[message_block[2][:id]] = @harvest[message_block[2][:id]] = nil
83
- elsif @full_crop && @seeds.compact.empty? && @sprouts.compact.empty?
84
- socket_send([message_block[0],:garden,@crops.compact,@mem_client_socket_path])
85
- @crops.clear; @full_crop = false
79
+ case message_block[1]
80
+ when :harvest
81
+ @sprouts[message_block[2][:id]] = nil
82
+ @crops[message_block[2][:id]] = message_block[2]
83
+ if @harvest_queue[message_block[2][:id]]
84
+ socket_send(message_block[0..2]+[@harvest_queue[message_block[2][:id]]])
85
+ @crops[message_block[2][:id]] = @harvest_queue[message_block[2][:id]] = nil
86
+ elsif @full_crop_message_block && @seeds.compact.empty? && @sprouts.compact.empty?
87
+ socket_send(message_block[0..1]+[@crops.compact,@full_crop_message_block[3]])
88
+ @crops.clear; @full_crop_message_block = nil
89
+ end
90
+ when :seed_all
91
+ @seed_all_message_block[4][:crops] << message_block[2]
92
+ if @seed_all_message_block[4][:crops].size == @seed_all_message_block[1]
93
+ @seed_all_message_block[2] = @seed_all_message_block[4][:crops]; @seed_all_message_block[4] = nil
94
+ socket_send(@seed_all_message_block.compact); @seed_all_message_block = nil
95
+ end
96
+ when :init
97
+ @init_message_block[4][:crops] << message_block[2]
98
+ if @init_message_block[4][:crops].size == @init_message_block[2]
99
+ @init_message_block[2] = @init_message_block[4][:crops]; @init_message_block[4] = nil
100
+ socket_send(@init_message_block.compact); @init_message_block = nil
101
+ end
86
102
  end
87
103
  end
88
104
 
89
105
  def report_growth(message_block)
90
- case message_block[2]
106
+ case message_block[1]
91
107
  when :progress
92
108
  value = @crops.size.to_f / (@crops.size + @sprouts.compact.size + @seeds.size)
93
109
  value = 1 if value.nan?; progress = sprintf( "%.2f", value)
94
- socket_send([message_block[0],:garden,progress,message_block[3]])
110
+ message_block[2] = progress
95
111
  when :seed
96
- socket_send([message_block[0],:garden,@seeds.size,message_block[3]])
112
+ message_block[2] = @seeds.size
97
113
  when :sprout
98
- socket_send([message_block[0],:garden,@sprouts.compact.size,message_block[3]])
114
+ message_block[2] = @sprouts.compact.size
99
115
  when :crop
100
- socket_send([message_block[0],:garden,@crops.size,message_block[3]])
116
+ message_block[2] = @crops.size
101
117
  else
102
- socket_send([message_block[0],:garden,false,message_block[3]])
118
+ message_block[2] = false
103
119
  end
120
+ socket_send(message_block)
104
121
  end
105
122
 
106
123
  def harvest_some(message_block)
107
- case message_block[2]
124
+ case message_block[1]
125
+ when :one
126
+ unless message_block[2].nil?
127
+ if @crops[message_block[2]]
128
+ socket_send(message_block[0..1]+[@crops[message_block[2]],message_block[3]])
129
+ @crops[message_block[2]] = nil
130
+ else
131
+ @harvest_queue[message_block[2]] = message_block[3]
132
+ end
133
+ else
134
+ message_block[2] = false; socket_send(message_block)
135
+ end
108
136
  when :all
109
- socket_send([message_block[0],:garden,{:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops.compact},message_block[3]])
137
+ message_block[2] = {:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops.compact}
138
+ socket_send(message_block)
110
139
  when :seed
111
- socket_send([message_block[0],:garden,@seeds,message_block[3]])
140
+ message_block[2] = @seeds; socket_send(message_block)
112
141
  when :sprout
113
- socket_send([message_block[0],:garden,@sprouts.compact,message_block[3]])
142
+ message_block[2] = @sprouts.compact; socket_send(message_block)
114
143
  when :crop
115
- socket_send([message_block[0],:garden,@crops.compact,message_block[3]])
116
- @crops.clear
144
+ message_block[2] = @crops.compact; socket_send(message_block); @crops.clear
117
145
  when :full_crop
118
146
  if @seeds.compact.empty? && @sprouts.compact.empty?
119
- socket_send([message_block[0],:garden,@crops.compact,message_block[3]])
120
- @crops.clear
147
+ message_block[2] = @crops.compact; socket_send(message_block); @crops.clear
121
148
  else
122
- @full_crop = true
123
- @mem_client_socket_path = message_block[3]
149
+ @full_crop_message_block = Array.new(message_block)
124
150
  end
151
+ when :init
152
+ @init_message_block = Array.new(message_block)
153
+ @init_message_block[4] = {:row_done => [], :crops => []}
125
154
  else
126
- if message_block[2].is_a? Integer
127
- if @crops[message_block[2]]
128
- socket_send([message_block[0],:garden,@crops[message_block[2]],message_block[3]])
129
- @crops[message_block[2]] = nil
130
- else
131
- @harvest[message_block[2]] = {:client_socket_path => message_block[3]}
132
- end
133
- else
134
- socket_send([message_block[0],:garden,false,message_block[3]])
135
- end
155
+ message_block[2] = false; socket_send(message_block)
136
156
  end
137
157
  end
138
-
139
- def ask_for_init_status(message_block)
140
- @do_init = message_block[2]
141
- @init_return = {:client_socket_path => message_block[3]}
142
- end
143
-
144
- def answer_init_status(message_block)
145
- @init_all_crop << message_block[2]
146
- if @init_all_crop.size == @do_init
147
- socket_send([message_block[0],:garden,@init_all_crop, @init_return[:client_socket_path]])
148
- @init_return = Hash.new; @init_done = Array.new; @do_init = nil; @init_all_crop = Array.new
149
- end
150
- end
151
-
152
- def special_crop_seed_all(message_block)
153
- @seed_all_crop << message_block[2]
154
- if @seed_all_crop.size == @seed_all_message_block[1]
155
- socket_send([message_block[0],:garden,@seed_all_crop, @seed_all_message_block[3]])
156
- @seed_all_message_block = nil; @seed_all_done = Array.new; @seed_all_crop = Array.new
157
- end
158
- end
159
-
158
+
160
159
  def close_all(message_block)
161
- if message_block[2][:level] == :garden
162
- @seeds_pid = message_block[2][:pid]
163
- @quit = true
164
- @mem_client_socket_path = message_block[3]
165
- else
166
- @seeds_pid.delete(message_block[2][:pid].to_i)
167
- if @seeds_pid.empty?
168
- socket_send([:close,:garden,{:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops.compact}, @mem_client_socket_path])
160
+ case message_block[1]
161
+ when :garden
162
+ @close_message_block = Array.new(message_block)
163
+ when :row
164
+ @close_message_block[2].delete(message_block[2].to_i)
165
+ if @close_message_block[2].empty?
166
+ @close_message_block[2] = {:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops.compact}
167
+ socket_send(@close_message_block)
169
168
  exit
170
169
  end
171
170
  end
data/lib/gardener.rb CHANGED
@@ -48,7 +48,7 @@ class Gardener
48
48
  # === Example
49
49
  # puts gardener.init_status.inspect # => [{:message=>"init ok", :success=>true, :pid=>4760}, {:message=>"init failed", :success=>false, :pid=>4761}]
50
50
  def init_status
51
- message_block = socket_duplex([:init,:gardener,@garden_rows.pids.size,@garden_path])
51
+ message_block = socket_duplex([:harvest,:init,@garden_rows.pids.size,@garden_path])
52
52
  message_block[2].map! do |row|
53
53
  {:success => row[:success], :message => row[:message], :pid => row[:id]}
54
54
  end
@@ -92,8 +92,8 @@ class Gardener
92
92
  # progress = gardener.growth(:progress)
93
93
  # puts "progress is now #{progress}" # => progress is now 0.75
94
94
 
95
- def growth(data=:progress)
96
- message_block = socket_duplex([:growth,:gardener,data,@garden_path])
95
+ def growth(option=:progress)
96
+ message_block = socket_duplex([:growth,option,nil,@garden_path])
97
97
  return message_block[2]
98
98
  end
99
99
 
@@ -101,18 +101,20 @@ class Gardener
101
101
  # It has two different behaviour on queue data, one for ripe elements where it removes them from crop array ( on _seedID_ and :crop invocations ),
102
102
  # for all other methods of invocation it leaves the queue intact.
103
103
  # === Parameter
104
- # The parameter given as a symbol specifies the level of queue results you wish to get:
105
- # * seedID = return the result for a specific seed, if seed hasn't processed it wait until completed, _seedID_ is removed from crop array
104
+ # The option given as a symbol specifies the level of queue results you wish to get:
106
105
  # * :crop = return an array of seed for which process has completed, empties the crop array.
107
106
  # * :sprout = return an array of seed actually processing
108
107
  # * :seed = return an array of seed waiting to be processed
109
108
  # * :all = return a hash of respective arrays for crops, sprouts and seeds
110
109
  # * :full_crop = wait for all seeds to be done processing, then returns as in :crop.
110
+ # * :one = return the result for a specific seed, if seed hasn't processed it wait until completed, _seed_id_ is removed from crop array
111
+ # When specifying :one as option, a seed ID is also required:
112
+ # * _seedID_ = the id as returned by the +seed+ method
111
113
  # === Example
112
- # seed1_result = gardener.harvest(id_seed_1)
114
+ # seed1_result = gardener.harvest(:one,id_seed_1)
113
115
 
114
- def harvest(data)
115
- message_block = socket_duplex([:harvest,:gardener,data,@garden_path])
116
+ def harvest(option,seed_id=nil)
117
+ message_block = socket_duplex([:harvest,option,seed_id,@garden_path])
116
118
  return message_block[2]
117
119
  end
118
120
 
@@ -122,7 +124,7 @@ class Gardener
122
124
  # final_harvest = gardener.close
123
125
 
124
126
  def close
125
- message_block = socket_duplex([:close,:gardener,{:level => :garden, :pid => @garden_rows.pids},@garden_path])
127
+ message_block = socket_duplex([:close,:garden,@garden_rows.pids,@garden_path])
126
128
  return message_block[2]
127
129
  end
128
130
 
@@ -20,6 +20,8 @@ class Garden
20
20
  # :title:Rows
21
21
 
22
22
  class Rows
23
+ require 'rows_paths'
24
+ include Paths
23
25
  require 'toolshed'
24
26
  include Toolshed
25
27
  attr_reader :pids
@@ -42,7 +44,6 @@ class Garden
42
44
  @pids = []
43
45
  rows.times do
44
46
  @pids << fork do
45
- @seed_all = false
46
47
  set_my_socket_as_a(:row,garden_pid)
47
48
  t1 = Thread.new do
48
49
  gardener_block.call
@@ -54,42 +55,28 @@ class Garden
54
55
  message_block = socket_duplex([:row,:row,my_socket_path,@garden_path])
55
56
  case message_block[1]
56
57
  when :sprout
57
- $seed = message_block[2]
58
+ sprout(message_block)
58
59
  when :all
59
- @seed_all = true
60
- $seed = {:id => Process.pid, :seed => message_block[2]}
60
+ all(message_block)
61
61
  when :wait
62
62
  message_block = socket_recv
63
63
  case message_block[1]
64
64
  when :sprout
65
- $seed = message_block[2]
65
+ sprout(message_block)
66
66
  when :all
67
- @seed_all = true
68
- $seed = {:id => Process.pid, :seed => message_block[2]}
67
+ all(message_block)
69
68
  when :init
70
- $init = {:seed => 'init_status', :message => 'No Init Message', :id => Process.pid} if $init.nil?
71
- socket_send([:init_crop,:row,$init,@garden_path])
69
+ init
72
70
  when :quit
73
- pid = Process.pid
74
- socket_send([:close,:row,{:level => :seed, :pid => pid},@garden_path])
75
- exit
71
+ quit
76
72
  end
77
73
  when :init
78
- $init = {:seed => 'init_status', :message => 'No Init Message', :id => Process.pid} if $init.nil?
79
- socket_send([:init_crop,:row,$init,@garden_path])
74
+ init
80
75
  when :quit
81
- pid = Process.pid
82
- socket_send([:close,:row,{:level => :seed, :pid => pid},@garden_path])
83
- exit
76
+ quit
84
77
  end
85
- elsif ! $seed[:success].nil?
86
- if @seed_all
87
- socket_send([:seed_all_crop,:row,$seed,@garden_path])
88
- @seed_all = false
89
- else
90
- socket_send([:crop,:row,$seed,@garden_path])
91
- end
92
- $seed = nil;
78
+ elsif $seed[:success]
79
+ crop
93
80
  else
94
81
  t1.run
95
82
  end
data/lib/rows_paths.rb ADDED
@@ -0,0 +1,40 @@
1
+ class Garden
2
+ class Rows
3
+ # The Paths module is a set of method used by the Rows's forks.
4
+ # You will not need to use these methods unless you plan on refactoring the Rows.
5
+ #
6
+ # Author:: lp (mailto:lp@spiralix.org)
7
+ # Copyright:: 2008 Louis-Philippe Perron - Released under the terms of the MIT license
8
+ # :title:Rows
9
+ module Paths
10
+
11
+ def all(message_block)
12
+ $seed = {:id => Process.pid, :seed => message_block[2], :all => true}
13
+ end
14
+
15
+ def crop
16
+ if $seed[:all]
17
+ socket_send([:crop,:seed_all,$seed,@garden_path])
18
+ else
19
+ socket_send([:crop,:harvest,$seed,@garden_path])
20
+ end
21
+ $seed = nil
22
+ end
23
+
24
+ def init
25
+ $init = {:seed => 'init_status', :message => 'No Init Message', :id => Process.pid} if $init.nil?
26
+ socket_send([:crop,:init,$init,@garden_path])
27
+ end
28
+
29
+ def quit
30
+ socket_send([:close,:row,Process.pid,@garden_path])
31
+ exit
32
+ end
33
+
34
+ def sprout(message_block)
35
+ $seed = message_block[2]
36
+ end
37
+
38
+ end
39
+ end
40
+ end
data/test/tc_high_api.rb CHANGED
@@ -69,7 +69,7 @@ class TestHighAPI < Test::Unit::TestCase
69
69
  id = @g.seed(Process.pid)
70
70
  assert_kind_of(Integer,id)
71
71
 
72
- answer = @g.harvest(id)
72
+ answer = @g.harvest(:one,id)
73
73
  assert_kind_of(Hash,answer)
74
74
  assert_equal(Process.pid,answer[:seed])
75
75
  assert_equal(id,answer[:id])
@@ -40,8 +40,8 @@ class TestHighAPI < Test::Unit::TestCase
40
40
  id1 = @g1.seed(Process.pid)
41
41
  id2 = @g2.seed(Process.pid)
42
42
 
43
- answer1 = @g1.harvest(id1)
44
- answer2 = @g2.harvest(id2)
43
+ answer1 = @g1.harvest(:one,id1)
44
+ answer2 = @g2.harvest(:one,id2)
45
45
 
46
46
  assert(answer1[:message] != answer2[:message])
47
47
  assert(answer1[:message] =~ /gardener1.*/)
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
4
+ version: 1.2.5
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-16 00:00:00 -05:00
12
+ date: 2009-01-18 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -25,8 +25,9 @@ files:
25
25
  - lib/abundance.rb
26
26
  - lib/garden.rb
27
27
  - lib/garden_cycles.rb
28
- - lib/garden_rows.rb
29
28
  - lib/gardener.rb
29
+ - lib/rows.rb
30
+ - lib/rows_paths.rb
30
31
  - lib/seed.rb
31
32
  - lib/toolshed.rb
32
33
  - test/tc_burst.rb