Archived

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

IcePack/Query documentation?

Hi!
We are currently trying to obtain all proxies registered with an IcePack registry by using the IcePack/Query facility. Unfortunately we had to deduce nearly everything from one of the examples. We'd like to use findAllObjectsWithType(), but we do not even get the QueryPrx object checkedCast()ed.
Since there is not very much documentation to be found, we would really appreciate some information, specifically about what configuration options are needed to influence the behaviour and usage of the query facility (like, do we need to set an endpoint as for the IcePack/Locator?).
Thanks in advance!

Regards,
Ingmar

Comments

  • benoit
    benoit Rennes, France
    Hi,

    The IcePack::Query and IcePack::Locator interfaces are both accessible through the IcePack.Registry.Client endpoints. Your client only needs the Ice.Default.Locator property to be set to a valid locator proxy to acccess the IcePack::Query interface. The configuration of the IcePack registry is explained in the manual (section 20.5).

    For example, if your IcePack registry is configured with the IcePack.Registry.Client.Endpoints="tcp -p 12000 -h myhost.mydomain.com" property, your client needs to be started with the property Ice.Default.Locator="IcePack/Locator:default -p 12000 -h myhost.mydomain.com".

    Once this is correctly configured, you should be able to get the IcePack/Query interface in your client by doing something like this:
    IcePack::QueryPrx query = IcePack::QueryPrx::checkedCast(communicator->stringToProxy("IcePack/Query"));

    If the checked cast doesn't work, most likely, you have a configuration problem. Is your locator proxy correctly configured? Is the IcePack registry client endpoint accessible to your client? You should be able to figure this out by starting your client with the Ice.Trace.Network=1 and Ice.Trace.Location=1 properties. If you send us the output of this tracing information along with the configuration files you are using for your client and IcePack registry, we should be able to figure out what's wrong.

    Benoit.
  • Hi Benoit,

    thanks for the advice so far. It was indeed a configuration problem, but it happened in our initialization code. So the query proxy is really not a problem.

    But a question still remains: The string argument that is passed to findAllObjectsWithType(string) denotes the type of the objects to be found. But how is this type defined? In an example we saw that "::Hello" was used as the type. Am I right if I assume that this does directly correspond to a class name in Slice?

    Respects,
    Ingmar
  • Hi again,

    sorry for bothering so much. I've just found it in the documentation, chapter 4.12, 'Type IDs'. What still is not clear is with which Slice constructs does this work in conjunction with findAllObjectsWithType(). I am confused about whether I should use an interface or a class or an interface implemented by a class.
    The Slice definition currently looks like this:

    sequence<int> IntSeq;
    sequence<double> DoubleSeq;

    interface Solver
    {
    void initialize(IntSeq matrix1, IntSeq matrix2);
    void finalize();
    void setIndices(IntSeq ints1, IntSeq ints2, IntSeq ints3);
    void setWeights(DoubleSeq weights);
    void setCuts(IntSeq cuts);
    void setActive(IntSeq active);
    ["ami"]void solve(DoubleSeq coeff, DoubleSeq rhs, double res, out DoubleSeq x);
    };

    Implementation is done by extension of the generated class:
    class SolverImpl : public Solver
    {...}

    After successfully registering the adapter, I tried to use icepackadmin to find the object by type, like ::Solver or ::SolverImpl, but none of it worked. Same with "class Solver" in the Slice definition. I would really appreciate any hints about this. Is it crucial to use a class with a factory?

    Ingmar
  • benoit
    benoit Rennes, France
    Sorry for the late answer. Objects are not registered automatically, this is something you have to do either manually (with the icepackadmin admin tool) or by specifying the objects you want to be registered in the XML deployment descriptors. Registering an object adapter with IcePack won't cause all the objects from the object adapter to also be registered with the IcePack object registry.

    To register your objects using a deployment descriptor, you should declare object elements inside the adapter element:
    <adapter name="MyAdapter" endpoints="tcp">
    <object identity="MyCategory/MyName" type="::Solver"/>
    </adapter>

    This will register the object with the stringified "MyCategory/MyName" identity and the type "::Solver" with the IcePack object registry. You should then be able to find the object by type with the icepackadmin tool or the IcePack::Query interface.

    The type should be the Slice type id (there's actually no validation right now so it could be anything but this might change).

    Benoit.
  • Ah, thanks, that really helped a lot to understand what is going on. If I get this right, this is done manually in your IcePack/hello demo factory implementation:

    IcePack::AdminPrx admin = IcePack::AdminPrx::checkedCast(communicator->stringToProxy("IcePack/Admin"));
    admin->addObject(object);

    I believe this is the way that induces the least 'Ice infrastructure overhead' like XML descriptors, which is what we want to achieve.

    Regards,
    Ingmar
  • benoit
    benoit Rennes, France
    Right, you can also register objects with the IcePack::Admin interface (the admin interface is accessible through the IcePack.Registry.Admin endpoints -- make sure these endpoints are accessible to your application). You can also use the icepackadmin "object add" command to register an object.

    Benoit.
  • Okay, object adding works very well. However, a new problem arises: suddenly, I am not able to obtain the Query proxy. It worked already, now it does not anymore. The configuration file is used for both the registry machine and the 'client' machine that starts the Solver:

    # icepackregistry location
    Ice.Default.Locator=IcePack/Locator:default -p 42000 -h harlekin.first.fraunhofer.de

    #
    # Solver configuration
    #
    SolverAdapter.AdapterId=Solver01
    SolverAdapter.Endpoints=default

    #
    # IcePack registry configuration.
    #
    IcePack.Registry.Client.Endpoints=tcp -p 42000 -h harlekin.first.fraunhofer.de
    IcePack.Registry.Server.Endpoints=default
    IcePack.Registry.Admin.Endpoints=tcp -p 41000 -h harlekin.first.fraunhofer.de
    IcePack.Registry.Data=db
    IcePack.Registry.DynamicRegistration=1

    #
    # be extremely verbose
    #
    Ice.PrintAdapterReady=1
    Ice.Trace.Location=1
    IcePack.Registry.Trace.ServerRegistry=1
    IcePack.Registry.Trace.AdapterRegistry=1
    IcePack.Registry.Trace.ObjectRegistry=1
    Ice.Trace.Network=1

    The outputs from the registry show that everything registers well and is up and running. When starting a test program (client machine) that tries to get the Query proxy and then the objects, it says:

    [ ClusterCommunicator: Location: couldn't contact the locator to retrieve adapter endpoints
    object = IcePack/Query
    reason = Network.cpp:447: Ice::ConnectFailedException:
    connect failed: Connection refused ]
    [ ClusterCommunicator: Location: couldn't contact the locator to retrieve adapter endpoints
    object = IcePack/Query
    reason = Network.cpp:447: Ice::ConnectFailedException:
    connect failed: Connection refused ]

    ... and the registry does not show any network activity (I also tried to set the networking tracing level to 3).
    Maybe I should just go home and sleep some time, but if it is just a small bug, I would be very grateful for a last hint.

    Ingmar
  • benoit
    benoit Rennes, France
    Somehow, your client can't establish a network connection to the IcePack registry. Your configuration looks fine. Can you set Ice.Trace.Network to 2 instead 1? The client should trace the network connection attempt to the registry and you should see on which address/port it's trying to connect to.

    Are the client and IcePack registry running on the same host? Do you perhaps have a problem with DNS lookup? You could try to replace the hostnames with numeric addresses to rule out DNS problems.

    Benoit.
  • It was a fault in the code, again. Configuring Ice inside the application is generally a bad idea and is only necessary with this specific application.
    Now my (hopefully) last question: Is it possible to use the same object adapter (created by the first Solver application) for the objects of the other Solver applications? The way the application is configured now there is one AdapterId=Solver01, and for any additional Solver application there has to be another AdapterId. Is it possible to handle this without XML descriptors?
    From the documentation I know that normally multiple servants will be registered with an adapter before activating it, but what we want to do is registering additional servants after activation of the adapter.

    Regards,
    Ingmar
  • benoit
    benoit Rennes, France
    Originally posted by rbx
    It was a fault in the code, again. Configuring Ice inside the application is generally a bad idea and is only necessary with this specific application.
    Now my (hopefully) last question: Is it possible to use the same object adapter (created by the first Solver application) for the objects of the other Solver applications? The way the application is configured now there is one AdapterId=Solver01, and for any additional Solver application there has to be another AdapterId. Is it possible to handle this without XML descriptors?

    I'm not sure I see what a "Solver application" is. Are these applications sharing the same object adapter instance in a single process?

    If that's the case, I don't see any problems with registering several time the ::Solver interface/class with the same object adapter as long as they are registered with different identities (the object adapter will prevent you anyway from registering several servant with the same identity).

    If you mean several processes where in each processes you register the ::Solver interface with the process object adapter, you effectively have different object adapters so each object adapter needs to be registered with a different AdapterId with the IcePack registry (each object adapter has different endpoints, they are listening on different TCP/IP ports for instance).

    From the documentation I know that normally multiple servants will be registered with an adapter before activating it, but what we want to do is registering additional servants after activation of the adapter.

    Regards,
    Ingmar

    You don't have to register all your servants before the object adapter activation, it's fine to register servants after the object adapter activation.

    Let me know if this still not clear!

    Benoit.
  • There is the problem. A Solver is a working entity, in Ice terms, a servant. But there are lots of them, and we just want them all to be registered; we already know how to have each of them a different identity. Every Solver runs as a process on it's own PC but we do not want to configure each of them manually by editing lots of configuration files and setting different AdapterIds.

    Maybe I can put the question differently. Is there a way to set the AdapterId inside the Ice application code? Each Solver has a specific number that is used to set different object identities. We could use that to generate different AdapterId strings.

    Another thought that occurred to me was to use the ability of an adapter to have multiple endpoints, but from you and other posts here I understand that having several processes means having several adapters; multiple endpoints are there to allow requests to be sent to several endpoints. This is quite clear if I understand the functionality of the adapter as described in the documentation. So this seems to be no option.

    Ingmar
  • benoit
    benoit Rennes, France
    Originally posted by rbx
    There is the problem. A Solver is a working entity, in Ice terms, a servant. But there are lots of them, and we just want them all to be registered; we already know how to have each of them a different identity. Every Solver runs as a process on it's own PC but we do not want to configure each of them manually by editing lots of configuration files and setting different AdapterIds.

    Maybe I can put the question differently. Is there a way to set the AdapterId inside the Ice application code? Each Solver has a specific number that is used to set different object identities. We could use that to generate different AdapterId strings.

    Sure, you can set the AdpaterId property programatically, something like the following should do:
    Ice::PropertiesPtr properties = communicator->getProperties();
    properties->setProperty("MyAdapterName.Endpoints", "tcp");
    properties->setProperty("MyAdapterName.AdapterId", "Adapter01");
    communicator->createObjectAdapter("MyAdapterName");

    This will create an object adapter with a TCP/IP endpoint and the AdapterId "Adapter01". It's important to set the properties before the creation of the object adapter. Also, note that the adapter id shouldn't be a generated UUID since otherwise each time you restart your server, a new adapter id will be registered with the IcePack registry and the IcePack adapter registry will always grow.

    Another thought that occurred to me was to use the ability of an adapter to have multiple endpoints, but from you and other posts here I understand that having several processes means having several adapters; multiple endpoints are there to allow requests to be sent to several endpoints. This is quite clear if I understand the functionality of the adapter as described in the documentation. So this seems to be no option.

    Ingmar

    An adapter can have multiple endpoints but I don't think this is what you need here. I assume you are referring to the ability to have a proxy with multiple endpoints instead. Yes, that's another possibility. Basically each of your server object adapter would listen on a given endpoint. Each server would have a ::Solver object which is registered with the same identity. So for example:
    • Server01 would have an object with the identity "Solver" and an object adapter listening on host named "a.host.com" port 10000
    • Server01 would have an object with the identity "Solver" and an object adapter listening on the host named "b.host.com" port 10000

    To contact one of the Solver object, your client would use the stringified proxy "Solver:tcp -h a.host.com -p 10000:tcp -h b.host.com -p 10000". The Ice runtime will randomly choose an endpoint to invoke on the "Solver" object. This approach might be easier for you since you don't even have to use IcePack. However, this means that each server needs to listen a fixed endpoint and your client needs to know each server endpoint.

    Benoit.
  • Yes, the first one looks exactly like what we need. Thank you very much for pointing this out! I'll see whether I run into bigger problems again, but this looks very good.

    Regards,
    Ingmar