Archived

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

uncheckedCast vs. checkedCast

Hi there,

I thought I understood the concept. But...

Can you please tell me if uncheckedCast does any invocation to the respective servant? I.e., will it return 0 if the servant is not available and return != 0 if the servant (in case of uncheckedCast: any servant on that port) is present?

Until this evening I thought that uncheckedCast would not invoke anything on the servant's side at all, i.e. returning always != 0.

Could you help me out of the confusion?

regs,

Stephan

Comments

  • mes
    mes California
    Hi Stephan,

    The uncheckedCast function never makes a remote invocation. It assumes that the caller knows that it is safe and always returns a non-nil proxy (assuming the input argument is not nil).

    Take care,
    - Mark
  • Hi mes,
    The uncheckedCast function never makes a remote invocation.

    thanks for your answer. That was what I was assuming. I was just wondering because I received a 0 proxy (0 pointer) for a stringToProxy()/ uncheckedCast() call. I was probably mix that up with the stringToProxy() returning 0 because of the unavailable servant, right?

    regs,

    Stephan
  • mes
    mes California
    The stringToProxy function only returns 0 if the stringified proxy is an empty string; if any sort of error occurs, such as a parsing error, it raises an exception. Like uncheckedCast, it is strictly local in scope and does not make remote invocations.

    Was your argument to stringToProxy an empty string?

    Take care,
    - Mark
  • Hi Mark!
    Was your argument to stringToProxy an empty string?

    No, it wasn't. It was a usual connect string: "objectname:default -h 127.0.0.1 -p 6000" but the return value for this is definitely 0.

    Maybe, I can modify my original question a bit. The scenario is that I have an arbitrary number of computers with one servant per machine (same type of servant).

    Now I want to check as fast as possible if the machine is up and running (respectively if the servant is reachable). To do so, I do a stringToProxy() (in case I don't have no proxy handle yet) and then do either an ice_ping() or a checkedCast(). Before I do so, I cast to a timeout handle in order not to wait for too long.

    I.e. (meta)

    obj = stringToProxy()

    // version 1
    obj = timeoutCast(obj, 3 seconds)
    obj->ice_ping()

    // version 2
    obj = timeoutCast(obj)
    myObj = checkedCast(obj)

    and then see if an exception is raised. However, even with a timeout cast, the sychronous approach takes 3 seconds in the worst case. I instantiated 500 objects on one machine for testing purpose and if they are not available any more, the server is blocked for quite some time (3 * 500 = 1500 = 25 minutes :) ).

    The options I see are:
    1. make the checkMachineStates() function a oneway function, i.e. the call of this function will not lead to blocking the caller
    2. implement an asynchronous ping function using AMI to allow multiple ping calls at once (however, this option is currently not existing through the 0 pointer phenomenon).

    If you imagine better performing ideas, I'd love to hear more about them :)

    Thanks a lot in advance!

    Stephan
  • mes
    mes California
    Stephan,

    If you can provide a small, self-contained example that demonstrates the stringToProxy problem, I'd be happy to take a look at it.

    Please also specify the Ice version, your platform and compiler.

    Take care,
    - Mark
  • Hi again and thanks for taking care!

    Unfortunately, I cannot provide a self-contained example currently but at least copy the portion of code where the problem arises:


    std::string connString = std::string("myobject:default ")
    + std::string("-h ") + (*it).szHostIp
    + std::string(" -p ") + (*it).szPortNo;

    CMyObjectPrx client = 0;
    try
    {
    Ice::CommunicatorPtr comm = current.adapter->getCommunicator();
    Ice::ObjectPrx obj = comm->stringToProxy(connString);
    obj = Ice::ObjectPrx::uncheckedCast(obj->ice_timeout(3100));

    if (checkExistence)
    {
    if (obj)
    client = CAAClientPrx::checkedCast(obj);
    (*it).nStatus = PresentStatus;
    }
    else
    {
    MyLog("Connect string is: %s. Pointer is: %p",
    connString.c_str(),(*it).clientProxy);
    client = CAAClientPrx::uncheckedCast(obj);
    (*it).nStatus = UnknownStatus;
    }
    }
    catch (const Ice::Exception &e)
    {
    MyLog("resolveClient(): Error retrieving client object handle (host = '%s'). \
    Message: %s",
    (*it).szLogicalHostname.c_str(),
    e.ice_name().c_str());
    (*it).nStatus = AbsentStatus;
    }
    catch (const char* msg)
    {
    MyLog("resolveClient(): Error retrieving client object handle (host = '%s'). \
    Message: %s",
    (*it).szLogicalHostname.c_str(),
    msg);
    (*it).nStatus = AbsentStatus;
    }


    I'm holding a list containing a client information structure here, the host is e.g. 127.0.0.1 and let the port be 6000. "checkExistence" is a boolean parameter to the function which leads to a type check of the servant, i.e. is slower but more safe.
    I'm referring to the output that is outputted when checkExistence is false.

    For the platform: I'm using Ice 2.0 and MS Visual C++ 2003 on Windows XP here.

    I hope the information is of value. btw: Do you have a recommendation for checking the existence of large number of objects as mentioned in my previous mail?

    cheers,

    Stephan
  • mes
    mes California
    Stephan,

    I don't see anything in the code that would cause stringToProxy to return 0. Are you absolutely certain that this is happening? For example, you could add the following line after the call to stringToProxy:

    assert(obj);

    Note that it is not necessary to call Ice::ObjectPrx::uncheckedCast on the return value of ice_timeout, because ice_timeout always returns an instance of Ice::ObjectPrx.

    So unless you can provide an example that allows me to reproduce this behavior, or unless you can step into the Ice run time with the debugger to identify where the failure occurs, I'm afraid I can't be of much help on this issue.

    Regarding your performance question: If the server is running then the response to a call to ice_ping or checkedCast should be quite fast. If the server is not running, then essentially you are at the mercy of the operating system's TCP stack in terms of the delay involved in attempting to establish a connection. Setting a timeout is a good idea, but you could probably set it much lower than 3s and still be safe.

    Also be aware that Ice automatically retries (once, by default) if a connection failure occurs, which can be seen if you set Ice.Trace.Retry=2. You can disable automatic retries by setting Ice.RetryIntervals=-1, but note that this setting affects all retries and there is no way to control retries on a per-proxy basis.

    Take care,
    - Mark
  • Mark,

    it's even more funny. I was always printing using '%p' which I'm used to. However, for some reason, what is printed there seems to have nothing to do with the actual value of the proxy. I.e., if I do if (obj) MyLog("It exists!"); it is recognized that obj is not 0.

    If I do MyLog("%p", obj);, still '0' is printed. Strange, eh? But that should not be about Ice at all. So sorry for bugging you with that and thanks a lot for your help!!

    However, for me the thread was quite useful as I have a recommendation for proceeding with the pinging. Could you tell me a timeout value that makes sense? I mean, 1 second would still mean 1 * 500 = 8 minutes to go for scanning. It's better, but still bad enough :) Would an asynchronous implementation like

    ["ami"] void asyncPing();

    improve or do you see other limitations in it?
    In this case, I would set the client state in the response respectively exception functions of the respective callback class.
    As far as I understand, the thread pool is used automatically by Ice internally and thus lots of pings are performed at the same time and the other ones are queued.
    So I would have an almost immediate return after calling 'asyncPing()' on 500 objects.

    Another chance I see would be to use a separate thread to (continously) ping the clients in the client list. This would also prevent interference between other tasks of the server and the status gathering.

    cheers,

    Stephan
  • mes
    mes California
    Originally posted by stephan
    Mark,

    it's even more funny. I was always printing using '%p' which I'm used to. However, for some reason, what is printed there seems to have nothing to do with the actual value of the proxy. I.e., if I do if (obj) MyLog("It exists!"); it is recognized that obj is not 0.

    If I do MyLog("%p", obj);, still '0' is printed. Strange, eh? But that should not be about Ice at all. So sorry for bugging you with that and thanks a lot for your help!!
    You should have used this instead:

    MyLog("%p", obj.get());

    Regarding the ping issue: it's still not clear to me exactly what the application is doing. It sounds like your server is attempting to ping an arbitrary number of objects in response to a request from a client. If it is necessary to update the machine states continuously (and not just once, such as when the server starts up), then your idea of using a separate thread sounds reasonable to me.

    Take care,
    - Mark