Archived

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

How to use ADAPTER more efficiently?

Hi.

We want to supply a number of services by several processes running on one PC server. And every process we create has to occupy a port when we "createObjectAdapter".

We wonder how to user adapter more efficiently? Can we make an adapter shared by several processes? But we cannot find the function to retrieve the existing adapter. Retrieve adapter by its name? Or there are reasons for what processes cannot share an adapter?

Very thanks for your help

Comments

  • matthew
    matthew NL, Canada
    An adapter has one or more endpoints. One of the standard and most used communication endpoints with Ice is a TCP/IP endpoint. Several processes cannot share a port, that's a fundamental limitation of TCP/IP.

    An alternative would be to bundle all your services into the same process. You might want to look at IceBox to provide you with a convenient infrastructure for this.
  • Thank you for reply.

    And I also want to know whether there is a way to retrieve an existing adapter by its name or identity or something else?
    Maybe it cannot be true, but if I does not use a variant to store the adapter after I create it, how can I retrieve it?

    Another question is that when I "createObjectAdapterWithRouter", there is no definite endpoint. I have tried to get proxy of a service supplied by that adapter with the IP and port of Router, but it didn't work.
    So the problem is: If the Adapter created by Router does not send proxies of its servants actively, how can clients request for services?

    Thanks again.
  • matthew
    matthew NL, Canada
    Once created there is no way to retrieve an adapter from the communicator. You have to remember it. Within a dispatched method on a servant you can get the current adapter from the Ice::Current parameter.

    With respect to routed endpoints I'm not really sure what you mean. Could you give a concrete example of the problem?
  • Just like these codes:
    //////
    Glacier2::RouterPrx _router
    = Glacier2::RouterPrx::checkedCast(_ComPtr->stringToProxy(strAddress));
    _router->createSession(name, pwd);

    _adapter = _ComPtr->createObjectAdapterWithRouter("Adapter", router);
    ObjectPrx _objPrx = _adapter->add(new Object, id);
    //////

    If server do not send _objPrx to clients, how can clients get it?
    We have tried to request ObjectPrx remotely using 'strAddress' and 'id', but it seemed not to work properly.

    Thank you.
  • matthew
    matthew NL, Canada
    Ok, while I think you could in theory construct the string proxy in the server backend to call to a glacier2 connected client I think its very impractical to do so, as the category field of the object-id changes on a per-session basis.

    Specifically in this case I suspect you have not done the following correctly:
    - Added the session category to the object identity. You must call router->getCategoryForClient() to get the session specific category.
    - You must use the glacier2 router server-side endpoints, not the client-side endpoints. You must use the contents of the Glacier2.Server.Endpoints, not Glacier2.Client.Endpoints.
  • Problems come out without an end while project goes on ...

    I have an interface below:
    //////
    interface Subscription
    {
    bool Login(string Account);
    void Logout(string Account);
    };
    //////

    I use it to publish an topic:
    //////
    IceStorm::TopicPrx _topicPrx;
    ObjectPrx _publisherPrx;
    try
    {
    _topicPrx = g_App.m_TopicMngPrx->retrieve(TopicName);
    _publisherPrx = _topicPrx->getPublisher()->ice_oneway();
    }
    catch (const IceStorm::NoSuchTopic&)
    {
    try
    {
    _topicPrx = g_App.m_TopicMngPrx->create(TopicName);
    _publisherPrx = _topicPrx->getPublisher()->ice_oneway();
    }
    }
    SubscriptionPrx m_SubPrx = SubscriptionPrx::uncheckedCast(_publisherPrx);
    m_SubPrx->Logout(strAccount);
    m_SubPrx->Login(strAccount);
    //////

    The result is: Logout succeeded, but Login failed.
    Error is :"Ice::TwowayOnlyException"
    I think they should be okay even if there are no subscriber. But why one passed while the other failed?

    Thanks a lot for your patient
  • matthew
    matthew NL, Canada
    The exception is as it says... you cannot call methods that return results with a oneway proxy. Specifically, in your case you are trying to call "bool Login(string Account);" with a oneway proxy.

    To further compound the problem you cannot change the proxy to a twoway proxy, since you may only call oneway semantic methods (ie: no return values, or exceptions) through IceStorm. If you really need a response model then you either should not use IceStorm, or return the response to your client through some other mechanism such as an IceStorm back-channel, or another interface/proxy.

    For example, something like:
    interface LoginCallback
    {
       void loggedIn(string account);
    };
    
    interface Subscription
    {
    void Login(string Account, LoginCallback* cb);
    void Logout(string Account);
    };
    
  • I am so sorry... I have noticed that when I read documents. But so many details are forgotten or even ignored...

    Thank you for your patient again.
  • I wonder whether it is proper to continue proposing my questions in this thread. But I don't think it is worth posting a new thread. So as below:

    //////
    Context ctx
    ctx["test"] = "test";
    _objPrx = _objPrx->ice_context(ctx);
    //////

    I use above codes to update the Context of a proxy.
    If I use _objPrx to invoke some functions, the server will get context from the special parameter "current".

    But once I send this updated proxy as a parameter to another servant, I find the context is lost. Why?
    And can we keep the context in a proxy?

    I want my server to update the proxies and send them to clients, so clients do not need to update proxies by themselves.

    Thanks a lot to Matthew.
  • matthew
    matthew NL, Canada
    The context is part of the local proxy data, and so does not follow the proxy over the wire. See my article "Proxies" in issue 23 for details http://www.zeroc.com/newsletter/issue23.pdf
  • Finally, pre-proxy contexts permit context information to be passed by
    through intermediate parts of a system without cooperation of those intermediate parts. For example, suppose you set a per-proxy context on a proxy and then pass that proxy to another system component. When that component uses the proxy to invoke an operation, the per-proxy context will still be sent. In other words, perproxy contexts allow you to transparently propagate information via intermediaries that are ignorant of the presence of any context.

    I copy this paragraph from User Manual 3.2.1 in 919 Page "32.11 The Ice::Context Parameter".
    I used to think it is possible to keep context in proxies. Would you please explain these words for me? Thank you very much.
  • arlmarse wrote: »
    I used to think it is possible to keep context in proxies. Would you please explain these words for me? Thank you very much.

    "System component" means some other part of your program, not some other, remote Ice server. If you set a context on a proxy and send the proxy over the wire, the context set on that proxy is *not* marshaled. In other words, contexts are ephemeral things that are local to a process, and are not intrinsically part of a proxy. If you stringify a proxy or transmit the proxy as a parameter of an invocation, any per-proxy context is lost.

    I will clarify this in the manual--thanks for pointing this out.

    Cheers,

    Michi.
  • matthew wrote: »
    Ok, while I think you could in theory construct the string proxy in the server backend to call to a glacier2 connected client I think its very impractical to do so, as the category field of the object-id changes on a per-session basis.

    Specifically in this case I suspect you have not done the following correctly:
    - Added the session category to the object identity. You must call router->getCategoryForClient() to get the session specific category.
    - You must use the glacier2 router server-side endpoints, not the client-side endpoints. You must use the contents of the Glacier2.Server.Endpoints, not Glacier2.Client.Endpoints.


    I have the same doubt!

    how to call ice-object which live in the router-adapter from another program which run at the same computer?
    the question for the cause of I can't know the router-adapter ports-settings.
  • matthew
    matthew NL, Canada
    I'm sorry, I don't understand your question. Here is a typical setup:
    Client <- C1 -> Router/Glacier2 --  C2 -> Server(s)
                                   <- C3  --
    

    Normally the Client, Glacier2 & the backend servers(s) all run on separate machines. The client talks to Glacier2 through a connection. If the client supports callback objects this connection will be bi-directional (in this case C1). Glacier2 talks with the server over connection C2. If the server(s) call back on the client then the, the server will use a separate connection, C3.

    What exactly is the case you are talking about?
  • "Client <- C1 -> Router/Glacier2 -- C2 -> Server(s)
    <- C3 --"


    my doubt just in client (one machine);

    I create adapter with router and add several object in the adapter,then another executable program which also run in the client can not touch the objects because of I can not know the adapter's ports-settings

    Accessing a proxy through character string "object:default -p ????"
  • matthew
    matthew NL, Canada
    Do you want the calls to go through the router? I would assume not, they should go directly to the client. Assuming that is the case then you should create an non-routed object adapter in the client, and publish the same objects through that OA. Then the second client that resides on the same machine would use the non-routed OA for direct communications to the client.
  • thanks for reply!

    then i use communicator()->stringtoproxy("object:tcp -p 10000"),does it resolve the the string like that "object:tcp -h 127.0.0.1 -p 10000"?

    if yes,

    My system's framework is that :

    client2 -> client1 -> router/glaciser ->server
    ↓ *************↑

    A server object proxy just leave in client1's care (the proxy is stored in an Ice object that reside in client1's OA);client2 will get the proxy for a while and communicate directly with server object;

    my question is "how to use client2's communicator that with Glaciser2/router to get the proxy?"
  • xdm
    xdm La Coruña, Spain
    Hi Leo

    Not sure if i understand well your problem.

    You have two client applications in the same machine and you want C2 be able to call C1, also C2 do not know C1 endpoints.

    Is the above sentence right?

    If both clients are intended to run always in the same machine, i think the simple solution can be that C1 write the endpoints it use to some file when start and C2 read this on startup.

    If you want C1 and C2 to be able to run in different machines, you can use indirect proxies better. For example C1 can register a well know object with IceGrid on startup and C2 create a proxy from a well know id that would point to the correct object.

    Without much details of what you are trying to archive is difficult to give you better advice.


    Hope this help
  • thank you for your help!

    give me try;

    Another problem is that:

    communicator that with router will resolve "-h 127.0.0.1" like Glaciser2 server IP,not localhost;

    So ,I can't request Localhost IO's proxy by communicator->StringToProxy("ObjectID:default -p portNo") function !
  • sorry ,I take a mistake above!

    communicator->StringToProxy("ObjectID:default -p portNo") function can find out localhost IO;

    but it cause another problem:
    the communicator with router how to request a IO's proxy ?

    How to find out localhost's and server's IO just by only a function that communicator->StringToProxy("ObjectID:default -p portNo") ?
  • matthew
    matthew NL, Canada
    I'm sorry, but your description is not very clear. However, if I understand you correctly the issue is that you want client1 to talk directly with client2

    I imagine that the problem you've run into is that then client1 tries to talk with client2, the request is routed through glacier2 (assuming that you have set Ice.Default.Locator, as the manual directs you to do).

    The solution here is to clear the router on the proxy by calling ice_router. Something like:
    ObjectPrx obj = ...; // some proxy that refers to client2.
    obj = obj->ice_router(0); // Clear the router.
    

    All calls on obj at this point are non-routed, and will NOT go through Glacier2.
  • thanks for reply.

    The problem has resolved!

    I just want to know : how the ICE's core run?
    The function of communicator()->StringToProxy("ObjectID:default -p portNo") can get server IO,also successful to get client IO without IP setting.
    why?(the server and the client have resided in different machine and the communicator have been set Ice.Default.Router)

    To this question is because my application run slowly when I use router.
  • matthew
    matthew NL, Canada
    I'm sorry, I'm not sure what you are talking about. You'll have to rephrase your question, or give a concrete example for us to help.