DRb functions disappearing?

(Kevin Brown) #1

I will start by admitting I'm new to Ruby, but am generally a quick learner.
Anyway, I put together a simple DRb test program which works fine. I'm now
trying to do the real thing, where I need a graphical front end to
communicate with a backend on localhost for the moment, but eventually, on
another machine.

My problem is that the functions seem to disappear. If the code in my class
is like below:

    DRb.start_service()
    @connection = DRbObject.new(nil, 'druby://localhost:9000')
    @connection.login

I get the following output:

(druby://localhost:9000) /usr/lib/ruby/1.8/drb/drb.rb:1478:in `login': wrong
number of arguments (0 for 1) (ArgumentError)
        from ./dli-frontend.rb:33:in `initialize'
        from ./dli-frontend.rb:62:in `new'
        from ./dli-frontend.rb:62

Which is correct. login takes one argument. I then supply the argument with:

    DRb.start_service()
    @connection = DRbObject.new(nil, 'druby://localhost:9000')
    user = User.new
    @connection.login(user)

Here's the output:

(druby://localhost:9000) ./db/db.rb:999:in `login': undefined method `login'
for #<DRb::DRbUnknown:0xb72c2fec> (NoMethodError)
        from (druby://localhost:9000) ./listener.rb:31:in `login'
        from ./dli-frontend.rb:33:in `initialize'
        from ./dli-frontend.rb:62:in `new'
        from ./dli-frontend.rb:62

If there's more info I need to provide, please let me know... Otherwise, any
ideas as to what I'm doing wrong?

(Eric Hodel) #2

I will start by admitting I'm new to Ruby, but am generally a quick learner.
Anyway, I put together a simple DRb test program which works fine. I'm now
trying to do the real thing, where I need a graphical front end to
communicate with a backend on localhost for the moment, but eventually, on
another machine.

My problem is that the functions seem to disappear. If the code in my class
is like below:

    DRb.start_service()
    @connection = DRbObject.new(nil, 'druby://localhost:9000')
    @connection.login

I get the following output:

(druby://localhost:9000) /usr/lib/ruby/1.8/drb/drb.rb:1478:in `login': wrong
number of arguments (0 for 1) (ArgumentError)
        from ./dli-frontend.rb:33:in `initialize'
        from ./dli-frontend.rb:62:in `new'
        from ./dli-frontend.rb:62

Which is correct. login takes one argument. I then supply the argument with:

    DRb.start_service()
    @connection = DRbObject.new(nil, 'druby://localhost:9000')
    user = User.new
    @connection.login(user)

Here's the output:

(druby://localhost:9000) ./db/db.rb:999:in `login': undefined method `login'
for #<DRb::DRbUnknown:0xb72c2fec> (NoMethodError)

^^^
Looks like you're missing a DRbUndumped somewhere.

        from (druby://localhost:9000) ./listener.rb:31:in `login'
        from ./dli-frontend.rb:33:in `initialize'
        from ./dli-frontend.rb:62:in `new'
        from ./dli-frontend.rb:62

If there's more info I need to provide, please let me know... Otherwise, any
ideas as to what I'm doing wrong?

How about some code?

···

On 25 Aug 2005, at 21:49, Kevin Brown wrote:

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

(Kevin Brown) #3

Your wish is my command.

Here's the backend code:
--START--
require 'db/db'
require 'listener'
require 'drb'

# Initialize Database Connection
db = DB.new

# Start Listener
listener = Listener.new(db)
listener.extend DRb::DRbUndumped
DRb.start_service('druby://localhost:9000', listener)

puts "DLI server is up and running...\n"

DRb.thread.join
--END--

DB is a database abstraction layer, listener maps calls to it, only allowing
access to login for now.

Here's listener, not like it matters much:
--START--
require 'db/db'
require 'thread'

class Listener

···

On Friday 26 August 2005 01:14, Eric Hodel wrote:

On 25 Aug 2005, at 21:49, Kevin Brown wrote:
> Here's the output:
>
> (druby://localhost:9000) ./db/db.rb:999:in `login': undefined
> method `login'
> for #<DRb::DRbUnknown:0xb72c2fec> (NoMethodError)

^^^
Looks like you're missing a DRbUndumped somewhere.

How about some code?

  #---------------------------------------------------------------------------
  # Method: initialize
  # Purpose: Prepare listener to be able to direct behavior of backend
  # Pre: Listener has none of the objects it needs to control the backend
  # Post: Listener is prepped for use
  #---------------------------------------------------------------------------
  def initialize(db)
    @db = db
    @mutex = Mutex.new
  end

  #---------------------------------------------------------------------------
  # Method: login
  # Purpose: Allow user to login to the system
  # Pre: User is not logged in
  # Post: User is logged in and returned, or error is raised.
  #---------------------------------------------------------------------------
  def login(user)
    @db.login(user)
  end
end
--END--

And the client code is in a KDE app, so I won't bore you all with the pile
there:
--START--
require 'Korundum'
require 'drb'
require 'errors'
require 'login'

class Dli < KDE::MainWindow
  attr_reader :connection

  slots 'newUser()'

  def initialize(name)
    super(nil, name)

    # Prepare messenger to get to backend.
    DRb.start_service()
    @connection = DRbObject.new(nil, 'druby://localhost:9000')
    user = User.new
    @connection.login(user)
--END--
The connection.login is the "disappearing" method... And that's all the code
that has to do with that. :slight_smile:

Thanks for the quick reply!

(Eric Hodel) #4

Here's the output:

(druby://localhost:9000) ./db/db.rb:999:in `login': undefined
method `login'
for #<DRb::DRbUnknown:0xb72c2fec> (NoMethodError)

^^^
Looks like you're missing a DRbUndumped somewhere.

How about some code?

Your wish is my command.

Here's the backend code:
--START--
require 'db/db'
require 'listener'
require 'drb'

# Initialize Database Connection
db = DB.new

# Start Listener
listener = Listener.new(db)
listener.extend DRb::DRbUndumped
DRb.start_service('druby://localhost:9000', listener)

puts "DLI server is up and running...\n"

DRb.thread.join
--END--

DB is a database abstraction layer, listener maps calls to it, only allowing
access to login for now.

Here's listener, not like it matters much:

The listener isn't involved in the failure, right?

--START--
require 'db/db'
require 'thread'

class Listener

  def initialize(db)
    @db = db
    @mutex = Mutex.new
  end

  def login(user)
    @db.login(user)
  end
end
--END--

And the client code is in a KDE app, so I won't bore you all with the pile
there:
--START--
require 'Korundum'
require 'drb'
require 'errors'
require 'login'

I don't see require 'db/db' here, so you'll need to add 'include DRbUndumped' to db/db if you don't want db/db to live here.

···

On 26 Aug 2005, at 00:32, Kevin Brown wrote:

On Friday 26 August 2005 01:14, Eric Hodel wrote:

On 25 Aug 2005, at 21:49, Kevin Brown wrote:

class Dli < KDE::MainWindow
  attr_reader :connection

  slots 'newUser()'

  def initialize(name)
    super(nil, name)

    # Prepare messenger to get to backend.
    DRb.start_service()
    @connection = DRbObject.new(nil, 'druby://localhost:9000')
    user = User.new
    @connection.login(user)
--END--
The connection.login is the "disappearing" method... And that's all the code
that has to do with that. :slight_smile:

Thanks for the quick reply!

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

(Kevin Brown) #5

If I don't want db/db to live here? It's a seperate process...? I'm totally
lost as to A) Why that class would exist here, and B) Why it existing here
would cause DRb to not be able to call one of my methods in the listener
class?

···

On Friday 26 August 2005 02:08, Eric Hodel wrote:

On 26 Aug 2005, at 00:32, Kevin Brown wrote:
> And the client code is in a KDE app, so I won't bore you all with
> the pile
> there:
> --START--
> require 'Korundum'
> require 'drb'
> require 'errors'
> require 'login'

I don't see require 'db/db' here, so you'll need to add 'include
DRbUndumped' to db/db if you don't want db/db to live here.

(Kevin Brown) #6

Server code now looks like:
require 'db/db'
require 'listener'
require 'drb'

# Initialize Database Connection
db = DB.new

# Start Listener
db.extend DRb::DRbUndumped
listener = Listener.new(db)
listener.extend DRb::DRbUndumped
DRb.start_service('druby://localhost:9000', listener)

puts "DLI server is up and running...\n"

DRb.thread.join

And it's still showing the same behavior...

(Eric Hodel) #7

And the client code is in a KDE app, so I won't bore you all with
the pile
there:
--START--
require 'Korundum'
require 'drb'
require 'errors'
require 'login'

I don't see require 'db/db' here, so you'll need to add 'include
DRbUndumped' to db/db if you don't want db/db to live here.

If I don't want db/db to live here? It's a seperate process...?

db/db may be a huge object that you wouldn't want sent across the wire, or its a lot of code that doesn't need to be loaded.

I'm totally lost as to A) Why that class would exist here, and B) Why it existing here would cause DRb to not be able to call one of my methods in the listener
class?

A) DRb tries to marshal objects when communicating. If DRb can't marshal the object, it sends a DRbObject proxy instead.

B) When DRb is trying to send marshaled objects back and forth, both sides need the class definition or the object needs to be undumpable.

···

On 26 Aug 2005, at 01:18, Kevin Brown wrote:

On Friday 26 August 2005 02:08, Eric Hodel wrote:

On 26 Aug 2005, at 00:32, Kevin Brown wrote:

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

(Eric Hodel) #8

Looking again, maybe its User in the KDE process... Its hard to tell when I can't run it :frowning:

···

On 26 Aug 2005, at 09:27, Kevin Brown wrote:

Server code now looks like:
require 'db/db'
require 'listener'
require 'drb'

# Initialize Database Connection
db = DB.new

# Start Listener
db.extend DRb::DRbUndumped
listener = Listener.new(db)
listener.extend DRb::DRbUndumped
DRb.start_service('druby://localhost:9000', listener)

puts "DLI server is up and running...\n"

DRb.thread.join

And it's still showing the same behavior...

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

(Kevin Brown) #9

>>> And the client code is in a KDE app, so I won't bore you all with
>>> the pile
>>> there:
>>> --START--
>>> require 'Korundum'
>>> require 'drb'
>>> require 'errors'
>>> require 'login'
>>
>> I don't see require 'db/db' here, so you'll need to add 'include
>> DRbUndumped' to db/db if you don't want db/db to live here.
>
> If I don't want db/db to live here? It's a seperate process...?

db/db may be a huge object that you wouldn't want sent across the
wire, or its a lot of code that doesn't need to be loaded.

Ok, that makes sense... I don't want it marshalled, just need proxy objects,
and that's why I've been using the undumped...

> I'm totally lost as to A) Why that class would exist here, and B)
> Why it existing here would cause DRb to not be able to call one of
> my methods in the listener
> class?

A) DRb tries to marshal objects when communicating. If DRb can't
marshal the object, it sends a DRbObject proxy instead.

Exactly what I want. :slight_smile:

B) When DRb is trying to send marshaled objects back and forth, both
sides need the class definition or the object needs to be undumpable.

Ok, DB is a gigantic class, that depends on a large pile of subclasses. The
part that's getting me is that the DRb proxy object is obviously correctly
associated with the Listener class. The error comes from the call inside the
listener when it calls @db.login(user). The user I'm passing in was just to
reproduce the error, but if it did execute correctly, an error would be
raised from my code. I know the User is fine as far as the listener call is
concerned.

So, my confusion now lies in the fact that I really just want DRb to send the
message to the server, and back off while that happens. It still seems to
want to do it on the client side via marshalling, but I'm new enough to this
I could be on total crack. :slight_smile:

···

On Friday 26 August 2005 12:53, Eric Hodel wrote:

On 26 Aug 2005, at 01:18, Kevin Brown wrote:
> On Friday 26 August 2005 02:08, Eric Hodel wrote:
>> On 26 Aug 2005, at 00:32, Kevin Brown wrote:

(Eric Hodel) #10

And the client code is in a KDE app, so I won't bore you all with
the pile
there:
--START--
require 'Korundum'
require 'drb'
require 'errors'
require 'login'

I don't see require 'db/db' here, so you'll need to add 'include
DRbUndumped' to db/db if you don't want db/db to live here.

If I don't want db/db to live here? It's a seperate process...?

db/db may be a huge object that you wouldn't want sent across the
wire, or its a lot of code that doesn't need to be loaded.

Ok, that makes sense... I don't want it marshalled, just need proxy objects,
and that's why I've been using the undumped...

I'm totally lost as to A) Why that class would exist here, and B)
Why it existing here would cause DRb to not be able to call one of
my methods in the listener class?

A) DRb tries to marshal objects when communicating. If DRb can't
marshal the object, it sends a DRbObject proxy instead.

Exactly what I want. :slight_smile:

B) When DRb is trying to send marshaled objects back and forth, both
sides need the class definition or the object needs to be undumpable.

Ok, DB is a gigantic class, that depends on a large pile of subclasses. The
part that's getting me is that the DRb proxy object is obviously correctly
associated with the Listener class. The error comes from the call inside the
listener when it calls @db.login(user). The user I'm passing in was just to
reproduce the error, but if it did execute correctly, an error would be
raised from my code. I know the User is fine as far as the listener call is
concerned.

Its hard to say what exactly is wrong without being able to tinker with it :frowning: Did you see my other email about adding DRbUndumped to the User class?

Even if you mark a class as Undumped, objects generated by the class may be marshaled and returned across the wire.

So, my confusion now lies in the fact that I really just want DRb to send the
message to the server, and back off while that happens. It still seems to
want to do it on the client side via marshalling, but I'm new enough to this
I could be on total crack. :slight_smile:

If you could reduce your failure to something that is easily distributable, I could help more.

···

On 26 Aug 2005, at 20:07, Kevin Brown wrote:

On Friday 26 August 2005 12:53, Eric Hodel wrote:

On 26 Aug 2005, at 01:18, Kevin Brown wrote:

On Friday 26 August 2005 02:08, Eric Hodel wrote:

On 26 Aug 2005, at 00:32, Kevin Brown wrote:

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

(Kevin Brown) #11

Its hard to say what exactly is wrong without being able to tinker
with it :frowning: Did you see my other email about adding DRbUndumped to
the User class?

Nope, but I'll give it a shot.

Even if you mark a class as Undumped, objects generated by the class
may be marshaled and returned across the wire.

Hmmm... Maybe I'm simply using the wrong technology? I really just need
messages sent, and exceptions tossed back if they happen. Would this be
better suited to TCP/IP directly by chance?

> So, my confusion now lies in the fact that I really just want DRb
> to send the
> message to the server, and back off while that happens. It still
> seems to
> want to do it on the client side via marshalling, but I'm new
> enough to this
> I could be on total crack. :slight_smile:

If you could reduce your failure to something that is easily
distributable, I could help more.

That's definitely not out of the question. I'll see if I can hack it down to
something reasonable that shows the behavior, and if so, I'll send it your
way.

···

On Saturday 27 August 2005 03:03, Eric Hodel wrote:

(Eric Hodel) #12

Even if you mark a class as Undumped, objects generated by the class
may be marshaled and returned across the wire.

Hmmm... Maybe I'm simply using the wrong technology? I really just need
messages sent, and exceptions tossed back if they happen. Would this be
better suited to TCP/IP directly by chance?

If you want messages and exceptions, you may end up implementing half of DRb to get what you want, depending on what features you want to support.

Your problem seems to be that something is marked as shared that shouldn't be. Remember both sides of the connection attempt to Marshal things. DRb is best described as server-server rather than client-server.

···

On 27 Aug 2005, at 06:54, Kevin Brown wrote:

On Saturday 27 August 2005 03:03, Eric Hodel wrote:

If you could reduce your failure to something that is easily
distributable, I could help more.

That's definitely not out of the question. I'll see if I can hack it down to
something reasonable that shows the behavior, and if so, I'll send it your
way.

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

(Kevin Brown) #13

>> Even if you mark a class as Undumped, objects generated by the class
>> may be marshaled and returned across the wire.
>
> Hmmm... Maybe I'm simply using the wrong technology? I really
> just need
> messages sent, and exceptions tossed back if they happen. Would
> this be
> better suited to TCP/IP directly by chance?

If you want messages and exceptions, you may end up implementing half
of DRb to get what you want, depending on what features you want to
support.

Your problem seems to be that something is marked as shared that
shouldn't be. Remember both sides of the connection attempt to
Marshal things. DRb is best described as server-server rather than
client-server.

Alright. Today I just included the classes directly so work could proceed on
the project. Tomorrow I'll change the two lines to get DRb back in the
picture, and I'll hack my brains out. Thank you very much for your help!

···

On Saturday 27 August 2005 16:31, Eric Hodel wrote:

On 27 Aug 2005, at 06:54, Kevin Brown wrote:
> On Saturday 27 August 2005 03:03, Eric Hodel wrote:

>> If you could reduce your failure to something that is easily
>> distributable, I could help more.
>
> That's definitely not out of the question. I'll see if I can hack
> it down to
> something reasonable that shows the behavior, and if so, I'll send
> it your
> way.

(Kevin Brown) #14

You totally win. I sat down to start dinking with it, marked User as
DRbUndumped, and life was good.

THANK YOU!!!

···

On Saturday 27 August 2005 16:31, Eric Hodel wrote:

On 27 Aug 2005, at 06:54, Kevin Brown wrote:
> On Saturday 27 August 2005 03:03, Eric Hodel wrote:
>> Even if you mark a class as Undumped, objects generated by the class
>> may be marshaled and returned across the wire.
>
> Hmmm... Maybe I'm simply using the wrong technology? I really
> just need
> messages sent, and exceptions tossed back if they happen. Would
> this be
> better suited to TCP/IP directly by chance?

If you want messages and exceptions, you may end up implementing half
of DRb to get what you want, depending on what features you want to
support.

Your problem seems to be that something is marked as shared that
shouldn't be. Remember both sides of the connection attempt to
Marshal things. DRb is best described as server-server rather than
client-server.

(Eric Hodel) #15

:slight_smile:

···

On 28 Aug 2005, at 18:35, Kevin Brown wrote:

You totally win. I sat down to start dinking with it, marked User as
DRbUndumped, and life was good.

THANK YOU!!!

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

(bww00amdahl@yahoo.com) #16

Eric,
Would you share your code ???
Thanks
Bryan Webb
Eric Hodel wrote:

···

On 28 Aug 2005, at 18:35, Kevin Brown wrote:

> You totally win. I sat down to start dinking with it, marked User as
> DRbUndumped, and life was good.
>
> THANK YOU!!!

:slight_smile:

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

(Kevin Brown) #17

Eric,
Would you share your code ???
Thanks
Bryan Webb

Do you mean my code? It's actually a commercial app, so I can't share the
code in its entirety, but I can create a set of classes and such that have
the same relationships as my code, and that would probably be as good of an
example as any...

···

On Tuesday 30 August 2005 10:11, bww00amdahl@yahoo.com wrote:

Eric Hodel wrote:
> On 28 Aug 2005, at 18:35, Kevin Brown wrote:
> > You totally win. I sat down to start dinking with it, marked User as
> > DRbUndumped, and life was good.
> >
> > THANK YOU!!!
> >
> :slight_smile:
>
> --
> Eric Hodel - drbrain@segment7.net - http://segment7.net
> FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04

(bww00amdahl@yahoo.com) #18

Kevin,
Whatever you can shre would be great.

Thanks
bryan Webb

Kevin Brown wrote:

···

On Tuesday 30 August 2005 10:11, bww00amdahl@yahoo.com wrote:
> Eric,
> Would you share your code ???
> Thanks
> Bryan Webb

Do you mean my code? It's actually a commercial app, so I can't share the
code in its entirety, but I can create a set of classes and such that have
the same relationships as my code, and that would probably be as good of an
example as any...

> Eric Hodel wrote:
> > On 28 Aug 2005, at 18:35, Kevin Brown wrote:
> > > You totally win. I sat down to start dinking with it, marked User as
> > > DRbUndumped, and life was good.
> > >
> > > THANK YOU!!!
> > >
> > :slight_smile:
> >
> > --
> > Eric Hodel - drbrain@segment7.net - http://segment7.net
> > FEC2 57F1 D465 EB15 5D6E 7C11 332A 551C 796C 9F04