abundance 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/lib/garden.rb +58 -62
  2. data/lib/gardener.rb +7 -8
  3. data/lib/toolshed.rb +64 -110
  4. metadata +2 -2
data/lib/garden.rb CHANGED
@@ -32,68 +32,67 @@ class Garden
32
32
  def initialize
33
33
  @pid = fork do
34
34
  @quit = false; @full_crop = false; @do_init = nil; @seed_all = nil; @init_all_crop = []
35
- @harvest = []; @rows_port = []; @init_done = []; @seed_all_done = []; @seed_all_crop = []
35
+ @harvest = []; @rows_socket_paths = []; @init_done = []; @seed_all_done = []; @seed_all_crop = []
36
36
  @seeds = []; @sprouts = []; @crops = []; @id = 0
37
- @socket_server = Toolshed.socket_server(Toolshed::garden_port)
38
- @socket_client_temp = Toolshed.socket_client_temp
37
+ set_my_socket_as_a(:garden)
39
38
  loop do
40
39
  catch :fill_rows do
41
40
  loop do
42
- if ! @seed_all.nil? && ! @rows_port.empty? && @seed_all_done.size != @seed_all[0]
43
- row_port = @rows_port.shift
44
- unless @seed_all_done.include?( row_port )
45
- socket_client_temp(:seed_all,@seed_all[1],row_port)
46
- @seed_all_done << row_port
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
47
46
  else
48
- @rows_port << row_port
47
+ @rows_socket_paths << row_socket_path
49
48
  end
50
- elsif ! @do_init.nil? && ! @rows_port.empty? && @init_done.size != @do_init
51
- row_port = @rows_port.shift
52
- unless @init_done.include?( row_port )
53
- socket_client_temp(:init,'init_status',row_port)
54
- @init_done << row_port
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
55
54
  else
56
- @rows_port << row_port
55
+ @rows_socket_paths << row_socket_path
57
56
  end
58
- elsif ! @seeds.empty? && ! @rows_port.empty?
57
+ elsif ! @seeds.empty? && ! @rows_socket_paths.empty?
59
58
  seed = @seeds.shift
60
59
  @sprouts[seed[:id]] = seed
61
- row_port = @rows_port.shift
62
- socket_client_temp(:sprout,seed,row_port)
63
- elsif @quit && ! @rows_port.empty?
60
+ row_socket_path = @rows_socket_paths.shift
61
+ socket_send(:sprout,seed,row_socket_path)
62
+ elsif @quit && ! @rows_socket_paths.empty?
64
63
  seed = nil
65
- row_port = @rows_port.shift
66
- socket_client_temp(:quit,seed,row_port)
64
+ row_socket_path = @rows_socket_paths.shift
65
+ socket_send(:quit,seed,row_socket_path)
67
66
  else
68
67
  throw :fill_rows
69
68
  end
70
69
  end
71
70
  end
72
- command, data, clientport, clientname, clientaddr = socket_server_recv
71
+ command, data, client_socket_path = socket_recv
73
72
  case command
74
73
  when :seed
75
74
  @id += 1; @seeds << {:id => @id , :seed => data}
76
- socket_server_send(command,@id,clientaddr,clientport)
75
+ socket_send(command,@id,client_socket_path)
77
76
  when :row
78
77
  if @quit
79
78
  command = :quit
80
79
  seed = nil
81
80
  elsif @seeds.empty?
82
81
  seed = nil
83
- @rows_port << data
82
+ @rows_socket_paths << data
84
83
  else
85
84
  seed = @seeds.shift
86
85
  @sprouts[seed[:id]] = seed
87
86
  end
88
- socket_server_send(command,seed,clientaddr,clientport)
87
+ socket_send(command,seed,client_socket_path)
89
88
  when :crop
90
89
  @sprouts[data[:id]] = nil
91
- @crops[data[:id]] = data; socket_server_send(command,true,clientaddr,clientport)
90
+ @crops[data[:id]] = data
92
91
  if @harvest[data[:id]]
93
- socket_server_send(command,data, @harvest[data[:id]][:clientaddr], @harvest[data[:id]][:clientport])
92
+ socket_send(command,data, @harvest[data[:id]][:client_socket_path])
94
93
  @crops[data[:id]] = @harvest[data[:id]] = nil
95
94
  elsif @full_crop && @seeds.compact.empty? && @sprouts.compact.empty?
96
- socket_server_send(command,@crops.compact,@mem_addr,@mem_port)
95
+ socket_send(command,@crops.compact,@mem_client_socket_path)
97
96
  @crops.clear; @full_crop = false
98
97
  end
99
98
  when :growth
@@ -101,81 +100,79 @@ class Garden
101
100
  when :progress
102
101
  value = @crops.size.to_f / (@crops.size + @sprouts.compact.size + @seeds.size)
103
102
  value = 1 if value.nan?; progress = sprintf( "%.2f", value)
104
- socket_server_send(command,progress,clientaddr,clientport)
103
+ socket_send(command,progress,client_socket_path)
105
104
  when :seed
106
- socket_server_send(command,@seeds.size,clientaddr,clientport)
105
+ socket_send(command,@seeds.size,client_socket_path)
107
106
  when :sprout
108
- socket_server_send(command,@sprouts.compact.size,clientaddr,clientport)
107
+ socket_send(command,@sprouts.compact.size,client_socket_path)
109
108
  when :crop
110
- socket_server_send(command,@crops.size,clientaddr,clientport)
109
+ socket_send(command,@crops.size,client_socket_path)
111
110
  else
112
- socket_server_send(command,false,clientaddr,clientport)
111
+ socket_send(command,false,client_socket_path)
113
112
  end
114
113
  when :harvest
115
114
  case data
116
115
  when :all
117
- socket_server_send(command,{:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops.compact},clientaddr,clientport)
116
+ socket_send(command,{:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops.compact},client_socket_path)
118
117
  when :seed
119
- socket_server_send(command,@seeds,clientaddr,clientport)
118
+ socket_send(command,@seeds,client_socket_path)
120
119
  when :sprout
121
- socket_server_send(command,@sprouts.compact,clientaddr,clientport)
120
+ socket_send(command,@sprouts.compact,client_socket_path)
122
121
  when :crop
123
- socket_server_send(command,@crops.compact,clientaddr,clientport)
122
+ socket_send(command,@crops.compact,client_socket_path)
124
123
  @crops.clear
125
124
  when :full_crop
126
125
  if @seeds.compact.empty? && @sprouts.compact.empty?
127
- socket_server_send(command,@crops.compact,clientaddr,clientport)
126
+ socket_send(command,@crops.compact,client_socket_path)
128
127
  @crops.clear
129
128
  else
130
129
  @full_crop = true
131
- @mem_addr = clientaddr; @mem_port = clientport
130
+ @mem_client_socket_path = client_socket_path
132
131
  end
133
132
  else
134
133
  if data.is_a? Integer
135
134
  if @crops[data]
136
- socket_server_send(command,@crops[data],clientaddr,clientport)
135
+ socket_send(command,@crops[data],client_socket_path)
137
136
  @crops[data] = nil
138
137
  else
139
- @harvest[data] = {:clientaddr => clientaddr, :clientport => clientport}
138
+ @harvest[data] = {:client_socket_path => client_socket_path}
140
139
  end
141
140
  else
142
- socket_server_send(command,false,clientaddr,clientport)
141
+ socket_send(command,false,client_socket_path)
143
142
  end
144
143
  end
145
144
  when :init
146
145
  @do_init = data
147
- @init_return = {:clientaddr => clientaddr, :clientport => clientport}
146
+ @init_return = {:client_socket_path => client_socket_path}
148
147
  when :init_crop
149
- socket_server_send(command,true,clientaddr,clientport)
150
148
  @init_all_crop << data
151
149
  if @init_all_crop.size == @do_init
152
- socket_server_send(command,@init_all_crop, @init_return[:clientaddr], @init_return[:clientport])
150
+ socket_send(command,@init_all_crop, @init_return[:client_socket_path])
153
151
  @init_return = Hash.new; @init_done = Array.new; @do_init = nil; @init_all_crop = Array.new
154
152
  end
155
153
  when :seed_all
156
154
  @seed_all = data
157
- @seed_all_return = {:clientaddr => clientaddr, :clientport => clientport, :data => []}
155
+ @seed_all_return = {:client_socket_path => client_socket_path, :data => []}
158
156
  when :seed_all_crop
159
- socket_server_send(command,true,clientaddr,clientport)
160
157
  @seed_all_crop << data
161
158
  if @seed_all_crop.size == @seed_all[0]
162
- socket_server_send(command,@seed_all_crop, @seed_all_return[:clientaddr], @seed_all_return[:clientport])
159
+ socket_send(command,@seed_all_crop, @seed_all_return[:client_socket_path])
163
160
  @seed_all = nil; @seed_all_return = Hash.new; @seed_all_done = Array.new; @seed_all_crop = Array.new
164
161
  end
165
162
  when :close
166
163
  if data[:level] == :garden
167
164
  @seeds_pid = data[:pid]
168
165
  @quit = true
169
- @mem_addr = clientaddr; @mem_port = clientport
166
+ @mem_client_socket_path = client_socket_path
170
167
  else
171
168
  @seeds_pid.delete(data[:pid].to_i)
172
169
  if @seeds_pid.empty?
173
- socket_server_send(:close,{:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops.compact}, @mem_addr, @mem_port)
170
+ socket_send(:close,{:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops.compact}, @mem_client_socket_path)
174
171
  exit
175
172
  end
176
173
  end
177
174
  else
178
- socket_server_send(command,false,clientaddr,clientport)
175
+ socket_send(command,false,client_socket_path)
179
176
  end
180
177
  end
181
178
  end
@@ -194,7 +191,7 @@ class Garden
194
191
  #
195
192
 
196
193
  def rows(rows,init_timeout,grow_block)
197
- Rows.new(rows,init_timeout,grow_block)
194
+ Rows.new(rows,init_timeout,@pid,grow_block)
198
195
  end
199
196
 
200
197
  # :title:Rows
@@ -213,17 +210,16 @@ class Garden
213
210
  # === Parameter
214
211
  # * _rows_ = garden rows number, the number of concurent threads
215
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
216
214
  # === Example
217
215
  # rows = Rows.new(4,2) { grow_block }
218
216
 
219
- def initialize(rows,init_timeout,gardener_block)
217
+ def initialize(rows,init_timeout,garden_pid,gardener_block)
220
218
  @pids = []
221
219
  rows.times do
222
- row_port = Toolshed.available_port
223
220
  @pids << fork do
224
- @socket_client_perm = Toolshed.socket_client_perm
225
221
  @seed_all = false
226
- @socket_server = Toolshed.socket_server(row_port)
222
+ set_my_socket_as_a(:row,garden_pid)
227
223
  t1 = Thread.new do
228
224
  gardener_block.call
229
225
  end
@@ -231,15 +227,15 @@ class Garden
231
227
  t2 = Thread.new do
232
228
  loop do
233
229
  if $seed.nil?
234
- command, data = socket_client_perm_duplex(:row,row_port)
230
+ command, data = socket_duplex(:row,my_socket_path)
235
231
  if command == :quit
236
232
  pid = Process.pid
237
- socket_client_perm_send(:close,{:level => :seed, :pid => pid})
233
+ socket_send(:close,{:level => :seed, :pid => pid})
238
234
  exit
239
235
  end
240
236
  $seed = data
241
237
  if $seed.nil?
242
- command, data, clientport, clientname, clientaddr = socket_server_recv
238
+ command, data, client_socket_path = socket_recv
243
239
  case command
244
240
  when :sprout
245
241
  $seed = data
@@ -248,15 +244,15 @@ class Garden
248
244
  $seed = {:id => Process.pid, :seed => data}
249
245
  when :init
250
246
  $init = {:seed => 'init_status', :message => 'No Init Message', :id => Process.pid} if $init.nil?
251
- command, data = socket_client_perm_duplex(:init_crop,$init)
247
+ socket_send(:init_crop,$init)
252
248
  end
253
249
  end
254
250
  elsif ! $seed[:success].nil?
255
251
  if @seed_all
256
- command, data = socket_client_perm_duplex(:seed_all_crop,$seed)
252
+ socket_send(:seed_all_crop,$seed)
257
253
  @seed_all = false
258
254
  else
259
- command, data = socket_client_perm_duplex(:crop,$seed)
255
+ socket_send(:crop,$seed)
260
256
  end
261
257
  $seed = nil;
262
258
  else
data/lib/gardener.rb CHANGED
@@ -35,12 +35,11 @@ class Gardener
35
35
  elsif options[:wheelbarrow] < 1024 then 1024
36
36
  else options[:wheelbarrow]
37
37
  end
38
- Toolshed::garden_port = Toolshed.available_port
39
38
 
40
39
  @garden = Garden.new
41
40
  @garden_rows = @garden.rows(options[:rows], options[:init_timeout], gardener_block)
42
41
 
43
- @socket_client_perm = Toolshed.socket_client_perm
42
+ set_my_socket_as_a(:gardener,@garden.pid)
44
43
  end
45
44
 
46
45
  # The +init_status+ method for the Gardener instance allow to harvest an initialisation status message
@@ -49,7 +48,7 @@ class Gardener
49
48
  # === Example
50
49
  # puts gardener.init_status.inspect # => [{:message=>"init ok", :success=>true, :pid=>4760}, {:message=>"init failed", :success=>false, :pid=>4761}]
51
50
  def init_status
52
- command, data = socket_client_perm_duplex(:init,@garden_rows.pids.size)
51
+ command, data = socket_duplex(:init,@garden_rows.pids.size)
53
52
  data.map! do |row|
54
53
  {:success => row[:success], :message => row[:message], :pid => row[:id]}
55
54
  end
@@ -63,7 +62,7 @@ class Gardener
63
62
  # id_seed_1 = gardener.seed("system 'ruby -v'")
64
63
 
65
64
  def seed(command)
66
- command, data = socket_client_perm_duplex(:seed,command)
65
+ command, data = socket_duplex(:seed,command)
67
66
  return data
68
67
  end
69
68
 
@@ -76,7 +75,7 @@ class Gardener
76
75
  # {:success=>true, :message=>["row pref changed to local"], :seed=>"pref local", :pid=>14913}]
77
76
  def seed_all(command)
78
77
  seed = [@garden_rows.pids.size, command]
79
- command, data = socket_client_perm_duplex(:seed_all, seed)
78
+ command, data = socket_duplex(:seed_all, seed)
80
79
  data.map! do |row|
81
80
  {:success => row[:success], :message => row[:message], :pid => row[:id]}
82
81
  end
@@ -95,7 +94,7 @@ class Gardener
95
94
  # puts "progress is now #{progress}" # => progress is now 0.75
96
95
 
97
96
  def growth(crop=:progress)
98
- command, data = socket_client_perm_duplex(:growth,crop)
97
+ command, data = socket_duplex(:growth,crop)
99
98
  return data
100
99
  end
101
100
 
@@ -114,7 +113,7 @@ class Gardener
114
113
  # seed1_result = gardener.harvest(id_seed_1)
115
114
 
116
115
  def harvest(crop)
117
- command, data = socket_client_perm_duplex(:harvest,crop)
116
+ command, data = socket_duplex(:harvest,crop)
118
117
  return data
119
118
  end
120
119
 
@@ -124,7 +123,7 @@ class Gardener
124
123
  # final_harvest = gardener.close
125
124
 
126
125
  def close
127
- command, data = socket_client_perm_duplex(:close,{:level => :garden, :pid => @garden_rows.pids})
126
+ command, data = socket_duplex(:close,{:level => :garden, :pid => @garden_rows.pids})
128
127
  return data
129
128
  end
130
129
 
data/lib/toolshed.rb CHANGED
@@ -10,142 +10,96 @@
10
10
  #
11
11
  # :title:Toolshed
12
12
 
13
+ # TODO:
14
+ # -dedicated server on garden for 'ready!' rows where rows go write their PID
15
+
13
16
  module Toolshed
17
+ require 'ftools'
14
18
  require 'socket'
15
- UDP_HOST = 'localhost'
16
- @@start_port = 50000
17
- @@sessions = []
18
-
19
- # The Toolshed.available_port method scans for a an available UDP port and returns its value.
20
- def Toolshed.available_port
21
- port = @@start_port + 1
22
- catch :scan_port do
23
- stat = `netstat`
24
- loop do
25
- throw :scan_port unless stat =~ /localhost\.#{port}/
26
- port += 1
27
- end
28
- end
29
- @@start_port = port
30
- return port
31
- end
32
-
33
- # The Toolshed.socket_client_perm method creates a client socket permanently connected to the main server socket. Returns the client socket object.
34
- def Toolshed.socket_client_perm
35
- socket = UDPSocket.new
36
- socket.connect(UDP_HOST,@@garden_port)
37
- return socket
38
- end
39
-
40
- # The Toolshed.socket_client_temp method creates a client socket available for changing connections to multiple socket servers. Returns the client socket object.
41
- def Toolshed.socket_client_temp
42
- UDPSocket.new
43
- end
44
-
45
- # The Toolshed.socket_server method creates a permanent main server socket. Returns the server socket object.
46
- def Toolshed.socket_server(port)
47
- socket_server = UDPSocket.new
48
- socket_server.bind(nil,port)
49
- return socket_server
50
- end
51
-
19
+ SOCKET_ROOT = '/tmp/abundance/'
20
+ Dir.mkdir(SOCKET_ROOT) unless File.exist?(SOCKET_ROOT)
21
+
52
22
  # The Toolshed::block_size= method sets the UDP block size for socket operations.
53
23
  def Toolshed::block_size=(block_size)
54
24
  @@block_size = block_size
55
25
  end
56
26
 
57
- # The Toolshed::block_size method gets and returns the UDP block size for socket operations.
58
- def Toolshed::block_size
59
- @@block_size
60
- end
27
+ # The +assign_sockets+ method assign a value client and server variables
61
28
 
62
- # The Toolshed::garden_port= sets the UDP socket port for the garden server.
63
- def Toolshed::garden_port=(garden_port)
64
- @@garden_port = garden_port
29
+ def set_my_socket_as_a(role,garden_pid=Process.pid)
30
+ case role
31
+ when :garden
32
+ set_my_socket
33
+ else
34
+ set_garden_path(garden_pid)
35
+ set_my_socket
36
+ end
65
37
  end
66
38
 
67
- # The Toolshed::garden_port gets the UDP socket port of the garden server.
68
- def Toolshed::garden_port
69
- @@garden_port
39
+ def my_socket_path
40
+ @my_socket_path
70
41
  end
71
42
 
72
- # The +socket_client_perm_duplex+ method is used as the main Row loop send/receive method and for all gardener's send/receive
73
- def socket_client_perm_duplex(command,data)
74
- block_splitter([command,data]) do |block|
75
- @socket_client_perm.send(block,0)
76
- end
77
- recv_block,address = block_filter { @socket_client_perm.recvfrom(@@block_size) }
78
- return Marshal.load(recv_block)
43
+ #
44
+
45
+ def socket_send(command,data,server_socket_path=@garden_path)
46
+ send_block(command,data,server_socket_path)
79
47
  end
80
48
 
81
- def socket_client_perm_send(command,data)
82
- block_splitter([command,data]) do |block|
83
- @socket_client_perm.send(block,0)
84
- end
49
+ def socket_duplex(command,data,server_socket_path=@garden_path)
50
+ send_block(command,data,server_socket_path)
51
+ Marshal.load(recv_whole_block)
85
52
  end
53
+
54
+ def socket_recv
55
+ Marshal.load(recv_whole_block)
56
+ end
57
+
58
+ private
86
59
 
87
- # The +socket_client_temp+ method is used by the Garden for connecting with the Row idle socket for quick messages.
88
- def socket_client_temp(command,data,port)
89
- @socket_client_temp.connect(UDP_HOST,port)
90
- block_splitter([command,data]) do |block|
91
- @socket_client_temp.send(block,0)
92
- end
60
+ def socket_path(pid)
61
+ File.catname(pid.to_s,SOCKET_ROOT)
93
62
  end
94
63
 
95
- # The +socket_server_recv+ method is used by the Garden permanent socket and by the Row idle socket to wait for incomming messages.
96
- def socket_server_recv
97
- block,address = block_filter { @socket_server.recvfrom(@@block_size) }
98
- clientport = address[1]; clientname = address[2]; clientaddr = address[3]
99
- command, data = Marshal.load(block)
100
- return command, data, clientport, clientname, clientaddr
64
+ def set_my_socket
65
+ @my_socket_path = socket_path(Process.pid)
66
+ File.delete(@my_socket_path) if File.exist?(@my_socket_path)
67
+ @my_socket = UNIXServer.open(@my_socket_path)
101
68
  end
102
69
 
103
- # The +socket_server_send+ method is used by the Garden to answer back to socket clients.
104
- def socket_server_send(command,data,clientaddr,clientport)
105
- block_splitter([command,data]) do |block|
106
- @socket_server.send(block, 0, clientaddr, clientport)
107
- end
70
+ def set_garden_path(garden_pid)
71
+ @garden_path = socket_path(garden_pid)
108
72
  end
109
73
 
110
- private
111
- # The +block_splitter+ method is used internally by the Toolshed method to split message into acceptable UDP block size. Its operating as a block method, sending a message chunk on each iteration.
112
- def block_splitter(data)
113
- data_string = Marshal.dump(data)
114
- if data_string.size >= @@block_size
115
- parts = data_string.size / (@@block_size - @@block_size/32) + 1
116
- yield Marshal.dump([:block_head,Process.pid,parts])
117
- parts.times do |num|
118
- part = [data_string[0,@@block_size - @@block_size/32]]; data_string[0,@@block_size - @@block_size/32] = ''
119
- yield Marshal.dump([:block_part,Process.pid,num, part])
74
+ def recv_whole_block
75
+ begin
76
+ client = @my_socket.accept; block = []
77
+ catch :whole_block do
78
+ loop do
79
+ packet = client.recvfrom(@@block_size)[0]
80
+ if packet == ''
81
+ throw :whole_block
82
+ else
83
+ block << packet
84
+ end
85
+ end
120
86
  end
121
- else
122
- yield data_string
87
+ return block.join
88
+ rescue Errno::EADDRINUSE
89
+ retry
123
90
  end
124
91
  end
125
92
 
126
- # The +block_filter+ method is used internally by the Toolshed method to filter splitted messages blocks, buffering them until the full message can be reconstructed.
127
- def block_filter
128
- loop do
129
- block,address = yield
130
- block_array = Marshal.load(block)
131
- if block_array[0] == :block_head
132
- @@sessions[block_array[1]] = {} if @@sessions[block_array[1]].nil?
133
- @@sessions[block_array[1]][:size] = block_array[2]
134
- @@sessions[block_array[1]][:address] = address
135
- elsif block_array[0] == :block_part
136
- @@sessions[block_array[1]] = {} if @@sessions[block_array[1]].nil?
137
- @@sessions[block_array[1]][:data] = [] if @@sessions[block_array[1]][:data].nil?
138
- @@sessions[block_array[1]][:data][block_array[2]] = block_array[3]
139
- else
140
- return block,address
141
- end
142
- if ! @@sessions[block_array[1]].nil? && ! @@sessions[block_array[1]][:data].nil? && @@sessions[block_array[1]][:data].size == @@sessions[block_array[1]][:size]
143
- block = @@sessions[block_array[1]][:data].join
144
- address = @@sessions[block_array[1]][:address]
145
- @@sessions[block_array[1]] = nil
146
- return block,address
147
- end
93
+ def send_block(command,data,server_socket_path)
94
+ begin
95
+ client = UNIXSocket.open(server_socket_path)
96
+ client.send(Marshal.dump([command,data,@my_socket_path]),0)
97
+ client.close
98
+ rescue Errno::EADDRINUSE
99
+ retry
100
+ rescue Errno::ECONNREFUSED
101
+ retry
148
102
  end
149
103
  end
150
-
104
+
151
105
  end
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.1.2
4
+ version: 1.2.0
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-10 00:00:00 -05:00
12
+ date: 2009-01-11 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies: []
15
15