Archived

This forum has been archived. Please start a new discussion on GitHub.

Problem with replication in IceGrid

Hello!

I am testing the Ripper application to prove and learn all the functionality of IceGrid (see 36.4 section of the ICE documentation). I use ICE 3.1.1, Debian Sid, and Python 2.4.4.

I have the registry and a node running in a same host: the host Node1. However, I have a problem when I add another node: Node2, which runs in the same host but has another name and, therefore, another configuration file and another data directory.

This is the configuration file related to the configuration of the first node:
#Registry properties
IceGrid.Registry.Client.Endpoints=default -p 10000
IceGrid.Registry.Server.Endpoints=default
IceGrid.Registry.Admin.Endpoints=default
IceGrid.Registry.Internal.Endpoints=default
IceGrid.Registry.Data=registry

#Node properties
IceGrid.Node.Name=Node1
IceGrid.Node.Endpoints=default
IceGrid.Node.Data=node
IceGrid.Node.CollocateRegistry=1
IceGrid.Node.Trace.Activator=3
Ice.Default.Locator=IceGrid/Locator:tcp -h 127.0.0.1 -p 10000

This is the configuration file related to the configuration of the second node:
#Node properties
IceGrid.Node.Endpoints=tcp
IceGrid.Node.Name=Node2
IceGrid.Node.Data=node2
IceGrid.Node.Trace.Activator=3
Ice.Default.Locator=IceGrid/Locator:tcp -h 127.0.0.1 -p 10000

I am currently using Round Robin as my load balancing type.

My descriptors are specified in the following configuration file:
<icegrid>
  <application name="Ripper">

    <replica-group id="EncoderAdapters">
      <load-balancing type="round-robin"/>
      <object identity="EncoderFactory" type="::Ripper::MP3EncoderFactory"/>
    </replica-group>

    <server-template id="EncoderServerTemplate">
      <parameter name="index"/>
      <parameter name="exepath" default="./Server.py"/>
      <server id="EncoderServer${index}"
        exe="${exepath}"
	activation="on-demand">
	<adapter name="EncoderAdapter"
	  replica-group="EncoderAdapters"
	  register-process="true"
	  endpoints="tcp"/>
      </server>
    </server-template>

    <node name="Node1">
      <server-instance template="EncoderServerTemplate" index="1"/>
    </node>

    <node name="Node2">
      <server-instance template="EncoderServerTemplate" index="2"/>
    </node>

  </application>
</icegrid>

And this is the relevant code of the Server:
class Mp3EncoderI (Ripper.Mp3Encoder):
    def encode (self, leftSamples, rightSamples, current):
        print 'Encoding...'
        return None

    def flush (self, current):
        print 'Flushing...'
        return None
    
class Mp3EncoderFactoryI (Ripper.Mp3EncoderFactory):
    def createEncoder (self, current):
        return Ripper.Mp3EncoderPrx.uncheckedCast(
            current.adapter.addWithUUID(Mp3EncoderI()))
                                        
class Server (Ice.Application):
    def run (self, argv):
        self.shutdownOnInterrupt()
        adapter = self.communicator().createObjectAdapter('EncoderAdapter')
        adapter.add(Mp3EncoderFactoryI(), Ice.stringToIdentity('EncoderFactory'))
        adapter.activate()
        self.communicator().waitForShutdown()
        return 0

Server().main(sys.argv)

As you see, I am only testing the IceGrid functionality.

I start the registry and the Node1 node, I start the Node2 node and, finally, I deploy the Ripper application. If a start a client, the server related to the Node1 node shows the textual message but, when I start a second client I obtain the following error:
Traceback (most recent call last):
  File "/var/lib/python-support/python2.4/Ice.py", line 524, in main
    status = self.run(args)
  File "Client.py", line 14, in run
    encoder.encode(None, None)
  File "Ripper.ice", line 62, in encode
ObjectNotExistException: exception ::Ice::ObjectNotExistException
{
    id =
    {
        name = 60CF5A6C-CB41-468E-B7DA-7599ADE72A4C
        category =
    }
    facet =
    operation = encode
}

As I use a round-robin based load balancing type, I know this fail is related to the Node2 node.

This is my simple client:
class Client (Ice.Application):
    def run (self, argv):
        self.shutdownOnInterrupt()
        obj = self.communicator().stringToProxy('EncoderFactory')
        ripper = Ripper.Mp3EncoderFactoryPrx.checkedCast(obj)
        encoder = ripper.createEncoder()
        encoder.encode(None, None)
        self.communicator().waitForShutdown()
        return 0

Client().main(sys.argv, 'client.cfg')

I suppose I do not take into account some question, but studying the documentation I have not found the answer to my problem.

I hope you could help me.

Thank you,
David.

Comments

  • benoit
    benoit Rennes, France
    Hi,

    You're registering the Encoder servant with an object adapter from a replica group (the `EncoderAdapter' adapter). By default, the object adapter creates proxies containing the replica group ID not the adapter ID.

    As a result, the proxy returned by the createEncoder method is "<uuid> @ EncoderAdapters" and when you invoke on the proxy, your client sends the request to the next replica (because of the round-robin load balancing).

    You should change the code that creates the encoder to:
    class Mp3EncoderFactoryI (Ripper.Mp3EncoderFactory):
        def createEncoder (self, current):
            Ice.ObjectPrx prx = current.adapter.addWithUUID(Mp3EncoderI());
            return Ripper.Mp3EncoderPrx.uncheckedCast(current.adapter.createIndirectProxy(prx.ice_getIdentity())
    

    See the Ice manual for more information on the Ice::ObjectAdapter::createIndirectProxy method.

    Cheers,
    Benoit.
  • Hello again!

    When I try to invoke the createIndirectProxy I obtain the following error:
    Traceback (most recent call last):
      File "./Server.py", line 20, in createEncoder
        return Ripper.Mp3EncoderPrx.uncheckedCast(current.adapter.createIndirectProxy(prx.ice_getIdentity()))
    AttributeError: 'ObjectAdapterI' object has no attribute 'createIndirectProxy'
    
    identity: EncoderFactory
    facet:
    operation: createEncoder
    

    I have review the ICE documentation and the name of the method is the same you specified.

    Any idea?
  • benoit
    benoit Rennes, France
    You found a bug in IcePy! The implementation of this method is unfortunately missing. We'll fix this for the next release.

    In the meantime, you should be able to use the following code as a workaround:
    class Mp3EncoderFactoryI (Ripper.Mp3EncoderFactory):
        def createEncoder (self, current):
            Ice.ObjectPrx prx = current.adapter.addWithUUID(Mp3EncoderI());
            string adapterId = current.adapter.getCommunicator().getProperties().getProperty(current.adapter.getName() + ".AdapterId")
            return Ripper.Mp3EncoderPrx.uncheckedCast(prx.ice_adapterId(adapterId))    
    

    Cheers,
    Benoit.