Rinda: random ECONNREFUSED error

I was following rinda examples from
http://segment7.net/projects/ruby/drb/rinda/ringserver.html and randomly
got
ECONNREFUSED: Connection refused - connect(2)
error from running the list_services code.

I tried a variation from ringserver example as attached below. I ran it
on different machines (all Linux RedHat 2.4) with ruby 1.8.6p111+ and
1.8.7p22. Same behavior. Eventually, I’ll get several
#<Errno::ECONNREFUSED: Connection refused - connect(2)> errors.

There is great chance that the mistake is in my code or due to the lack
of my understanding, so I would appreciate if someone could point it
out. Thanks in advance

-andre

foreach i (*) # I have ± 100 files
foreach? ruby client.rb
foreach? end

– server.rb –
require ‘rinda/tuplespace’
require ‘rinda/ring’
include Rinda
DRb.start_service
RingServer.new TupleSpace.new
DRb.thread.join

– service.rb –
require ‘rinda/ring’
include Rinda
DRb.start_service
RingFinger.primary.write [:service, “Test1”]
DRb.thread.join

– client.rb –
require ‘rinda/ring’
include Rinda
DRb.start_service
puts RingFinger.primary.read([:service, nil])[1]

Andreas Sun wrote:

I was following rinda examples from
http://segment7.net/projects/ruby/drb/rinda/ringserver.html and randomly
got
ECONNREFUSED: Connection refused - connect(2)
error from running the list_services code.

– server.rb –
require ‘rinda/tuplespace’
require ‘rinda/ring’
include Rinda
DRb.start_service
RingServer.new TupleSpace.new
DRb.thread.join

– service.rb –
require ‘rinda/ring’
include Rinda
DRb.start_service
RingFinger.primary.write [:service, “Test1”]
DRb.thread.join

– client.rb –
require ‘rinda/ring’
include Rinda
DRb.start_service
puts RingFinger.primary.read([:service, nil])[1]

Good question. I can never get primary() to work either.

I always end up using:

finger=Rinda::RingFinger.new([BROADCAST_ADDRESS])

remote_tuplespace=finger.lookup_ring_any

for the client and service code…

djief

I always end up using:

finger=Rinda::RingFinger.new([BROADCAST_ADDRESS])

remote_tuplespace=finger.lookup_ring_any

for the client and service code…

This seems works. Thank you.

You’ve got me looked at the RingFinger class. The default broadcast
address list is [’’, ‘localhost’]. It is that ‘’
that returns uri from other localhost’s ports or other machines in my
network, somewhat in a non deterministic order, thus primary is non
deterministic. I tried to find out what this mean and it
seems to bring me to the topic of socket itself, which I’m not familiar
with.

Now, if the default broadcast address list is reversed, that is
‘localhost’ is the first address, then you’ll always get the same
primary (from my quick, loosely test). Any idea why it is set up as it
is?

Thanks again for the solution
-andre

Andreas Sun wrote:

I always end up using:

finger=Rinda::RingFinger.new([BROADCAST_ADDRESS])

remote_tuplespace=finger.lookup_ring_any

for the client and service code…

This seems works. Thank you.

You’ve got me looked at the RingFinger class. The default broadcast
address list is [’’, ‘localhost’]. It is that ‘’
that returns uri from other localhost’s ports or other machines in my
network, somewhat in a non deterministic order, thus primary is non
deterministic. I tried to find out what this mean and it
seems to bring me to the topic of socket itself, which I’m not familiar
with.

Now, if the default broadcast address list is reversed, that is
‘localhost’ is the first address, then you’ll always get the same
primary (from my quick, loosely test). Any idea why it is set up as it
is?

Thanks again for the solution
-andre

I wish I knew for certain…I spent some time looking at it a few months
back and couldn’t work my way through the sequence of execution with any
satisfaction.

Through testing I noticed that for my version (Ubuntu 7/Ruby 1.8.6 p36)
the instance variable @primary wasn’t set unless I forced a call to
lookup_ring_any which then set & returned the primary instance (and so
the code above).

I could never get the @rings array to populate with any secondary
servers so I suspect there are some other issues with how broadcasts are
being processed, not necessarily within the Rinda code but that may be
possible as well.

If you look at the RingerFinger initialize method, you see that if you
use nil for the broadcast address ‘localhost’ is used. This lead me to
conclude that the default for the class variable @@broadcast_list (i.e.
[’’, ‘localhost’]) was likely just a stub meant to be
overridden but I’m willing to admit that there may be implications that
have escaped me.

In practice, I’ve found that you need to provide a broadcast address if
you’re actually distributing the services across multiple machines so
that finger knows which interface to send the broadcast packets to. This
isn’t terribly limiting if your machines share a LAN segment or VLAN but
it can require a bit more work at the router/switch level if this isn’t
the case.

Also worth noting is line 2 in lib/ring.rb:

Note: Rinda::Ring API is unstable.

My current thinking is that may just be easier to write a simple
TupleSpace server (or pair) to provide service location and supply their
addresses in a config file to all service providers and clients
especially since you would appear to need to provide a minimal
configuration (the broadcast address) at any rate.

I’ve been testing this approach and it appears to be solid so far…