CORBA IPC implementation hints

Environment

Prerequisites

Directory $IVD3RDPARTY/omni contains

In order to use omniORB, just extract appropriate archive file and execute the ivd-orb.sh script, which copies the libraries and executable to /opt/ivd/lib and /var/opt/ivd/lbin:

[ivd-3rdparty/omni]$ tar xzvf omni.tar.gz
[ivd-tools/env]$ ./ivd-orb.sh

Make sure that you have updated version of ivd-profile.sh script, which sets paths for omniORB environment and paths.

Files and services

  1. Naming Service:
    1. CORBA Naming Service is running as a daemon on all IVD servers (port 2809).

    2. $IVD3RDPARTY/omni/omniORB.cfg is a configuration file that configures CORBA environment to use naming service on grau.
      Path to the config file is specified with env. variable OMNIORB_CONFIG, which is set in ivd-profile.sh during startup. This file is created in /etc/opt/ivd/ for each of the IVD servers

    3. nameclt list command can be used to list, add, remove contents of the naming service.

  2. Libraries and binaries:
    1. All necessary libraries (Linux platform only!) are located on $IVD3RDPARTY/omni/lib/linux/. This path is already included in IVD-MakeRules.
    2. All necessary binaries (Linux platform only!) are located on $IVD3RDPARTY/omni/bin/linux/.
  3. Include files:
    1. All necessary include files are located on $IVD3RDPARTY/omni/include/. Use relative paths to header files in the source code. Library path is already added in IVD-MakeRules.
      Developer Studio tip: Add the path to the omniORB include directory to the Tools -> Options -> Directories -> Include Files.

Example

NOTE: Directory $IVDSRC/proto/corba/play contains sources that exercise various CORBA concepts. See the README and the sources for more information. That directory is used to test a CORBA concept before it is applied in the product.

This is a real-life example on how to use CORBA

The examples are explained in more detail in the book Advanced CORBA Programming with C++ by Michi Henning and Steve Vinoski (ACPWC) The book can be found somewhere in the eastern part of HSL-NG.

What To Do Step by Step

Define structures that will be passed through CORBA

Basic IDL type and structure definitions are located in i_types.idl.

Sample:

    struct i_PartitionCfg {
        long            minWaitTime;
        long            minNumMigFiles;
        long            minMigSize;
        long            maxWaitTime;
        string          fileChangeTrigger;
    };

Add component specific interfaces and definitions in specific idl file (ivd -src/lib/ipc/).

There are already templates for all ivd modules so you have to continue filling the specific file for your module.

interface i_PartitionManager : i_Component {
    i_PartitionCfg* GetCfg() raises(i_IvdException);
    void            ApplyCfg(in i_PartitionCfg);
};

IMPORTANT: Pay attention to indicate that the function throws an exception with the IDL raises clause. If you do not declare it then CORBA will throw a CORBA::SystemException.

See also ACPWC page 51

Building

Run make in /lib/ipc

Make will generate:

These files compile and link into libipc.a which you have to link to your CORBA server and client.

i_ivd_i.cc file will be generated as an implementation skeleton to make writing of the implementation code easier.

Copy the contents of this file to a file where the implementation of the interface will be located. (For example i_pm_impl.cpp ) and then implement the empty functions. (See also IVD-CodingStyle.doc for naming conventions.)

Implementation class declarations can be copied to a header file (For Example i_pm_impl.h)

Implementation

Server Side:

Put following lines in the server main function:

int main(int argc, char** argv)
{ 
    log_FUNC_m(main);
    ipc_Corba   corba;
    corba.InitDebug();
    dbg_On(dbg_DETAIL, dbg_INOUT, "debug.file");

    try {
        corba.Init(argv, argc);
        PortableServer::POAManager_var pman = corba.m_poa->the_POAManager();
        pman->activate();

        i_PartitionManager_i* myPM = new i_PartitionManager_i();
        corba.Register(myPM->_this(), "IVD/server/pm_374");

        corba.m_orb->run();
    }
    catch (ivd_Error &ie) {
        cout << ie << endl;
    }
    catch (ivd_InternalError &iie) {
        cout << iie << endl;
    }
    catch(CORBA::SystemException&) {
        cerr << "Caught CORBA::SystemException." << endl;
    }
    catch(CORBA::Exception&) {
        cerr << "Caught CORBA::Exception." << endl;
    }
    catch(omniORB::fatalException& fe) {
        cerr << "Caught omniORB::fatalException:" << endl;
        cerr << "  file: " << fe.file() << endl;
        cerr << "  line: " << fe.line() << endl;
        cerr << "  mesg: " << fe.errmsg() << endl;
    }
    catch(...) {
        cerr << "Caught unknown exception." << endl;
    }
    return 0;
}

With the CORBA Server implementation, this main function and the libipc.a library you should be able to build an executable. Run it and check the debug.file for errors.

See also ACPWC page 39

Client Side:

On the client side you have to put following lines to get a reference to the CORBA object (e.g. i_PartitionManager) :

    corba.Init(argv, argc);
    CORBA::Object_var obj = corba.Resolve("IVD/server/pm_374");
    i_PartitionManager_var myPM = i_PartitionManager::_narrow(obj);

then use it:

    myPM->ApplyCfg(myCfg);    

See also ACPWC page 44.

Corba Functions returning variable-length structures (pointer to struct)

Variable-length structures have one or more members, which size is not known in advance. All of IDL structures that contain CORBA strings are typical representatives of such structures.

In the implementation of the Corba functions that are returning some pointer you have to dynamically allocate the space for it. After that you have to destroy it on the client side.

Server side method implementation:

i_PartitionCfg* i_PartitionManager_i::GetCfg(){
    i_PartitionCfg* i_pCfg = new i_PartitionCfg;
    // ... do something
    
    return i_pCfg;
}    

Usage on the client side:

    i_PartitionCfg *myPMCfg;
    myPMCfg = myPM->GetCfg();
    
    // ... 
    
    delete myPMCfg;

See also ACPWC page 289