Archived

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

IcePatch2-Server adding new functionality

Hello, guys. I'm quite new to the all Ice stuff, so maybe my question is trivial but nevertheless:) I was going to add new functionality to IcePatch2. I implemented it that way, that every time the icepatch2client starts it calls a routine on the server side. For example the routine writes "Triggered" on the server side.

I have written a normal slice declaration for this procedure "myTriggerFilesUpdate", compiled it with slice2cpp. I have writen the implementation of the procedure like it is desrcibed in the introductory example in the documentation (the "hello world" programm). Then I integrated the code into the code of the Server.cpp.

So I added the following lines to the Server.cpp:

using namespace ServerCallHandle;
class OnRequestI: public OnRequest{
public:
virtual void myTriggerFilesUpdate(const Ice::Current&);
};

void OnRequestI::myTriggerFilesUpdate(const Ice::Current&){
cout<<"Triggered\n";
}

It compiled and linked fine. But as I wanted to start the icepatch2server I got the following message:
../icepatch2server: relocation error: ../icepatch2server: undefined symbol: _ZTIN16ServerCallHandle9OnRequestE

So what's wrong? Any idea? Would appreciate any help:)

Comments

  • bernard
    bernard Jupiter, FL
    It sounds like you forgot to implement a function, or link the corresponding .o with your modified icepatch2server.

    However on RHEL 4:

    $ c++filt _ZTIN16ServerCallHandle9OnRequestE
    typeinfo for ServerCallHandle::OnRequest

    So check you compiler flags and make sure you did not disable RTTI.

    Cheers,
    Bernard
  • Thanks

    Hey, thank you. The problem was with the Makefile, I had to paste in the pathes to my new created files. After I did that, it worked.

    But now I got a new, different problem. As I have written, I want to modify the functionality. I want the server to perform some actions before it patches the files. So I inserted my own routine before the original server and client code in the main functions. I marked my changes in the code in the Italic font and the original code in bold:

    The main function of the server looks now:

    int
    main(int argc, char* argv[])
    {
    IcePatch2::PatcherService svc;
    int status = EXIT_FAILURE;




    Ice::CommunicatorPtr myIc;
    try {
    myIc = Ice::initialize();
    Ice::ObjectAdapterPtr adapter
    = myIc->createObjectAdapterWithEndpoints(
    "OnRequestAdapter", "default -p 10003");
    Ice::ObjectPtr object = new OnRequestI;
    adapter->add(object, myIc->stringToIdentity("OnRequest")
    );
    adapter->activate();
    myIc->waitForShutdown();
    } catch (const Ice::Exception& e) {
    cerr << e <<"hallo1"<< endl;
    status = 1;
    } catch (const char* msg) {
    cerr << msg <<"hallo2"<< endl;
    status = 1;
    }
    if (myIc) {
    try {
    myIc->destroy();
    } catch (const Ice::Exception& e) {
    cerr << e <<"hallo3"<< endl;
    status = 1;
    }
    }


    status = EXIT_FAILURE;
    #ifdef _WIN32
    status = svc.main(argc, argv);
    #else


    .... the rest

    The code of the main function of the client looks:
    int
    main(int argc, char* argv[])

    {

    int status = EXIT_FAILURE;
    Ice::CommunicatorPtr ic;
    try {
    ic = Ice::initialize();
    Ice::ObjectPrx base = ic->stringToProxy(
    "OnRequest:default -p 10003");
    OnRequestPrx printer = OnRequestPrx::checkedCast(base);
    if (!printer)
    throw "Invalid proxy";
    printer->myTriggerFilesUpdate();
    } catch (const Ice::Exception& ex) {
    cerr << ex << endl;
    status = 1;
    } catch (const char* msg) {
    cerr << msg << endl;
    status = 1;
    }
    if (ic)
    ic->destroy();
    //return status;



    Client app;
    return app.main(argc, argv);

    }

    So for me it looks fine:) But not for Ice. When I start the server and the client I get the following on the client side:
    $ ../icepatch2client --IcePatch2.Endpoints="tcp -h 127.0.0.1 -p 10003" .
    ../icepatch2client: Outgoing.cpp:368: Ice::ObjectNotExistException:
    object does not exist:
    identity: `IcePatch2/server'
    facet:
    operation: ice_isA

    On the server side my routine is executed and the message "Triggered" appears on the screen. That was what I added to the server. But the program stops than and doesn't do its original work. What could be wrong?

    Greetingz
    Ewgenij
  • benoit
    benoit Rennes, France
    Hi,

    The problem is most likely that the implementation of your servant method "myTriggerFilesUpdate" isn't shutting down the communicator. So the server gets stuck in the "myIc->waitForShutdown();" call and never actually starts the IcePatch2 server (the Ice::ObjectNotExistException is raised because your object adapter doesn't register any servant for the IcePatch2/server identity...).

    Cheers,
    Benoit.
  • Ah

    Hey, you are right! My implementation doesn't shut down the communicator. How can I do that? Have I to give the pointer to the communicator myIC to myTriggerFilesUpdate and shut it down, or is there another way for doing that?

    Ewgenij
  • benoit
    benoit Rennes, France
    Hi,

    You can get a hold on the communicator object with the Ice::Current structure passed to your servant method. See the implementation of the shutdown method in demo/Ice/hello/HelloI.cpp for an example.

    Cheers,
    Benoit.
  • Hi

    Hello, thanks. I managed that. Now the communicator shuts after executing the routine. But

    1) Nevertheless I get the following error message on the client side after executing of my server routine:
    $ ../icepatch2client --IcePatch2.Endpoints="tcp -h 127.0.0.1 -p 10003" .
    Network.cpp:669: Ice::ConnectionRefusedException:
    connection refused: Connection refused

    2) I want the server to execute the routine each time a client connects! If I shut the communicator, the server does it only the very first time a client connects.
  • benoit
    benoit Rennes, France
    The Ice::ConnectionRefusedException is most likely a race condition caused by the IcePatch2 server not being started yet when the client invokes on it. It's not clear to me what you're trying to do actually. Why don't you simply create a separate server from IcePatch2 to host your servant?

    If you want your servant to be accessible through the IcePatch2 endpoint, you shouldn't create another communicator/object adapter, you should use the IcePatch2 server communicator instead.

    In any case, I'm afraid it's difficult to help without more information on what exactly you're trying to do. Note also that this goes a bit beyond of the free support we can provide on these forums. We could provide you consulting services however, please contact info@zeroc.com if you're interested.

    Cheers,
    Benoit.
  • Hey, thanks for help. I solved the problem:)