Archived

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

Problems 3.1 client --> 3.2 server

Hello,

We have just updated to v3.2 of ICE, though we have an existing C++ client API that uses the 3.1 framework that still needs to be supported. So far this client is unable to unpack any data successfully.

Our C# clients using either 3.1 or 3.2 versions of ICE appear to work end to end against this 3.2 server.

This is the exception received..

ProtocolException:
_file 0x007266bc "f:\src\vc60\stage\Ice-3.1.1\src\ice\BasicStream.cpp"
_line 398
reason "" (just empty string)

The exception is thrown when making the following call in the auto generated wrapper:

__is->readPendingObjects();

Where:

::IceInternal::BasicStream* __is = __og.is();


Has anyone got any ideas?

cheers
James

Comments

  • mes
    mes California
    Hi James,

    A few questions for you:
    • What language is your server written in?
    • Is your server now using Ice 3.2?
    • Is your C++ client communicating directly with the server, or does it use Glacier2?
    • Do you have the complete stack trace where the exception occurs?
    • Can you show us the relevant Slice definitions of the operation being invoked when this exception occurs?
    Thanks,
    - Mark
  • mes
    mes California
    One other thing: Are you certain that your C++ client and your server are using the same Slice definitions?

    - Mark
  • Hi Mark, thanks for answering. In answer to your questions;

    Our server is C# .NET 2.0 and is using Ice 3.2.
    The server does appear to process requests from this particular client and no errors are reported/logged there.

    Our C++ 3.1 client is communicating directly with the server, we haven't used any Glacier/Grid, etc. functionality in this application.

    Acually, your last point about slice defs got me thinking and this could be where the problem indeed lies.
    A month or so ago, we updated a small section of our slice definition and released to some integration test servers using Ice 3.1. All testing was successful with our .NET clients (e.g. those with newer slice defs and those with older slice defs). We still have these test servers in place so I pointed the problematic C++ client (with the old slice defs) to this server and it blew up with the same way as reported earlier. A
    protocol exception.

    So Ice 3.1 --> 3.2 does not appear to be the issue any more. It is now why do .NET clients with older slice defs communicate successfully with a server utilising newer slice defs, when our C++ equivalent does not?

    The slice definitions were extended like below.

    /******************************************************
    Version 2 changes
    ****************************/
    module SliceV2{

    class TsrIceEnrichedFieldDef extends Slice::TsrIceEnrichedFieldDef {
    bool IsFixedSchema;
    };

    interface ITsrQueryDistributor extends Slice::ITsrQueryDistributor {
    };
    };

    The hosted server implementation was defined like so

    public class TsrQueryDistributorImpl : SliceV2.ITsrQueryDistributorDisp_, IDistributorInitialisable
    {
    .....
    }

    And we used 2 facets, like so...

    string identity = "";
    TsrQueryDistributorImpl distributor = new TsrQueryDistributorImpl();

    adapter.addFacet((IceObject) distributor, communicator().stringToIdentity(identity), ""); //default
    adapter.addFacet((IceObject) distributor, communicator().stringToIdentity(identity), "v2");


    Clients using the old slice defs would use the default empty string facet. The C++ code to instantiate the proxy is below..

    // create the proxy to the server
    Ice::ObjectPrx base = (*((Ice::CommunicatorPtr*)(_pDistributorProxy->GetIceCommunicator())))->
    stringToProxy(_connectionString);

    _pQueryProxy = new Slice::ITsrQueryDistributorPrx();

    *(_pQueryProxy) = Slice::ITsrQueryDistributorPrx::uncheckedCast(base);


    Have you got any ideas?


    cheers
    James
  • matthew
    matthew NL, Canada
    From this description what you've done should work. However, you haven't really shown enough of the code or slice definitions to try and isolate the cause of the problem. Your C++ & C# code looks pretty strange also:
    string identity = "";
    TsrQueryDistributorImpl distributor = new TsrQueryDistributorImpl();
    
    adapter.addFacet((IceObject) distributor, communicator().stringToIdentity(identity), ""); //default
    adapter.addFacet((IceObject) distributor, communicator().stringToIdentity(identity), "v2");
    

    I assume the identity is really not the empty string. Why the cast when adding the servant?
    // create the proxy to the server
    Ice::ObjectPrx base = (*((Ice::CommunicatorPtr*)(_pDistributorProxy->GetIceCommunicator())))->
    stringToProxy(_connectionString);
    

    Why all the casting?
    _pQueryProxy = new Slice::ITsrQueryDistributorPrx();
    *(_pQueryProxy) = Slice::ITsrQueryDistributorPrx::uncheckedCast(base );
    

    This is never necessary... proxies are created by the Ice runtime, not by your code in this manner. This code should be:
    _pQueryProxy = Slice::ITsrQueryDistributorPrx::uncheckedCast(base );
    

    What do you do with the proxy once you've narrowed it? Are you sure you didn't accidently change a V1 interface?

    With all of the casting and unnecessary memory management I wouldn't be surprised if your C++ code has some nasty problem lurking.
  • Thanks for the input,

    yep, as you point out the identity isn't really empty string, I just removed the actual value to male the example a little clearer. I guess that it didn't work. :( Similarly, the casting when adding the servant is a hangover from converting working code to example code. Sorry. All the servants to be hosted are stored in a .NET 1.1 dictionary and needed casting from object type, like so
    IDictionary _servants;
    (...populate _servants...)
    
    foreach (string identity in _servants.Keys)
    {
    	adapter.addFacet((IceObject) _servants[identity], communicator().stringToIdentity(identity), ""); //default
    	adapter.addFacet((IceObject) _servants[identity], communicator().stringToIdentity(identity), "v2");
    }
    


    As you point out the c++ code base is not optimal though, I will have to look at it a bit more closely.

    regards
    James