brb 0.2.0

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.
@@ -0,0 +1,7 @@
1
+ 0.2.0 (Apr 16, 2010)
2
+
3
+ * Releasing gem and wiki
4
+
5
+ 0.1.0 (Feb 01, 2009)
6
+
7
+ * Initial release
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Guillaume Luccisano - g-mai|: guillaume.luccisano
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,49 @@
1
+ = BrB - Easy and Fast distributed ruby
2
+
3
+ BrB is a simple and extremely fast interface for doing simple distributed ruby.
4
+ The main power of the architecture is provided by EventMachine (Fast and reliable IO event library).
5
+
6
+ BrB was build in order to achieve these 4 main goals :
7
+ * Simple and fast message passing between distant ruby process.
8
+ * Message passing with handling of return value when needed.
9
+ * Being extremely fast in order to handle more than a few thousand messages per seconds.
10
+ * Being completely transparent for developer.
11
+
12
+ The principle is simple and inspired from Drb (Original distributed ruby library) :
13
+ A process want to expose an object on the network, and want other ruby processes calling directly method on it.
14
+ BrB handle all that part, it's fully transparent in the ruby code.
15
+
16
+ BrB only support message passing with Marshable dumpable object : String, symbol, Array, hash, Number, Object etc...
17
+ That mean you can not send file descriptor, Thread or another funky things like that :)
18
+
19
+ == Main Functionalities
20
+
21
+ * Unlimited objects exposed
22
+ * Processes can expose object and be client to exposed object too at the same time
23
+ * Do not wait for return by default : just do simple message passing
24
+ * Wait for return if needed by simply adding <em>_block</em> at the end of the function name
25
+ * Transmission of Exception when blocking call
26
+ * Thread safe if used correctly with Event Machine
27
+
28
+ == How it works
29
+
30
+ First of all, a process declare himself as a sever and expose any object on a given address and port.
31
+ Then, any number of distant processes can create a <em>Tunnel</em> with that server and can expose an object in exchange too.
32
+ After connection are ready, just call method on the tunnel. It will just act like normal method calling on the exposed object !
33
+
34
+ == What BrB is usable for ?
35
+
36
+ * Doing Simple message passing between ruby process.
37
+ * Connecting hundred of ruby process transparently.
38
+ * Building a real-time scalable (game) server
39
+ * Taking important load on a server easily just by distributing the load on multiple BrB instance.
40
+ * Taking advantage of multi-core and multi-threaded systems.
41
+
42
+ == TODO
43
+ * Better README and Wiki
44
+ * Writing more examples
45
+ * Publish Benchmarks VS drb
46
+ * Improve logging mechanism
47
+ * Clean up
48
+
49
+ Copyright (c) 2009-2010 Guillaume Luccisano - g-mai|: guillaume.luccisano, released under the MIT license
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'spec/rake/spectask'
4
+
5
+ spec_files = Rake::FileList["spec/**/*_spec.rb"]
6
+
7
+ desc "Run specs for current Rails version"
8
+ Spec::Rake::SpecTask.new do |t|
9
+ t.spec_files = spec_files
10
+ t.spec_opts = ["-c"]
11
+ end
12
+
13
+ task :default => :spec
14
+
15
+ desc "Run simple core"
16
+ task :simple_core_example do
17
+ require 'examples/simple_core'
18
+ end
19
+
20
+ desc "Run simple client (call simple_core_before)"
21
+ task :simple_client_example do
22
+ require 'examples/simple_client'
23
+ end
@@ -0,0 +1,37 @@
1
+ require 'lib/brb'
2
+
3
+ port = 5555
4
+ host = 'localhost'
5
+
6
+ EM::run do
7
+ EM::set_quantum(20)
8
+ # Connecting to the core server, retrieving its interface object : core
9
+ # We do not want to expose an object, so the first parameter is nil
10
+ core = BrB::Tunnel.create(nil, "brb://#{host}:#{port}", :silent => false)
11
+
12
+ # Create thread here, as you can not block the EventMachine::run block
13
+ Thread.new do
14
+
15
+ # Calling 10 times an non blocking method on the distant core server
16
+ 10.times do
17
+ core.simple_api_method # Do not wait for response
18
+ end
19
+
20
+ # Calling 10 times again long treatment time distant methods
21
+ 10.times do
22
+ core.simple_long_api_method # Do not wait for response
23
+ end
24
+
25
+ # Calling a blocking method with _block on the distant core server :
26
+ puts " >> Calling 1s call, and wait for response..."
27
+ r = core.simple_api_method_block
28
+ puts " > Api response : #{r}"
29
+
30
+ puts " >> Calling long call, and wait for response..."
31
+ r = core.simple_long_api_method_block
32
+ puts " > Api long response : #{r}"
33
+
34
+ # Our job is over, close
35
+ EM.stop
36
+ end
37
+ end
@@ -0,0 +1,31 @@
1
+ require 'lib/brb'
2
+
3
+ class ExposedCoreObject
4
+
5
+ def simple_api_method
6
+ puts "#{Thread.current} > In simple api method, now sleeping"
7
+ sleep 1
8
+ puts "#{Thread.current} > Done sleeping in simple api method, return"
9
+ return 'OK'
10
+ end
11
+
12
+ def simple_long_api_method
13
+ puts "#{Thread.current} > In simple long api method, now sleeping"
14
+ sleep 10
15
+ puts "#{Thread.current} > Done sleeping in long api method, return"
16
+ return 'OK LONG'
17
+ end
18
+
19
+ end
20
+
21
+ Thread.abort_on_exception = true
22
+
23
+ port = 5555
24
+ host = 'localhost'
25
+
26
+ EM::run do
27
+ EM::set_quantum(20)
28
+
29
+ puts " > Starting the core on brb://#{host}:#{port}"
30
+ BrB::Service.instance.start_service(:object => ExposedCoreObject.new, :silent => false, :host => host, :port => port)
31
+ end
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ # encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), 'lib', 'brb.rb')
@@ -0,0 +1,48 @@
1
+ require File.join(File.dirname(__FILE__), 'brb', 'exception.rb')
2
+ require File.join(File.dirname(__FILE__), 'brb', 'event_machine.rb')
3
+ require File.join(File.dirname(__FILE__), 'brb', 'tunnel.rb')
4
+ require 'singleton'
5
+
6
+ #
7
+ # Brb Main class used to do basic distributed ruby, Simple but fast
8
+ # Use two distinct canal, one for the command reception, and the other one for send return value
9
+ #
10
+ module BrB
11
+ class Service
12
+ attr_reader :silent
13
+ attr_reader :uri
14
+
15
+ include Singleton
16
+
17
+ # Start a server hosted on the object given,
18
+ # If an uri is given, automatcilay connect to the distant brb object
19
+ def start_service(opts = {}, &block)
20
+ return if @em_signature
21
+
22
+ @silent = opts[:silent]
23
+
24
+ addr = "brb://#{opts[:host] || 'localhost'}:#{opts[:port] || 6200}"
25
+
26
+ tputs " [BrB] Start service on #{addr} ..."
27
+ @uri, @em_signature = BrBProtocol.open_server(addr, BrB::Tunnel::Handler, opts.merge(:block => block))
28
+ tputs " [BrB] Service started on #{@uri}"
29
+ end
30
+
31
+ private
32
+ def tputs(s)
33
+ puts s if !@silent
34
+ end
35
+
36
+ public
37
+ # Stop the Brb Service
38
+ def stop_service
39
+ return if !@em_signature
40
+
41
+ tputs ' [BrB] Stop service'
42
+ EM::stop_server(@em_signature)
43
+ @em_signature = nil
44
+ @uri = nil
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,44 @@
1
+ require 'eventmachine'
2
+
3
+ # Define a BrBProtocol using event machine
4
+ class BrBEventMachine
5
+
6
+ def self.parse_uri(uri)
7
+ if /^brb:\/\/(.+):([0-9]+)$/ =~ uri
8
+ [$1, $2.to_i]
9
+ else
10
+ raise "Bad tcp BrB url: '#{uri}'"
11
+ end
12
+ end
13
+
14
+ def self.open(uri, klass, opts = {})
15
+ host, port = parse_uri(uri)
16
+ begin
17
+ socket = EventMachine::connect host, port, klass, opts.merge(:uri => "brb://#{host}:#{port}")
18
+
19
+ rescue Exception => e
20
+ puts e.backtrace.join("\n")
21
+ raise "#{e} - #{uri}"
22
+ end
23
+ return socket
24
+ end
25
+
26
+ def self.open_server(uri, klass, opts = {})
27
+ host, port = parse_uri(uri)
28
+ max = 80
29
+ begin
30
+ #EventMachine::epoll
31
+ uri = "brb://#{host}:#{port}"
32
+ return uri, EventMachine::start_server(host, port, klass, opts.merge(:uri => uri))
33
+ rescue Exception => e
34
+ max -= 1
35
+ port += 1
36
+ retry if max > 0
37
+ puts e.backtrace.join("\n")
38
+ raise "#{e} - BrB Tcp Event machine Can not bind on #{host}:#{port}"
39
+ end
40
+ end
41
+ end
42
+
43
+ class BrBProtocol < BrBEventMachine
44
+ end
File without changes
@@ -0,0 +1,81 @@
1
+ module BrB
2
+ module Request
3
+
4
+ def is_brb_request_blocking?(meth)
5
+ if m = meth.to_s and m.rindex('_block') == (m.size - 6)
6
+ return true
7
+ end
8
+ nil
9
+ end
10
+
11
+ # Execute a request on a distant object
12
+ def new_brb_out_request(meth, *args)
13
+ Thread.current[:brb_nb_out] ||= 0
14
+ Thread.current[:brb_nb_out] += 1
15
+
16
+ block = is_brb_request_blocking?(meth) ? Thread.current.to_s.to_sym : nil
17
+ if block
18
+ args << block
19
+ args << Thread.current[:brb_nb_out]
20
+ end
21
+
22
+ args.size > 0 ? brb_send([:s, meth, args]) : brb_send([:s, meth])
23
+
24
+ # Block jusqu'au retour de la requete
25
+ if block
26
+ #TimeMonitor.instance.watch_thread!(@timeout_rcv_value || 45)
27
+ begin
28
+ r = recv(block, Thread.current[:brb_nb_out])
29
+ rescue Exception => e
30
+ #@object.log_error(e, "Error sending out request #{meth}(#{args.inspect})")
31
+ raise e
32
+ ensure
33
+ #TimeMonitor.instance.remove_thread!
34
+ end
35
+ if r.kind_of? Exception
36
+ raise r
37
+ end
38
+ return r
39
+ end
40
+
41
+ nil
42
+ end
43
+
44
+ # Execute a request on the local object
45
+ def new_brb_in_request(meth, *args)
46
+
47
+ if is_brb_request_blocking?(meth)
48
+
49
+ m = meth.to_s
50
+ m = m[0, m.size - 6].to_sym
51
+
52
+ idrequest = args.pop
53
+ thread = args.pop
54
+ begin
55
+ #TimeMonitor.instance.watch_thread!(25)
56
+ r = ((args.size > 0) ? @object.send(m, *args) : @object.send(m))
57
+ brb_send([:r, r, thread, idrequest])
58
+ rescue Exception => e
59
+ brb_send([:r, e, thread, idrequest])
60
+ tputs e.to_s
61
+ tputs e.backtrace.join("\n")
62
+ #raise e
63
+ ensure
64
+ #TimeMonitor.instance.remove_thread!
65
+ end
66
+ else
67
+
68
+ begin
69
+ (args.size > 0) ? @object.send(meth, *args) : @object.send(meth)
70
+ rescue Exception => e
71
+ tputs "#{e.to_s} => By calling #{meth} on #{@object.class} with args : #{args.inspect}"
72
+ tputs e.backtrace.join("\n")
73
+ raise e
74
+ end
75
+
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,81 @@
1
+ # encoding: utf-8
2
+ require 'eventmachine'
3
+ require File.join(File.dirname(__FILE__), 'request.rb')
4
+ require File.join(File.dirname(__FILE__), 'tunnel', 'shared.rb')
5
+
6
+ module BrB
7
+ module Tunnel
8
+
9
+ def self.create(object, uri = nil, opts = {}, &block)
10
+ BrBProtocol.open(uri, BrB::Tunnel::Handler, opts.merge(:object => object, :block => block))
11
+ end
12
+
13
+ # Brb interface Handler for Tunnel over Event machine
14
+ class Handler < EventMachine::Connection
15
+ attr_reader :uri
16
+
17
+ include BrB::Request
18
+ include BrB::Tunnel::Shared
19
+
20
+ def initialize(opts = {})
21
+ super
22
+ @object = opts[:object]
23
+ @silent = opts[:silent]
24
+ @timeout_rcv_value = opts[:timeout] || 30
25
+ @close_after_timeout = opts[:close_after_timeout] || false
26
+ @uri = opts[:uri]
27
+ @closed = nil
28
+ @replock = Mutex.new
29
+ @responses = {}
30
+ @block = opts[:block]
31
+ @mu = Mutex.new
32
+
33
+ @queue = Queue.new
34
+ @buffer = ''
35
+ end
36
+
37
+ def post_init
38
+ tputs " [BrB] Tunnel initialized on #{@uri}"
39
+ @active = true
40
+ if @block
41
+ EventMachine.defer do
42
+ @block.call(:register, self)
43
+ end
44
+ end
45
+ end
46
+
47
+ def close_connection(after_writing = false)
48
+ @active = false
49
+ super
50
+ end
51
+
52
+ def unbind
53
+ tputs ' [BrB] Tunnel service closed'
54
+ @active = false
55
+ if @block
56
+ EventMachine.defer do
57
+ @block.call(:unregister, self)
58
+ end
59
+ end
60
+ end
61
+
62
+ def stop_service
63
+ tputs ' [BrB] Stop Tunnel service'
64
+ @active = false
65
+ EM.schedule do
66
+ close_connection
67
+ end
68
+ end
69
+
70
+ def active?
71
+ @active
72
+ end
73
+
74
+ def method_missing(meth, *args)
75
+ return nil if !@active
76
+ new_brb_out_request(meth, *args)
77
+ end
78
+ end
79
+ end
80
+
81
+ end
@@ -0,0 +1,109 @@
1
+ # encoding: utf-8
2
+
3
+ module BrB
4
+ module Tunnel
5
+ module Shared
6
+ def tputs(s)
7
+ puts s if !@silent
8
+ end
9
+
10
+ def make_proxy(r)
11
+ if r.is_a?(Array)
12
+ t = []
13
+ r.each do |obj|
14
+ t << if obj.is_a? Array
15
+ make_proxy(obj)
16
+ elsif !obj.is_a?(Symbol) and !obj.is_a?(String) and obj and !(Marshal::dump(obj) rescue nil)
17
+ #puts " - > Make proxy for : #{obj.class}"
18
+ obj.to_s.to_sym
19
+ else
20
+ obj
21
+ end
22
+ end
23
+ return t
24
+ else
25
+ return r.to_s
26
+ end
27
+ end
28
+
29
+ def brb_send(r)
30
+ return nil if !@active
31
+ s = Marshal::dump(r) rescue Marshal::dump(make_proxy(r))
32
+
33
+ s = [s.size].pack('N') + s
34
+ EM.schedule do
35
+ send_data s
36
+ end
37
+ end
38
+
39
+ SizeOfPackedInt = [1].pack('N').size
40
+
41
+ def load_request
42
+ return nil if @buffer.size < SizeOfPackedInt
43
+ len = @buffer.unpack('N').first + SizeOfPackedInt
44
+ if @buffer.size < len
45
+ return nil
46
+ end
47
+
48
+ obj = Marshal::load(@buffer[SizeOfPackedInt, len])
49
+ @buffer.slice!(0,len)
50
+ return obj
51
+ end
52
+
53
+ def receive_data(data)
54
+ @buffer << data
55
+
56
+ while obj = load_request
57
+ if obj[0] == :r
58
+ @replock.lock
59
+ @responses[obj[2]] ||= Queue.new
60
+ @replock.unlock
61
+ @responses[obj[2]] << [obj[1], obj[3]]
62
+ else
63
+
64
+ @queue << obj
65
+
66
+ EventMachine.defer do
67
+ treat_request(@queue.pop)
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+
74
+ def treat_request(obj)
75
+ if obj.size == 2
76
+ new_brb_in_request(obj[1])
77
+ else
78
+ new_brb_in_request(obj[1], *(obj.last))
79
+ end
80
+ end
81
+
82
+ def recv(key, nb_out)
83
+ begin
84
+ @replock.lock
85
+ r = @responses[key] ||= Queue.new
86
+ @replock.unlock
87
+ while rep = r.pop
88
+ if rep[1] == nb_out # On check ke c'est bien la réponse que l'on attend
89
+ return rep[0]
90
+ end
91
+ #Error.create(:backtrace => "Error in Brb receiving in thread #{Thread.current}. Try to get #{nb_out} request id, but get #{rep[1]}", :type => 'BrBRecvBadId', :url => "#{@object.class}-#{@uri}")
92
+ if rep[1] > nb_out
93
+ return nil
94
+ end
95
+ end
96
+ rescue Exception => e
97
+ if @close_after_timeout == true
98
+ #Error.create(:backtrace => "Error in Rcv in thread #{Thread.current}. Try to get #{nb_out} => Stop service #{e.class.to_s}\n\n#{e.backtrace.join("\n")}", :type => e.to_s, :url => "#{@object.class}-#{@uri}")
99
+ stop_service
100
+ sleep 1
101
+ raise e
102
+ else
103
+ raise e
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,72 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe :brb_service do
4
+ before(:all) do
5
+ @brb = BrB::Service.instance
6
+ @brb.stop_service
7
+ @brb_test = BrBTest.new
8
+ open_service(@brb_test)
9
+ @clients = []
10
+ 20.times do
11
+ @clients << connect_to_the_service(self, @brb.uri) do |type, tunnel|
12
+ end
13
+ end
14
+ end
15
+
16
+ # Start the service
17
+ it "should the service be started" do
18
+ @clients.each do |cl|
19
+ cl.should_not be_nil
20
+ cl.active?.should be_true
21
+ cl.uri.should == @brb.uri
22
+ end
23
+ end
24
+
25
+ it "should works with massive simple messaging" do
26
+ nb_call_before = @brb_test.nb_call || 0
27
+ nb_call_to_do = 500
28
+
29
+ @clients.each do |cl|
30
+ nb_call_to_do.times do
31
+ cl.noarg
32
+ end
33
+ end
34
+
35
+ sleep 6
36
+ # Wait a little in order to be sure all the stack is processed
37
+ @brb_test.last_call.should == :noarg
38
+ @brb_test.nb_call.should == (nb_call_to_do * @clients.size) + nb_call_before
39
+ end
40
+
41
+ it "should works with massive simple messaging including blocking messaging" do
42
+ nb_call_before = @brb_test.nb_call || 0
43
+ nb_call_to_do = 500
44
+ nb_call_blocking_to_do = 50
45
+
46
+ t = Thread.new do
47
+ @clients.each do |cl|
48
+ nb_call_blocking_to_do.times do
49
+ val = Time.now.to_f
50
+ cl.return_same_value_block(val).should == val
51
+ end
52
+ end
53
+ end
54
+
55
+ @clients.each do |cl|
56
+ nb_call_to_do.times do
57
+ cl.noarg
58
+ end
59
+ end
60
+
61
+ sleep 6
62
+ t.join
63
+ # Wait a little in order to be sure all the stack is processed
64
+ @brb_test.nb_call.should == (nb_call_to_do * @clients.size + nb_call_blocking_to_do * @clients.size) + nb_call_before
65
+ end
66
+
67
+ # Finally, stop the service
68
+ it "should stop the service after usage" do
69
+ @brb.stop_service
70
+ @brb.uri.should be_nil
71
+ end
72
+ end
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe :brb_service do
4
+ before(:all) do
5
+ @brb = BrB::Service.instance
6
+ @brb.stop_service
7
+ @brb_test = BrBTest.new
8
+ open_service(self)
9
+ end
10
+
11
+ # Start the service
12
+ it "should open a service on localhost:6200" do
13
+ @brb.uri.should_not be_nil
14
+ end
15
+
16
+ # Finally, stop the service
17
+ it "should stop the service" do
18
+ @brb.stop_service
19
+ @brb.uri.should be_nil
20
+ end
21
+
22
+ it "should start again the service after a stop" do
23
+ open_service(self)
24
+ @brb.stop_service
25
+ open_service(self)
26
+ @brb.uri.should_not be_nil
27
+ end
28
+ end
29
+
@@ -0,0 +1,124 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ $last_unregistered = nil
4
+ $last_registered = nil
5
+
6
+ describe :brb_service do
7
+ before(:all) do
8
+ @brb = BrB::Service.instance
9
+ @brb.stop_service
10
+ @brb_test = BrBTest.new
11
+ open_service(@brb_test)
12
+ @client = connect_to_the_service(self, @brb.uri) do |type, tunnel|
13
+ if type == :unregister
14
+ $last_unregistered = tunnel
15
+ elsif type == :register
16
+ $last_registered = tunnel
17
+ end
18
+ end
19
+ end
20
+
21
+ # Start the service
22
+ it "should the service be started" do
23
+ @client.should_not be_nil
24
+ @client.active?.should be_true
25
+ @client.uri.should == @brb.uri
26
+ end
27
+
28
+ it "should have get the register message" do
29
+ sleep 0.2 # Be sure to get the message
30
+ $last_registered.class.should == @client.class
31
+ end
32
+
33
+ it "should correctly call simple distant method without args and without return" do
34
+ @client.noarg
35
+ sleep 0.2
36
+ # Wait a little in order to be sure the method is called
37
+ @brb_test.last_call.should == :noarg
38
+ end
39
+
40
+ it "should correctly call simple distant method without args and without return multipe times" do
41
+ nb_call_before = @brb_test.nb_call
42
+ nb_call_to_do = 50
43
+
44
+ nb_call_to_do.times do
45
+ @client.noarg
46
+ end
47
+ sleep 0.2
48
+ # Wait a little in order to be sure the method is called
49
+ @brb_test.last_call.should == :noarg
50
+ @brb_test.nb_call.should == nb_call_to_do + nb_call_before
51
+ end
52
+
53
+ it "should correctly call distant method with one argument" do
54
+ @client.very_long(:hello)
55
+ sleep 0.2
56
+ # Wait a little in order to be sure the method is called
57
+ @brb_test.last_args.should == [:hello]
58
+ end
59
+
60
+ it "should correctly call distant method with multiple arguments" do
61
+ args = [:one, :two, 3, "four"]
62
+ @client.fourargs(*args)
63
+ sleep 0.2
64
+ # Wait a little in order to be sure the method is called
65
+ @brb_test.last_args.should == args
66
+ end
67
+
68
+ it "should correctly return arguments symbol value" do
69
+ @client.one_arg_with_return_block(:hello).should == :hello
70
+ end
71
+
72
+ it "should correctly return arguments string value" do
73
+ @client.one_arg_with_return_block('hello').should == 'hello'
74
+ end
75
+
76
+ it "should correctly return arguments Fixnum value" do
77
+ @client.one_arg_with_return_block(42).should == 42
78
+ end
79
+
80
+ it "should correctly return arguments Float value" do
81
+ @client.one_arg_with_return_block(42.42).should == 42.42
82
+ end
83
+
84
+ it "should correctly return arguments Table value" do
85
+ @client.one_arg_with_return_block([:one, :two, 3, "four"]).should == [:one, :two, 3, "four"]
86
+ end
87
+
88
+ it "should correctly return arguments Hash value" do
89
+ h = {:yoyo => :titi, "salut" => 45}
90
+ @client.one_arg_with_return_block(h).should == h
91
+ end
92
+
93
+ it "should dump to symbol undumpable value by using the proxy" do
94
+ @client.return_same_value_block(Thread.current).class.should == Symbol
95
+ @client.return_same_value_block(Thread.current).should == Thread.current.to_s.to_sym
96
+ end
97
+
98
+ it "should transmit with success exception when blocking" do
99
+ e = nil
100
+ begin
101
+ @client.notavalidmeth_block
102
+ rescue Exception => e
103
+ end
104
+ e.should be_a NameError
105
+ end
106
+
107
+ # Finally, stop the service
108
+ it "should stop the service after usage" do
109
+ @brb.stop_service
110
+ @brb.uri.should be_nil
111
+ end
112
+
113
+ # Finally, stop the service
114
+ it "should stop the tunnel after usage" do
115
+ @client.stop_service
116
+ @client.active?.should_not be_true
117
+ end
118
+
119
+ it "should have get the unregister message" do
120
+ sleep 0.2 # Be sure to get the message
121
+ $last_unregistered.class.should == @client.class
122
+ end
123
+ end
124
+
@@ -0,0 +1,68 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ Thread.abort_on_exception = true
5
+
6
+ require File.dirname(__FILE__) + '/../init.rb'
7
+
8
+ def open_service(object, host = 'localhost', port = 6200)
9
+ if !EM::reactor_running?
10
+ # Launch event machine reactor
11
+ Thread.new do
12
+ EM::run do
13
+ EM::set_quantum(20)
14
+ end
15
+ end
16
+ sleep 0.05
17
+ end
18
+ r = nil
19
+ EM.schedule do
20
+ r = BrB::Service.instance.start_service(:object => object, :silent => true, :host => host, :port => port)
21
+ end
22
+ sleep 0.1
23
+ return r
24
+ end
25
+
26
+ def connect_to_the_service(object_exposed, uri, &block)
27
+ r = nil
28
+ EM.schedule do
29
+ r = BrB::Tunnel.create(object_exposed, uri, :silent => true, &block)
30
+ end
31
+ sleep 0.1
32
+ return r
33
+ end
34
+
35
+ class BrBTest
36
+ attr_reader :last_call
37
+ attr_reader :last_args
38
+ attr_reader :nb_call
39
+
40
+ def increment_nb_call(call_name, *args)
41
+ @last_call = call_name
42
+ @last_args = args
43
+ @nb_call ||= 0
44
+ @nb_call += 1
45
+ end
46
+
47
+ def very_long(ar)
48
+ increment_nb_call(:very_long, ar)
49
+ end
50
+
51
+ def fourargs(arg1, arg2, arg3, arg4)
52
+ increment_nb_call(:fourargs, arg1, arg2, arg3, arg4)
53
+ end
54
+
55
+ def noarg
56
+ increment_nb_call(:noarg)
57
+ end
58
+
59
+ def one_arg_with_return(ar)
60
+ increment_nb_call(:one_arg_with_return)
61
+ return ar
62
+ end
63
+
64
+ def return_same_value(val)
65
+ increment_nb_call(:return_same_value)
66
+ return val
67
+ end
68
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: brb
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
+ platform: ruby
11
+ authors:
12
+ - Guillaume Luccisano
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-04-16 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: eventmachine
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ description: BrB is a simple and extremely fast interface for doing simple distributed ruby and message passing
33
+ email: guillaume.luccisano@gmail.com
34
+ executables: []
35
+
36
+ extensions: []
37
+
38
+ extra_rdoc_files: []
39
+
40
+ files:
41
+ - examples/simple_client.rb
42
+ - examples/simple_core.rb
43
+ - lib/brb/event_machine.rb
44
+ - lib/brb/exception.rb
45
+ - lib/brb/request.rb
46
+ - lib/brb/tunnel/shared.rb
47
+ - lib/brb/tunnel.rb
48
+ - lib/brb.rb
49
+ - spec/brb/brb_massive_usage_spec.rb
50
+ - spec/brb/brb_service_spec.rb
51
+ - spec/brb/brb_tunnel_spec.rb
52
+ - spec/spec_helper.rb
53
+ - CHANGELOG.rdoc
54
+ - MIT-LICENSE
55
+ - Rakefile
56
+ - README.rdoc
57
+ - init.rb
58
+ has_rdoc: true
59
+ homepage: http://github.com/kwi/BrB
60
+ licenses: []
61
+
62
+ post_install_message:
63
+ rdoc_options: []
64
+
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ segments:
79
+ - 1
80
+ - 3
81
+ - 4
82
+ version: 1.3.4
83
+ requirements:
84
+ - eventmachine
85
+ rubyforge_project: brb
86
+ rubygems_version: 1.3.6
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: BrB is a simple and extremely fast interface for doing simple distributed ruby
90
+ test_files: []
91
+