Can DRbUndumped be disabled for certain return types?

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

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

Or:

def initialize
@undumped = lambda {}
end

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

On 10/11/2010 05:39 AM, Josh Mcdade wrote:

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?

On Mon, Oct 11, 2010 at 8:16 PM, Joel VanderWerf
[email protected] wrote:

implemented in Ruby with a Java front-end, written in Java and using

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 entry’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

Robert K. 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?

On 10/12/2010 11:39 AM, Brian C. wrote:

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.

On 10/12/2010 01:07 AM, Robert K. wrote:

On Mon, Oct 11, 2010 at 8:16 PM, Joel VanderWerf

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.

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

On Tue, Oct 12, 2010 at 8:06 PM, Joel VanderWerf
[email protected] wrote:

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.

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

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs