ARQUITECTURA CORBA ■ CORBA ■ ■ ■ ■ ➨ ■ ■ Angel García Baños ■ Escuela de Ingeniería de Sistemas y Computación ■ Universidad del Valle ■ 27 de Noviembre de 2002 CORBA 3 ■ La interfase con el ORB Extensión CORBA del Object Model de OMA. Estructura del ORB. Lenguaje de definición de interfases (IDL). Mapeo del IDL en lenguajes de programación. La interfase de Object. La interfase con el ORB. Los adaptadores de objetos (BOA y POA). Depósito de implementaciones (IMR). El tipo any. Depósito de interfases (IR). Interfase dinámica (DII y DSI). Interoperabilidad (GIOP, IIOP). AGB La interfase con el ORB SERVIDOR ■ SIRVIENTE CLIENTE Interfase de invocación IR dinámica (DII) Interfase de invocación estática (stub IDL) Interfase del ORB Interfase de Interfase esqueleto dinámica estática (skeleton IDL) (DSI) ■ ■ esqueleto Adaptador del objeto IMR ■ ■ NÚCLEO DEL ORB ■ ■ AGB 3 La interfase con el ORB ■ ■ ORB ORB_init(inout arg_list argv, in ORBid orb_identifier); release(ORB orb); // ... Conversión de una referencia a string. De-conversión de un string a una referencia. }; – Manejo de la interfase dinámica: ■ ■ ■ Creación de listas de parámetros. Realización de llamadas remotas normales, oneway y diferidas. AGB Inicialización y destrucción: module CORBA // PIDL { typedef string ORBid; typedef sequence<string> arg_list; interface ORB; // forward declaration – Inicialización, despacho y destrucción. – Obtención de referencias iniciales (usualmente a servicios, al POA, etc). – Manejo de referencias a objetos: ■ El ORB no es un objeto (es un pseudo-objeto). Sin embargo, debe proporcionar una serie de interfases hacia los objetos, que también se definen en el mismo lenguaje IDL (pseudo-IDL = PIDL). Estas pseudo-interfases no heredan de Object. Las pseudo-interfases no pueden pasarse como argumentos (con algunas salvedades). Las operaciones de las pseudo-interfases no pueden invocarse dinámicamente (via DII). Su mapeo en los lenguajes de programación puede no seguir las reglas habituales. Las pseudo-interfases no se almacenan en el depósito de interfases. 4 AGB La interfase con el ORB La pseudo-interfase con el ORB ofrece las siguientes operaciones: ■ 2 5 La operación ORB_init() inicializa el ORB en tiempo de ejecución, retornando una pseudo-referencia del pseudo-objeto ORB. AGB 6 La interfase con el ORB ■ La interfase con el ORB Mapeo en C++ ■ namespace CORBA { // .... ORB_ptr ORB_init(int & argc, char **argv, const char *orb_identifier=“”); // ... }; ■ ■ 7 La interfase con el ORB ■ ■ ■ 8 Obtención de referencias iniciales y de la lista de servicios iniciales disponibles: module CORBA // PIDL { // ... interface ORB { typedef string ObjectId; typedef sequence <ObjectId> ObjectIdList; Object resolve_initial_references(in ObjectId id) raises(InvalidName); ObjectIdList list_initial_services(); }; // ... }; AGB 10 La interfase con el ORB Conversión de referencias a strings y viceversa: ■ module CORBA // PIDL { // ... interface ORB { string object_to_string(in Object obj); Object string_to_object(in string str); }; // ... }; Estas dos funciones permiten la conversión de referencias a strings, por ejemplo, para imprimirlas o almacenarlas en disco o transmitirlas por email. AGB ■ 9 La interfase con el ORB ■ AGB La interfase con el ORB El ORB no puede inicializarse antes del main(), por razones técnicas de inicialización de su librería. Pero, a la vez, es conveniente que sea accesible desde cualquier parte del programa. Por ello, conviene crearlo usando un “patrón Singleton”. ORB_init() escanea argv en busca de opciones válidas, que retira después, de modo que las opciones que queden son para el resto de la aplicación. Si orb_identifier es un string vacío, se puede especificar como opción de línea de ejecución, usando -ORBid arg AGB ■ int main(int argc, char *argv[]) { CORBA::ORB_ptr orb; try { orb = ORB_init(argc, argv); } catch(...) { cerr<<“Error al inicializar el ORB”<<endl; exit(1); } // Se usa el ORB ... CORBA::release(orb) } Los argumentos argc y argv son los de la línea de ejecución, que recibe main(). Y orb_identifier es un identificador opcional, para el caso de que haya mas de un ORB en el mismo computador. En orb_identifier se pueden especificar QoS, dependiendo del fabricante del ORB. AGB Su uso típico desde un programa en C++ sería: 11 Su mapeo en C++ es: namespace CORBA { // ... class ORB { public: char * object_to_string(Object_ptr obj); Object_ptr string_to_object(const char * str); }; // ... }; AGB 12 La interfase con el ORB ■ La interfase con el ORB Y su uso típico desde un programa en C++ es: ■ CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv); CORBA::Object_ptr obj; // En argv[1] debe venir una referencia en formato de string: try { obj = orb->string_to_object(argv[1]); } catch(...) { cerr<<“Error: mal formato en la referencia”<<endl; exit(1); } if(CORBA::is_nil(obj)) cerr<<“Error: referencia nula”<<endl; exit(1); CCS::Controller_ptr ctrl; try { ctrl = CCS::Controller::_narrow(obj); } catch(...) { cerr<<“Error: referencia a objeto incorrecto”<<endl; exit(1); } CORBA::release(obj); if(CORBA::is_nil(ctrl)) cerr<<“Error: referencia a objeto incorrecto”<<endl; exit(1); // Se usa .... CORBA::release(ctrl); CORBA::release(orb); AGB ■ ■ ■ 13 AGB La interfase con el ORB ■ ■ CORBA::ORB_ptr orb = CORBA::ORB_init(argc, argv); CCS::Controller_ptr ctrl = ...; // Obtiene una referencia try { char * s = orb->object_to_string(ctrl); } catch(...) { cerr<<“Error: no se pudo convertir a string”<<endl; exit(1); } cout << s << endl; CORBA::string_free(s); CORBA::release(ctrl); CORBA::release(orb); ■ ■ ■ 15 La interfase con el ORB ■ ■ La función object_to_string() retorna un string de memoria dinámica, que hay que liberar con CORBA::string_free() Las referencias son opacas al programador. Hay herramientas para ver su contenido, a efectos de curiosidad y depuración, pero nunca hay que tratar de manipularlas. Los strings procedentes de referencias comienzan con IOR: seguido de un número par de dígitos hexadecimales. Es legal que un ORB produzca dos strings distintos al convertir la misma referencia. Por ello, los strings no 16 AGB deben compararse entre si. La interfase con el ORB Una vez inicializado el ORB y el POA (ver mas adelante), hay que dar la orden al ORB de que comience a despachar peticiones de los clientes hacia los objetos. Ello se hace con la llamada run(), que es bloqueante. Si la aplicación es multithread, se pueden manejar las peticiones CORBA en un thread (usando este comando run() que bloquearía este thread), mientras se atienden otros eventos (ventanas, mouse, teclado, sockets...) desde otros thread. (Thread = hilo de ejecución) AGB 14 La interfase con el ORB Ejemplo en el lado del servidor: AGB La función string_to_object() convierte un string a una referencia genérica a Object. La función _narrow() convierte una referencia genérica a Object, a una referencia especializada a un objeto mas concreto (downcast). Esta función es miembro de cualquier objeto que se defina. Ya vimos que la función CORBA::is_nil() chequea si una referencia es nula. Cada vez que se genera una referencia se crea un “proxy”, que hay que liberarlo con release() cuando ya no se vaya a usar mas. 17 ■ ■ Para finalizar el ORB hay que hacer shutdown(). Esta función recibe un único parámetro bool de entrada (true = esperar que las conexiones se cierren; false = retornar sin esperar). No es razonable que se le permita a un cliente hacer esta llamada, pues podría abortar la comunicación del servidor con otros clientes. El shutdown se puede hacer de tres maneras: – Por timeout: si expira un cierto tiempo sin que haya habido peticiones de clientes. – Se puede matar la aplicación servidor desde la consola, con Ctrl-C o con kill. – Usando un cliente especial para administración del servidor y enviándole un mensaje IDL AGB que ejecute el shutdown(). 18 La interfase con el ORB ■ Si solo hay un thread y se quieren manejar otros eventos (ventanas, sockets...) simultáneamente con los de CORBA entonces no se debe usar run() sino work_pending() y perform_work(), que son no-bloqueantes: CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); // Inicializar POA, POAmanager y activar objetos... bool fin = false; while( ! fin) { if(orb->work_pending()) orb->perform_work(); fin = manejar_otros_eventos(); } orb->shutdown(true); AGB 19