A flaw in tuplespace implementation?

it seems tuplespace’s read operation is not considered important
somehow. consider this:

class HelloWorld

include DRbUndumped

attr_writer :str
def initialize(str)
	@str = str
end
def _dump#(*args, &block)

Marshal.dump(@str, *args, &block)

end
def HelloWorld._load#(*args, &block)

HelloWorld.new(Marshal.load(*args, &block))

end
def to_s
	@str
end

end

i created a simple hello world class, and released its object into the
tuplespace. i then created a simple process doing indefinite loop of
reading the object, and another one reading and modifying the object.

so what is the problem you say? i don’t want to use pass-by-reference
and DRbUndumped, so that each reader process actually gets a copy of the
object instead of a reference to it. to do that, i have to define my own
marshalling method. after a few run, i realized that the tuplespace
seems only need to see a _dump and a _load, instead of marshal_dump and
marshal_load, and that the tuplespace doesn’t even bother if there is no
parameter given in the _dump and _load or if there is no operation
within (returning nil). but the result is still a pass-by-reference. try
uncommenting the above class code, and something similar to this will
occur:

in init_with_ary': undefined methodsize’ for
#DRb::DRbUnknown:0x28d21d0 (NoMethodError)

any suggestion, or is tuplespace’s read operation isn’t as important as
take operation? is this a flaw?

On Apr 18, 2006, at 12:31 AM, Guest wrote:

so what is the problem you say? i don’t want to use pass-by-reference
and DRbUndumped, so that each reader process actually gets a copy
of the
object instead of a reference to it.

This is exactly how DRb works by default.

to do that, i have to define my own marshalling method.

No you don’t.

DRb takes care of this for you.

You don’t need to do anything other that make sure the class exists
on all processes that will hold it.

try uncommenting the above class code, and something similar to
this will
occur:

in init_with_ary': undefined method size’ for
#DRb::DRbUnknown:0x28d21d0 (NoMethodError)

If you ever get a DRb::DRbUnknown object you don’t have the class
available on one of your remote processes. Fix that problem first.

The second problem is that you seem to be passing an object that is
neither an Array nor a Hash into the Tuplespace. The code you gave
didn’t specify how you were adding the object to the Tuplespace, so a
full example is necessary to figure out what’s gone wrong.

any suggestion, or is tuplespace’s read operation isn’t as
important as
take operation? is this a flaw?

There is no flaw in Tuplespace. What you want to do works out of the
box. Adding extra marshalling doesn’t do anything since ruby’s built-
in Marshal does that work for you.

Here’s an example that illustrates what you want. Each slave process
gets a copy of the object, not a reference to it. You only need to
have the class exist in every process that will hold the object:

$ cat ts.rb
require ‘drb’
require ‘rinda/tuplespace’
require ‘x’

ts = Rinda::TupleSpace.new
DRb.start_service nil, ts
puts DRb.uri
DRb.thread.join

$ cat master.rb
require ‘drb’
require ‘x’

DRb.start_service

ts = DRbObject.new nil, ARGV.shift

x = X.new
x.value = 0

ts.write [:x, x]

$ cat slave.rb
require ‘drb’
require ‘x’

DRb.start_service

ts = DRbObject.new nil, ARGV.shift

obj = ts.read [:x, nil]

p obj.last
p obj.last.value
obj.last.value = 100
p obj.last.value

$ cat x.rb
class X
attr_accessor :value
end

$ ruby ts.rb &
druby://kaa.coop.robotcoop.com:52189
[2] 17630
$ ruby master.rb druby://kaa.coop.robotcoop.com:52189
$ ruby slave.rb druby://kaa.coop.robotcoop.com:52189
#<X:0x3997e8 @value=0>
0
100
$ ruby slave.rb druby://kaa.coop.robotcoop.com:52189
#<X:0x3997e8 @value=0>
0
100


Eric H. - [email protected] - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

have you tried combining the tuplespace and ring API? your example
indeed works when ring API is not used, simply providing a tuplespace as
a DRb service instead of a Ring service. but i’d rather have some code
that would enable me to automatically find a tuplespace, not manually by
passing the tuplespace’s uri. i modified your code to show you the
problem i faced in my first post, and added two ring files (name server
and space provider, which is actually your code as listed in your
segment7 site)

Eric H. wrote:

$ cat ts.rb
not needed, since i am using ring API to provide the tuplespace

$ cat master.rb
require “rinda/ring”
require ‘drb’
require ‘x’

DRb.start_service

#ts = DRbObject.new nil, ARGV.shift
ringServer = Rinda::RingFinger.primary
ts = ringServer.read([:name, :TupleSpace, nil, nil])[2]
ts = Rinda::TupleSpaceProxy.new ts

x = X.new
x.value = 0

ts.write [:x, x]

$ cat slave.rb
require “rinda/ring”
require ‘drb’
require ‘x’

DRb.start_service

#ts = DRbObject.new nil, ARGV.shift
ringServer = Rinda::RingFinger.primary
ts = ringServer.read([:name, :TupleSpace, nil, nil])[2]
ts = Rinda::TupleSpaceProxy.new ts

obj = ts.read [:x, nil]

p obj.last
p obj.last.value
obj.last.value = 100
p obj.last.value

$ cat name_server.rb
require “rinda/ring”
require “rinda/tuplespace”

DRb.start_service

Rinda::RingServer.new Rinda::TupleSpace.new

DRb.thread.join

$ cat space_provider.rb
require “rinda/ring”
require “rinda/tuplespace”

DRb.start_service

ts = Rinda::TupleSpace.new
provider = Rinda::RingProvider.new :TupleSpace, ts, “Tuple Space”
provider.provide

DRb.thread.join

$ ruby name_server.rb &
$ ruby space_provider.rb &
$ ruby master.rb &
…[error strings]
in init_with_ary': undefined methodsize’ for
DRb::DRbUnknown:0x28d21d0 (NoMethodError)
…[another error strings]
$ ruby slave.rb

On Apr 23, 2006, at 9:37 PM, [email protected] wrote:

have you tried combining the tuplespace and ring API?

It makes no difference if you use Rinda::Ring or not.

your example indeed works when ring API is not used, simply
providing a tuplespace as a DRb service instead of a Ring service.
but i’d rather have some code that would enable me to automatically
find a tuplespace, not manually by passing the tuplespace’s uri.

So just throw in Rinda::Ring.

i modified your code to show you the problem i faced in my first
post, and added two ring files (name server and space provider,
which is actually your code as listed in your segment7 site)

Since you didn’t respond to the same thread I’ve since lost that
email. I suggest you subscribe to the mailing list rather than post
through the forum.

$ cat rs.rb
require ‘rinda/ring’
require ‘rinda/tuplespace’

DRb.start_service
Rinda::RingServer.new Rinda::TupleSpace.new
DRb.thread.join
$ cat ts.rb
require ‘drb’
require ‘rinda/tuplespace’
require ‘rinda/ring’
require ‘x’

DRb.start_service
ts = Rinda::TupleSpace.new
provider = Rinda::RingProvider.new :TupleSpace, ts, ‘Tuple Space’
provider.provide
DRb.thread.join

$ cat master.rb
require ‘drb’
require ‘rinda/ring’
require ‘x’

DRb.start_service

rs = Rinda::RingFinger.primary
tuple = rs.read [:name, :TupleSpace, nil, nil]
ts = tuple[2]

x = X.new
x.value = 0

ts.write [:x, x]

$ cat slave.rb
require ‘drb’
require ‘rinda/ring’
require ‘x’

DRb.start_service

rs = Rinda::RingFinger.primary
tuple = rs.read [:name, :TupleSpace, nil, nil]
ts = tuple[2]

obj = ts.read [:x, nil]

p obj.last
p obj.last.value
obj.last.value = 100
p obj.last.value

$ cat x.rb
class X
attr_accessor :value
end

$ ruby rs.rb &
[1] 28527
$ ruby ts.rb &
[2] 28528
$ ruby master.rb
$ ruby slave.rb
#<X:0x38ca34 @value=0>
0
100


Eric H. - [email protected] - http://blog.segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com