Back to TIL list

CORBA

Created at

Introdução

O que é CORBA?

  • é o acrônimo para Common Object Request Broker Architecture
  • é um framework para construção de sistemas distribuídos orientados a objetos
  • é multiplataforma
  • é independente de linguagem
  • é um padrão aberto e extensível definido pela Object Management Group
  • clientes e servidores estão em diferentes máquinas
  • programas clientes enviam mensagens para servidores remotos como se este estivesse locais (location transparency)

O que é a OMG?

  • www.omg.org
  • fundada em 1989
  • somente provê especificações
  • não provê implementações
  • todas as especificações são free

CORBA vs SOAP/XML-RPC

  • SOAP e XML-RPC são protocolos wire
  • CORBA inclui:
    • um protocolo wire
    • GIOP
    • object model
    • IDL
    • mapeamento de linguagem
    • serviços
    • códigos de cliente e servidor portáveis entre implementações CORBA

CORBA é pesado?

ORB - Object Request Broker

  • é o núcleo da Object Management Architecture
  • integra:
    • diferentes linguagens
    • diferentes arquiteturas
    • diferentes sistemas operacionais
  • é responsável por:
    • encontrar uma implementação para uma requisição
    • preparar implementações para receber requisições
    • comunicar dados das requisições

Clientes

  • possuem referências para objetos e invocam operações nestes objetos
  • conhecem apenas a interface dos objetos do servidor
  • não conhecem a implementação dos objetos nem os adaptadores utilizados por estas implementações
  • invocam interfaces definidas por uma IDL
  • invocam as implementações através de:
    • proxies (IDL generated stubs)
    • DII (Dynamic Invocation Interface)

Servidores

  • se registram no ORB
  • se disponibilizam para aceitar requisições
  • implementam uma IDL

IDL

  • provê interfaces independente de linguagem e sistema operacional
  • é puramente declarativa (não provê detalhes de implementação)
  • é fortemente tipada
  • especificações podem ser escritas e invocadas em qualquer linguagem

IDL Features

  • modules
  • interfaces
  • operations
  • attributes
  • inheritance
  • basic types
  • arrays
  • sequences
  • struct, enum, union
  • typedef
  • consts
  • exceptions

Tipos básicos

  • float
  • double
  • long
  • short
  • unsigned long
  • unsigned short
  • char
  • boolean
  • octet
  • any

Direções dos parâmetros

  • in - do cliente para o servidor
  • out - do servidor para o cliente
  • inout - do cliente para o servidor e de volta para o cliente

Exceções

CORBA define dois tipos de exceções:

  • system exceptions: exceções padrões definidas pelo CORBA
  • user defined exceptions: exceções definidas pelo usuário através da IDL
  • Implicitamente, todas as operações definidas na IDL podem lançar qualquer uma das exceções padrão do sistema CORBA
  • Nenhuma referência para exceções padrão devem aparecer na especificação da IDL
  • para especificar que uma operação pode lançar uma exceção definida pelo usuário você deve:
    • primeiro definir a estrutura da exceção
    • incluir raises à definição da operação
  • uma exceção da IDL pode conter membros
Interface Bank {
  exception Reject {
    string reason; // membro da exceção
  };
  exception TooMany {}; // exceção sem membros

  Account newAccount( in string name ) raises (Reject, TooMany);
};

Operações oneway

Interface Account {
  oneway void notice( in string notice );
};
  • não bloqueantes
  • não aceitam parâmetros out ou inout
  • não lançam exceções (não aceitam raise)

The OMG CORBA specification defines the following exceptions:

  • BAD_CONTEXT - if a request does not contain a correct context this exception is raised.
  • BAD_INV_ORDER - this exception indicates that operations has been invoked operations in the wrong order, which would cause, for example, a dead-lock.
  • BAD_OPERATION - raised if the target object exists, but that the invoked operation is not supported.
  • BAD_PARAM - is thrown if, for example, a parameter is out of range or otherwise considered illegal.
  • BAD_TYPECODE - if illegal type code is passed, for example, encapsulated in an any data type the 'BAD_TYPECODE' exception will be raised.
  • BAD_QOS - raised whenever an object cannot support the required quality of service.
  • CODESET_INCOMPATIBLE - raised if two ORB's cannot communicate due to different representation of, for example, char and/or wchar.
  • COMM_FAILURE - raised if an ORB is unable to setup communication or it is lost while an operation is in progress.
  • DATA_CONVERSION - raised if an ORB cannot convert data received to the native representation. See also the 'CODESET_INCOMPATIBLE' exception.
  • FREE_MEM - the ORB failed to free dynamic memory and failed.
  • IMP_LIMIT - an implementation limit was exceeded in the ORB at run time. A object factory may, for example, limit the number of object clients are allowed to create.
  • INTERNAL - an internal failure occurred in an ORB, which is unrecognized. You may consider contacting the ORB providers support.
  • INTF_REPOS - the ORB was not able to reach the interface repository, or some other failure relating to the interface repository is detected.
  • INITIALIZE - the ORB initialization failed due to, for example, network or configuration error.
  • INVALID_TRANSACTION - is raised if the request carried an invalid transaction context.
  • INV_FLAG - an invalid flag was passed to an operation, which caused, for example, a connection to be closed.
  • INV_IDENT - this exception indicates that an IDL identifier is incorrect.
  • INV_OBJREF - this exception is raised if an objet reference is malformed or a nil reference (see also corba:create_nil_objref/0).
  • INV_POLICY - the invocation cannot be made due to an incompatibility between policy overrides that apply to the particular invocation.
  • MARSHAL - this exception may be raised by the client- or server-side when either ORB is unable to marshal/unmarshal requests or replies.
  • NO_IMPLEMENT - if the operation exists but no implementation exists, this exception is raised.
  • NO_MEMORY - the ORB has run out of memory.
  • NO_PERMISSION - the caller has insufficient privileges, such as, for example, bad SSL certificate.
  • NO_RESOURCES - a general platform resource limit exceeded.
  • NO_RESPONSE - no response available of a deferred synchronous request.
  • OBJ_ADAPTER - indicates administrative mismatch; the object adapter is not able to associate an object with the implementation repository.
  • OBJECT_NOT_EXIST - the object have been disposed or terminated; clients should remove all copies of the object reference and initiate desired recovery process.
  • PERSIST_STORE - the ORB was not able to establish a connection to its persistent storage or data contained in the the storage is corrupted.
  • REBIND - a request resulted in, for example, a 'LOCATION_FORWARD' message; if the policies are incompatible this exception is raised.
  • TIMEOUT - raised if a request fail to complete within the given time-limit.
  • TRANSACTION_MODE - a transaction policy mismatch detected.
  • TRANSACTION_REQUIRED - a transaction is required for the invoked operation but the request contained no transaction context.
  • TRANSACTION_ROLLEDBACK - the transaction associated with the request has already been rolled back or will be.
  • TRANSACTION_UNAVAILABLE - no transaction context can be supplied since the ORB is unable to contact the Transaction Service.
  • TRANSIENT - the ORB could not determine the current status of an object since it could not be reached. The error may be temporary.
  • UNKNOWN - is thrown if an implementation throws a non-CORBA, or unrecognized, exception.

Estruturas

struct PersonalDetails {
  string name;
  short age;
};

interface Bank {
  PersonalDetails getPerDet(in string name);
};

Arrays

  • podem ser multidimensionais
  • precisam ter tamanho fixo (conhecido em tempo de definição)
Account bankAccounts[100];
short matrix[10][20]; // 2D array

Constantes

Interface Bank {
  const long MaxAccounts = 10000;
};

Contantes dos tipos long, float e string podem ser declarada.

Typedef

typedef short size;
size i;

typedef Account Accounts[100]; // acho que está invertido aqui
Accounts bankAccounts;

Módulos

Module Finance {
  interface Bank { ... };
  interface Account { ... };
};
  • são usados para agrupar interfaces em unidades lógicas
  • utilize nomes completos (p.e. Finance::Account *a;)

Preprocessador

  • baseado no preprocessador do C++
  • substituição de macro
  • compilação condicional
  • inclusão de IDL
  • #include
  • #define
  • #if
  • #ifdef
  • #defined

Mapeamento para linguagem

  • linguagens OO e non-OO acessam de modos diferentes
  • tipos específicos da linguagem
  • estrutura do stub cliente (somente para non-OO)
  • interface de invocação dinâmica
  • esqueleto de implementação
  • adaptadores de objeto
  • interface direta ao ORB

Mapeamento de identificadores

  • usa o mesmo nome
  • se for uma palavra reservada do C++ receberá um _ como prefixo (p.e. _new)

Mapeamento de interface

  • são mapeadas para classes
  • uma IDL mapeada para uma classe C++ não pode ser instanciada
Interface Account { ... }

será mapeado para:

class Account : public virtual CORBA::Object { ... }

Mapeamento de escopo

Interface para classe

Interface Bank {
  struct Details { ... };
};

será mapeado para:

class Bank {
  public:
    struct Details { ... };
};

Module para namespace

Module M {
  Interface A { ... };
  Interface B { ... };
};

será mapeado para:

namespace M {
  class A { ... };
  class B { ... };
};

Acessíveis via M::A e M::B.

Mapeamento do módulo padrão do CORBA

Será mapeado para:

namespace CORBA { ... }

Utilize os membros como:

CORBA::ORB_init( ... );

Mapeamento de tipos

IDLC++Tamanho e faixa
shortCORBA::Short16 bit:
longCORBA::Long32 bit:
long longCORBA::LongLong64 bit:
unsigned shortCORBA::UShort16 bit:
unsigned longCORBA::ULong32 bit:
unsigned long longCORBA::ULongLong64 bit:
floatCORBA::Float32 bit IEEE single precision floating point number
doubleCORBA::Double64 bit IEEE double precision floating point number
long doubleCORBA::LongDouble--
charCORBA::Char8 bit
wcharCORBA::WChar-- (Wide Char)
stringCORBA::char *--
wstringCORBA::WChar *--
booleanCORBA::Booleantrue/false
octetCORBA::Octet(unsigned char) 8 bit raw. Sem conversão
anyCORBA::AnyArbitrary

Repositório de interfaces

  • provê armazenamento para informações da IDL
  • um programa pode referenciar objetos cuja interface será conhecida em tempo de execução
  • estas informações podem ser usadas pelo ORB para realizar requisições
  • pode armazenar outras informações sobre interfaces:
    • debugging
    • info
    • browser routines

Repositório de implementação

  • informações que o ORB utiliza para localizar e ativar implementações de um servidor de objetos
  • armazena informações de ativação:
    • máquina onde um servidor pode ser iniciado a partir de uma requisição do cliente

Dynamic Invocation Interface

  • Em vez de chamar um stub específico de uma operação, é possível especificar um objeto, operação e parâmetros para através de uma chamada ou sequência de chamadas
  • o cliente precisa fornecer os tipos dos parâmetros passados

Interoperabilidade

  • suporta rede de objetos distribuídos em múltiplos ORBs (heterogêneos)
  • InterORBability
  • GIOP: (General Inter-ORB Protocol) sintaxe padrão de transferência e conjunto de formato de mensagens
  • ESIOP: (Environment Specific Inter-ORB Protocol) protocolo especializado
  • IIOP: mapeamento TCP/IP para GIOP

COSS - Common Object Service Specification

  • naming
  • events
  • life cycle
  • time
  • transactions
  • concurrency
  • persistence
  • query
  • security
  • licensing
  • relationships
  • properties
  • externalization
  • collection

OA - Object Adapter

  • Conectam implementações de objetos ao ORB
  • Ativam os múltiplos objetos implementados por um servidor
  • Encaminhamento de requisições de serviço
  • Geram object references
    • Para ter o status de CORBA Object o objeto deve ser registrado com o adaptador

BOA - Basic Object Adapter

  • Presente na especificação CORBA até a revisão 2.1
  • CORBA 2.2 substituiu o BOA pelo POA
  • ORB com BOA significa que os servidores não são portáveis

POA Portable Object Adapter

  • O POA (Portable Object Adapter) auxilia o ORB (Object Request Broker) na passagem das requisições do clientes para a implementação do servidor (servant).
  • O POA interpreta a requisição, empacota a passagem de parâmetros e então localiza o servant e os tratadores de recuperação erros e de segurança.
  • Isto habilita portabilidade, independência de fabricantes e extensibilidade compatível com a especificação da OMG (Object Management Group)
  • POA também habilita a persistência de objetos bem como dá suporte a ciclo de vida do serviço
  • Identificadores de objetos automaticamente gerados ou especificados pelo usuário
  • Ativação explícita ou por demanda
  • Relação: um servant <-> um ou mais objetos CORBA
  • Aplicação tem total controle sobre o comportamento e sobre a existência dos objetos CORBA
  • Servants podem usar esqueletos estáticos ou dinâmicos

Identificador de Objeto

  • Valor usado para identificar um objeto no contexto de um POA
    • Não é um identificador globalmente único!
  • Pode ser determinado pela aplicação ou gerado pelo POA
    • typedef sequence<octet> ObjectID;
  • O POA coloca esse valor no campo object id da IOR

O Campo Object Id da IOR

Instalação do omniORB no Debian

apt install libomniorb4-dev omniidl omniorb omniorb-doc omniorb-nameserver omniidl-python python-omniorb

Iniciar o servidor de nomes

OmniORB

Incluir no arquivo /etc/omniORB.cfg a seguinte linha:

InitRef = OmniNameService=corbaname::localhost

null O nome OmniNameService deve ser conhecido pelo servidor e pelo cliente. null

Para iniciar o servidor de nomes do OmniORB use:

omniNames -start

Exemplo de saída do comando acima:

omniNames: (0) 2019-12-30 15:36:29.516974: Data file: '/var/lib/omniorb/omninames-erebo.dat'.
omniNames: (0) 2019-12-30 15:36:29.517058: Starting omniNames for the first time.
omniNames: (0) 2019-12-30 15:36:29.517348: Wrote initial data file '/var/lib/omniorb/omninames-erebo.dat'.
omniNames: (0) 2019-12-30 15:36:29.517444: Read data file '/var/lib/omniorb/omninames-erebo.dat' successfully.
omniNames: (0) 2019-12-30 15:36:29.517529: Root context is IOR:010000002b00000049444c3a6f6d672e6f72672f436f734e616d696e672f4e616d696e67436f6e746578744578743a312e300000010000000000000070000000010102000d0000003139322e3136382e302e31330000f90a0b0000004e616d6553657276696365000300000000000000080000000100000000545441010000001c000000010000000100010001000000010001050901010001000000090101000354544108000000ad430a5e010075e0
omniNames: (0) 2019-12-30 15:36:29.517600: Checkpointing Phase 1: Prepare.
omniNames: (0) 2019-12-30 15:36:29.517703: Checkpointing Phase 2: Commit.
omniNames: (0) 2019-12-30 15:36:29.517802: Checkpointing completed.

A porta padrão é a 2809.

Os arquivos de controle serão criados por padrão no diretório /var/lib/omniorb/:

  • /var/lib/omniorb/omninames-nome-da-maquina.dat
  • /var/lib/omniorb/omninames-nome-da-maquina.bak

Para especificar um diretório diferente use a opção -logdir:

omniNames -logdir /tmp -start

MICO

Para iniciar o servidor de nomes do MICO use:

nsd -ORBIIOPAddr inet:localhost:2809

Veja exemplo em Connecting 3 ORBs.

Exemplo

Componentes do exemplo
Componentes do exemplo

Criando a IDL

Arquivo de interface Data.idl:

#ifndef __DATADIST_IDL__
#define __DATADIST_IDL__
module Data
{
  interface ServiceA {
    boolean CallServiceRoutineA (
        in    long num1,
        inout long num2,
        out   long retNum );
    boolean CallServiceRoutineB (
        inout long num1,
        inout long num2);
  };
};
#endif

Gerando backend a partir da IDL

Use a opção -b para escolher o backend a ser gerado.

omniidl -bcxx    Data.idlomniidl -bpython Data.idlomniidl -bdump   Data.idl

Gerando Python

omniidl -bpython Data.idl

os arquivos abaixo são criados:

  • Data_idl.py
  • Data__POA/__init__.py
  • Data/__init__.py

null Descrever os arquivos gerados em python. null

Gerando C++

Ao executar o seguinte comando:

omniidl -bcxx Data.idl

os arquivos abaixo são criados:

  • Data.hh - cabeçalho que será usado pelo cliente e pelo servidor
  • DataSK.cc - deve ser compilado e lincado com o programa que proverá a infraestrutura de comunicação

Contendo os seguintes items:

  • classe ServiceA contendo funções estáticas e definições de tipos
  • ServiceA_ptr - um ponteiro para o tipo do objeto de referência
  • ServiceA_var - um helper para gerenciamento de memória usado por ServiceA_ptr
  • classe POA_Service! - a classe esqueleto para o servidor
Data.hh
  // interface ServiceA
  class ServiceA {
  public:
    // Declarations for this interface type.
    typedef ServiceA_ptr _ptr_type;
    typedef ServiceA_var _var_type;
    static _ptr_type _duplicate(_ptr_type);
    static _ptr_type _narrow(::CORBA::Object_ptr);
    static _ptr_type _unchecked_narrow(::CORBA::Object_ptr);
    static _ptr_type _nil();
DataSK.cc
// This file is generated by omniidl (C++ backend)- omniORB_4_2. Do not edit.

#include "Data.hh"
#include <omniORB4/IOP_S.h>
#include <omniORB4/IOP_C.h>
#include <omniORB4/callDescriptor.h>
#include <omniORB4/callHandle.h>
#include <omniORB4/objTracker.h>

OMNI_USING_NAMESPACE(omni)
...

Criando o servidor

Server.cc

Código do servidor:

  1. Iniciar o ORB
  2. Obter a referência para o POA raiz para registra-se
  3. Vincular com o serviço de nomes
  4. Iniciar o servidor de objetos
// Server.cc

#include <assert.h>
#include <iostream>
#include <signal.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include "CServiceA_i.hh"
#include "Data.hh"

using namespace std;

int main( int argc, char **argv )
{
  try {
    // (1) Iniciar o ORB
    CORBA::ORB_var orb = CORBA::ORB_init( argc, argv );
    // (2) Obter a referência para o POA raiz para registra-se para ficar disponível para os clientes
    CORBA::Object_var       obj  = orb->resolve_initial_references( "RootPOA" );
    PortableServer::POA_var _poa = PortableServer::POA::_narrow( obj.in() );
    // As operações definidas na interface são invocadas pelo objeto de referência.
    // Um instância de CRequestSocketStream_i é iniciada
    PortableServer::Servant_var<CServiceA_i> myRequestServiceA = new CServiceA_i();
    // o servidor e objetos é ativado no RootPOA
    PortableServer::ObjectId_var myRequestServiceA_oid = _poa->activate_object( myRequestServiceA );
    // Obtêm o objeto de referência do servidor e registra no servidor de nome
    CORBA::Object_var SA_obj = myRequestServiceA->_this();
    // Obtêm uma referência para o objeto e imprime seu IOR como string
    CORBA::String_var sior( orb->object_to_string( SA_obj.in() ) );
    cerr << "'" << (char *)sior << "'" << endl;

null Aqui você deve utilizar o mesmo nome do servidor de nomes definido no arquivo /etc/omniORB.cfg. null

    // (3) Vincular com o serviço de nomes
    // o serviço é definido pela diretiva InitRef e pelo identificador
    // "OmniNameService" no arquivo omniORB.cfg
    CORBA::Object_var obj1 = orb->resolve_initial_references( "OmniNameService" );
    assert( !CORBA::is_nil( obj1.in() ) );
    CosNaming::NamingContext_var nc = CosNaming::NamingContext::_narrow( obj1.in() );
    assert( !CORBA::is_nil( nc.in() ) );
    CosNaming::Name name;
    name.length( 1 );
    name[0].id = CORBA::string_dup( "DataServiceName1" );
    nc->rebind( name, SA_obj.in() );
    //========================================================================
    myRequestServiceA->_remove_ref();
    //
    PortableServer::POAManager_var pmgr = _poa->the_POAManager();
    pmgr->activate();
    // (4) Iniciar o servidor de objetos para aceitar requisições dos clientes
    orb->run();
    //
    // Se o ORB deixar o loop de tratamento de eventos
    // Atualmente está configurado para nunca dar timeout
    orb->destroy();
    //
    free( name[0].id ); // str_dup realiza um malloc internamente
  }

Tratar as exceções:

  catch( CORBA::TRANSIENT & ) {
    cerr << "Caught system exception TRANSIENT -- unable to contact the server." << endl;
  }
  catch( CORBA::OBJECT_NOT_EXIST & ) {
    cerr << "Caught system exception OBJECT_NOT_EXIST" << 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;
}

Implementação do Servant

São denotados pelo sufixo _i.

CServiceA_i.hh

// CServiceA_i.hh
#include "Data.hh"

class CServiceA_i : public POA_Data::ServiceA, public PortableServer::RefCountServantBase {
public:
  CServiceA_i();
  virtual ~CServiceA_i();
  virtual CORBA::Boolean CallServiceARoutineA(
    /*in*/    CORBA::Long num1,
    /*inout*/ CORBA::Long &num2,
    /*out*/   CORBA::Long &retNum );
  virtual CORBA::Boolean CallServiceARoutineB(
    /*inout*/ CORBA::Long &num1,
    /*inout*/ CORBA::Long &num2 );
};

CServiceA_i.cc

// CServiceA.cc

#include <fstream>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sys/types.h>
#include <unistd.h>
#include <vector>

#include "CServiceA_i.hh"

using namespace Data;

#include <sys/wait.h>

CServiceA_i::CServiceA_i() { }

CServiceA_i::~CServiceA_i( void ) { }

CORBA::Boolean CallServiceARoutineA(
    /*in*/    CORBA::Long num1,
    /*inout*/ CORBA::Long &num2,
    /*out*/   CORBA::Long &retNum )
{
  num2   = num2 + num1;
  retNum = 10;
  return true;
}

CORBA::Boolean CallServiceARoutineB(
    /*inout*/ CORBA::Long &num1,
    /*inout*/ CORBA::Long &num2 )
{
  num1++;
  num2++;
  return true;
}

Cliente CORBA

null

Client.cc

// Client.cc
#include "CRequestServiceA.hh"

int main( int argc, char **argv )
{
  // O construtor estabelece o link como o servidor CORBA.
  CRequestServiceA requestServiceA;

  if( requestServiceA.RequestServiceARoutineA() ) {
    cout << "ServiceA RoutineA: True" << endl;
  }
  if( requestServiceA.RequestServiceARoutineB() ) {
    cout << "ServiceA RoutineB: True" << endl;
  }
  return 0;
}

CRrquestServiceA.hh

// CRrquestServiceA.hh
#include "Data.hh"
#include <cassert>
#include <fstream>
#include <iostream>

using namespace std;

class CRequestServiceA {
public:
  CRequestServiceA();
  ~CRequestServiceA();
  bool RequestServiceARoutineA();
  bool RequestServiceARoutineB();

  CosNaming::Name m_corbaCosName;

  // CORBA ORB
  CORBA::ORB_var m_orb;

  CORBA::Object_var m_obj;  // ORB Object
  CORBA::Object_var m_obj1; // Resolved id to object reference

  // Resolved and narrowed CORBA object for proxy calls
  Data::ServiceA_var m_Data;
};

class DS_ServerConnectionException {
public:
  DS_ServerConnectionException()
  {
    cerr << "CORBA COMM_FAILURE" << endl;
  };
};

class DS_SystemException {
public:
  DS_SystemException()
  {
    cerr << "CORBA Exception" << endl;
  };
};

class DS_FatalException {
public:
  DS_FatalException()
  {
    cerr << "CORBA Fatal Exception" << endl;
  };
};

class DS_Exception {
public:
  DS_Exception()
  {
    cerr << "Exception" << endl;
  };
};

CRequestServiceA.cc

// CRequestServiceA.cc

#include "CRequestServiceA.hh"
using namespace Data;

CRequestServiceA::CRequestServiceA()
{
  try {
    // Inicia o objeto ORB
    int            argc = 0; // Variáveis dummy.
    char **        argv = 0;
    CORBA::ORB_var orb  = CORBA::ORB_init( argc, argv );

    // Vincula o objeto ORB ao servidor de nome
    // Deve ser o mesmo nome definido em /etc/omniORB.cfg
    CORBA::Object_var obj = orb->resolve_initial_references( "OmniNameService" );
    assert( !CORBA::is_nil( obj.in() ) );

    CosNaming::NamingContext_var nc = CosNaming::NamingContext::_narrow( obj.in() );
    assert( !CORBA::is_nil( nc.in() ) );

    CosNaming::Name _corbaCosName;
    _corbaCosName.length( 1 );
    _corbaCosName[0].id = CORBA::string_dup( "DataServiceName1" );

    CORBA::Object_var obj1 = nc->resolve( _corbaCosName );
    assert( !CORBA::is_nil( obj1.in() ) );

    m_Data = ServiceA::_narrow( obj1.in() );
    if( CORBA::is_nil( m_Data.in() ) ) {
      cerr << "IOR is not an SA object reference." << endl;
    }
  }
  catch( CORBA::COMM_FAILURE &ex ) {
    cerr << "Caught system exception COMM_FAILURE -- unable to contact the "
         << "object." << endl;
    throw DS_ServerConnectionException();
    return;
  }
  catch( CORBA::SystemException & ) {
    cerr << "Caught a CORBA::SystemException." << endl;
    throw DS_SystemException();
    return;
  }
  catch( CORBA::Exception & ) {
    cerr << "Caught CORBA::Exception." << endl;
    throw DS_Exception();
    return;
  }
  catch( omniORB::fatalException &fe ) {
    cerr << "Caught omniORB::fatalException:" << endl;
    cerr << "  file: " << fe.file() << endl;
    cerr << "  line: " << fe.line() << endl;
    cerr << "  mesg: " << fe.errmsg() << endl;
    throw DS_FatalException();
    return;
  }
  catch( ... ) {
    cerr << "Caught unknown exception." << endl;
    throw DS_Exception();
    return;
  }
  return;
}

CRequestServiceA::~CRequestServiceA()
{
  // ...
}

bool CRequestServiceA::RequestServiceARoutineA()
{
  CORBA::Long num1 = 4;
  CORBA::Long num2 = 5;
  CORBA::Long retNum;

  cout << "Valores de entrada para a rotina A do serviço A: " << num1 << " " << num2 << " " << retNum << endl;

  // Esta chamada CORBA será executada remotamente
  if( m_Data->CallServiceRoutineA( num1, num2, retNum ) ) {
    cout << "Valores retornados pelo serviço A: " << num1 << " " << num2 << " " << retNum << endl;
    return true;
  }
  return false;
}

bool CRequestServiceA::RequestServiceARoutineB()
{
  CORBA::Long num1 = 0;
  CORBA::Long num2 = 50;

  cout << "Valores de entrada para a rotina B do serviço A: " << num1 << " " << num2 << endl;

  // Esta chamada CORBA será executada remotamente
  if( m_Data->CallServiceRoutineB( num1, num2 ) ) {
    cout << "Valores retornados pelo serviço B: " << num1 << " " << num2 << endl;
    return true;
  }
  return false;
}

Makefile

# Makefile
LDFLAGS+=-lomniORB4 -lomnithread -lomniDynamic4
CXXFLAGS+=-Wall

all: server client

server: DataSK.o CServiceA_i.o Server.o
    $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)

client: DataSK.o Client.o CRequestServiceA.o
    $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)

clean:
    rm -f *.o
    rm -f server
    rm -f client

This is the value of CORBA. This is why we use CORBA. Look at how simple the program looks. The constructor establishes the link with the CORBA server. The subsequent calls to Routine A and B are processed remotely on the CORBA server but called like any other local function call.

Todo

Referências

No related pages found.