Removing methods from DRbObject

My application is using DRb extensively in support of its client-server
model. Ideally I would like to have the remote objects in the client
scripts appear exactly as they would if they were local. All my data
objects include DRb::DRbUndumped so that only references are passed
across the network, as the objects’ code needs to run on the server
(database access etc). Unfortunately, DRb::DRbObject defines a bunch of
methods which it doesn’t really use, such as ==, ===, <=> etc; but
because it defines them, calls to them don’t get proxied to the server.

The Criteria module has in it a neat little bit of code that looks like
this:

mask = [“send”, “id”, “inspect”, “class”, “is_a?”, “dup”,
“instance_eval”];
methods = instance_methods(true)
methods = methods - mask

methods.each do |m|
undef_method(m)
end

This removes all methods from the class except those in mask.
Something like this in DRb::DRBObject, with an appropriate mask list,
would be really useful, because at the moment, if I have two DRbObjects
which represent the same object on the remote side, the == method still
returns false because of the way DRbObject defines == (the default way,
if it’s not exactly the same object they’re not equal).

Therefore I have three questions:

  1. Is this a reasonable change to make?
  2. What is an appropriate mask list to use for DRb::DRbObject?
  3. Can I get this change into the core library?
···


Tim Bates
tim@bates.id.au

“Tim Bates” tim@bates.id.au schrieb im Newsbeitrag
news:4023592E.9090409@bates.id.au…

My application is using DRb extensively in support of its client-server
model. Ideally I would like to have the remote objects in the client
scripts appear exactly as they would if they were local. All my data
objects include DRb::DRbUndumped so that only references are passed
across the network, as the objects’ code needs to run on the server
(database access etc). Unfortunately, DRb::DRbObject defines a bunch of
methods which it doesn’t really use, such as ==, ===, <=> etc; but
because it defines them, calls to them don’t get proxied to the server.

The Criteria module has in it a neat little bit of code that looks like
this:

mask = [“send”, “id”, “inspect”, “class”, “is_a?”, “dup”,
“instance_eval”];
methods = instance_methods(true)
methods = methods - mask

methods.each do |m|
undef_method(m)
end

This removes all methods from the class except those in mask.
Something like this in DRb::DRBObject, with an appropriate mask list,
would be really useful, because at the moment, if I have two DRbObjects
which represent the same object on the remote side, the == method still
returns false because of the way DRbObject defines == (the default way,
if it’s not exactly the same object they’re not equal).

Therefore I have three questions:

  1. Is this a reasonable change to make?
  2. What is an appropriate mask list to use for DRb::DRbObject?
  3. Can I get this change into the core library?

I’ll prefer to raise another issue: usually it is not a good idea to
reference masses of instances remotely. Thies yields hight network load
since lot’s of methods are not invoked locally but remotely. This can
degenerate to a degree where an application is no longer usable. Did you
verify that your application does not suffer from this performance
degeneration? If not, I’d first verify that usig lots of instances
remotely is practical. While transparent distribution of instances sounds
like a good thing, a typical application using distribution should / must
be aware of the distribution in order to do things efficiently. In your
case it might be better to transfer an array or hash of data objects to
the client, work with then and send them back afterwards.

Just my 0.02EUR…

Kind regards

robert

Tim Bates wrote:

This removes all methods from the class except those in mask.
Something like this in DRb::DRBObject, with an appropriate mask list,
would be really useful, because at the moment, if I have two DRbObjects
which represent the same object on the remote side, the == method still
returns false because of the way DRbObject defines == (the default way,
if it’s not exactly the same object they’re not equal).

You might want consider requiring drb/eq, which defines #== and #hash in
terms of the remote reference, rather than object identity.

Joel VanderWerf wrote:

You might want consider requiring drb/eq, which defines #== and #hash in
terms of the remote reference, rather than object identity.

class DRbObject
def ==(other)
return false unless DRbObject === other
(@ref == other.__drbref) && (@uri == other.__drburi)
end

This doesn’t do what I want either. It does some comparison of whether
they represent the same object on the remote side. In my case, they
don’t - but the remote objects have a definition of #== that makes them
equal. This doesn’t solve my problem.

By undefining #==, #inspect, #class and so on, you could make a
DRbObject appear and behave exactly like the local one. I’m not sure how
many of these such methods it is wise to undefine, though - some may be
crucial to the way DRb works. Can someone with a knowledge of the
internals of DRb please tell me if I’ll get into trouble by undefining
the wrong methods, and what those methods are?

···


Tim Bates
tim@bates.id.au