brb 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+