Abundance 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,94 @@
1
+ # This class provides a mean to parallelize the execution of your program processes.
2
+ #
3
+ # Its caracteristics are:
4
+ # * concurent
5
+ # * non-blocking
6
+ # * simple
7
+ # * pure ruby
8
+ # * no dependency installation
9
+ #
10
+ # It:
11
+ # * scales to multi core
12
+ # * is intended for batch processing or other parallel ready operations
13
+ # * can boost you program's performance
14
+ #
15
+ # And not:
16
+ # * a replacement for Thread.new invocations
17
+ # * a replacement for Thread friendly programming languages like Erlang
18
+ #
19
+ #
20
+ # Based on Gardener,Garden,Seed natural design patern
21
+ #
22
+ # While there should be no use for this kind of class in most programs, there are some occasions where processes
23
+ # cannot live inside serialized execution without blocking. The built in threading model can save your execution in many occasions, but in many case green threading is not enough, or simply just won't work.
24
+ # For a nice explanation on the subject of ruby green threading, you can refer to: http://www.igvita.com/2008/11/13/concurrency-is-a-myth-in-ruby/
25
+ #
26
+ # Abundance is by no mean intended to equal or compete with the tools mentionned in the article, its rather a different
27
+ # approach on the same problem. I hope it will inspire some of you to hack out something that works even better,
28
+ # and hopefully, eventually this tool will become obsolete because Ruby will get concurency built in.
29
+ #
30
+ # So, the approach here is really simple, you require abundance in your program.
31
+ # Then ask the Abundance.gardener class method to build you a garden built with a garden patch block you provide as part of the invocation.
32
+ # This garden patch block includes an initialization block, which may be empty,
33
+ # and the invocation of the Abundance.grow class method, the perpetual seed ready patch garden.
34
+ # It becomes the threaded looping object, growing concurently on garden patch row forks.
35
+ #
36
+ # The gardener objected is then available to seeds and harvest the multiple garden patch row forks,
37
+ # allowing you to cultivate parallel garden rows where your seeds sprout till fruitful harvest time comes.
38
+ #
39
+ # Author:: lp (mailto:lp@spiralix.org)
40
+ # Copyright:: 2008 Louis-Philippe Perron - Released under the terms of the MIT license
41
+ #
42
+ # :title:Abundance
43
+
44
+ class Abundance
45
+ require 'garden'
46
+ require 'gardener'
47
+ require 'seed'
48
+
49
+ # The +gardener+ class method initializes a gardener instance
50
+ # with its garden supplied as a block. The invocation block must include
51
+ # the +grow+ class method and a preceeding optional initialisation section.
52
+ # === Parameters
53
+ # * :seed_size = allowed seed size in bytes
54
+ # * :rows = garden rows number, the number of concurent threads
55
+ # * :init_timeout = allow to pause execution to allow for larger gardens to initialize
56
+ # === Example
57
+ # gardener = Abundance.gardener( :block_size => 8192, :rows => 2, :init_timeout => 2) do
58
+ #
59
+ # processor = SpecialProcess.new
60
+ #
61
+ # Abundance.grow do |seed|
62
+ # command = seed.sprout
63
+ # results = processor.parse(command)
64
+ # seed.crop( true, results)
65
+ # end
66
+ # end
67
+ #
68
+ # id1 = gardener.seed('command1')
69
+ # id2 = gardener.seed('command2')
70
+ #
71
+ # result1 = gardener.harvest(id1)
72
+ # result2 = gardener.harvest(id2)
73
+ #
74
+ # # with many more seeds over here
75
+ #
76
+ # gardener.close
77
+
78
+ def Abundance.gardener(options={:seed_size => 8192, :rows => 2, :init_timeout => 2},&gardener_block)
79
+ return Gardener.new(options,gardener_block)
80
+ end
81
+
82
+ # The +grow+ class method needs to be used inside the gardener invocation.
83
+ # A seed instance is given each time, acting as getter/setter for your queued seed commands
84
+
85
+ def Abundance.grow(&grow_block)
86
+ loop do
87
+ unless $seed.nil? || $seed.include?(:message)
88
+ grow_block.call(Seed.new)
89
+ end
90
+ Thread.stop
91
+ end
92
+ end
93
+
94
+ end
@@ -0,0 +1,206 @@
1
+ # These classes provides the garden part of the Gardener,Garden,Seed natural design patern
2
+ #
3
+ # The Garden is where the thread concurency is implemented,
4
+ # offering itself as a thread queue manager,
5
+ # dispatching seeds from the Gardener to its Rows child class and back again.
6
+ # Since Ruby doesn't implement Native Threads, and only Native Threads scales to multi-core execution,
7
+ # the way to implement concurent execution is through splitting the task at hand between multiple single threaded parallel executions.
8
+ # The Rows system does exactly that, using the Ruby fork function, then connecting the isolated running
9
+ # processes to the Garden, through a simple socket system provided by the Toolshed Module.
10
+ #
11
+ # Author:: lp (mailto:lp@spiralix.org)
12
+ # Copyright:: 2008 Louis-Philippe Perron - Released under the terms of the MIT license
13
+ #
14
+ # :title:Garden
15
+
16
+ class Garden
17
+ require 'toolshed'
18
+ include Toolshed
19
+
20
+ attr_reader :pid
21
+
22
+ # The +new+ class method initializes the Garden.
23
+ # As part of the Abundance lib, Garden is not initialized directly,
24
+ # but rather as a side effect of the Gardener's initialization.
25
+ # Its instance resides in the @garden Gardener's instance variable.
26
+ # Its real muscles are inaccessibles from instance method intervention,
27
+ # because of its nature as a forked Ruby process.
28
+ # === Example
29
+ # garden = Garden.new
30
+
31
+ def initialize
32
+ @pid = fork do
33
+ @quit = false
34
+ @harvest = []
35
+ @rows_port = []
36
+ @seeds = []; @sprouts = []; @crops = []; @id = 0
37
+ @socket_server = Toolshed.socket_server(Toolshed::garden_port)
38
+ @socket_client_temp = Toolshed.socket_client_temp
39
+ loop do
40
+ catch :fill_rows do
41
+ loop do
42
+ if ! @seeds.empty? && ! @rows_port.empty?
43
+ seed = @seeds.shift
44
+ @sprouts[seed[:id]] = seed
45
+ row_port = @rows_port.shift
46
+ socket_client_temp(:sprout,seed,row_port)
47
+ elsif @quit && ! @rows_port.empty?
48
+ seed = nil
49
+ row_port = @rows_port.shift
50
+ socket_client_temp(:quit,seed,row_port)
51
+ else
52
+ throw :fill_rows
53
+ end
54
+ end
55
+ end
56
+ command, data, clientport, clientname, clientaddr = socket_server_recv
57
+ case command
58
+ when :seed
59
+ @id += 1; @seeds << {:id => @id , :seed => data}
60
+ socket_server_send(command,@id,clientaddr,clientport)
61
+ when :row
62
+ if @quit
63
+ command = :quit
64
+ seed = nil
65
+ elsif @seeds.empty?
66
+ seed = nil
67
+ @rows_port << data
68
+ else
69
+ seed = @seeds.shift
70
+ @sprouts[seed[:id]] = seed
71
+ end
72
+ socket_server_send(command,seed,clientaddr,clientport)
73
+ when :crop
74
+ @sprouts[data[:id]] = nil
75
+ @crops[data[:id]] = data; socket_server_send(command,true,clientaddr,clientport)
76
+ socket_server_send(command,data, @harvest[data[:id]][:clientaddr], @harvest[data[:id]][:clientport]) if @harvest[data[:id]]
77
+ when :growth
78
+ case data
79
+ when :progress
80
+ progress = sprintf( "%.2f", @crops.size.to_f / (@crops.size + @sprouts.compact.size + @seeds.size))
81
+ socket_server_send(command,progress,clientaddr,clientport)
82
+ when :seed
83
+ socket_server_send(command,@seeds.size,clientaddr,clientport)
84
+ when :sprout
85
+ socket_server_send(command,@sprouts.compact.size,clientaddr,clientport)
86
+ when :crop
87
+ socket_server_send(command,@crops.size,clientaddr,clientport)
88
+ else
89
+ socket_server_send(command,false,clientaddr,clientport)
90
+ end
91
+ when :harvest
92
+ case data
93
+ when :all
94
+ socket_server_send(command,{:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops},clientaddr,clientport)
95
+ when :seed
96
+ socket_server_send(command,@seeds,clientaddr,clientport)
97
+ when :sprout
98
+ socket_server_send(command,@sprouts.compact,clientaddr,clientport)
99
+ when :crop
100
+ socket_server_send(command,@crops,clientaddr,clientport)
101
+ else
102
+ if data.is_a? Integer
103
+ if @crops[data]
104
+ socket_server_send(command,@crops[data],clientaddr,clientport)
105
+ else
106
+ @harvest[data] = {:clientaddr => clientaddr, :clientport => clientport}
107
+ end
108
+ else
109
+ socket_server_send(command,false,clientaddr,clientport)
110
+ end
111
+ end
112
+ when :close
113
+ if data[:level] == :garden
114
+ @seeds_pid = data[:pid]
115
+ @quit = true
116
+ @mem_addr = clientaddr; @mem_port = clientport
117
+ else
118
+ @seeds_pid.delete(data[:pid].to_i)
119
+ if @seeds_pid.empty?
120
+ socket_server_send(:close,{:seeds => @seeds, :sprouts => @sprouts.compact, :crops => @crops}, @mem_addr, @mem_port)
121
+ exit
122
+ end
123
+ end
124
+ else
125
+ socket_server_send(command,false,clientaddr,clientport)
126
+ end
127
+ end
128
+ end
129
+ return pid
130
+ end
131
+
132
+ # The +rows+ method for the Garden instance allow instantiation of its child Rows.
133
+ # As part of the Abundance lib, Garden.rows is not invoked directly,
134
+ # but rather as a side effect of the Gardener's initialization.
135
+ # Its in reality an indirect initializer for the Rows class.
136
+ # === Parameter
137
+ # * _rows_ = garden rows number, the number of concurent threads
138
+ # * _init_timeout_ = allow to pause execution to allow for larger garden rows to initialize
139
+ # === Example
140
+ # rows = garden.rows(4,2) { grow_block }
141
+ #
142
+
143
+ def rows(rows,init_timeout,grow_block)
144
+ Rows.new(rows,init_timeout,grow_block)
145
+ end
146
+
147
+ # :title:Rows
148
+
149
+ class Rows
150
+ include Toolshed
151
+ attr_reader :pids
152
+
153
+ # The +new+ class method initializes the Rows.
154
+ # As part of the Abundance lib, Rows is not initialized directly,
155
+ # but rather as a side effect of the Gardener's initialization,
156
+ # through the +rows+ Garden instance method.
157
+ # Its instance resides in the @garden_rows Gardener's instance variable.
158
+ # Its real muscles are inaccessibles from instance method intervention,
159
+ # because of its nature as a forked Ruby process.
160
+ # === Parameter
161
+ # * _rows_ = garden rows number, the number of concurent threads
162
+ # * _init_timeout_ = allow to pause execution to allow for larger garden rows to initialize
163
+ # === Example
164
+ # rows = Rows.new(4,2) { grow_block }
165
+
166
+ def initialize(rows,init_timeout,gardener_block)
167
+ @pids = []
168
+ rows.times do
169
+ row_port = Toolshed.available_port
170
+ @pids << fork do
171
+ @socket_server = Toolshed.socket_server(row_port)
172
+ t1 = Thread.new do
173
+ gardener_block.call
174
+ end
175
+
176
+ t2 = Thread.new do
177
+ @socket_client_perm = Toolshed.socket_client_perm
178
+ loop do
179
+ if $seed.nil?
180
+ command, data = socket_client_perm_duplex(:row,row_port)
181
+ if command == :quit
182
+ pid = Process.pid
183
+ socket_client_perm_send(:close,{:level => :seed, :pid => pid})
184
+ exit
185
+ end
186
+ $seed = data
187
+ if $seed.nil?
188
+ command, data, clientport, clientname, clientaddr = socket_server_recv
189
+ $seed = data
190
+ end
191
+ elsif $seed.include?(:success)
192
+ command, data = socket_client_perm_duplex(:crop,$seed)
193
+ $seed = nil
194
+ else
195
+ t1.run
196
+ end
197
+
198
+ end
199
+ end
200
+ t2.join
201
+ end
202
+ end
203
+ sleep init_timeout
204
+ end
205
+ end
206
+ end
@@ -0,0 +1,99 @@
1
+ # This class provides the gardener part of the Gardener,Garden,Seed natural design patern
2
+ #
3
+ # The Gardener act as the client class for accessing and assessing the Garden ressources.
4
+ # Its initialization occurs through the Abundance.gardener class method.
5
+ # Its instance methods are fourthfold, following the 4 states of the garden.
6
+ # Like the 4 seasons northern hemisphere gardening cycles:
7
+ # * seed = the setting of your command cycle
8
+ # * growth = the evolution of your command growing period
9
+ # * harvest = the getting of your command results
10
+ # * close = the closing and dying cycle
11
+ #
12
+ # Author:: lp (mailto:lp@spiralix.org)
13
+ # Copyright:: 2008 Louis-Philippe Perron - Released under the terms of the MIT license
14
+ #
15
+ # :title:Gardener
16
+
17
+ class Gardener
18
+ require 'toolshed'
19
+ include Toolshed
20
+
21
+ # The +new+ class method initializes the class.
22
+ # As part of the Abundance lib, Gardener is not initialized directly,
23
+ # but rather through +Abundance.gardener+.
24
+ # === Parameters
25
+ # * :seed_size = allowed seed size in bytes
26
+ # * :rows = garden rows number, the number of concurent threads
27
+ # * :init_timeout = allow to pause execution to allow for larger gardens to initialize
28
+ # === Example
29
+ # gardener = Gardener.new({:seed_size => 1024, :rows => 6, :init_timeout => 1}) do
30
+ # Abundance.grow do |seed|
31
+ # seed.crop(`#{seed.sprout}`)
32
+ # end
33
+ # end
34
+ #
35
+
36
+ def initialize(options,gardener_block)
37
+ Toolshed::block_size = options[:seed_size]
38
+ Toolshed::garden_port = Toolshed.available_port
39
+
40
+ @garden = Garden.new
41
+ @garden_rows = @garden.rows(options[:rows], options[:init_timeout], gardener_block)
42
+
43
+ @socket_client_perm = Toolshed.socket_client_perm
44
+ end
45
+
46
+ # The +seed+ method for the Gardener instance allow to sow a command in the Gardener's Garden.
47
+ # === Parameter
48
+ # * _command_ = a ruby expression or object
49
+ # === Example
50
+ # id_seed_1 = gardener.seed('ruby -v')
51
+
52
+ def seed(command)
53
+ command, data = socket_client_perm_duplex(:seed,command)
54
+ return data
55
+ end
56
+
57
+ # The +growth+ method for the Gardener instance allow to get report of the growing process
58
+ # === Parameter
59
+ # The parameter given as a symbol specifies the level of growth report you wish to get:
60
+ # * :progress = return actual progress status, scaled between 0.00 and 1.00
61
+ # * :seed = return total seeds waiting to be processed
62
+ # * :sprout = return total seeds actually in process
63
+ # * :crop = return total seeds for which process has completed
64
+ # === Example
65
+ # progress = gardener.growth(:progress)
66
+ # puts "progress is now #{progress}" # => progress is now 0.75
67
+
68
+ def growth(crop=:progress)
69
+ command, data = socket_client_perm_duplex(:growth,crop)
70
+ return data
71
+ end
72
+
73
+ # The +harvest+ method for the Gardener instance allow to get arrays of results for each queue level
74
+ # === Parameter
75
+ # The parameter given as a symbol specifies the level of queue results you wish to get:
76
+ # * _seedID_ = return the result for a specific seed, if seed hasn't processed it wait until completed
77
+ # * :crop = return an array of seed for which process has completed
78
+ # * :sprout = return an array of seed actually processing
79
+ # * :seed = return an array of seed waiting to be processed
80
+ # * :all = return a hash of respective arrays for crops, sprouts and seeds
81
+ # === Example
82
+ # puts "result is: #{gardener.harvest(id_seed_1)} # => result is: ruby 1.8.6 (2007-09-24 patchlevel 111) [universal-darwin9.0]
83
+
84
+ def harvest(crop)
85
+ command, data = socket_client_perm_duplex(:harvest,crop)
86
+ return data
87
+ end
88
+
89
+ # The +close+ method for the Gardener instance allow to safely close the Garden and its Rows.
90
+ # It return a hash of respective arrays for crops, sprouts and seeds at the moment of closing.
91
+ # === Example
92
+ # final_harvest = gardener.close
93
+
94
+ def close
95
+ command, data = socket_client_perm_duplex(:close,{:level => :garden, :pid => @garden_rows.pids})
96
+ return data
97
+ end
98
+
99
+ end
@@ -0,0 +1,42 @@
1
+ # This class provides the seed part of the Gardener,Garden,Seed natural design patern
2
+ #
3
+ # In nature, seed is usually small, and so is this class.
4
+ # No attributes/variables of itself, its only a kind of localized getter/setter class for
5
+ # the global $seed variable. Every garden row assess one fork-localized $seed variable, and
6
+ # you get access to it from a +seed+ instance passed to every Abundance.grow iteration.
7
+ #
8
+ # Author:: lp (mailto:lp@spiralix.org)
9
+ # Copyright:: 2008 Louis-Philippe Perron - Released under the terms of the MIT license
10
+ #
11
+ # :title:Seed
12
+
13
+ class Seed
14
+
15
+ # The +new+ class method initializes the class.
16
+ # You don't have to initialize it inside of Abundance,
17
+ # as it gets initialized automatically inside the Abundance.grow method
18
+
19
+ # The +sprout+ method for the Seed instance allow to get the passed command
20
+ # from the inside the Abundance.grow block.
21
+ # === Example
22
+ # system "#{seed.sprout}\n"
23
+ def sprout
24
+ return $seed[:seed]
25
+ end
26
+
27
+ # The +crop+ method for the Seed instance allow to set a success status and
28
+ # a return message from the inside the Abundance.grow block.
29
+ # === Parameter
30
+ # * _success_ = success of the iteration, may be true or false
31
+ # * _message_ = a ruby expression or object
32
+ # === Example
33
+ # if success
34
+ # seed.crop(true,results)
35
+ # else
36
+ # seed.crop(false,results)
37
+ # end
38
+ def crop(success,message)
39
+ $seed[:success] = success; $seed[:message] = message
40
+ end
41
+
42
+ end
@@ -0,0 +1,121 @@
1
+ require 'pty'
2
+ require 'expect'
3
+ require 'abundance'
4
+
5
+ # puts "Init pid #{Process.pid}"
6
+ #
7
+ # g = Abundance.gardener(:seed_size => 8192, :rows => 1, :init_timeout => 1) do
8
+ # puts "Garden init done, pid: #{Process.pid}"
9
+ # puts "@@ yield just before growing..."
10
+ # Abundance.grow do |seed|
11
+ # puts "@@ yield #{Time.now}: got in here"
12
+ # puts "@@ yield job: #{seed.sprout}"
13
+ # seed.crop(true, "Bravo!!gadigooo!!")
14
+ # end
15
+ # puts "Garden seeded"
16
+ # end
17
+ #
18
+ # g.seed("jobidoo")
19
+ # puts "First chore sent"
20
+ # g.seed("jobidaa")
21
+ # puts "second chore sent"
22
+ # g.seed("jobidob")
23
+ # puts "!!!!!!!!!!!!!!!!!!!!!!! growth: #{g.growth}"
24
+ # g.seed("jobidoc")
25
+ # puts "!!!!!!!!!!!!!!!!!!!!!!! growth: #{g.growth}"
26
+ # id = g.seed("jobidod")
27
+ # puts "!!!!!!!!!!!!!!!!!!!!!!! growth: #{g.growth}"
28
+ # puts "!!!!!!!!!!!!!!!!!!!!!!!!!! waiting for harvest: #{id.class.to_s}"
29
+ # har = g.harvest(id)
30
+ # puts "!!!!!!!!!!!!!!!!!!!!!!!!!! famous harvest: #{har.inspect}"
31
+ # g.seed("jobidoe")
32
+ # puts "!!!!!!!!!!!!!!!!!!!!!!! growth: #{g.growth}"
33
+ # g.seed("jobidof")
34
+ # puts "!!!!!!!!!!!!!!!!!!!!!!! growth: #{g.growth}"
35
+ # g.seed("jobidog")
36
+ # puts "!!!!!!!!!!!!!!!!!!!!!!! growth: #{g.growth}"
37
+ # g.seed("jobidoh")
38
+ # puts "!!!!!!!!!!!!!!!!!!!!!!! growth: #{g.growth}"
39
+ # g.seed("jobidoi")
40
+ # puts "!!! some seeds: #{g.harvest(:seed).inspect}"
41
+ # puts "!!! some sprouts: #{g.harvest(:sprout).inspect}"
42
+ # puts "!!! some crops: #{g.harvest(:crop).inspect}"
43
+ # puts "!!!!!!!!!!!!!!!!!!!!!!! growth: #{g.growth}"
44
+ # g.seed("jobidoj")
45
+ # puts "!!!!!!!!!!!!!!!!!!!!!!! growth: #{g.growth}"
46
+ # g.seed("jobidok")
47
+ # puts "!!!!!!!!!!!!!!!!!!!!!!! growth: #{g.growth}"
48
+ # g.seed("jobidol")
49
+ # puts "!!!!!!!!!!!!!!!!!!!!!!! growth: #{g.growth}"
50
+ # g.seed("jobidom")
51
+ # puts "!!!!!!!!!!!!!!!!!!!!!!! growth: #{g.growth}"
52
+ # g.seed("jobidon")
53
+ # g.seed("jobidop")
54
+ # g.seed("jobidoq")
55
+ # g.seed("jobidor")
56
+ # g.seed("jobidos")
57
+ # g.seed("jobidot")
58
+ # g.seed("jobidou")
59
+ # g.seed("jobidov")
60
+ # g.seed("jobidow")
61
+ # g.seed("jobidox")
62
+ # g.seed("jobidoy")
63
+ # g.seed("jobidoz")
64
+ # puts "!!!!!!!!!!!!!!!!!!!!!!! growth: #{g.growth}"
65
+ # sleep 30
66
+ # puts "!!! some seeds: #{g.harvest(:seed).inspect}"
67
+ # puts "!!! some sprouts: #{g.harvest(:sprout).inspect}"
68
+ # puts "!!! some crops: #{g.harvest(:crop).inspect}"
69
+ # sleep 5
70
+ # puts "!!!!!!!!!!!!!!!!!!!!!!! growth: #{g.growth}"
71
+ # fin = g.close
72
+ # puts "on close #{fin.inspect}"
73
+
74
+ puts "Init pid #{Process.pid}"
75
+
76
+ g = Abundance.gardener(:seed_size => 8192, :rows => 1, :init_timeout => 3) do
77
+ puts "@@ yield just before growing..."
78
+ PTY.spawn('smbclient //spiralgemini/geminishare goLEELAubu -U leelasheel') do |r,w,pid|
79
+ w.sync = true
80
+ $expect_verbose = false
81
+
82
+ r.expect(/.*smb: \\>.*/) do |text|
83
+ puts "!!! starter: #{text}"
84
+ end
85
+ Abundance.grow do |seed|
86
+ neew = seed.sprout
87
+ puts "??? will go for: #{neew}"
88
+ w.print "#{seed.sprout}\n"
89
+
90
+ r.expect(/.*smb: \\>/) do |text|
91
+ puts "!!! got #{text}"
92
+ unless text
93
+ r.expect(/.*smb: \\>/) do |text|
94
+ puts "!!!2 got #{text}"
95
+ seed.crop(true, text)
96
+ end
97
+ else
98
+ seed.crop(true, text)
99
+ end
100
+
101
+ end
102
+ end
103
+
104
+ end
105
+ end
106
+
107
+ puts "Garden seeded"
108
+
109
+ g.seed("ls")
110
+ puts "First chore sent"
111
+ g.seed("pwd")
112
+ puts "second chore sent"
113
+ g.seed("volume")
114
+ g.seed("help")
115
+ g.seed("du")
116
+ g.seed("put inside.rb")
117
+ sleep 20
118
+ # r = g.harvest
119
+ # puts r.inspect
120
+ fin = g.close
121
+ puts fin.inspect
@@ -0,0 +1,95 @@
1
+ # This module provides a toolkit of helper methods to Abundance
2
+ #
3
+ # It uses the Socket Ruby standard library to provide a communication mechanism
4
+ # between Abundance concurent processes. It's used as both a namespace for init variables of
5
+ # the different Abundance Classes, using Toolshed's Class Method like qualified names,
6
+ # and as mixins methods which access directly the instance variables of the client classes .
7
+ #
8
+ # Author:: lp (mailto:lp@spiralix.org)
9
+ # Copyright:: 2008 Louis-Philippe Perron - Released under the terms of the MIT license
10
+ #
11
+ # :title:Toolshed
12
+
13
+ module Toolshed
14
+ require 'socket'
15
+ UDP_HOST = 'localhost'
16
+ @@start_port = 50000
17
+
18
+ def Toolshed.available_port
19
+ port = @@start_port + 1
20
+ catch :scan_port do
21
+ loop do
22
+ begin
23
+ socket = UDPSocket.new
24
+ socket.connect(UDP_HOST,port)
25
+ socket.send('',0)
26
+ response,address = socket.recvfrom(1024)
27
+ rescue Errno::ECONNREFUSED
28
+ throw :scan_port
29
+ end
30
+ port += 1
31
+ end
32
+ end
33
+ @@start_port = port
34
+ return port
35
+ end
36
+
37
+ def Toolshed.socket_client_perm
38
+ socket = UDPSocket.new
39
+ socket.connect(UDP_HOST,@@garden_port)
40
+ return socket
41
+ end
42
+
43
+ def Toolshed.socket_client_temp
44
+ UDPSocket.new
45
+ end
46
+
47
+ def Toolshed.socket_server(port)
48
+ socket_server = UDPSocket.new
49
+ socket_server.bind(nil,port)
50
+ return socket_server
51
+ end
52
+
53
+ def Toolshed::block_size=(block_size)
54
+ @@block_size = block_size
55
+ end
56
+
57
+ def Toolshed::block_size
58
+ @@block_size
59
+ end
60
+
61
+ def Toolshed::garden_port=(garden_port)
62
+ @@garden_port = garden_port
63
+ end
64
+
65
+ def Toolshed::garden_port
66
+ @@garden_port
67
+ end
68
+
69
+ def socket_client_perm_duplex(command,data)
70
+ @socket_client_perm.send(Marshal.dump([command,data]),0)
71
+ recv_block,address = @socket_client_perm.recvfrom(@@block_size)
72
+ return Marshal.load(recv_block)
73
+ end
74
+
75
+ def socket_client_perm_send(command,data)
76
+ @socket_client_perm.send(Marshal.dump([command,data]),0)
77
+ end
78
+
79
+ def socket_client_temp(command,data,port)
80
+ @socket_client_temp.connect(UDP_HOST,port)
81
+ @socket_client_temp.send(Marshal.dump([command,data]),0)
82
+ end
83
+
84
+ def socket_server_recv
85
+ block,address = @socket_server.recvfrom(@@block_size)
86
+ clientport = address[1]; clientname = address[2]; clientaddr = address[3]
87
+ command, data = Marshal.load(block)
88
+ return command, data, clientport, clientname, clientaddr
89
+ end
90
+
91
+ def socket_server_send(command,data,clientaddr,clientport)
92
+ @socket_server.send(Marshal.dump([command,data]), 0, clientaddr, clientport)
93
+ end
94
+
95
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: Abundance
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Louis-Philippe Perron
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-12-03 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: lp@spiralix.org
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/abundance.rb
26
+ - lib/garden.rb
27
+ - lib/gardener.rb
28
+ - lib/seed.rb
29
+ - lib/test.rb
30
+ - lib/toolshed.rb
31
+ has_rdoc: true
32
+ homepage: http://abundance.rubyforge.org/
33
+ post_install_message:
34
+ rdoc_options: []
35
+
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: "0"
43
+ version:
44
+ required_rubygems_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: "0"
49
+ version:
50
+ requirements: []
51
+
52
+ rubyforge_project: Abundance
53
+ rubygems_version: 1.2.0
54
+ signing_key:
55
+ specification_version: 2
56
+ summary: Ruby Parallel Processing, Concurent Native Threads
57
+ test_files: []
58
+