Can DRbUndumped be disabled for certain return types?

J

Josh Mcdade

I have server model classes that definitely need DRbUndumped. Except
for the methods that return an array. I would rather it return an array
that is NOT wrapped in a DRbObject, and everything else still be a
DRbObject.

Here is a client/server example: http://pastie.org/1211949

The main reason I need this is because I'm integrating a remote backend
implemented in Ruby with a Java front-end, written in Java and using
JSR223 w/ JRuby to grab the objects. The DRbObject will map to the
appropriate interfaces, except when the DRbObject is an Array. The Java
application only knows the DRbObject as a org.jruby.RubyObject and it
cannot be cast to SomeArray[] for instance.

I'm asking this in the Ruby forum because the DRbObject behavior is the
same in Ruby/JRuby, I just need it for JRuby purposes.

I tried patching DRbObject, but I've had no success. Here is my
attempt:

http://pastie.org/1212829
 
J

Joel VanderWerf

I have server model classes that definitely need DRbUndumped. Except
for the methods that return an array. I would rather it return an array
that is NOT wrapped in a DRbObject, and everything else still be a
DRbObject.

Here is a client/server example: http://pastie.org/1211949

The main reason I need this is because I'm integrating a remote backend
implemented in Ruby with a Java front-end, written in Java and using
JSR223 w/ JRuby to grab the objects. The DRbObject will map to the
appropriate interfaces, except when the DRbObject is an Array. The Java
application only knows the DRbObject as a org.jruby.RubyObject and it
cannot be cast to SomeArray[] for instance.

I'm asking this in the Ruby forum because the DRbObject behavior is the
same in Ruby/JRuby, I just need it for JRuby purposes.

I tried patching DRbObject, but I've had no success. Here is my
attempt:

http://pastie.org/1212829

If you add this line to the client:

DRb.start_service

then your #each call works. The array stays on the server, however, and
each iteration involves a message to and from the server to get the
array entry's DRbObject. This would be inefficient for a large array,
unless your round-trip latency is small.

What do you actually want to get back on the client side? An array of
DRbUndumped proxies to RemoteObj instances on the server, or an array of
copies of Remote Obj?
 
B

Brian Candler

You mean, you want your objects to be DRbUndumped, except when you return an array of them?

Then I suggest you don't include DRbUndumped in your class, but extend individual objects with DRbUndumped - except for those objects which don't need it.

If you want this to be transparent, then extend DRbUndumped in your initialize method, then make another version of 'new' which doesn't.

Maybe like this (totally untested)

class RemoteObj
def initialize(*args,&blk)
extend DRbUndumped
initialize_hidden(*args,&blk)
end

def initialize_hidden(...)
.. normal initialize logic
end

def self.new_hidden(*args,&blk)
o = allocate
o.initialize_hidden(*args,&blk)
o
end
end
 
B

Brian Candler

Or:

def initialize
@undumped = lambda {}
end

def can_dump
@undumped = nil # is there instance_variable_unset ?
end
 
R

Robert Klemme

I have server model classes that definitely need DRbUndumped. =A0Except
for the methods that return an array. =A0I would rather it return an arr= ay
that is NOT wrapped in a DRbObject, and everything else still be a
DRbObject.

Here is a client/server example: http://pastie.org/1211949

The main reason I need this is because I'm integrating a remote backend
implemented in Ruby with a Java front-end, written in Java and using
JSR223 w/ JRuby to grab the objects. =A0The DRbObject will map to the
appropriate interfaces, except when the DRbObject is an Array. =A0The Ja= va
application only knows the DRbObject as a org.jruby.RubyObject and it
cannot be cast to SomeArray[] for instance.

I'm asking this in the Ruby forum because the DRbObject behavior is the
same in Ruby/JRuby, I just need it for JRuby purposes.

I tried patching DRbObject, but I've had no success. =A0Here is my
attempt:

http://pastie.org/1212829

If you add this line to the client:

DRb.start_service

then your #each call works.

I do not think this is necessary nor does this seem to be the issue if
I get Josh correctly.
The array stays on the server, however, and each
iteration involves a message to and from the server to get the array entr= y's
DRbObject. This would be inefficient for a large array, unless your
round-trip latency is small.

Whatever network performance, iterating an Array remotely is awfully
slow compared to in memory. Note that for each iteration there is a
call back into the client for processing the block. So you have 2 + n
* 2 network communications, where n is the number of items in the
Array.
What do you actually want to get back on the client side? An array of
DRbUndumped proxies to RemoteObj instances on the server, or an array of
copies of Remote Obj?

I believe Josh expected the former (a local Array with proxies). DRb
seems to apply some automatism, i.e. if there is at least one
DRbUndumped in an Array the whole Array is proxied. If you only place
String, Fixnum etc. in the Array then you actually get a local copy.

I have no idea why this automatism is in place and I would love to
learn the wisdom behind this. Right now it seems to much automation
to me. But I may be overlooking something.

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
J

Joel VanderWerf

I do not think this is necessary nor does this seem to be the issue if
I get Josh correctly.

Yes it is necessary, but no, I don't think that's what he wants.

If you comment out the client's #start_service call in the following,
you get a DRb::DRbServerNotFound.

$ cat svr.rb
require 'drb'

URI = "druby://localhost:5555"
class RemoteObj
include DRb::DRbUndumped

def some_array
(0..10).map { RemoteObj.new }
end
end

s = DRb::DRbServer.new URI, RemoteObj.new
$stderr.puts "Started: #{s.uri}"
s.thread.join

$ cat clt.rb
require 'drb'
URI = "druby://localhost:5555"
DRb.start_service

ro = DRb::DRbObject.new nil, URI

some_array = ro.some_array

some_array.each do |x|
p x
end
 
B

Brian Candler

Robert Klemme wrote in post #949407:
I believe Josh expected the former (a local Array with proxies). DRb
seems to apply some automatism, i.e. if there is at least one
DRbUndumped in an Array the whole Array is proxied. If you only place
String, Fixnum etc. in the Array then you actually get a local copy.

I have no idea why this automatism is in place

The response is a single object, and DRb just Marshals it to get a
String to send over the wire. If it can't be marshalled, then you get a
proxy for the whole thing instead. All that including DRbUndumped does
is to make the whole thing unmarshallable:

module DRbUndumped
def _dump(dummy) # :nodoc:
raise TypeError, 'can\'t dump'
end
end

So, an Array which contains even one object with DRbUndumped is itself
not marshallable.

If you want to send over an array of proxies, well, you could construct
explicit DRbObject wrappers, but I just noticed this in the drb/drb.rb
source:

class DRbArray
def initialize(ary)
@ary = ary.collect { |obj|
if obj.kind_of? DRbUndumped
DRbObject.new(obj)
else
begin
Marshal.dump(obj)
obj
rescue
DRbObject.new(obj)
end
end
}
end

def self._load(s)
Marshal::load(s)
end

def _dump(lv)
Marshal.dump(@ary)
end
end

So why not just make one of those?
 
J

Joel VanderWerf

If you want to send over an array of proxies, well, you could construct
explicit DRbObject wrappers, but I just noticed this in the drb/drb.rb
source:

class DRbArray

Good to know about, thanks!

Clever how an instance of DRbArray on the server becomes an ordinary
Array on the client side.
 
R

Robert Klemme

Yes it is necessary, but no, I don't think that's what he wants.

Of course you are right! I an sorry for the (my) confusion. I just
thought I had done an iteration but I actually didn't in my test
scripts. As soon as there are remote calls done into the VM the DRb
service needs to be started. And as I said elsewhere this happens
during iteration. :-}

Kind regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
DewittMill
Top