i i i i i i i i i i i i i i i i i i i i I NFRAESTRUCTURA PARA LA I NTEGRACIÓN DE R EDES DE S ENSORES Y ACTUADORES EN E NTORNOS I NTELIGENTES i i i i i i i i i i i i i i i i D EPARTAMENTO DE T ECNOLOGÍAS Y S ISTEMAS DE I NFORMACIÓN E SCUELA S UPERIOR DE I NFORMÁTICA U NIVERSIDAD DE C ASTILLA -L A M ANCHA TESIS DOCTORAL I NFRAESTRUCTURA PARA LA I NTEGRACIÓN DE R EDES DE S ENSORES Y ACTUADORES EN E NTORNOS I NTELIGENTES Autor: David Villa Alises Ingeniero Informático Universidad de Castilla-La Mancha Directores: Francisco Moya Fernández Dr. Ingeniero de Telecomunicación Universidad de Castilla-La Mancha Juan Carlos López López Dr. Ingeniero de Telecomunicación Catedrático de Universidad Universidad de Castilla-La Mancha Ciudad Real, 2009 i i i i i i i i David Villa Alises Ciudad Real Spain E-mail: Telefono: Web site: c 2009 [email protected] (+34) 926 295300 (ext: 3707) http://arco.esi.uclm.es/~david.villa/ David Villa Alises Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License". Se permite la copia, distribución y/o modificación de este documento bajo los términos de la Licencia de Documentación Libre GNU, versión 1.3 o cualquier versión posterior publicada por la Free Software Foundation; sin secciones invariantes. Una copia de esta licencia esta incluida en el apéndice titulado «GNU Free Documentation License». Muchos de los nombres usados por las compañías para diferenciar sus productos y servicios son reclamados como marcas registradas. Allí donde estos nombres aparezcan en este documento, y cuando el autor haya sido informado de esas marcas registradas, los nombres estarán escritos en mayúsculas o como nombres propios. i i i i i i i i Resumen L AS redes de sensores —especialmente las inalámbricas— son desde hace unos años un importante tema de investigación para muchas disciplinas debido quizá al impresionante potencial que se prevé en su aplicación a campos tan dispares como la medicina o la defensa. Y todo ello a pesar de los graves problemas que suponen sus peculiares características: energía limitada, reducido tamaño, movilidad, comunicaciones intermitentes y un largo etcétera. Uno de los aspectos más importantes para una utilización provechosa de las redes de sensores es la creación de servicios de valor sobre ellas. Para lograrlo hay que resolver primero un problema clave: se deben establecer los medios para comunicar los sistemas de información tradicionales con los nodos sensores, pero también éstos entre sí, aun perteneciendo a redes con distinta tecnología. Tradicionalmente la solución a estos problemas es un middleware de comunicaciones, y aunque existe gran cantidad de propuestas para diseño de middlewares para redes de sensores, en nuestra opinión, se ocupan solo de los problemas específicos y olvidan la importancia de una solución global aplicable a todo el sistema. Esta tesis propone una infraestructura que permite adaptar middlewares de comunicaciones orientados a objetos de propósito general para uso dentro y fuera de la red de sensores. Esta infraestructura proporciona un entorno homogéneo y eficaz para la creación de servicios de alto nivel, evitando la necesidad de contemplar casos especiales cuando tratamos con redes de sensores o actuadores. Las contribuciones más importantes son: un método para crear objetos distribuidos empotrados, un modelo de información adaptado a la naturaleza de las redes de sensores, un protocolo de descubrimiento de servicios y un mecanismo para la interconexión de redes heterogéneas por medio de encaminamiento de mensajes sobre el middleware. A diferencia de muchos trabajos previos, éstas no son soluciones particulares; todas ellas pueden ser aplicadas al sistema completo —incluya o no redes de sensores— sin un sacrificio significativo de eficiencia o prestaciones. Palabras clave – red de sensores, middleware de comunicaciones, computación distribuida orientada a objetos. VII i i i i i i i i i i i i i i i i Abstract S ENSOR networks —specially wireless sensor networks— have been the focus of very active research in many fields, probably due to their impressive potential in broadly different fields such as medicine or defense. This is happening in spite of their severe problems regarding their distinctive characteristics: limited energy, reduced size, mobility, intermittent communication, and so on. One of the main aspects that may lead to a fruitful exploitation of sensor networks is the development of valuable services on top of them. To achieve this goal another key problem must be solved first: there must be well defined means to communicate traditional information systems with sensor nodes, and also among themselves, even when they use different underlying technologies. The traditional solution to this kind of problems is a communication middleware and there is a large offering of proposals of middlewares for sensor networks. Unfortunately we believe that they are all limited to some specific problems, forgetting about the importance of a global solution which may be applied to the whole system. This thesis proposes an infrastructure to enable the adaptation of any general purpose object oriented communication middleware to be used inside and outside of the sensor network. This infrastructure provides an homogeneous and effective environment to develop high level services and avoids the need to consider special cases when dealing with sensor and actuator networks. The main contributions are: a method to define highly efficient embedded distributed objects, an information model specially suited to the needs of sensor networks, a service discovery protocol, and a mechanism for heterogeneous network interconnection by means of message routing on top of the underlying middleware. By contrast to many former works these are not isolated solutions; they may all be applied to the whole system whether it includes sensor networks or not without any noticeable overhead regarding efficiency or performance. Keywords – sensor network, communication middleware, object oriented distributed computing. IX i i i i i i i i i i i i i i i i Índice general Índice general XI Índice de cuadros XXI Índice de figuras XXIII Índice de listados XXVII Listado de acrónimos XXXI 1. Introducción 1 1.1. Redes de sensores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.2. Objetivos de la investigación . . . . . . . . . . . . . . . . . . . . . . . . 5 1.3. Estructura del documento . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.4. Middleware de referencia . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.5. Convenciones tipográficas . . . . . . . . . . . . . . . . . . . . . . . . . 9 2. Antecedentes 11 2.1. Entornos inteligentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2. Aplicaciones distribuidas . . . . . . . . . . . . . . . . . . . . . . . . . 13 2.3. 2.2.1. Primeras aproximaciones . . . . . . . . . . . . . . . . . . . . . . 13 2.2.2. Llamada a procedimiento remoto . . . . . . . . . . . . . . . . . . 14 2.2.3. Invocación a método remoto . . . . . . . . . . . . . . . . . . . . . 17 Sistemas Distribuidos Heterogéneos . . . . . . . . . . . . . . . . . . . . 17 2.3.1. Nomenclatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.3.2. Servicios comunes . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.3.3. CORBA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 XI i i i i i i i i ÍNDICE GENERAL XII 2.3.4. 2.4. 2.5. 2.6. ZeroC Ice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Miniaturización de middlewares generalistas . . . . . . . . . . . . . . . 37 2.4.1. Minimum CORBA . . . . . . . . . . . . . . . . . . . . . . . . . . 38 2.4.2. e*ORB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 2.4.3. Gibraltar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 2.4.4. nORB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 2.4.5. dynamicTAO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 2.4.6. UIC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 2.4.7. LegORB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 2.4.8. MicroQoSCORBA . . . . . . . . . . . . . . . . . . . . . . . . . . 46 2.4.9. Smart Transducer Interface . . . . . . . . . . . . . . . . . . . . . 47 2.4.10. UORB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 2.4.11. I CE -E . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Middlewares para redes de sensores . . . . . . . . . . . . . . . . . . . . 50 2.5.1. SINA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 2.5.2. DSWare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 2.5.3. TinyDB . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 2.5.4. Cougar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 2.5.5. Maté . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 2.5.6. Magnet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 2.5.7. SensorWare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 2.5.8. MiLAN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 2.5.9. TinyCubus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 2.5.10. Impala . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 2.5.11. TinyLime . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 2.5.12. EnviroTrack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 2.5.13. Kairos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 2.5.14. WSP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 2.5.15. C OPRA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Encaminamiento en redes heterogéneas . . . . . . . . . . . . . . . . . . 69 2.6.1. Protocolo de red universal . . . . . . . . . . . . . . . . . . . . . . 69 2.6.2. Pasarelas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 i i i i i i i i ÍNDICE GENERAL 2.7. XIII 2.6.3. Protocolos híbridos . . . . . . . . . . . . . . . . . . . . . . . . . . 76 2.6.4. Redes «inmersivas» . . . . . . . . . . . . . . . . . . . . . . . . . 78 Descubrimiento de servicios y recursos . . . . . . . . . . . . . . . . . . 78 2.7.1. Terminología . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 2.7.2. Prestaciones habituales . . . . . . . . . . . . . . . . . . . . . . . . 79 2.7.3. Descubrimiento de Servicios en redes ad hoc y SAN . . . . . . . . 81 3. Objetos Distribuidos Universales 83 3.1. Nomenclatura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 3.2. Interfaces escalares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 3.2.1. Actuación relativa . . . . . . . . . . . . . . . . . . . . . . . . . . 87 3.3. Contenedores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 3.4. Actores activos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 3.4.1. Reactivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 3.4.2. Proactivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 3.4.3. Activación condicional . . . . . . . . . . . . . . . . . . . . . . . . 92 3.5. Componentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 3.6. Actores compuestos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 3.7. 3.6.1. Actor compuesto activo . . . . . . . . . . . . . . . . . . . . . . . 96 3.6.2. Distribución . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Composición básica de servicios . . . . . . . . . . . . . . . . . . . . . 97 3.7.1. Cableado virtual . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 3.7.2. Servicios reactivos . . . . . . . . . . . . . . . . . . . . . . . . . . 98 3.7.3. Relaciones n-arias . . . . . . . . . . . . . . . . . . . . . . . . . . 98 3.8. Consulta múltiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 3.9. Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 4. picoObjetos 103 4.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103 4.2. Una estrategia diferente . . . . . . . . . . . . . . . . . . . . . . . . . . 107 4.2.1. 4.3. El objeto mínimo . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 Interoperabilidad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 4.3.1. picoCORBA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110 i i i i i i i i ÍNDICE GENERAL XIV 4.3.2. 4.4. Funcionamiento del picoObjeto . . . . . . . . . . . . . . . . . . . . . . 115 4.4.1. 4.5. 4.6. 4.7. picoIce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Máquina de estados . . . . . . . . . . . . . . . . . . . . . . . . . 115 Especificación de picoObjetos . . . . . . . . . . . . . . . . . . . . . . . 116 4.5.1. Gestión de los datos . . . . . . . . . . . . . . . . . . . . . . . . . 117 4.5.2. Utilidades auxiliares . . . . . . . . . . . . . . . . . . . . . . . . . 120 4.5.3. Repertorio de instrucciones FSM . . . . . . . . . . . . . . . . . . 120 4.5.4. Bloques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 4.5.5. Subrutinas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 4.5.6. Eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 4.5.7. Sirvientes, código de usuario . . . . . . . . . . . . . . . . . . . . 124 4.5.8. Bytecode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 4.5.9. Limitaciones y saltos . . . . . . . . . . . . . . . . . . . . . . . . . 126 Transformación de FSM a bytecode . . . . . . . . . . . . . . . . . . . . 127 4.6.1. Optimizaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 4.6.2. Generación del bytecode . . . . . . . . . . . . . . . . . . . . . . . 129 Máquina virtual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 4.7.1. Comunicación con el sirviente . . . . . . . . . . . . . . . . . . . . 130 4.8. Generación de código nativo . . . . . . . . . . . . . . . . . . . . . . . . 130 4.9. Despliegue de aplicaciones en la SAN . . . . . . . . . . . . . . . . . . . 130 4.10. Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131 5. Descubrimiento del entorno 133 5.1. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 5.2. Elementos básicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 5.2.1. Canales de eventos . . . . . . . . . . . . . . . . . . . . . . . . . . 135 5.2.2. Propiedades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 5.2.3. Taxonomía . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 5.3. Prestaciones de ASDF . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 5.4. Anunciamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 5.5. Descripción de servicios . . . . . . . . . . . . . . . . . . . . . . . . . . 140 5.5.1. Servicios proporcionados . . . . . . . . . . . . . . . . . . . . . . 141 5.5.2. Persistencia de las propiedades . . . . . . . . . . . . . . . . . . . 142 i i i i i i i i ÍNDICE GENERAL 5.5.3. 5.6. XV Servidor de propiedades . . . . . . . . . . . . . . . . . . . . . . . 143 Búsqueda de servicios . . . . . . . . . . . . . . . . . . . . . . . . . . . 143 5.6.1. Directorio distribuido puro . . . . . . . . . . . . . . . . . . . . . . 144 5.6.2. Directorio híbrido . . . . . . . . . . . . . . . . . . . . . . . . . . 144 5.6.3. Directorio centralizado . . . . . . . . . . . . . . . . . . . . . . . . 145 5.6.4. Directorio jerárquico . . . . . . . . . . . . . . . . . . . . . . . . . 146 5.6.5. Anunciamiento reactivo . . . . . . . . . . . . . . . . . . . . . . . 147 5.7. Servicio de metamodelo . . . . . . . . . . . . . . . . . . . . . . . . . . 148 5.8. Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 6. Flujo de diseño 6.1. 6.2. 6.3. 151 Lenguaje IcePick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 6.1.1. Especificación de interfaces . . . . . . . . . . . . . . . . . . . . . 153 6.1.2. Objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153 6.1.3. Adaptadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154 6.1.4. Eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155 6.1.5. Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 6.1.6. Atributos por defecto en objetos . . . . . . . . . . . . . . . . . . . 157 6.1.7. Métodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 Lenguaje SIS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 6.2.1. Métodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159 6.2.2. Eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 El compilador ipkc . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 6.3.1. Estructura general . . . . . . . . . . . . . . . . . . . . . . . . . . 161 6.3.2. Frontal para IcePick . . . . . . . . . . . . . . . . . . . . . . . . . 162 6.3.3. Frontal para SIS . . . . . . . . . . . . . . . . . . . . . . . . . . . 162 6.3.4. Frontal para S LICE . . . . . . . . . . . . . . . . . . . . . . . . . . 162 6.3.5. Compilador extensible . . . . . . . . . . . . . . . . . . . . . . . . 166 6.3.6. Soporte para macro-programación . . . . . . . . . . . . . . . . . . 166 6.3.7. Generación de FSM . . . . . . . . . . . . . . . . . . . . . . . . . 168 6.4. Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170 6.5. Plataforma para desarrollo de picoObjetos . . . . . . . . . . . . . . . . 171 i i i i i i i i ÍNDICE GENERAL XVI 7. Integración de redes heterogéneas 7.1. 175 Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 7.1.1. Inter-redes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 7.1.2. Encaminamiento homogéneo . . . . . . . . . . . . . . . . . . . . 178 7.1.3. Acerca de los prototipos . . . . . . . . . . . . . . . . . . . . . . . 179 7.2. Direccionamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179 7.2.1. Identidad del objeto . . . . . . . . . . . . . . . . . . . . . . . . . 180 7.2.2. Un posible esquema de direccionamiento . . . . . . . . . . . . . . 180 7.3. Endpoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 7.4. Gestión de calidad de servicio . . . . . . . . . . . . . . . . . . . . . . . 184 7.5. Entrega de mensajes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 7.5.1. Entrega directa . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 7.5.2. Entrega indirecta . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 7.6. Encaminamiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 7.6.1. Encaminamiento dinámico . . . . . . . . . . . . . . . . . . . . . . 189 7.6.2. Gestión de la red . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 7.7. Integración con el middleware . . . . . . . . . . . . . . . . . . . . . . . 190 7.7.1. 7.8. Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 8. Prototipos 8.1. API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192 197 Dispositivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 8.1.1. Motas Crossbow . . . . . . . . . . . . . . . . . . . . . . . . . . . 197 8.1.2. TINI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 8.1.3. NXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 8.1.4. XPort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 8.1.5. WIZnet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 8.1.6. Cámaras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 8.2. Máquina virtual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201 8.3. TwinPanel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 8.4. Servicios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 8.4.1. PropertyServer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 8.4.2. ContextServer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 i i i i i i i i ÍNDICE GENERAL 8.5. XVII 8.4.3. CacheService . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 8.4.4. CameraServer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206 8.4.5. ChannelMonitor . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 Activos experimentales . . . . . . . . . . . . . . . . . . . . . . . . . . 209 8.5.1. Actor mínimo . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 8.5.2. Otros actores sencillos . . . . . . . . . . . . . . . . . . . . . . . . 210 8.5.3. Cerradura inteligente . . . . . . . . . . . . . . . . . . . . . . . . . 211 8.5.4. Control de consumo . . . . . . . . . . . . . . . . . . . . . . . . . 212 8.5.5. Placas de prototipado . . . . . . . . . . . . . . . . . . . . . . . . 213 8.5.6. Cableado virtual . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 8.5.7. Termostato . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 8.5.8. Sensor día/noche . . . . . . . . . . . . . . . . . . . . . . . . . . . 216 8.5.9. Detección de presencia polivalente . . . . . . . . . . . . . . . . . 216 8.5.10. Requisitos de memoria . . . . . . . . . . . . . . . . . . . . . . . . 218 8.6. 8.7. 8.8. Análisis de protocolos . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 8.6.1. DUO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 8.6.2. ASDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Prototipos IDM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222 8.7.1. Latencia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223 8.7.2. Rendimiento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 9. Conclusiones y trabajo futuro 9.1. 225 Infraestructura de integración . . . . . . . . . . . . . . . . . . . . . . . 225 9.1.1. Middleware orientado a objetos . . . . . . . . . . . . . . . . . . . 226 9.1.2. picoObjetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228 9.1.3. Modelo de información . . . . . . . . . . . . . . . . . . . . . . . 228 9.1.4. Descubrimiento de servicios . . . . . . . . . . . . . . . . . . . . . 229 9.1.5. Redes heterogéneas . . . . . . . . . . . . . . . . . . . . . . . . . 229 9.2. Un middleware para WSN . . . . . . . . . . . . . . . . . . . . . . . . . 230 9.3. Resumen de contribuciones . . . . . . . . . . . . . . . . . . . . . . . . 232 9.4. Publicaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232 9.5. Nuevas líneas de trabajo . . . . . . . . . . . . . . . . . . . . . . . . . . 233 i i i i i i i i ÍNDICE GENERAL XVIII 9.5.1. Encaminamiento ad hoc con IDM . . . . . . . . . . . . . . . . . . 234 9.5.2. Plataforma de gestión para redes heterogéneas . . . . . . . . . . . 234 9.5.3. Plataforma de despliegue heterogéneo . . . . . . . . . . . . . . . . 235 9.5.4. Modelado semántico de servicios . . . . . . . . . . . . . . . . . . 235 A. Repertorio de instrucciones FSM 239 B. Servicios Web empotrados 245 B.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246 B.2. Servicios Web en la SAN . . . . . . . . . . . . . . . . . . . . . . . . . 246 B.3. Un enfoque ascendente . . . . . . . . . . . . . . . . . . . . . . . . . . 247 B.3.1. Compilación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250 B.4. Arquitectura de red . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251 B.5. Prototipos EWS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254 B.6. Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255 C. El protocolo Ice C.1. 257 Codificación de datos . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 C.1.1. Tamaños . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 C.1.2. Encapsulaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 C.1.3. Slices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258 C.1.4. Tipos básicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 C.1.5. Cadenas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 C.1.6. Tipos agregados . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 C.1.7. Identidades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 C.2. Proxies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 C.2.1. Endpoints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261 C.3. Mensajes del protocolo . . . . . . . . . . . . . . . . . . . . . . . . . . 262 C.3.1. Cabecera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 263 C.3.2. Cuerpo del mensaje de petición . . . . . . . . . . . . . . . . . . . 263 C.3.3. Cuerpo del mensaje de petición por lotes . . . . . . . . . . . . . . 264 C.3.4. Cuerpo del mensaje de respuesta . . . . . . . . . . . . . . . . . . 265 C.3.5. Mensaje de validación de conexión . . . . . . . . . . . . . . . . . 265 i i i i i i i i ÍNDICE GENERAL XIX C.3.6. Mensaje de cierre de conexión . . . . . . . . . . . . . . . . . . . . 265 D. General Inter-ORB Protocol 267 D.1. Visión general de GIOP . . . . . . . . . . . . . . . . . . . . . . . . . . 267 D.1.1. Representación común de datos (CDR) . . . . . . . . . . . . . . . 269 D.1.2. Mensajes GIOP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 269 D.1.3. Transferencia de mensajes GIOP . . . . . . . . . . . . . . . . . . 270 D.2. Sintaxis de transferencia de CDR . . . . . . . . . . . . . . . . . . . . . 270 D.2.1. Tipos primitivos . . . . . . . . . . . . . . . . . . . . . . . . . . . 271 D.2.2. Tipos compuestos . . . . . . . . . . . . . . . . . . . . . . . . . . 274 D.2.3. Encapsulación . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275 D.3. Formato de los mensajes GIOP . . . . . . . . . . . . . . . . . . . . . . 276 D.3.1. Cabecera GIOP . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277 D.3.2. Mensaje de petición (Request) . . . . . . . . . . . . . . . . . . . . 278 D.3.3. Mensaje de respuesta (Reply) . . . . . . . . . . . . . . . . . . . . 279 D.3.4. Mensaje de cancelación de petición (CancelRequest) . . . . . . . . 281 D.3.5. Mensaje de petición de localización (LocateRequest) . . . . . . . . 282 D.3.6. Mensaje de respuesta de localización (LocateReply) . . . . . . . . 282 D.3.7. Mensaje de finalización de conexión (CloseConnection) . . . . . . 283 D.3.8. Mensaje de error (MessageError) . . . . . . . . . . . . . . . . . . 283 D.4. Transporte de mensajes GIOP . . . . . . . . . . . . . . . . . . . . . . . 284 E. Interfaces Slice 285 E.1. DUO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 E.2. ASDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 E.3. Property Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 F. GNU Free Documentation License 291 F.0. PREAMBLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291 F.1. APPLICABILITY AND DEFINITIONS . . . . . . . . . . . . . . . . . 291 F.2. VERBATIM COPYING . . . . . . . . . . . . . . . . . . . . . . . . . . 292 F.3. COPYING IN QUANTITY . . . . . . . . . . . . . . . . . . . . . . . . 292 F.4. MODIFICATIONS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292 i i i i i i i i ÍNDICE GENERAL XX F.5. COLLECTIONS OF DOCUMENTS . . . . . . . . . . . . . . . . . . . 294 F.6. AGGREGATION WITH INDEPENDENT WORKS . . . . . . . . . . . 294 F.7. TRANSLATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294 F.8. TERMINATION . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294 F.9. FUTURE REVISIONS OF THIS LICENSE . . . . . . . . . . . . . . . 294 F.10. RELICENSING . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295 Glosario 297 Bibliografía 299 Índice alfabético 311 i i i i i i i i Índice de cuadros 2.1. Semánticas de RPC en presencia de distintos fallos . . . . . . . . . . . . 16 2.2. nORB: Tamaños de programa para una aplicación de referencia . . . . . . 43 2.3. Memoria necesaria para algunas configuraciones de UIC . . . . . . . . . 45 2.4. MQC: Comparativa de memoria necesaria . . . . . . . . . . . . . . . . . 47 2.5. Maté: Requerimientos de memoria . . . . . . . . . . . . . . . . . . . . . 56 2.6. SensorWare: Requerimientos de memoria . . . . . . . . . . . . . . . . . 57 2.7. Impala: Requerimientos de memoria . . . . . . . . . . . . . . . . . . . . 63 2.8. WSP: Requerimientos de memoria . . . . . . . . . . . . . . . . . . . . . 68 5.1. ASDF: Resumen de las prestaciones del protocolo . . . . . . . . . . . . . 149 6.1. Tokens del lenguaje IcePick . . . . . . . . . . . . . . . . . . . . . . . . 163 6.2. Tokens del lenguaje SIS . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 8.1. Memoria requerida por la máquina virtual de picoObjetos . . . . . . . . . 204 8.2. Memoria requerida para varios prototipos . . . . . . . . . . . . . . . . . 220 8.3. I CE y DUO: Tamaño de los mensajes . . . . . . . . . . . . . . . . . . . . 221 8.4. ASDF: Tamaño de los mensajes . . . . . . . . . . . . . . . . . . . . . . 222 8.5. IDM: Pruebas de latencia . . . . . . . . . . . . . . . . . . . . . . . . . . 224 8.6. IDM: Pruebas de rendimiento . . . . . . . . . . . . . . . . . . . . . . . . 224 A.1. FSM: Resumen del juego de instrucciones . . . . . . . . . . . . . . . . . 244 B.1. Comparativa de tamaños de un WS para un servicio get/set básico . . . . 254 C.1. Tamaño de los tipos básicos de Slice . . . . . . . . . . . . . . . . . . . . 259 XXI i i i i i i i i XXII ÍNDICE DE CUADROS D.1. Alineación requerida para los tipos primitivos de IDL . . . . . . . . . . . 271 D.2. Tamaño y ordenamiento de los tipos IDL enteros . . . . . . . . . . . . . 272 D.3. Tamaño y ordenamiento de los tipos IDL de punto flotante . . . . . . . . 273 D.4. GIOP: Tipos de mensajes . . . . . . . . . . . . . . . . . . . . . . . . . . 276 i i i i i i i i Índice de figuras 2.1. Arquitectura CORBA . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.2. Métodos de entrega de eventos en un modelo híbrido . . . . . . . . . . . 29 2.3. Representación de las características omitidas en Minimum CORBA respecto a CORBA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 2.4. Representación de un sistema STI . . . . . . . . . . . . . . . . . . . . . 48 2.5. Relación de MiLAN con las capas de red inferiores . . . . . . . . . . . . 59 2.6. Arquitectura de capas de Impala . . . . . . . . . . . . . . . . . . . . . . 62 2.7. Nodo ZebraNet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 2.8. Combinación de Stargate y mota MICA2 usada en un prototipo de Kairos 66 2.9. Estructura de un nodo WSP . . . . . . . . . . . . . . . . . . . . . . . . . 67 2.10. Encaminamiento de mensajes CORBA . . . . . . . . . . . . . . . . . . . 71 2.11. Red SAN con una pasarela explícita . . . . . . . . . . . . . . . . . . . . 74 3.1. Diagramas de secuencia del actor reactivo y el proactivo . . . . . . . . . 91 3.2. Actor DUO::IByte::R compuesto según patrón de diseño . . . . . . . . . 95 3.3. Actor DUO::IByte::R compuesto con interfaces DUO . . . . . . . . . . . 96 3.4. Ejemplo de cableado virtual . . . . . . . . . . . . . . . . . . . . . . . . 100 3.5. Diagrama de secuencia de una consulta múltiple . . . . . . . . . . . . . . 101 4.1. Comparación de una invocación convencional con una a picoObjeto . . . 105 4.2. Representación gráfica de CORBA, Minimum CORBA y picoCORBA . . . 108 4.3. Ejemplo de una máquina de estados para dos objetos I CE sencillos . . . . 117 5.1. Clases de servicios definidos en la taxonomía . . . . . . . . . . . . . . . 137 5.2. Diagrama de secuencia de un anunciamiento . . . . . . . . . . . . . . . . 139 5.3. Ejemplo de herencia múltiple de interfaces para servicios . . . . . . . . . 142 XXIII i i i i i i i i XXIV ÍNDICE DE FIGURAS 5.4. Búsqueda de servicios con directorio distribuido puro . . . . . . . . . . . 145 5.5. Delegación de la búsqueda de servicios al dominio superior . . . . . . . . 147 6.1. Diagrama simplificado del proceso de compilación . . . . . . . . . . . . 152 6.2. Diagrama de bloques del compilador ipkc . . . . . . . . . . . . . . . . . 161 6.3. Ejemplo de macro-programación . . . . . . . . . . . . . . . . . . . . . . 168 6.4. Plataforma completa para desarrollo y prueba de picoObjetos . . . . . . . 172 6.5. Distintos roles en la creación del entorno inteligente . . . . . . . . . . . . 173 7.1. IDM: Ejemplo de encaminamiento funcional . . . . . . . . . . . . . . . . 181 7.2. Un posible esquema de direccionamiento para IDM . . . . . . . . . . . . 181 7.3. Relación de IDM con el modelo de capas de red tradicional . . . . . . . . 182 7.4. Una inter-red IDM formada por 4 redes IDM . . . . . . . . . . . . . . . . 186 7.5. Diagrama de bloques de IDM . . . . . . . . . . . . . . . . . . . . . . . . 188 7.6. Comparación entre un encaminador IP y uno IDM . . . . . . . . . . . . . 189 7.7. IDM: Invocación de un objeto IDM remoto . . . . . . . . . . . . . . . . 191 8.1. Motas Crossbow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198 8.2. Módulo DSTINI1 en el socket E10 . . . . . . . . . . . . . . . . . . . . . 199 8.3. Aspecto del NXT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 8.4. XPort y WIZnet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200 8.5. Cámaras de vídeo utilizadas en los prototipos . . . . . . . . . . . . . . . 201 8.6. TwinPanel, aspecto general . . . . . . . . . . . . . . . . . . . . . . . . . 205 8.7. TwinPanel inspeccionando un contexto alojado en un ContextServer . . . 207 8.8. TwinPanel inspeccionando el CacheService . . . . . . . . . . . . . . . . 207 8.9. TwinPanel inspeccionando una cámara servida por CameraServer . . . . 209 8.10. Cerradura electrónica controlada por un picoObjeto . . . . . . . . . . . . 212 8.11. Prototipo para control de consumo eléctrico . . . . . . . . . . . . . . . . 212 8.12. Placa de prototipado para picoObjetos (ALSO1) . . . . . . . . . . . . . . 213 8.13. Interruptor inalámbrico para cableado virtual . . . . . . . . . . . . . . . 214 8.14. Topología de red utilizada para las pruebas de rendimiento . . . . . . . . 223 9.1. Esquema general de la infraestructura de integración de redes SAN . . . . 226 i i i i i i i i ÍNDICE DE FIGURAS XXV B.1. Máquina de estados simplificada para los mensajes SOAP get y set . . . 250 B.2. Topología de red para la gestión de luces de emergencia . . . . . . . . . . 252 B.3. Proceso de encapsulación de la pasarela . . . . . . . . . . . . . . . . . . 253 D.1. Diagrama de capas de CORBA . . . . . . . . . . . . . . . . . . . . . . . 268 i i i i i i i i i i i i i i i i Índice de listados 2.1. Interfaz CORBA::Object . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.2. Proxies directos e indirectos en I CE . . . . . . . . . . . . . . . . . . . . . 33 2.3. Interfaz Ice::Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 2.4. Programa de ejemplo de Maté . . . . . . . . . . . . . . . . . . . . . . . 55 3.1. Interfaces DUO escalares . . . . . . . . . . . . . . . . . . . . . . . . . . 86 3.2. Creación de una interfaz para composición de interfaces básicas . . . . . 87 3.3. Interfaz DUO::Func::Relative . . . . . . . . . . . . . . . . . . . . . . . 87 3.4. Módulo DUO::Container para colecciones de objetos . . . . . . . . . . . 88 3.5. Módulo DUO::Active en lenguaje Slice . . . . . . . . . . . . . . . . . . 90 3.6. Interfaz DUO::Component . . . . . . . . . . . . . . . . . . . . . . . . . 93 3.7. Módulo para construcción de actores DUO compuestos . . . . . . . . . . 95 3.8. Actor DUO::IByte::R compuesto . . . . . . . . . . . . . . . . . . . . . . 95 4.1. Ejemplo de uso de las funciones del banco de registros . . . . . . . . . . 119 4.2. Ejemplos de variables FSM . . . . . . . . . . . . . . . . . . . . . . . . . 119 4.3. Ejemplos de constantes FSM (zona DATA) . . . . . . . . . . . . . . . . . 119 4.4. Algunos bloques de ejemplo de un programa FSM . . . . . . . . . . . . . 121 4.5. Parte del bytecode resultante de la compilación de un programa FSM . . . 126 5.1. ASD::Listener: Interfaz para recepción de anunciamientos . . . . . . . . 138 5.2. Services.ice: Definición de interfaces para servicios . . . . . . . . . . 140 5.3. Herencia (incorrecta) de múltiples servicios . . . . . . . . . . . . . . . . 141 5.4. ASD::PropHldr: Delegación de propiedades a un objeto externo . . . . . 143 5.5. ASD::Search: Interfaz para búsqueda de servicios . . . . . . . . . . . . . 144 5.6. Interfaz IceGrid::Query . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 5.7. Interfaz Slice de MIS . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148 6.1. IcePick: Definición de objetos . . . . . . . . . . . . . . . . . . . . . . . 153 XXVII i i i i i i i i XXVIII ÍNDICE DE LISTADOS 6.2. IcePick: Definición de una faceta . . . . . . . . . . . . . . . . . . . . . . 154 6.3. IcePick: Declaración de adaptadores . . . . . . . . . . . . . . . . . . . . 155 6.4. IcePick: Cláusulas para definición de triggers . . . . . . . . . . . . . . . 156 6.5. IcePick: Instrucciones para gestión de eventos . . . . . . . . . . . . . . . 157 6.6. IcePick: Funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 6.7. SIS: Ejemplo de declaración de la interfaz de un sirviente . . . . . . . . . 159 6.8. SIS: Soporte a parámetros de tipos variables . . . . . . . . . . . . . . . . 160 6.9. Gramática del lenguaje IcePick . . . . . . . . . . . . . . . . . . . . . . . 164 6.10. Gramática del lenguaje SIS . . . . . . . . . . . . . . . . . . . . . . . . . 165 6.11. IcePick: Ejemplo de macro-programación . . . . . . . . . . . . . . . . . 167 7.1. Formato de los mensajes IDM . . . . . . . . . . . . . . . . . . . . . . . 183 7.2. Interfaz para administración de perfiles de Q O S en encaminadores IDM . 185 7.3. Interfaz ALP para registro de objetos y localización de adaptadores . . . . 186 7.4. Tabla de rutas IDM simplificada . . . . . . . . . . . . . . . . . . . . . . 188 7.5. Interfaz Slice para el protocolo de encaminamiento RIP . . . . . . . . . . 190 7.6. Implementación de un servidor IDM mínimo . . . . . . . . . . . . . . . 193 7.7. Implementación de un cliente IDM mínimo . . . . . . . . . . . . . . . . 194 8.1. Declaración de un actor que sirve una cámara de vídeo PTZ . . . . . . . . 208 8.2. Objeto mínimo: DUO::Pulse::W con transporte oneway . . . . . . . . . 210 8.3. Un sensor DUO::IBool::R y un actuador DUO::IBool::RW . . . . . . . 210 8.4. Declaración de una interfaz Slice para un sensor activo . . . . . . . . . . 211 8.5. Definición de un sensor booleano proactivo . . . . . . . . . . . . . . . . 211 8.6. Especificación del nodo de control del termostato con alarma . . . . . . . 215 8.7. Sensor día/noche con activación condicional . . . . . . . . . . . . . . . . 217 8.8. Detección de presencia polivalente (iluminación e intrusión) . . . . . . . 219 8.9. Disección de un mensaje ASD::Listener::adv() . . . . . . . . . . . . 222 B.1. Ejemplo de petición SOAP . . . . . . . . . . . . . . . . . . . . . . . . . 247 B.2. Especificación WSDL para el ejemplo descrito . . . . . . . . . . . . . . . 248 B.3. Respuesta SOAP sintetizada . . . . . . . . . . . . . . . . . . . . . . . . 248 B.4. Ejemplo de IcePick para un WS . . . . . . . . . . . . . . . . . . . . . . 251 B.5. Fragmento WSDL para la localización de un nodo . . . . . . . . . . . . . 253 C.1. Formato de codificación de una encapsulación Slice . . . . . . . . . . . . 258 i i i i i i i i ÍNDICE DE LISTADOS XXIX C.2. Estructura de una identidad de objeto I CE . . . . . . . . . . . . . . . . . 260 C.3. Estructura común de un proxy I CE . . . . . . . . . . . . . . . . . . . . . 260 C.4. Estructura de un endpoint TCP . . . . . . . . . . . . . . . . . . . . . . . 261 C.5. Estructura de un endpoint UDP . . . . . . . . . . . . . . . . . . . . . . . 262 C.6. Estructura de un endpoint SSL . . . . . . . . . . . . . . . . . . . . . . . 262 C.7. Protocolo I CE: Formato de la cabecera . . . . . . . . . . . . . . . . . . . 263 C.8. Protocolo I CE: Formato del mensaje de petición . . . . . . . . . . . . . . 264 C.9. Protocolo I CE: Formato del mensaje de petición por lotes . . . . . . . . . 264 C.10. Protocolo I CE: Formato del mensaje de respuesta . . . . . . . . . . . . . 265 D.1. Formato de la cabecera GIOP . . . . . . . . . . . . . . . . . . . . . . . . 277 E.1. DUO.ice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 E.2. ASDF.ice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 E.3. PropertyService.ice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287 E.4. PropertyType.ice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290 i i i i i i i i i i i i i i i i Listado de acrónimos ACE ADAPTIVE Communication Environment ACM Active Connection Management ALP Adapter Location Protocol AmI Ambient Intelligence AMI Asynchronous Method Invocation AMD Asynchronous Method Dispatching ANSI American National Standards Institute AODV Ad hoc On-Demand Distance Vector API Application Program Interface ARCO Arquitectura y Redes de Computadores ARPANET Advanced Research Projects Agency NETwork ASCII American Standard Code for Information Interchange ASDA ASDF Announce ASDF Abstract Service Discovery Framework ASDS ASDF Search ASN Abstract Syntax Notation BOA Basic Object Adapter BSD Berkeley Software Distribution CAN Control Area Network CASE Computer-Aided Software Engineering CBA Content-Based Addresses CCD Charge Coupled Device CCITT Comité Consultatif International Téléphonique et Télégraphique CCM CORBA Component Model CDR Common Data Representation CIDL Component Implementation Definition Language CIOP IOP sobre DCE CMR CORBA Message Routing CORBA Common Object Request Broker Architecture CPD Centro de Proceso de Datos XXXI i i i i i i i i LISTADO DE ACRÓNIMOS XXXII CPU Central Processing Unit CRC Cyclic Redundancy Check DAIS Declarative Applications in Immersive Sensor networks DARPA Defense Advanced Research Projects Agency DBA Distributed Breakout Algorithm DCE Distributed Computing Environment DCOM Distributed Component Object Model DHCP Dynamic Host Configuration Protocol DII Dynamic Invocation Interface DNS Domain Name System DOBS Distributed Object Based Services DPS Distributed Programming System DSI Dynamic Skeleton Interface DSL Domain-Specific Language DSP Digital Signal Processor DSWare Data Service middleWare DTN Delay Tolerant Network DUO Distributed Universal Objects EBNF Extended Backus-Naur Form EEPROM Electrically Erasable Programmable Read-Only Memory EJB Enterprise JavaBeans ESIOP Environment Specific IOP EWS Embedded Web Services FPGA Field-Programmable Gate Array FSM Finite State Machine FTP File Transfer Protocol GCC GNU Compiler Collection GIOP General IOP GNU GNU is Not Unix GPIO General Purpose Input/Output GPS Global Positioning System GTK The GIMP Toolkit GUI Graphical User Interface GUID Globally Unique IDentifiers HTIOP IOP sobre HTTP HTTP Hypertext Transfer Protocol HTML HyperText Markup Language I2C Inter-Integrated Circuit Ice Internet Communications Engine i i i i i i i i LISTADO DE ACRÓNIMOS Ice-E Embedded I CE IceP I CE Protocol IDL Interface Definition Language IDM Inter-Domain Messaging IEC International Electrotechnical Commission IEEE Institute of Electrical and Electronics Engineers IETF Internet Engineering Task Force IFS Interface File System IIOP Internet IOP IOP Inter-ORB Protocol IOR Interoperable Object Reference IP Internet Protocol IPC Inter-Process Communication IPv6 IP versión 6 IR Interface Repository ISA Instruction Set Architecture ISO International Organization for Standardization ISTAG Information Society Technologies Advisory Group JVM Java Virtual Machine LAN Local Area Network LCD Liquid Crystal Display LDR Light Dependent Resistor LED Light Emitting Diode LIME Linda in Mobile Environments M-JPEG Motion JPEG MAC Media Access Control MANET Mobile Ad-hoc Network MDOO Middleware Distribuido Orientado a Objetos MiLAN Middleware Linking Applications and Networks MIS Model Information Service MQC MicroQoSCORBA MTU Maximum Transmission Unit MVC Model-View-Controller NAT Network Address Translation NEST Networked Embedded System Technology NDR Network Data Representation NFS Network File System OASIS Organization for the Advancement of Structured Information Standards OID Object Identity XXXIII i i i i i i i i LISTADO DE ACRÓNIMOS XXXIV OMA Object Management Architecture OMG Object Management Group ONC Open Network Computing OO Orientación a Objetos ORB Object Request Broker OSGi Open Systems Gateway Initiative OSI Open Systems Interconnection OSF Open Software Foundation OWL Ontology Web Language P2P Peer to Peer PAL Phase Alternating Line PARC Palo Alto Research Center PC Personal Computer PCP Procedure Call Protocol PDA Personal Digital Assistant PDP Pervasive Discovery Protocol PIR Passive Infra Red PLC Power Line Carrier POA Portable Object Adapter POO Programación Orientada a Objetos PPE Protocol Processing Stages PPS Protocol Precessing Engines PTZ Pan-Tilt-Zoom QoS Quality of Service RAM Random Access Memory RFC Request For Comments RIP Routing Information Protocol RMI Remote Method Invocation ROM Read Only Memory RPC Remote Procedure Call RSI Rutina de Servicio de Interrupción RTE Run-Time Environment RTSP Real Time Streaming Protocol SA Sistema Autónomo SAN Sensor Actuator Network SAX Simple API for XML SDP Service Discovery Protocol SENDA Services and Networks for Domotic Applications SIMM Single In-line Memory Module i i i i i i i i LISTADO DE ACRÓNIMOS SI Sistema de Información SINA Sensor Information Networking Architecture SIS Servant Interface Specification Slice Specification Language for Ice SLIP Serial Line Internet Protocol SLOC Source Lines of Code SLP Service Location Protocol SMS Short Message Service SO Sistema Operativo SOA Service Oriented Architecture SOAP Simple Object Access Protocol SPI Serial Peripheral Interface SQL Structured Query Language SQTL Sensor Query and Tasking Language SRAM Static Random Access Memory SSDP Simple Service Discovery Protocol SSL Secure Socket Layer SSLIOP IOP over SSL ST Smart Transducer STI Smart Transducer Interface SVG Scalable Vector Graphics TAO The ACE ORB Tcl Tool Command Language TCP Transmission Control Protocol TCP/IP Arquitectura de protocolos de Internet TDMA Time Division Multiple Access TINI Tiny InterNet Interface TMN Telecommunications Management Network ToS Type of Service TTL Time To Live UART Universal Asynchronous Receiver/Transmitter UIC Universally Interoperable Core UDDI Universal Description Discovery and Integration UDP User Datagram Protocol UPnP Universal Plug and Play UORB Ubiquitous ORB USART Universal Synchronous Receiver/Transmitter USB Universal Serial Bus UTF Unicode Transformation Format XXXV i i i i i i i i LISTADO DE ACRÓNIMOS XXXVI V-ISA Virtual ISA VLC Video LAN Client VM Virtual Machine VPN Virtual Private Network WASP Wirelessly Accessible Sensor Populations WS Web Services WSN Wireless Sensor Network WSAN Wireless Sensor-Actuator Network WSDL Web Services Definition Language XBow Crossbow XDR eXternal Data Representation XML Extensible Markup Language XML-RPC RPC sobre XML i i i i i i i i Agradecimientos Como es lógico y normal ésta será, probablemente, la única hoja que leerá la mayor parte de la gente que llegue a abrir este libro. No lo digo tanto por la falta de interés que puedan tener sino por el probable desconocimiento del tema. Entre esas personas está mi familia. A pesar de que todo este mundo les pueda resultar ajeno y extraño, sé que están tan orgullos de mí como yo de ellos. Les agradezco su apoyo, paciencia y comprensión al dejarme elegir esta profesión. Al menos lograré formar parte de ese nada exclusivo club de los M C D1 . Desgraciadamente el país en el que vivimos otorga poco valor a una tesis doctoral. Normalmente los que nos metemos en esta aventura buscamos algo distinto al reconocimiento o estatus social. En mi caso, confieso que la universidad me ha dado la oportunidad de dedicarme a cosas en las que tengo claro que es casi imposible trabajar en la empresa, en la española al menos. He de admitir que he disfrutado con ello, no sólo con el trabajo técnico o científico. Las discusiones, propuestas e incluso peleas en torno al desarrollo de las ideas y los prototipos han sido para mí el mejor aliciente y el motivo no es otro que la gente tan agradable y capaz con la que tengo la suerte de trabajar cada día. Quiero expresar mi agradecimiento y admiración a mis directores: Francisco Moya y Juan Carlos López. A Paco por su infinita paciencia, por estar siempre dispuesto a escuchar cualquier problema (o «solución»), por compartir con nosotros su impresionante capacidad técnica y aplicar sus particulares dotes diplomáticas en los escasos momentos en los que las aguas salieron de su cauce. A Juan Carlos por su constante preocupación por el trabajo bien hecho, por darme su confianza y demostrarme que no siempre el camino fácil es el mejor. Por supuesto quiero agradecer el buen ambiente que hay tanto arriba como en el laboratorio. Gracias a Fernando, Jesús, Paco Sánchez, David de la Fuente, María José y especialmente a Félix que, como compañero de despacho, sufre más que nadie mis desvaríos, tanto en cuestiones de docencia como de investigación. Y lo mismo puedo decir de los tecnólogos, becarios y colaboradores del grupo ARCO. Gracias a Cleto, sobre todo en el último año a cargo del compilador de IcePick, que ha experimentado como nadie el concepto de requisitos dinámicos. A Javieralso por las incontables e interminables horas de pelea constante con los picos, sufriendo la desesperación que conlleva trabajar con hardware, algo difícil de entender para los que no se han visto en la tesitura. A Oscarah por su estupendo trabajo a cargo de los prototipos de TwinPanel, IDM y EWS entre otros; su profesionalidad resulta inspiradora. Tampoco se han librado Tobías, Lucas, Miguel Ángel, Peris y Nacho; ni Top, Magmax y Víctor, 1 Mileuristas con Doctorado i i i i i i i i aunque estos últimos ya no estén con nosotros, tuvieron el buen juicio de irse a tiempo. También a Carlos González por sus consejos sobre la cubierta. Debo agradecer al Ministerio de Industria, Comercio y Telecomunicaciones, a la Junta de Comunidades de Castilla-La Mancha y al Fondo Europeo de Desarrollo Regional la financiación parcial de este trabajo por medio de los proyectos SODA (TIN2005-08719), Hesperia (CENIT 2005), MARISA (PBC-05-0009) y RGRID (PAI08-0234-8083). De manera especial quiero agradecer a Gloria su tremenda paciencia, su constante apoyo y comprensión. No es sencillo entender que durante estos años haya antepuesto muchas veces (demasiadas) mi trabajo a mi vida personal, robándole horas que eran suyas. También le agradezco su gran labor revisando incansablemente este documento, con un nivel de detalle y precisión que costaría creer a quien no la conozca personalmente. Ella siempre está ahí para mí. Sé que no es fácil, y no puedo por menos que ofrecerle mi más profunda gratitud y todo mi cariño. Mi más sincero agradecimiento a todos los compañeros de ARCO, por ser amigos, y no sólo colegas. Me siento afortunado de poder contar con gente de tanta calidad humana y profesional. No lo habría logrado sin vosotros. David i i i i i i i i 11 Introducción 1.1. 1.2. 1.3. 1.4. 1.5. Redes de sensores Objetivos de la investigación Estructura del documento Middleware de referencia Convenciones tipográficas C UALQUIER sistema de información que realice algún tipo de interacción con el entorno obtiene la mayor parte de sus datos a través de sensores y responde por medio de actuadores. La utilización de estos dispositivos en el ámbito industrial, doméstico, académico, etc., está creciendo y dando lugar a nuevas aplicaciones en diversos campos: domótica, inmótica, e-health y computación ubicua, pervasive computing, A M I, etc. Todas estas tecnologías, que se pueden encuadrar en lo que habitualmente se conocen como entornos inteligentes, constituyen un nuevo paradigma en la forma en la que los sistemas de cómputo se relacionan con las personas y el entorno. La tendencia actual parece indicar que su uso aumentará a medio y largo plazo. La computación ubicua y su aplicación para la creación de entornos inteligentes se basa en las posibilidades de comunicación con estos sensores y actuadores, desplegados masivamente en el entorno. Para varios autores [RMKC00, RKM02], el éxito de estos sistemas depende en gran parte de la disponibilidad de medios que logren la interoperabilidad entre todos estos dispositivos, tecnologías y redes heterogéneas. Ello implica interfaces y protocolos bien definidos que les proporcionen un medio sencillo y eficiente para exportar los servicios que pueden proporcionar. Esas son precisamente algunas de las prestaciones típicas de un middleware de comunicaciones. Sin embargo, se da una circunstancia interesante que puede estar condicionando el desarrollo de una industria alrededor de los entornos inteligentes. Una parte considerable de esos sensores o actuadores son dispositivos muy simples en la forma en la que el sistema interactúa con ellos; su función principal es ofrecer un único valor escalar como puede ser temperatura, intensidad luminosa, presión, presencia, etc. En contraposición, gran parte de las propuestas y plataformas que se vienen utilizando (muchas materia de investigación) imponen una importante sobrecarga en muchos aspectos y ello repercute dramáticamente en el coste final del conjunto. Consideramos que ése es uno de los motivos 1 i i i i i i i i 2 1. I NTRODUCCIÓN —probablemente el más grave— por el que sigue siendo inviable la adopción masiva de estas aplicaciones en el mercado de consumo. En este tipo de plataformas, la cantidad de memoria externa de los dispositivos empleados va desde los 32 KiB en plataformas WesC hasta 64 MiB en la plataforma Rockwell WINS 3.0 [KHH05, PH05, WIN]. Del mismo modo, el microcontrolador incluido en la plataforma Crossbow MICA1 , es un ATmega128L, varios órdenes de magnitud más caro que el microcontrolador más sencillo que existe en el mercado. Estas plataformas consumen una cantidad de recursos considerable, aunque los nodos sensores implementen una funcionalidad mínima. Por ejemplo, Open Systems Gateway Initiative (OSG I) [All06], una de las tecnologías con mayor aceptación en el mundo de la domótica, necesita dispositivos que requieren una máquina Java con soporte RMI, lo cual implica un precio mínimo de alrededor de 30e por unidad. Pensar que este tipo de dispositivo es necesario para cada punto de luz, interruptor, detector de paso, presencia, etc., es algo completamente inadmisible en muchos aspectos, no sólo el económico. Eso implica una importante contradicción: dispositivos muy sencillos y potencialmente muy baratos, tienen precios desorbitados debido a las necesidades de cómputo que requiere el software que permite conectarlos al sistema. Como resultado, el coste del dispositivo que ofrece la funcionalidad real (sensor o actuador) es marginal en relación al coste total del nodo al que está conectado. A primera vista puede parecer que el coste de un despliegue con cualquiera de estas tecnologías no es tan alto. Pero si se toma en consideración que cualquier aplicación de ambient intelligence o instalación domótica con una funcionalidad digna de mención puede involucrar decenas o centenares de dispositivos tales como sensores de movimiento, de proximidad, micrófonos, detectores de paso, cerraduras electrónicas y un largo etcétera, implica que el precio total de la instalación resulte totalmente prohibitivo. Además muchas de esas plataformas resultan insuficientes o ineficientes cuando, en la misma infraestructura de comunicaciones, se pretende integrar aplicaciones que requieren un ancho de banda elevado, como puede ser la transmisión de flujos multimedia. Otro aspecto importante es la interoperabilidad entre aplicaciones, servicios y dispositivos. Lo habitual es que cada fabricante utilice sus propios dispositivos, protocolos e infraestructura física de comunicaciones. Por ejemplo, un sensor de presencia del sistema de seguridad no puede ser utilizado por las aplicaciones de mejora del confort, de modo que es necesario instalar otro dispositivo que tiene prácticamente la misma funcionalidad, pero que se comunica utilizando interfaces y protocolos de un fabricante distinto. Intentar atar al cliente a una tecnología o fabricante concreto es una estrategia de mercado habitual pero, en este caso, los gastos del equipo, instalación y despliegue sobrepasan las ventajas que se obtienen. Sin embargo, con el enfoque, medios y herramientas adecuadas es posible diseñar, implementar y fabricar nodos sensores y actuadores de complejidad no trivial, dotarlos de inteligencia local y reduciendo su coste a una décima parte, como mínimo. A pesar del interés que tiene esa posibilidad, es importante señalar de nuevo que el auténtico 1 La más utilizada en redes de sensores inalámbricas. i i i i i i i i 1. I NTRODUCCIÓN 3 objetivo no es el bajo coste. Ese es sólo un requisito que permitirá afrontar el auténtico reto: la posibilidad de diseñar e implementar sistemas de sensores y actuadores lo suficientemente ricos, por cantidad y calidad de la información que manejan, como para plantear aplicaciones realmente innovadoras en entornos inteligentes. Solo con un precio de unos pocos euros por unidad es razonable pensar en aplicaciones que impliquen alguna de las siguientes circunstancias: Despliegue o instalación de gran número de dispositivos en la oficina o el hogar: cientos o miles. Condicionantes que supongan la destrucción de los dispositivos, tales como observación y/o control de fenómenos naturales como volcanes o incendios. Aplicaciones que, por la ubicación de los dispositivos, impliquen costes de mantenimiento implanteables: glaciares, exploración submarina o extraterreste, etc. 1.1. Redes de sensores Las redes formadas por los dispositivos mencionados reciben varias denominaciones dependiendo de las capacidades, tecnología de comunicaciones, protocolos de encaminamiento de mensajes, etc. Una de las variantes más relevantes en los últimos años son las llamadas WSN (Wireless Sensor Network). Según [RKM02]: Una red de sensores inalámbricos (WSN) consiste en un gran número de pequeños nodos, con capacidad de cómputo limitada, que cooperan en tareas de detección y se comunican con tecnologías de comunicaciones inalámbricas. Para las aplicaciones y servicios del sistema no debería haber ninguna diferencia en el tipo de comunicaciones (cableadas, inalámbricas o mixtas) que se requieren para acceder a los nodos. Sin embargo, las comunicaciones tienen una gran influencia en el desempeño y autonomía de la red, los procesos de despliegue, encaminamiento y actualización de software entre otros. La capa de enlace necesita protocolos robustos que soporten bien las frecuentes pérdidas o fallos en la transmisión física de los mensajes. En la capa de red, la naturaleza dinámica y propensa a errores de la red inalámbrica puede producir fragmentación de la red por lo que deben existir mecanismos para solventar las consecuencias, sobre todo, en el caso de redes ad hoc. Aunque no es obligatorio, los nodos de las WSN suelen ser pequeños y utilizar alimentación por medio de baterías, paneles solares o algún otro tipo sistema con poca autonomía o potencia. Por ello, tanto el software empotrado en el nodo como los protocolos implicados deben considerar esta cuestión a fin de conseguir un uso eficiente de la energía disponible. Otro concepto más general, que no implica necesariamente comunicaciones inalámbricas, es la Red de Sensores. La siguiente definición está tomada de [Hae06]: i i i i i i i i 4 1. I NTRODUCCIÓN Una Red de Sensores es un conjunto de pequeños sistemas autónomos, llamados nodos sensores, que cooperan para resolver al menos una aplicación común. Sus tareas incluyen algún tipo de percepción de parámetros físicos. Ampliando aún más el concepto, se puede abordar también el problema de la gestión de nodos actuadores o mixtos sensor/actuador. A estas redes se las denomina SANet o SAN (Sensor Actuator Network) . Cuando la SAN utiliza únicamente comunicaciones inalámbricas se la denomina WSAN (Wireless Sensor-Actuator Network). Incidiendo en la nomenclatura del área, es necesario puntualizar que el concepto de sensor normalmente debe entenderse en un sentido amplio hasta el punto de englobar también a los dispositivos de actuación. Para evitar la confusión que ello pudiera implicar, se utiliza en este texto el término transductor2 para hacer referencia tanto a sensores como actuadores. Por supuesto, se utilizan los términos específicos cuando se pretende distinguirlos. En el caso de redes de dispositivos se utiliza preferentemente el término SAN aunque ocasionalmente y, por respeto a la bibliografía, se emplean otros como WSN y red de sensores que, en algunos casos, pueden englobar actuadores. A pesar de ser una tecnología joven, en la que aún quedan muchos aspectos importantes por resolver, existe ya un gran número de aplicaciones que explotan las características únicas que ofrecen las SAN y, en especial, las WSN. Según [Mar05], los siguientes son algunos de los usos más importantes que se han dado a las redes de sensores y se prevé aumentarán en un futuro próximo. Aplicaciones de monitorización de hábitats naturales. Observación de entorno y sistemas de previsión. Aplicaciones relacionadas con la salud. Aplicaciones militares. Monitorización de edificios inteligentes. Sistemas inteligentes para control del tráfico. Sistemas domóticos y entornos inteligentes. Este trabajo pretende aportar facilidades técnicas para el desarrollo de servicios y aplicaciones que involucren el uso de transductores accesibles de algún modo por medio de redes de comunicaciones. Al mismo tiempo, se persigue una reducción de costes que haga económicamente posible la implantación de las aplicaciones mencionadas. Se utiliza un enfoque integrador de modo que no sea necesario renunciar a dispositivos o tecnologías existentes o futuras. La intención es conseguir un middleware con el que sea posible desarrollar y utilizar aplicaciones dentro y fuera de las redes SAN de forma transparente, evitando la necesidad de utilizar herramientas, tecnologías o paradigmas distintos para una misma aplicación. En muchos aspectos, las redes SAN pueden verse como una particularización de la computación distribuida heterogénea tradicional. No obstante, en este tipo de sistema 2 La definición a la que se refiere es más cercana a la palabra inglesa transducer que al término español. i i i i i i i i 1. I NTRODUCCIÓN 5 distribuido lo más importante no es la productividad en términos de capacidad de cómputo, como suele ocurrir en sistemas grid, clusters, redes malladas mesh networks, etc. En el caso de las SAN son mucho más relevantes otros aspectos como el dimensionamiento adecuado de los recursos o los servicios específicos. Otros escenarios especiales, como las WSN, requieren soluciones a problemas inherentes como movilidad, pérdida temporal de conectividad, autonomía de las baterías, etc. Extendiendo los argumentos de [HMCP04], podemos considerar que en las redes SAN se presentan una serie de particularidades que hacen que el desarrollo de aplicaciones sea diferente al de las redes convencionales: Las redes SAN están conceptual y físicamente distribuidas. Los nodos están dispersos por el espacio físico y, en ocasiones, pueden ser completamente autónomos. Nuestro enfoque trata precisamente de potenciar esta cualidad. Disponibilidad dinámica de nodos. Pueden aparecer o desaparecer nodos en cualquier momento ya sea porque los ha instalado/desplegado un operador o bien porque queden momentáneamente inaccesibles al utilizar comunicaciones inalámbricas. Las aplicaciones demandan ciertas restricciones: disponibilidad de ciertos nodos, servicios y niveles de Q O S, lo que puede implicar la necesidad de replicación u otras técnicas para lograr diferentes niveles de tolerancia ante fallos. Recursos limitados. El ancho de banda de la red, la energía disponible, la memoria y la capacidad de cómputo de los nodos pueden estar gravemente acotados. Aplicaciones cooperativas. Es frecuente y deseable que las aplicaciones puedan compartir el acceso a los nodos y datos que proporcionan, aunque eso puede requerir de cierto control para evitar colapsar las comunicaciones o malgastar energía. Esta tesis propone utilizar middlewares de comunicaciones orientados a objetos para la integración de dispositivos simples en la red. A pesar de que históricamente se ha considerado que arquitecturas como CORBA (Common Object Request Broker Architecture) son pesadas y requieren una importante cantidad de recursos de cómputo [RBW01, Yu004], el presente trabajo aporta argumentos en contra de esa teoría, demostrando que es perfectamente factible implementar objetos distribuidos plenamente operativos en algunos de los dispositivos de cómputo más pequeños y baratos que se fabrican3 y que, a pesar de ello, cumplen los protocolos y estándares aplicables. 1.2. Objetivos de la investigación Tal como se comentaba anteriormente, el objetivo principal de esta tesis es el diseño de una infraestructura para el desarrollo de aplicaciones en entornos inteligentes sobre plataformas de redes de transductores, así como la definición de métodos y servicios para la integración de esta infraestructura con los flujos de diseño de sistemas distribuidos heterogéneos tradicionales. Los resultados incluyen un conjunto de protocolos y herramientas altamente cohesivas y con bajo acoplamiento que facilitan la creación de 3 Tales como microcontroladores de 8 bits con 1024 palabras de memoria de programa y 128 bytes de RAM. i i i i i i i i 6 1. I NTRODUCCIÓN redes SAN de bajo coste y que permiten la integración con otras tecnologías habituales en el campo de aplicación. Además se describe un conjunto de servicios comunes construidos sobre objetos distribuidos estándar, pero diseñados teniendo en cuenta las características de las redes SAN. Eso incluye un protocolo para descubrimiento de servicios y dispositivos, utilidades para distribución de eventos y soporte para monitorización del entorno. Los objetivos específicos se detallan a continuación: Middleware polivalente Se pretende aportar métodos específicos para la implementación de objetos distribuidos completamente autónomos e interoperables sobre plataformas de cómputo empotradas. El principal criterio de diseño consiste en minimizar los requerimientos de memoria y potencia de cálculo. El aspecto más importante es que no se intenta desarrollar un nuevo middleware para redes SAN. Se propone desarrollar métodos que permitan la utilización de un middleware de propósito general en todo el sistema, dentro y fuera de la red o las redes de sensores, pudiendo haber varias y de varios tipos; sin casos especiales. Este planteamiento contrasta fuertemente con todas las propuestas previas. Un nuevo paradigma La integración del middleware de comunicaciones en cualquier elemento del sistema es un logro que conlleva una ventaja decisiva. Para cualquiera de los profesionales que intervienen en el desarrollo de aplicaciones en entornos inteligentes (analistas, diseñadores, programadores, etc.) supone un importante cambio conceptual bajo el cual, esta vez sí, todo es un objeto y en el que cualquier elemento físico o lógico puede verse como una entidad que ofrece servicios al sistema, hasta tal punto que pueden resultar indistinguibles, si se desea. Desde el punto de vista del desarrollador de aplicaciones, un transductor presente en el sistema se comporta exactamente igual que un objeto distribuido convencional, si bien la implementación interna puede ser considerablemente diferente. Descubrimiento del entorno Se pretende aportar un SDP (Service Discovery Protocol) perfectamente compatible con la filosofía de los middlewares para sistemas distribuidos, y que contemple expresamente el enfoque orientado a objetos y las limitaciones propias de los dispositivos de cómputo utilizados para la implementación de picoObjetos. El uso de este protocolo no se limita a la red SAN. Se pretende que sea un SDP de propósito general que pueda ser utilizado para cualquier servicio del sistema. Encaminamiento heterogéneo El objetivo de integración de los nodos de la red de sensores va más allá del mero acceso a la información que pueden ofrecer. La intención es que los propios nodos tengan la posibilidad de acceder por sí mismos a cualquier host o servicio del sistema o, incluso, a nodos de otras redes SAN. El problema aquí es que estas redes suelen utilizar protocolos de red incompatibles entre sí y también con la red troncal, lo cual —en la actualidad— obliga a utilizar pasarelas a nivel de aplicación. i i i i i i i i 1. I NTRODUCCIÓN 7 Se propone el desarrollo de un nuevo protocolo de red que utilice identificadores de objeto como direcciones lógicas y que permita, por medio de encaminadores especiales, transportar mensajes extremo a extremo sin importar los protocolos de red, tecnologías o topología de las redes implicadas. Validación experimental Se pretende validar las propuestas anteriores mediante el desarrollo de un conjunto de prototipos funcionales que demuestren la viabilidad de su implementación sobre aplicaciones reales. 1.3. Estructura del documento El presente documento trata de exponer con detalle todos los aspectos de la problemática presentada anteriormente. A lo largo del texto se ofrecen las soluciones que propone el autor a cada uno de esos problemas, con un enfoque constructivo, abordando primero los problemas técnicos elementales para después ir incorporando servicios con un mayor nivel de abstracción. Para una comprensión más sencilla, el autor aconseja una lectura secuencial del resto del texto. A continuación, se describe brevemente el contenido de cada capítulo. Capítulo 2: «Antecedentes» Se introducen las tecnologías y plataformas relacionadas con el ámbito del problema. También se comentan aproximaciones anteriores, algunas aún en desarrollo, que persiguen objetivos similares a los planteados aquí. Capítulo 3: «Objetos Distribuidos Universales» Es un modelo de información básico que facilita y simplifica sensiblemente la interacción remota de los traductores entre sí y con las aplicaciones. La intención es aprovechar al máximo las posibilidades de los dispositivos empotrados más simples, pero manteniendo la generalidad, es decir, sin que ello suponga plantear casos especiales al acceder a estos dispositivos. Capítulo 4: «picoObjetos» Los picoObjetos son nuestra propuesta para solventar el problema de la miniaturización de middlewares. Este capítulo describe en detalle sus fundamentos, funcionamiento y las estrategias de implementación de los mismos en sistemas empotrados. Se hace una descripción de los requisitos funcionales mínimos necesarios para que un nodo de una red SAN pueda interoperar con una implementación tradicional de un Middleware Distribuido Orientado a Objetos (MDOO). Capítulo 5: «Descubrimiento del entorno» Contiene una descripción de ASDF (Abstract Service Discovery Framework), un protocolo para Descubrimiento de Servicios diseñado para cubrir las necesidades especiales de nodos de redes SAN implementados como picoObjetos, pero planteado como una solución global aplicable al sistema completo. i i i i i i i i 8 1. I NTRODUCCIÓN Capítulo 6: «Flujo de diseño» Este capítulo describe el soporte que se ofrece a diseñadores, integradores y desarrolladores de software empotrado para obtener un máximo aprovechamiento de las aportaciones de esta tesis en la creación de aplicaciones para entornos inteligentes y sistemas de sensorización y control. Se ha desarrollado un compilador y herramientas auxiliares para facilitar y agilizar sensiblemente el proceso de desarrollo. Capítulo 7: «Integración de redes heterogéneas» Disponer de un protocolo de red y soporte de encaminamiento a un nivel de abstracción similar al del middleware ofrece grandes ventajas operativas que pueden influir decisivamente en la factibilidad de ciertas aplicaciones que, de otro modo, sería complejo conseguir. En este capítulo se analizan dichos casos de uso y se describe el protocolo de red que se ha diseñado al efecto. Capítulo 8: «Prototipos» Se argumentará la viabilidad del enfoque y la metodología con un conjunto de prototipos que ofrecen distintos grados de interoperabilidad con CORBA y ZeroC I CE, así como con sus servicios más importantes. Se describen las características, limitaciones y funcionalidad de dichos prototipos y se justifica en qué medida demuestran la consecución de las propuestas desarrolladas a lo largo de todo el documento. Capítulo 9:«Conclusiones y trabajo futuro» Por último, se exponen las conclusiones a las que hemos llegado tras evaluar los resultados obtenidos en aplicación de los prototipos. Como consecuencia de las contribuciones, se han abierto nuevas líneas de trabajo e investigación que el autor considera podrían resultar interesantes en el futuro. Anexo A: «Repertorio de instrucciones FSM» Define el repertorio de instrucciones para especificación del comportamiento de picoObjetos. Incluye el formato, modos de direccionamiento, sintaxis y ejemplos de cada una de las instrucciones. Anexo B: «Servicios Web empotrados» Presenta una propuesta para la implementación de Servicios Web autónomos en plataformas empotradas. Se utiliza una filosofía similar a la de los picoObjetos, pero teniendo en cuenta las características y limitaciones propias de los protocolos empleados en este tipo de sistemas. Se incluyen prototipos específicos. Anexos C: «El protocolo Ice» y D: «GIOP» Debido a la relevancia que tienen los protocolos GIOP e I CE P en la exposición de algunos problemas y soluciones que se tratan a lo largo del documento, se ha considerado oportuno incluir una traducción resumida de la documentación oficial de dichos protocolos. Anexo E: «Interfaces Slice» Es una recopilación de todas las interfaces que se definen a lo largo del documento. i i i i i i i i 1. I NTRODUCCIÓN 1.4. 9 Middleware de referencia Parte de las aportaciones de esta tesis se encuentran en los mecanismos que hacen posible la implementación y utilización de un middleware empotrado. Por ello, el autor considera que la inclusión de la especificación de algunas de las interfaces propuestas, así como ejemplos y fragmentos de código, contribuye a facilitar significativamente la comprensión de los conceptos y procedimientos descritos. Aunque en términos generales los resultados son aplicables a la miniaturización de cualquier MDOO, la mayoría de las especificaciones y ejemplos se refieren al middleware ZeroC I CE. Con ello se pretende definir una línea de referencia a lo largo de todo el documento como medio para evitar complejidad innecesaria a la hora explicar cada una de las aportaciones y sus interrelaciones. 1.5. Convenciones tipográficas Este documento ha sido escrito adoptando las normas básicas de la tradición tipográfica y ortográfica del castellano, siendo [Mar08] una excelente referencia a este respecto. Para evitar posibles ambigüedades en la terminología técnica, a menudo se incluyen —en cursiva y entre paréntesis— los vocablos equivalentes en inglés. Allí dónde no sea posible la traducción del término, o el autor la considere confusa, se utiliza el vocablo original. A fin de facilitar la lectura del texto, se han utilizado algunos convenios adicionales: Los nombres de clases, tipos y otras entidades propias de los lenguajes de programación se escriben con letra palo seco. Las interfaces se escriben en cursiva. Los identificadores de variables, nombres de ficheros, funciones y fragmentos de código aparecen con letra monoespaciada. i i i i i i i i i i i i i i i i Antecedentes 2.1. 2.2. 2.3. 2.4. 2.5. 2.6. 2.7. Entornos inteligentes Aplicaciones distribuidas Sistemas Distribuidos Heterogéneos Miniaturización de middlewares generalistas Middlewares para redes de sensores Encaminamiento en redes heterogéneas Descubrimiento de servicios y recursos 22 E N este capítulo se describen tecnologías, tanto industriales como experimentales, relacionadas con los objetivos planteados en la introducción. Se ofrece una descripción de los sistemas, iniciativas, proyectos, trabajos de investigación, etc., que se aplican, o se podrían aplicar, a la resolución total o parcial de los problemas propuestos. Las primeras secciones introducen los conceptos y paradigmas clásicos involucrados históricamente en el desarrollo de sistemas distribuidos. Después se tratan las plataformas que han tenido o tienen mayor apoyo por parte de la industria y, por último, se hace un repaso a los sistemas más innovadores, siendo muchos de ellos materia de investigación actualmente. 2.1. Entornos inteligentes Los entornos inteligentes (o A M I) son, por su enfoque y características, una de las tecnologías emergentes más influenciada por los sistemas de interacción con el entorno físico y concretamente en su relación con las personas. Según Z ELKHA [ZE98], el entorno inteligente se caracteriza por: Disponer de una gran cantidad de información procedente de dispositivos integrados en el entorno, con capacidad para comunicarse por medio de una red de datos. Poder utilizar esa información para detectar situaciones concretas que afectan a las personas, es decir, son sensibles al contexto. Pueden reconocer necesidades concretas de cada persona de modo que la respuesta del sistema cambia dependiendo de la cada situación o los individuos a los que afecta. 11 i i i i i i i i 12 2. A NTECEDENTES Tienen en cuenta la interacción del usuario con el sistema, especialmente de forma implícita, de modo que se adaptan a situaciones y requisitos cambiantes. Pueden anticipar las necesidades de las personas a partir de experiencia o directrices previas. Desde el punto de vista de la infraestructura tecnológica puede no haber una diferencia significativa con un sistema domótico . Sin embargo, A M I proporciona servicios mucho más complejos basados en la percepción de situaciones y necesidades, y en la capacidad para adaptarse y adelantarse a nuevos requisitos impuestos implícitamente por los usuarios. En estos términos, A M I tiene evidentes relaciones con la computación ubicua o los sistemas pervasivos. Todos estos paradigmas de computación requieren mucha más información del entorno y de medios para filtrarla y clasificarla de modo que resulte útil a sus propósitos. En este contexto nace el concepto de la Internet de cosas (Internet of Things) que hace referencia a la necesidad de obtener información a partir de cualquier elemento del entorno, por insignificante que parezca, incluyendo el mobiliario o la ropa. Esto supone una gran diferencia con los sistemas domóticos, en los que generalmente el usuario interacciona con el sistema de forma explícita. Según el conocido informe del Information Society Technologies Advisory Group (ISTAG) «Scenarios for ambient intelligence in 2010» [DBS+ 01], los requisitos tecnológicos para lograr los objetivos marcados incluyen la disponibilidad de: Hardware especializado integrado en el entorno. Independientemente de su complejidad o sofisticación, este tipo de dispositivos responde claramente a las características de las redes SAN. Una infraestructura de comunicaciones que integre dispositivos móviles y fijos. Es decir, protocolos que permitan acceso e interacción con cualquier elemento independientemente de la red o tecnología que utilice. El informe lo describe con un requisito bastante esclarecedor: «Probablemente todas las redes podrían operar con algo equivalente a la tecnología IP. Es probable que las redes troncales y de acceso converjan». Redes de dispositivos masivamente distribuidas y dinámicas. De nuevo se refiere a redes de sensores, pero además implica middlewares capaces de escalar para trabajar con cantidades enormes de dispositivos y datos, en múltiples dominios y pudiendo adaptarse a entornos cambiantes. La disponibilidad de tanta y tan variada información procedente del entorno no es un requisito baladí. Ya era un grave problema en la domótica [Moy03] debido principalmente a la complejidad de integrar protocolos, dispositivos y herramientas de distintos fabricantes. Los nuevos requisitos que impone A M I agravan aún más esos problemas, además de exigir nuevas y complejas prestaciones. Si bien las redes de sensores tienen aplicación en infinidad de campos, y muchos de los problemas que se presentan aparecen recurrentemente, en los entornos inteligentes tienen un papel protagonista [PST07, BFG06] hasta el punto de que pueden determinar el éxito o fracaso de este paradigma de computación. Por este motivo hemos elegido los entornos inteligentes como hilo conductor sobre el que apoyar nuestras propuestas, aunque sin detrimento de otros posibles usos fuera de este campo. i i i i i i i i 2. A NTECEDENTES 2.2. 13 Aplicaciones distribuidas En una aplicación distribuida el usuario no necesita tener (a veces, no puede tener) conciencia de qué nodo de la red realiza el cómputo o en cuál están almacenados físicamente los datos, y eso es cierto incluso en las aplicaciones cliente-servidor más básicas. La principal diferencia es que en un sistema distribuido el usuario demanda un servicio sin especificar explícitamente dónde se encuentra. En esta sección se hace una breve retrospectiva de las principales aportaciones conceptuales y técnicas que han contribuido a definir las bases de los sistemas distribuidos actuales. 2.2.1. Primeras aproximaciones Debido al gran éxito de los sistemas Unix y su vinculación en el comienzo de Internet, el socket BSD pronto se estableció como el estándar de facto para el desarrollo de aplicaciones de red. Sin embargo, el socket es una API de muy bajo nivel que habitualmente implica graves problemas de escalabilidad y mantenimiento en aplicaciones grandes ya que los desarrolladores deben lidiar con demasiados detalles relativos a las comunicaciones. Además, el socket no impone formato a los datos por lo que cada nuevo servicio debe ir acompañado de un nuevo protocolo específico (protocolos del nivel de aplicación). Las bases de los sistemas distribuidos son casi tan antiguas como las redes de computadores. Ya a finales de la década de los 70, IETF publicó la RFC 707 [Whi75] titulada «High-level framework for network-based resource sharing». En ella se aborda la problemática del acceso a recursos remotos por medio de Protocolos Orientados a la Función (Function-Oriented Protocols). En esa categoría encuadra los protocolos de red desarrollados hasta ese momento para ARPANET, como FTP o Telnet. La RFC plantea un enfoque innovador en aquel momento: desarrollar un protocolo genérico de petición/respuesta que se puede utilizar como mecanismo de comunicación entre procesos (IPC). Según el autor, este enfoque aporta interesantes ventajas: Los recursos son accesibles a otros programas, no solo a operadores humanos. Es posible crear un único protocolo independiente del recurso para ofrecer acceso a un nivel funcional. Los recursos remotos están accesibles al programador desde el punto de vista funcional y con independencia de la aplicación. Evita tener que diseñar, implementar y documentar nuevos protocolos específicos para cada nueva aplicación. Estimula la creación de recursos específicamente pensados para ser accedidos remotamente. Cada instrucción lleva asociado un nombre, un identificador y un conjunto de parámetros. La respuesta incluye ese mismo identificador para realizar la correspondencia y los resultados de la petición. La consecuencia evidente es que ese enfoque se puede denominar protocolo de llamada a procedimiento1 . El documento concluye (texto literal): 1 Procedure Call Protocol. i i i i i i i i 14 2. A NTECEDENTES El modelo de llamada a procedimiento elevaría la tarea de creación de protocolos de aplicación a la definición de procedimientos y la secuencia de llamadas. Proporcionaría los fundamentos para un verdadero sistema de programación distribuida (DPS) que agiliza y facilita el trabajo del programador extendiendo el entorno de programación local para abarcar módulos en otras máquinas a través del RTE. Esta integración de los entornos de programación local y de red se puede llevar más lejos modificando los compiladores para que puedan proporcionar variantes de las llamadas a procedimientos para permitir realizar llamadas remotas. J. E. W HITE, RFC 707 El autor opina que este enfoque debería tener una gran influencia en el desarrollo de la mayoría de los sistemas distribuidos que estaban por llegar. También advierte sobre dos cuestiones a tener en cuenta: La invocación de un procedimiento local tiene un coste computacional prácticamente despreciable mientras que una invocación remota puede ser potencialmente muy cara. Esto implica que el diseño de las aplicaciones debe hacer un uso responsable de las llamadas a procedimientos remotos. Las aplicaciones convencionales normalmente tienen un único punto de control, mientras que en las aplicaciones distribuidas no suele ser así. 2.2.2. Llamada a procedimiento remoto El enfoque que planteaba [Whi75] fue objeto de debate en la comunidad científica durante algunos años. Una de las consecuencias más importantes fue el trabajo de Xerox PARC en torno al proyecto Cedar [DT80] cuya cara más visible fue la tesis de Bruce N ELSON [Nel81] y un artículo titulado «Implementing Remote Procedure Calls» [BN84]. Como resultado desarrollaron Courier [Cou81], la primera implementación de un protocolo para ejecución de procedimientos remotos y que dio nombre a las RPC (Remote Procedure Call). Sus objetivos principales fueron: Simplificar la programación de aplicaciones distribuidas, para que personal con conocimientos básicos de redes pudiera acometer el desarrollo de aplicaciones complejas centrándose en los problemas específicos como sincronización o tolerancia a fallos. Conseguir una alta eficiencia. Lo suficiente como para que el programador pudiera optar por una llamada remota sin tener que plantearse una reducción sensible del desempeño de la aplicación. Los experimentos de los autores incluyen la posibilidad de eliminar los protocolos de red cuando la máquina remota pertenece a la misma red. Como principio de diseño, mantener la semántica de invocación lo más cercana posible a la de las llamadas a procedimientos convencionales. Seguridad en las comunicaciones. Los pasos para realizar una llamada remota incluyen: El programa del usuario realiza una llamada a un procedimiento local. i i i i i i i i 2. A NTECEDENTES 15 Los cabos de usuario realizan el enlace (binding) y empaquetan la llamada y los argumentos. El núcleo de comunicaciones (RPCRuntime) transfiere los paquetes de forma confiable. Los cabos del servidor desempaquetan el mensaje y realizan una llamada al procedimiento en el servidor como si fuese una llamada local con los parámetros procedentes del cliente. Los cabos del servidor empaquetan el resultado y lo envían al cliente. Los cabos de usuario desempaquetan el resultado y devuelven el control al programa del usuario cuyo proceso ha estado bloqueado desde el inicio del proceso. Los cabos eran generados por un programa llamado Lupine a partir de una especificación de la interfaz exportada. Incluía características muy interesantes como excepciones remotas, mecanismos de indirección, enlace dinámico (dynamic binding) por medio de una base de datos, etc. Como el lector podrá comprobar, las similitudes con los sistemas venideros son evidentes y no es arriesgado decir que este trabajo sentó las bases técnicas de los sistemas distribuidos tal como son hoy en día. A pesar de ello, la primera implementación de RPC que se popularizó significativamente fue la que Sun Microsystems realizó para el sistema de ficheros NFS en Unix, quizá debido al éxito de este entorno en relación al de Xerox. Esta implementación se conoce como ONC RPC (o Sun RPC) y está recogida en la RFC 1831 [Sri95a]. ONC RPC utiliza las convenciones de invocación del lenguaje C por homogeneidad con el sistema operativo Unix. Emplea un sistema de serialización de datos llamado XDR [Sri95b, Eis06]. La implementación de Sun incluye un compilador llamado rpcgen que genera ficheros C para el cliente y el servidor a partir de la especificación XDR. DCE/RPC es una implementación de RPC que forma parte de DCE (Distributed Computing Environment) de OSF (Open Software Foundation). Entre sus características más destacables está la autenticación opcional mediante Kerberos, la posibilidad de utilizar parámetros de entrada/salida y el uso de hilos en el servidor para atender múltiples procesos de forma concurrente. Dispone de un lenguaje de especificación de interfaces llamado Interface Definition Language (IDL) y de un sistema de representación de datos llamado Network Data Representation (NDR). También es digno de mención el estándar ISO/IEC 11578:1996 dentro de OSI, más conocido como ISO RPC. Define un modelo de interacción, un modelo de comunicación, un lenguaje de notación y un protocolo. Utiliza ASN-1 como sistema de representación externa de datos. Características comunes Prácticamente todas las implementaciones de RPC definen: Un lenguaje de especificación de la interfaz, que incluye los tipos de datos y las signaturas de los procedimientos. i i i i i i i i 16 2. A NTECEDENTES Un compilador para el lenguaje anterior. Un formato de intercambio de datos, que permite salvar las diferencias entre arquitecturas y sistemas operativos. Un protocolo específico para codificación de los mensajes. El uso de uno o varios protocolos de transporte. Semántica de llamada Un aspecto a considerar es el soporte que se da a las distintas semánticas de llamada posibles. La definición de esta semántica es importante cuando ocurren errores en el transporte de los mensajes o en los servidores. Dependiendo de la semántica requerida, puede ser preciso saber si la petición de ejecución de un procedimiento por parte de un cliente ya se satisfizo. Idealmente una RPC debería implementar la semántica exactly-once, es decir, debe garantizar que incluso en presencia de fallo cada llamada a procedimiento remoto se ejecuta una y sólo una vez. Sin embargo, en sistemas asíncronos, como es el caso de las redes más extendidas en el espacio de interés de esta tesis, no es posible implementar tales garantías. El cuadro 2.1 resume las características de las semánticas más usuales en relación al ideal. Tipo de fallo Sin fallos Mensaje perdido Servidor caído Maybe Ejecuta: 1 Resultado: 1 Ejecuta: 1 Resultado: 1 Ejecuta: 1 Resultado: 1 Ejecuta: 1 Resultado: 1 Ejecuta: 0/1 Resultado: 0 Ejecuta: ≥ 1 Resultado: ≥ 1 Ejecuta: 1 Resultado: 1 Ejecuta: 1 Resultado: 1 Ejecuta: 0/1 Resultado: 0 Ejecuta: ≥ 0 Resultado: ≥ 0 Ejecuta: 0/1 Resultado: 0 Ejecuta: 1 Resultado: 1 Al-least-once At-most-once Exactly-once C UADRO 2.1: Semánticas de RPC en presencia de distintos fallos (P UDER [PRP05]) A efectos prácticos predominan dos semánticas intermedias entre exactly-once y maybe: Al menos una vez (at-least-once) Se refiere a procedimientos que garantizan la ejecución en el servidor en caso de pérdida de mensajes. Sin embargo, puede darse el caso de que una sola invocación dé lugar a ejecuciones repetidas. Este tipo de semántica es adecuada con procedimientos idempotentes, es decir, aquellos en los que la ejecución múltiple provoca exactamente el mismo efecto y resultados que si se ejecutaran una sola vez. Un procedimiento que calcula un valor a partir de sus parámetros es un ejemplo de llamada idempotente. A lo sumo una vez (at-most-once) Se refiere a procedimientos que garantizan una única ejecución, salvo en caso de fallo del servidor. En general, este tipo de semántica requiere una infraestructura i i i i i i i i 2. A NTECEDENTES 17 software considerablemente más compleja, incluyendo secuenciamiento de mensajes y filtrado de duplicados. Es prácticamente imposible que el compilador de RPC pueda averiguar la semántica de invocación requerida por sí mismo. Por eso el programador debería indicarlo convenientemente, ya que la mejora en la eficiencia de la aplicación puede ser significativa. Otra característica que mejora el desempeño del protocolo consiste en no enviar los resultados de una operación al usuario a menos que sea necesario. Cuando se utiliza un procedimiento remoto que no tiene valor de retorno ni parámetros de salida es posible realizar algunas optimizaciones para el transporte de los mensajes. Por ello, se distingue entre llamadas twoway si se requiere devolver datos al usuario o oneway en caso contrario. También puede ser relevante para el runtime considerar el envío de mensajes multi-destino, como un caso particular de las llamadas oneway. 2.2.3. Invocación a método remoto La posterior revolución que supuso la Orientación a Objetos (OO) a finales de los 80 propició la aparición de un concepto obviamente relacionado: RMI (Remote Method Invocation) . Disponer de objetos da la oportunidad no solo de aprovechar los recursos de una máquina remota; permite además modelar el problema en los mismos términos que si se tratara de una aplicación local, retrasando las decisiones de qué elemento debe ser local y cuál remoto. Además simplifica enormemente la gestión de los datos relacionados (el estado de los objetos), abriendo todo un mundo de posibilidades como el envío de referencias a objetos propios o de terceros, paso por valor (envío de instancias), indirección, transparencia de localización, replicación, migración y otras muchas características que se desarrollaron a lo largo de los años 90, principalmente a cargo de la investigación en torno a los sistemas distribuidos. 2.3. Sistemas Distribuidos Heterogéneos Desde comienzos de la década de los 80 la industria ha realizado numerosos esfuerzos para intentar reducir la complejidad intrínseca del desarrollo de aplicaciones distribuidas. Los esfuerzos más destacables son CORBA de OMG, DCE de OSF y Java RMI por parte de Sun. La mayoría de los sistemas distribuidos actuales tienen una infraestructura basada en una capa de software intermedio, comúnmente llamado middleware de comunicaciones. El middleware define protocolos, servicios básicos y un API para el desarrollo de aplicaciones. Uno de los modelos de programación más exitosos hoy en día es el paradigma de objetos distribuidos, que tiene como objetivo aplicar la misma semántica de la orientación a objetos tradicional para llevar a cabo invocación a métodos de objetos remotos. La mayoría proporcionan bibliotecas de programación en varios lenguajes, junto a un convenio de uso que se conoce habitualmente por su denominación en inglés, mappings. Ofrecen soporte para varios sistemas operativos, plataformas y arquitecturas hardware y, por eso, se las reconoce como viables para el desarrollo de aplicaciones distribuidas sobre i i i i i i i i 18 2. A NTECEDENTES sistemas heterogéneos. Las plataformas de objetos distribuidos suelen incorporar un rico conjunto de herramientas y servicios a los desarrolladores proporcionando medios comunes, probados y eficientes para aprovechar al máximo las posibilidades del middleware. 2.3.1. Nomenclatura La mayor parte de los conceptos relacionados con objetos distribuidos fueron desarrollados antes de que se extendiera el concepto de patrón de diseño en la ingeniería de software. Por ello existe una amplia variedad de términos relacionados que se corresponden total o parcialmente con patrones de diseño bien establecidos. En este documento utilizaremos una terminología relativamente actualizada, similar a la empleada en los middlewares más modernos, que se resumen en esta sección. Servidor Designa un programa (un ejecutable) que se mantiene inactivo, esperando recibir una petición de otro programa a través de una conexión de red. También se aplica servidor para identificar el rol pasivo que puede tener un programa durante el proceso de comunicación, aunque es habitual que un servidor pueda actuar también como cliente. Se suele utilizar para identificar un programa que aloja objetos accesibles remotamente, siendo esa su función principal. Cliente Se refiere a un programa que solicita un servicio a un servidor. Como el caso anterior, también se utiliza para designar el rol activo de cualquier programa en el proceso de comunicación aunque eso no impide que en otros momentos pueda actuar como servidor. Interfaz Una interfaz es un conjunto de métodos que pueden ser invocados remotamente. La interfaz es únicamente declarativa, debe existir una entidad que la implemente para poder ser utilizada. Objeto (distribuido) Es una entidad abstracta que puede ser identificada unívocamente por medio de una identidad u OID (Object Identity). Es equivalente al concepto del mismo nombre en la Programación Orientada a Objetos (POO) con la peculiaridad de que puede recibir invocaciones desde clientes en otras máquinas. Cada objeto implementa una o más interfaces. Sirviente Es una entidad concreta (una porción de código, la instancia de una clase, etc.) que en último término realiza la funcionalidad requerida por la invocación de un método sobre un objeto remoto. Un único objeto puede hacer uso de uno o varios sirvientes del mismo modo que un único sirviente puede respaldar más de un objeto. Adaptador (de objetos) Es un elemento que permite al servidor registrar objetos para que sean accesibles remotamente. El adaptador debe conocer qué sirviente o sirvientes respaldan cada i i i i i i i i 2. A NTECEDENTES 19 objeto o la forma de conseguirlos. Cada adaptador tiene asociado uno o varios endpoints a los que está vinculado. El endpoint especifica un punto lógico de conexión. En el caso de TCP/IP, el endpoint indica una dirección IP y un puerto, puede incluir otras características de la conexión como, por ejemplo, el timeout. Proxy Es un delegado del objeto distribuido remoto en el espacio de direcciones del cliente. A veces se le denomina referencia remota dado que su diseño sigue las directrices básicas del patrón remote proxy [GHJV96]. Implementa la misma interfaz que el objeto remoto, pero su función es únicamente la de redirigir las peticiones que recibe al objeto remoto correspondiente. Del mismo modo, devuelve a la invocación local los resultados obtenidos por la ejecución del método remoto. El proxy permite al programador utilizar un objeto remoto como si fuera local. A veces se distingue entre proxies directos: aquellos para los que se conoce un endpoint específico, y proxies indirectos: que se designan con un identificador que debe ser resuelto a través de un segundo objeto conocido. Bus de comunicaciones Se trata de un bus lógico situado conceptualmente justo encima de la infraestructura de red. Este bus es el encargado de codificar, transmitir y decodificar los mensajes que portan las invocaciones remotas. Se suele identificar por las siglas ORB (Object Request Broker), término acuñado por OMG, pero que se aplica frecuentemente para cualquier middleware orientado a objetos. 2.3.2. Servicios comunes En esta sección se describen brevemente algunos de los servicios que suelen incorporar los middlewares. Se explica únicamente la utilidad general puesto que los detalles y casos de uso pueden variar sensiblemente de un middleware a otro. Servicio de eventos Los objetos habitualmente tienen estado o propiedades que cambian y, a menudo, es necesario notificar esos cambios de forma asíncrona a otros objetos que pudieran estar interesados. El servicio de eventos proporciona un mecanismo de envío de mensajes asíncronos a través del bus lógico, desacoplando productores y consumidores de datos. Por medio de un objeto intermedio (el canal), los consumidores obtienen datos que los productores envían al canal, previa suscripción. Normalmente, el servicio de eventos es un mecanismo de propagación centralizado, aunque puede estar respaldado por varios objetos. Cuando el middleware y el protocolo de red subyacente lo permitan puede no ser necesario un servicio como tal. Creando un proxy asociado a un endpoint multicast es posible enviar un mensaje a todos los objetos vinculados a dicho endpoint, de modo que no hay realmente ningún objeto intermedio y solo una copia del mensaje. Evidentemente eso obliga a todos los participantes del canal a utilizar un mismo protocolo que, en la mayoría de los casos, no ofrecerá garantía de entrega. i i i i i i i i 20 2. A NTECEDENTES Cuando sea posible, el objeto interesado en los mensajes del canal puede escuchar a la vez en un endpoint multicast y también en uno unicast de modo que se pueden aprovechar las ventajas del servicio de eventos estándar y del direccionamiento multicast, según convenga. Servicio de nombres Ofrece la posibilidad de asociar un identificador arbitrario (normalmente una cadena de texto) a un proxy. El servicio de nombres como tal también es un objeto cuya referencia debe ser conocida por todas las aplicaciones que necesiten resolver objetos de manera similar a lo que ocurre con el servicio de DNS en Internet. Servicio de persistencia La persistencia proporciona un medio para almacenar el estado de los objetos incluso aunque el nodo que los aloja sea reiniciado o sean migrados a otro lugar. Normalmente la gestión de la persistencia se delega a algún agente externo tal como una base de datos u otro mecanismo proporcionado por el usuario. Servicio de propiedades Permite definir un conjunto de variables que se pueden asociar a los objetos en tiempo de ejecución para obtener un modelo de datos más rico y dinámico. Resulta muy adecuado cuando no se puede prever en tiempo de diseño qué atributos requerirá cada clase. Servicio de transacciones Ofrece soporte para la gestión de transacciones y de los problemas derivados: escrituras prematuras, equivalencia secuencial, ejecución estricta, gestión de bloqueos, esquemas optimistas de control de concurrencia, ordenación por marcas de tiempo, etc. Servicio de seguridad La seguridad es un aspecto básico de cualquier sistema distribuido, involucra tanto la confidencialidad de los datos como su integridad. Proporciona mecanismos para garantizar la identidad de los extremos (autenticación). También puede proporcionar transporte con cifrado para garantizar la privacidad de las comunicaciones. 2.3.3. CORBA OMG (Object Management Group) [OMG] es un consorcio que agrupa a más de 800 empresas de todo el mundo. Su misión es impulsar el uso y desarrollo de la orientación a objetos con el fin de reducir la complejidad, el coste de los sistemas de información y permitir la introducción de nuevas aplicaciones. Para lograrlo, desde 1989 OMG desarrolla OMA (Object Management Architecture) , una arquitectura basada en componentes que proporciona un bus software conceptual, independiente de: i i i i i i i i 2. A NTECEDENTES 21 El fabricante. La plataforma de desarrollo y explotación. El lenguaje de programación. El lugar donde se ejecutan. El núcleo de OMA es CORBA (Common Object Request Broker Architecture) [COR02] y el componente intermedio que garantiza la interoperabilidad es el ORB (Object Request Broker), que consigue que componentes escritos por diferentes fabricantes puedan interoperar por medio de redes de comunicaciones independientemente del sistema operativo, lenguaje o compilador empleado. Este estándar permite que un objeto invoque a cualquier otro sin conocimiento del lugar donde reside. La norma CORBA cubre cinco grandes ámbitos constitutivos de los sistemas de objetos distribuidos: Un lenguaje de descripción de objetos, denominado IDL, y una infraestructura de distribución de objetos llamada ORB, que ha dado su nombre a la propia norma. CORBA describe completamente las capas de servicios y de transporte características de los sistemas de objetos distribuidos. Una descripción de servicios comunes necesarios sistemáticamente para los objetos de aplicación (CorbaServices). Estas especificaciones cubren los servicios de nombres, persistencia, anuario, ciclo de vida de los objetos, concurrencia, etc. Estos servicios, descritos mediante IDL, son necesarios en los sistemas distribuidos y permiten aislar a clientes y servidores de los detalles de implementación debidos a su localización o a su estado de activación. Una descripción de servicios comunes a las aplicaciones, y no ya solamente a los objetos (CorbaFacilities). Estas especificaciones cubren servicios de más alto nivel como la interfaz de usuario, los documentos compuestos (para los que OMG ha adoptado la norma OpenDoc), la administración de sistemas y redes, etc. Se trata de un gran proyecto puesto que CorbaFacilities pretende definir colecciones de objetos prefabricados para aplicaciones recurrentes en la empresa: creación de documentos, administración de sistemas informáticos, etc. Una colección de descripciones de servicios especializados por rama industrial (DomainServices). Estas especificaciones pretenden ofrecer una descripción estándar de objetos y servicios comunes a una industria determinada. Existen grupos de trabajo para los sectores de las telecomunicaciones, la salud, las finanzas, etc. Éste es el proyecto más ambicioso de OMG; DomainServices pretende crear una fundación orientada a objetos para una informática específica de cada sector, poniendo en común la experiencia de las empresas líderes en estos ámbitos. Una especificación normativa de compatibilidad entre ORB S, llamada CORBA 2.0 y posterior en algunos años a la norma CORBA 1, a la cual engloba. Esta especificación cubre el ámbito de las comunicaciones entre diferentes ORB S, necesaria debido a la proliferación de las implementaciones, a menudo incompatibles entre sí, consecuencia de la adopción de la norma CORBA 1.1. i i i i i i i i 22 2. A NTECEDENTES F IGURA 2.1: Arquitectura CORBA Los objetos CORBA difieren de los objetos implementados en un lenguaje de programación típico en tres aspectos. Los objetos CORBA pueden: Residir en cualquier parte de la red y además pueden moverse dentro de ella. Interoperar con objetos escritos en otras plataformas. Escribirse en cualquier lenguaje de programación para el que se haya definido un mapping a IDL. En la mayoría de las situaciones, un cliente CORBA tiene una referencia a un objeto remoto en forma de cabo (stub). Éste se encarga de la comunicación con el objeto remoto, de modo que se puede acceder localmente a la interfaz del objeto como si fuese local. Hay muchas formas de que una aplicación cliente consiga una referencia a objeto a través del ORB, pero todas ellas deben utilizar uno de estos métodos: Conseguir una referencia inicial directamente desde el ORB. Conseguir una referencia a objeto a través de la invocación de un método de otro objeto remoto. Usar una referencia serializada conseguida por otro medio y convertirla a una referencia real a objeto. En la figura 2.1, la aplicación cliente hace peticiones y la aplicación servidora las recibe y ejecuta. El flujo de peticiones surge del cliente, atraviesa el ORB y llega hasta el servidor del siguiente modo: El cliente puede utilizar un cabo estático compilado a partir de la definición de la interfaz del objeto o usando Dynamic Invocation Interface (DII)2 . En cualquier caso, el cliente dirige las peticiones al núcleo del ORB enlazado con sus procesos. El ORB del cliente transmite las peticiones al ORB enlazado con el servidor. 2 Interfaz de Invocación Dinámica. i i i i i i i i 2. A NTECEDENTES 23 El ORB del servidor redirige la petición al adaptador de objetos que ha creado el objeto destino. El adaptador de objetos dirige la petición al sirviente que implementa el objeto destino. Como en el cliente, el servidor puede elegir entre mecanismos de recepción estáticos o dinámicos para sus sirvientes. Puede confiar en esqueletos estáticos compilados a partir de la interfaz del objeto o en que sus sirvientes usen Dynamic Skeleton Interface (DSI)3 . El servidor devuelve su respuesta a la aplicación cliente después de ejecutar la operación. IDL La parte más importante de la especificación de OMG es el IDL que permite hacer una especificación exacta de la interfaz pública del objeto. Por tanto, en el interior de todo objeto CORBA está su interfaz IDL, la parte más importante de su implementación. Permite a cada objeto interactuar con el resto de objetos indicando a través del ORB qué métodos y parámetros tiene. A partir de la especificación IDL, CORBA define una correspondencia (mapping) entre IDL y los lenguajes de implementación. Este mapping está perfectamente normalizado de modo que garantiza la compatibilidad. En la actualidad, el mapping de IDL está definido para C, C++, Java, Ada, COBOL, Lisp, Python, CORBA Scripting Language, Smalltalk, etc. Los fabricantes de ORB S, siguiendo estas especificaciones, han construido compiladores que, a partir de un fichero IDL que define una interfaz, generan código en un lenguaje de programación convencional determinado. A partir del fichero IDL el compilador genera diferentes archivos: El cabo del cliente, mediante el cual se puede acceder a los objetos remotos. El skeleton (esqueleto) del objeto, a partir del cual el servidor gestionará las peticiones de los clientes e interaccionará con ellos a través del Portable Object Adapter (POA) . Entre las principales características del lenguaje IDL podemos citar: Es un lenguaje neutro y de sólo especificación (no implementación). No existe polimorfismo. Permite la herencia de interfaces. Contempla la definición de: • • • • • 3 Interfaz Módulos. Interfaces. Operaciones. Atributos. Excepciones. de Esqueleto Dinámico. i i i i i i i i 24 2. A NTECEDENTES • Constantes. Tiene un fuerte control de tipos. Contiene calificadores de parámetros de las operaciones para determinar si son de entrada (in), salida (out) o ambas (inout). ORB El ORB es el núcleo de CORBA. Es lo que se conoce como el bus lógico de objetos. El ORB se encarga de poner en contacto a los clientes y a los objetos de forma transparente con respecto a su localización. Sus responsabilidades principales son: Proporcionar mecanismos para que el cliente localice la implementación de la interfaz. Preparar la implementación de la interfaz para que pueda recibir invocaciones remotas. Proveer la comunicación que hace posible la invocación de métodos (argumentos de la función y parámetros de retorno). Hacer transparente al cliente los detalles de localización, acceso, serialización y activación de un objeto remoto. Encontrar la implementación del objeto que se solicita. Para cubrir estas responsabilidades, el ORB proporciona cinco elementos básicos: Una DII, para que la aplicación cliente construya dinámicamente los mensajes. Una DSI, para que la aplicación servidor responda a mensajes construidos dinámicamente. Un repositorio de interfaces o Interface Repository (IR). Una interfaz de programación para el propio ORB. Una implementación del POA. POA El POA es el componente del ORB encargado de hacer accesibles remotamente los objetos que el programador crea en un servidor. Entre sus funciones más importantes, el POA proporciona: Un medio para crear implementaciones de objetos portables (entre ORB S). Soporte básico para el ciclo de vida de los objetos, incluyendo la persistencia. Activación transparente de objetos y sirvientes. Desacoplamiento entre objeto y sirviente, de modo que sea posible implementar estrategias como default servant. Creación y gestión de objetos temporales (minimizando la sobrecarga). i i i i i i i i 2. A NTECEDENTES 25 Soporte para construir implementaciones de objetos a partir de los esqueletos generados por el compilador de IDL y también por medio de la interfaz DSI. Se trata de un objeto que el programador debe instanciar para poner sus objetos a disposición del ORB y, por tanto, de los clientes. Por medio de un conjunto de políticas (policies) el programador determina aspectos concretos del comportamiento del POA que se aplican a todos los objetos vinculados a él. El ORB incluye por defecto el RootPOA, pero si se precisan comportamientos diferentes es posible crear varios POA S y asignarles otras políticas. Las políticas y sus valores posibles son: Thread – El ORB creará un hilo para atender cada nueva invocación (ORB_CTRL_MODEL) o se atenderán en el mismo hilo (SINGLE_THREAD_MODEL). Lifespan – Los sirvientes serán eliminados al destruirse el POA (TRANSIENT) o serán persistentes (PERSISTENT). Object Id Uniqueness – Los sirvientes tienen identidades únicas (UNIQUE_ID) o múltiples (MULTIPLE_ID). Id Assignment – Las identidades de objetos son generadas por el ORB (SYSTEM_ID) o por el usuario (USER_ID). Servant Retention – Los sirvientes se mantienen en el mapa de objetos RETAIN / NON_RETAIN. Request Processing – Política de procesamiento de invocaciones: USE_ACTIVE_OBJECT_MAP_ONLY, USE_DEFAULT_SERVANT o USE_SERVANT_MANAGER. Implicit Activation – Los sirvientes se activan automáticamente IMPLICIT_ACTIVATION / NO_IMPLICIT_ACTIVATION. Referencias a objetos Las referencias a objetos son análogas a los punteros a instancias de una clase de C++, pero pueden denotar objetos implementados en procesos distintos (incluso en otra máquina), así como objetos implementados en el mismo espacio de memoria del cliente. Excepto por esta capacidad de direccionamiento distribuido, las referencias a objetos tienen una semántica muy similar a los punteros a instancias C++: Cada referencia a objeto identifica exactamente a una instancia de una clase. Varias referencias distintas pueden identificar al mismo objeto. Las referencias pueden ser nulas (no se refieren a ningún objeto). Pueden quedar invalidadas (si el objeto referido desaparece). Son opacas. Usan tipado fuerte. Permiten enlace tardío o dinámico. Pueden ser persistentes. i i i i i i i i 26 2. A NTECEDENTES Pueden ser interoperables. Para que un cliente pueda utilizar un objeto remoto necesita una referencia que puede conseguir por alguno de estos métodos: Como valor de retorno o de salida de un método de otro objeto. Por medio del Naming Service o el Trading Service. Convertir una referencia a objeto en un string y escribiéndolo en un fichero que puede transmitirse o publicarse por algún medio. Este último tipo de referencia es textual y está pensada como alternativa a las referencias binarias cuando se quiere almacenar o transmitir por medios más cercanos al usuario. Las referencias textuales pueden ser de tres tipos: IOR (Interoperable Object Reference) 4 : Identifica uno o más protocolos de apoyo y contiene información específica para cada uno. Es lo suficientemente flexible como para almacenar la información de casi cualquier mecanismo inter-ORB imaginable. Permite que se puedan añadir nuevos protocolos a CORBA sin tener que rehacer las aplicaciones existentes. Un IOR de IIOP contiene un nombre de host, un puerto TCP/IP y una clave de objeto que permite identificar unívocamente al objeto destino. La IOR es una secuencia de bytes de longitud variable que comienza siempre por IOR:. CORBAloc : Para disponer de referencias a objetos se definieron dos tipos más: el corbaloc y el corbaname. El corbaloc está pensado para referirse a objetos que implementan servicios estándar o a objetos registrados en el POA con un nombre concreto (object key). Un corbaloc tiene una apariencia del tipo: corbaloc :: arco . uclm . es :5000/ NameService que se refiere al objeto con identidad NameService en el puerto 5 000 de la máquina llamada arco.uclm.es. CORBAname : Permite especificar una referencia registrada en un servicio de nombres. Por ejemplo: corbaname :: arco . uclm . es :5000/ NameService # casa1 / cerradura que hace referencia al objeto registrado con el nombre cerradura en el contexto casa1 del Name Service que reside en la máquina arco. Transporte de mensajes Todos los mensajes que se transmiten entre cliente y servidor utilizan un protocolo llamado GIOP (General IOP). El anexo D es una descripción detallada de todas las características de GIOP que pueden resultar de interés para el ámbito de este documento. Incluye también las especificaciones relativas a la serialización de datos conforme al formato CDR (Common Data Representation). 4 Referencia Interoperable de Objeto. i i i i i i i i 2. A NTECEDENTES 27 Existen varias especificaciones relacionadas con GIOP que es interesante nombrar aquí: IIOP [Obj04] Se trata del transporte de GIOP sobre una arquitectura de red que utiliza una pila de protocolo TCP/IP. ESIOP Se trata de protocolos no compatibles con GIOP, pero que pueden ser utilizados para comunicación entre ORB S. La comunicación entre GIOP y distintos ESIOP puede lograrse por medio de puentes (Inter-ORB Bridges). DCE CIOP [Obj04] Es un ESIOP para DCE. HTIOP Es una implementación de IIOP sobre HTTP pensada para facilitar el paso de cortafuegos. SSLIOP Es una implementación de IIOP sobre SSL. CORBA::Object Cuando se procesa la especificación de interfaces, el compilador genera esqueletos para los sirvientes en forma de clases. El programador debe heredar de esas clases y proporcionar una implementación para los métodos que definió en el fichero IDL. Son métodos completamente dependientes del dominio del problema y, por tanto, sólo él puede especificar la funcionalidad requerida. Sin embargo, esas clases-esqueleto incluyen un conjunto de métodos que corresponden a la interfaz CORBA::Object. De ese modo, el ORB asegura que todos los objetos CORBA tienen una funcionalidad mínima que garantiza interoperabilidad y proporciona soporte de introspección. El listado 2.1 muestra la descripción de la mencionada interfaz en pseudo-IDL. La mayoría de estos métodos son atendidos por el ORB o el proxy local. Solo algunos de ellos, como non_existent() o is_a(), implican realmente acceso al objeto remoto. Se colocan juntos por conveniencia desde el punto de vista de la abstracción de objeto. CORBAServices Los CorbaServices son interfaces IDL cuya especificación provee los servicios básicos necesarios en toda arquitectura distribuida. Las distribuciones de ORB suelen traer implementados desde los servicios más básicos (como MICO), hasta los más avanzados, como TAO (The ACE ORB). Se describen brevemente algunos de los servicios más importantes especificados hasta la fecha. Servicio de Nombres El Naming Service [Obj01b] de OMG proporciona una organización para las referencias a objetos muy parecida a la estructura empleada en i i i i i i i i 28 2. A NTECEDENTES interface Object { InterfaceDef get_interface () ; boolean is_nil () ; boolean is_a (in RepositoryId lo gi ca l_ t yp e_ id ) ; boolean non_existent () ; boolean is_equivalent (in Object other_object ) ; unsigned long hash (in unsigned long maximum ) ; string respo sitory_i d () ; // [...] }; L ISTADO 2.1: Interfaz CORBA::Object un sistema de ficheros, es decir, con forma de árbol o grafo. Desde el punto de vista práctico, su utilidad es la asociar una cadena de texto a un objeto, de modo que pueda obtenerse una referencia real al objeto dado su nombre simbólico. Es parecido a los DNS utilizados en Internet para resolución de nombres de dominio. Como en aquellos, el cliente necesita una referencia inicial a el/los servicios de nombres que desee utilizar. Una referencia a objeto es una estructura opaca que contiene la información necesaria para la localización del objeto por parte del ORB, en el caso de TCP/IP, la información contenida en esta referencia se compone del puerto, máquina e identificador dentro del proceso del objeto referenciado. Las referencias a objetos se almacenan mediante un nombre y una extensión (kind); el binomio nombre-referencia se denomina vínculo (binding). Para crear un vínculo se utiliza el método CosNaming::NamingService::bind(), para lo cual el cliente requiere una referencia al contexto raíz5 . Dentro de un contexto se pueden vincular a su vez otros contextos consiguiendo así la estructura de árbol. Además, tanto los objetos como los contextos pueden vincularse varias veces con diferentes nombres. El contexto raíz lo implementa normalmente una aplicación específica proporcionada por el fabricante del ORB. El cliente requiere conocer la referencia al servidor de nombres para poder utilizarlo. Consulte la sección 2.3.3 para más información sobre referencias a objetos. Servicio de eventos Event Service [Obj01a] establece canales a los cuales se suscriben dos tipos de objetos: los productores y los consumidores. Cuando un objeto se suscribe a un canal como productor lanza eventos al canal codificando la información necesaria, en el otro lado todos los consumidores suscritos al canal reciben el evento (y la información contenida en él) y actúan en consecuencia. Además, existen dos tipos de interfaces, tanto para productores como consumidores: la interfaz de inyección (push) y la de extracción (pull). Lo que da lugar a cuatro tipos de elementos: Productor por inyección (PushSupplier). Ejecuta un método remoto implementado por el consumidor para transmitir el evento. 5 Los contextos implementan la interfaz CosNaming::NamingContext. i i i i i i i i 2. A NTECEDENTES 29 Productor por extracción (PullSupplier). Provee una interfaz pública para que el administrador del canal o los clientes pregunten por los nuevos eventos. Consumidor por inyección (PushConsumer). Provee una interfaz pública de modo que el administrador del canal puede ejecutar su método PushConsumer::push() cuando tenga un evento para él. Consumidor de extracción (PullConsumer). El consumidor debe invocar el método try_pull() o pull() de su proveedor continuamente para comprobar si hay eventos nuevos. El método pull() bloquea al consumidor. Las comunicaciones se establecen por medio del SupplierAdmin y el ConsumerAdmin respectivamente. Los modelos de inyección y extracción pueden darse a la vez en el mismo canal de eventos (ver figura 2.2). F IGURA 2.2: Métodos de entrega de eventos en un modelo híbrido Esta forma de comunicación asíncrona permite la realización de operaciones comunes a determinados sucesos dentro del sistema. Existen varias evoluciones del servicio de eventos, como el denominado Notification Service [Rod] (Servicio de Notificación), que además permite: Definir las notificaciones como estructuras de datos, pudiendo de ese modo enviar una información más completa. Los consumidores pueden especificar filtros para determinar los eventos de interés, con lo que evitan tener que procesar eventos que no van dirigidos a ellos. Los suministradores pueden descubrir los eventos que interesan a sus consumidores y generar sólo esos eventos. Se pueden configurar las propiedades del canal de eventos, de manera que se establezcan políticas de descarte, prioridades en los eventos, etc. Servicio de propiedades Property Service [Obj00] establece un conjunto de interfaces estándar para asociar propiedades a los objetos. Una propiedad es un valor tipado (property_value) identificado por un nombre (property_name). Las propiedades no forman parte del conjunto de tipos del sistema, es decir, no están especificadas en un fichero IDL (tampoco como atributos). De ese modo, el usuario de la aplicación puede enriquecer el modelo de información para un cometido o durante un período concretos. i i i i i i i i 30 2. A NTECEDENTES No interfiere con la visión que otros usuarios o aplicaciones tienen del mismo sistema y se evita la necesidad de recompilar o reiniciar ningún componente. La especificación incluye interfaces para la definición de metadatos básicos como tipo de acceso (lectura/escritura), propiedades obligatorias, conjuntos de propiedades (PropertySet), iteradores y comprobación de restricciones. Seguridad y autenticación de objetos El Security Service (Servicio de Seguridad) de CORBA define dos niveles de seguridad [Bak97]: El nivel uno soporta clientes y servidores que no conocen el servicio de seguridad. Este nivel se aplica a todos los elementos que se ejecutan sobre un ORB seguro. Incluye seguridad entre las invocaciones y respuestas de los clientes y servidores, protección de mensajes, control y registro de accesos. El nivel dos soporta clientes y servidores que tienen conocimiento del servicio de seguridad. Este servicio pone a su disposición una serie de interfaces y opciones que delega a estas aplicaciones. El servicio de seguridad contempla credenciales y atributos que determinan lo que se puede hacer y lo que no. Actualmente hay dos tipos de atributos: de identidad y de privilegios. Todos los métodos invocados deben ir acompañados con estos atributos, el servicio de seguridad establece sus privilegios en base a ellos. Mediante las interfaces que se ponen a disposición de las aplicaciones (en el nivel dos), éstas pueden registrarse obteniendo credenciales para sus objetos. En lo concerniente a las llamadas, el servicio de seguridad añade una serie de operaciones a las referencias a objetos que permiten, por ejemplo, asociar credenciales a referencias de manera que se apliquen cada vez que se usan. Resumiendo, el servicio de seguridad contempla: Autenticación de usuarios (ya sean personas físicas o sistemas). Control de acceso a las llamadas. Registro de acciones que ayudan al administrador del sistema a trazar los principales eventos que han sucedido. Delegación de seguridad entre objetos. Encriptación de los mensajes que viajan a través de la red. Es necesario resaltar que en la seguridad del sistema deben intervenir todas las partes involucradas: ORB, aplicaciones etc. Otros servicios importantes son: Trading Service (Anuario de objetos). Permite que un cliente localice un objeto servidor en base a determinadas propiedades de éste. Si comparamos el Naming Service con la guía telefónica, el Trading Service es como las páginas amarillas. Lifecycle Service (Servicio de ciclo de vida) se ocupa de los detalles de creación, destrucción, copia y movimiento de objetos. Al contrario que otros servicios de i i i i i i i i 2. A NTECEDENTES 31 OMG, éste no puede ser construido por un fabricante, es sólo un conjunto de recomendaciones. El servicio describe varias interfaces y patrones de diseño para gestionar el ciclo de vida de los objetos. Persistent Object Service (Servicio de persistencia). Transaction Service (Transacciones entre objetos). Concurrency Service (Paralelismo entre objetos). Security Service y Licensing Service (Seguridad y autenticación de objetos). Componentes CORBA Component Model (CCM) [CCM06] describe el modelo de componentes de CORBA, que incluye la especificación de interfaces, implementación, empaquetado y despliegue de componentes. Un componente es básicamente un meta-tipo que se especifica en lenguaje IDL. El componente se representa por medio de una referencia a objeto. Cada tipo de componente puede verse como una entidad que proporciona un conjunto de prestaciones encapsulando su implementación y representación interna. Se definen varias formas diferentes de interactuar con un componente, ya sea con los clientes o cualquier otro elemento del sistema. Se las denomina puertos (ports) y son las siguientes: Facets – Una faceta representa un modo de interacción entre el componente y el cliente. Normalmente cada faceta implementa una interfaz IDL diferente. La interfaz del componente incluye métodos para listar y resolver las facetas disponibles. Receptacles – Se trata de puntos de conexión predefinidos, que pueden alojar una referencia a un objeto proporcionado por otra entidad del sistema. Se trata de un medio portable para establecer relaciones entre objetos. Fuentes y sumideros de eventos – Son entidades que, respectivamente, pueden producir y aceptar eventos de un tipo concreto. Una fuente de eventos puede estar asociada a uno o varios consumidores o a un canal de eventos. Atributos – Son similares a los atributos de los objetos CORBA convencionales (disponibles a través de accesores y mutadores) con la diferencia de que éstos pueden producir excepciones. Se utilizan principalmente para configurar el componente. Los componentes básicos no pueden ofrecer ninguna de las prestaciones anteriores, solo pueden tener atributos. CCM introduce un nuevo lenguaje declarativo llamado Component Implementation Definition Language (CIDL), que extiende la sintaxis de IDL para especificación de implementación de componentes. Esta especificación indica los detalles de conexión del componente con el sistema, servicios estándar y otros componentes. El componente se diseña de modo que pueda desempeñar un conjunto de tareas para un servidor de aplicaciones manteniendo cierta generalidad. El servidor debe proporcionar un contenedor compatible. El contenedor es el medio para lograr la interacción entre i i i i i i i i 32 2. A NTECEDENTES el sistema y el componente puesto que actúa de intermediario en cualquier operación que implique al componente. Se definen cuatro categorías de componentes: Service component – Son aquellos cuya vida está ligada a una operación. No tienen identidad, estado ni persistencia. Session component – Están asociados a un cliente concreto. Aunque pueden tener estado no tienen persistencia si se reinicia el servidor. Process component – Su identidad y estado es persistente, aunque este último no es visible para el cliente. Lo gestiona la implementación o su contenedor. Puede interactuar con múltiples clientes. Entity component – Su estado es persistente y accesible por el cliente. También puede ser compartido por múltiples clientes. Se puede obtener por medio de una primary_key de modo que su utilidad semántica es similar —salvando las distancias— a las entidades de una base de datos. El componente también incluye metadatos e información para su empaquetado y despliegue utilizando un fichero XML. 2.3.4. ZeroC Ice I CE (Internet Communications Engine) [Hen04, HS08] es un middleware de comunicaciones orientado a objetos de propósito general desarrollado por ZeroC [Zera]. Se trata de una empresa relativamente joven formada por prestigiosos profesionales de la industria de los sistemas distribuidos, tales como Michi Henning, vinculado durante años a algunos de los comités técnicos de OMG en el desarrollo de CORBA. I CE respeta la mayor parte de los conceptos que sustentan CORBA. Sin embargo, su diseño está dirigido únicamente por objetivos prácticos, directamente plasmados en una implementación para su puesta en producción. Eso contrasta con el diseño por comité característico de una organización como OMG. También evita el lastre que implica la compatibilidad con protocolos, especialmente cuando éstos llevan asociados errores de diseño conocidos y reconocidos. El resultado hace de I CE uno de los middlewares con más servicios funcionales y de más calidad del mercado, en contraste con los muchos servicios de OMG que nunca fueron implementados por ningún fabricante. Aunque existen diferencias destacables, es posible hacer una correspondencia directa entre muchas de las características de I CE con respecto a las de CORBA. Proxies El proxy encapsula toda la lógica necesaria para contactar con el objeto remoto, enviar el mensaje de petición, serializar los parámetros y recoger los resultados. Tiene algunas particularidades respecto al concepto general (véase § 2.3.1) ya que el proxy I CE debe incorporar la identidad del objeto y el identificador de la faceta. i i i i i i i i 2. A NTECEDENTES 33 Los proxies directos incluyen información para localizar el servidor en el que se aloja el objeto destino (el endpoint). Los protocolos soportados por defecto son TCP, UDP y SSL; de modo que el endpoint especifica un protocolo, una dirección IP y un puerto. Se proporcionan mecanismos para la creación de nuevos tipos de endpoints que pueden utilizar otros protocolos que nada tengan que ver con Internet, aunque en la versión actual no existe un API pública para ello. I CE permite la posibilidad de utilizar proxies indirectos. En ese caso, el proxy utiliza los mecanismos de indirección del núcleo de comunicaciones para resolver el endpoint adecuado y poder contactar con el objeto. Representación de proxies Cualquier proxy tiene una representación textual legible asociada denominada en inglés stringified-proxies (el equivalente al IOR de CORBA). Para los proxies directos esa representación está formada por la identidad del objeto, un modo y una lista de endpoints. Es posible construir un proxy a partir de datos proporcionados por el usuario dado que no existen partes ocultas u opacas. En los proxies indirectos no se especifica ningún endpoint. Si el objeto está registrado como bien conocido solo es necesario indicar su nombre. Si pertenece a un adaptador bien conocido se especifica la identidad del objeto y el nombre del adaptador. El listado 2.2 muestra las representaciones de los tres tipos de proxies. El apéndice D (Proxies and Endpoints) del manual oficial de I CE [HS08] muestra en detalle el formato y opciones aplicables. # proxy directo SystemControl −t : −h 10.0.0.21 −p 10000 # proxy indirecto de un objeto bien conocido SystemControl # proxy indirecto de un objeto en un adaptador bien conocido SystemControl @ SystemAdapter L ISTADO 2.2: Proxies directos e indirectos en I CE Slice I CE define un completo lenguaje de especificación de interfaces llamado Slice. Como es habitual, es un lenguaje diseñado para especificar la interfaz de los objetos y los tipos de datos que manejan de forma abstracta e independiente de la implementación tanto del servidor como del cliente. El programador escribe la especificación Slice en un fichero que posteriormente será compilado por medio de uno de los I CE translators, compiladores específicos para cada lenguaje soportado por el middleware. En la versión actual, I CE soporta la implementación de servidores y clientes en C++, Java, C#, Python y Objective-C; y de clientes en Ruby y PHP. Sin embargo, algunos de los servicios y extensiones solo tienen API S para C++ y Java. Contempla la declaración de: Módulos. i i i i i i i i 34 2. A NTECEDENTES Interfaces (con herencia). Clases (con herencia). Atributos. Excepciones. Tipos: • • • • • • bool, byte, short, int, long, float, double, string, enumerados, estructuras, secuencias, diccionarios y constantes y literales. Algunas de sus características: Admite directivas de preprocesamiento para incluir otros ficheros (#include) y su control por medio de guardas (#ifndef). Ofrece soporte para Freeze —el servicio de persistencia de I CE— directamente en la definición de los tipos. Permite influir sobre la generación de los cabos por medio de metadatos. Transporte de mensajes Para la codificación y transporte de invocaciones, respuestas, etc., I CE utiliza su propio protocolo, llamado I CE P (I CE Protocol). En el anexo C se incluye una descripción detallada de todas las características de I CE P que el autor considera pueden resultar de interés para el lector a lo largo del presente documento. Un aspecto muy interesante de I CE P es que los parámetros se encapsulan en slices (rodajas) que son estructuras especificadas por un tamaño y una codificación. Si la aplicación conoce el formato de la slice puede entender su contenido, en caso contrario todavía puede almacenarla o reenviarla de modo completamente transparente. I CE dispone de una biblioteca denominada Dynamic I CE que permite leer y escribir mensajes I CE P de modo programático. La biblioteca se encarga de la (de)serialización de datos de acuerdo al formato correspondiente. Esto, junto a las slices, es de gran utilidad ya que un servidor puede redirigir invocaciones sin tener que comprender la estructura interna de los datos que incluye. En eso se basa el funcionamiento del servicio de eventos. Ice::Object Todo objeto I CE implementa la interfaz Ice::Object. Como en el caso de CORBA::Object, esta interfaz proporciona capacidades mínimas de introspección mediante los métodos ice_isA(), ice_id() y ice_ids(), y comprobación de alcanzabilidad por medio del método ice_ping(). Estos mecanismos de introspección no están disponibles si se accede al objeto a través de un transporte oneway. El listado 2.3 muestra una especificación parcial de la citada interfaz. i i i i i i i i 2. A NTECEDENTES interface Object { idempotent void idempotent bool idempotent string idempotent StrSeq // [...] }; 35 ice_ping () ; ice_isA (string typeID ) ; ice_id () ; ice_ids () ; L ISTADO 2.3: Interfaz Ice::Object Soporte para programación asíncrona El modelo de invocación de I CE sigue el comportamiento tradicional de RMI. Como en las invocaciones locales, implica el bloqueo del hilo que realiza la petición hasta el momento en que reciben los resultados. Sin embargo, I CE también ofrece AMI (Asynchronous Method Invocation). En ese caso, el cliente debe utilizar un método distinto, acabado en _async. A parte de los parámetros del método original, éste requiere un objeto proporcionado por el usuario, que debe implementar una interfaz específica. Cuando se completa la invocación, el ORB ejecuta un método de ese objeto para proporcionar los resultados o informar de una posible excepción. Si se especifica en la declaración del método (como metadato), el compilador de interfaces genera los métodos AMI, es decir, este mecanismo afecta únicamente al cliente. Para el servidor la interfaz es la misma y los métodos son atendidos y ejecutados de la forma habitual puesto que no hay nada distinto en el mensaje de petición. Por parte del servidor también es posible realizar despachado asíncrono mediante AMD (Asynchronous Method Dispatching). En el modo de funcionamiento habitual (síncrono) el servidor se ve forzado a atender inmediatamente las invocaciones de los clientes. El hilo que gestiona los mensajes de petición en los cabos del servidor permanece bloqueado hasta que recibe los resultados. Con AMD el servidor puede atender la petición más adelante. Cuando el servidor realiza el trabajo informa al ORB de que la invocación ha sido satisfecha y se pueden enviar los resultados al cliente. Los mecanismos AMI y AMD son independientes y no afectan en absoluto al funcionamiento de la otra parte. Puede plantearse AMI sólo para algunos clientes, o sólo para algunas invocaciones o circunstancias especiales, y lo mismo puede aplicarse a AMD por parte del servidor. Es factible emplear cualquier combinación de los tres mecanismos posibles: síncrono-síncrono, AMI-síncrono, síncrono-AMD o AMI-AMD. También es posible construir servidores que delegan parte de su trabajo a otros servidores, en cuyo caso puede ser muy útil despachar a sus clientes con AMD e invocar con AMI. Servicio de eventos: IceStorm IceStorm es una implementación directa del patrón de diseño observer (también llamado publish-subscribe). Es decir, a diferencia de los servicios de eventos habituales en otros middlewares, IceStorm es un servicio de propagación de invocaciones, en lugar de datos. i i i i i i i i 36 2. A NTECEDENTES Eso tiene importantes ventajas, por ejemplo, para un cliente no hay diferencia entre enviar un evento o hacer una invocación convencional a un servidor, lo único distinto es el proxy que utiliza. La única particularidad es que los métodos que se invocan sobre un canal de eventos no pueden tener valor de retorno ni parámetros de salida por razones obvias. Por motivos de escalabilidad no es conveniente conectar demasiados nodos a un mismo canal de eventos. Por ello, se utilizan diferentes topics6 que tienen un coste mínimo de recursos, pero que pueden ser interconectados mediante links para propagar eventos entre ellos. Es posible definir costes asociados a estas acciones y, de ese modo, definir umbrales como medio para priorizar ciertos mensajes. Por medio de la federación, se pueden agrupar los nodos asociados a una funcionalidad, localización, tipo o servicio concreto en un mismo canal, pero manteniendo la posibilidad de propagar ciertos eventos a otros canales. Permite utilizar diferentes protocolos de transporte (al menos TCP, SSL y UDP) de forma transparente para los implicados y sobre el mismo canal. Cada publicador o suscriptor puede incluso elegir el transporte que desea de forma individual. Servicio de persistencia: Freeze Para utilizar el servicio de persistencia, el usuario debe aportar una especificación del estado de sus objetos utilizando el lenguaje Slice. Un compilador especial genera código específico para almacenar y recuperar ese tipo en una base de datos. El servicio también contempla una solución de escalabilidad basada en los Freeze Evictors. Éstos permiten que no todos los sirvientes que respaldan los objetos accesibles tengan que estar en memoria en un momento dado. La base de datos de Freeze puede almacenar una gran cantidad de objetos aunque realmente solo unos pocos estén activos. Cuando se realiza una petición a uno de los objetos desactivados, el servicio se encarga de recuperarlo de la base de datos automáticamente. La penalización es prácticamente irrelevante para la mayoría de las aplicaciones. IceGrid IceGrid proporciona un conjunto muy rico de prestaciones: Indirección de objetos, por medio del Locator. El Locator es el encargado de resolver la localización real de un objeto a partir de un proxy indirecto. Activación de servidores bajo demanda. De forma implícita la invocación de un cliente es utilizada para desencadenar la activación del servidor que aloja el objeto invocado. Soporte para replicación y balanceo de carga automático. Despliegue de aplicaciones y actualizaciones. IceGrid se integra directamente con IceBox, un servidor de aplicaciones genérico. IceBox se utiliza para arrancar y gestionar un conjunto de servidores aportando grandes 6 Un topic es un canal de eventos lógico. i i i i i i i i 2. A NTECEDENTES 37 ventajas como la posibilidad de compartir la misma instancia del ORB o la misma máquina virtual en el caso de Java. IcePatch2 Es un servicio para despliegue de aplicaciones y todo tipo de ficheros que éstas puedan necesitar. Funciona bajo demanda, es decir, los nodos deben actuar como clientes para solicitar al servidor IcePatch la versión más actual disponible de la aplicación concreta. El servidor puede autenticar al cliente y desplegar los ficheros necesarios, incluso en redes formadas por computadores heterogéneos. Glacier2 Es un servicio para facilitar la integración de redes que utilizan NAT o detrás de cortafuegos muy restrictivos. Glacier2 plantea el uso de sesiones seguras por medio de tráfico SSL y certificados, por lo que la seguridad de la red no se verá comprometida. 2.4. Miniaturización de middlewares generalistas Varias iniciativas han ideado estrategias para integrar middlewares ad hoc en dispositivos empotrados. Sin embargo, han existido relativamente pocos esfuerzos por garantizar interoperabilidad con las plataformas y herramientas estándar como las que se utilizan en los sistemas de cómputo habituales. En esta sección se describen algunas de las propuestas más destacables. El problema principal que aparece cuando se intenta empotrar un MDOO de propósito general para su instalación en dispositivos de cómputo con características limitadas es principalmente la cantidad de memoria que requieren los núcleos de comunicaciones habituales. Tal como apunta RODRIGUES [RFC03], existen principalmente tres alternativas principales para lograr la miniaturización de objetos distribuidos: Eliminar las prestaciones más costosas Consiste en determinar qué prestaciones de un middleware existente (en la mayoría de los casos CORBA) tendrán poca o ninguna utilidad en un dominio específico. Eliminando estas prestaciones es posible reducir drásticamente las necesidades de recursos en la plataforma objetivo. A esta estrategia corresponden la especificación Minimum CORBA (véase § 2.4.1) y los núcleos de comunicaciones nORB (véase § 2.4.4), dynamicTAO (véase § 2.4.5) y sus descendientes: LegORB (véase § 2.4.7), UIC (véase § 2.4.6) y I CE -E (véase § 2.4.11). Adaptar el middleware a dispositivos específicos Este tipo de sistemas buscan aprovechar todas las características propias de una plataforma concreta con el fin de conseguir una implementación pequeña y eficiente que satisfaga los requisitos de la aplicación. Normalmente ello supone un sacrificio de portabilidad, es decir, prácticamente implica por diseño la imposibilidad i i i i i i i i 38 2. A NTECEDENTES de adaptar el sistema a otros dispositivos. En este grupo se podrían incluir TINIORB [MML02] y PalmORB [RSC+ 99]. Usar pasarelas de protocolo La tercera posibilidad consiste en utilizar un protocolo específico, mucho más simple que el que impone el middleware, para comunicar un nodo maestro con los nodos de la red. Ese maestro o pasarela se encarga bien de realizar la conversión de protocolos, bien de recopilar información de la red interna y presentarla al exterior. En cualquier caso, implica el uso de una pasarela que aloja entidades software (proxies) que materialicen la ilusión de que los nodos de la red interna son objetos distribuidos. Este es el enfoque usado en Smart Transducer Interface (STI) (véase § 2.4.9), UORB y en una de las alternativas de integración que propone SENDA (Services and Networks for Domotic Applications) [ML02]. Todos estos trabajos siguen las mismas reglas básicas: Eliminar los métodos de invocación e instanciación dinámica. Simplificar el lenguaje de definición de interfaces (OMG IDL en el caso de CORBA). Eliminar los tipos de datos complejos o grandes. Eliminar algunos campos del formato de trama definida por el protocolo de comunicaciones. Eliminar o simplificar los tipos de mensajes usados en el protocolo. Eliminar el soporte a referencias indirectas y a servicios comunes. Modularizar el núcleo de comunicaciones e instanciar sólo aquellos componentes que realmente se necesiten en cada caso. Es importante señalar que todos los núcleos de comunicación que se citan requieren muchas utilidades de soporte adicionales: serialización de tipos de datos, primitivas de comunicaciones, sistema operativo, etc. Es decir, los requerimientos de memoria reales pueden llegar a ser órdenes de magnitud mayores que los citados, lo que además impide que puedan ser comparados con precisión. 2.4.1. Minimum CORBA El propio OMG publicó la especificación Minimum CORBA [Obj02] , una versión ligera de su popular arquitectura CORBA. Se trata de un subconjunto de CORBA diseñado específicamente para sistemas con recursos limitados. Elimina las prestaciones más costosas del núcleo de comunicaciones manteniendo un buen grado de interoperabilidad con objetos CORBA estándar. En los ORB S de CORBA convencionales hay muchas características que se incluyen tanto si se utilizan como si no. Es decir, el hecho de utilizarlas no repercute en la cantidad de recursos requeridos. En la mayoría de las aplicaciones esto no es importante, pero en una aplicación en la que los recursos son limitados la inclusión de estas características puede hacer impracticable la utilización del ORB. Minimum CORBA elimina algunas de ellas de manera que se puedan implementar sólo en la aplicación que las requiera, pero i i i i i i i i 2. A NTECEDENTES 39 omitiéndolas cuando no se necesitan. Estas características dejan de formar parte del ORB para delegar en la propia aplicación (figura 2.3). F IGURA 2.3: Representación de las características omitidas en Minimum CORBA (b) respecto a CORBA (a) La omisión de una característica de CORBA supone una elección entre usabilidad y recursos utilizados. CORBA es un entorno más amigable para el programador, mientras que Minimum CORBA permite un mayor aprovechamiento de los recursos. La especificación establece unos objetivos principales: Elegir cuidadosamente qué características de CORBA se deben mantener, adquiriendo un perfil que aún tenga aplicación en el mundo de los sistemas de recursos limitados. Minimum CORBA debe poder interactuar con CORBA, de manera que las aplicaciones que operen sobre el ORB de Minimum CORBA puedan ser parte de sistemas que incluyan componentes sobre ORB S de CORBA. El soporte de IDL debe ser completo, de manera que, con los suficientes recursos, cualquier aplicación CORBA pueda utilizarse tanto sobre CORBA como sobre Minimum CORBA e, incluso, sobre una combinación de las dos. La posibilidad de utilizar el mismo lenguaje IDL de OMG permite que la compatibilidad de aplicaciones respecto a CORBA sea completa (véase § 2.4.1). Las características que proveen a CORBA de aspectos dinámicos se omiten, de manera que deberán ser los propios sistemas los encargados de proporcionarlos en tiempo de diseño. Como siempre existe la posibilidad de encontrar entornos más reducidos o acotados, los objetivos prioritarios como portabilidad, interoperabilidad y el soporte completo del IDL son necesarios y trata de restringir las capacidades de CORBA, pero respetando estos objetivos. De cualquier modo, Minimum CORBA considera ciertas características de CORBA que influyen en el coste en términos de los recursos utilizados por el ORB o el tamaño de los cabos, aunque estas características no se utilicen: TypeCodes – Se mantiene la seguridad en todos los TypeCodes salvo para el tipo Any (que está excluido), serializando las referencias a Objetos. Excepciones – El soporte, tanto de las excepciones de usuario como las de sistema, se puede omitir cuando no se utilizan en la aplicación. Este modelo de programación i i i i i i i i 40 2. A NTECEDENTES aún puede ser útil (por ejemplo, en máquinas de estados finitos cooperativas donde los objetos puedan terminar de forma segura y su recuperación depende de la propia aplicación). Herencia – Se pueden omitir las tablas necesarias para mantener herencia múltiple si la aplicación no la utiliza. Las implementaciones de Minimum CORBA pueden decidir omitir estas características si se aseguran de que las aplicaciones no van a utilizarlas. El estándar contempla todas las características de CORBA explicando cuáles soporta y cuáles ha decidido omitir. A continuación, se exponen algunas de ellas: Repositorio de Interfaces Es un componente del ORB que permite el almacenamiento persistente de las definiciones de interfaces, su distribución y el manejo de colecciones de definiciones de interfaz relativas a los objetos. Se ha omitido todo excepto: RepositoryId: es una cadena que establece la identidad de la información en el repositorio. Permite a los programas operar con estos identificadores. TypeCode: son valores que representan los tipos de datos, tanto primitivos como derivados. Son necesarios para manejar el tipo CORBA Any, por lo que se ha mantenido en Minimum CORBA. El adaptador de objetos: POA Minimum CORBA admite un subconjunto de las interfaces y políticas del POA: Interfaces: POA – Se omite el soporte del modo dinámico de operación del POA. POAManager – El objeto POAManager se mantiene puesto que se utiliza en la operación create_POA. Las únicas declaraciones que no se han omitido son la operación activate y la excepción AdapterInactive, debido a que esta operación proporciona portabilidad de las aplicaciones en entornos CORBA. ServantManager – Se omiten los ServantManager debido a que ofrecen un modo de operación que no resulta imprescindible en un ORB básico. Como consecuencia, las interfaces derivadas también se omiten, igual que las excepciones inherentes a este modo de operación. Políticas: ThreadPolicy – Sólo se mantiene la política ORB_CTRL_MODEL, que es la que se aplica por defecto. Esta política delega en el ORB la responsabilidad de asignar hilos para peticiones al POA que controla dicho ORB. LifespanPolicy – Minimum CORBA la soporta completamente, con los valores TRANSIENT y PERSISTENT. Los objetos asociados a un POA con política TRANSIENT no pueden sobrevivir a la instancia del POA en la que fueron creados. Se mantiene la política PERSISTENT debido a que es la única manera i i i i i i i i 2. A NTECEDENTES 41 de crear objetos con una referencia conocida. Esta característica puede ser necesaria para que un servicio sea capaz de localizar a un objeto tras haber sido reinicializado. También es útil cuando se requiere un entorno prefijado, como puede ocurrir en aplicaciones que ofrezcan el código de acceso a las referencias de los servidores. ObjectIdUniquenessPolicy – También se encuentra totalmente soportada. Sus valores UNIQUE_ID y MULTIPLE_ID permiten que los sirvientes se activen ante un único ObjectId o que puedan soportar varios ObjectId. El coste de implementación de ambos es muy pequeño y permite a un único sirviente manejar varios objetos mediante multiplexación, lo que puede redundar en un mayor aprovechamiento de recursos. IdAssignmentPolicy – Los valores SYSTEM_ID y USER_ID se mantienen debido a que su coste es pequeño. Si se utiliza la política SYSTEM_ID será el propio POA quien asigne los ObjectId a los objetos, mientras que con la política USER_ID debe ser la aplicación la encargada de ello. ServantRetentionPolicy – Especifica si el POA debe mantener sus sirvientes activos en la Tabla de Objetos Activos (Active Object Map). En este caso, la política NON_RETAIN contiene elementos dinámicos no deseables, por lo que sólo se mantiene la política RETAIN. RequestProcessingPolicy – Especifica la forma de acceder a los sirvientes, pero como se explicó anteriormente, el modo de acceso siempre será a través de la Tabla de Objetos Activos que se encuentre en el POA. Esto implica que el único valor posible para esta política es USE_ACTIVE_OBJECT_MAP_ONLY. ImplicitActivationPoicy – Nuevamente se toma la decisión en base a qué valores permite una implementación de un ORB sencillo y sin valores dinámicos, puesto que el valor IMPLICIT_ACTIVATION tiene un coste nada despreciable. De este modo, Minimum CORBA sólo soporta el modo NO_IMPLICIT_ACTIVATION, por lo que el POA no permite la activación implícita de sirvientes. Interoperabilidad Para lograr la interoperabilidad hay que tener en cuenta dos situaciones: la comunicación entre la aplicación y el ORB, y la comunicación entre distintos ORB S. Si se desea que la interoperabilidad sea completa es necesario que estas dos situaciones se resuelvan de manera satisfactoria. El API del ORB ofrece un conjunto de servicios que la aplicación puede utilizar (dichos servicios se describen en «ORB Interoperability Architecture») [COR02, Cap.13]. Si el ORB es interoperable en este punto, cualquier aplicación CORBA podrá utilizarlo. Por otra parte, la interoperabilidad entre ORB S permite la comunicación entre sistemas con distintos conjuntos de prestaciones; por ejemplo, puede asegurar la comunicación entre el ORB de Minimum CORBA y CORBA, de manera que las aplicaciones que los utilicen puedan interactuar. i i i i i i i i 42 2. A NTECEDENTES Correspondencias de lenguajes CORBA especifica correspondencias con gran número de lenguajes: Ada, C, C++, COBOL, Java, Lisp, Python, etc.; las especificaciones de estas correspondencias pueden encontrarse en [Gro]. Minimum CORBA no especifica ninguna de ellas como obligatoria; sólo indica que debe existir, al menos, correspondencia con un lenguaje. 2.4.2. e*ORB OpenFusion e*ORB [eOR] es una implementación de Minimum CORBA con extensiones para tolerancia a fallos y tiempo real para obtener distintos niveles de servicios de disponibilidad y predictibilidad. Proporciona bindings para los lenguajes C, C++, Java y Ada. Las características de cada uno de ellos son diferentes, pero podemos resumirlas en las siguientes: Conformes a la especificación de Minimum CORBA 1.0. Portables entre distintas plataformas. GIOP 1.2. IIOP. Compilador de IDL a los diferentes lenguajes. Alrededor de un 10 % de sobrecarga frente a sockets. e*ORB se puede ejecutar en una HP iPAQ o en un DSP Texas Instruments TMS320C64X. El fabricante lo describe como «el ORB CORBA más pequeño y rápido», aunque no proporciona código fuente ni comparativas con otras alternativas. 2.4.3. Gibraltar Esta implementación trata de ser fiel a la especificación de Minimum CORBA. El proyecto está dividido en módulos con objetivos concretos. Así, Gibraltar [Gib04] necesita los módulos: tibet, que contiene toda la documentación, y france, que es el compilador de IDL. Esta división hace posible la utilización de herramientas de otros fabricantes para tareas específicas. 2.4.4. nORB nORB [SXGC03, GSP+ 03, SXG+ 04] es un middleware de propósito específico basado en CORBA para redes de sensores, concretamente se trata del mismo dominio que describe el programa NEST (Networked Embedded System Technology) [NESb] de DARPA. Los objetivos que se marcaron sus diseñadores fueron: Reutilizar infraestructuras existentes – Para evitar el desarrollo de un middleware desde cero. i i i i i i i i 2. A NTECEDENTES 43 Proporcionar garantía de tiempo real – Debe proporcionar tiempos deterministas a las aplicaciones. Proporcionar un MDOO robusto – El enfoque de comunicación de objetos distribuidos ofrece un modelo de programación más mantenible y ofrece comunicación directa con los nodos de la red. Recursos de cómputo limitados – La plataforma objetivo son los nodos transductores, que tienen fuertes restricciones de memoria. nORB sigue una estrategia de diseño bottom-up utilizando ACE (ADAPTIVE Communication Environment) como base, pero muy dirigida por los conceptos de diseño de Kokyu, e*ORB, UIC-Core y, especialmente, de TAO. nORB soporta los tipos básicos de CORBA, estructuras y secuencias, pero no los tipos Any ni TypeCode ya que se considera que las aplicaciones sobre la SAN no harán un uso relevante de estos tipos. Utiliza CDR para la serialización de datos, cuyo soporte proporciona ACE. nORB ofrece únicamente los mensajes Request, Reply, Locate Request y Locate Reply, pero elimina algunos campos del protocolo GIOP, como service context, ya que considera que eliminar generalidad innecesaria ayuda a reducir los recursos requeridos por la implementación. El entorno experimental que describe S UBRAMONIAN [SXGC03] consta de cuatro computadores con procesador Pentium 4 a 2,53 GHz, cuentan con 512 MiB de RAM y sistema operativo KURT con núcleo Linux 2.4.18. La aplicación de pruebas aplica Distributed Breakout Algorithm (DBA) al problema del coloreado de grafos distribuido. La tabla 2.2 muestra el tamaño del programa ejecutable en varias alternativas. Note que los valores mostrados incluyen el código específico de la aplicación (unos 164 kB), pero no el de las bibliotecas del sistema o el SO. middleware ACE TAO nORB TAO optimizado nORB optimizado tamaño (kB) 376 1 800 567 1 738 509 C UADRO 2.2: nORB: Tamaños de programa para una aplicación de referencia nORB implementa un conjunto de protocolos de transporte como plugins, que incluyen protocolos ESIOP S. 2.4.5. dynamicTAO dynamicTAO [KCBC02] es una extensión para dotar a TAO de capacidades de reflexión. Un middleware reflexivo es aquel que tiene la capacidad de acceder a sus parámetros de funcionamiento interno (introspección) y modificarlos en tiempo de ejecución para adaptar su desempeño a las necesidades de un entorno cambiante. i i i i i i i i 44 2. A NTECEDENTES TAO utiliza el concepto de estrategia para encapsular un conjunto de parámetros de configuración que permiten definir aspectos de concurrencia, planificación, gestión de conexión, etc. La estrategia está expresada en un fichero de configuración y es evaluada y establecida en el arranque del ORB. dynamicTAO aporta mecanismos para que el middleware pueda cambiar de estrategia en tiempo de ejecución, clientes conectados o pueda afectar a instancias remotas del mismo ORB. Su arquitectura se basa en un conjunto de entidades llamadas configuradores de componentes (component configurators). Son los encargados de gestionar las dependencias entre los componentes del sistema. Los más importantes son: DomainConfigurator – Se encarga de mantener referencias a otras instancias del ORB y a los sirvientes vinculados a un proceso. Debe existir una instancia de este componente en cada proceso que ejecuta el ORB. TAOConfigurator – Contiene referencias a las estrategias activadas. Estos componentes están implementados como plugins, de modo que se pueden cargar o descargar en tiempo de ejecución. Network Broker – Recibe y gestiona las peticiones de reconfiguración del ORB. Dynamic Service Configurator – Proporciona primitivas para la reconfiguración dinámica de los componentes. 2.4.6. UIC Universally Interoperable Core (UIC) [RKC01] es un middleware reflexivo diseñado para cubrir las necesidades propias de las aplicaciones de computación ubicua, es decir: Integración de una gran variedad de dispositivos, protocolos y servicios. Entornos altamente dinámicos. Posibilidad de adaptación de la propia arquitectura del middleware a la funcionalidad requerida. Proporciona un esqueleto para un entorno de comunicaciones completo basado en componentes abstractos y sus instancias concretas como componentes que pueden ser cargados dinámicamente. De ese modo, es capaz de ofrecer soporte a distintas plataformas, dispositivos y protocolos. Su diseño sigue dos principios básicos: Simplicidad – Se consigue con un diseño muy modular, de modo que la descomposición funcional sea clara y fácil de comprender. Adaptabilidad – Sólo los componentes necesarios para cubrir la funcionalidad requerida serán incluidos en cada instancia concreta de UIC. Esto supone una gran diferencia respecto a los núcleos de comunicaciones convencionales, en los que se incluye siempre toda la funcionalidad disponible aunque no se utilice para un cliente u objeto concreto. i i i i i i i i 2. A NTECEDENTES 45 La instanciación dinámica de componentes puede no ser conveniente o posible en dispositivos con recursos limitados. Por ello, existe también la posibilidad de generar un núcleo UIC de forma estática. Los componentes, sus interfaces exportadas y la propia estructura del esqueleto pueden ser adaptadas estática o dinámicamente dependiendo del escenario o dispositivo concreto. Proporciona componentes especializados para tres importantes núcleos de comunicaciones orientados a objetos: CORBA, Java RMI y DCOM (Distributed Component Object Model), aunque ello no implica la imposibilidad de adaptación a otras plataformas que no estén basadas en objetos distribuidos. Los componentes relacionados con un middleware específico se denominan personalidad distinguiendo entre cliente y servidor; es posible que un mismo núcleo tenga varias personalidades al tiempo, por ejemplo, ClientCORBA, ServerCORBA y ClientJavaRMI. Todos los aspectos del núcleo de comunicaciones pueden ser adaptados por medio de componentes: protocolos de transporte, estrategias de serialización, despachado de invocaciones, interfaz de los objetos, gestión de la memoria, de la concurrencia, etc. La flexibilidad de UIC permite crear núcleos de comunicaciones para un amplio rango de necesidades; desde sistemas sin limitaciones de recursos (en cuyo caso todas las prestaciones habituales del ORB están disponibles) hasta PDA S, cubriendo únicamente la funcionalidad requerida. La tabla 2.3 muestra los tamaños para algunos núcleos concretos en dispositivos de recursos limitados. Personalidad HybridMultipersonality CORBA Dynamic Server Simple TCP Dynamic Server CORBA Static Client CORBA Static Server CORBA Static Full (client + server) WindowsCE (SH3) PalmOS 39 28 30 29 35 44,5 16 - C UADRO 2.3: Memoria necesaria (en kB) para algunas configuraciones de UIC. (ROMAN [RKC01]) 2.4.7. LegORB LegORB [RMKC00] es un ORB modularizado con capacidades de configuración dinámica por medio de una arquitectura basada en componentes. Sigue los mismos principios de diseño que UIC, pero con dos diferencias principales: está mucho más orientado a dispositivos con pocos recursos y sólo utiliza CORBA. LegORB incluye únicamente los componentes esenciales para garantizar interoperabilidad CORBA. El programador puede implementar componentes a medida o utilizar los que ya incorpora el ORB. El núcleo de LegORB tiene tres component configurators (véase § 2.4.5): LegORB configurator, Client-side configurator y Server-side configurator. Con ellos se pueden combinar los elementos necesarios para crear un núcleo de comunicaciones funcional. Estos elementos se clasifican en diferentes categorías: red, serialización, etc. Así se determina la funcionalidad, comportamiento y tamaño del ORB resultante. No obstante, estos componentes se pueden cargar y eliminar en tiempo de i i i i i i i i 46 2. A NTECEDENTES ejecución, de modo que la aplicación puede decidir si se requiere la funcionalidad necesaria como cliente, como servidor o ambos. La interfaz de invocación dinámica no es conforme a la especificación CORBA pero, según sus autores, resulta suficiente para dispositivos empotrados. LegORB ha sido instalado con una PDA PalmPilot con SO PalmOS 3.0 y con un terminal HP Jornada 680 con WindowsCE 2.11. Se ha probado la interoperabilidad de un cliente conectando a un objeto alojado en un PC que utiliza TAO. En la versión PalmPilot el tamaño de LegORB es de 6 kB y en la WindowsCE de 20 kB (solo cliente en ambos casos). 2.4.8. MicroQoSCORBA MicroQoSCORBA (MQC) [Hau01] es un conjunto de herramientas CASE para la creación de núcleos CORBA personalizables. Su objetivo es facilitar la creación de middlewares especializados a desarrolladores de aplicaciones distribuidas sobre sistemas empotrados que no tengan experiencia en este área. Utilizando un compilador de IDL propio y herramientas gráficas proporciona al desarrollador la posibilidad de especificar diferentes aspectos tales como protocolo de comunicaciones, seguridad, consumo de potencia, rendimiento y otras restricciones de Q O S, para obtener un ORB a la medida de las necesidades de la aplicación y plataforma objetivo. Algunos de los aspectos que puede especificar el programador son: Roles del ORB Sólo se incluyen las utilidades para el lado del servidor, del cliente o ambos, si son necesarias. Soporte para servicios Por ejemplo, para utilizar el servicio de nombres. Protocolos de comunicación Aparte de los protocolos de transporte soportados: TCP/IP, UDP, serie y 1-Wire; también permite distintos protocolos para codificación de mensajes: GIOP, GIOPLite y MQC-IOP. MQC-IOP es un protocolo basado en GIOP 1.1, pero que elimina campos innecesarios para simplificar las rutinas de construcción y reconocimiento de mensajes. También utiliza otras técnicas que no comprometen la interoperabilidad, como la restricción de utilizar identidades de objeto de tamaño fijo. Tipos de datos El programador puede especificar individualmente si desea que se incluyan las rutinas para serialización de muchos de los tipos CDR y excepciones. No se permiten tipos complejos como Any o TypeCode. Compresión Opcionalmente es posible comprimir los nombres de métodos e interfaces para reducir el tamaño de los mensajes. La implementación realizada está escrita en lenguaje Java y se ejecuta sobre el dispositivo Tiny InterNet Interface (TINI) y también sobre PC S convencionales. La implementación i i i i i i i i 2. A NTECEDENTES 47 proporcionaba interoperabilidad con ORB genéricos como JacORB, TAO, Visibroker y ZEN. Las opciones utilizadas fueron GIOP, TCP/IP, serialización en línea y compresión de nombres. La tabla 2.4 muestra el tamaño de los ficheros .class de la aplicación y las bibliotecas para distintas alternativas. En la comparación, MQC no proporciona soporte para ningún servicio estándar mientras que JacORB sí lo hace (suponen unos 3.7 MB del tamaño indicado). El tamaño de la JVM es de 1 MB para JacORB y 200 kB para ZEN. La memoria RAM requerida por MQC en el dispositivo TINI es de unos 31 kB para un cliente y unos 35 KB para un servidor. GNU/Linux TINI middleware cliente servidor cliente servidor Java RMI MQC Zen JacORB 4,38 35,18 356,08 6 596,19 4,59 43,41 351,70 6 592,64 14,59 - 22,11 - C UADRO 2.4: MQC: Comparativa de memoria necesaria (en kB). (Olav H AU GAN [Hau01]) 2.4.9. Smart Transducer Interface Las redes de dispositivos (no solo las SAN) tienen habitualmente un conjunto de necesidades comunes. En ese contexto, aparece el concepto de ST (Smart Transducer)7 , que puede definirse como sigue: Un smart transducer es un dispositivo formado por uno o varios transductores (sensores y/o actuadores), un elemento de cómputo simple (microcontrolador), una o varias interfaces de comunicaciones y el software necesario para la comunicación, calibración y diagnosis de los transductores que incorpora. Existen varias propuestas que pretenden definir una interfaz estándar para ST S: el estándar IEC 61158 (muy influenciado por sistemas anteriores como PROFIBUS y FieldBus), IEEE 1451.2, etc. Sin embargo, en el contexto de este documento, resulta mucho más interesante la especificación STI [Obj03] de OMG debido a que implica la utilización de un MDOO. STI pretende definir y estandarizar una interfaz universal para la comunicación e integración de ST S pasados y futuros, incorporando al diseño los requisitos que aparecen reiteradamente en las aplicaciones relacionadas con estos dispositivos. La especificación comprende un servicio de transporte de datos dirigido por tiempo (time-triggered) y la definición de interfaces para un sistema CORBA. Para STI un sistema ST es un conjunto de racimos (cluster) de transductores accesibles a través de un único bus de comunicaciones. Cada racimo depende de un nodo maestro que lo conecta a una pasarela que es la encargada de que los transductores sean vistos como objetos CORBA. El maestro se comunica con los ST S utilizando un protocolo de comunicaciones de tiempo real (ver figura 2.4). 7 Transductor inteligente. i i i i i i i i 48 2. A NTECEDENTES F IGURA 2.4: Representación de un sistema STI [Obj03] Todos los datos que puede ofrecer el transductor se acceden a través de registros de un sistema llamado Interface File System (IFS). Por medio del bus interno del racimo (fieldbus) se copian datos desde y hacia el IFS de cada ST. La planificación de estas operaciones de bus está predefinida. Cada ST puede contener un máximo de 64 ficheros en su IFS; cada fichero es un vector de 256 registros (32 bits por registro). Estos registros son accesibles como unidades individuales mediante un sistema de direccionamiento jerárquico. Se definen tres interfaces especializadas para acceder a los datos de cada ST individual por medio de registros IFS: DM (diagnosis and management) – Permite leer y modificar registros IFS relacionados con los parámetros y la calibración inicial del transductor, también se utiliza para acceder a datos de diagnóstico que sirven para verificar el correcto funcionamiento del nodo y sus transductores. CP (configuration and planning) – Se utiliza para configurar e integrar nodos nuevos en la red. RS (real-time service) – Se establece una comunicación periódica para recoger datos relacionados con el valor de los transductores del nodo. En el caso de un sensor, el ST realiza lecturas del sensor periódicamente, las preprocesa, acondiciona y las envía al maestro del racimo. El transporte definido en la citada especificación ha sido implementado en el protocolo TTP/A. Utiliza un sistema de arbitraje de bus de tipo TDMA, y es lo suficientemente simple para ser implementado en microcontroladores de 2 KiB de memoria Flash y 64 bytes de memoria RAM. Es importante señalar que este protocolo se utiliza sólo en el racimo para comunicar los ST S con el maestro, es decir, los clientes de la aplicación CORBA acceden a datos alojados en la pasarela y en ningún momento tienen comunicación directa con los dispositivos detrás de la misma. i i i i i i i i 2. A NTECEDENTES 49 NAGEL[NA02] propone un enfoque con características similares. Describe cómo una colección de pequeños microcontroladores de 8 bits pueden aparecer como un conjunto de objetos CORBA. El host ejecuta un proxy para cada dispositivo conectado y las comunicaciones entre los dispositivos y el proxy utilizan un protocolo específico no estándar. 2.4.10. UORB Ubiquitous ORB [RFC03] propone un sistema que permite a dispositivos con limitaciones de capacidad de cómputo y memoria, participar en un entorno CORBA, pero sin que estos implementen ninguna función del ORB. Sigue un modelo similar al que planteaba Jini Surrogate Architecture [Sun06] de Sun Microsystems. No implementa ninguna interfaz CORBA en los dispositivos, de forma similar a STI, de modo que éstos utilizan la infraestructura CORBA únicamente a través de los objetos intermediarios8 alojados en un computador sin restricciones de recursos. Estos intermediarios son objetos CORBA convencionales que pueden desarrollarse con cualquier ORB disponible; es la referencia de estos objetos la que se publica y la que utilizan los clientes para acceder desde la red CORBA. El sistema proporciona integración automática de nuevos dispositivos basada en un mecanismo de descubrimiento entre el dispositivo y el computador intermediario. Por medio del objeto intermediario, el dispositivo averigua la identidad del servidor pero no necesita conocer la información de direccionamiento. También es posible utilizar diversos mecanismos de comunicación entre los dispositivos y el host intermediario, tales como memoria compartida o sockets Unix. Como UORB no es una implementación conforme a Minimum CORBA, todos las estrategias de escalabilidad como servant activators o servant locators están disponibles, así como cualquier servicio de la plataforma. Por ejemplo, se requiere el servicio de nombres (CosNaming) e IR para su correcto funcionamiento. El sistema se sustenta en dos módulos principales: El servicio intermediario (Surrogate Host). Se preocupa de la carga, activación y ejecución de los objetos intermediarios. El adaptador de interconexión (Interconnect Adapter). Se encarga de las comunicaciones entre el módulo anterior y los dispositivos, que se efectúa por medio del protocolo de interconexión. Dicho protocolo (basado en IP) define los mecanismos de descubrimiento (basado en multicast), registro y recuperación de objetos intermediarios y comprobación periódica de los dispositivos (liveness). Se realizó y simuló un prototipo implementado en lenguaje Java con JDK 1.3 sobre ORBacus 4.1. El tamaño del bytecode generado es de 45 kB tanto en el caso de un cliente como en un servidor. En cuanto a la plataforma requerida, RODRIGUES[RFC03] indica que las necesidades de procesamiento y memoria son menores que las de Orbix/E 8 Llamados surrogate objects en la terminología de Jini. i i i i i i i i 50 2. A NTECEDENTES 2000 (un ORB conforme a Minimum CORBA). No se indican detalles concretos sobre la posible plataforma objetivo. 2.4.11. I CE -E Embedded I CE (I CE -E) es una versión de I CE para sistemas empotrados, especialmente orientada a smart phones y otros dispositivos personales con energía y memoria relativamente limitada. Como en los casos anteriores, la estrategia utilizada consiste en eliminar prestaciones, concretamente se ha eliminado la gestión de conexiones ACM, el soporte para UDP y SSL, el Servant Locator, las optimizaciones de co-ubicación, el despachado asíncrono (AMD), las utilidades de dynamic I CE y la compresión de paquetes entre otras. Sin embargo, se han añadido otras prestaciones útiles para las aplicaciones y plataformas objetivo: sirvientes por defecto, priorización de hilos, soporte para Windows Mobile y dispositivos Embedded Linux, compilación estática y lo más importante, la posibilidad de elegir las prestaciones del ORB al compilar gracias a su sistema de construcción modular. Pudiendo además utilizar una versión completa de la biblioteca o una que solo incluye funcionalidad para clientes. Según su documentación [Ice], un cliente enlazado estáticamente ocupa menos de 216 kB mientras que un servidor ronda los 272 kB. 2.5. Middlewares para redes de sensores En esta sección se hace una descripción de algunos de los middlewares para redes SAN más relevantes. La mayoría de ellos se centran específicamente en WSN dado que se considera un área con condicionantes particulares [HM06, RKM02, HR06, WCLD08, Yu004, VHM+ 07, R0̈4]. Concretamente, las comunicaciones inalámbricas y la alimentación por medio de baterías tienen una gran influencia en el diseño y prestaciones de estos sistemas. Las propuestas analizadas se han clasificado en 5 tipos, aunque no son excluyentes. Para cada tipo se presentan en detalle las que consideramos más representativas. Máquina virtual Se basa en la utilización de un intérprete de bytecode que se aloja en el nodo. Los motivos para seguir este enfoque son variados: Conseguir portabilidad de los programas entre distintas arquitecturas. Se consigue independencia del dispositivo, simplifica los procesos de depuración y prueba. Crear un juego de instrucciones con un mayor nivel de abstracción, más cercano al dominio del problema de modo que el programador de la aplicación no necesita conocer los detalles del dispositivo. Disponer de programas más pequeños. Eso implica actualización y despliegue más eficiente de las aplicaciones que se ejecutan en los nodos al tener que transmitir menos bytes. Se describen Maté (§ 2.5.5), Magnet (§ 2.5.6), SensorWare (§ 2.5.7) y WSP (§ 2.5.14). i i i i i i i i 2. A NTECEDENTES 51 Base de datos virtual Modelan la red de sensores como una base de datos distribuida. Ofrecen un lenguaje de consulta similar a SQL. Este lenguaje permite escribir consultas para seleccionar un conjunto de sensores por su tipo, localización u otros atributos. A los sensores seleccionados se les puede solicitar su valor y en algunos casos proporcionan operadores de agregación como la suma o la media de sus valores. En general estos sistemas consideran que todos los nodos son similares y ofrecen información homogénea asumiendo que todos ellos tienen un conjunto concreto de sensores que se representan como columnas de una tabla. Esto es una grave limitación en entornos en los que pueden aparecer nuevos tipos de nodos o sensores. Este modelo es adecuado para sensores que ofrecen valores simples, pero es insuficiente para tratar datos generados por sensores complejos como micrófonos, arrays de sensores infrarrojos o cámaras de vídeo [HR06]. Se describen SINA (§ 2.5.1), DSWare (§ 2.5.2), TinyDB (§ 2.5.3) y Cougar (§ 2.5.4). Macro-programación Es un enfoque holístico de la funcionalidad de la SAN. El programador escribe un programa en el que especifica el funcionamiento de la red completa como un solo ente. Después, un compilador genera un conjunto de instrucciones o programa individual para cada nodo, y así una vez en ejecución, el comportamiento de la red corresponda con el requerido en la especificación original. Se describen Maté (§ 2.5.5), Magnet (§ 2.5.6), SensorWare (§ 2.5.7) y WSP (§ 2.5.14). Clusters Son middlewares cuyo funcionamiento está determinado por la formación de clusters o grupos de nodos. Uno de los nodos del cluster asume un rol especial actuando como cabeza. Ese nodo se encarga de tareas de agregación de datos, filtrado o encaminamiento. El procedimiento para la formación del grupo o la elección de la cabeza varía mucho de un sistema a otro. SINA (§ 2.5.1), DSWare (§ 2.5.2) o EnviroTrack (§ 2.5.12) utilizan clusters. Otros Se describen también otros middlewares con diseños menos convencionales; orientados a la movilidad de los nodos: Impala (§ 2.5.10), con especial énfasis en la adaptabilidad de la red y las aplicaciones: MiLAN (§ 2.5.8) y TinyCubus (§ 2.5.9) o que modelan la SAN como un espacio de memoria compartida: TinyLime (§ 2.5.11). 2.5.1. SINA Sensor Information Networking Architecture (SINA) [SJS01] es un middleware que ofrece soporte para la organización adaptativa de la información disponible en los sensores mediante un conjunto de primitivas. Modela la SAN como una colección de objetos i i i i i i i i 52 2. A NTECEDENTES masivamente distribuidos y permite la organización e interacción con los nodos de la red bajo criterios de escalabilidad, fiabilidad y uso eficiente de la energía. Las bases de su diseño son: Organización como clustering jerárquico basado en los niveles de energía y proximidad de los nodos. Con ello se logra un acceso energéticamente eficiente desde el punto de vista de las comunicaciones. Hace uso de protocolos que reducen las retransmisiones cuando la información solicitada involucra a nodos cercanos. El proceso de clustering se reinicia cuando la cabeza del cluster falla o su batería baja de cierto umbral. SINA asume que el usuario nunca requerirá información proporcionada por un sensor concreto. Las aplicaciones únicamente requieren datos generales sobre una zona o colección de sensores relacionados. Identificación de los nodos basada en atributos. Los nodos no se acceden por medio de un identificador o dirección explícita. En lugar de eso se utiliza un enfoque basado en atributos y valores [EGHK99] ya que se considera que encaja mejor en la naturaleza data-centric de las redes de sensores. Por ejemplo, se puede seleccionar un nodo como [type=temperature, id=101, timestamp=1/10/2000:09:05:29, location=N-E, temperature=103] y responderá o no dependiendo de la consulta que se haga a la red. La información de los sensores se almacena y presenta como hojas de cálculo asociativas [KSSZ97]. De ese modo, la información se accede y organiza de acuerdo a las necesidades de cada aplicación específica. Las aplicaciones obtienen la información recogida por los sensores haciendo consultas a esas hojas de cálculo (una por sensor) por medio de SQTL (Sensor Query and Tasking Language). SQTL es un lenguaje de script basado en la sintaxis de SQL. Aparte del acceso a los datos de los dispositivos, proporciona primitivas para la gestión de eventos y las comunicaciones. Las aplicaciones consideradas por SINA requieren la localización espacial de los nodos. Como resulta económicamente prohibitivo instalar un receptor GPS en cada sensor, se establecen mecanismos para que los nodos que no lo tienen puedan calcular su posición a partir de información periódica que reciben de los nodos que sí tienen GPS. La asunción de que las aplicaciones no estarán interesadas en datos de nodos individuales impide a la aplicación elegir la granularidad que más le conviene en cada caso. También limita las posibilidades del middleware para realizar tareas sencillas, pero muy habituales en aplicaciones típicas en muchos ámbitos como la domótica, la seguridad y, en general, cualquier entorno inteligente. 2.5.2. DSWare Data Service middleWare (DSWARE) [LLS+ 03] es un middleware centrado en los datos que proporciona una abstracción de base de datos. Está basado en la definición de grupos como medio para la toma de decisiones, correlación de datos y ahorro de i i i i i i i i 2. A NTECEDENTES 53 energía. Asume que las operaciones sobre la WSN implican restricciones temporales y requieren una respuesta en tiempo real. La arquitectura de DSWare se basa en los siguientes componentes funcionales: Almacenamiento de datos Los datos que describen diferentes ocurrencias del mismo tipo de actividad se pueden mapear en ciertas localizaciones para que futuras consultas no impliquen nuevos mensajes en la red, optimizando de ese modo el uso de la red y, por tanto, la autonomía. Caché de datos Se mantienen varias copias de los datos más solicitados. Los datos se distribuyen a lo largo de las rutas para reducir las comunicaciones. Es posible determinar el uso de cada copia. Éstas se pueden migrar a otros nodos para maximizar su uso. Gestión de grupos Asume que los sensores del mismo área producen valores similares. Eso permite que, en zonas con suficiente densidad de sensores, se puedan detectar nodos que ofrecen lecturas erróneas. También es posible desactivar sensores cuando se detecta que ofrecen información redundante y así ahorrar energía. Este componente se encarga también de aquellas tareas que requieren la cooperación de un conjunto concreto de sensores. Los grupos se crean cuando se debe satisfacer una necesidad y desaparecen cuando termina la tarea asignada. El sistema hace una consulta a la red y son los sensores los que deciden si formarán parte del grupo evaluando el criterio indicado en la consulta. Detección de eventos Los eventos se registran de acuerdo a cada aplicación. Suscripción de datos Es un servicio avanzado de suscripción a eventos por medio de consultas que implican una duración y un ratio. Planificación Proporciona gestión de plazos para tiempo real y ahorro de energía. Las aplicaciones pueden especificar el esquema de planificación teniendo en cuenta sus propios condicionantes. Los eventos tienen una gran importancia en esta propuesta. Se clasifican en atómicos (detectados por un sensor) o compuestos (inferidos a partir de coincidencia temporal o espacial de otros eventos). Por ejemplo, un evento compuesto explosión ocurre cuando se detectan eventos atómicos acústicos, luminosos y de subida de la temperatura al mismo tiempo. Cuando ocurren eventos físicos lo habitual es que el sistema detecte sus consecuencias por medio de diferentes sensores (sub-eventos). La función de confianza ayuda a determinar si el conjunto de sub-eventos encajan en la definición de un evento complejo teniendo i i i i i i i i 54 2. A NTECEDENTES en cuenta factores de contexto, históricos, importancia relativa de cada sub-evento, distancia al lugar, etc. Para la declaración, registro y cancelación de eventos utiliza una interfaz que procesa un lenguaje similar a SQL. Plataforma Ofrece resultados en la gestión de eventos en un despliegue simulado, pero no incluye información sobre una implementación en dispositivos físicos o de los requisitos de cómputo que implicaría. 2.5.3. TinyDB TinyDB [MFHH05] utiliza un lenguaje llamado ACQL similar al utilizado por SINA. El procesador de consultas está diseñado para reducir las comunicaciones y el consumo de energía. La red de sensores completa está modelada como una única tabla (SENSORS) de una base de datos en la que cada fila es un sensor y cada columna un atributo: identificador, autonomía, etc. El lenguaje de consulta tiene capacidades para procesamiento de eventos y especificación del tiempo de validez. Dispone de características para agregación flexible y extensible de los datos. Sin embargo, el middleware ofrece poco soporte a las aplicaciones. Éstas no tienen la posibilidad de influir en los parámetros a optimizar y deben implementar la mayor parte de la funcionalidad necesaria por los servicios. Presenta problemas de escalabilidad dado que las consultas se envían a todos los nodos y debe mantener un árbol de expansión de toda la red. Está implementado como un componente para TinyOS. 2.5.4. Cougar Cougar [YG02] es otro middleware de base de datos virtual. Como en los anteriores, utiliza un lenguaje de consulta inspirado en SQL. Sus características son muy similares a las de TinyDB incluyendo los operadores para selección de sensores y agregación de datos por técnicas de clustering, gestión de eventos y procesamiento de consultas optimizado para ahorro de batería. No se aporta información sobre la plataforma de implementación o los recursos requeridos. 2.5.5. Maté Maté [LC02, LGC05] es un intérprete de bytecode (máquina virtual) que se ejecuta en motas con TinyOS. Está inspirado en Active Messages y J-Machine, pero simplificado debido a las restricciones de la plataforma objetivo. Define un juego de instrucciones que permite especificar el comportamiento del nodo ante una serie de eventos predefinidos. Dichos eventos están ligados a los sensores disponibles en la plataforma. La máquina virtual se utiliza para conseguir instrucciones de mayor nivel de abstracción. De ese modo, es posible describir comportamientos no triviales en programas muy cortos. i i i i i i i i 2. A NTECEDENTES 55 Los programas se dividen en cápsulas de 24 instrucciones para que sea más sencillo transmitirlos sobre los protocolos típicos en esta plataforma. Disponer de programas tan cortos hace que el coste de las actualizaciones en términos de energía sea muy bajo. Maté está diseñado bajo la presunción de que, dentro de un mismo dominio, las aplicaciones están compuestas a partir de un conjunto cerrado de bloques funcionales, de modo que únicamente la forma en la que se combinan determina la finalidad del servicio o sub-sistema. El juego de instrucciones permite al programador definir hasta 8 instrucciones propias. Cada instrucción virtual se ejecuta como una tarea independiente de TinyOS, por lo que los servicios propios del sistema operativo pueden funcionar de forma concurrente a la ejecución de las instrucciones. El listado 2.4 muestra un programa de ejemplo: en cada ciclo de reloj incrementa un contador y representa en los LED S de la mota sus tres bits menos significativos. pushc 1 add copy pushc 7 and putled halt # Push one onto operand stack # Add the one to the stored counter # Copy the new counter value # Take bottom three bits of copy # Set the LEDs to these three bits L ISTADO 2.4: Programa de ejemplo de Maté. (P. L EVIS [LC02]) Con esta filosofía es posible construir aplicaciones complejas como encaminamiento ad hoc que pueden estar compuestas por varias cápsulas ocupando en total menos de 100 bytes. Aparte del bytecode, cada cápsula contiene un tipo y un número de versión. Existen cuatro tipos: envío de mensaje, recepción de mensaje, de tiempo y de subrutina. La máquina virtual emplea una pila para operandos, que es utilizada por la mayor parte de las instrucciones. Una segunda pila almacena direcciones de retorno y la utilizan las instrucciones de control de flujo. Además, algunas de las instrucciones tienen operandos implícitos codificados con algunos de los bits del propio código de instrucción. La máquina dispone de tres contextos de ejecución concurrentes para timeouts, recepción y envío de mensajes. Para el despliegue de código dispone de una instrucción para enviar la propia cápsula a otra mota. Dicha instrucción se ocupa de los detalles necesarios para que sea encaminada automáticamente. El diseño de la ISA (Instruction Set Architecture) y la máquina virtual permiten desplegar y ejecutar código con bajo consumo y alta seguridad. El sistema oculta la asincronía de TinyOS de modo que el programador sólo tiene que ocuparse de la coherencia secuencial de su programa. Sin embargo, el diseño de Maté dificulta la posibilidad de incluir nuevas características en los nodos y más aún si se trata de nuevas plataformas o arquitecturas. La asunción de que todos los programas de un dominio emplean los mismos bloques funcionales implica una baja flexibilidad en las posibilidades de adaptar Maté a entornos especializados o dinámicos. i i i i i i i i 56 2. A NTECEDENTES Tiene un gran acoplamiento con TinyOS y la plataforma, hasta el punto de que realiza un direccionamiento predefinido de los sensores disponibles en el dispositivo (por ejemplo, la lectura del sensor de luz es pushc 1; sense). No ofrece una abstracción real sobre los dispositivos que propicie la elaboración de servicios de alto nivel ni ofrece mecanismos para la integración de la red SAN en aplicaciones complejas o que abarquen otras redes de sensores. Además, la máquina virtual no permite modelar el protocolo de comunicaciones; los programas escritos con bytecode especifican la funcionalidad del sirviente, es decir, cómo se manejan los datos procedentes de los sensores, pero no se utiliza para describir los sensores disponibles o sus tipos. Según sus autores, Maté es sólo una arquitectura y un bytecode. El siguiente paso es crear lenguajes de alto nivel y modelos de programación para el desarrollo de aplicaciones, proporcionando un entorno de programación distintivo de TinyOS. Agilla [FRL05] propone algunas mejoras sobre Maté, estableciendo procedimientos más eficaces para despliegue de actualizaciones de código. Utiliza agentes que pueden moverse de un nodo a otro evaluando el estado de la red. Plataforma Puede instalarse sobre las motas modelo MICA y Rene2. La tabla 2.5 muestra los requerimientos de memoria para una aplicación patrón. componente Máquina virtual (Maté) Network Logger Hardware Boot/Scheduler Total código (bytes) datos (bytes) 7 286 6 410 844 1 232 272 16 044 603 206 18 8 14 849 C UADRO 2.5: Maté: Requerimientos de memoria 2.5.6. Magnet Magnet [BBD+ 02] es un sistema adaptativo para redes ad hoc y redes de sensores. Proporciona una máquina virtual Java que representa toda la red. Ofrece gran flexibilidad al programador permitiéndole migrar objetos y decidir su localización. Sus aplicaciones pueden verse como macro-programas, dado que se escribe un único programa Java que se ejecuta sobre toda la red. El sistema se encarga de dividir y distribuir el código y colocar los objetos en el lugar más adecuado. Es decir, lo más cerca de los datos que consumen y con ello consigue reducir los recursos y energía necesarios para las comunicaciones. El hecho de utilizar Java simplifica su uso aunque también implica limitaciones en cuanto a soporte de plataformas heterogéneas. En ese sentido, la JVM requiere demasiados i i i i i i i i 2. A NTECEDENTES 57 recursos de cómputo como para que se pueda ejecutar siquiera en la plataforma WSN por excelencia: las motas. 2.5.7. SensorWare SensorWare [BHS03, BHSS07] es un framework muy enfocado al despliegue de actualizaciones de software en redes WSN. Mediante un conjunto de servicios abstractos y la ejecución de scripts de control que pueden ser instalados en los nodos puede definir nuevos servicios de forma dinámica. Su enfoque permite la agregación de los datos consultados como una base de datos distribuida, pero no utiliza un lenguaje derivado de SQL. En su lugar utiliza scripts T CL. Aplica la idea de sensores activos, es decir, que pueden reaccionar a distintos tipos de eventos, no sólo a consultas recibidas de los clientes. Por tanto, se trata de un sistema dirigido por eventos. Su diseño considera que un algoritmo distribuido debe ser entendido como un conjunto de programas que se ejecutan en nodos independientes y colaboran para realizar una tarea. Todos los recursos del nodo (sensores, interfaz de comunicaciones, etc.) están disponibles para estos scripts. Los clientes realizan consultas inyectando scripts de control en la red, que se propagan a los nodos que lo requieran. SensorWare está formado por dos componentes principales: un lenguaje y un entorno de ejecución. Cada una de las instrucciones que forman el lenguaje abstrae una tarea concreta en el nodo sensor, tal como la comunicación con otros nodos, la lectura de información de los sensores, etc., aparte de instrucciones de control de flujo y sentencias condicionales habituales en un lenguaje procedural. Éste está constituido por funciones T CL. Para dar soporte a plataformas heterogéneas, se representan los dispositivos por medio de una capa de abstracción de hardware que permite utilizarlos como dispositivos virtuales (concepto extraído del kernel Linux). Existe una serie de primitivas que se implementan en el driver de dispositivo y permiten añadir nuevos elementos al run-time de SensorWare. Existen varios prototipos de implementación en torno a varios modelos de PDA S HP iPAQ. El último de ellos [BHSS07] utiliza una iPAQ 3950 con procesador Intel XScale de 32 bits, 16 MiB de RAM y 64 MiB de Flash. El sistema operativo utilizado es Familiar con Linux 2.4.18. También se ha portado a nodos Rockwell WINS, que disponen de un procesador StrongARM y 1 MiB de Flash. Utiliza SO eCos y microC/OS-II. La tabla 2.6 muestra los requisitos de memoria de un nodo SensorWare sobre HP iPAQ; no incluye el código de drivers de dispositivo, timers, etc. componente Librerías tinyTcl SensorWare Core Aplicación Total tamaño (KiB) 97 64 35 40 237 C UADRO 2.6: SensorWare: Requerimientos de memoria i i i i i i i i 58 2. A NTECEDENTES 2.5.8. MiLAN M I LAN (Middleware Linking Applications and Networks) [HMCP04] apuesta por un modelo en el que las aplicaciones tienen un papel proactivo que influye directamente en el comportamiento de la red y los nodos. Asume que las aplicaciones para SAN están dirigidas a datos (data-driven). Las aplicaciones recogen datos y estiman su calidad en función de las características de los sensores utilizados, ruido, condiciones externas momentáneas, de contexto, etc. Las aplicaciones tienen estado. Las necesidades de la aplicación cambian con el tiempo o al recibir determinados datos de los sensores. MiLAN permite a las aplicaciones especificar los necesidades de Q O S y ajustar los parámetros de la red para conseguir su objetivo. Esos parámetros se obtienen de tres fuentes: Las necesidades que las aplicaciones demandan en términos de Q O S y la especificación de alternativas para conseguirla a partir de distintos conjuntos de sensores. Para ello, las aplicaciones disponen de unos grafos especiales en los que describen cambios entre estados y los requerimientos necesarios en cada uno de ellos. La prioridad que cada aplicación tiene para el sistema en relación a las demás. La disponibilidad de recursos (sensores), la autonomía con que cuentan, su ancho de banda, etc. A partir de estos datos, MiLAN adapta continuamente los parámetros de la red para conseguir el mejor resultado global: qué sensores envían datos, cuáles tienen roles especiales o pueden encaminar su tráfico de cierta manera, etc. Su objetivo principal es maximizar la vida útil de la red SAN y de sus nodos cuando éstos están alimentados con baterías. El sistema debe saber qué sensores están activos, en qué tarea están implicados y cómo se relacionan con los demás desde el punto de vista funcional y topológico. Los diseñadores creen que el diseño de los middlewares suele considerar el uso eficiente de la red, pero no las características y propiedades de la propia red. Arguyen que actuar sobre los parámetros de la red puede mejorar la gestión de la energía de los nodos y el desempeño de las aplicaciones. También creen importante dotar al sistema de la flexibilidad suficiente como para dar soporte a requisitos de Q O S, arquitecturas y protocolos de red diferentes. Para lograr un control mucho más fino de los parámetros de la red, MiLAN actúa sobre toda la pila de protocolos de red y no solo sobre la capa de transporte (ver figura 2.5). Para ofrecer soporte para distintas tecnologías de red, incorpora una capa de abstracción. Por medio de plugins convierte las primitivas de comunicaciones propias a las de cada uno de los protocolos soportados. Dependiendo de la tecnología de red subyacente, puede actuar sobre determinadas variables específicas a fin de lograr objetivos equivalentes. Hace uso de un protocolo de descubrimiento de servicios que depende de la red subyacente, puede usar SLP (Service Location Protocol) [VGPK97, GPVD99] de IETF i i i i i i i i 2. A NTECEDENTES F IGURA 2.5: Relación de MiLAN (H EINZELMAN [HMCP04]) 59 con las capas de red inferiores. o SDP de BlueTooth. El SDP se utiliza para saber cuándo aparecen y desaparecen nodos. Cuando un nodo deja de estar disponible se asume que su batería se ha agotado. El SDP también es responsable de ofrecer información del nodo como la potencia a la que puede transmitir, la autonomía que le queda o el tipo de información que sus sensores pueden ofrecer. Plataforma Menciona su relación con las pilas de protocolos en redes BlueTooth e IEEE 802.11, pero no se especifica con qué dispositivos o plataformas se ha probado. 2.5.9. TinyCubus TinyCubus [MLM+ 05] es otro middleware diseñado sobre TinyOS. Consiste en tres partes principales: Tiny Data management Framework Proporciona un conjunto de componentes para manipulación de datos que cubren las necesidades de acceso, replicación, agregación, etc. Este componente es responsable de seleccionar la implementación adecuada en función de los requisitos del sistema. Cubus hace referencia a un modelo de tres ejes ortogonales que representan los parámetros de optimización, aplicación y sistema. Los algoritmos de cada componente están clasificados en función de su peso en estos tres ejes de modo que su importancia relativa determina su idoneidad para un objetivo o situación concreta. Tiny Cross-layer Framework Proporciona acceso a parámetros de los niveles de red inferiores para poder realizar las optimizaciones necesarias en términos de rendimiento y ahorro de energía. i i i i i i i i 60 2. A NTECEDENTES Dispone de un lenguaje de especificación para describir la información que puede generar y consumir cada componente. Para proporcionar información cross-layer, dispone de: El repositorio de estado. Para evitar que cualquier componente acceda sin control a cualquier otro componente o capa, la información se obtiene a través de un elemento intermedio (el repositorio) que permite mantener desacoplados los componentes. Enlaces o retro-llamadas. Se encargan de la asociación entre los datos y los componentes, de modo que pueden cambiar dinámicamente. Tiny Configuration Engine Es el componente encargado de instalar y distribuir código nuevo en la red de sensores, normalmente para dar soporte a nuevos tipos de sensores, funciones de agregación o requisitos de aplicación. El gestor de topología se encarga de la configuración de la red y la asignación de roles a los nodos en función de sus recursos de cómputo, situación física y relación con los nodos próximos. Algunos roles son: SOURCE, AGGREGATOR, SINK, GATEWAY, CLUSTERHEAD, VIBRATION, LIGHT, etc. La especificación de roles y el algoritmo de asignación de roles determina el rol de cada nodo individual consultando una serie de reglas descritas con el lenguaje de especificación. El algoritmo se ejecuta localmente en cada nodo. La asignación de rol determina el código que será enviado e instalado en cada nodo. Aunque la plataforma de prototipado y simulación es TinyOS/TOSSIM, los autores han tenido en cuenta en su diseño la posibilidad de integrar dispositivos con cierto grado de heterogeneidad, sobre todo, en lo referente al despliegue de código específico. 2.5.10. Impala Impala [LM03] se diseñó para cubrir las necesidades del proyecto ZebraNet [JOW+ 02, LSZM04]. El objetivo de este proyecto es buscar soluciones para la instalación de sensores en animales salvajes a fin de llevar a cabo tareas de control y observación. Los animales pueden moverse libremente por amplias zonas geográficas sin ningún tipo de infraestructura de comunicaciones. Por tanto, se caracteriza por una alta movilidad, toma continua de datos y mayor potencia de transmisión que en otros escenarios. Los objetivos del middleware se centran en la modularidad, facilidad en las actualizaciones, eficiencia en el consumo de energía y fiabilidad del software. Una de sus funciones más destacables y en la que más esfuerzo hicieron sus autores es el despliegue de código a los nodos por medio de pequeñas actualizaciones. De ese modo, se requiere poca potencia para la transmisión ayudando a mejorar la autonomía de los dispositivos y la vida útil del sistema. Las aplicaciones son muy modulares y las actualizaciones utilizan versionado y almacenamiento intermedio para que el sistema sea robusto ante actualizaciones parciales o incompatibles. La aplicación sigue funcionado mientras se recibe el nuevo código. Esto responde a un enfoque particular de su diseño i i i i i i i i 2. A NTECEDENTES 61 por el que se asume que un sistema de este tipo, incluso en explotación, sufrirá frecuentes actualizaciones para afinar su funcionamiento. Solo es posible ejecutar una aplicación en cada momento. El sistema dispone de un algoritmo y una estructura de datos (Application Device Table) que determina cuál es la siguiente aplicación a ejecutar en función de la disponibilidad de los datos requeridos o de los sensores asociados. Los nodos pueden almacenar información de forma independiente y la transmitirán hacia la estación base cuando la comunicación sea factible. En la capa inferior (ver figura 2.6) existen tres componentes importantes: Filtro de eventos Se encarga de recibir y procesar eventos procedentes de los dispositivos y enviarlos a otros módulos del sistema y a las aplicaciones. Existen cinco tipos de eventos: de tiempo – Indican que expiró un temporizador. Hay tres tipos de eventos: para la aplicación activa, el adaptador de aplicaciones y el actualizador de aplicaciones. de paquete – Indica que ha llegado un mensaje. Hay dos tipos: de aplicación a aplicación y de actualizador a actualizador. de datos – Indica a la aplicación activa que existe un sensor listo para ser leído. de dispositivo – Indica al adaptador de aplicaciones que se ha detectado un fallo en un dispositivo. envío completado – Indica que se ha completado el envío de un mensaje. El adaptador de aplicaciones Los nodos pueden utilizar distintas aplicaciones para encaminar datos a la estación base, dependiendo de condicionantes como el rendimiento, el ahorro de energía u otros factores. La adaptación está soportada por el modelo de programación de eventos de Impala. La adaptación ocurre como respuesta a los distintos tipos de eventos. El actualizador de aplicaciones Las actualizaciones en Impala tienen algunas peculiaridades: alta movilidad de los nodos, bajo ancho de banda que se debe compartir con la transmisión de datos de los sensores y actualizaciones de distinta consideración, desde parches a cambios completos en las aplicaciones. Debido a ello, las actualizaciones deben afrontar varios problemas: actualizaciones parciales debido a cortes en las comunicaciones, procesos de ejecución y actualización simultánea, actualizaciones procedentes de varios orígenes y gestión de la memoria, cada nodo puede contener código de cuatro aplicaciones a la vez. Los módulos tienen un número de versión asignado. Solo se transmite un módulo cuando el receptor confirma que la versión instalada es más antigua. Aunque se despliegan como binarios, el actualizador es el encargado de enlazar los módulos a la aplicación. No se permiten las dependencias entre éstos. Cuando se dispone de todos los módulos, el nodo procede a su enlace en la aplicación. i i i i i i i i 62 2. A NTECEDENTES F IGURA 2.6: Arquitectura de capas de Impala. (Ting L IU [LSZM04]) Plataforma Los módulos Application Adapter y Application Updater se ejecutan en una PDA HP iPAQ con CPU a 266 MHz, 32 MB de RAM y 16 MB de Flash para el sistema de ficheros. Utilizan el sistema operativo Linux Familiar 5.2. Los módulos Operation Scheduler, Event Filter y Network support se ejecutan en nodos ZebraNet (ver figura 2.7). Este dispositivo dispone de un microcontrolador TI MSP430F149 RISC de 16 bits con 2 KiB de RAM y 60 KiB de ROM, con un reloj dual de 8 MHz/32 KHz. Para las comunicaciones utiliza un módulo de radio MaxStream 9Xstream a 902928MHz que permite una tasa 19,2Kbps en campo abierto con un alcance de entre media y una milla. Para el almacenamiento de datos en modo desconectado utiliza una memoria Flash ATMEL AT45DB041B de 4 MiB, que le permite almacenar datos durante 78 días. Para la localización utiliza un GPS µblox GPS-MS1E. Los cuatro módulos se comunican mediante un bus SPI a 667 Kbps y USART a 38,4 Kbps. Los requisitos de memoria para la aplicación prototipada se muestran en la tabla 2.7. Como prototipo se hizo un despliegue montando nodos zebranet en collares que se colocaron a 7 cebras que vivían en libertad en una reserva natural de Kenia durante enero de 2004. Se trata de un middleware confiable y con un sistema de actualizaciones eficiente desde el punto de vista energético. Sin embargo, es una solución muy especializada que no contempla aspectos generales de la problemática de las WSN como, por ejemplo, la i i i i i i i i 2. A NTECEDENTES 63 componente tamaño firmware Impala Aplicación RAM 10 KiB 7 KiB 1 KiB 650 B C UADRO 2.7: Impala: Requerimientos de memoria (a) (b) F IGURA 2.7: Diagrama de bloques (a) y aspecto físico (b) del nodo ZebraNet. (Ting L IU [LSZM04]) limitación de ejecutar una única aplicación. Difícilmente es aplicable o portable a otros entornos, plataformas o aplicaciones fuera del ámbito de estudio. 2.5.11. TinyLime TinyLime [CGG+ 05] al igual que los sistemas de base de datos virtual, dispone de un lenguaje de consulta, pero su modelo de datos es un espacio de tuplas [Gel85] que funciona como una especie de memoria compartida. Una tupla es una lista de valores que puede ser creada o accedida por las aplicaciones. TinyLime es un trabajo derivado de LIME (Linda in Mobile Environments). Las tuplas las almacena temporalmente cada nodo de la red y pueden ser consultadas por sus vecinos. Por tanto, la información es generada y consultada de forma asíncrona puesto que no se requiere que dichas operaciones ocurran en el mismo momento y lugar. El mecanismo de suscripción de las aplicaciones depende de plantillas que especifican cuáles son los datos de interés. Estas plantillas deben tener el mismo formato que utilizan las tuplas de los sensores y pueden incluir condicionantes de dicha suscripción, tales como la frecuencia de actualización. i i i i i i i i 64 2. A NTECEDENTES Para que la información esté disponible para las aplicaciones del exterior, se representa cada sensor de la red por medio de un agente LIME alojado en la pasarela. Ese agente se encarga de recoger información procedente del sensor y representarla en el espacio de tuplas. Funciona sobre TinyOS en la plataforma de sensores Crossbow Mote. La implementación aporta por defecto la especificación del formato de tuplas para los sensores habituales en dicha plataforma. 2.5.12. EnviroTrack EnviroTrack [Abd04] es un middleware distribuido basado en objetos que persigue dos objetivos principales: la gestión eficiente de grupos por medio de objetos lógicos, y el seguimiento (tracking) de entidades del entorno físico. El tracked object es una abstracción que se puede instanciar dinámicamente y que permite obtener datos relativos a un fenómeno u objeto físico, tal como un vehículo o un incendio. El middleware se encarga de recoger toda la información relativa al fenómeno físico y presentarla al programador de la aplicación por medio de una interfaz única, aunque provenga de varios sensores o se mueva a través de la red. Eso significa que, dinámicamente, se crean grupos de sensores en torno a los fenómenos observados. EnviroTrack se basa en un concepto llamada estado agregado aproximado (approximate aggregate state). Se trata de una función que permite obtener un dato como resultado de la agregación del estado de los sensores que forman un grupo (por ejemplo, la media). La peculiaridad es que el grupo se define automáticamente por aquellos nodos que satisfacen un predicado dado (p.ej. umbral de temperatura) en un instante t. Como esta información no puede ser calculada y transmitida de forma instantánea, se define una ventana de tiempo para realizar la agregación. Por último, se precisa un número mínimo de sensores (masa crítica) para que el fenómeno sea tomado en consideración. Por ejemplo, se considera que existe fuego si al menos 5 sensores detectan alta temperatura en un plazo de 3 segundos en la misma zona. Estos condicionantes son considerados restricciones de Q O S en la detección de fuego. Por último, una abstracción denominada etiqueta de contexto (context label) realiza el seguimiento sobre la entidad del entorno y mantiene el valor agregado. La etiqueta de contexto es un sistema de direccionamiento de nodos basado en atributos similar al de otros desarrollos; sin embargo, en este caso es posible asociar objetos (tracking objects) que pueden realizar trabajos sobre el contexto (los nodos relacionados con el fenómeno). Plataforma El entorno de programación de EnviroTrack está formado por cuatro elementos: Un preprocesador que transforma declaraciones EnviroTrack en código nesC que se encarga de materializar la gestión de grupos, la agregación de datos y las comunicaciones. Un protocolo de gestión de grupos que utiliza las etiquetas de contexto para tomar las decisiones de membresía. i i i i i i i i 2. A NTECEDENTES 65 Servicios de directorio y direccionamiento de objetos, que mantiene una lista de objetos activos y su posición. El servicio de transporte y comunicación por medio de RMI. El sistema se ha probado con motas MICA2 utilizando TinyOS. No se facilitan datos precisos sobre los recursos de cómputo necesarios, cuáles de los componentes citados se alojan en las motas y cuáles fuera, dónde se ejecutan las aplicaciones o cómo se comunican con la WSN. 2.5.13. Kairos Kairos [GGG05] es un ejemplo claro de macro-programación. Su objetivo es dar al programador la capacidad de expresar el comportamiento global de toda una red de sensores proporcionando un único programa con instrucciones de alto nivel. Ese programa se compila, generando código específico que se distribuye después a cada nodo. Todo ese proceso es transparente al programador. Para ello ofrece un lenguaje con las siguientes abstracciones: El nodo permite al programador hacer referencia a un nodo o conjunto de ellos. Los nodos se direccionan utilizando números enteros como identificadores. El vecino es un nodo directamente alcanzable desde otro dado. Como en otros middlewares, es posible obtener la lista de vecinos e iterar sobre ellos para realizar operaciones relacionadas con el encaminamiento y la topología. El acceso remoto a datos permite acceder remotamente al valor de cualquier variable del nodo, siempre que tenga sentido fuera de él. Los nodos mantienen copias en caché de las variables remotas por lo que se hace necesario un mecanismo de sincronización. No es posible modificar variables remotas, por lo que no se plantean problemas de acceso concurrente. Kairos asume que las aplicaciones pueden funcionar adecuadamente empleando un sistema de sincronización débil (loose). Significa que la lectura de una variable remota se bloquea únicamente cuando se obtiene la referencia y no en cada lectura de la variable. Así se consigue menor sobrecarga de comunicaciones aunque puedan aparecer inconsistencias entre los valores reales de las variables y sus cachés. En los casos en que este tipo de inconsistencia sea intolerable, Kairos proporciona una sincronización más estricta (loop-level) entre las variables en cada iteración del bucle en lugar de utilizar sólo el valor almacenado localmente. Aunque no se aportan datos sobre los requerimientos de cómputo de Kairos, a la vista de los prototipos utilizados, parece claro que no es viable su instalación en los dispositivos de la SAN propiamente dichos. Plataforma Los autores describen una plataforma de evaluación consistente en una red híbrida formada por 16 Stargate’s que ejecutan Kairos. i i i i i i i i 66 2. A NTECEDENTES Stargate [Sta] es un dispositivo de la empresa Crossbow. Cuenta con un procesador Intel PXA255 (XScale) y 64 MiB de RAM. Ejecuta una versión empotrada de Linux y se puede conectar a varios modelos de motas como IRIS, MICAz, etc., y otros periféricos. Kairos utiliza Emstar [GES+ 04] para implementar el encaminamiento y la gestión de la topología. Emstar usa una mota MICA2 conectada al Stargate como interfaz de red. Las motas ejecutan TinyOS. Es decir, cada nodo es una combinación de una mota MICA2 conectada a un Stargate (ver figura 2.8), que ejecuta Linux con Emstar y Kairos. F IGURA 2.8: Combinación de Stargate y mota MICA2 usada en un prototipo de Kairos Otro despliegue utiliza 8 MICA2DOT conectadas por un puerto serie a un PC estándar que ejecuta un proceso Emstar y un proceso Kairos para cada una. 2.5.14. WSP Otra propuesta bastante reciente [BLV09], relacionada con el proyecto WASP (Wirelessly Accessible Sensor Populations) [WAS], pretende desarrollar un modelo de programación para WSN heterogéneas utilizando un enfoque basado en eventos. Se trata de mensajes auto-contenidos, que incluyen una función global y una lista de argumentos. Se trata de una propuesta similar a SensorScheme [EHK+ 07] o Active Messages [VECGS92]. Cada tipo de mensaje tiene un manejador asociado y su procesamiento no requiere de nuevas comunicaciones. Los mensajes incluyen campos con información de Q O S tales como prioridad, plazo, fiabilidad requerida, etc. Todos los mensajes incluyen además un identificador de aplicación para agrupar manejadores y gestionar la versión del protocolo. El objetivo de estos mensajes es doble: aplicar optimizaciones cross-layer, y adaptar la complejidad y tamaño del mensaje a las necesidades concretas. Los mensajes se pueden encapsular en cualquier capa que permita transporte de mensajes aunque la preferencia es utilizar la capa más baja posible. En las implementaciones se encapsula sobre IEEE802.15.4. i i i i i i i i 2. A NTECEDENTES 67 Cada nodo de la red expone una serie de servicios. Cada uno de ellos contiene un conjunto de generadores de eventos, manejadores y suscripciones. La figura 2.9 muestra el diagrama de bloques de un nodo, en el que se representan las relaciones entre los elementos citados. F IGURA 2.9: Estructura de un nodo WSP. (Remi B OSMAN [BLV09]) La aplicación determina los servicios y las suscripciones. Desde la perspectiva de un nodo, una suscripción es una conexión lógica entre un evento local y un manejador remoto. Los generadores de eventos son tuplas condición-acción de modo que se envía un mensaje cuando se produce una condición dada. Las funciones de un servicio se ejecutan en un contexto dado. Se definen cuatro contextos: Gcontext – Es una lista de todas las variables y contantes disponibles globalmente. Incluye primitivas del SO como, por ejemplo, la lectura de sensores. Ncontext – Variables locales al servicio. Mcontext – Manejadores del servicio. Scontext – La información proporcionada por un suscriptor para los generadores de eventos. Por ejemplo, umbrales para el disparo de eventos. Utiliza Content-Based Addresses (CBA) con dos propósitos: establecer servicios en los nodos y para la suscripción de manejadores a generadores de eventos. Una CBA es una expresión que puede ser evaluada por el nodo remoto. Cuando se solicita una suscripción se especifica una de estas expresiones y un conjunto de características de Q O S. El establecimiento de servicios se realiza por medio de un mensaje especial cuyos argumentos son instrucciones de una pequeña máquina virtual (de 6 instrucciones). Este lenguaje se usa para definir CBA S, declarar variables en el Gcontext y definir manejadores y generadores de eventos en el nodo. Se trata de un sistema de macro-programación que genera bytecode para una máquina virtual (basada en pila) que se ejecuta en cada nodo. El lenguaje de macro-programación i i i i i i i i 68 2. A NTECEDENTES (llamado Network Programming Language) intenta reducir el salto de abstracción que hay entre la descripción del escenario y el código que se ejecuta realmente en los nodos. El conjunto de standard handlers es la definición de la interfaz remota del nodo, de modo que los servicios del nodo quedan determinados por diseño. Tiene manejadores específicos para el establecer rutas, encaminar mensajes, pedir suscripciones, fijar la potencia de transmisión, encender/apagar LED S, etc., hasta un total de 27 funciones; todo ello sin una diferenciación conceptual o definición de roles. Define abstracciones que tienen claros equivalentes en la OO y que podrían ser empleados o adaptados para representar los mismos conceptos y restricciones, con la consiguiente simplificación en la especificación y nomenclatura. Plataforma No se aporta información sobre un despliegue en dispositivos físicos, aunque sí aparece una tabla con los requisitos de memoria de la implementación de la máquina virtual (ver 2.8). componente SO VM Llamadas al sistema Total ROM (bytes) RAM (bytes) 24 084 1 664 1 530 27 278 1 191 20 146 1 357 C UADRO 2.8: WSP: Requerimientos de memoria 2.5.15. C OPRA C OPRA [KN06] (parte del proyecto C OCOS) no es un middleware como los anteriores. Se trata de una arquitectura para el diseño e implementación de protocolos de comunicaciones para dispositivos de escasos recursos. Plantea como principio de diseño que utilizar un protocolo o middleware genérico para una red SAN siempre resulta ineficiente, dado que al no estar optimizados para hardware específico, supone un gasto de recursos innecesario. Otro problema añadido es que al utilizar transductores de radio muy simples, la CPU debe encargarse de tareas como el control de acceso al medio o el direccionamiento, que normalmente haría la interfaz de red [KKKP99]. C OPRA define una biblioteca de PPS (Protocol Precessing Engines), que son componentes simples que pueden ser ensamblados para crear protocolos de comunicaciones dependientes de aplicación llamados Protocol Processing Stagess (PPE S), curiosamente se trata de una solución prácticamente opuesta al principio de W HITE [Whi75]. El PPE es una cadena de PPS u otros PPE en el que cada uno de ellos tiene un puntero al siguiente, de modo que los datos procedentes del dispositivo de radio o la aplicación atraviesan toda la cadena. Utilizar una cadena de invocaciones explícitas a través de la cadena implica copiar el mensaje con el consiguiente gasto en tiempo y memoria. i i i i i i i i 2. A NTECEDENTES 69 Por ejemplo, I MPACT [BKN07] es un protocolo muy interesante construido sobre C OPRA. I MPACT aprovecha los enlaces inalámbricos característicos de las WSN para evitar enviar reconocimientos. Cuando un nodo reenvía un mensaje hacia su destino, el nodo anterior también lo recibe, de ese modo puede comprobar que el mensaje le llegó correctamente haciendo innecesario un mensaje de reconocimiento explícito y ahorrando así una importante cantidad de energía. Prevé casos especiales en los que sí hay que enviar ese reconocimiento, por ejemplo en los enlaces asimétricos (unidireccionales) o en el caso del nodo destino, que no reenvía el mensaje a nadie. 2.6. Encaminamiento en redes heterogéneas La interconexión de redes heterogéneas (de diferente tecnología) es la esencia misma de cualquier protocolo de red, pero existen otras soluciones, parciales quizá, al mismo problema. El objetivo de una inter-red es poder intercambiar datos —en los niveles superiores— entre hosts que disponen de interfaces de comunicaciones incompatibles o que requieren la utilización de una o varias redes intermedias debido a la distancia física que las separa. Aunque es posible tratar el problema de la interconexión desde un punto de vista generalista, en esta sección se trata dentro del contexto que nos ocupa, es decir, conectar redes de sensores entre sí y a la infraestructura de comunicaciones del SI, y potencialmente a Internet. En la línea de lo que apunta S ENNER [SKLN08], la interconexión de redes heterogéneas se puede lograr de cuatro maneras diferentes, que se detallan a continuación. 2.6.1. Protocolo de red universal Se trata de un único protocolo que deben adoptar obligatoriamente todos los nodos de todas las redes que se pretende comunicar entre sí. Esta solución implica también la definición de un sistema de direccionamiento universal que garantice que cada nodo de la red tiene una dirección única. Se trata, por supuesto, de la solución adoptada en Internet gracias a IP. Entre las muchas ventajas de esta solución, existe la de poder establecer islas que pueden tener incluso sus propios protocolos de encaminamiento dinámico (llamadas Sistema Autónomo (SA) en la terminología de TCP/IP). Dado que es muy probable que en algún momento se necesite conectar cualquier red imaginable a Internet, la solución obvia parece que es utilizar IP en absolutamente cualquier dispositivo. Propuestas como uIP [DAV04] van en esta línea. Emplear un protocolo de red idéntico en todos los nodos simplifica significativamente el proceso de encaminamiento y reenvío de paquetes. Los encaminadores realizan la misma tarea y con los mismos condicionantes en cualquier parte de la inter-red. No tienen estado y no necesitan modificar los paquetes transmitidos, a excepción de campos de control sencillos como el caso del TTL. Otra cuestión es el protocolo de encaminamiento dinámico que puede ser muy distinto dependiendo del ámbito, como ocurre por ejemplo en las Mobile Ad-hoc Network (MANET). i i i i i i i i 70 2. A NTECEDENTES Sin embargo, IP no se adapta bien a muchas particularidades específicas de ciertas redes o dispositivos (como es el caso de las WSN), no solo por los requisitos de cómputo necesarios, también por la necesidad de protocolos de transporte que por diseño resultan inadecuados. Por ejemplo, en un enlace inalámbrico, lo habitual es introducir información redundante que permita recuperar los datos que se pierden debido a los frecuentes errores. Por el contrario, TCP reacciona reduciendo la tasa de salida asumiendo que es un problema de congestión [HV99]. Otros problemas están relacionados con las grandes diferencias en la MTU, uno de los problemas que trata de resolver 6L OWPAN [MKHC07, KMS07]. Para lograr un desempeño aceptable de TCP/IP en nodos limitados habitualmente son necesarias adaptaciones como compresión de cabeceras [Dun03], modificaciones en la encapsulación de los paquetes, direccionamiento, etc. Este tipo de «optimizaciones» implican cambios en el formato de las cabeceras que es precisamente una de las consecuencias que se pretendía evitar utilizando un protocolo de red homogéneo. Respetar el protocolo que el fabricante utiliza en sus nodos puede tener ventajas que no resultan compensadas al intentar aplicar TCP/IP sobre ellos, además de simplificar su uso puesto que podemos contar con las herramientas que proporciona el fabricante. Además, existe una gran cantidad de trabajo [AY05, CSAT06] en relación al encaminamiento para redes WSN con propuestas que tratan de mejorar el consumo energético, utilizando información geográfica, creando un árbol basado en clusters o presuponiendo la existencia de enlaces unidireccionales. Algunos de esos protocolos utilizan atajos (cross-layer) o tienen un diseño tan peculiar como SPIN [HKB99] o Directed Diffusion [IGE00] que utiliza un encaminamiento orientado a datos, es decir, los sensores no tienen direcciones únicas. Estos modelos plantean serias dificultades si se pretende adaptarlos a los parámetros clásicos de los protocolos de encaminamiento que se emplean en IP. Encaminamiento de mensajes en CORBA Los mismos problemas que se pretende resolver con un direccionamiento y un protocolo de red común pueden ser atacados a otro nivel. CORBA y, en general cualquier middleware orientado a objetos, dispone de alguna entidad lógica para direccionar unívocamente cualquier objeto dentro del sistema distribuido, ya sea de forma directa o indirecta. Como vimos en la sección 2.3.3, la referencia al objeto (IOR) incluye la información necesaria para contactar con el adaptador que sirve el objeto destino. La referencia está compuesta de perfiles etiquetados; toda IOR tiene al menos uno. Existe un gran número de perfiles de IOR predefinidos. Entre ellos, el más común es TAG_INTERNET_IOP que corresponde con referencias que se resuelven por medio de IIOP. Uno de ellos resulta especialmente interesante para el tema que nos ocupa. Se trata de TAG_MESSAGE_ROUTERS, lo que nos lleva al capítulo «CORBA Messaging» [Obj08b] de la especificación y concretamente a la sección titulada «Message Routing Interoperability». Tanto AMI como la entrega de invocaciones no dependientes del tiempo, es decir, aquellas que pueden llegar a entregarse aunque el destino no estuviera disponible en el momento de producirse la invocación, no pueden ser efectuadas con una comunicación GIOP síncrona. i i i i i i i i 2. A NTECEDENTES 71 Este tipo de invocaciones (y sus respuestas) son reenviadas a través de una serie de agentes (o encaminadores) hasta alcanzar su destino. El último encaminador (el más cercano al servidor, en términos de coste) efectúa la invocación como si fuera el cliente, recoge la respuesta y la envía de vuelta al cliente como una nueva invocación empleando la referencia de un objeto callback. Dicho objeto debe implementar la interfaz ReplyHandler y lo puede aportar el cliente o, en su defecto, el primer encaminador (el situado más cerca del cliente). El proceso de una invocación completa se ilustra en la figura 2.10. F IGURA 2.10: Encaminamiento de mensajes CORBA [Obj08b] La principal utilidad de este sistema de encaminamiento es permitir que los servidores puedan especificar otros destinos alternativos cuando el nodo final pueda no estar disponible durante largos períodos de tiempo. Esos destinos alternativos son encaminadores. El objeto especifica la lista de referencias a esos encaminadores como un componente de su propia IOR. El identificador de ese perfil es TAG_MESSAGE_ROUTERS, al que nos referíamos anteriormente. La tarea del encaminador consiste en reenviar la invocación al siguiente que aparece en la lista o, si le es posible, efectuar la invocación sobre el servidor. El mensaje que se reenvía a través de los encaminadores contiene una invocación estándar para el objeto destino además de la información necesaria para el proceso de encaminamiento, que incluye: La lista de encaminadores visitados. La lista de encaminadores por visitar (los que aparecen en la IOR del objeto destino). La referencia al objeto destino. La referencia al objeto que ha de recibir la respuesta. Una secuencia de descriptores de Q O S. El propio encaminador es también un objeto CORBA; estos mensajes se codifican usando GIOP y se envían como parámetros de las operaciones de la interfaz implementada por el encaminador (MessageRouting::Router). Cada encaminador reenvía el mensaje al siguiente utilizando esa misma interfaz, o bien al objeto destino si está accesible. i i i i i i i i 72 2. A NTECEDENTES Aunque se han indicado varios roles para los encaminadores (primero, último e intermedios), realmente un mismo proceso puede implementar varios de ellos, y es posible incluso que el cliente o el objeto destino dispongan de encaminadores co-localizados. Cuando el cliente no puede invocar directamente al objeto destino, por no estar accesible mediante un protocolo síncrono, el ORB cliente intenta contactar con el primer encaminador. Si la IOR del objeto destino tiene un componente TAG_MESSAGE_ROUTERS, el ORB utiliza las referencias de la lista que contiene, empezando por la última, que debe ser la más cercana al objeto destino. Si no puede contactar con ninguno de los encaminadores de la lista, o la IOR destino no tiene dicho componente, el ORB cliente utiliza el encaminador por defecto más cercano al destino. El cliente puede decidir entre dos alternativas para realizar la invocación sobre el primer encaminador: Modelo de objeto callback – El cliente crea y sirve un objeto que implementa la interfaz ReplyHandler y le pasa la referencia al primer encaminador. Esta referencia será utilizada por el último encaminador para enviar la respuesta de la invocación como otra invocación a ese objeto. Modelo polling – En este caso no es el cliente, es el primer encaminador el que crea el objeto para recepción de la respuesta. Lo hace a petición del cliente a través de su interfaz PersistentRequestRouter mediante la operación create_persistent_request que le devuelve una referencia al objeto alojado en el primer encaminador. Posteriormente, el cliente puede invocar las operaciones get_reply() o get_reply_with_context() para averiguar si la respuesta está disponible y obtener el resultado cuando suceda. La especificación incluye una interfaz para interacción entre encaminadores (RouterAdmin) para evitar tráfico de red innecesario. Cuando un encaminador es contactado por otro que no conoce, se registra en él y le da instrucciones que debe usar si en el futuro no puede contactarle. Esta información dice durante cuánto tiempo puede seguir intentando contactar antes de declararlo inactivo, el intervalo de tiempo entre reintentos, la progresión con la que crece ese intervalo, su valor máximo, etc. Cada encaminador dispone de una lista en la que aparecen otros encaminadores registrados de este modo y si están activos o no. Si un encaminador recibe mensajes que solo pueden ser entregados a través de otro inactivo, puede almacenarlos y esperar a que vuelva a estar activo. Así se consigue un sistema de transporte de mensajes con características típicas de una Delay Tolerant Network (DTN). Aunque se trata de un sistema de encaminamiento de invocaciones muy potente, su uso está orientado a un problema bastante particular: la imposibilidad de realizar una comunicación síncrona entre cliente y objeto destino. La selección de rutas se basa en información contenida en las referencias almacenadas en los propios mensajes, no hay tablas de encaminamiento. No proporciona mecanismos para descubrimiento de rutas o vecinos ni ningún otro equivalente funcional a un protocolo de encaminamiento dinámico. La lista de encaminadores que aparece en la referencia del objeto es una forma de aumentar las posibilidades de recibir mensajes, nombrando otros objetos (los i i i i i i i i 2. A NTECEDENTES 73 encaminadores) que pueden redirigírselos. Tampoco prevé transporte de invocaciones multi-destino ni esquemas de direccionamiento adecuados para ello. 2.6.2. Pasarelas La principal ventaja de usar pasarelas9 es que permite que cada red tenga su propio esquema de direccionamiento, delegando en ellas la traducción de protocolos. Ésta puede ser una solución aceptable cuando hay muy pocos sistemas distintos y para una aplicación acotada. Aun así la ausencia de un esquema de direcciones global implica importantes problemas que se comentan a continuación. Direccionar nodos de una red desde otra diferente implica conocer los esquemas de direccionamiento ajenos. Como lo anterior resulta prácticamente inviable, en la mayoría de los casos se opta por instalar delegados (representantes) de cada nodo en las pasarelas para la conversión de direcciones. Esto es lo habitual en las redes SAN por medio de las llamadas estaciones base. El problema es que estos delegados suelen funcionar sólo en un sentido. Se puede acceder a los nodos de la SAN desde la red troncal pero no a la inversa. Los clientes realizan peticiones sobre la pasarela utilizando un protocolo como TCP/IP. El software presente en la pasarela se ocupa de hacer llegar la petición hasta el nodo y recoger la respuesta utilizando el protocolo específico de la red en cuestión (ver figura 2.11). La conversión de direcciones requiere disponer de un sistema de equivalencia uno a uno entre ambos esquemas de direccionamiento o bien que la pasarela conozca, bien de antemano bien dinámicamente, las direcciones de los nodos de la SAN. Resulta difícil comunicar dos redes distantes iguales a través de una diferente debido a que todas las redes que utilizan el mismo esquema de direccionamiento deben estar coordinadas para evitar conflictos; se hace necesario un sistema de encaminamiento que permita saber a qué red se debe enviar cada mensaje normalmente utilizando técnicas de tunneling. Resulta especialmente complicado instalar varias pasarelas en una misma red dado que todas deberían tener una copia de todos los delegados con el consiguiente problema de coordinación que plantea. Pueden surgir problemas de ambigüedad en la semántica de acceso o bucles en la entrega de mensajes. Utilizar sólo una pasarela supone admitir un único punto de fallo, y Cuando se emplean protocolos ad hoc en redes inalámbricas ocurre que los nodos cercanos a la pasarela consumirán mucha más energía que los demás dado que deben encaminar los mensajes de toda la red. La consecuencia es que una vez agotada la energía de estos nodos, la red queda incomunicada y potencialmente inservible. Existen algunos trabajos que tratan de evitar estos problemas [PH08]. Las pasarelas son elementos explícitos del sistema. Con frecuencia el programador debe ser consciente de la existencia de la pasarela. Para solicitar un servicio a un 9 Denominadas habitualmente sink en la bibliografía sobre SAN. i i i i i i i i 74 2. A NTECEDENTES nodo de la SAN debe indicar la dirección de la pasarela en lugar de la dirección o identificador del sensor que realmente le interesa. Esto contrasta fuertemente con los encaminadores de la alternativa anterior, que normalmente son transparentes para las aplicaciones. Pérdida de autonomía. Los nodos de la red SAN no pueden interactuar directamente con elementos externos y por eso resulta complicado que puedan ofrecer y, sobre todo, demandar servicios a dispositivos que están en una red SAN diferente. F IGURA 2.11: Red SAN con una pasarela explícita A pesar de todos esos problemas, estas pasarelas inteligentes (smart gateways) son la principal solución de conectividad para la aplastante mayoría de middlewares y protocolos de comunicaciones para redes de dispositivos de todo tipo, incluyendo sistemas domóticos, entornos inteligentes, de control de procesos, etc. Las razones para adoptar esta solución a pesar de los inconvenientes tienen mucho que ver con la reducción de complejidad que supone para los nodos sensores. En los middlewares de redes de sensores orientados a base de datos [SJS01, LLS+ 03, MFHH05, YG02, BHSS07], el procesamiento de las consultas suele hacerse en la pasarela mientras que la recolección de información suele tener poco que ver con la forma en la que se presentan los datos al cliente. A veces, la consulta no se produce de forma síncrona; se ofrecen datos recopilados durante instantes previos que se encuentran almacenados en la pasarela. En ocasiones, servicios o módulos importantes del middleware residen en la pasarela como Impala [LM03] o Kairos [GGG05]. También es el caso de STI [Obj03], en el que la pasarela se encarga de que un conjunto de dispositivos simples sean vistos desde la red como si fuesen objetos distribuidos, aunque las comunicaciones entre la pasarela y dichos dispositivos utilizan un protocolo mucho más simple. Arquitectura de interoperabilidad de CORBA El problema de la integración de redes también se da a nivel del middleware. En esta situación, se suele hablar de dominios, un concepto más general que además de las incompatibilidades debidas a protocolos o tecnologías de red pueden deberse a aspectos de más alto nivel como seguridad, cifrado, políticas administrativas, etc. La «ORB Interoperability Architecture» [Obj08a] de la especificación CORBA trata en detalle todos los aspectos relacionados con el transporte de mensajes entre dominios. i i i i i i i i 2. A NTECEDENTES 75 La correspondencia (mapping) se basa en el uso de puentes (bridges) en un sentido amplio10 . Se exponen dos posibles enfoques: Mediated bridging – La transformación entre elementos de ambos dominios se realiza a una tercera forma común. Esa forma no tiene porqué ser universal, puede depender del sistema para así conseguir una solución óptima. Immediate bridging – La transformación se realiza desde el dominio origen directamente al formato del dominio destino. Es una solución más eficiente que la anterior, pero menos general y flexible. Uno de los aspectos más interesantes es el direccionamiento, que en el caso de CORBA se aplica a los objetos (mediante las referencias). Cada perfil de una referencia a objeto (la IOR) identifica uno o más protocolos y los detalles para conectar con un adaptador remoto, eso incluye la dirección de red del host, puertos, etc. Es posible que el direccionamiento utilizado en un dominio no sea aplicable en otros, por lo que es necesario realizar algún tipo de transformación. Nótese que las referencias a objetos no solo se utilizan para dirigir un mensaje hacia su destino. Se pueden obtener en los parámetros de retorno de una operación, como ocurre con el servicio de nombres. También se utilizan habitualmente para enviar object callbacks de modo que el destinatario disponga de una referencia al objeto responsable del mensaje original o un tercero. Es decir, la transformación de referencias afecta al contenido de la invocación además de a su cabecera. La sección «Object addressing» explica diferentes esquemas posibles para traducir referencias a objetos en los puentes. Object Reference Translation Reference Embedding – El puente almacena la referencia recibida y genera otra completamente nueva que identifica el objeto en el otro dominio. El puente se encarga de gestionar las referencias almacenadas de modo que para cada referencia «puenteada» se pueda referenciar el objeto en el dominio original. Reference Encapsulation – El puente no almacena estado. Lo que hace es concatenar un identificador del nuevo dominio en el nombre del objeto. En una invocación, se asume que la referencia ya dispone de un identificador encapsulado en el dominio destino y, en ese caso, el puente elimina el identificador del dominio origen. Domain Reference Translation – El estado almacenado en el puente (un identificador de la ruta basado en el dominio) puede ser compartido por varias referencias. En cada una de ellas se incluye únicamente ese identificador. Reference Canonicalization – Es similar al anterior, pero utiliza identificadores de dominio globales en lugar de codificar una ruta. Cada alternativa presenta ventajas e inconvenientes. Un problema importante que afecta a la escalabilidad es la necesidad de almacenar estado en los puentes, ya sean 10 Se respeta aquí el término «puente» sobre «pasarela» utilizado en el resto del texto. i i i i i i i i 76 2. A NTECEDENTES referencias a los objetos en el dominio origen o identificadores con la ruta al dominio de partida. Cuando se encapsulan referencias o se añade información extra al atravesar un puente puede ocurrir que los mensajes crezcan dado que las referencias pueden tener tamaños realmente considerables. Este tipo de interconexión de dominios no está basado en la decisión o cálculo de rutas ni media ningún tipo de algoritmo de encaminamiento. Es un mecanismo para interconectar ad hoc dominios distintos dependientes de una entidad administrativa común. Es decir, no está diseñado como un método flexible y escalable para interconexión ocasional de dominios sino como una solución permanente para un conjunto concreto y estudiado de subsistemas. Agimone Un caso un tanto especial es Agimone [HFRL06], un middleware que proporciona movilidad para agentes entre distintas WSN usando redes IP (principalmente Internet) como mecanismo intermedio. Los agentes de la WSN están implementados sobre el middleware Agilla [FRL05]. Para poder ser transportados a través de Internet requieren una adaptación como agentes para el middleware Limone [FRH04]. Es decir, Agimone es una capa adicional para proporcionar interacción entre dos middlewares de agentes existentes: Agilla (específico de la WSN) y Limone (específico de la red IP). Se asume que cada WSN está conectada a Internet a través un PC o Stargate [Sta] que actúa como pasarela, aloja una instancia de Limone y se encarga del proceso de adaptación. 2.6.3. Protocolos híbridos Se trata de un intento por resolver parte de los problemas que causan las pasarelas. Consiste en diseñar un protocolo que puede funcionar en modo dual de manera que se pueda utilizar para acceder a nodos de al menos dos redes diferentes. La necesidad de eliminar la pasarela se debe a que ambas redes deben poder interconectarse sin absolutamente ninguna infraestructura. S ENNER [SKLN08] propone una solución para el clásico escenario de los bomberos. Utiliza un esquema de direccionamiento en el que se reserva 1 bit para indicar a qué tipo de red se refiere el resto de la dirección. Nótese que no se trata de un prefijo de subred sino un código que identifica la tecnología de la red. Se supone la existencia de una red de sensores (desplegados por los propios bomberos) y otra formada por las PDA S que llevan consigo. La red de PDA S es obviamente móvil y utiliza encaminamiento ad hoc (una MANET), mientras que la red SAN se considera fija. Ambas redes deben interconectarse por medio de cualquier par PDA-sensor dado que las PDA S van equipadas con una interfaz W I F I y una de radio del mismo tipo que utiliza la SAN. La consecuencia es que cualquier PDA puede actuar como puente entre ambas redes. Debido a las limitaciones de energía, la SAN solo transporta mensajes producidos por los nodos sensores, pero en circunstancias excepcionales es posible encaminar mensajes procedentes de una PDA y dirigidos a otra, por ejemplo si se produce la orden de abandonar un edificio cuyo colapso es inminente. Este trabajo propone eliminar IP también en la red de PDA y encapsular los datos directamente sobre el protocolo de enlace. El nuevo esquema de direccionamiento está dividido entre identidades para los sensores y para las PDA S de la i i i i i i i i 2. A NTECEDENTES 77 MANET. Utiliza 1 bit para indicar si el mensaje debe propagarse a ambas redes o solo a una, otro para indicar la red a la que corresponde y 6 bits más para direccionar el nodo. Es decir, puede haber un máximo de 63 nodos sensores y 63 PDA S en total. Los nodos utilizados en los experimentos son TMote Sky, que cuentan con 10 KiB de RAM y 48 KiB de ROM. Se trata, por tanto, de una solución diseñada ex profeso para un despliegue particular. Las limitaciones a 2 redes con 63 nodos por red son inaceptables para plantear una solución general y es fácil comprobar que el mismo planteamiento no escala bien a cualquier número de redes o nodos. El protocolo concreto es específico de la aplicación y se ha creado a partir de la arquitectura C OPRA (véase § 2.5.15). No se dan detalles sobre sus características o prestaciones aunque sí se ofrecen datos sobre su desempeño en simulaciones utilizando una versión modificada de AODV (Ad hoc On-Demand Distance Vector) para el encaminamiento de paquetes. Además de los problemas de escalabilidad, hay algunos detalles importantes que el artículo deja pendientes o no aclara: ¿Cuál es el formato de la cabecera? – No solo se requiere un esquema de direccionamiento común, también en necesario un formato que permita a los encaminadores obtener esas direcciones de la cabecera de cada datagrama. ¿Cuál es la representación de datos externa? – Cómo se serializan y representan los datos de la aplicación «en el cable». El propio artículo indica que se debería determinar el tamaño de los tipos de datos y su ordenamiento. ¿Cómo se gestiona la diferencia de MTU? – No cualquier mensaje de la MANET puede atravesar la WSN dado que éstas suelen tener una trama mucho menor que W I F I. ¿Cómo se comunica la red MANET con otras? – ¿Es posible acceder a la MANET desde Internet o una red troncal de otro tipo? La conclusión a todas estas cuestiones es que no basta con un esquema de direcciones unificado, es necesario también un protocolo de red único. G ADALLAH [GEK08] plantea un escenario muy similar al anterior. En este caso, se supone una red de sensores que se despliega inmediatamente después de una catástrofe, como un terremoto o un gran incendio. La otra red está formada por los vehículos de los equipos de emergencia, que forman una MANET, pero que además tienen interfaces de radio compatibles con la WSN y posiblemente acceso a Internet. Cualquiera de estos vehículos puede funcionar como pasarela entre la MANET y la WSN. Lo interesante de este trabajo es que propone un protocolo de encaminamiento que proporciona dos modos: Modo orientado a dirección, se utiliza para comunicar los vehículos entre sí utilizando AODV. Si un nodo sensor recibe un mensaje de petición de ruta en este modo lo descarta inmediatamente. Modo orientado a datos, se utiliza para obtener información de la red de sensores. Cuando un mensaje de consulta (que no incluye dirección destino) llega a un sensor, si la consulta que contiene le atañe, puede responder encaminando el mensaje a través de la ruta almacenada en el propio mensaje de petición. i i i i i i i i 78 2. A NTECEDENTES La ventaja de este tipo de protocolos orientados a datos es que no se requiere un protocolo de transporte adicional, el propio protocolo de encaminamiento lo es también de transporte. Sin embargo, presenta el inconveniente de que los tipos de datos, sus tamaños y los criterios de selección están definidos intrínsecamente en el propio protocolo de encaminamiento de modo que un nuevo tipo de sensor o consulta implica tener que modificar el protocolo. 2.6.4. Redes «inmersivas» Se trata de redes inalámbricas en las que pueden aparecer dispositivos de otra naturaleza pero con capacidad para comunicarse con los nodos de la red. El ejemplo clásico es un sistema ubicuo en el que una persona con una PDA o smart phone puede comunicarse directamente con los dispositivos que hay instalados en el entorno, para lo cual debe disponer lógicamente de una interfaz de radio compatible. En realidad es un escenario muy similar al de los bomberos que veíamos en la sección anterior. En esta situación, cualquier nodo puede actuar como pasarela para dispositivos externos. Aunque desde el punto de vista de los sistemas ubicuos, ésta es una situación con un gran potencial para las WSN, raramente se considera en la bibliografía debido quizá al alto grado de autonomía que implica para los nodos, a la necesidad de plantear un protocolo de comunicaciones suficientemente robusto y a la potencial heterogeneidad y dinamismo que implica. Por ejemplo, K ABADAYI [Kab06] propone un modelo para el desarrollo de un middleware en el que una persona puede entrar en una zona en la que hay una red de sensores (inmersión) y configurar un escenario con unos condicionantes muy precisos para acceder a los nodos próximos hasta una cierta «profundidad» (no a cualquiera). Este middleware, denominado Declarative Applications in Immersive Sensor networks (DAIS) está basado en la composición de estas escenas y en la utilización de sensores virtuales para agregación de datos procedentes de los sensores. El trabajo citado es bastante preliminar y no ha sido posible encontrar detalles sobre cómo se produce la entrega de mensajes, su formato o el protocolo de encaminamiento utilizado. DAIS contempla la aparición de dispositivos individuales que interaccionan con la WSN, mientras que [SKLN08] considera dos redes formadas por dispositivos distintos pero situadas en la misma zona, a pesar de ello. Aunque el título de esta sección se ha tomado de este artículo, una vez analizado su diseño, quizá sería más preciso hablar de «clientes inmersos». 2.7. Descubrimiento de servicios y recursos Es frecuente que en muchos sistemas distribuidos los servicios disponibles puedan aparecer y desaparecer dinámicamente. También puede ocurrir que varias entidades puedan proporcionar el mismo servicio, quizá con distintos condicionantes de Q O S. Los SDP S son una solución bastante efectiva para proporcionar mecanismos a los servicios para darse a conocer, y a los clientes y aplicaciones para localizar el servicio más adecuado a sus necesidades. En esta sección veremos primero unos conceptos generales, después las prestaciones habituales de los SDP S analizando las distintas alternativas para su diseño y funcionamiento. i i i i i i i i 2. A NTECEDENTES 79 Por último, se introducen algunas iniciativas destacables en su aplicación a las SAN y en entornos inteligentes. 2.7.1. Terminología Para la descripción de SDP utilizaremos la terminología y criterios de clasificación habituales en este campo, siendo M ARIN -P ERIANU [MPHS05] un buen referente a este respecto. Se definen a continuación algunos de los conceptos más importantes en este campo a fin de evitar posibles ambigüedades: Servicio Cualquier funcionalidad que una entidad hardware o software ofrece a la red y que pudiera ser de interés para otros elementos del sistema, ya sean usuarios u otros servicios. Descubrimiento de Servicios Protocolos y herramientas destinados a la búsqueda, registro y detección automática de dispositivos y sus servicios en una red de comunicaciones. De acuerdo con la terminología habitual, se pueden identificar tres tipos de entidades básicas en cualquier SDP: Cliente12 La entidad interesada en encontrar y utilizar servicios presentes en la red. Eso implica aplicaciones finales para el usuario del sistema, aplicaciones de gestión y depuración, servicios derivados, etc. Servidor La entidad que ofrece el servicio. Un nodo puede alojar varios objetos del mismo o diferentes tipos. Podemos concluir pues que el rol de servidor recae en el nodo tanto como entidad física como lógica. Cuando los servicios se implementan con las herramientas estándar del middleware (sobre un PC, por ejemplo) el concepto de servidor es muy similar desde ambos puntos de vista: el SDP y el middleware. Directorio14 Se trata de un servicio especial que permite a cualquier elemento del sistema acceder a la información que describe los demás servicios, de modo que se pueda determinar qué nodo o nodos ofrecen determinado servicio y en qué condiciones. 2.7.2. Prestaciones habituales A continuación se enumeran y describen los casos de uso habituales que soportan los SDP S. Aunque no todos ellos incorporan todas las prestaciones, y algunos integran otros aspectos adicionales (como encaminamiento) que no son contemplados aquí, puede servir como referente a efectos de comparación. 12 También 14 También user. servidor, broker, central, resolver. i i i i i i i i 80 2. A NTECEDENTES A pesar de que algunos SDP S (como el de Jini [Sun01]) definen el uso del servicio como parte del protocolo de descubrimiento, nosotros hemos excluido ese aspecto puesto que consideramos que realmente queda fuera de la funcionalidad del SDP como tal. Descripción de servicios El SDP debe definir algún lenguaje, nomenclatura o modelo de información para describir qué función realiza el servicio, cómo se usa y los requisitos que debe cumplir el cliente para utilizarlo, incluyendo posiblemente directrices de autenticación o seguridad. Así por ejemplo, SLP [VGPK97] define sus servicios mediante plantillas [GPK99]. Éstas incluyen conjuntos de atributos y sus valores. Bluetooth SDP [BT04] también define sus servicios por medio de una lista de atributos. Persistencia de las descripciones Existen varias alternativas para el almacenamiento de las descripciones de los servicios. En los protocolos basados en directorio, éstas residen en el mismo (modelo centralizado), mientras que en el modelo distribuido pueden estar en los nodos que implementan los servicios. Son posibles modelos híbridos y directorios jerarquizados. UP N P SSDP [UPn00] utiliza un modelo de persistencia distribuido, mientras que SLP y Jini utilizan modelos centralizados basados en directorio. En cuanto al formato de los datos, Universal Plug and Play (UP N P) y otros utilizan descripciones en XML lo que los hace poco adecuados como candidatos para SAN ya que los requisitos para el procesamiento de XML pueden resultar prohibitivos en dispositivos con recursos limitados. Referencia del servicio Todo servicio debe tener asociada una referencia o descriptor que haga posible su uso o localización. Tanto el proceso de búsqueda como el de anunciamiento utilizan descriptores de servicios para lograr su función. El formato del descriptor, que por comodidad suele tener un formato textual, puede incluir un protocolo, una dirección de host y otra información para localización unívoca del servicio. Anunciamiento/Registro El procedimiento por el cual un servicio nuevo se da a conocer al sistema se denomina anunciamiento (advertisement). Para ello se utiliza algún mecanismo de multi-envío que puede estar basado en direccionamiento broadcast o multicast, requiriendo en este último caso una dirección conocida públicamente. Este hecho normalmente limita la operación del mecanismo de anunciamiento a una LAN o medio de difusión equivalente, puesto que propagarlos a una red de tamaño considerable tiene importantes efectos sobre su escalabilidad. El anunciamiento puede ser un proceso proactivo (descubrimiento pasivo) si lo realiza el servicio por iniciativa propia o bien puede ser reactivo (descubrimiento activo), si lo desencadena una acción del cliente, aunque en ese caso puede ser visto como una i i i i i i i i 2. A NTECEDENTES 81 modalidad de búsqueda. El anunciamiento proactivo suele ser periódico lo que, en principio, lo convierte en una mala solución para SAN si los dispositivos se alimentan con baterías. También es posible encontrar SDP S que contemplan la despedida de servicios como una forma de cortesía para evitar interacciones innecesarias cuando un servicio desaparece. En los SDP S basados en directorio el mecanismo de anunciamiento puede ser substituido por una operación de registro explícito. El directorio mejora la escalabilidad de la solución puesto que no requiere tráfico adicional en la red. También son posibles modelos híbridos en los que los servicios pueden elegir entre registro, anunciamiento reactivo o proactivo. SLP registra sus agentes de servicio en los agentes de directorio enviando mensajes SrvReg. También dispone de anunciamiento explícito para servicios y directorios por medio de los mensajes SAAdvert y DAAdvert. Los servicios Jini se registran enviando al directorio (el Jini Lookup Service) un objeto que contiene la descripción y atributos del servicio. Búsqueda El proceso de búsqueda de servicios es siempre un mecanismo proactivo, normalmente iniciado por el cliente, aunque es interesante la posibilidad de búsquedas realizadas a expensas de agentes de mantenimiento, gestión o, incluso, de composición automática de servicios. La búsqueda implica algún tipo de consulta o criterio de aceptación. El resultado suele ser una lista de posibles candidatos aunque si lo que se pretende es un procedimiento complemente automático, lo ideal es que el sistema decida por sí mismo cuál es la elección ideal sin intervención del usuario. En SLP la búsqueda incluye una lista de atributos que el servicio ha de cumplir. Otros como INS [BBK02] permiten especificar comodines. Jini utiliza una plantilla para realizar el filtrado de servicios disponibles. Si la consulta se satisface, el cliente obtiene un objeto procedente del directorio que le sirve como proxy para contactar con el servicio. 2.7.3. Descubrimiento de Servicios en redes ad hoc y SAN El descubrimiento de servicios resulta especialmente importante en redes ad hoc, SAN y WSN debido a su naturaleza dinámica, no ya por la movilidad (que puede no existir) sino por el hecho de que las comunicaciones inalámbricas, la aparición de nuevos nodos y el agotamiento de las baterías pueden provocar cambios en la disponibilidad de servicios. Los SDP S para SAN suelen prestar especial atención a cualquier característica del protocolo que pueda tener repercusión sobre los recursos de cómputo y energía a la vez que se cuidan los aspectos dinámicos. Por ello, suelen evitarse los protocolos basados en XML, el descubrimiento pasivo, el directorio centralizado, etc., muy habituales en SDP S para redes convencionales. Veamos algunos de los protocolos más representativos en este área. R. M ARIN -P ERIANU [MPSH06, MPSHH08] utiliza un enfoque basado en grupos (clusters) para diseñar un SDP para WSN heterogéneas. A fin de reducir el tráfico necesario para realizar registros y búsquedas se divide la red en grupos como es habitual en muchos i i i i i i i i 82 2. A NTECEDENTES middlewares para SAN y para cada uno de ellos se nombra una cabeza que alojará un directorio local. Ese nodo será el más potente o con más energía del vecindario (nodos alcanzables en un salto). El resultado es un modelo de directorio jerárquico en el que los nodos solo informan de sus servicios a la cabeza de su grupo. C. F RANK [FHK04] propone un SDP integrado con el protocolo de encaminamiento asumiendo que se trata de un protocolo ad hoc bajo demanda como puede ser AODV, que es lo habitual en redes MANET y en WSN aunque la movilidad no sea un factor aplicable. El motivo más importante para hacerlo de este modo es el considerable ahorro de mensajes que supone, algo especialmente importante en WSN. Propone dos posibles soluciones; la primera consiste en extender el protocolo de encaminamiento para transportar información sobre la descripción de los servicios tal como propone C. P ERKINS [PK02]. La segunda es utilizar una arquitectura de direccionamiento semántico [HKFK03] empleando algunos de sus mensajes para implementar anunciamientos y búsquedas con muy poca sobrecarga adicional. Otros protocolos similares son GSD [CJYF02] y HSID [OKK04]. Pervasive Discovery Protocol (PDP) [Cam02, CMnP+ 05, CGMA06] es un SDP diseñado para cubrir dos problemas de los protocolos anteriores: La necesidad de un elemento o servidor central (directorio) es incompatible con los entornos pervasivos o ubicuos dado que no hay garantías de que ningún dispositivo esté conectado y accesible para todos por tiempo indefinido. Las soluciones sin directorio hacen un uso constante e ineficiente de comunicaciones multicast o broadcast que suponen un grave inconveniente para dispositivos alimentados por baterías. Para evitar los problemas que suponen estos dos enfoques, PDP propone un modelo completamente distribuido con una mezcla de descubrimiento pasivo y anuncios reactivos. Es decir, los nodos anuncian sus servicios sólo cuando un cliente realiza una petición de servicio. Las respuestas a esas consultas son anunciamientos de servicios (que podemos considerar reactivos) pero que se transmiten broadcast a todos los dispositivos y clientes de la red de modo que todos conocen el nuevo servicio, pero sólo si ha habido una solicitud. Con ello se minimiza la cantidad de mensajes necesarios aunque no se puedan descubrir los nuevos servicios inmediatamente de estar disponibles. i i i i i i i i Objetos Distribuidos Universales 3.1. 3.2. 3.3. 3.4. 3.5. 3.6. 3.7. 3.8. 3.9. Nomenclatura Interfaces escalares Contenedores Actores activos Componentes Actores compuestos Composición básica de servicios Consulta múltiple Conclusiones 33 U NA parte considerable de los dispositivos que aparecen en las redes SAN suele ofrecer información escalar tal como un valor de temperatura, presión, intensidad luminosa; e incluso más simple, como un contacto libre: presencia mediante una barrera de infrarrojos, cierre de una puerta, una pisadera y un largo etcétera. En los dispositivos utilizados actualmente, sobre todo en las WSN, es muy habitual que un mismo nodo integre varios sensores distintos: LDR, acelerómetro, inclinómetro, etc. (ver figura 8.1a). Desde el primer momento, nuestra visión de la red SAN desacopla funcionalmente el transductor y el nodo al que está físicamente conectado. Cada transductor situado en la placa de un nodo es un objeto distribuido autónomo e independiente, y el nodo al que está conectado desempeña únicamente el papel de punto de conexión. Aunque obviamente todos comparten el mismo dispositivo de cómputo e interfaz de red, eso resulta irrelevante para los clientes, los servicios implicados y la aplicación distribuida de la que forma parte. Teniendo muy presente la idea del transductor como objeto independiente y tomando como base las interfaces que ya proponía el proyecto SENDA [ML02, Moy03], definimos un modelo de información basado en un conjunto de interfaces que homogeneiza el acceso y simplifica la interacción remota con los transductores para, de ese modo, aprovechar al máximo las posibilidades de los dispositivos empotrados más simples. Ese modelo de información, que denominamos DUO (Distributed Universal Objects), es el tema del presente capítulo. Es importante señalar que DUO no está en modo alguno limitado a la interacción con los transductores de una red SAN. Se puede aplicar a servicios o dispositivos complejos —como una cámara de vídeo— sin detrimento de su funcionalidad o eficiencia, tal como se mostrará en la descripción de los prototipos (véase capítulo 8). 83 i i i i i i i i 84 3. O BJETOS D ISTRIBUIDOS U NIVERSALES 3.1. Nomenclatura Con la intención de evitar posibles ambigüedades, aparecen a continuación definiciones informales para algunos conceptos que se utilizarán habitualmente en éste y subsiguientes capítulos. Faceta Un mismo objeto puede desempeñar distintos roles dependiendo del subsistema o cliente que desea interaccionar con él. Cada uno de estos roles o facetas representa una forma diferente de interactuar con un mismo objeto. Cada faceta suele implementar interfaces diferentes y normalmente tiene asociado un conjunto distinto de casos de uso. Cada faceta se identifica por medio de una clave o cadena y existe una faceta por defecto, que debería corresponder con la funcionalidad principal del objeto. Servicio Aunque se han dado definiciones de servicio tan vagas como «la implementación de un algoritmo o el acceso a un dispositivo en un host de modo que un cliente puede contactar con él para utilizarlo» [OVB05], el concepto de servicio en DUO es más cercano al que OASIS define para su modelo SOA (Service Oriented Architecture) [Org06], que viene a decir: Un servicio es un mecanismo que permite acceder a una o más capacidades. El acceso se proporciona usando una interfaz prescrita y se ejerce ajustándose a las restricciones y políticas especificadas en la descripción del servicio. Precisamente este capítulo contiene la interfaz, la descripción y las restricciones de cada servicio. Es decir, las siguientes secciones definen los servicios DUO que pueden ser implementados por objetos distribuidos. Nótese que un solo objeto puede proporcionar varios servicios implementando varias interfaces y/o facetas. Actor Llamamos actores a los objetos que desempeñan una tarea dentro del sistema y no son meros consumidores de los servicios que éste presta. Así, un actor DUO es todo objeto distribuido que implemente alguna de las interfaces especificadas en el modelo. 3.2. Interfaces escalares Se define un módulo para cada tipo de dato susceptible de ser utilizado para representar el estado de un transductor, es decir, el valor de la magnitud que mide el sensor, o aplica el actuador. En el caso general, cada módulo tiene dos interfaces: R (readable) y W (writable) que definen respectivamente los métodos get() y set(). Es un modelo de datos basado en consulta (query-based), una versión orientada a objetos del enfoque data-centric utilizado en muchos middlewares de SAN como TinyDB [MFHH05], Cougar [YG02] o SensorWare [BHS03]. Se trata de interfaces minimalistas que reflejan cómo se utiliza el actor, pero no qué es. Son deliberadamente pobres desde el punto de vista semántico. La interacción entre i i i i i i i i 3. O BJETOS D ISTRIBUIDOS U NIVERSALES 85 actores y la configuración de servicios se han diseñado como mecanismos ortogonales y desacoplados. Dicha diferenciación posibilita la delegación parcial de responsabilidades a otros dispositivos o servicios aprovechando mejor el enfoque distribuido y resulta en un sistema más tolerante a fallos. Una vez fijadas las relaciones entre actores (configuración), la única funcionalidad esencial es la que permite interactuar con el estado de los mismos, es decir, averiguar o modificar el valor de los transductores. Despojar a la interfaz de gran parte de su semántica simplifica sensiblemente su implementación, aumenta la generalidad y no perjudica el modelo de información. Partiendo de esta premisa, es posible modelar tres situaciones muy frecuentes: Un sensor (interfaz R). Un actuador, cuyo estado no es accesible de modo síncrono (W). Esta situación ocurre cuando no se dispone de conectividad bidireccional, aunque eso no implica que ese valor no pueda ser obtenido indirectamente, como se verá más adelante. Un actuador, cuyo estado puede ser consultado de modo síncrono. Implementa tanto R como W. El listado 3.1 muestra la declaración de las interfaces básicas por medio del lenguaje Slice. El método get() es idempotente en todos los módulos, es decir, puede ser invocado varias veces consiguiendo el mismo efecto (sobre el actor) que si se invocara sólo una vez. Obviamente el método puede devolver un valor distinto en cada ocasión si el dispositivo efectúa una lectura instantánea de su sensor. El método set() tiene dos parámetros: el primero es el valor que se pretende asignar al actuador, el segundo (oid) es una identidad de objeto y lo utiliza el emisor del mensaje para que el receptor pueda identificarlo. Si no hay ningún actor ligado al emisor del mensaje (se trata de un cliente puro) puede especificar una identidad vacía. Lo habitual es que los clientes y aplicaciones envíen una identidad nula como segundo argumento, mientras que los actores activos (véase § 3.4) indican su propia identidad. La interfaz Pulse::W se utiliza para actores que deben ser informados de la ocurrencia de un suceso, pero éste no tiene asociado valor alguno. Un disparador remoto para una cámara fotográfica es un buen ejemplo para ilustrar el uso de esta interfaz. También merece especial atención el módulo Object. El tipo de dato en este caso es una referencia a objeto. De ese modo, se proporciona la posibilidad de que un actor ofrezca/acepte un proxy (que puede cambiar). Este mecanismo se puede utilizar para proteger objetos, pudiendo conseguir la referencia al verdadero objeto únicamente cuando se cumplen determinadas condiciones. También se puede utilizar para proporcionar un mecanismo de delegación similar al concepto de receptacle en la nomenclatura CCM. La utilización de nombres tan cortos para las interfaces y los módulos no es casual. Los métodos para introspección (como ice_id() o ice_isA()) transmiten esos tipos como cadenas. Nombres más largos implican mensajes más largos, más cantidad de memoria, energía, etc. Por ese motivo, los programadores deberían aplicar este principio también a los nombres de sus interfaces. i i i i i i i i 86 3. O BJETOS D ISTRIBUIDOS U NIVERSALES module DUO { module Pulse { interface W { void set ( Ice :: Identity oid ) ; }; }; module IBool { interface R { idempotent bool get () ; }; interface W { void set (bool v , Ice :: Identity oid ) ; }; }; module IByte { interface R { idempotent byte get () ; }; interface W { void set (byte v , Ice :: Identity oid ) ; }; }; module IInt { interface R { idempotent int get () ; }; interface W { void set (int v , Ice :: Identity oid ) ; }; }; module IFloat { interface R { idempotent float get () ; }; interface W { void set (float v , Ice :: Identity oid ) ; }; }; module IString { interface R { idempotent string get () ; }; interface W { void set (string v , Ice :: Identity oid ) ; }; }; module IByteSeq { interface R { idempotent Ice :: ByteSeq get () ; }; interface W { void set ( Ice :: ByteSeq v , Ice :: Identity oid ) ; }; }; module IObject { interface R { idempotent Object∗ get () ; }; interface W { void set (Object∗ v , Ice :: Identity oid ) ; }; }; }; L ISTADO 3.1: Interfaces DUO escalares (especificación Slice) i i i i i i i i 3. O BJETOS D ISTRIBUIDOS U NIVERSALES 87 Si se requiere un actor que implemente al tiempo la interfaz R y W de un módulo, el programador deberá definir una interfaz adicional que herede de ambas. Nótese que ni la aplicación cliente ni ninguna otra entidad que haga uso del actor necesita conocer esa tercera interfaz; se trata de un mecanismo de composición para la funcionalidad del servidor. Es decir, no importa el nombre que se le dé a esa interfaz o que cambie de un actor a otro; la única directiva es utilizar también nombres cortos por las razones explicadas en el párrafo anterior. Un ejemplo de esto aparece en el listado 3.2. module MySystem { interface MyBoolRW extends DUO :: IBool :: R , DUO :: IBool :: W {}; }; L ISTADO 3.2: Creación de una interfaz para composición de interfaces básicas. El resto del sistema puede ignorarla sin consecuencias 3.2.1. Actuación relativa Pueden aparecer situaciones en las que es conveniente manipular un actuador sin conocer su valor actual. Estas situaciones se dan cuando: La tecnología de la red de datos no permite averiguar su valor (p.ej. X10 [X10]). El transporte de datos no permite leer un valor (por ser oneway) de modo que no se puede utilizar (get()) para obtenerlo. Realmente no se requiere conocer el valor del actuador, solo modificarlo, evitando así el mensaje adicional de lectura. Se trata de añadir al actuador soporte (opcional) para manipulación relativa de su estado. Para ello se define una nueva interfaz que aparece en el listado 3.3. module DUO { module Func { interface Relative { void inc (short nsteps ) ; }; }; }; L ISTADO 3.3: Interfaz DUO::Func::Relative Esta interfaz es aplicable a casos como el desplazamiento de un motor (izquierda/derecha), zoom (acercar/alejar), enfoque y muchas otras actuaciones similares que pueden definirse indicando un valor relativo respecto al actual, a diferencia de set() que indica un valor absoluto. El único método de la interfaz DUO::Func::Relative es inc(), y su parámetro (nsteps) indica un número de pasos. Como este parámetro tiene signo, puede indicar tanto incremento como decremento. El valor del paso lo establece el propio actor y puede no ser conocido por el cliente. i i i i i i i i 88 3. O BJETOS D ISTRIBUIDOS U NIVERSALES 3.3. Contenedores La creación de colecciones de objetos o transductores, ya sea por medio de grupos o clusters [VR05], es una característica habitual en los middlewares convencionales como, por ejemplo, el servicio CosNaming [Obj01b] de CORBA. También es común en middlewares especializados en redes WSN. La formación de grupos responde a diversos motivos: puede estar ligada a un suceso o necesidad puntual (EnviroTrack [Abd04], DSWare [LLS+ 03]), utilizar criterios como la proximidad o el nivel de energía a efectos de optimización de las comunicaciones (SINA [SJS01], MiLAN [HMCP04]) o formar grupos a partir de los elementos que satisfacen un criterio dado [Abd04] o los sensor spaces de COCOS [KKN07]. El módulo DUO::Container proporciona un mecanismo básico para crear colecciones y jerarquías de actores similar al servicio CosNaming. La interfaz DUO::Container::R ofrece un diccionario de objetos cuyas claves son cadenas de texto arbitrarias elegidas por el programador. Las referencias que contiene ese diccionario pueden ser de objetos situados en cualquier parte, no tienen porqué tener relación alguna con el actor contenedor. La interfaz DUO::Container::W (listado 3.4) ofrece métodos para manipular la lista de objetos que mantiene el contenedor. El método link() registra un objeto asociado a una clave, ambos proporcionados por el cliente. El método unlink() elimina un registro. module DUO { dictionary <string , Object∗ > ObjectPrxDict ; module Container { exception A l r e a d y E x i s t s E x c e p t i o n { string key ; }; exception N o S u c h K e y E x c e p t i o n { string key ; }; interface RW ; interface R { idempotent ObjectPrxDict list () ; }; interface W { void link (string key , Object∗ value ) throws A l r e a d y E x i s t s E x c e p t i o n ; void unlink (string key ) throws N o S u c h K e y E x c e p t i o n ; Container :: RW ∗ create (string key ) throws A l r e a d y E x i s t s E x c e p t i o n ; void destroy () ; }; interface RW extends R , W {}; }; }; L ISTADO 3.4: Módulo DUO::Container para colecciones de objetos Por otra parte, el método create() se puede utilizar para crear un contenedor y vincularlo (con el nombre dado) dentro del contenedor que proporciona el método. Nótese que esos contenedores hijos los crea y mantiene el servidor en el que se i i i i i i i i 3. O BJETOS D ISTRIBUIDOS U NIVERSALES 89 encuentre el contenedor padre. El método destroy() elimina tanto la asociación como el propio contenedor. Existe una tercera interfaz RW debido a que los contenedores que devuelve el método create() deben implementar R y W. 3.4. Actores activos Con frecuencia, las aplicaciones que utilizan redes SAN necesitan mecanismos para conocer el valor actualizado de un transductor o varios (un grupo). Sin embargo, cuando hay gran cantidad de nodos conectados, la consulta síncrona por parte de los clientes presenta varios problemas: Se requiere un transporte twoway, pues el valor se obtiene como respuesta. Como alternativa, y empleando transporte unidireccional, existe la posibilidad de utilizar algún mecanismo de retrollamada, en el cual el cliente indica en la invocación la referencia de un segundo objeto bajo su control. A continuación, el nodo envía un mensaje a dicho objeto con el valor solicitado. En ambos casos, se requieren dos mensajes para obtener el dato deseado. Si se utiliza un transporte twoway, se debe consultar a cada objeto de forma independiente ya que no existe la posibilidad de utilizar multicast. Una gran parte de los objetos consultados no habrán sufrido cambios y retornarán el mismo valor que en la consulta anterior resultando por tanto innecesaria, pero no hay forma de saberlo de antemano. Todas estas circunstancias incrementan la cantidad de mensajes, lo cual repercute en el dimensionamiento del ancho de banda necesario en la red SAN y, por ende, en su coste. Además, implica también un incremento significativo del consumo, que en el caso de nodos alimentados por baterías lleva consigo una reducción de su autonomía. Para evitar estos problemas utilizamos actores activos. Se trata de actores que pueden actuar también como clientes, es decir, que pueden realizar invocaciones a otros objetos, aunque de un modo muy concreto. Los actores activos utilizan esas invocaciones con el propósito exclusivo de notificar a otros su propio estado y su identidad (utilizando las interfaces W). Al igual que DSWare [LLS+ 03], TinyDB [MFHH05], Impala [LM03] o Mires [SGaV+ 04], DUO proporciona soporte para estrategias de comunicación basadas solo en eventos, útiles también para aquellos casos en los que no se puede o no se desea utilizar un medio twoway por los motivos antes mencionados. Los actores activos materializan el soporte de DUO para redes de sensores activas [BHS03], es decir, redes en las que los nodos no sólo responden a paquetes de datos procedentes de la red; también lo hacen a eventos del entorno físico, timeouts, etc. No se debe confundir con otro concepto del mismo nombre que presenta [LGC05], y que se refiere a la capacidad de los nodos sensores para realizar procesamiento de datos. i i i i i i i i 90 3. O BJETOS D ISTRIBUIDOS U NIVERSALES Todo actor activo puede tener asociado un objeto observador1 , es decir, otro objeto distribuido que observa el estado del actor. Para permitir esta asociación el actor dispone de una referencia a su observador que puede ser modificada si se requiere. Cuando sea preciso, el actor invocará el método set() de su observador para comunicar el nuevo estado del transductor. Se requiere, por tanto, que el observador implemente una interfaz DUO compatible (ver figura 3.1). La interfaz en lenguaje Slice para la implementación de objetos activos se muestra en el listado 3.5. En el caso de la implementación para I CE, la interfaz DUO::Active tiene un soporte específico para su servicio de eventos. Eso conlleva grandes ventajas porque así puede utilizarse con un número arbitrario de observadores, se desacopla al productor de los consumidores (el actor sólo tiene que conocer la referencia del canal) y facilita la integración con otros servicios proporcionados por el middleware. Sin embargo, el hecho de utilizar canales de eventos como observadores no excluye la posibilidad de utilizar objetos convencionales no ligados al servicio de eventos del fabricante. module DUO { module Active { interface R { Object∗ getCb () ; IceStorm :: Topic ∗ getTopic () ; }; interface W { void setCbTopic (Object∗ publisher , IceStorm :: Topic ∗ topic ) ; }; }; }; L ISTADO 3.5: Módulo DUO::Active en lenguaje Slice La interfaz DUO::Active::R proporciona información acerca del canal asociado al objeto. El método getCb() se utiliza para conseguir una referencia al observador del objeto. Cuando el actor activo se conecta a un canal de eventos este método retorna el publicador de dicho canal, un objeto remoto al que se deben enviar los mensajes que deben llegar a los consumidores. El método getTopic() retorna una referencia al canal de eventos asociado. Este dato es necesario para suscribir consumidores adicionales o cualquier otra operación de mantenimiento del canal. Este proxy no es utilizado por el objeto, simplemente lo sirve a terceros por conveniencia, dado que de otro modo la relación actor/cliente sería dependiente de un tercero. Cuando el observador es un objeto sin relación con el servicio de distribución de eventos el método getTopic() retorna un proxy nulo. Por su parte, la interfaz DUO::Active::W ofrece la oportunidad de cambiar remotamente el observador del objeto. Esto resulta especialmente interesante cuando el objeto es tan reducido que no tiene capacidad suficiente para crear su propio canal de eventos. En ese caso, un servicio externo puede intermediar creando y asignando los canales de eventos automáticamente a los objetos que lo requieran (véase § 8.4.5). 1 Por cercanía semántica, se aplica aquí la terminología del patrón de diseño observer [GHJV96]. i i i i i i i i 3. O BJETOS D ISTRIBUIDOS U NIVERSALES 91 La interfaz DUO::Active::W sólo define el método setCbTopic(), cuya función es informar al actor de las referencias necesarias para utilizar un nuevo observador/canal. De nuevo, si el observador no es un canal proporcionado por el middleware, el segundo parámetro (topic) ha de ser un proxy nulo. Para eliminar el observador, el cliente debe invocar este método pasando dos proxies nulos. A efectos terminológicos, los objetos que no ofrecen este comportamiento se denominan pasivos. Su estado sólo se puede averiguar mediante una consulta directa por medio de su método get(). Eso implica la necesidad de un soporte de comunicaciones bidireccional, mientras que los activos pueden implementarse utilizando únicamente primitivas de comunicación unidireccional. 3.4.1. Reactivos Un actor reactivo informa de su estado invocando el método set() de su observador cada vez que recibe un mensaje ice_ping(), tal como muestra la figura 3.1a. (a) (b) F IGURA 3.1: Diagramas de secuencia de un actor reactivo (a) y uno proactivo (b) Es importante señalar que se trata de un mecanismo idempotente y completamente asíncrono ya que el tiempo de que dispone el actor para reaccionar no está acotado, aunque podría estarlo. Otro punto importante es que la aplicación interesada en obtener el valor del transductor no tiene porqué ser la misma que envía los mensajes ping. i i i i i i i i 92 3. O BJETOS D ISTRIBUIDOS U NIVERSALES En aquellos middlewares en los que los objetos no disponen de serie de un método equivalente a Ice::Object::ice_ping() o CORBA::Object::non_existent() será necesario definir una interfaz DUO::Object para proporcionar este tipo de funcionalidad. 3.4.2. Proactivos Un actor proactivo puede enviar mensajes set() de forma espontánea. Resulta especialmente adecuado en las siguientes situaciones: Sensores que pueden detectar cambios en la magnitud asociada. De este modo sólo se envían nuevos mensajes cuando hay algún cambio en el valor. Actuadores que informan de su estado como consecuencia de un cambio provocado por un tercero. Sensores o actuadores que por definición deben comunicar su estado cada cierto tiempo con independencia de los cambios que se produzcan en él. Esto es útil para implementar wathdogs, señales de sincronización, etc. Nótese que, al contrario de lo que ocurre con los actores reactivos, ninguno de estos casos requiere un mensaje de petición de estado implícito ni explícito (ver figura 3.1b). 3.4.3. Activación condicional Como hemos visto, los sensores proactivos envían su estado cada vez que cambia. Sin embargo, este comportamiento puede ser contraproducente en muchos casos. Por ejemplo, si tenemos un sensor que lee un termómetro quizá no necesitemos que el actor envíe un evento cada vez que la temperatura cambie, incluso aunque lo pudiéramos discretizar a grados o décimas de grado. Evitar el envío de esos mensajes es importante, se ahorra energía y ancho de banda, muy escasos en una red tipo WSN. Existen dos vías sencillas para reducir considerablemente el número de mensajes que envía un actor activo. Lo ideal es que sólo se transmita información nueva cuando es realmente útil para sus potenciales consumidores. Activación por rango Se trata de fijar un rango para que el actor sólo envíe nuevos eventos si su valor está dentro (o fuera) de un rango determinado. Para ello se asocian facetas especiales al actor, llamadas range_min y range_max. Así por ejemplo, un sensor con interfaz DUO::IFloat::R puede tener una o ambas facetas, que deben implementar el mismo tipo. Opcionalmente, estas facetas pueden implementar la interfaz de escritura para permitir la modificación remota del umbral. Un actor proactivo que disponga de estas facetas no se comportará como tal a menos que su valor se encuentre dentro del rango definido por las mismas. Si el valor de range_max es menor que el de range_min, entonces sólo enviará eventos si el valor queda fuera del rango. Es posible también asociar al actor una de las facetas (en lugar de las dos), caso en el que se utilizará como umbral que debe superar el valor. Por razones obvias, esta funcionalidad solamente tiene sentido para actores escalares no booleanos. i i i i i i i i 3. O BJETOS D ISTRIBUIDOS U NIVERSALES 93 Activación por magnitud del cambio Otro caso muy frecuente es la necesidad de evitar la transmisión de valores demasiado similares. Para solventar este problema se utiliza también una faceta (delta). Esta vez la faceta indica cuál es la diferencia mínima entre el valor actual y el del último evento enviado para considerar que debe producirse un nuevo evento. De este modo, se evita una gran cantidad de mensajes sin perder información, dado que la aplicación puede modificar el valor delta remotamente adaptándolo a sus necesidades en relación a la precisión del sensor. 3.5. Componentes En algunas situaciones puede ser conveniente que un solo objeto ofrezca varios roles. Por ejemplo, un punto de luz regulable podría modelarse con la interfaz DUO::IByte::W para ajustar la intensidad, pero también con la interfaz DUO::IBool::W para encender/apagar. El problema aquí es que en muchos middlewares, un objeto no puede tener dos métodos con el mismo nombre; en este caso, tendría un set() heredado de cada interfaz. La solución consiste en crear una faceta para cada uno de los roles que puede ofrecer el objeto. El cliente puede listar sus facetas y después decidir cuál le interesa. Para ello, se utiliza la interfaz DUO::Component, que se muestra en el listado 3.6. Se trata de una interfaz muy sencilla cuando se utiliza I CE como middleware. Se debe a que los objetos I CE ya disponen del método ice_getFacet() que devuelve un proxy a la faceta solicitada a partir de cualquier otra. En otros middlewares que no dispongan de esa funcionalidad habría que añadirla en esta misma interfaz. module DUO { interface Component { Ice :: StringSeq getAllFacets () ; }; }; L ISTADO 3.6: Interfaz DUO::Component No se considera conveniente emplear el soporte de componentes que pudiera estar disponible en cada middleware (como es el caso de CCM) porque la implementación de objetos y clientes puede llegar a ser bastante compleja, mientras que la interfaz DUO::Component —a pesar de ser tan simple— proporciona la funcionalidad básica necesaria y puede ser implementada en dispositivos empotrados. El resto de las características propias de un componente, como fuentes y sumideros de eventos, receptacles o atributos se pueden conseguir por medio de otras interfaces DUO. En cualquier caso, nótese que la finalidad de DUO::Component no es la de conseguir un componente con todas las prestaciones propias de CCM o EJB (Enterprise JavaBeans), sino únicamente la de proporcionar navegabilidad de facetas. i i i i i i i i 94 3. O BJETOS D ISTRIBUIDOS U NIVERSALES 3.6. Actores compuestos La abstracción de la agregación aparece de forma recurrente en muchas de las propuestas que se comentan en la sección 2.5. Por razones obvias, la agregación involucra colecciones de objetos (véase § 3.3). Muchos middlewares, sobre todo aquellos con interfaz de base de datos, ofrecen operadores o servicios explícitos de agregación de datos como, por ejemplo, SINA [SJS01], DSWare [LLS+ 03], TinyDB [MFHH05], Cougar [YG02] o Mires [SGaV+ 04]. En muchos casos, son similares a los del lenguaje SQL; por medio de una sentencia de selección y un operador que se aplica al resultado (p.ej. AVG). En otros, la agregación se consigue de forma transparente mediante un objeto lógico o virtual [CMP06, RMDS02, Kab06]. DUO ofrece soporte para agregación transparente de actores a través de actores compuestos, es decir, aquellos que implementan la interfaz DUO::Composite. Los objetos compuestos (o simplemente composite) se utilizan para implementar transductores virtuales, es decir, su estado no corresponde con el valor medido por un transductor físico, sino que se obtiene luego de aplicar una función de agregación a partir de los valores de un conjunto de actores. Esta posibilidad permite, por ejemplo, obtener la temperatura media de una habitación en la que hay desplegados una docena de sensores, pero realizando sólo una lectura, y con la ventaja de que resulta completamente transparente para el cliente, que puede percibirlo a todos los efectos como la lectura de un sensor real único. La interfaz Composite toma su nombre del conocido patrón de diseño [GHJV96]. Lo cual implica que desde el punto de vista de diseño, el composite desempeña las relaciones tiene-un y es-un respecto a una interfaz DUO escalar. Para lograrlo, Composite hereda de la interfaz DUO::Container para proporcionar agrupación de referencias a los actores implicados (relación tiene-un). El resultado de la función de agregación lo proporciona implementando la misma interfaz que los actores que agrega (es-un). La figura 3.2 lo ilustra para el caso de un composite de DUO::IByte::R. Sin embargo, no se utiliza este diseño porque presenta varios problemas: 1. No exporta un medio para que el usuario pueda listar o añadir nuevos actores al composite. 2. No explicita la función de agregación que se está utilizando. No hay ninguna pista para el cliente de cuál es la implementación del método get() del composite. 3. No permite proporcionar más de una función de agregación para el mismo conjunto de actores. El primer problema se resuelve utilizando la interfaz DUO::Container, que dota al composite de métodos remotos para listar, añadir o eliminar referencias a los actores. Los otros dos problemas se resuelven haciendo que el composite implemente también la interfaz DUO::Component. Para obtener el resultado de una función de agregación concreta se debe acceder a la faceta correspondiente: sum, max, avg, any, all, etc. El composite y todas las facetas deben implementar la misma interfaz DUO escalar. Para averiguar de qué i i i i i i i i 3. O BJETOS D ISTRIBUIDOS U NIVERSALES 95 F IGURA 3.2: Diagrama de herencia de interfaces para un actor DUO::IByte::R compuesto, según el patrón de diseño funciones de agregación dispone el composite basta utilizar su método getAllFacets(). La implementación de múltiples facetas no tiene porqué implicar un gran consumo de recursos puesto que se pueden utilizar estrategias default servant, consiguiendo que un único sirviente pueda calcular todas las funciones de agregación soportadas. La faceta, por tanto, puede ser vista como un mecanismo de multiplexación. La especificación aparece en el listado 3.7. El módulo Composite proporciona interfaces R y W dependiendo de si el conjunto de actores agregados está predefinido (R) o el cliente tiene la posibilidad de editar el conjunto (W). module DUO {} module Composite { interface R extends DUO :: Component , DUO :: Container :: R {}; interface W extends DUO :: Component , DUO :: Container :: RW {}; }; }; L ISTADO 3.7: Módulo para construcción de actores DUO compuestos (especificación Slice) Estas interfaces permiten acceder a la funcionalidad de navegación de facetas y agrupación de actores, pero aún falta especificar el tipo concreto del compuesto. Para ello, el programador debe escribir una interfaz adicional que herede de DUO::Composite y del tipo que corresponda a los actores que desea agregar. Como ejemplo, el listado 3.8 y la figura 3.3 muestran el caso de un actor DUO::IByte::R compuesto. interface M y B y t e R C o m p o si t e extends DUO :: IByte :: R , DUO :: Composite :: W {}; L ISTADO 3.8: Actor DUO::IByte::R compuesto (especificación Slice) El método DUO::Container::W::link() debe encargarse de verificar que los objetos añadidos al compuesto por los clientes implementan todos los tipos DUO escalares que implemente el propio composite. i i i i i i i i 96 3. O BJETOS D ISTRIBUIDOS U NIVERSALES F IGURA 3.3: Diagrama de herencia de interfaces para un actor DUO::IByte::R compuesto, utilizando interfaces DUO Como el composite solo contiene referencias, un mismo actor puede estar agregado en varios de ellos al mismo tiempo siendo totalmente transparente para él mismo y para los actores agregados. Para participar en un composite, el actor no tiene que implementar ninguna funcionalidad o interfaz especial. 3.6.1. Actor compuesto activo El composite también puede comportarse como un actor activo (ya sea reactivo o proactivo) para cada una de sus funciones de agregación (facetas). Cada faceta en uso puede tener su propio observador o canal de eventos asociado. Nótese que cada faceta se comporta a todos los efectos como un actor DUO escalar y se puede utilizar en cualquier lugar o servicio en el que cabe esperar un actor convencional. Esto es una gran ventaja a efectos de coherencia semántica, bajo acoplamiento y facilidad en el despliegue respecto a las propuestas citadas anteriormente. Entre otras cosas, eso permite que se puedan agrupar (Container) o federar en otros actores compuestos. 3.6.2. Distribución La contrapartida de la agregación de datos es la distribución de acciones. En este caso, un actor compuesto que implementa una interfaz escalar escribible (W) aplicará el valor que recibe en su invocación set() a todos los actores que contiene. El mismo comportamiento se podría conseguir utilizando el mecanismo estándar de distribución de eventos si todos los actores agregados se suscriben a un canal creado al efecto y se envía la invocación al publicador del canal. Sin embargo, la utilización del composite presenta varias ventajas: i i i i i i i i 3. O BJETOS D ISTRIBUIDOS U NIVERSALES 97 Se abstrae el mecanismo de distribución. Realmente la implementación puede realizarse por medio de un canal de eventos tal como se ha explicado, pero resulta transparente al cliente. El mecanismo puede cambiar en aquellos entornos en los que el servicio de eventos no resulte conveniente o no esté disponible, sin que afecte la forma en que los clientes utilizan la aplicación. Existe una forma sencilla de listar los suscriptores a través de la interfaz DUO::Container. Proporciona un servicio de distribución basado en invocaciones para aquellos middlewares en los que el servicio de eventos está orientado a datos, como ocurre en el EventService de CORBA. Proporciona un mecanismo elegante de comprobación de tipo para aquellos middlewares que no lo tienen por defecto en su servicio de eventos, como ocurre en IceStorm. Cuando se usa un composite para distribución solo existe un método set() (el del propio actor compuesto). Este método debe ser el encargado de hacer llegar el dato a cada actor agregado por el medio más conveniente en el dominio de la aplicación concreta, aunque tal como se ha indicado, el más sencillo y eficiente suele ser el servicio de eventos que incorpora el middleware. Por supuesto, también es posible y útil implementar un composite para actores que sean al tiempo R y W. Como ejemplo, suponga un edificio en el que se dispone de cerraduras automatizadas para bloquear el acceso a partir de una hora o a una zona. Si esta cerradura está controlada con un actor booleano que implementa R y W, se puede leer y modificar su estado (bloqueado/desbloqueado). Si todos estos actores se añaden a un composite del mismo tipo, podríamos manipular todas las puertas con un solo mensaje. Pero además podrían estar disponibles funciones de agregación como any o all que informarían respectivamente si hay alguna puerta bloqueada o todas lo están. 3.7. Composición básica de servicios El diseño de las interfaces DUO hace posible un modelo de despliegue de servicios básicos extremadamente simple y robusto. Dado que la definición de las interfaces fuerza una comprobación estricta de tipos, el propio middleware puede garantizar la consistencia del modelo de información de toda la aplicación. 3.7.1. Cableado virtual Utilizando actores activos es posible realizar conexiones lógicas dinámicas entre servicios. Sobre un sistema en explotación y utilizando específicamente la interfaz DUO::Active::W, un operador del sistema puede reconfigurar dinámicamente el observador de cualquier actor, o bien crear y destruir canales de eventos relacionados. De ese modo, los consumidores de los datos producidos por los dispositivos del sistema pueden ser reasignados en cualquier momento por decisión del operador o de un servicio específico de alto nivel. i i i i i i i i 98 3. O BJETOS D ISTRIBUIDOS U NIVERSALES Denominamos a este mecanismo cableado dinámico virtual (dynamic virtual wiring) debido a que permite crear y gestionar un conjunto de relaciones unidireccionales entre actores (cableado) que pueden cambiar sin afectar al resto del sistema (dinámico) y que están completamente desacopladas de la topología de red o tecnología de comunicaciones subyacente (virtual). Este cableado tiene la ventaja adicional de que la información necesaria para establecer las relaciones se encuentra en los mismos nodos en los que están alojados los actores. Eso significa que, una vez configurado, el sistema es autosuficiente. La única infraestructura requerida es la red de comunicaciones. Si se utiliza el servicio de eventos, obviamente también se requiere un computador que aloje el servicio. Sin embargo, es viable crear una versión empotrada de dicho servicio que puede ser implementada en plataformas similares a las marcadas como objetivo para nuestros transductores. 3.7.2. Servicios reactivos Mediante el cableado virtual es posible desplegar servicios reactivos básicos, pero capaces de solventar un alto porcentaje de las necesidades de automatización de un entorno inteligente. El caso más simple (y más común) implica la conexión lógica de un sensor y un actuador. En este escenario, cuando el sensor detecta un cambio en su entrada, dispara la ejecución de una acción por parte del actuador. Esto sólo tiene sentido cuando el tipo del sensor y el actuador son compatibles, por ejemplo, un sensor de presencia todo/nada que activa la apertura de una puerta motorizada. Si bien se trata de un servicio funcionalmente trivial, resuelto anteriormente por infinidad de tecnologías, en nuestro caso presenta grandes ventajas que raramente se encuentran en otras propuestas: No existe ningún intermediario y, sin embargo, no es un sistema aislado. Tanto el sensor como el actuador pueden ser operados por terceros sin romper la relación existente. La relación es persistente, pero remotamente reconfigurable. Un operador del sistema puede modificar la configuración del sensor por medio de invocaciones remotas para designar otro actuador (observador). 3.7.3. Relaciones n-arias El mismo esquema se puede utilizar para desplegar servicios reactivos que implican a varios actores. Para algunas situaciones ni siquiera se requieren canales de eventos, como el caso en el que varios sensores operan sobre un actuador. Supongamos un escenario algo más complejo. La apertura de cualquier puerta de emergencia de un edificio activa una señal acústica para alertar al personal de seguridad. En ese caso, los elementos involucrados implican los siguientes requisitos: Las puertas están equipadas con un sensor proactivo que implementa la interfaz DUO::IBool::R. i i i i i i i i 3. O BJETOS D ISTRIBUIDOS U NIVERSALES 99 Cuando la puerta se abre, el estado del sensor cambia a True. La señal acústica está controlada por un actuador que implementa la interfaz DUO::IBool::W. Se activará al recibir un mensaje set(True) y se desactivará al recibir un mensaje set(False). La interconexión de estos actores puede realizarse de tres modos: Se crea un canal de eventos (T) y se asigna el publicador de ese canal (TP) a todos los sensores de las puertas mediante su método setCbTopic(). Requiere que los sensores sean DUO::Active::W. El actuador se suscribe al canal T. Ver figura 3.4a. Se crea un canal de eventos (T) y se federan (enlazan) los canales de todos los sensores (T1-Tn). Requiere que los sensores implementen DUO::Active::R y que dispongan de un canal propio, es decir, que su método getTopic() devuelva un proxy no nulo. El actuador se suscribe al canal T. Ver figura 3.4b. Se asigna el proxy del actuador alarma (A) como observador a todos los sensores mediante el método setCbTopic(). Necesita que los sensores sean DUO::Active::W, pero no es obligatorio un servicio de eventos. Sin embargo, esta solución es menos flexible en cuanto a posibilidades de gestión, ya que no hay un modo sencillo de averiguar qué sensores están lógicamente conectados. Ver figura 3.4c. La elección del tipo de interconexión a realizar dependerá de las necesidades específicas de la aplicación concreta. Por ejemplo, el tercer método no permite añadir nuevos consumidores para esos mensajes a menos que los actuadores cuenten con direcciones multicast. En todos los casos, se cumple el principio de autonomía que se indicaba en la sección anterior. Cualquier cliente puede consultar el estado de los sensores, y puede leer y escribir sobre el actuador sin que ello afecte a las relaciones establecidas. 3.8. Consulta múltiple En las redes de sensores es habitual que un agente o servicio externo necesite consultar el valor de un conjunto de sensores en el mismo instante, por ejemplo, para realizar un mapa que represente el nivel de humedad de una explotación agraria o un campo de fútbol, instalando una cantidad considerable de sensores. El objetivo es evitar la necesidad de enviar un mensaje de consulta dirigido específicamente a cada uno de los sensores. La solución propuesta pasa por usar actores reactivos (véase § 3.4.1). Para recibir los eventos con el estado de cada sensor, el cliente crea un nuevo canal recolector. Se enlazan a éste los canales de todos los sensores involucrados. Dicho canal puede ser reutilizado para sucesivas consultas, siempre que involucre a los mismos actores. Si los nodos tienen algún tipo de relación funcional o estructural es factible crear estos canales automáticamente. Todos los clientes interesados en recibir el valor de los sensores se suscriben al canal recolector (o son suscritos por un tercero). El diagrama de secuencia de la figura 3.5 muestra todo el proceso. i i i i i i i i 100 3. O BJETOS D ISTRIBUIDOS U NIVERSALES F IGURA 3.4: Ejemplo de cableado virtual. Tres alternativas: a) Fijando el canal de los actores activos, b) Enlazando sus canales y c) Sin utilizar el servicio de eventos El mensaje que dispara el proceso —el método ice_ping()— debe llegar a todos los sensores reactivos involucrados utilizando un canal de consulta. La forma más conveniente de implementar este canal sería que los sensores tuvieran un endpoint multicast adicional, pero eso no siempre es posible pues depende de la tecnología de red subyacente. En esos casos se puede utilizar un canal de eventos adicional. A dicho canal se suscriben todos los sensores. Nótese que esta operación de suscripción la realiza la aplicación cliente (o, en su defecto, un servicio especializado), pero nunca el propio sensor. Una vez interconectados los objetos como se ha explicado, una invocación ice_ping() sobre el canal de consulta provoca que cada sensor reaccione enviando el valor de su estado actual a su canal. Al estar éstos enlazados al canal recolector, la aplicación recibirá un mensaje set() por cada sensor. Dado que el segundo parámetro de ese mensaje es la identidad del emisor, la aplicación tiene constancia de a qué sensor i i i i i i i i 3. O BJETOS D ISTRIBUIDOS U NIVERSALES 101 F IGURA 3.5: Diagrama de secuencia de una consulta múltiple corresponde cada valor, información que puede utilizar a efectos de contabilidad, estadística o representación gráfica del entorno. Nótese que aunque el proceso se ha explicado refiriéndose a sensores exclusivamente (por continuidad con el ejemplo inicial), el mecanismo de consulta múltiple es perfectamente aplicable sin ninguna diferencia para un conjunto de actuadores o también a una mezcla de ambos, a condición de que todos ellos sean reactivos y del mismo tipo. La diferencia evidente respecto a los actores compuestos es que la consulta múltiple se utiliza cuando se necesita el valor de todos los sensores y no el resultado de una función de agregación. Sin embargo, ambos mecanismos se pueden combinar haciendo que el composite reenvíe también la invocación de su método ice_ping() a los actores agregados y proporcionando automáticamente el canal de eventos recolector. 3.9. Conclusiones DUO es un modelo de información completo para el desarrollo de sistemas en los que intervienen transductores y redes de transductores de todo tipo. Se sustenta en el principio de que todo sensor o actuador es un objeto, en todas sus acepciones y durante todo el ciclo de vida del sistema o aplicación, desde la captura de requisitos hasta el mantenimiento y explotación. i i i i i i i i 102 3. O BJETOS D ISTRIBUIDOS U NIVERSALES DUO proporciona interfaces simples y escalables para cualquier tipo de transductor, pero también para realizar descomposición funcional de dispositivos más complejos, en los que se requiere acceso individual a los elementos que lo conforman. Dispone de interfaces para agrupación y agregación, objetos virtuales, navegación de facetas, interconexión dinámica de objetos, actualización asíncrona, distribución de eventos, etc. Su diseño no promueve ni asume la existencia de una sola forma correcta de solucionar el problema. Al contrario, proporciona herramientas genéricas que trabajan bien juntas, con bajo acoplamiento y alta cohesión. Facilita el diseño de sistemas adaptándose a las restricciones o necesidades del entorno: lenguaje, middleware, disponibilidad de sus servicios, etc. La utilización de estas interfaces facilita sensiblemente la integración en cualquier sistema automatizado o de información, puesto que el acceso al transductor se hace utilizando un API local proporcionada por el middleware a través del proxy correspondiente, todo ello de un modo predecible y estandarizado. Se integra perfectamente con el dominio del problema que se trata de modelar, dado que aporta conceptos de alto nivel respetando el paradigma de la OO y aplicando conceptos y patrones de diseño clásicos. Los transductores pasan a ser entidades básicas en el modelado del sistema, simplificando los procesos de captura de requisitos, análisis, diseño y, particularmente, la implementación. El personal involucrado en el desarrollo no requiere formación específica, sea cual sea la tecnología empleada por el fabricante de los dispositivos o la red de datos utilizada. Cualquier programador o diseñador, acostumbrado a trabajar con objetos distribuidos de cualquier tecnología, inmediatamente puede comprender y aplicar DUO al desarrollo de soluciones que integran redes de transductores de manera natural. A pesar de otorgar interfaces de alto nivel a simples transductores, la sobrecarga de implementación puede ser realmente baja. Los mensajes que se intercambian, incluso siendo conformes al protocolo inter-ORB, son pequeños y regulares. Por ello, DUO es un modelo de información especialmente adecuado para plataformas con pocos recursos de cómputo, memoria, energía y ancho de banda. En resumen, DUO es un buen candidato para construir una «Internet de cosas». i i i i i i i i picoObjetos 4.1. 4.2. 4.3. 4.4. 4.5. 4.6. 4.7. 4.8. 4.9. 4.10. Introducción Una estrategia diferente Interoperabilidad Funcionamiento del picoObjeto Especificación de picoObjetos Transformación de FSM a bytecode Máquina virtual Generación de código nativo Despliegue de aplicaciones en la SAN Conclusiones 44 E L modelo de información e interacción propuesto en el capítulo anterior proporciona una imagen minimalista y homogénea de las redes de sensores en entornos heterogéneos. No se ha sacrificado ningún aspecto de la riqueza de modelos de interacción disponibles, pero además debe ser complementado con un modelo de ejecución y despliegue de objetos distribuidos que pueda ser implementado en las tecnologías de redes de sensores actuales. El presente capítulo es una descripción detallada de la propuesta que realiza esta tesis para obtener implementaciones mínimas funcionales de objetos distribuidos, llamados picoObjetos, en middlewares de comunicaciones de propósito general. Después de comentar las pautas iniciales, se introducen las restricciones de interoperabilidad y criterios de diseño para dos casos concretos: picoCORBA y picoIce. A continuación, se establecen las bases de la solución y del modelo de ejecución de código propuesto. 4.1. Introducción Nuestra motivación principal es proporcionar una infraestructura para el desarrollo de aplicaciones distribuidas sobre dispositivos como los que se utilizan habitualmente en las redes SAN, pero también cualquier otro elemento de cómputo conectado a una red —independientemente de su complejidad y capacidades— que sea susceptible de ser integrado en un entorno inteligente o automatizado. Un aspecto clave de este enfoque es la posibilidad de utilizar exactamente la misma metodología de desarrollo empleada tradicionalmente en los MDOO para diseñar y desarrollar aplicaciones y servicios que involucran redes de sensores. 103 i i i i i i i i 104 4. picoObjetos Empecemos analizando cómo se produce una invocación sobre un método remoto. En un MDOO, una invocación remota implica la cooperación de una cantidad considerable de entidades: uno o más adaptadores de objetos, un conjunto de sirvientes que implementan el comportamiento de los objetos, y un mapa de objetos activos que supervisa las relaciones entre objetos y sirvientes. Cada invocación a método remoto se traduce, al menos, en una petición (un mensaje) que incluye tres importantes componentes: La identidad del objeto, que identifica unívocamente al objeto destino en toda la red o, al menos, de modo que no sea posible un conflicto dentro del mismo dominio. La operación, que determina qué método del sirviente se ha de ejecutar. Un conjunto de argumentos necesarios para llevar a cabo la operación. Cualquier interacción entre un cliente y un objeto se consigue exclusivamente por el paso de mensajes usando el protocolo estandarizado (GIOP en CORBA o I CE P en ZeroC I CE). Por tanto, cualquier implementación de un objeto sigue siendo compatible siempre que cumpla el protocolo inter-ORB correspondiente. Como se vio en el capítulo 2, todos estos sistemas tienen un flujo de desarrollo muy similar. El proceso de desarrollo tradicional de aplicaciones distribuidas basado en modelos de programación de objetos empieza con la descripción de las interfaces remotas que ofrecen los objetos (el contrato). Después, se utiliza un compilador para generar automáticamente tanto los cabos del cliente como el esqueleto del servidor para cada interfaz. La figura 4.1 muestra dos implementaciones compatibles y, sin embargo, muy diferentes. La figura 4.1a es una simplificación de un diagrama de secuencia que muestra una invocación tal como la realiza cualquier middleware tradicional. La figura 4.1b muestra el comportamiento de la propuesta de este trabajo. La idea básica es conseguir máquinas de estados capaces de reconocer los mensajes procedentes de los clientes a través de una interfaz de red y generar respuestas válidas. De ese modo, su comportamiento será indistinguible de un objeto distribuido convencional. Con este enfoque es posible obtener programas con tamaños, dependencias y restricciones adecuados para su implementación en plataformas empotradas con recursos de cómputo gravemente limitados. Sin embargo, no es sólo una cuestión de tamaño. Hemos fijado una serie de requisitos que deben cumplir los picoObjetos y, a pesar de que ello implica cierta complejidad adicional, consideramos que son lo suficientemente importantes como para asumir el impacto que supone sobre el consumo de recursos: Autonomía La principal característica de los picoObjetos es que son autónomos. Eso garantiza que una red compuesta por picoObjetos puede funcionar de forma independiente. Los nodos y los servicios básicos seguirán trabajando incluso aunque todas las pasarelas de servicio fallen. Esta característica es crucial para conseguir un sistema lo suficientemente robusto, confiable y tolerante a fallos. i i i i i i i i 4. picoObjetos 105 (a) (b) F IGURA 4.1: Comparación de la invocación de un método remoto a un objeto implementado en un middleware convencional (a) y a un picoObjeto (b) Los elementos intermedios tales como las pasarelas que propone OMG STI [Obj03] u OSG I [All06] suponen además puntos únicos de fallo, encarecimiento y dependencia funcional. Debería ser posible implementar servicios autónomos garantizados, sin que ello dependa de la disponibilidad o estado de cualquier pasarela o servicio externo. Obviamente, en muchos casos sigue siendo necesaria la conectividad con el exterior, pero utilizando pasarelas sencillas, sin estado, que únicamente transportan mensajes entre dos o más redes, pero no intervienen en absoluto en el funcionamiento de la aplicación. Objetos distribuidos Se trata de obtener dispositivos empotrados que ofrezcan sus capacidades como si fuesen objetos distribuidos convencionales, indistinguibles de los implementados con las herramientas y bibliotecas suministradas por el fabricante. i i i i i i i i 106 4. picoObjetos Sistema heterogéneo Los picoObjetos deben ser capaces de ocultar sus características internas: la plataforma hardware sobre la que se hallan, las tecnologías de comunicaciones subyacentes, los protocolos de transporte y red empleados, etc. Para dotar de un núcleo de comunicaciones a dispositivos con muy escasos recursos de cómputo y memoria, la técnica habitual, que sigue manteniendo compatibilidad, es recortar o eliminar sus capacidades más complejas (véase § 2.4). El principal servicio que el núcleo de comunicaciones presta a los objetos es el soporte para el envío y recepción de mensajes conforme a las reglas del protocolo concreto, ocupándose de la codificación y serialización de datos y consiguiendo, de ese modo, una comunicación transparente con los clientes. Al mismo tiempo, el programador de la aplicación distribuida no tiene que preocuparse de todos esos detalles, evitando muchos errores recurrentes. La disponibilidad de un protocolo de alto nivel para la comunicación entre pares dentro del middleware permite que desde el exterior el objeto se pueda ver con dos enfoques: A nivel de programa Cualquier objeto remoto es como un objeto local. El núcleo de comunicaciones se encarga de crear en el espacio de memoria local del cliente un delegado del objeto remoto, llamado proxy en la terminología específica. Ese nombre se debe a que realmente se trata de una implementación automática del patrón de diseño remote proxy [GHJV96]. Desde este enfoque, la aplicación no conoce —no necesita conocer— la ubicación física y lógica del objeto al que se está invocando. A nivel del bus Con un segundo enfoque de más bajo nivel, el objeto puede verse desde la red como un servidor que implementa un pequeño protocolo inter-ORB. Si la intención es buscar objetos mínimos, ese segundo enfoque puede resultar muy conveniente. En el caso extremo, permite eliminar todo el núcleo de comunicaciones y substituirlo por el código necesario para dar soporte al protocolo concreto que le afecta. Tras nuestra experiencia en este asunto, esa parece ser la única estrategia que hace viable alojar un objeto distribuido en un dispositivo que está lejos de poder dar cabida a cualquier ORB convencional, incluso ateniéndose a las limitaciones de Minimum CORBA. Concretando, la propuesta consiste en implementar un pequeño núcleo de comunicaciones generado completamente a la medida de los mensajes que debe responder e invocar el nodo. Dicho núcleo está constituido por una máquina de estados jerárquica y las utilidades mínimas necesarias para ejecutar el código de los métodos del sirviente asociado a cada objeto. El código generado no se puede considerar una biblioteca dado que puede variar sustancialmente de una implementación a otra. Esta estrategia es útil porque no se genera un conjunto de servicios comunes para los objetos. Al contrario, cada servidor implementa ad hoc la funcionalidad mínima imprescindible para cubrir las necesidades del conjunto de objetos que reside en el nodo. Es decir, el código generado para cada servidor es esencialmente distinto al de cualquier otro dado que el conjunto de objetos y sus tipos determinan la mayor parte. i i i i i i i i 4. picoObjetos 107 El código generado no se puede considerar un ORB puesto que no están disponibles servicios habituales —pero exclusivos— que no tienen relación directa con los objetos. Tales servicios incluyen, por ejemplo, la indirección y localización de objetos. Sólo se responde a mensajes dirigidos específicamente a algún objeto alojado en el servidor. Como su nombre indica, la principal finalidad de los picoObjetos es la implementación de objetos, entendiendo el objeto como el ente pasivo que presta servicios bajo demanda (véase § 2.3.1). Sin embargo, resulta también muy conveniente dotar a los dispositivos de capacidades como clientes, es decir, la posibilidad de realizar invocaciones a otros objetos. Eso permite prestar servicios muy interesantes, como actualización asíncrona de observadores del transductor (véase § 3.4), anunciamiento de servicios (véase § 5.4), etc. Éstas y otras características se discutirán a lo largo del texto. Estas invocaciones deben ser oneway, es decir, no se espera ni se procesa respuesta alguna. Esa asunción simplifica la implementación pues no se requieren otros autómatas para reconocer cada una de las respuestas posibles. Aunque esta restricción resta algo de potencia y flexibilidad, el ahorro en complejidad resulta conveniente. Estas invocaciones se utilizan para informar a terceros y no para solicitar información. Teniendo en cuenta estos condicionantes, podríamos dar una definición informal de picoObjeto como: Una entidad autónoma capaz de procesar, responder y enviar invocaciones a métodos remotos conforme a un protocolo definido por un MDOO. Implementa una máquina de estados generada ad hoc para un dispositivo con acceso a una red de datos, que integra uno o más transductores y los ofrece al sistema como objetos distribuidos convencionales. 4.2. Una estrategia diferente Minimum CORBA (véase § 2.4.1) propone un modelo simplificado de ORB manteniendo interoperabilidad con la arquitectura CORBA. Aunque el alcance de los picoObjetos no está limitado a la norma CORBA y, como hemos visto, Minimum CORBA no es la única iniciativa de miniaturización, sí es un buen referente para comparar las prestaciones y limitaciones de la implementación de picoObjetos para CORBA (picoCORBA) y, por extensión, las de otros middlewares. Los objetos CORBA convencionales están conectados a un ORB que le proporciona los servicios básicos de comunicación. Los objetos Minimum CORBA se programan y utilizan del mismo modo. En contraste, los picoObjetos deben integrar ellos mismos todos los servicios proporcionados. Los sirvientes no se registran para ser accesibles; no existe un adaptador de objetos explícito, aunque sí un mapa de objetos rudimentario. Todo ello implica un gran ahorro de complejidad y memoria también respecto a Minimum CORBA. La figura 4.2 muestra de forma visual las diferencias de picoCORBA en relación a CORBA y Minimum CORBA. Veamos en qué medida cumplen los picoObjetos los objetivos de Minimum CORBA y las diferencias entre ambos: i i i i i i i i 108 4. picoObjetos F IGURA 4.2: Representación gráfica de CORBA (a), Minimum CORBA (b) y picoCORBA (c) Portabilidad – Un servidor escrito para Minimum CORBA se puede compilar y ejecutar en otro ORB sin ningún cambio. Por contra, un picoObjeto no tiene ningún soporte de portabilidad puesto que es monolítico y autocontenido. Las únicas bibliotecas con las que se enlaza serán las del runtime estándar y las del soporte de comunicaciones disponible en la plataforma objetivo. Interoperabilidad – Puesto que los servidores de picoObjetos implementan directamente el protocolo inter-ORB e interactúan directamente con el núcleo de comunicaciones del cliente, la interoperabilidad está garantizada. Soporte del lenguaje de especificación de interfaces – El compilador de picoObjetos incluye soporte para los tipos de datos básicos y para los mecanismos de composición como estructuras o secuencias. También proporciona soporte a tipos complejos concretos como identidades o proxies, dada su relevancia. Por supuesto, nuestro objetivo en la reducción de recursos va más allá que Minimum CORBA u otras iniciativas. Nos planteamos dos requisitos adicionales: Funcionalidad mínima – Definiendo el objeto mínimo que sigue teniendo un comportamiento compatible y respetando los requisitos imprescindibles de interoperabilidad, aunque en ocasiones puedan quedar acotados a una aplicación o entorno concreto. Dimensionamiento – Diseñando e implementando mecanismos que permitan adaptar y adoptar funcionalidades deseables aunque no esenciales según las capacidades de cómputo y memoria de la plataforma concreta. i i i i i i i i 4. picoObjetos 109 En relación a Minimum CORBA, los objetos picoCORBA hacen mucho más que reducir prestaciones. Éstos ofrecen un grado de portabilidad mucho menor dado que pueden implementarse en un lenguaje ensamblador específico. Incluso los que están implementados en C o Java no respetan en absoluto el mapping que define OMG. Algunos de estos lenguajes, incluso de propósito específico, ni siquiera han sido considerados por el estándar; por supuesto no existe ninguna implementación del middleware que ofrezca una biblioteca de soporte para esos lenguajes. 4.2.1. El objeto mínimo En lugar de buscar características prescindibles como medio para lograr la reducción de requerimientos hardware, decidimos plantear el problema desde el otro extremo, con una filosofía bottom-up. Definimos las características funcionales mínimas de la entidad lógica que podemos seguir considerando como objeto distribuido. A partir de ahí podremos evaluar la sobrecarga que supone añadir otras prestaciones que impliquen un mayor nivel de interoperabilidad y cumplimiento de la norma aplicable, o que supongan características funcionales adicionales. Aunque la plataforma objetivo son dispositivos muy pequeños y baratos, además de los dispositivos habituales en el mundo de las redes SAN, el modelo propuesto permite —en principio— implementar cada detalle de un núcleo de comunicaciones convencional de modo que la solución se podría aplicar a cualquier tamaño y complejidad. Sin embargo, utilizar el modelo de picoObjetos para una implementación completa de un núcleo de comunicaciones que cuente con adaptadores de objetos, serialización de tipos complejos, mecanismos de indirección, etc., podría llegar a ser complejo e ineficaz por la dificultad intrínseca para manejar un entorno dinámico, resultando una mala alternativa a la implementación de un ORB convencional. El único caso en el que se podría justificar dicho uso sería en entornos muy específicos en los que fueran cruciales las consideraciones de tiempo real o de confiabilidad, precisamente por la naturaleza estática y determinista del modelo de ejecución de los picoObjetos. A continuación se definen algunas consideraciones adicionales al conjunto mínimo de prestaciones generales anteriores: 1. Siempre se cumple el formato de mensajes del protocolo inter-ORB de cada middleware. Aunque puede haber mensajes no soportados, los que se soportan no sufren modificaciones. Consideramos que usar protocolos modificados (como el protocolo GIOPLite de MicroQoSCORBA [Hau01] o nORB [SXGC03]) conlleva necesariamente la utilización de pasarelas, responsables de la traducción de protocolos para lograr la interoperabilidad con los ORB S estándar. Ello supondría una contradicción a nuestra intención de hacer dispositivos directamente accesibles desde una red de comunicaciones común. 2. Únicamente se ofrece soporte a la versión más simple del protocolo, siempre que ello no repercuta negativamente en la interoperabilidad, por ejemplo, protocolos obsoletos. i i i i i i i i 110 4. picoObjetos 3. Los objetos que residen en un nodo están siempre activos (always on). No hay ningún modo de activar objetos adicionales o desactivar los que ya existen. 4.3. Interoperabilidad Existen gran cantidad de detalles que deben considerarse cuando se desea realizar una implementación empotrada de un middleware comercial convencional. Esta sección muestra cómo se han tomado en cuenta las restricciones específicas de dos middlewares distribuidos concretos para obtener implementaciones empotrables eficientes: CORBA e I CE. 4.3.1. picoCORBA En esta sección se explican las decisiones de diseño que se han tomado en picoCORBA respecto al formato de los mensajes y otras características del protocolo GIOP. Se analiza el soporte ofrecido para cada tipo de mensajes y sus implicaciones en la compatibilidad con el middleware. Todas las alusiones a GIOP se refieren al capítulo 15 de la especificación CORBA [COR02]; el anexo D es un resumen de dicho documento. Una primera medida para simplificar el proceso consiste en utilizar identidades de objeto (el campo object_key) de tamaño fijo, tal como hacen otras propuestas, por ejemplo, MicroQoSCORBA (véase § 2.4.8). La identidad aparece en la referencia pública del objeto (la IOR) y la norma especifica que los clientes deben utilizarla sin modificaciones. Es decir, no plantea ningún problema de interoperabilidad. Versión de GIOP Se ofrece soporte únicamente para GIOP versión 1.0. Aunque los clientes dispongan de soporte para versiones posteriores del protocolo, la especificación obliga al cliente a utilizar una versión igual o inferior a la que el servidor indique en la referencia del objeto. Por tanto, si el servidor (el objeto) opta por utilizar la versión 1.0, eso asegura compatibilidad total con cualquier cliente actual o futuro. Por la misma razón, cuando un objeto picoCORBA actúa como cliente, genera mensajes de petición con GIOP 1.0, lo que asegura que cualquier servidor podrá procesarlos adecuadamente. Las revisiones posteriores del estándar GIOP han añadido funcionalidades relacionadas con: Direccionamiento indirecto de objetos a otros ORB S. Fragmentación de mensajes. GIOP bi-direccional. Estas prestaciones quedan fuera de los objetivos marcados para picoObjetos. Resulta muy conveniente tener la posibilidad de obviarlas pues su implementación supondría un grave impacto sobre los requerimientos de memoria necesarios, puesto que la norma obliga además a cumplir todas las versiones inferiores. i i i i i i i i 4. picoObjetos 111 Ordenamiento La especificación GIOP indica que el extremo que inicia la comunicación determina cuál será el ordenamiento de bytes (big endian, little endian) mientras dure la conexión. En el caso de GIOP 1.0, el iniciador de la conexión es siempre el cliente. El servidor debe realizar la conversión cuando sea necesario y responder con el ordenamiento que use el cliente. Debido al enfoque minimalista del diseño de los picoObjetos, implementar ambos ordenamientos obliga a prácticamente duplicar el código necesario para el reconocimiento de los mensajes. Aunque puede incrementar sensiblemente la cantidad de código, si la aplicación lo requiere, tal posibilidad es perfectamente factible. Sin embargo, en la mayor parte de los casos, los picoObjetos se utilizarán para implementar nodos de una red instalada en un entorno acotado en los que este aspecto se puede controlar, pudiendo soportar sólo el ordenamiento necesario. Por tanto, incluso soportando únicamente uno de los ordenamientos, no habría problemas de interoperabilidad con los clientes, que pueden ser desarrollados de la forma habitual. CORBA::Object Todo objeto CORBA está obligado a implementar un conjunto de métodos comunes que corresponden a la interfaz heredada CORBA::Object (véase § 2.3.3). A pesar de que, desde el punto de vista del cliente, estos métodos se utilizan del mismo modo que los definidos en la especificación IDL, lo cierto es que el código asociado no tiene relación directa con el sirviente. En su lugar, el ORB o el esqueleto del servidor captura y responde estas invocaciones sin que lleguen al sirviente que implementa el programador. Aunque esta interfaz incluye bastantes métodos, algunos de ellos son atendidos de forma local por el ORB del cliente (duplicate(), release() o is_nil()). De entre los que requieren acceder al ORB remoto, el picoObjeto mínimo solo requiere implementar dos de ellos: non_existent() Permite a un cliente comprobar si el objeto sigue vivo. is_a() Ofrece prestaciones mínimas de introspección, necesarias para poder averiguar qué interfaces implementa un objeto una vez obtenido un proxy genérico. A diferencia de lo que ocurre en un ORB convencional, estos métodos son procesados y respondidos por el picoObjeto ya que no dispone de un ORB. Se genera una implementación automática que se incorpora implícitamente a cualquier objeto picoCORBA sin que el programador necesite indicar nada al respecto. Mensajes GIOP GIOP 1.0 define tres tipos de mensajes que el cliente puede enviar al servidor: Request, LocateRequest y CancelRequest, y tres más que el servidor puede enviar al cliente: i i i i i i i i 112 4. picoObjetos Reply, LocateReply y CloseConnection, más un mensaje MessageError que pueden enviar ambos ante una situación de error. Cabecera GIOP Los objetos picoCORBA reconocen y generan cabeceras GIOP estándar. La única peculiaridad es que el campo GIOP_version es siempre 1.0 y en la implementación mínima solo se soporta uno de los ordenamientos, por tanto, el campo byte_order es constante. Petición Los mensajes de petición (Request) son invocaciones de métodos del objeto remoto. Se toman las siguientes consideraciones: El campo service_context se ignora. El valor del campo response_expected se ignora. Los picoObjetos siempre generan respuestas aunque no se soliciten. Se trata de un comportamiento correcto porque los clientes ignoran a su vez respuestas no solicitadas. El campo requesting_principal está obsoleto y se ignora. Respuesta El objeto envía mensajes de respuesta (Reply) al recibir un mensaje de invocación y ejecutar con éxito el código asociado. Si el mensaje de petición es incorrecto, está mal formado o simplemente no coincide con lo que la máquina de estados espera, el objeto no responderá a esa petición y quedará a la espera del siguiente mensaje. En la versión mínima, picoCORBA no ofrece soporte para ningún tipo de excepción. La máquina aprovecha partes del mensaje de petición para construir el mensaje de respuesta, además de los valores de los parámetros de salida y valor de retorno que resultan de la ejecución del procedimiento de usuario correspondiente. Sobre los campos del mensaje: service_context – Se genera un contexto vacío. Opcionalmente se puede considerar un objeto que copia byte a byte el valor que tuviese este campo desde el mensaje de petición. request_id – Se copia el valor que llega en la petición. reply_status – Dado que no se soportan excepciones, el valor de este campo es siempre NO_EXCEPTION. Nótese que lo explicado se refiere al objeto mínimo. Es posible añadir soporte básico de excepciones para informar sobre objetos o métodos desconocidos. Cancelación de petición Los objetos picoCORBA ignoran completamente los mensajes de cancelación de petición (CancelRequest). El nodo procesa y ejecuta la operación solicitada a pesar de que el cliente envíe un mensaje de cancelación. La norma permite explícitamente este comportamiento. i i i i i i i i 4. picoObjetos 113 Localización Los mensajes de localización (LocateRequest/LocateReply) se utilizan para dar soporte a los mecanismos de transparencia de localización del middleware. Los picoObjetos no tienen por sí mismos capacidad para localizar otros objetos dado que esta característica correspondería a un hipotético ORB. Por tanto, ni se atienden ni se generan estos mensajes. Cierre de conexión El mensaje de cierre de conexión (CloseConnection) lo utiliza el servidor para indicar al cliente que dejará de estar disponible en breve. Esta situación no se contempla en picoCORBA puesto que se asume que los nodos en los que se ejecuta el picoObjeto están siempre conectados. Error Los mensajes de notificación de error (MessageError) sirven para indicar al emisor que la invocación que ha enviado es un mensaje incorrecto, mal formado o que corresponde a una versión de GIOP incorrecta. Dado que picoCORBA ignora los mensajes incorrectos o no soportados, tampoco genera este tipo de mensaje. Tampoco es capaz de procesarlos si provienen de un cliente. Tal circunstancia implicaría un fallo en la implementación del picoObjeto, y al ser ésta completamente estática no hay mucho que el nodo pueda hacer al respecto. Resumen Se muestra a continuación un breve resumen de las decisiones de diseño que se han expuesto en esta sección. Un servidor picoCORBA mínimo: Ignora todos los mensajes que no vayan dirigidos a uno de los objetos alojados en el nodo. Es decir, si la identidad del objeto que aparece en el mensaje no es una de las que se indicaron al generar la implementación, el mensaje de invocación se descarta silenciosamente. Solo soporta uno de los ordenamientos e ignora los mensajes que pueda recibir con un ordenamiento distinto. Únicamente implementa los métodos heredados is_a() y non_existent(). Ignora los mensajes CancelRequest, LocateRequest y MessageError y nunca genera CloseConnection ni MessageError. 4.3.2. picoIce En esta sección se explican las decisiones de diseño que se han tomado en picoIce respecto al formato de los mensajes y otras características del protocolo I CE P. Se analiza el soporte ofrecido para cada tipo de mensaje y sus implicaciones en la compatibilidad con el middleware. Todas las alusiones a I CE P se refieren al capítulo 38 del manual de referencia de I CE [HS08]; el anexo C es un resumen de dicho capítulo. A pesar de que actualmente tiene poco soporte para plataformas empotradas, I CE ofrece varias ventajas respecto a CORBA en la reducción del uso de recursos. El protocolo I CE es más simple que GIOP debido a varios motivos: i i i i i i i i 114 4. picoObjetos Los mensajes son siempre little endian. Soporta protocolos de transporte no confiables como UDP, mucho más sencillos de implementar en dispositivos empotrados de bajo coste. Existen menos tipos de mensajes y algunos de ellos pueden ser obviados sin comprometer la interoperabilidad. Los campos no procesados se pueden saltar fácilmente porque van precedidos por un campo que indica su longitud. No se realiza alineamiento de palabras al serializar los mensajes. ICE::Object Del mismo modo que con CORBA, todos los objetos I CE implementan por defecto la interfaz ICE::Object (véase § 2.3.4). Los objetos picoIce implementan todos los métodos remotos definidos en la interfaz por lo que está garantizado un comportamiento estándar también a ese nivel. Mensajes I CE P Los objetos picoIce soportan todos los mensajes I CE P exceptuando BatchRequest. Eso no supone ningún problema de interoperabilidad dado que el envío por lotes es únicamente una característica opcional para optimización del ancho de banda. Se utilizan cabeceras I CE P convencionales aunque el campo compressionStatus debe ser siempre 0 (no permitido). De nuevo, la compresión es una prestación opcional que de hecho no suele aplicarse a mensajes pequeños (menores de 100 bytes), que corresponden precisamente con los que nos interesan. Mensajes de petición Son muy similares a sus equivalentes CORBA. Existe un identificador de petición (requestId) que se utiliza para establecer la correspondencia entre peticiones y respuestas y que, por tanto, debe ser copiado al generar estas últimas. También existe un campo que indica la identidad del objeto cuyo tamaño se asume constante. Mensajes de respuesta Contienen los resultados en el caso de invocaciones twoway. Estos mensajes incluyen un campo replyStatus que tiene un valor 0 cuando la invocación es correcta. El objeto picoIce también es capaz de informar sobre un mensaje dirigido a un objeto inexistente (excepción 2) y de la invocación de un método no definido (excepción 4). Ver el cuadro 38.16 de [HS08] para obtener información más detallada. Mensajes de validación Cuando un servidor acepta una nueva conexión —lógicamente, con un protocolo orientado a conexión— lo primero que debe hacer es enviar un mensaje especial de reconocimiento ValidateConnection. Sólo cuando el cliente ha recibido dicho mensaje empieza a enviar mensajes de petición. Se trata de un mensaje pequeño formado únicamente por una cabecera (14 bytes) y todo su contenido es completamente estático por lo que no representa ningún problema para ser implementado en picoObjetos. De i i i i i i i i 4. picoObjetos 115 este modo se evitan situaciones que pueden llevar a dead-locks consumiendo recursos en el cliente cuando se utilizan distintos hilos para cada petición. Mensajes de cierre de conexión Del mismo modo, cuando un cliente deja de hacer peticiones al servidor, debe enviar un mensaje CloseConnection. El servidor también puede hacerlo para indicar al cliente que no aceptará nuevas peticiones. Los objetos picoIce responden a este mensaje, pero nunca lo envían. Estos dos mensajes no se utilizan cuando se emplea un protocolo de transporte no orientado a conexión. Funcionamiento del picoObjeto 4.4. El primer paso que debe realizar el programador para crear un picoObjeto es escribir un fichero en lenguaje FSM. A partir de éste, el compilador fsm2data genera un fichero que contiene el bytecode correspondiente, además de la especificación de la memoria necesaria, datos constantes, etc. Posteriormente, ese bytecode es susceptible de ser ejecutado por una máquina virtual de la que se han creado implementaciones para varias plataformas, tal como se verá en el Capítulo 8. Esta sección describe los detalles de dicho procedimiento y todos los elementos involucrados. 4.4.1. Máquina de estados El programa FSM citado anteriormente es la especificación de un autómata de estados finitos que se ha de crear a la medida de los objetos que alojará el nodo objetivo. La gramática y elementos léxicos concretos quedan determinados por: El formato de los mensajes del protocolo de comunicación inter-ORB definido por el middleware. Las identidades de los objetos alojados. Nótese que lo habitual será que varios objetos estén respaldados por el mismo sirviente. Esta técnica se denomina sirviente por defecto (default servant) cuando se aplica en middlewares convencionales. Las interfaces que implementa cada uno de los objetos. Eso implica conocer los nombres y tipos de los argumentos de entrada y salida de cada método. Los procedimientos de serialización definidos por el middleware (CDR en el caso de CORBA). Interfaces estándar heredadas por todos los objetos (CORBA::Object, Ice::Object, etc.). Para minimizar la cantidad de memoria necesaria, los mensajes de entrada se procesan en línea, es decir, en ningún momento se almacenan en la memoria del dispositivo. Pero no todas las transiciones entre los estados del autómata están determinadas por un único byte. En lugar de procesar el mensaje byte a byte, se precalculan sumas de comprobación (checksums) para secuencias de bytes que solo pueden tener unos valores i i i i i i i i 116 4. picoObjetos concretos y predecibles; tal es el caso de las identidades de objeto, las facetas y los nombres de los métodos. Por ejemplo, en el mensaje de petición, los nombres de los métodos y, en general, cualquier cadena de caracteres, va precedida por su tamaño. Una función puede leer y calcular un checksum para la cantidad de bytes indicada por ese tamaño. Como se conocen los valores de checksum que corresponden a cada uno de los métodos posibles, basta con comparar el resultado obtenido para determinar cuál es el método que está siendo invocado. El coste en memoria de esta operación solo requiere de 2 ó 3 bytes de memoria RAM dependiendo del tipo de checksum que se implemente. Obviamente esta técnica no resuelve todos los problemas. Hay partes del mensaje que deben ser almacenadas para su utilización posterior en la generación del mensaje de respuesta (p.ej. el identificador de petición), o deben estar disponibles durante la ejecución del método (p.ej. parámetros de la invocación). Otros campos simplemente pueden ignorarse porque no tienen efecto en la ejecución sea cual sea su valor (p.ej. campos obsoletos). Como ejemplo, la figura 4.3 ilustra una máquina de estados para dos objetos (sensor01 y actuator02) que implementan respectivamente las interfaces DUO::IByte::R y DUO::IBool::RW. Queda patente que el autómata debe realizar acciones muy concretas dependiendo del objeto y mensaje que está siendo recibido o enviado. Puesto que escribir a mano un programa FSM teniendo en cuenta todos esos detalles puede llegar a ser una tarea compleja y repetitiva, se ha diseñado un lenguaje de alto nivel (IcePick) y un compilador que ayudan a automatizar y simplificar sensiblemente el proceso. El capítulo 6 aborda la descripción de alto nivel para objetos empotrados utilizando dicho lenguaje. 4.5. Especificación de picoObjetos Las máquinas de estados para descripción de picoObjetos se definen por medio de un fichero FSM. Se trata de un lenguaje de programación diseñado al efecto. Es un DSL (Domain-Specific Language) basado en el lenguaje Python [Pyt], aunque sólo soporta un subconjunto muy reducido de la funcionalidad del mismo. Permite la creación de variables de los tipos básicos: entero, cadena, lista y tupla, y el uso de todos sus métodos. Un programa FSM está formado por los siguientes elementos, que se describen en las siguientes secciones: Banco de registros Variables Constantes Persistencia Un conjunto de bloques i i i i i i i i 4. picoObjetos 117 F IGURA 4.3: Ejemplo de una máquina de estados para dos objetos I CE sencillos 4.5.1. Gestión de los datos Como todo sistema de cómputo, un picoObjeto ejecuta un conjunto de instrucciones que operan sobre una colección de datos (constantes y variables) almacenadas en memoria. En esta sección veremos cómo se organizan y manipulan esos datos. Banco de registros El banco de registros es un array de bytes indexable por medio del juego de instrucciones FSM (véase § 4.5.3). Aunque todos los registros son accesibles para lectura y escritura en cualquier momento, hay algunos que tienen un uso predefinido: i i i i i i i i 118 4. picoObjetos 0. Registro de trabajo – Algunas instrucciones utilizan este registro como parámetro adicional y/o como ubicación para el resultado. 1. Longitud de la petición – Tamaño total del mensaje de invocación. Se determina a partir del campo correspondiente en la cabecera del mensaje y se utiliza para detectar errores en el formato del mensaje o resincronizar con el siguiente mensaje en caso de error. 2. Identificador de petición – Es un entero de 4 bytes que utiliza el cliente para comprobar la correspondencia entre el mensaje de petición que envía y el mensaje de respuesta que recibe. 3. Identidad – Se utiliza para almacenar la identidad del objeto sobre el que se realiza la invocación actual. El resto de los registros son de propósito general y se utilizan principalmente para el almacenamiento temporal de los parámetros y su uso concreto lo determina el compilador en cada caso. El banco de registros se ubica normalmente en la RAM del dispositivo y, por tanto, su contenido se perderá al ocurrir un corte en la alimentación. Es posible definir variables en el banco de registros asignando identificadores a los índices del array. Estas variables pueden tener tamaño arbitrario. Para que las funciones del sirviente puedan localizar la situación de los parámetros se construye un mapa de parámetros. Es un vector que indica en qué registro comienza cada uno de los parámetros de entrada/salida que toman los métodos de los objetos. El mapa de parámetros se ubica al comienzo de la zona DATA, dado que las cantidades y tamaños de los parámetros son datos que se pueden obtener en tiempo de compilación y, por ello, pueden ser almacenados estáticamente. En un programa FSM, el banco de registros se utiliza como un objeto (bank) con la siguiente interfaz1 : byte alloc(byte n) Reserva espacio para una variable en el banco de registros. El parámetro n indica el tamaño en bytes que debe tener la variable. El método retorna el índice del primer registro asignado a la variable (su dirección). Este valor se puede asignar a un identificador para después utilizar esa variable en el programa. byte alloc(str val) Si se invoca el método alloc() pasando una cadena de caracteres, se obtiene una variable de tamaño igual al de dicha cadena y se copia la cadena en él. byte alloc(list val) Si el parámetro de alloc() es una lista, los elementos de dicha lista se convierten a una secuencia de bytes y se procede como en el caso anterior. init(var, [values]) Asigna valores iniciales a los registros. El parámetro var es el identificador de la variable (o el número de registro), el parámetro values es una lista con los valores que se deben asignar a cada byte de la variable. 1 Los tipos indicados son meramente descriptivos puesto que Python no permite forzarlos en la signatura de las funciones. i i i i i i i i 4. picoObjetos 119 El listado 4.1 muestra cómo reservar espacio en el banco de registros desde un programa FSM: request_len request_id identity param_map param0_len param0 socket_1 = = = = = = = bank . alloc (1) bank . alloc (4) bank . alloc (5) bank . alloc (2) bank . alloc (1) bank . alloc (2) bank . alloc ([ ’T ’ , ’ 127.0.0.1 ’. ljust (15) , [208 , 7]]) L ISTADO 4.1: Ejemplo de uso de las funciones del banco de registros Variables auxiliares Se utilizan para fabricar trozos de los mensajes que se emplearán posteriormente. También para calcular tamaños o definir valores simbólicos. Las variables únicamente se utilizan como almacenamiento auxiliar en tiempo de compilación, pero no forman parte del autómata a menos que sea copiado en las zonas DATA o Flash. Para crear una de estas variables basta asignar un valor a un identificador. El listado 4.2 muestra ejemplos de variables FSM. TIMER_EVENT = 4 var_I ce_Objec t = lit ( ’:: Ice :: Object ’) L ISTADO 4.2: Ejemplos de variables FSM Constantes, zona DATA Son fragmentos de mensajes, normalmente para la generación de respuestas e invocaciones, aunque también se pueden utilizar para reconocimiento de mensajes entrantes. Cuando se programa el dispositivo, los valores definidos en la zona DATA deberían colocarse en memoria de sólo lectura puesto que son constantes a todos los efectos. Para introducir valores en la zona DATA se utiliza el objeto data, que funciona de modo muy similar a bank (ver listado 4.3). Cuando se introduce un valor en la zona DATA automáticamente se antepone un byte adicional que contiene el tamaño de la secuencia. Por ejemplo, en el listado 4.3, la asignación para la sentencia id_ob1 almacena en realidad los valores 3, 8, 12 y 10 en la posición correspondiente. Los valores se ubican en memoria en el mismo orden en el que se escriben estas asignaciones en el fichero fuente, precedidos de su tamaño. Debido a que se direcciona por medio de un registro de 1 byte, la cantidad total de la zona DATA no puede exceder los 256 bytes, y es obvio que tampoco puede hacerlo ningún elemento almacenado en ella. IceHeader = data . alloc ( ’ IceP ’ , 1 , 0 , 1 , 0) id_ob1 = data . alloc (8 , 12 , 10) L ISTADO 4.3: Ejemplos de constantes FSM (zona DATA) i i i i i i i i 120 4. picoObjetos Persistencia, zona Flash En la zona Flash se almacenan valores que pueden cambiar, pero que lo harán con poca frecuencia y que además es conveniente conservar ante reinicios del dispositivo o eventuales fallos de alimentación. Tal es el caso de las direcciones (endpoints) de objetos remotos que deben ser invocados por el picoObjeto. Otro caso interesante ocurre cuando el nodo debe conseguir su propia dirección después del arranque y necesita almacenarla para comunicarla a otros servicios. La sintaxis y estructura de almacenamiento es análoga a la de DATA. 4.5.2. Utilidades auxiliares Al escribir un programa FSM, el programador dispone de algunas funciones que facilitan tareas comunes. Son: byte digest(byteseq) Retorna el valor de la suma de comprobación. Como parámetro se le puede pasar un número arbitrario de valores de tipos entero, cadena, o tuplas y listas de estos. Internamente la función convierte todos esos parámetros en una lista de bytes a la que aplica el algoritmo para obtener la suma de comprobación. Literal lit(byteseq) Es una función factoría que crea un objeto Literal a partir de los parámetros. El Literal es un tipo que almacena una secuencia de bytes constante y que, bajo demanda, puede ser precedida automáticamente por su tamaño. 4.5.3. Repertorio de instrucciones FSM FSM es una arquitectura de repertorio de instrucciones virtual (V-ISA). Se trata de instrucciones muy especializadas para el reconocimiento y generación de elementos léxicos. Y aunque se puede conseguir cierta versatilidad, las tareas principales para las que ha sido diseñado son: Lectura/escritura de un byte en la interfaz de red. Lectura/escritura de una secuencia de bytes precedida por el tamaño de ésta. Lectura de una secuencia de bytes de la que se conoce de antemano el valor de una suma de comprobación y el tamaño. Movimiento de datos entre registros y operaciones aritméticas básicas. Definición de etiquetas e instrucciones de salto para control del flujo de ejecución. Gestión de eventos síncronos/asíncronos. Ejecución de rutinas aportadas por el programador del dispositivo (sirvientes). Gestión de conexiones activas/pasivas. La especificación del repertorio de instrucciones, sus formatos y modos de direccionamiento se explican detalladamente en el anexo A. i i i i i i i i 4. picoObjetos 4.5.4. 121 Bloques Las instrucciones FSM han de incluirse siempre en algún bloque. La utilidad real del bloque es definir un punto de entrada (una etiqueta) que sirve como destino para las instrucciones de salto, ejecución de funciones, subrutinas o manejadores para eventos. En todos esos casos se utiliza el nombre de un bloque como parámetro de la instrucción, tal como hemos visto en el juego de instrucciones. El proceso de compilación traduce cada etiqueta por la dirección que ocupa la primera instrucción de cada bloque. Nótese que las instrucciones se ejecutan siempre de forma secuencial y, a menos que exista un salto, la ejecución continuará en el bloque subsiguiente. El listado 4.4 muestra tres de estos bloques e ilustra este hecho. La ejecución del bloque replyIds implica siempre la ejecución posterior del bloque replyId. Existe un bloque especial —llamado init por convenio— que es siempre el primero que aparece en el programa y el que obtiene el control cuando arranca el dispositivo. En este bloque recae la responsabilidad de la inicialización de los periféricos o cualquier otra tarea como, por ejemplo, la obtención de la dirección de red si es dinámica. Dado que estas tareas normalmente son específicas de cada plataforma, este proceso implica la ejecución de procedimientos de usuario proporcionados por el programador del dispositivo. def init () : user_proc ( PROC_INIT ) set_event ( ’ validate ’ , IN COMING_E VENT ) set_event ( ’ main ’ , RESET_EVENT ) reset () def replyIds () : put_data ( Ice_Object ) put_data ( DUO_IBool_R ) put_data ( DUO_IBool_W ) def replyId () : put_data ( DUO_IBool_RW ) goto ( ’ ice_close ’) L ISTADO 4.4: Algunos bloques de ejemplo de un programa FSM 4.5.5. Subrutinas Las subrutinas permiten ejecutar un bloque volviendo al punto de llamada una vez terminada la ejecución del mismo. Para ello se utiliza la instrucción call() indicando el nombre de un bloque. El bloque invocado debe tener una instrucción ret() (normalmente al final); sin embargo, ésta será ignorada si el flujo de ejecución llega a ella de otro modo (mediante goto). Así pues, un mismo bloque se puede utilizar como subrutina o como etiqueta de salto dependiendo de la instrucción que se utilice para llegar a él. No existe pila, sólo hay un puntero de retorno, por lo que no es posible ejecutar subrutinas de forma anidada. i i i i i i i i 122 4. picoObjetos 4.5.6. Eventos El funcionamiento del picoObjeto está dirigido por eventos , ya sean síncronos (lanzados explícitamente) o asíncronos (provocados por una señal externa). Los eventos se representan con un valor entero único, aunque en el código fuente FSM se asocian a un identificador para facilitar su lectura. Gracias al uso de eventos se consiguen varias prestaciones interesantes: Mínimo acoplamiento No hay ninguna dependencia entre la generación del evento y su tratamiento. Ambos procesos ocurren en partes distintas del programa. La instrucción set_event() asocia un evento con su manejador (un bloque). Esta instrucción se puede invocar desde cualquier parte del programa, de modo que el manejador de un mismo evento se puede modificar cuando se requiera. Fácilmente extensible Resulta trivial añadir eventos y manejadores nuevos y no requiere ningún soporte ni modificaciones adicionales. De hecho, no se trata de algo excepcional, es bastante habitual que cada objeto necesite añadir sus propios eventos. Ejecución lineal El manejador no es ejecutado inmediatamente después de producirse el evento. En su lugar, se marca una bandera y cuando han terminado las tareas pendientes, se atienden los eventos en orden de prioridad. Por ese motivo, la ejecución de los manejadores es lineal y no puede ser interrumpida. Esto simplifica sensiblemente la implementación de la máquina virtual y facilita su depuración. Hay varios eventos que se utilizan prácticamente en cualquier programa y por ello tienen nombre, valor y finalidad predeterminada: RESET_EVENT El manejador asociado a este evento es utilizado internamente como dirección de salto al terminar la ejecución de la instrucción reset(). Es decir, asocia un bloque (por convenio llamado main) como punto de salto después de reiniciar la máquina de estados. Normalmente ese bloque es el que hace el reconocimiento de la cabecera de los mensajes entrantes. En la mayor parte de los programas FSM aparece una sentencia set_event(‘main’, RESET_EVENT) en el bloque init. INCOMING_EVENT Este evento lo produce la máquina virtual cuando detecta una conexión entrante. Como respuesta ejecutará el bloque asociado como manejador. Esta funcionalidad se requiere para contemplar casos como el mensaje de validación de conexión de I CE (véase § C.3.5). ERROR_EVENT Cuando se detecta un error de reconocimiento, la máquina de estados ejecuta el manejador programado para este evento. Su misión debe ser sincronizar el autómata con el siguiente mensaje de entrada, cerrar las conexiones abiertas, etc. Este manejador termina ejecutando la instrucción reset(). i i i i i i i i 4. picoObjetos 123 Los timers están también relacionados con los eventos. Cada timer está representado por un evento que se lanza cuando el tiempo asociado llega a 0. El manejador del timer es un bloque al igual que cualquier otro evento. El programador también puede definir y utilizar sus propios eventos, que puede disparar desde el código del sirviente. Resultan especialmente adecuados para modelar el comportamiento de sensores que pueden detectar cambios en el entorno físico. El dispositivo puede instalar una RSI para la interrupción correspondiente y utilizar esa rutina para disparar el evento FSM. El picoObjeto como reactor Tomando en cuenta estas consideraciones, podemos ver el picoObjeto como una implementación del patrón de diseño reactor [GHJV96]. Es una máquina dirigida por eventos dado que materializa la especificación de un autómata de estados finitos. A partir del estado de reposo pueden ocurrir las siguientes situaciones: Una conexión pasiva. Se considera como una activación del evento INCOMING_EVENT y desencadena la ejecución del manejador registrado. Llegada de un byte por la interfaz de red. Este hecho sólo se considera como evento si es el primero del mensaje. El bloque que está en ejecución en espera de ese primer byte corresponde al manejador registrado para el evento RESET_EVENT. Expiración de un timer. Se dispara la ejecución del manejador asociado. La activación de un periférico del dispositivo (un sensor) genera una interrupción. El identificador de dicho evento debe estar especificado en el fichero FSM y como con cualquier otro evento, se debería haber registrado un manejador. Tratamiento de eventos Los eventos pueden producirse en cualquier momento: asíncronos si se trata de un evento asociado a un sensor o la invocación de un mensaje, o síncronos si el propio código incluye la instrucción raise_event(). Sin embargo, los eventos no se atienden en el mismo instante en que se producen, sufren un pequeño retardo debido a que sólo se comprueban cuando se ejecuta una instrucción de lectura o durante un reset(). Aunque la forma de implementar el registro de eventos pendientes dependerá de cada máquina virtual concreta, el modo más sencillo es un vector de banderas booleanas. El identificador de cada evento determina la posición de la bandera en este vector. Si se produce el evento se marca activando la bandera correspondiente, y cuando se atiende un evento se desactiva su bandera. La prioridad queda determinada también por la posición de su bandera en el vector. El evento (RESET) es el más prioritario (evento 0). No se atienden eventos menos prioritarios aunque se produjeran antes. Implementarlo de este modo tiene algunas consecuencias deseables, en aras de la simplicidad: Los manejadores de eventos no pueden anidarse, de modo que la ejecución de sus manejadores es secuencial y por prioridad. i i i i i i i i 124 4. picoObjetos Si se produce un mismo evento antes de que pueda ser atendido, el manejador sólo se ejecutará una vez. Esto debe ser tenido en cuenta por el programador de tener implicaciones indeseadas para ciertas aplicaciones concretas. En las plataformas con menos recursos, el vector de banderas para los eventos se puede implementar utilizando los bits individuales de una palabra, con lo que un solo byte sirve para representar ocho eventos, más que suficiente para muchos transductores sencillos. 4.5.7. Sirvientes, código de usuario Como en cualquier middleware de comunicaciones, la invocación de un procedimiento o método remoto desencadena la ejecución de código vinculado a la aplicación específica que se está desarrollando y que, por tanto, debe ser proporcionado por el programador; de ahí la denominación de código de usuario. El conjunto de procedimientos relacionados como métodos de un mismo objeto (en el caso de los MDOO) se denomina sirviente (véase § 2.3.1). Como el objetivo es poder implementar picoObjetos en una amplia variedad de dispositivos y plataformas, tanto la máquina virtual que ejecuta el bytecode como el propio código de usuario deben estar escritos en un lenguaje soportado por la plataforma específica. Para desacoplar al máximo máquina virtual y sirviente, se asigna un simple identificador entero a cada procedimiento de usuario y por medio de la instrucción user_proc se determina cuál ejecutar. La implementación de esa instrucción la debe proporcionar el programador. Esta instrucción es responsable de las siguientes tareas: Recuperar el identificador del procedimiento a ejecutar. Acceder a los parámetros de la invocación desde el banco de registros. Dejar el valor de retorno y parámetros de salida en esos mismos registros. Paso de parámetros La máquina de estados lee y almacena los parámetros de tamaño fijo (bool, byte, int, float, etc.) en el banco de registros. Cada parámetro requiere un byte que indica el tamaño del parámetro y a continuación el valor del mismo. El sirviente puede determinar dónde empieza cada parámetro utilizando el mapa de parámetros ubicado en la zona DATA (véase § 4.5.1). Los parámetros de tamaño variable, como string, identidades de objeto, proxies y otros tipos permitidos reciben un tratamiento muy especial. Dado que no se puede determinar su tamaño hasta el momento de su llegada, no es posible decidir cuántos bytes deberían reservarse en el banco de registros. Por otro lado, se pretende que el banco sea lo más pequeño posible. Por limitaciones de direccionamiento nunca puede ser mayor de 256 bytes; en muchas plataformas concretas está limitado a 128 bytes, dado que esa es la RAM disponible. La mayoría de las implementaciones de los prototipos realizados requieren menos de 64 bytes. Para el tratamiento de parámetros de tamaño variable el programador debe proporcionar rutinas específicas que serán invocadas por la máquina de estados en el momento i i i i i i i i 4. picoObjetos 125 oportuno. Estas rutinas se encargan de leer/escribir los parámetros directamente desde el dispositivo de red y almacenarlos en memoria gestionada por su cuenta, fuera del banco de registros de la máquina virtual. 4.5.8. Bytecode A partir de un fichero fuente FSM individual, el compilador fsm2data genera un fichero de bytecode (ver listado 4.5) compuesto básicamente por cuatro secuencias de bytes: fsmCode Contiene los equivalentes numéricos de las instrucciones FSM del fichero fuente y los valores de sus parámetros (ver § 4.5.3 y § 4.5.4). Es simplemente un array, una secuencia unidimensional que, durante la programación del dispositivo, se copia directamente a memoria de sólo lectura. El código se genera en el mismo orden en el que las instrucciones están escritas en el fichero fuente sin necesidad de marcas entre bloques. fsmData Contiene los datos almacenados en la zona DATA (véase § 4.5.1). El proceso de instalación en el dispositivo es responsable de ubicar estos datos bajo la premisa de que nunca necesitarán ser modificados por el programa en ejecución (ROM). fsmFlash Los datos de la zona Flash, como su nombre indica, deben ir a una memoria Flash u otro dispositivo de almacenamiento persistente. fsmBank Contiene los valores iniciales para los registros (véase § 4.5.1). Además, su tamaño indica cuántos registros serán necesarios. El formato del fichero que contiene el bytecode depende del lenguaje de programación en el que esté implementada la máquina virtual. Es posible generar el mismo bytecode en Java, Python, C y ensamblador de la familia MicroChip PIC. Dependiendo también de la plataforma y lenguaje objetivo, el fichero del bytecode puede contener otros datos: Etiquetas de inclusión Se trata de una lista con los nombres de las instrucciones que realmente se utilizan en el programa FSM. Cuando se genera C, se utilizan cláusulas #define del preprocesador, lo que permite generar una implementación completamente especializada en la que ni siquiera se incluye el código de las instrucciones innecesarias, con el consiguiente ahorro en tamaño de memoria de programa. Cadenas de depuración Si la plataforma objetivo soporta log para depuración —instrucción debug()— el fichero de bytecode puede incluir el texto correspondiente como una secuencia de cadenas. Sólo las implementaciones de la máquina virtual que se ejecutan sobre un PC disponen de esta posibilidad. i i i i i i i i 126 4. picoObjetos fsmCode = [ 26 , 0, 6, 1, [...] 103 , 4, 211 , 4, 182 , 4, 26 , 17 , 1, 3, 6, 6, 1, 8, 1 , 229 , 1 , 61 , 38 , 0 , 191 , 228 , 0 , 252 , 2, 4, 4, 1, 2, 1, 0 , 183 , 0 , 199 , 1] fsmData = [ 6, 4, 4 , 84 , 4 , 76 , [...] 118 , 101 , 85 , 79 , 108 , 58 , 76 , 80 , 79 , 79 , 67 , 67 , 67 , 49 , 50 , 49 , 0, 0, 82 , 58 , 58 , 17 , 58 , 82 , 16 , 73 , 87] 58 , 58 , 68 , 66 , 111 , 111 , fsmBank = [ 0, 0, 0, 0, 0, 0, 50 , 55 , 32 , 32 , 0, 0, 0, 46 , 32 , 0, 0, 0, 48 , 32 , 0, 0, 0, 46 , 32 , 0, 0, 15 , 18 , 18 , 84 , 48 , 46 , 32 , 208 , 0, 0, 7, 7, 6, 0, 0, 0, 49 , 49 , 7] L ISTADO 4.5: Parte del bytecode resultante de la compilación de un programa FSM 4.5.9. Limitaciones y saltos Al estar diseñado para dispositivos de cómputo muy simples, todas las direcciones y registros corresponden a una máquina de 8 bits. Y por ello, los tamaños de memoria y código quedan limitados. Las tres zonas de memoria (banco de registros, DATA y Flash) pueden tener un máximo de 256 bytes cada una. También las variables y los mensajes que puede recibir el objeto están limitados a ese tamaño. Estos tamaños máximos son asumibles puesto que en muchos casos los microcontroladores que consideramos como objetivo tienen aun menos recursos. Sin embargo, 256 palabras de bytecode es insuficiente. Para paliar este problema se permite que las instrucciones de salto tengan direcciones de 2 bytes. Se utiliza un espacio de memoria de programa segmentado. El primer byte de una dirección indica una página y el segundo un desplazamiento dentro de la misma. Cada página tiene 256 palabras y puede haber tantas como permita el almacenamiento del dispositivo hasta un máximo de 256 × 256 = 64KiB que supera con creces la cantidad de memoria de programa necesaria para el tipo de aplicaciones que nos planteamos. El mismo sistema podría aplicarse a las zonas de memoria de datos, aunque aumentaría el tamaño de todas las instrucciones al requerir direcciones de 16 bits. La implementación de transductores simples es perfectamente compatible con las limitaciones que plantea la máquina de 8 bits, con el ahorro que implica. En cualquier caso, éstas son limitaciones del bytecode, no del repertorio FSM. Un bytecode y una máquina de 16 bits resultarían adecuados para servicios más complejos como encaminadores (capítulo 7), bridges, propagación de eventos, etc. Los requerimientos i i i i i i i i 4. picoObjetos 127 funcionales de tales servicios pueden sobrepasar fácilmente las prestaciones de cualquier microcontrolador de 8 bits. 4.6. Transformación de FSM a bytecode En las secciones anteriores se ha descrito tanto el lenguaje FSM como el bytecode equivalente. Esta transformación la realiza el compilador/traductor fsm2data. Es necesario puntualizar ciertos detalles no triviales de este proceso. El lenguaje FSM es un programa Python muy restringido. El proceso de compilación comienza ejecutando ese programa con un intérprete de Python estándar, pero dentro de un entorno modificado, que contiene los objetos y funciones Python especiales comentados anteriormente (bank, data, flash, lit, etc.). Dicho entorno también contiene las instrucciones del repertorio implementadas como métodos de un objeto. Éstos realizan la transformación de cada instrucción y sus parámetros a su equivalente en bytecode, que se almacena programáticamente utilizando una representación abstracta. Su representación definitiva depende del lenguaje que requiera la plataforma objetivo. 4.6.1. Optimizaciones Al analizar el bytecode resultante vemos que, de media, ocupa menos de 4 páginas (unas 450 palabras). Es fácil comprobar que muchos de los saltos tienen como destino bloques de la misma página. Es decir, solo los saltos que se refieren a bloques de otras páginas necesitarían realmente indicar la página. Es por ello que se definen dos tipos de saltos: Salto corto Cuando el destino es un bloque de la misma página en la que está la instrucción de salto. El único byte de la dirección indica el desplazamiento dentro de la página actual. Salto largo Cuando el destino es un bloque de otra página. La dirección tiene el formato que se ha indicado más arriba: el primer byte indica la página y el segundo es el desplazamiento respecto a aquella. Las instrucciones de salto necesitan distinguir qué tipo de salto deben efectuar. La solución es sencilla: leen el primer byte de la dirección, si su valor es menor o igual al número de páginas (p) se entiende que indica una página y, por tanto, es un salto largo; a continuación, lee el siguiente byte para determinar el desplazamiento. Si el valor es mayor a p, se interpreta como un salto corto y ese valor indica el desplazamiento dentro de la página actual. La consecuencia es que no se puede indicar un salto corto a un bloque cuyo comienzo esté en los primeros pbytes de una página; en esos casos es necesario utilizar un salto largo. Estadísticamente eso ocurre con muy poca frecuencia de modo que la sobrecarga adicional es muy baja. i i i i i i i i 128 4. picoObjetos Fragmentación de instrucciones Con el fin de simplificar aún más la implementación de la máquina virtual, se asume que la lógica que gestiona el cambio de página al leer el bytecode solo está disponible al cargar una nueva instrucción, y no durante la carga de los operandos. Para que eso sea posible, toda la instrucción incluyendo sus operandos debe estar en la misma página. Es responsabilidad del compilador de FSM reubicar el código para evitar esa situación. De ahí la existencia de una instrucción nop. Se utiliza como relleno al final de una página de modo que la siguiente instrucción quede alineada a la siguiente página. Dado que la instrucción más larga tiene 4 bytes, en el caso peor se introducirían solo 3 instrucciones nop. Conversión de direcciones El compilador construye un mapa de memoria a partir de las instrucciones asignando direcciones a cada instrucción en función de su tamaño y número de parámetros. Cuando todas las instrucciones están ubicadas traduce la etiqueta de cada bloque por la dirección asignada a su primera instrucción. Inicialmente todos los saltos son largos (véase § 4.5.9). En una segunda pasada, el compilador substituye los saltos largos por cortos cuando la dirección destino está en la misma página. Al eliminar datos del bytecode, las direcciones de los bloques subsiguientes cambian (a un valor menor), por lo que requiere modificar también dichas direcciones en las instrucciones de salto y llamada a subrutinas. Al modificar las direcciones puede ocurrir que un bloque al comienzo de una página pase al final de la página anterior. Eso tiene importantes consecuencias, puesto que los saltos cortos a ese bloque de su página original deben convertirse de nuevo en largos, y los cortos en la página destino pueden ahora convertirse en largos, de modo que todo el proceso debe comenzar de nuevo. Se trata de un problema de equilibrio típico que se resuelve con programación dinámica. Reordenación de bloques Exceptuando el bloque init (que debe ser el primero), los bloques FSM pueden estar en cualquier parte del código. Pero, en el proceso de traducción, el bytecode se genera respetando el orden del fichero original. Por ello ese orden, aunque funcionalmente irrelevante, conlleva la generación de bytecodes distintos, dependiendo de las posibilidades de optimización de los saltos. El compilador fsm2data puede reordenar los bloques buscando la situación que haga posible una solución óptima, es decir, minimizando el número de saltos largos necesarios. Otra pequeña optimización a tener en cuenta es la aparición de un salto al bloque siguiente. Por diseño, al alcanzarse el final de un bloque, el flujo de ejecución continúa en el siguiente bloque a menos que haya una instrucción de salto (véase § 4.5.4). El compilador debe favorecer esta situación a fin de poder eliminar saltos incondicionales cuando se producen al final de un bloque. i i i i i i i i 4. picoObjetos 4.6.2. 129 Generación del bytecode La generación del bytecode concreto para un lenguaje destino se realiza por medio de una implementación del patrón de diseño builder [GHJV96]. 4.7. Máquina virtual El bytecode generado está diseñado para ser independiente de la plataforma. Obviamente, se necesita una implementación de la máquina virtual para el dispositivo concreto. Ésta se encarga de ejecutar las instrucciones codificadas y acceder a los datos necesarios. El modelo de máquina virtual ofrece varias ventajas: Facilita la incorporación de nuevos dispositivos y plataformas. Únicamente se requiere implementar la máquina virtual sobre la nueva plataforma. No tiene ningún impacto sobre el proceso de compilación de FSM ni sobre las herramientas de alto nivel. Simplifica la depuración. Al disponer de una implementación de la máquina virtual para PC se pueden reconstruir situaciones que puedan aparecer en cualquier aspecto o eventualidad de la comunicación de un dispositivo con el exterior. Hace posible la re-programación remota. Al utilizar una máquina virtual, es posible distribuir nuevas versiones del bytecode incluso con el sistema en producción (véase § 4.9). La implementación de la máquina virtual para una nueva plataforma no requiere un esfuerzo considerable precisamente porque se ha hecho incapié en conseguir un diseño tan simple como ha sido posible. Las prestaciones que debe ofrecer una implementación de la máquina virtual son: Gestión y alojamiento del banco de registros y las zonas de datos DATA y Flash. La implementación decide si es posible y/o conveniente aprovechar las necesidades de cada zona. Por ejemplo, si el dispositivo no cuenta con memoria Flash u otro tipo de persistencia puede utilizar memoria RAM, aunque debe avisar para evitar las consecuencias que ello pudiera acarrear. Funciones para la ejecución de las instrucciones del repertorio. La mayoría son realmente simples. La implementación de repertorio completo no supera las 200 SLOC de código en lenguaje C. Vector de banderas para gestión de eventos. Una posible implementación se esboza en la sección 4.5.6. Gestión de tiempo para los timers. Lectura/escritura desde la interfaz de red. Ejecución de métodos del sirviente. i i i i i i i i 130 4. picoObjetos 4.7.1. Comunicación con el sirviente La especificación del autómata se encarga de colocar los parámetros de entrada en el banco de registros e invocar la instrucción user_proc(). Desde ese código, el programador puede acceder a cualquier componente lógico del dispositivo: banco de registros, ROM, etc. También dispone de soporte para leer y escribir en la interfaz de red, pero no para acceso a periféricos. Esa es precisamente la responsabilidad principal del sirviente. 4.8. Generación de código nativo La alternativa al binomio máquina virtual + bytecode es generar un programa completo ad hoc. Es posible plantear esta opción con un compilador que genere código nativo directamente a partir del código FSM. Las ventajas principales de este enfoque son la reducción de tamaño del programa y la sobrecarga que implica el código que carga e interpreta el bytecode. También implica un sensible aumento en la complejidad de adaptar la solución a nuevas plataformas y la pérdida de todas las ventajas que aparecen en la sección anterior. La depuración del intérprete de una máquina virtual es muy sencilla; se pueden realizar baterías de pruebas para cada instrucción ante escenarios diferentes. Sin embargo, la depuración y prueba de un generador de código para un lenguaje y arquitectura concreta resulta mucho más complicada y no es fácil extrapolar su funcionamiento a una arquitectura PC, que es significativamente más amigable para el proceso de desarrollo y depuración. 4.9. Despliegue de aplicaciones en la SAN picoGrid es nuestra propuesta para despliegue de aplicaciones en la SAN. Es posible reprogramar el funcionamiento de un picoObjeto sin más que enviar una nueva versión del bytecode. Éste incluye la definición de los objetos alojados en el nodo y sus tipos, pero también tratamiento de eventos y relaciones entre objetos que permiten especificar servicios sencillos, como se verá en el capítulo 6. Los requisitos para permitir despliegue remoto con picoGrid son: FSM en memoria reescribible. Se debe almacenar el código FSM en memoria Flash o EEPROM en lugar de ROM. Utilizar únicamente drivers como sirvientes. El código de los sirvientes no se despliega en la red dado que es dependiente de la plataforma. El nodo debe disponer de los drivers necesarios para manipular todos sus sensores y actuadores, aunque en un primer momento no los necesite. Máquina virtual completa. Aunque está prevista la posibilidad de no incluir en el dispositivo la implementación de instrucciones no utilizadas, esta optimización no es posible si se desea reprogramación remota. Para que un nodo pueda ser reprogramado necesita además un objeto especial (el picoNode) que atenderá las solicitudes para envío de código nuevo. Es un objeto i i i i i i i i 4. picoObjetos 131 especificado del mismo modo que cualquier otro usando código FSM. Eso significa que una nueva versión del bytecode podría eliminar el picoNode impidiendo futuros despliegues. Si se desea evitar esta posibilidad es necesario almacenar el bytecode de ese objeto en memoria ROM y garantizar que podrá seguir accesible. 4.10. Conclusiones Como vimos en el capítulo 2, existen varias propuestas que utilizan máquinas virtuales para la implementación de lógica de control y comunicaciones en dispositivos asociados a transductores de una red SAN. El repertorio de instrucciones FSM, a diferencia de Maté [LC02], no está orientado a la especificación del sirviente, sino al protocolo de comunicaciones y las relaciones con otros servicios. Maté está limitado a plataformas MICA con sistema TinyOS. Sus instrucciones se refieren específicamente a los sensores de estas plataformas y su diseño es difícilmente generalizable. Sin embargo, la máquina FSM se puede implementar sobre prácticamente cualquier dispositivo de cómputo con capacidad de red. No está ligado a ningún protocolo o middleware concreto dado que las instrucciones son de más bajo nivel y, por tanto, mucho más flexible. Ciertamente, el diseño del repertorio está especializado en protocolos binarios similares a GIOP, pero su diseño permite extensiones del repertorio para dotarlo de instrucciones especializadas en protocolos tipo XML sin pérdida de generalidad, con la ventaja añadida de que es posible eliminar de la máquina virtual las instrucciones no utilizadas. WSP [BLV09] también está ligado a la plataforma y algunas de las instrucciones virtuales de su repertorio son de un nivel de abstracción mucho mayor que las que se propone para los picoObjetos. Por ejemplo, incluye instrucciones para: establecimiento de rutas, encaminamiento de mensajes, encender/apagar un LED. Por contra, el repertorio FSM no presupone la existencia de ningún periférico concreto en el nodo, de la utilización de protocolo concreto, etc. Tanto WSP como el picoObjeto proponen un modelo de control por eventos, pero mientras el primero determina por diseño la existencia de servicios concretos e inmutables en el nodo, el picoObjeto es un sistema que permite definirlos y construirlos específicamente para un nodo concreto. Otra gran diferencia es que WSP propone un modelo de macro-programación, mientras que en nuestro caso ésta es una decisión de alto nivel, sin relación con el funcionamiento de la máquina virtual. Nuestra propuesta guarda ciertas similitudes con SensorWare [BHSS07]. El modelo en capas que propone, definiendo interfaces para drivers y servicios del SO, hace posible implementar el sistema sobre múltiples plataformas. La utilización de T CL como lenguaje de programación le proporciona flexibilidad a efectos de control de los algoritmos, sin embargo, las instrucciones son de muy alto nivel (p. ej. return_reply_to) de modo que no es posible modificar un protocolo de comunicaciones distinto con un programa nuevo; algo que es perfectamente posible con los picoObjetos. Por otra parte, la necesidad de un intérprete de T CL, soporte multi-hilo y los considerables requisitos de memoria que impone, hacen que SensorWare sea un middleware inviable para nuestros objetivos en lo referente a plataformas hardware a utilizar como nodos SAN. i i i i i i i i 132 4. picoObjetos La principal diferencia entre los picoObjetos y otras iniciativas es que, en nuestro caso, el repertorio de instrucciones está formado por ladrillos pequeños aunque orientados específicamente a la generación y reconocimiento de mensajes. Esto permite desacoplar la definición de los servicios y prestaciones del middleware del mecanismo que permite transportar información entre los elementos del sistema. Es decir, es posible proporcionar muchas de las prestaciones de alto nivel que proponen cualquiera de los middlewares que se han presentado; pero en lugar de proporcionar esa funcionalidad desde la máquina virtual, pueden obtenerse como servicios sobre el middleware. Es decir, los servicios no los ofrece el nodo, sino los objetos alojados en él. El problema de utilizar una ISA de tan bajo nivel es la dificultad de especificar servicios incluso muy simples. Por esta razón, se ha creado un lenguaje de alto nivel que simplifica sensiblemente esta tarea y a partir del cual es posible generar un programa FSM completo, este tema se trata en profundidad en el capítulo 6. i i i i i i i i Descubrimiento del entorno 5.1. 5.2. 5.3. 5.4. 5.5. 5.6. 5.7. 5.8. Objetivos Elementos básicos Prestaciones de ASDF Anunciamiento Descripción de servicios Búsqueda de servicios Servicio de metamodelo Conclusiones 55 E N los últimos años el grupo ARCO (Arquitectura y Redes de Computadores) ha desarrollado un nuevo SDP denominado ASDF (Abstract Service Discovery Framework). Se ha aplicado con éxito en varios proyectos sufriendo algunas modificaciones y mejoras para adaptarlo a nuevos requisitos. Si bien se trata de un protocolo de propósito general, su diseño está influenciado por las particularidades propias de dispositivos con recursos limitados como los que se utilizan para la implementación de picoObjetos. En este capítulo se describen sus características y usos, con especial énfasis en su aplicación a las redes SAN y otras redes heterogéneas susceptibles de incorporar picoObjetos. 5.1. Objetivos Aparte de las prestaciones típicas de cualquier SDP (véase § 2.7.2), ASDF se ha diseñado para cumplir los siguientes objetivos específicos: Orientado a objetos Dada la naturaleza del sistema de invocación remota que se emplea en la plataforma, se considera que lo más adecuado es modelar los servicios como clases e interfaces. Así, el proceso de enumeración y composición de servicios es un mecanismo homogéneo que se integra de forma natural con el resto del sistema. Extensible y escalable El diseño basado en interfaces permite versionado y especialización de una forma sencilla, haciendo uso de las prestaciones del middleware cuando estén disponibles. Auto-configuración Uno de los principales objetivos que cumple ASDF es ofrecer la posibilidad de integrar nuevos dispositivos y sus servicios en el sistema de forma automática. Como 133 i i i i i i i i 134 5. D ESCUBRIMIENTO DEL ENTORNO se verá, este objetivo está supeditado en algunos casos a las características de la tecnología de comunicaciones o los protocolos subyacentes como, por ejemplo, la disponibilidad de direccionamiento multicast o broadcast. Soporte para recursos limitados Otro requisito clave en el diseño del protocolo ASDF ha sido el soporte de dispositivos con reducidas capacidades de cómputo. Se han tomado en especial consideración las cuestiones referentes a tamaño de los mensajes, volumen de tráfico, consumo energético e interoperabilidad. También, aunque en menor medida, se han evaluado las limitaciones que pudiera implicar el uso de tecnologías de comunicaciones con poco ancho de banda, enlaces de datos de bajo coste o que por sus características pudieran no tener grandes prestaciones. A pesar de haber tenido muy en cuenta estas particularidades, su uso no está restringido a redes de transductores. Dado que los picoObjetos se comportan como objetos distribuidos convencionales, una consecuencia muy positiva es que ASDF es un protocolo de propósito general que se puede utilizar en todo el sistema simplificando la integración de cualquier tipo de servicio o dispositivo de forma natural. Interoperabilidad Se pretende alcanzar un nivel importante de interoperabilidad con otros SDP S ajenos, pero de amplio uso como pueden ser UP N P, Bluetooth SDP o Zeroconf. La intención es ofrecer los servicios ASDF en dominios distintos y, en principio, incompatibles. También poder representar dentro de nuestro dominio servicios ofrecidos por otros y, no menos relevante, conseguir que dos protocolos ajenos e incompatibles puedan interoperar entre sí gracias a nuestros mecanismos de integración. Félix J.V ILLANUEVA, co-diseñador del protocolo, aborda en su tesis doctoral [Vil09, Cap.7] los aspectos específicos de interoperabilidad de ASDF, proponiendo mecanismos concretos en diferentes escenarios. Estos aspectos quedan fuera de las aportaciones de esta tesis y, por ello, se recomienda al lector el citado documento si esas cuestiones resultasen de su interés. Todos estos objetivos están encaminados a facilitar al máximo el despliegue de redes SAN de todo tipo. Pretendemos que cualquier nuevo dispositivo que se active en el ámbito de la red sea capaz de auto-configurarse con mínima o nula intervención explícita por parte de los componentes del sistema. En particular, los nuevos dispositivos deberían ser perfectamente funcionales sin intervención alguna por parte del instalador u operador del sistema, aunque quizá no con todas sus prestaciones potenciales, como por ejemplo, su ubicación física. 5.2. Elementos básicos A continuación, se describen los elementos estructurales sobre los que se realiza la implementación del protocolo ASDF. Generalmente debería proporcionarlos el middleware pero, de no existir equivalencia, la propia aplicación podría proporcionar un sustituto dado que no implican una complejidad de implementación prohibitiva. i i i i i i i i 5. D ESCUBRIMIENTO DEL ENTORNO 5.2.1. 135 Canales de eventos ASDF hace un uso extensivo del servicio estándar de notificación de eventos provisto por el middleware. Con ello se consigue bajo acoplamiento entre todos los elementos involucrados de una manera sencilla y eficiente, principalmente porque los servicios comunes del middleware suelen estar más optimizados que cualquier desarrollo realizado por terceros. ASDF define y utiliza dos actores (normalmente canales de eventos) considerados como bien conocidos. Eso significa que el middleware puede obtener sus referencias automáticamente mediante los servicios de indirección o bien el nodo las tiene previamente almacenadas. Son estos: ASDA Se utiliza para enviar mensajes de anunciamiento (adv) y despedida (bye) de actores. Todos los objetos suscritos deben implementar la interfaz ASD::Listener. Cualquier elemento del sistema puede enviar ese tipo de mensajes a este canal (véase § 5.4). ASDS Se utiliza para enviar los mensajes de búsqueda de servicios (lookup). Los objetos suscritos —susceptibles de ser buscados— deben implementar la interfaz ASD::Search (véase § 5.6). Aunque se han descrito como canales de eventos, ASDA y ASDS pueden ser objetos distribuidos convencionales, dependiendo si se desea un planteamiento distribuido o centralizado, respectivamente. La alternativa que se elija no afecta en absoluto al resto del sistema. A efectos funcionales resulta transparente para los demás elementos. Se incidirá sobre esto más adelante en este capítulo. Los mecanismos de búsqueda pueden requerir la creación de otros canales auxiliares para propósitos concretos o puntuales. 5.2.2. Propiedades Una propiedad es una tupla clave-valor que representa una característica de un servicio. La clave es siempre una cadena de caracteres y el valor es normalmente un tipo básico (entero, cadena, float, etc.) o lista de ellos, aunque puede ser de tipos más complejos. El diseño de las interfaces para acceso remoto a las propiedades, definiciones y conjuntos de estas está basado en la descripción del Servicio de Propiedades [Obj00] definido por OMG. Para la implementación de los prototipos I CE se han realizado únicamente modificaciones relacionadas con las diferencias existentes entre los distintos lenguajes de especificación de interfaces. Con ello se pretende conseguir el mayor grado de interoperabilidad con pasadas o futuras implementaciones del servicio, independientemente del middleware que se utilice. Las propiedades pueden ofrecer información muy variada sobre un servicio; pueden almacenar desde el fabricante del dispositivo, el modelo, la precisión, el instalador, la fecha de la última operación de mantenimiento y un largo etcétera. Hay propiedades que se establecen por fabricación y ofrecen información estática, mientras que otras son modificables por el instalador, el usuario o, incluso, los servicios o aplicaciones. i i i i i i i i 136 5. D ESCUBRIMIENTO DEL ENTORNO La finalidad de las propiedades es doble: Permiten clasificar y discriminar servicios. Facilita al cliente la tarea de encontrar aquel que más se acerca a sus necesidades concretas. Como se verá, a cada servicio le corresponde un conjunto posible de propiedades que se puede comparar con los requisitos del usuario para evaluar en qué medida satisface una necesidad concreta. La otra utilidad de las propiedades está relacionada con las operaciones de gestión, mantenimiento y administración del sistema. Aportan meta-información muy útil para las aplicaciones finales en las que es necesario representar gráficamente el entorno. Los servicios pueden proporcionar propiedades que almacenan iconos, mapas, áreas de cobertura. Por ejemplo, una GUI para manipulación de una cámara tipo PTZ es mucho más útil y amigable si fuerza el valor de los ángulos límite (mínimo y máximo) que puede tomar físicamente el motor correspondiente. Se proporciona también soporte para meta-propiedades, es decir, datos referentes a una propiedad. Por ejemplo, si un servicio tiene una propiedad position puede ser necesario saber respecto a qué referencia está tomada. Para ello se construyen nombres de propiedades jerárquicos (separados con el carácter ‘.’); esa meta-propiedad se representaría como position.origin. Debe tenerse muy presente que la disponibilidad de los servicios prestados por los actores no está supeditada a la disponibilidad de las propiedades. Si se configura un servicio que relaciona ciertos objetos, ese servicio seguirá funcionando del mismo modo aunque las propiedades de los servicios involucrados dejen de estar accesibles. El sistema ofrece un modo degradado, pero completamente funcional, en el que no se podrá (o será más complejo) buscar o configurar servicios nuevos, pero que no afectará a ninguno de los que ya estuvieran en producción. Lo consideramos un principio de diseño del protocolo: Ninguna relación entre objetos o servicio ya establecido se verá afectada si posteriormente aparecen problemas temporales o permanentes en el acceso al sistema de propiedades. 5.2.3. Taxonomía Para que los servicios proporcionados por los actores se puedan buscar es necesario que tanto éstos como los clientes utilicen un vocabulario común para describirlos. Este vocabulario está definido en una taxonomía, que incluye: Una jerarquía de clases de servicios Cada clase identifica unívocamente un servicio estándar que puede ser ofrecido por un actor o demandado por un cliente. Cada clase se traduce en una interfaz de objeto remoto. Cada actor puede ofrecer varios de estos servicios sin más que implementar las interfaces correspondientes. Una jerarquía de eventos Los eventos son útiles para identificar situaciones especiales y realizar cambios de estado que pueden afectar al funcionamiento de varios servicios. i i i i i i i i 5. D ESCUBRIMIENTO DEL ENTORNO 137 Un diccionario de propiedades Define el conjunto de propiedades posibles que puede tener asociadas cada clase de servicios: el nombre, el tipo de dato del valor, de sólo lectura o modificable, obligatoria u opcional, etc. Esta taxonomía se define por medio de una ontología que se almacena en un fichero OWL. A partir de éste se obtiene toda la información necesaria, tanto para la definición de servicios por parte de los actores, como de los clientes para solicitar servicios a la red. La figura 5.1 muestra parte de la jerarquía de servicios. En todo caso, es previsible que cada aplicación tenga su propia taxonomía, puesto que la orientación del problema determina características y servicios relevantes que para otras aplicaciones podrían ser completamente inútiles; aspirar a un taxonomía universal absoluta no es práctico aparte de resultar muy complejo. F IGURA 5.1: Clases de servicios definidos en la taxonomía. (V ILLANUEVA [Vil09]) 5.3. Prestaciones de ASDF Por su enfoque integrador y flexible, el diseño del protocolo trata de recoger la mayoría de los casos de uso que se pueden encontrar en los SDP más utilizados. Por el mismo motivo se proporcionan alternativas centralizadas, distribuidas e híbridas para casi todos ellos. Estas son las prestaciones más importantes: i i i i i i i i 138 5. D ESCUBRIMIENTO DEL ENTORNO Registro Siempre que sea posible se utilizan los mecanismos propios del middleware para localización de objetos. En el caso de I CE, todo servicio que utilice el servidor de aplicaciones puede quedar automáticamente registrado en el Registry. Anunciamiento/despedida Para aquellos actores más limitados (como el caso de picoObjetos) el acceso al servicio de registro del middleware resulta demasiado complejo. En su caso envían mensajes a través del actor ASDA. Se proporciona soporte para anunciamiento proactivo y reactivo. También es posible su uso por cualquier servicio si no existe o no se desea utilizar un registro. Localización del directorio En nuestro protocolo la funcionalidad del directorio está dividida. Los mecanismos de búsqueda de servicios y descripción de los mismos son independientes. La única referencia necesaria para realizar búsquedas es ASDS y asumimos que es un objeto bien conocido tanto si es un canal de eventos como si es un actor al uso, es decir, no es necesario buscarlo. Búsqueda La localización de un servicio concreto se logra mediante consultas explícitas a la referencia ASDS por parte de las aplicaciones. El proceso de búsqueda en sí mismo también puede ser centralizado, distribuido o híbrido. En las siguientes secciones se describen las características y funcionamiento de cada uno de estos casos. A menos que se indique lo contrario, se debe asumir que se trata de las modalidades distribuidas de los mismos. 5.4. Anunciamiento Cuando un actor se conecta o vuelve de un estado de sleep su nodo envía un mensaje de anunciamiento adv() a ASDA. Estos anuncios también pueden efectuarse (opcionalmente) cada cierto tiempo, no necesariamente periódico. Éste es un mecanismo de anunciamiento proactivo puesto que se realiza por iniciativa del servidor/ actor. El método adv() corresponde a la interfaz ASD::Listener (ver listado 5.1). El argumento prx es un proxy para contactar con el actor. module ASD { interface Listener { idempotent void adv (Object∗ prx ) ; idempotent void bye ( Ice :: Identity oid ) ; }; }; L ISTADO 5.1: ASD::Listener: Interfaz para recepción de anunciamientos i i i i i i i i 5. D ESCUBRIMIENTO DEL ENTORNO 139 Los argumentos de este mensaje pueden ser completamente estáticos. El tamaño del mensaje completo no supera los 100 bytes, aunque depende mucho del tipo de endpoint que utilice el proxy: el tamaño de las direcciones lógicas y las identidades de objeto (véase § C.2). Gracias a ello es factible almacenarlo en memoria ROM en el propio dispositivo. En el caso extremo, en que el nodo no fuese capaz de enviar el mensaje adv(), un agente externo puede enviarlo por él si conoce su proxy. Sin embargo, esa es una situación a evitar por la grave pérdida de autonomía que conlleva. Los clientes y servicios interesados en recibir anuncios de los actores deben implementar la interfaz ASD::Listener y estar suscritos al canal ASDA (ver figura 5.2). Cuando un suscriptor recibe un evento adv() obtiene el proxy al actor anunciado y, desde ese momento, puede utilizar los mecanismos de introspección estándar del middleware para averiguar qué interfaces implementa, invocar sus métodos, etc. F IGURA 5.2: Diagrama de secuencia de un anunciamiento Se puede emplear también un servicio de anunciamiento centralizado (registro) sin más que substituir el canal ASDA por un objeto. Éste almacenaría las referencias a los objetos anunciados, es decir, sería parte de la funcionalidad de un directorio (véase § 5.6.3). Un modelo híbrido también es posible mediante un Servicio de Caché (CacheService), que se suscribe al canal ASDA, almacena y clasifica las referencias de todos los actores que se anuncian, y las elimina cuando se despiden. Este modelo híbrido es similar a la funcionalidad del Service Directory de UP N P en el sentido de que los anuncios/registros pueden ser distribuidos (con o sin caché) o centralizados. Sin embargo, en el caso de ASDF la ventaja es que el modelo elegido es transparente para los servicios. Del mismo modo que ocurre en el anunciamiento, un actor también puede despedirse (mensaje Listener::bye()) cuando va a dejar de estar disponible por un tiempo. Se puede considerar información de cortesía, pues evitará que otros actores —que mantuviesen una referencia— intenten contactar cuando el servicio ya no esté accesible. No es que eso suponga un problema grave, pero ayuda a mantener la coherencia de la información que unos servicios mantienen sobre otros y la convergencia de los protocolos que impliquen búsquedas activas. Si un servicio desaparece sin despedirse ocurrirá un error cuando un cliente que conocía la referencia trate de utilizarlo. En ese caso, el cliente puede informar al resto de la red enviando el mensaje bye() para dicho servicio, dado que conoce su identidad. Lo mismo puede aplicarse si se está utilizando un registro o el servicio de caché. Si por i i i i i i i i 140 5. D ESCUBRIMIENTO DEL ENTORNO error —o de forma maliciosa— un cliente envía mensajes bye() de servicios activos, no supondrá ningún problema ya que quedarán obsoletos al recibir nuevos anuncios, independientemente de que sean activos o proactivos. Además, resulta sencillo implementar servicios de monitorización (como suscriptores de ASDA) que detecten mensajes adv() y bye() para un mismo servicio, e informen convenientemente como causa probable de que está ocurriendo un mal funcionamiento en el sistema. En el caso de picoObjetos nunca se envían mensajes de despedida ya que se considera que son servicios siempre conectados, lo cual favorece además la simplicidad de su implementación. Es un mecanismo de anunciamiento de alto nivel puesto que se está distribuyendo una referencia a objeto directamente invocable por el receptor. Sin embargo, puede ser implementado en dispositivos muy simples con un comportamiento idéntico al de un objeto convencional. 5.5. Descripción de servicios La descripción de un servicio individual requiere de dos elementos: Una interfaz La clase de servicio, en términos de la taxonomía, queda definida en el lenguaje de especificación de interfaces del middleware. Son interfaces puramente declarativas, es decir, no tienen métodos ni definen comportamiento alguno. Sirven únicamente como etiquetado de los actores. Cualquier actor puede heredar de una o varias de estas interfaces para indicar que es capaz de proporcionar los servicios asociados. Un conjunto de propiedades Las propiedades habitualmente representan restricciones o valores para condiciones de entorno. Por ejemplo, un sensor de temperatura puede tener varias propiedades: valores máximo y mínimo, precisión de la medida, situación, etc. Cada clase de servicio tiene asociado un conjunto específico de propiedades. Si un actor implementa varias interfaces de servicio, tendrá varios conjuntos de propiedades, aunque se accedan a través de una misma referencia. El listado 5.2 muestra parte del fichero Services.ice que contiene las interfaces (en lenguaje Slice) que corresponden a las distintas clases de servicios. Se ha desarrollado una herramienta llamada ows2slice que genera automáticamente este fichero a partir de la descripción OWL de la taxonomía. module Services { interface Prese nceSenso r {}; interface T e m p e r a t u r e S e n s o r {}; interface MotionSensor {}; [...] }; L ISTADO 5.2: Services.ice: Definición de interfaces para servicios i i i i i i i i 5. D ESCUBRIMIENTO DEL ENTORNO 141 En las próximas secciones veremos cómo y dónde se almacena la información de descripción del servicio. 5.5.1. Servicios proporcionados La clase de servicio la mantiene la propia implementación del actor, heredando de la interfaz correspondiente. En el caso de un objeto convencional, el compilador de interfaces genera un esqueleto de implementación que incorpora la definición de esas interfaces como corresponda al lenguaje de implementación elegido para el servidor. En el caso de un picoObjeto, la propia implementación del autómata almacena estáticamente la información necesaria. Es muy simple determinar qué servicios implementa un actor a partir de una referencia; basta utilizar los mecanismos de introspección incorporados. En CORBA la única posibilidad es el método is_a() (véase § 2.3.3), mientras que en I CE existen los métodos ice_id(), ice_ids() y ice_isA() (véase § 2.3.4). Múltiples servicios por actor Las interfaces que definen servicios siguen una jerarquía de especialización. Por ejemplo, el servicio VideoCamera es una subclase del servicio ImageSource. Un actor que implementa el servicio Camera hereda todos los servicios definidos como supertipos en la jerarquía hasta la clase raíz (Service) y con ellos también sus propiedades asociadas. Los objetos también pueden utilizar herencia múltiple para implementar varios servicios a la vez, lo que significa que pueden ser utilizados con distintos roles. Siguiendo el ejemplo anterior, el objeto podría implementar además el servicio PhotoCamera, que también es una especialización del ImageSource tal como muestra la figura 5.3. El código de especificación para la nueva interfaz podría ser el que aparece en el listado 5.3. interface MyCam extends Services :: VideoCamera , Services :: PhotoCamera {}; L ISTADO 5.3: Herencia (incorrecta) de múltiples servicios Sin embargo, esto plantea un problema: como el servicio ImageSource tiene asociada la propiedad resolution, un objeto de clase MyCam heredaría dicha propiedad a través de dos caminos de herencia diferentes. Evidentemente la propiedad sólo puede tener un valor, pero rara vez una cámara de vídeo que puede ser usada como cámara de fotos tiene la misma resolución en ambos modos. La solución pasa por asumir cada servicio como una faceta diferente utilizando la interfaz DUO::Component (véase § 3.5). Aunque esta es la solución general, realmente no ocurre en todos los casos. La mayoría de las combinaciones de interfaces no producen este tipo de conflictos en las propiedades heredadas. i i i i i i i i 142 5. D ESCUBRIMIENTO DEL ENTORNO F IGURA 5.3: Ejemplo de herencia múltiple de interfaces para servicios 5.5.2. Persistencia de las propiedades Las propiedades asociadas a un objeto se acceden por medio de la interfaz PropertyService::PropertySetDef, que corresponde a la especificación del servicio Property Service [Obj00] de OMG. Se consideran tres posibilidades (excluyentes) que pueden darse a la hora de acceder a las propiedades de un servicio y que determinan dónde pueden estar realmente almacenadas: En el actor Si el actor implementa la interfaz PropertyService::PropertySetDef, él mismo sirve sus propiedades. Este caso es el habitual cuando se trata de objetos implementados con las herramientas estándar del ORB. Se ha creado una biblioteca denominada libPropertyServer que capacita a un objeto para servir sus propiedades y le confiere persistencia automática por medio de Freeze (véase § 2.3.4). En un Servidor de Propiedades Cuando un objeto no tiene suficiente capacidad (principalmente memoria) para gestionar sus propiedades y/o posibilidad de almacenar sus valores de forma persistente puede delegar esta responsabilidad en un servidor de propiedades que llamamos PropertyServer (véase § 5.5.3). Para ello, el objeto implementa la interfaz ASD::PropHldr (ver listado 5.4). Mediante el método getp(), el cliente solicita al objeto el proxy del objeto que mantiene sus propiedades, el cual implementa la interfaz PropertyService::PropertySetDef, de modo que al tratarse de una indirección no supone apenas complejidad adicional para los clientes. i i i i i i i i 5. D ESCUBRIMIENTO DEL ENTORNO 143 El objeto no tiene propiedades Si el actor no implementa la interfaz PropertyService::PropertySetDef ni tampoco ASD::PropHldr significa que no hay propiedades disponibles a pesar de que implemente alguna interfaz de servicio. Esto puede ocurrir en objetos extremadamente simples o que forman parte de un actor más complejo como ocurre en los contenedores (véase § 3.3) o los componentes (véase § 3.5). module ASD { interface PropHldr { idempotent P ro pe rt y Se rv ic e :: Prop ertySetD ef ∗ getp () ; }; }; L ISTADO 5.4: ASD::PropHldr: Delegación de propiedades a un objeto externo 5.5.3. Servidor de propiedades El almacenamiento de propiedades por delegación, es decir, cuando el actor utiliza la interfaz ASD::PropHldr implica la necesidad de un servicio especializado encargado de la persistencia de gran cantidad de objetos. Para cubrir esta necesidad se ha diseñado e implementado PropertyServer. Es un servicio IceBox que implementa únicamente la interfaz PropertyService::PropertySetDef. Para poder servir las propiedades de varios servicios (potencialmente cientos) utiliza un localizador de sirvientes modificado. Realmente sólo hay un sirviente encargado de localizar en una base de datos las propiedades que corresponden al objeto cuya identidad se ha utilizado para la invocación, aunque ese objeto no existe realmente en el adaptador. Para el cliente no hay diferencia, pero supone una gran ventaja en la escalabilidad de la solución. También por razones de escalabilidad, los actores no deberían delegar sus propiedades a instancias del PropertyServer fuera de su dominio. 5.6. Búsqueda de servicios El mecanismo básico de búsqueda de servicios implica al canal ASDS y a los actores suscritos al mismo. Cuando un cliente necesita buscar un servicio, crea un canal de eventos como callback para las respuestas y se suscribe a sí mismo a dicho canal (ver figura 5.4). Después, envía un mensaje lookup() (ver listado 5.5) al canal ASDS indicando: La interfaz del servicio que desea (la clase de la taxonomía). Un conjunto de propiedades que deben satisfacer los servicios. El proxy del canal que ha creado. La aplicación también es responsable de su eliminación cuando no sea necesario. i i i i i i i i 144 5. D ESCUBRIMIENTO DEL ENTORNO module ASD { interface Search { idempotent void lookup ( ASD :: Listener ∗ cb , string tid , P ro pe rt y Se rv ic e :: Properties query ) ; idempotent void discover ( ASD :: Listener ∗ cb ) ; }; }; L ISTADO 5.5: ASD::Search: Interfaz para búsqueda de servicios Quién y cómo se manejan estos mensajes de búsqueda por parte de los suscriptores del canal ASDS es lo que determina qué tipo de directorio se está usando. El resto de esta sección evalúa las diferentes posibilidades. 5.6.1. Directorio distribuido puro Cuando un actor (suscrito al canal ASDS) decide que cumple el criterio de búsqueda recibido a través de un mensaje lookup(), envía un mensaje adv() convencional al canal que aparece en el mensaje de búsqueda. Este procedimiento se muestra como diagrama de secuencia en la figura 5.4. Si hay otras aplicaciones o clientes interesados en las posibles respuestas simplemente pueden suscribirse también al canal creado por la aplicación interrogadora. Esto es útil si se quiere implementar un servicio de cacheado de búsquedas o simplemente a efectos de registro de actividades. Para asegurar que las respuestas de los actores no llegan antes que la suscripción de terceros, los actores esperan un tiempo fijo antes de enviar su anunciamiento. Es interesante la posibilidad de que esperen un tiempo adicional aleatorio antes de contestar para mejorar la escalabilidad de la solución, aunque la propia latencia de la red puede ser suficiente en muchos casos1 para evitar el pico de tráfico de red que pueden suponer las respuestas de los nodos en redes muy grandes. En este escenario no hay ningún elemento central que procese las búsquedas. La única referencia común es el canal ASDS, pero este mecanismo de distribución puede ser substituido de forma transparente por un endpoint multicast si la tecnología de red lo soporta. Se trata por ello de un directorio distribuido o P2P. 5.6.2. Directorio híbrido Teniendo en cuenta la información de que dispone el PropertyServer, es posible enriquecer su funcionalidad para darle un papel activo en el descubrimiento de servicios y convertirlo así en un servicio de directorio concreto, que llamamos ServiceDirectory. Este directorio se suscribe al canal ASDS. Recibe peticiones lookup(), evalúa las consultas sobre los actores que conoce y responde enviando anuncios para los servicios que correspondan. Se trata de una funcionalidad muy interesante pues permite buscar servicios alojados en picoObjetos sin que esos nodos tengan que soportar dicha funcionalidad, y todo de forma transparente para la aplicación cliente (véase § 5.5.2). 1 Debido el pequeño tamaño de los mensajes. i i i i i i i i 5. D ESCUBRIMIENTO DEL ENTORNO 145 F IGURA 5.4: Búsqueda de servicios con directorio distribuido puro Dado que no hay ningún motivo que impida la coexistencia de varios PropertyServer o ServiceDirectory en un mismo dominio —a condición de que las propiedades de un objeto dado estén en el mismo servidor— el mecanismo expuesto hace posible también un modelo de directorio distribuido estructurado. Este directorio no substituye al mecanismo de búsqueda abordado en la sección anterior, lo complementa, de ahí que se denomine híbrido. La única precaución que debe tomar el Servicio de Directorio es esperar un tiempo adecuado por si los servicios involucrados respondiesen por sí mismos. En el caso peor, tanto el actor como el directorio enviarían mensajes idénticos al canal de la aplicación interrogadora. Al ser información idempotente, no tendría ninguna consecuencia negativa importante, salvo el pequeño desperdicio de ancho de banda que implica. Nótese que los clientes del SDP no requieren de un mecanismo específico para encontrar los directorios puesto que estos están suscritos al canal ASDS y reciben las peticiones de forma indirecta. La asociación ServiceDirectory/PropertyServer responde únicamente a razones prácticas puesto que utilizan básicamente la misma información. Ni los clientes ni ningún otro componente del sistema necesitan saberlo. No debería asumirse que siempre ocurre de ese modo ya que es posible implementar directorios que recopilan información de otra forma como se verá en la sección 5.6.4. 5.6.3. Directorio centralizado Para lograr un modelo de directorio centralizado se substituye el canal ASDS por un ServiceDirectory. En este caso ningún actor sirve sus propiedades ni se suscribe a ningún canal. En esta situación, el directorio debería ser un suscriptor de ASDA para mantener la coherencia de la información que mantiene o, incluso, la referencia ASDA podría apuntar al propio ServiceDirectory, tal como se apunta en la sección 5.4. Aunque la situación es sensiblemente diferente para los actores, no implica ningún cambio para los clientes, que seguirán usando la referencia ASDS de la forma habitual. La i i i i i i i i 146 5. D ESCUBRIMIENTO DEL ENTORNO única diferencia es que ahora apunta a un objeto y no a un canal, pero esa circunstancia no afecta absolutamente en nada al funcionamiento o implementación de los clientes. Aunque esta modalidad de directorio tiene evidentes desventajas, puede ser una alternativa valiosa en determinadas circunstancias. Es responsabilidad del diseñador decidir cuál es la solución oportuna. 5.6.4. Directorio jerárquico Ningún mecanismo de búsqueda de servicios puede escalar indefinidamente; al igual que la mayor parte del protocolo ASDF, éste está diseñado para funcionar en entornos con un número de dispositivos predecible. Sin embargo, puede ser necesario acceder a servicios prestados por un dominio de nivel superior. Si el middleware que se está usando es I CE se puede utilizar para ello uno de sus servicios estándar: IceGrid. IceGrid ofrece muchas prestaciones orientadas al desarrollo de aplicaciones en grid, tales como balanceo de carga, migración, activación implícita, etc. En nuestro caso nos interesan especialmente dos de ellas: IceGrid/Locator Permite contactar con objetos concretos a partir de un proxy indirecto. Deben estar registrados previamente en otro componente llamado IceGrid/Registry. IceGrid/Query Es una interfaz para consultar la base de datos de objetos conocidos por el Registry. El listado 5.6 muestra algunos de los métodos de la citada interfaz. interface Query { Object∗ findO bjectByI d ( Ice :: Identity id ) ; Object∗ f i n d O b j e c t By T y p e (string type ) ; Ice :: O bjectPro xySeq f i n d A l l O b j e c t s B y T y p e (string type ) ; Ice :: O bjectPro xySeq f in d Al lR ep l ic as (Object∗ proxy ) ; }; L ISTADO 5.6: Interfaz IceGrid::Query Así pues, el componente IceGrid/Query sirve como sistema de directorio de servicios ya que permite obtener uno o todos los actores que implementan un servicio dado. Sin embargo, eso solo resuelve parte del problema. Es necesario implementar un objeto Locator con capacidad para redirigir peticiones al dominio superior cuando se requiera. Además, es necesario comprobar que esos objetos cumplen el criterio expresado por el conjunto de propiedades. Desde el punto de vista de clientes y actores, este nuevo componente, llamado ExternalLocator, actúa de forma transparente y para el cliente tiene un comportamiento indistinguible al descrito para el directorio centralizado (véase § 5.6.3). Desde el punto de vista estructural la diferencia es que el ExternalLocator funciona como un directorio jerárquico de dos niveles (ver figura 5.5). i i i i i i i i 5. D ESCUBRIMIENTO DEL ENTORNO 147 F IGURA 5.5: Delegación de la búsqueda de servicios al dominio superior 5.6.5. Anunciamiento reactivo ASDF también ofrece soporte para anuncios reactivos como una particularización del mecanismo de búsqueda. Los anuncios proactivos (véase § 5.4) pueden plantear problemas de escalabilidad si la red de comunicaciones tiene poco ancho de banda y, sobre todo, de consumo de energía si el servicio se aloja en un dispositivo alimentado por baterías. Una vez dado a conocer un servicio, los anunciamientos proactivos (periódicos o no) tienen poca utilidad. Únicamente pueden servir como heartbeat para que un hipotético servicio de monitorización de la red asuma que dicho servicio anunciado sigue estando activo sin necesidad de tener que invocarlo. Para estas situaciones se proporciona una interfaz para soporte de anunciamiento pasivo. El mecanismo es sencillo, cuando el objeto recibe una invocación a su método discover() (para lo cual debe implementar la interfaz ASD::Search) envía un mensaje adv() al proxy que aparece en la invocación. Ese proxy puede ser el canal ASDA si el cliente así lo decide. El método de anunciamiento reactivo se puede utilizar en los dos escenarios de canales de eventos: Cuando el actor dispone de un endpoint multicast estáticamente vinculado el canal ASDS (sin servicio de eventos). Cuando se utiliza el servicio de eventos y se dispone del proxy del canal ASDS en tiempo de compilación. En este caso, los picoObjetos se suscriben al canal en el arranque del nodo. Si no se da ninguna de estas condiciones no es posible utilizar anunciamientos reactivos ya que para enviar un mensaje al actor se requeriría su proxy, y precisamente ésa es la finalidad del anunciamiento. i i i i i i i i 148 5. D ESCUBRIMIENTO DEL ENTORNO 5.7. Servicio de metamodelo Nuestro SDP también proporciona acceso remoto al modelo de servicios a través de un servicio llamado MIS (Model Information Service), que implementa la interfaz MIS::Metamodel. Éste permite a cualquier componente del sistema acceder a la taxonomía de servicios y propiedades. Es posible averiguar de un modo sencillo cuál es el conjunto válido de propiedades para una clase dada, las relaciones entre clases, etc. El listado 5.7 muestra la interfaz MIS::Metamodel en lenguaje Slice. MIS::MetaClass es un tipo que se utiliza para describir clases de la ontología (una metaclase). Incluye métodos para obtener la especificación de las propiedades posibles para el servicio que representa y averiguar cuáles son las subclases disponibles. module MIS { interface MetaClass ; dictionary <string , MetaClass ∗ > MetaClassDict ; exception N o S u c h C l a s s E x c e p t i o n { string typeID ; }; interface MetaClass { P ro pe rt y Se rv ic e :: Pro pertySetD ef ∗ g e t P r o p e r t i e s S p e c () ; MetaClassDict getSubClasses () ; }; interface MetaModel extends Service :: MetaModel { MetaClass ∗ getClass (string typeId ) throws N o S u c h C l a s s E x c e p t i o n ; MetaClassDict getClasses () ; }; }; L ISTADO 5.7: Interfaz Slice de MIS El servicio de metamodelo resulta muy útil para construir herramientas de administración. Es posible editar las propiedades de los servicios validando las reglas que impone la taxonomía por medio de acceso remoto al propio modelo. MIS::Metamodel es una herramienta de introspección que ofrece acceso inmediato al conjunto de servicios posibles y a sus definiciones de forma programática. 5.8. Conclusiones ASDF es un SDP potente, con un diseño altamente flexible, capaz de cubrir necesidades muy diversas y adaptándose a las peculiaridades del middleware sobre el que se implemente, pudiendo suplir, si es necesario, la ausencia de transporte multicast o servicios como el de notificación de eventos. El protocolo completo solo define 5 mensajes diferentes para cubrir todos los escenarios. Es lo suficientemente sencillo como para ser implementado en dispositivos muy limitados, bajo el enfoque de diseño de picoObjeto ya que el almacenamiento de propiedades —la característica más costosa— se puede delegar a dispositivos más capaces. Los nodos i i i i i ASDS es el ServiceDirectory. PropertyServer. Anunciamiento / despedida Directorio (búsquedas) Persistencia de las propiedades ASDS es un canal de eventos (no hay directorio). Los actores responden a las búsquedas. Los actores sirven las propiedades. tos. Ambos. ServiceDirectory subscrito a ASDA. ServiceDirectory subscrito a ASDS. Ambos responden. CacheService. Basado en anunciamientos. ASDA es un canal de even- híbrido distribuido C UADRO 5.1: ASDF: Resumen de las prestaciones del protocolo Basado en los servicios del middleware. ASDA es el ServiceDirectory. Registro centralizado i i i i 5. D ESCUBRIMIENTO DEL ENTORNO 149 i i i i i i i 150 5. D ESCUBRIMIENTO DEL ENTORNO de la SAN se integran en la infraestructura sin necesidad de ninguna configuración previa ni de la intervención de ningún operador humano. El anunciamiento ofrece en un solo mensaje toda la información que el entorno inteligente requiere para localizar el nuevo actor y empezar a utilizarlo. El cuadro 5.1 resume las distintas alternativas que proporciona ASDF para soportar las prestaciones típicas de los SDP. Nótese que las columnas de dicho cuadro no representan escenarios excluyentes, es decir, es posible un escenario en el que exista búsqueda centralizada y anunciamiento distribuido al mismo tiempo. Por último, el servicio MIS ofrece un medio sencillo y potente para realizar introspección del modelo de servicios de un modo programático. i i i i i i i i Flujo de diseño 6.1. 6.2. 6.3. 6.4. 6.5. Lenguaje IcePick Lenguaje SIS El compilador ipkc Drivers Plataforma para desarrollo de picoObjetos 66 L LEGADOS a este punto, disponemos de los mecanismos y herramientas necesarios para construir una red SAN formada por nodos cuyos transductores son accesibles como objetos remotos por medio de picoObjetos. Sin embargo, el programador debe realizar una ardua tarea para conseguirlo: para cada nodo debe escribir un fichero FSM especificando cada detalle de cada mensaje del protocolo que el picoObjeto debe reconocer o generar. Además de resultar una tarea tediosa y propensa a errores, requiere del programador un profundo conocimiento del formato y detalles de bajo nivel del protocolo inter-ORB correspondiente. Se hace necesario disponer de un lenguaje de alto nivel que permita abstraer al programador de todos esos detalles: IcePick. Con este lenguaje se puede escribir un fichero que incluye la especificación de un nodo en el que residen uno o varios objetos. Después, un compilador (ipkc) se encarga de generar código FSM que, posteriormente, podrá ser a su vez compilado a bytecode. La figura 6.1 muestra un diagrama simplificado del proceso completo de compilación. A lo largo de este capítulo se refinará este diagrama incluyendo más detalles. Disponer de un lenguaje de más alto nivel no invalida FSM. Hay varios motivos para mantenerlo: A partir del lenguaje FSM es posible plantear la generación de bytecode o bien de código nativo (véase § 4.8). Esto pueden hacerlo dos herramientas independientes. Si no existiera el lenguaje FSM, el compilador ipkc debería dar soporte a ambas alternativas por sí mismo, aumentando la complejidad de su diseño e implementación. FSM permite depurar de un modo mucho más sencillo y rápido la salida del compilador ipkc. Es posible escribir baterías de pruebas que comprueben la validez 151 i i i i i i i i 152 6. F LUJO DE DISEÑO F IGURA 6.1: Diagrama simplificado del proceso de compilación del resultado comparando con ficheros FSM correctos. Hacerlo con bytecode implicaría disponer de la misma versión en todos los lenguajes de implementación soportados. FSM permite al diseñador escribir código a mano para poder experimentar con las posibilidades de la Virtual ISA (V-ISA) y plantear mejoras o detectar errores sin tener que modificar ipkc. Sólo cuando se ha comprobado que esos cambios son ventajosos se plantea la modificación del backend de ipkc. FSM impone una interfaz que aisla al lenguaje de alto nivel (IcePick) de los detalles relacionados con la máquina virtual o de la generación de código nativo, si fuera el caso. 6.1. Lenguaje IcePick El objetivo del lenguaje IcePick es definir el conjunto de objetos distribuidos que ha de alojar un nodo abstrayendo todos los detalles de bajo nivel. Concretamente, un fichero en lenguaje IcePick incluye los siguientes datos: Inclusión de interfaces (los tipos de los objetos). Declaraciones de objetos. Declaraciones de adaptadores remotos. Declaraciones de adaptadores locales, normalmente sólo uno, pero puede haber más. Definición de triggers. i i i i i i i i 6. F LUJO DE DISEÑO 6.1.1. 153 Especificación de interfaces Cualquier MDOO incluye algún lenguaje para especificar el contrato (interfaz) entre el objeto y sus clientes. Las cláusulas uses de IcePick se utilizan para hacer referencia a ficheros que contienen las declaraciones de estas interfaces. Tanto el lenguaje como el compilador están diseñados de modo que sean independientes del middleware utilizado. El compilador admite la posibilidad de incluir nuevos lenguajes de especificación de interfaces por medio de bibliotecas. Hasta el momento sólo hay disponibles frontends de S LICE (Specification Language for Ice) e IDL, pero se puede considerar la posibilidad de construir otros para sistemas como WSDL, Remoting o Java RMI. Como resultado del procesamiento de dichos ficheros, el compilador construye una tabla de símbolos que incluye todas las interfaces declaradas, con sus relaciones de herencia, métodos en cada interfaz, etc. Los nombres de estas interfaces y métodos están disponibles para el resto del fichero IcePick. Independientemente del formato que tuvieran en el lenguaje original, los nombres de las interfaces se indican como una ruta de herencia utilizando el carácter ‘.’ como separador (puede ver un ejemplo en el listado 6.1). IcePick no permite declarar interfaces adicionales. Únicamente se pueden utilizar las contenidas en los ficheros incluidos por medio de la cláusula uses. 6.1.2. Objetos La declaración de un objeto identifica una entidad lógica sobre la que se pueden realizar invocaciones. Todo objeto lleva asociado un tipo declarado en un fichero incluido con uses. La declaración de un objeto consta de: La palabra reservada object. Un tipo (interfaz remota). Un identificador dentro del fichero IcePick. Un bloque con argumentos (que puede ser vacío). El listado 6.1 muestra la declaración de varios objetos. 1 uses " DOBS / DUO . ice "; 3 4 5 6 7 8 object mode }; object object object DUO . IBool . RW lock { = oneway ; DUO . IFloat . R ldr ; ASD . Listener asda ; DUO . IBool . W signal ; L ISTADO 6.1: IcePick: Definición de objetos i i i i i i i i 154 6. F LUJO DE DISEÑO Argumentos El bloque de argumentos que se puede incluir en la declaración de un objeto funciona como un diccionario genérico clave/valor. Existen algunas claves predefinidas, pero es posible incorporar otras, como se verá a continuación. Los argumentos permiten añadir información adicional necesaria en casos especiales. El argumento mode indica si el objeto tiene capacidad para devolver valores de respuesta. Si su valor es oneway significa que no la tiene y, por tanto, el compilador puede realizar optimizaciones avisando si alguno de los métodos de las interfaces que implementa requiere devolver parámetros. Se utiliza para evitar la generación de los métodos de soporte de introspección que se incluyen por defecto, que en ese caso, serían inútiles. También es posible definir facetas utilizando argumentos. Una faceta es similar a un objeto convencional. La diferencia es que debe incluir dos argumentos especiales: facet – Es la cadena que identifica la faceta. default – Es el identificador de objeto de la faceta por defecto a la que está asociado. El listado 6.2 muestra un ejemplo de definición de un objeto con una faceta. uses " DOBS / DUO . ice "; object DUO . IByte . RW light ; object DUO . IBool . RW bool_light { default = light ; facet = " bool "; }; L ISTADO 6.2: IcePick: Definición de una faceta 6.1.3. Adaptadores El adaptador de IcePick es prácticamente equivalente al mismo concepto tal como se ha utilizado a lo largo del texto (ver glosario). Cada adaptador IcePick se declara con: Un tipo (local o remote). La palabra reservada adapter. Un identificador. La representación textual de uno o varios endpoints. Un mapa de objetos. El formato de la representación textual del endpoint depende completamente del middleware que se esté empleando. Así, en CORBA será un perfil de IOR (véase § 2.3.3), mientras que en I CE será un stringfied proxy (véase § 2.3.4). La declaración de un adaptador incluye obligatoriamente un conjunto de identificadores de objetos y las identidades a las que estarán asociados en ese adaptador. Eso significa i i i i i i i i 6. F LUJO DE DISEÑO 155 que estarán accesibles a través de los endpoints de ese adaptador. Es posible asociar un mismo objeto a más de un adaptador, con la misma identidad o distintas; o simplemente no asociarlo a ningún adaptador, caso en el que no será accesible remotamente. El listado 6.3 muestra un ejemplo que define dos adaptadores (uno de cada tipo) y varios objetos. uses " DOBS / DUO . ice "; uses " DOBS / ASDF . ice "; object DUO . IBool . W signal ; object DUO . IByte . RW obj1 ; object ASD . Listener asda ; local adapter node { endpoint = " tcp −h 20.0.0.2 −p 2030" ; objects = {" UUID1 ": signal , " UUID2 ": obj1 }; }; remote adapter gateway { endpoint = [" xbow −h 20740" , " tcp −p 2000"]; objects = {" IceStorm / ASDA . publisher ": asda }; }; L ISTADO 6.3: IcePick: Declaración de adaptadores 6.1.4. Eventos En la sección 4.5.6 se explicaba cómo el picoObjeto funciona como una máquina dirigida por eventos. Por esa razón, el lenguaje IcePick ofrece soporte para especificar eventos concretos y la forma en que deben ser atendidos (un manejador). Las cláusulas para especificación de eventos (triggers) implican un hecho y un conjunto de acciones que se llevarán a cabo como consecuencia. Existen cuatro cláusulas: boot Es un evento que se lanza en el arranque del dispositivo o cuando se reinicia, y una vez ha terminado de inicializarse. Sólo puede haber una cláusula boot en cada programa IcePick. En el manejador de este evento se inicializan los manejadores del resto de eventos y se realizan tareas de inicialización específicas del dispositivo invocando métodos del sirviente. timer Define un evento que se lanza periódicamente con el intervalo especificado. Se pueden definir varias cláusulas timer en un mismo programa. when Define un evento que se lanza al producirse una invocación sobre un método de un objeto local concreto. Puede haber varias cláusulas when. event Define un manejador para un evento aportado por el programador del transductor (en el sirviente). Esto es necesario para poder indicar al picoObjeto que cierta situación i i i i i i i i 156 6. F LUJO DE DISEÑO ha ocurrido en el dispositivo. Típicamente se tratará de una lectura asíncrona procedente de un sensor, aunque pueden darse otras situaciones. La cláusula event permite definir el comportamiento asociado a un evento cuya aparición queda fuera de la responsabilidad del código generado, es decir, el programador debe informar explícitamente de que ese evento se ha producido por medio de la instrucción raise_event() (véase § 4.5.3). Esta característica es la que hace posible definir comportamientos proactivos (véase § 3.4.2). El manejador de un evento es un conjunto de acciones que deben ejecutarse cuando se activa. Se especifica con un bloque que contiene una o más invocaciones a métodos. Éstos pueden corresponder tanto a objetos locales como remotos y deben estar declarados. El listado 6.4 muestra un ejemplo que incluye una cláusula de cada tipo de evento. 1 2 3 boot { signal . subscribe ( lock , lock . qos () ) ; } 5 6 7 8 timer (30) { asda . adv ( lock ) ; asda . adv ( ldr ) ; } 10 11 12 when ldr . get () do { lock . test () ; } 14 15 16 event AUTOL OCK_EVEN T do { lock . set ( True , lock . oid ) ; } L ISTADO 6.4: IcePick: Cláusulas para definición de triggers Gestión de triggers Todos los triggers definidos en un fichero IcePick están activos por defecto y se lanzarán según sus reglas (véase § 6.1.4) una vez que el picoObjeto ha arrancado. Para permitir mayor flexibilidad y dar soporte a comportamientos más complejos, IcePick permite especificar la activación/desactivación de los triggers, a excepción de boot. Para lograrlo primero es necesario nombrar el trigger; por defecto son anónimos. El nombrado se consigue escribiendo una etiqueta que se sitúa antes de la cláusula que define el trigger y seguida del carácter ‘:’. Después, se utiliza el método enable() con un parámetro booleano. Esta característica es de gran utilidad para definir distintos comportamientos en el mismo nodo dependiendo de condicionantes externos. Por ejemplo, un sensor de movimiento que envía eventos sólo cuando se ha establecido un modo de alerta. Con ello se logra ahorrar mensajes, evitando el consumo de energía para ese nodo y aquellos que deberían encaminar ese mensaje. i i i i i i i i 6. F LUJO DE DISEÑO 157 Como ejemplo, el listado 6.5 muestra un fragmento de un fichero IcePick en el que se utilizan estas instrucciones. El evento auto_off (línea 5) se encarga de apagar automáticamente la luz controlada por el objeto light una vez pasados 15 ticks. El evento auto_off no se repite puesto que su propio manejador lo desactiva (línea 7). 1 2 3 boot { auto_off .enable( false ) ; } 5 6 7 8 auto_off : timer (15) { light . set ( false , "") ; auto_off .enable( false ) ; } 10 11 12 when light . set () do { auto_off .enable( true ) ; } L ISTADO 6.5: IcePick: Instrucciones para gestión de eventos 6.1.5. Funciones Para evitar repetir código IcePick es posible definir funciones. Una función es una secuencia de instrucciones con un nombre asociado. Para invocarla se utiliza un método llamado run(). Vea un ejemplo en el listado 6.6. propagate : function { obj2 . set ( obj1 . get () , obj1 . oid ) ; obj3 . set ( obj1 . get () , obj1 . oid ) ; } when obj1 . set do { propagate . run () ; } L ISTADO 6.6: IcePick: Funciones 6.1.6. Atributos por defecto en objetos Todos los objetos asociados a un adaptador local tienen dos atributos especiales. Intentar acceder a ellos en otro caso provocará un error de compilación. Son los siguientes: Identidad del objeto Se obtiene escribiendo el identificador del objeto seguido de un punto y el identificador oid, tal como puede verse en el segundo argumento del método set() en la línea 15 del listado 6.4. Proxy El compilador generará un proxy completo para el objeto, simplemente escribiendo su identificador, tal como se ve en las líneas 6 y 7 del listado 6.4. i i i i i i i i 158 6. F LUJO DE DISEÑO 6.1.7. Métodos Dentro del bloque asociado al manejador de un evento se pueden realizar invocaciones a dos tipos de métodos: Métodos remotos Corresponden con los métodos accesibles remotamente, es decir, especificados en la interfaz que implementa el objeto. Es posible invocar métodos remotos de cualquier objeto, independientemente si el objeto es remoto o local, aunque solo se obtiene un posible valor de retorno cuando el objeto es local. Métodos locales El sirviente suministrado por el programador del dispositivo (escrito en el lenguaje específico de la plataforma) debe contener implementaciones para todos los métodos remotos declarados en la interfaz que implementa. Pero también puede contener métodos adicionales que pueden ser invocados únicamente desde el propio nodo. A esos métodos son los que denominamos locales. IcePick no dispone de un operador de asignación, de modo que no es posible recoger el valor de retorno de un método. El único caso en el que se puede utilizar el resultado de una invocación es usándolo como parámetro de otra; tal es el caso de la invocación lock.qos() en el listado 6.4 (línea 2). 6.2. Lenguaje SIS Los middlewares convencionales proporcionan bindings para unos cuantos lenguajes de uso común. Eso ofrece la posibilidad de implementar el sirviente en el lenguaje que el programador considere más adecuado para la aplicación. Estos lenguajes suelen ser de alto nivel puesto que el esqueleto del servidor y el código del sirviente se compilan juntos para obtener un binario. En el caso de los picoObjetos, la situación es sensiblemente distinta. Para aprovechar al máximo las posibilidades y capacidad del dispositivo se crea una implementación de la máquina virtual en el lenguaje propio de la plataforma, típicamente C, Java o algún ensamblador. Debido a la forma en que la máquina virtual ejecuta el código del sirviente (véase § 4.7.1) éste debe estar implementado en el mismo lenguaje que la máquina virtual. Lo mismo es aplicable incluso aunque el autómata fuese compilado a código nativo en lugar de a bytecode (véase § 4.8). Se podría utilizar una estrategia diferente decidiendo por diseño un lenguaje común para cualquier sirviente y también para la máquina virtual, tal es el caso de Maté [LC02] o WSP [BLV09]. Sin embargo, consideramos que esa alternativa no es conveniente para nuestros objetivos. En muchos casos, incluso usando un lenguaje tan adaptable y ligero como C, no siempre es posible aprovechar plenamente las posibilidades de los dispositivos más simples por la sobrecarga que supone. Utilizar un único lenguaje de implementación complica o limita el uso de algunos microcontroladores y otros dispositivos de cómputo para sistemas empotrados que existen actualmente, sobre todo, los menos potentes, que son precisamente los que más nos pueden interesar. i i i i i i i i 6. F LUJO DE DISEÑO 159 Sin embargo, ofrecer la posibilidad de implementar el sirviente en cualquier lenguaje también presenta algunos problemas, que consideramos hemos resuelto satisfactoriamente: Debe existir una implementación de la máquina virtual en el lenguaje de la plataforma, o bien la posibilidad de generar código para el autómata, directamente en ese lenguaje. Debido a su sencillo diseño, la implementación de la máquina virtual en una plataforma nueva no es un esfuerzo significativo. Además, eso permite optimizar al máximo los recursos requeridos en la plataforma destino. Se requiere un medio para que el programador del sirviente y el desarrollador que escribe el fichero IcePick puedan determinar una correspondencia entre ambos, principalmente en lo referente a métodos y eventos, es decir, una interfaz. El resto de la sección muestra la forma en la que se ha resuelto este problema. Con el lenguaje SIS (Servant Interface Specification) proporcionamos un modo genérico para especificar la interfaz del sirviente independientemente del lenguaje en el que esté escrito. SIS es un lenguaje sencillo y puramente declarativo. El listado 6.7 muestra un ejemplo. Dispone sólo de dos elementos: métodos y eventos. event AUTOL OCK_EVEN T (5) ; local DUO . IBool . RW test (6) ; local DUO . IBool . RW qos (7) ; local DUO . IFloat . R threshold (8) { input = byte; } local DUO . IBool . RW get (3) { input = byte; } L ISTADO 6.7: SIS: Ejemplo de declaración de la interfaz de un sirviente 6.2.1. Métodos La declaración de métodos sirve para asignar un identificador entero a cada procedimiento de usuario (métodos del sirviente). La ejecución de los métodos es responsabilidad de la máquina virtual al encontrar una instrucción user_proc(). La declaración de un método consta de: Un tipo (remote o local). Una interfaz. Puede incluir una lista de tipos de entrada (input) y salida (output). En el caso de métodos locales, esta especificación de parámetros es obligatoria; es el único modo que tendrá el compilador para verificar que las invocaciones son correctas. i i i i i i i i 160 6. F LUJO DE DISEÑO En el caso de métodos remotos, el compilador puede extraer la signatura de las declaraciones de interfaces en el fichero S LICE o IDL correspondiente de modo que, en principio, no es necesario que aparezcan especificados aquí. Sin embargo, por limitaciones de memoria obvias, la máquina virtual no puede almacenar parámetros de tipos arbitrariamente complejos o largos como cadenas, secuencias, etc. Para resolver este problema, el sirviente debe proporcionar manejadores (métodos especiales) que se encargarán de leer y escribir este tipo de parámetros en el cable. Es decir, serían el equivalente a los procedimientos de (de)serialización en los middlewares convencionales. Estos manejadores se especifican en la lista de parámetros indicando el nombre de los métodos tal como se muestra en el listado 6.8. Por este motivo, cuando un método remoto de un objeto local utiliza parámetros de tipos variables es necesario incluir la especificación de parámetros en el fichero SIS. En éste, los métodos get() y set() corresponden al módulo DUO::IString, es decir, manejan una cadena de caracteres. En la línea 7 se indican dos procedimientos, separados por comas, que son los encargados de leer sendos parámetros del método set() (valor e identidad). La línea 11 indica cómo enviar el resultado del método get(). Requiere dos métodos: el primero (put_size) se utiliza para obtener el tamaño del valor de retorno, necesario para calcular el tamaño total del mensaje que ha de escribirse en la cabecera; el segundo (put_data) escribe la secuencia de bytes en la interfaz de red. 1 2 3 4 local local local local DUO . IString . RW DUO . IString . RW DUO . IString . RW DUO . IString . RW get_data (20) ; get_id (21) ; put_size (22) ; put_data (23) ; 6 7 8 remote DUO . IString . W set (11) { input = get_data , get_id ; }; 10 11 12 remote DUO . IString . R get (12) { output = put_size : put_data ; }; L ISTADO 6.8: SIS: Soporte a parámetros de tipos variables 6.2.2. Eventos Los eventos declarados en el fichero SIS corresponden con los utilizados en las cláusulas event de IcePick. Declaran eventos que serán activados exclusivamente bajo la responsabilidad del sirviente. Se especifica un identificador y un valor entero único. El identificador se escribe utilizando sólo mayúsculas por convenio. Como ejemplo, el listado 6.7 incluye una declaración de evento en la primera línea. 6.3. El compilador ipkc El compilador ipkc es la principal herramienta para la generación de picoObjetos. Se encarga de procesar los ficheros de entrada y construir un modelo que aglutina todos los i i i i i i i i 6. F LUJO DE DISEÑO 161 detalles que conciernen a la definición de un nodo. La entrada principal es un fichero en lenguaje IcePick. Ese fichero incluye referencias a ficheros externos que aportan las declaraciones de interfaces para el middleware que corresponda. 6.3.1. Estructura general La estructura del compilador sigue un diseño clásico de frontends/backends. Incluye de forma obligatoria frontends para los lenguajes IcePick y SIS. Para el reconocimiento de los ficheros de interfaz se requiere un frontend específico dependiendo del lenguaje concreto. Actualmente se dispone de un frontend para S LICE basado en la biblioteca libSlice de ZeroC y existe una versión preliminar para IDL. La figura 6.2 muestra la estructura general del compilador ipkc. Ilustra el caso en que se usa Slice para generación de objetos compatibles con I CE, que es la situación más habitual en el desarrollo de nuestros prototipos. La información de los ficheros fuente es reconocida por un analizador léxico y otro sintáctico, creados con las herramientas flex y bison de GNU. El resultado es un objeto SymbolTable que sirve como fachada al resto del modelo de datos. Sobre este objeto se aplican un conjunto de restricciones semánticas y posteriormente se utiliza por los backends para generación de código. Los backends son específicos para cada middleware puesto que es su responsabilidad aplicar el formato y restricciones del protocolo inter-ORB concreto. F IGURA 6.2: Diagrama de bloques del compilador ipkc Todo el diseño del compilador está orientado a objetos, lo cual facilita la modularización y la incorporación de nuevos elementos: frontales para otros lenguajes de especificación de interfaces y backends para generación de código. La versión actual del compilador está implementada en lenguaje C++ y permite backends escritos tanto en C++ como Python. i i i i i i i i 162 6. F LUJO DE DISEÑO El diseño de todos los frontends está basado en el uso del patrón visitor, de modo que su estructura es muy regular y puede ser replicada con facilidad para crear otros nuevos. Todos son reconocedores de una única pasada puesto que construyen un modelo programático completo del fichero de entrada, que más tarde es verificado. Por esta razón no es necesario hacer declaraciones adelantadas cuando un identificador se usa antes de ser definido. Las siguientes secciones incluyen la especificación formal de los lenguajes introducidos anteriormente. 6.3.2. Frontal para IcePick Tabla de tokens El cuadro 6.1 muestra los tokens del lenguaje IcePick. Incluye el nombre del token, la expresión para el reconocedor léxico y el lexema o ejemplos cuando la expresión describe un conjunto de valores posibles. Gramática El listado 6.9 muestra la gramática de IcePick en notación EBNF. Nótese que, por generalidad, es posible especificar construcciones que la implementación real del picoObjeto no permite. Concretamente, la gramática permite invocaciones como parámetros de otras de forma indefinida, sin imponer restricciones al tipo de las mismas. Sin embargo, en la implementación actual de la máquina virtual existen dos limitaciones que no refleja esta gramática: No es posible utilizar más de un nivel de anidamiento. Es decir, la expresión obj1.method1(obj2.method2()) es correcta, pero no lo sería una en la que method2 tuviera a su vez otra invocación por parámetro. Únicamente se pueden utilizar invocaciones a objetos locales como parámetro de otras, nunca a objetos remotos. En todo caso, estas limitaciones se refieren a la versión actual, pueden no afectar a implementaciones alternativas o ser subsanadas en futuras versiones. Ese es el motivo por el que estas limitaciones no se han reflejado en la gramática. 6.3.3. Frontal para SIS SIS es un lenguaje puramente declarativo muy sencillo. Se limita a la definición de eventos y signaturas de métodos. Describe los tipos de los parámetros de entrada y salida, y en el caso de tipos variables, permite la especificación de manejadores concretos para cada parámetro. El cuadro 6.2 muestra los tokens y el listado 6.9 la gramática del lenguaje en forma EBNF. 6.3.4. Frontal para S LICE En el caso de S LICE no ha sido necesario desarrollar un reconocedor completo ya que la distribución estándar de I CE incorpora la biblioteca libSlice para soporte a la i i i i i i i i 6. F LUJO DE DISEÑO 163 token expresión lexemas colon semicolon dot comma equal start_block end_block start_p end_p eq neq lt gt lteq gteq if boot do event local object remote timer adapter uses when int bool literal id : ; . , = { } ( ) == != < > <= >= if boot do event local object remote timer adapter uses when [0-9]+ true | false “[ˆ\n"]∗ ” [A-Za-z_][A-Za-z0-9_]∗ ‘:’ ‘;’ ‘.’ ‘,’ ‘=’ ‘{’ ‘}’ ‘(’ ‘)’ ‘==’ ‘!=’ ‘<’ ‘>’ ‘<=’ ‘>=’ ‘if’ ‘boot’ ‘do’ ‘event’ ‘local’ ‘object ‘remote’ ‘timer’ ‘adapter’ ‘uses’ ‘when’ 06, 1024 ‘true’, ‘false’ “LIT3R4L.”, “123f” ‘var_23a’, ‘_3f’ C UADRO 6.1: Tokens del lenguaje IcePick i i i i i i i i 164 6. F LUJO DE DISEÑO PROG ::= USES DECLS BLOCKS | USES DECLS USES ::= uses lit ; { uses lit ;} DECLS DECL ::= DECL ; { DECL ;} ::= OBJECT_DECL | ADAP_DECL OBJECT_DECL ::= object INTER id | object INTER id ’{ ’ ATTRS ’} ’ ADAP_DECL ::= local | remote adapter id ’{ ’ ATTRS ’} ’ INTER ATTRS ATTR ::= id . ::= ATTR ::= id = | id | id DICT KV ::= ’{ ’ { KV } ’} ’ ::= lit | id : lit | id | int BLOCKS LABEL ::= [ LABEL ] BLOCK {[ LABEL ] BLOCK } ::= id : BLOCK ::= WHEN | BOOT | EVENT | TIMER | FUNCTION WHEN BOOT EVENT TIMER FUNCTION ::= ::= ::= ::= ::= id {. id } ; { ATTR ;} id = lit = DICT when INVOCATION do ’{ ’ INVOCATIONS ’} ’ boot ’{ ’ INVOCATIONS ’} ’ event id do ’{ ’ INVOCATIONS ’} ’ timer ’( ’ int ’) ’ ’{ ’ INVOCATIONS ’} ’ function ’{ ’ INVOCATIONS ’} ’ INVOCATIONS ::= INVOCATION ; { INVOCATION ;} INVOCATION ::= id . id ’( ’ [ PARAMS ] ’) ’ [ if ’( ’ COND ’) ’] COND COMP ::= PARAM COMP PARAM ::= == | != | < | > | <= | >= PARAMS PARAM ::= PARAM { , PARAM } ::= true | false | id | id . id | lit | int | INVOCATION | DICT L ISTADO 6.9: Gramática del lenguaje IcePick en notación EBNF. Los caracteres entrecomillados corresponden a tokens definidos en el cuadro 6.1. Se representan así por legibilidad i i i i i i i i 6. F LUJO DE DISEÑO 165 token expresión lexemas colon semicolon dot comma equal start_block end_block start_p end_p local remote byte bool int float double long id : ; . , = { } ( ) local remote byte bool int float double long [A-Za-z_][A-Za-z0-9_]∗ ‘:’ ‘;’ ‘.’ ‘,’ ‘=’ ‘{’ ‘}’ ‘(’ ‘)’ ‘local’ ‘remote’ ‘byte’ ‘bool’ ‘int’ ‘float’ ‘double’ ‘long’ ‘var_23a’, ‘_3f’ C UADRO 6.2: Tokens del lenguaje SIS SIS DECL EVENT METHOD TYPE DEF ATTR LIST VAL ::= DECL { DECL } ::= EVENT ; | METHOD ; ::= event ’( ’ integer ’) ’ ::= ( remote | local ) TYPE id ’( ’ int ’) ’ | ( remote | local ) TYPE id ’( ’ int ’) ’ ’{ ’ DEF ’} ’ ::= id . id { id . id } ::= ATTR ; { ATTR ;} ::= ( input | output ) = LIST ::= VAL { , VAL } ::= TYPEVAL | id | id : id TYPEVAL ::= byte | double | long | float | int | bool L ISTADO 6.10: Gramática del lenguaje SIS en notación EBNF. Los caracteres entrecomillados corresponden a tokens definidos en el cuadro 6.2. Se representan así por legibilidad i i i i i i i i 166 6. F LUJO DE DISEÑO construcción de compiladores de S LICE. Para utilizarla, el programador debe aportar una clase visitante (en la jerga del patrón de diseño). 6.3.5. Compilador extensible La posibilidad de incorporar nuevos argumentos a la definición de los objetos y adaptadores permite especificar semántica adicional al lenguaje por medio de plugins. Éstos son útiles para simplificar el trabajo del programador aportando comprobaciones semánticas adicionales y generación de código específica para entornos y situaciones concretas. Se muestran dos casos para módulos DUO. Objetos activos Un caso evidente de esta situación es el módulo DUO::Active (véase § 3.4). Los requisitos para la implementación de objetos DUO activos son demasiado particulares como para tener cabida en una especificación genérica de objetos distribuidos como la que pretende IcePick. Por otra parte, la funcionalidad que requieren los objetos activos es idéntica en todos los casos (almacenar y recuperar proxies) y resulta muy conveniente poder generar el código correspondiente cuando un objeto lo requiera. La solución ha sido crear un plugin que se incorpora al compilador ipkc, realizar las comprobaciones semánticas necesarias (interfaces implementadas por el objeto) y generar el código que le otorga a los objetos del nodo la capacidad de actuar como activos. Para hacer uso del plugin, el programador simplemente debe utilizar interfaces que hereden de DUO::Active::R o DUO::Active::W y añadir los atributos necesarios (topic y publisher). Contenedores Un caso similar es la interfaz DUO::Container. Este plugin se encarga de generar el código necesario para la implementación de los métodos que corresponden a dicha interfaz, de modo que el programador no tiene que preocuparse por ello, simplemente tiene que heredar de la interfaz DUO::Container::R o W. El atributo children se puede utilizar opcionalmente para indicar qué objetos están incluidos en el contenedor en el momento de su creación; ésta es la única opción si se trata de un contenedor de sólo lectura (R). 6.3.6. Soporte para macro-programación El objetivo inicial para el lenguaje FSM es la definición del comportamiento de un nodo en el que pueden residir varios objetos. IcePick, por contra, está orientado a la descripción de escenarios en los que se relacionan e interactúan varios objetos, del mismo o de diferentes nodos. En los ejemplos que se han mostrado hasta ahora aparecía sólo un adaptador local, que representa el punto de conexión del nodo en la red. En un sistema distribuido tradicional, un nodo puede disponer de varios adaptadores de objetos, ya sea en distintos puertos o en diferentes interfaces de red. Si hay relación entre los servicios que ofrecen (p.ej. un servicio de bridging) pueden ser considerados conceptualmente como un mismo nodo de la red. Por i i i i i i i i 6. F LUJO DE DISEÑO 167 contra, si los adaptadores alojan servicios independientes puede ser considerados nodos lógicos diferentes aunque se ejecuten en la misma máquina. Ambos escenarios son posibles en IcePick simplemente definiendo más de un adaptador local en el fichero fuente. Pero es posible ir un paso más allá. Podemos especificar una aplicación que involucra a varios nodos físicamente diferentes tal como hacer los lenguajes de macro-programación (véase § 2.5). Es necesario definir al menos un adaptador para cada nodo y modelar las interacciones por medio de triggers. Después el compilador genera un fichero FSM para cada nodo. Para soportar esta funcionalidad es necesario añadir una nueva estructura sintáctica al lenguaje (node), que agrupa uno o más adaptadores. Como ejemplo, la figura 6.3 muestra interacciones entre 4 objetos situados en 3 nodos diferentes, el listado 6.11 es el fichero IcePick equivalente. Al compilar ese fichero se obtienen 3 ficheros FSM independientes, que pueden instalarse sobre plataformas diferentes. uses " DOBS / DUO . ice "; object object object object DUO . IBool . W DUO . IBool . W DUO . IBool . W DUO . IBool . W obj0 ; obj1 ; obj2 ; obj3 ; local adapter ad1 { endpoint = " tcp −h 10.0.0.1 −p 1000"; objects = {" UUID00 ": obj0 , " UUID01 ": obj1 }; }; local adapter ad2 { endpoint = " tcp −h 10.0.0.2 −p 1000"; objects = {" UUID02 ": obj2 }; }; local adapter ad3 { endpoint = " tcp −h 10.0.0.3 −p 1000"; objects = {" UUID03 ": obj3 }; }; node node1 { adapters = [ ad1 ]; } node node2 { adapters = [ ad2 ]; } node node3 { adapters = [ ad3 ]; } when obj1 . set () do { obj2 . set ( obj1 . status () , obj1 . oid ) ; obj3 . set ( obj1 . status () , obj1 . oid ) ; } when obj2 . set () do { obj0 . set ( obj2 . status () , obj2 . oid ) ; } when obj0 . set () do { obj3 . ice_ping () ; } L ISTADO 6.11: IcePick: Ejemplo de macro-programación i i i i i i i i 168 6. F LUJO DE DISEÑO F IGURA 6.3: Ejemplo de macro-programación El soporte para características de macro-programación en el compilador ipkc es muy preliminar. Por el momento su principal objetivo es demostrar que es posible aplicar este enfoque y que no es en absoluto incompatible con un modelo centrado en el nodo. 6.3.7. Generación de FSM El backend slice2fsm es en el que se ha centrado la mayor parte del esfuerzo de desarrollo hasta el momento puesto que se ha empleado en prácticamente todos los prototipos actuales. En su diseño se ha aplicado el patrón Builder empleando un modelo lógico del código FSM que se pretende generar. Eso facilita la inclusión de código en cualquier momento y bloque, y también su posterior reordenamiento y optimización. Gran parte del código generado se basa en plantillas FSM que se pueden instanciar y parametrizar. Una vez terminada la generación se renderiza ese modelo sobre un fichero de texto. Gestión de memoria El módulo slice2fsm es el encargado de planificar el uso de la memoria del picoObjeto determinando qué valores pueden ir a ROM (zona DATA), a RAM (banco de registros) o a la zona de persistencia. Como vimos, algunos registros tienen un uso y ubicación prefijada, debido a que pueden ser accedidos también desde el sirviente. Otros registros, como las variables necesarias para los parámetros de las invocaciones deben ser decididos aquí. Estas variables son compartidas por todas las invocaciones para parámetros de entrada y salida, de modo que el ahorro de memoria sea máximo. El backend reserva tantas variables como parámetros tenga el método con más parámetros de cualquiera de las interfaces de los objetos que aloja el nodo. Del mismo modo, el tamaño de cada variable depende del mayor tamaño para el parámetro en esa posición en todas las interfaces. i i i i i i i i 6. F LUJO DE DISEÑO 169 Los fragmentos utilizados para la composición de mensajes se sitúan en ROM. Muchos de ellos tienen partes comunes. Algo especialmente común en las cadenas que se utilizan para identificación de los tipos (Type IDs en la terminología de I CE) puesto que tienen las mismas raíces . Muchos de esos fragmentos pueden ser almacenados sólo una vez para conseguir un significativo ahorro de memoria. Sin embargo, esa es una optimización que debe realizarse después, cuando se haya determinado el contenido completo de la memoria. Invocaciones Realizar una invocación a un objeto remoto implica generar código para: Abrir una conexión activa, lo cual requiere disponer de la dirección del adaptador remoto almacenada en memoria ROM o Flash. Una cabecera de invocación, que incluye el tamaño total del mensaje. La identidad del objeto remoto. El nombre del método. Una cabecera de encapsulación, con su tamaño. El valor de los parámetros. Puede implicar la invocación de métodos locales del sirviente si estos parámetros son variables. Un mensaje de cierre de conexión. Cerrar la conexión activa. Como se apuntaba anteriormente, el mensaje de respuesta se descarta si lo hubiese. En la mayor parte de los casos su uso está pensado para notificación de eventos sobre trasporte oneway o no confiable. Por la misma razón, no es posible utilizar un valor de retorno para otra acción. El tratamiento de las invocaciones a objetos locales es muy diferente. Cuando el objeto es local no se realiza una conexión ni se construye un mensaje de invocación, la operación se reduce a colocar el valor de los parámetros en los registros adecuados y ejecutar el método del sirviente con la instrucción user_proc(). Las invocaciones a objetos locales sí pueden devolver un valor de retorno, que se puede utilizar en otra invocación local o remota, tal como muestra el listado 6.4 (línea 2). Ese es el límite de anidamiento, no es posible realizar invocaciones anidadas de más de dos niveles con la versión actual de este backend. Optimizaciones Muchas tareas en el funcionamiento del picoObjeto requieren de datos estáticos o parametrizables. Los más importantes son: Datos de conexión a dispositivos remotos: direcciones IP, MAC o de otro tipo, puertos, etc. Identidades de objeto, ya sean remotos para realizar invocaciones, o locales para construir y retornar proxies. i i i i i i i i 170 6. F LUJO DE DISEÑO Identificadores de tipo (Type IDs), como resultado de las operaciones ice_id() e ice_ids(), por ejemplo. Cabeceras de mensajes. Cabeceras de encapsulación. Todos estas secuencias de bytes se deben colocar en la memoria ROM para que estén disponibles durante la ejecución. El backend slice2fsm recopila estas cadenas a partir del fichero fuente IcePick y de las especificaciones propias del protocolo. Una vez terminado este proceso es sencillo comprobar que muchas de esas cadenas, o partes de ellas, se repiten incluso varias veces. Por ejemplo, un actuador que utilice el módulo DUO::IFloat debe devolver las cadenas DUO::IFloat::R y DUO::IFloat::W cuando se invoque su método ice_ids(). En ese caso, lo ideal sería almacenar la raíz común una sola vez. Para conseguir una solución óptima se debe favorecer la reutilización de los fragmentos, evitando al mismo tiempo que sean demasiado pequeños. Cada fragmento tiene un coste de 1 byte (tamaño) además de la propia cadena; y enviarlo con la instrucción put_data requiere 2 bytes de bytecode. Se requiere un algoritmo que optimice el consumo total de memoria ROM para las cadenas y de instrucciones necesarias para utilizarlas. Para la fragmentación óptima del conjunto de cadenas se utiliza un algoritmo de texto predictivo, similar al que se emplea en los teléfonos móviles para edición de mensajes SMS. Se obtiene un grafo acíclico dirigido que indica la secuencia de fragmentos para conseguir cada cadena completa y el mapa de memoria tal como debe quedar en la zona DATA. 6.4. Drivers Intentado respetar lo máximo posible el planteamiento típico de los MDOO, hemos dado por hecho que el código de los sirvientes debe ser aportado por el programador, avalada esta teoría por el hecho de que puede haber una cantidad importante de plataformas diferentes, que utilizan distintos lenguajes de programación, métodos y protocolos para acceder a los periféricos (transductores). A pesar de ello, hemos hecho un esfuerzo por evitar al programador la necesidad de realizar tareas repetitivas. Gracias al uso de plugins, el compilador puede aportar parte de la funcionalidad del sirviente implementándola en la lógica de la máquina de estados. Siguiendo la misma idea y basándonos en la experiencia adquirida, vemos que el camino a seguir pasa por reducir la implementación del sirviente a su mínima expresión. Es más conveniente expresar toda la funcionalidad posible en IcePick y delegar en el sirviente únicamente el acceso al dispositivo y la responsabilidad de mantener el estado del transductor, cuando sea necesario. De esta manera, la funcionalidad del nodo está disponible en cualquier plataforma ya que se encuentra en el bytecode. En estos términos, las tareas que debe desempeñar el sirviente son: Acceso a los buses de dispositivo, como I2C, RS232, one-wire, etc. i i i i i i i i 6. F LUJO DE DISEÑO 171 Filtrado o conformación de señales, eliminación de ruidos, corrección de datos espurios, etc. Generación de eventos asíncronos, por medio de una Rutina de Servicio de Interrupción (RSI) o polling, dependiendo de las posibilidades del dispositivo. Almacenamiento del estado del dispositivo, si no es posible su lectura (X10) o el programador no lo considera eficiente. Lectura y escritura de parámetros de tipos variables desde/hacia las invocaciones, si los hubiere. La interfaz del sirviente se describe como siempre en un fichero SIS, convirtiéndose entonces en una entidad opaca, similar en algunos aspectos a un componente (interfaz + eventos), y que podríamos denominar driver. Otros middlewares basados en máquina virtual como Maté [LC02] o WSP [BLV09] han hecho un esfuerzo por especificar toda la funcionalidad del sirviente utilizando el repertorio de instrucciones virtual. El problema de ese enfoque es que acopla el sistema a un dispositivo concreto o familia de ellos. En imposible prever en la V-ISA todos los tipos posibles de transductores y dotar al run-time de código específico para manejarlos todos. Nuestro enfoque es más parecido al de SensorWare [BHSS07], aunque en nuestro caso no es imprescindible la existencia del driver. Es necesario recordar además que SensorWare tiene requerimientos de memoria y plataforma varios órdenes de magnitud mayores. Se puede desarrollar una biblioteca de drivers por cada plataforma soportada, implementada con un enfoque generalista. En una misma aplicación es poco probable que se requieran muchos tipos de drivers, pero si se requiere un driver no disponible, o cuya funcionalidad equivalente no pueda ser especificada en IcePick, siempre existirá la posibilidad de implementar el sirviente concreto a mano. Se trata de una solución más flexible que propuestas anteriores pues puede aplicarse a situaciones en las que muchas de ellas no lo serían (nueva plataforma o transductor), aun a costa de un esfuerzo adicional. 6.5. Plataforma para desarrollo de picoObjetos Los compiladores ipkc y fsm2data, y la implementación de la máquina virtual FSM para PC constituyen un conjunto de herramientas completo para el desarrollo de picoObjetos. Hacen posible la especificación, diseño, implementación, integración y prueba de objetos distribuidos en dispositivos empotrados. La máquina virtual dota al conjunto de gran flexibilidad. El código FSM puede ejecutarse sobre un PC, en un entorno distribuido real, incluso sobre la misma aplicación objetivo, sin necesidad de programarla en el nodo. Una vez probado y cuando se tienen ciertas garantías, se genera el bytecode equivalente para el dispositivo final. Con ello se recortan sensiblemente los tiempos de prueba y verificación sobre la plataforma concreta. La figura 6.4 describe todas las fases del proceso de compilación, desde los ficheros de especificación de interfaces, descripción del nodo (IcePick) y del sirviente (SIS), hasta la obtención del fichero binario para programar en el dispositivo. i i i i i i i i 172 6. F LUJO DE DISEÑO F IGURA 6.4: Plataforma completa para desarrollo y prueba de picoObjetos La característica más interesante del planteamiento es que permite utilizar un middleware convencional de propósito general sin ninguna modificación ni adaptación, dentro y fuera de la red de transductores. No afecta a ninguno de los procesos paralelos relacionados con el desarrollo de aplicaciones y servicios, involucren o no a las redes de dispositivos. El contrato que impone el middleware desacopla el trabajo entre los proveedores y los usuarios de los servicios. Por la misma razón, estos grupos pueden trabajar de forma independiente. Es sencillo desarrollar aplicaciones mínimas que substituyan uno de los lados (servidor o usuario). Los diseñadores y desarrolladores de aplicaciones y servicios para el entorno inteligente no necesitan formación especial. Cualquier programador habituado al trabajo con CORBA, EJB, .Net o Web Services puede ser productivo de inmediato. i i i i i i i i 6. F LUJO DE DISEÑO 173 Se utilizan los mismos conceptos y, salvando las distancias, existen abstracciones prácticamente equivalentes en todos ellos. Esa misma independencia se consigue también a nivel de dispositivo gracias a la máquina virtual. El diseñador/programador de servicios sobre el picoObjeto no necesita conocer los detalles de cada plataforma. La implementación de la máquina virtual para un dispositivo concreto no afecta ni se ve afectada por el funcionamiento de otros dispositivos. Por último, la creación de drivers puede ser también una tarea independiente, dado que sólo atañe a la gestión de los transductores y no tiene relación directa con la funcionalidad del nodo ni con la aplicación distribuida. La figura 6.5 muestra los distintos roles del personal involucrado y sus áreas de interés. F IGURA 6.5: Diferencias entre las tareas del diseñador de aplicaciones para el sistema y el programador de los nodos En la medida en que un middleware establecido cuente con el soporte adecuado en determinada tecnología o fabricante de dispositivos para redes SAN, no hay nada especial en el flujo de diseño utilizado en el desarrollo de aplicaciones para dichas redes. La mayoría de los servicios y aplicaciones finales están desarrolladas usando un flujo convencional y cualquiera de las herramientas disponibles comercialmente. i i i i i i i i 174 6. F LUJO DE DISEÑO El desarrollo de nodos SAN se integra perfectamente con el del middleware. Los cabos del cliente se generan como siempre, utilizando el compilador de interfaces que incorpora el ORB. Cuando el servidor es un picoObjeto, se utiliza ipkc partiendo de los mismos ficheros de interfaz. Respetar este modelo de desarrollo, habitual en los MDOO, aporta importantes beneficios a la construcción de aplicaciones con redes SAN desde el punto de vista metodológico. El analista/diseñador de la aplicación puede ver los nodos de la red SAN como entidades autónomas y opacas que poseen un rol claro ya desde fases tempranas del diseño del sistema. Es decir, el diseño de una aplicación que emplea redes SAN es completamente equivalente a cualquier otra aplicación basada en objetos. El desarrollador de la aplicación utiliza interfaces de programación genéricas y de alto nivel que permiten desacoplar el diseño de las cuestiones específicas de la tecnología del nodo. Los nodos transductores se pueden usar como cualquier otro objeto del sistema. El mismo middleware se utiliza en todas las fases y en todos los niveles. Los nodos se especifican por medio de un lenguaje de alto nivel (IcePick) indicando únicamente los tipos e identidades de los objetos involucrados y sus relaciones básicas. El desarrollador del código empotrado dispone de un conjunto de herramientas para automatizar la generación de la infraestructura de comunicaciones, conseguir la interacción entre los nodos de la red SAN y casi cualquier sistema externo. Programar y configurar una red de sensores es una tarea difícil y propensa a errores [CGG+ 05]. Empleando picoObjetos, el compilador genera todo el código relacionado con las comunicaciones, permitiendo al desarrollador concentrarse únicamente en los detalles relativos al acceso a los transductores y al tratamiento de los datos procedentes de éstos. i i i i i i i i Integración de redes heterogéneas 7.1. 7.2. 7.3. 7.4. 7.5. 7.6. 7.7. 7.8. Introducción Direccionamiento Endpoints Gestión de calidad de servicio Entrega de mensajes Encaminamiento Integración con el middleware Conclusiones 77 L A gran diversidad en protocolos y tecnologías existentes dificulta en muchas ocasiones el desarrollo de mecanismos para lograr interoperabilidad entre aplicaciones que se ejecutan en nodos cualesquiera, sea cual sea el tipo de red en la que se encuentren. No siempre es posible ni deseable utilizar el mismo protocolo de red. Un buen ejemplo de este problema es el acceso a los nodos de una red de sensores. Tales dispositivos utilizan tecnologías de red como Zigbee o Bluetooth, que si bien pueden operar con la pila TCP/IP, su adopción suele requerir un esfuerzo considerable y no siempre se obtienen soluciones óptimas. Otras tecnologías pueden implicar protocolos especializados o hardware propietario, lo cual en algunos casos, puede hacer inviable esa posibilidad. Desde el punto de vista de las SAN, éste es un asunto pendiente —al menos no totalmente resuelto— en lo concerniente al transporte transparente de mensajes entre una red troncal y las redes de sensores a las que está conectada. En particular buscamos una solución para los siguientes dos casos, pero lo suficientemente flexible como para cubrir muchos otros. Acceso desde el SI convencional de cualquier organización a las redes de sensores que se desplieguen como soporte a servicios cualesquiera. Interacción entre nodos de dos o más redes SAN con diferente tecnología, incluso si fuera necesario atravesar otras intermedias, de cualquier tipo. A fin de cuentas, el objetivo es poder enviar mensajes desde una red a cualquier otra sin importar que utilicen tecnologías o protocolos de red incompatibles. 175 i i i i i i i i 176 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS 7.1. Introducción Tal como vimos en la sección 2.6, existen varias alternativas para lograr la interconexión de redes heterogéneas. En la inmensa mayoría de los protocolos, middlewares y sistemas diseñados para la conectividad de redes SAN se considera, casi por descontado, que el sistema cuenta con una única pasarela de servicio que es utilizada por las redes externas para acceder a los nodos de la SAN. La pasarela aloja normalmente componentes software cruciales para el acceso a los nodos, lo que conlleva una gran cantidad de problemas que ya se comentaban en la sección 2.6.2. Comparando las diferentes alternativas que se plantean en la citada sección, parece que la solución más flexible y eficiente es la utilización de un protocolo de red común, incluyendo la definición de un esquema de direccionamiento global. Dado que obviamente no se pretende substituir IP, pero sí resolver los problemas que el uso de la pila TCP/IP puede suponer en ciertos ámbitos, el camino adecuado parece ser un protocolo no solo independiente de la red, también del transporte. Construir un nuevo protocolo sobre la capa de enlace implicaría reinventar la rueda enfrentándonos a problemas ya resueltos por otros ya probados y admitidos. La alternativa más adecuada es usar el protocolo o pila que resulte más natural en cada entorno y construir nuestro protocolo homogeneizador en una capa superior. La especificación «CORBA Message Routing» [Obj08b, cap. 17] (en adelante CMR) apunta en el camino correcto. El middleware proporciona una capa de abstracción lo suficientemente consistente como para ocultar los detalles de las tecnologías software y hardware subyacentes, se puede implementar sobre una gran diversidad de sistemas siempre que se cumplan ciertas condiciones (en función del middleware concreto), proporciona un sistema de direccionamiento abstracto mediante referencias interoperables a objetos, etc. Sin embargo, las motivaciones y decisiones de diseño de CMR no corresponden a un protocolo general de encaminamiento de mensajes. Al menos los siguientes aspectos resultan inadecuados o contrarios en relación a los objetivos que perseguimos: Los encaminadores no disponen de tablas de encaminamiento que permitan construir rutas extremo a extremo en colaboración con los encaminadores vecinos. La ruta queda determinada por las referencias indicadas en la propia referencia de objeto destino y/o de decisiones administrativas locales del ORB en el que ejecuta el encaminador intermedio. La ruta que sigue la invocación es una forma de lograr tolerancia a fallos ante la imposibilidad de entregar el mensaje directamente al destino, o a circunstancias que impliquen la desactivación temporal (o definitiva) de parte de los encaminadores involucrados. No prevé la posibilidad de implementar encaminamiento dinámico que permita establecer rutas alternativas ante cambios en la carga, disponibilidad o desempeño de los recursos de la red. Las referencias a objetos, que son el equivalente funcional a direcciones universales, pueden tener tamaños arbitrarios. Dado que contienen una cantidad no acotada de perfiles y componentes, que incluyen a su vez la lista de encaminadores posibles, el tamaño de estas referencias puede alcanzar con facilidad miles de bytes. i i i i i i i i 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS 177 No se puede considerar que éstos sean fallos de diseño en la especificación de CMR. Simplemente ocurre que su finalidad es diferente, lo cual dificulta su aplicación al problema de la interconexión genérica de redes. Este capítulo propone la especificación e implementación de un nuevo protocolo llamado Inter-Domain Messaging (IDM) , y de los mecanismos asociados para emplear un MDOO de propósito general para encapsular y transportar mensajes como invocaciones a objetos, aprovechando algunos aspectos del diseño de CMR, IP y otros protocolos existentes, pero cuidando otros aspectos que consideramos esenciales para nuestro propósito: Mantener una sobrecarga lo suficientemente baja como para permitir su aplicación a cualquier tipo de red, en especial las que tienen un MTU pequeño, como es habitual en las SAN. Menor sobrecarga de cabeceras implica también transmitir menos bytes y por tanto consumir menos energía. Incorporación de información tanto a la red como a los propios mensajes, que haga posible encaminamiento dirigido por requisitos de Q O S, tanto DiffServ (basado en clase) como IntServ (basado en flujo). El protocolo ha de ser lo suficientemente genérico como para implementar algoritmos de encaminamiento dinámico sobre él. Debe tener capacidades de cross-layer, que permitan eliminar capas o prestaciones innecesarias en función de los requisitos demandados por el cliente. Debe definir un esquema de direccionamiento universal, jerárquico, con direcciones de tamaño máximo acotado pero lo más pequeñas posible. El direccionamiento universal, que potencialmente puede incluir nodos de miles de redes, puede implicar direcciones de tamaño considerable. Por ello, es necesario llegar a un compromiso que satisfaga ambos requisitos contrapuestos. Tanto los elementos finales como los encaminadores de la red se modelarán e implementarán como objetos distribuidos convencionales. Además, el programador dispondrá de dos posibles puntos de vista a la hora de diseñar su aplicación: Un mecanismo transparente para la aplicación cliente, por medio de un API similar al de los sockets BSD. Una referencia a un objeto remoto (mediante un proxy) sobre la que puede invocar métodos conforme a su tipo. 7.1.1. Inter-redes Consideremos el problema como analogía a la red más conocida por todos. Internet, como en la mayoría de las redes, se fundamenta en el uso de un protocolo de red único, en este caso IP. Un esquema global de direcciones lógicas permite la interconexión de redes con distintas tecnologías en la capa de enlace y física. Por tanto, para que una red pueda formar parte de una inter-red requiere que se cumplan ciertas condiciones básicas: Los hosts deben entender el esquema de direccionamiento lógico. Los hosts deben poder fabricar y entramar paquetes sobre la tecnología de red subyacente. i i i i i i i i 178 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS En el caso de que se trate de un medio de difusión, debe existir un mecanismo que permita mapear direcciones lógicas a físicas. Debe existir una pasarela o encaminador capaz de reenviar (forward) paquetes entre redes diferentes, realizando los procesos de desentramado y entramado que correspondan a los protocolos de enlace de cada red. En Internet, cuando se precisa atravesar una red que utiliza un protocolo de red incompatible, la solución suele ser alguna técnica de tunneling, aunque eso impide normalmente implantar un esquema de encaminamiento homogéneo. El otro problema evidente es enviar datos entre dispositivos de esas redes, que tienen protocolos de red y direcciones lógicas incompatibles. 7.1.2. Encaminamiento homogéneo Nuestro objetivo es proporcionar un servicio de transporte de mensajes extremo a extremo, independiente de las tecnologías de las redes intermedias, aprovechando los protocolos y tecnologías disponibles en cada dominio a fin de no reimplementar funcionalidades ya disponibles. En muchos sentidos se trata de cumplir uno de los requisitos que planteaba el ISTAG [DBS+ 01] para los entornos inteligentes en cuanto a la necesidad de una infraestructura de comunicaciones integradora. También es una de las necesidades identificadas a menudo en los middlewares para redes de sensores [R0̈4]. IDM no delega el direccionamiento a las capas inferiores aunque sí puede delegar el encaminamiento. En ese aspecto cada red puede considerarse un SA. Por ejemplo, en una red TCP/IP se pueden encapsular los mensajes sobre paquetes IP y delegar el encaminamiento en los protocolos habituales, mientras que en una red MANET sin IP se puede implementar un protocolo de encaminamiento tipo AODV cuyos mensajes van encapsulados en mensajes de nuestro protocolo. La combinación de un middleware con la posibilidad de encaminamiento multicapa (cross-layer) extremo a extremo aporta muchas y valiosas ventajas: Direccionamiento Realmente global e independiente de la tecnología y el protocolo. Red virtual Posibilita el despliegue de redes virtuales sobre cualquier tipo de red existente o futura. Calidad de servicio Proporciona soporte para aplicar políticas de calidad de servicio de alto nivel, puesto que se puede manejar información mucho más rica en las capas superiores. Flexible Y adaptable a las necesidades de la aplicación. Utilizar un middleware de comunicaciones no implica necesariamente una sobrecarga de protocolos ni un aumento significativo de la complejidad. Por ejemplo, es perfectamente viable encapsular mensajes sobre tramas Ethernet, si los requerimientos de calidad de servicio solicitados lo permiten. i i i i i i i i 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS 179 Servicios de la plataforma Por el hecho de utilizar un middleware de comunicaciones de propósito general, se puede contar con muchos de los servicios comunes que incorpora. En el caso de nuestro prototipo actual (basado en I CE) podemos destacar: cifrado y autenticación transparentes, soporte multi-lenguaje, persistencia automática, despliegue, activación implícita, balanceo de carga, replicación transparente, etc. Transparencia de localización Nuestros encaminadores son entidades lógicas y, por tanto, pueden ser migrados o replicados a otros nodos de la red de forma transparente. Encaminamiento funcional Esta cualidad permite plantear esquemas y algoritmos de rutado basados en agrupaciones funcionales de nodos y no solo en su localización geográfica. Eficiencia Nuestros encaminadores también se pueden implementar sobre sistemas empotrados. Es posible utilizar plataformas que van desde microcontroladores, como los que incluyen los nodos de una SAN hasta sistemas sintetizables sobre lógica reconfigurable, como FPGA (Field-Programmable Gate Array). Esto es posible utilizando picoObjetos. Orientado a Objetos Si el programador lo desea, es posible ver al servidor como un objeto remoto por medio de la declaración de su interfaz. Si se trata de un servicio orientado a flujo o que no requiere semántica en la invocación, es posible utilizar un API alternativo con primitivas read/write. 7.1.3. Acerca de los prototipos En la sección 8.7 se describe en detalle el diseño de algunos de los prototipos iniciales. Para su implementación se ha utilizado I CE. Sin embargo, las propuestas que se plantean aquí no son específicas de éste. Se puede utilizar cualquier middleware heterogéneo basado en objetos distribuidos. A lo largo del texto se harán referencias a algunas de las características y particularidades de este middleware pues consideramos que puede ayudar a una mejor comprensión de los conceptos que se exponen. 7.2. Direccionamiento Los esquemas de direccionamiento de red tradicionales utilizan una dirección lógica que identifica al host, delegando la identificación de la aplicación destino (el servidor) a los protocolos de la capa de transporte, llamados puertos en el caso de TCP y UDP. IDM utiliza un esquema de direcciones jerárquico, en el que se reserva un sufijo para identificar la aplicación. Estas direcciones son realmente identidades de objetos. Si se desea direccionamiento global, se puede usar cualquier esquema de identificadores que garantice la unicidad, llamados GUID (Globally Unique IDentifiers), y que permita obtener i i i i i i i i 180 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS identificadores jerárquicos. Aunque es posible, no es estrictamente necesario que la dirección identifique el host en el que reside el objeto. El cliente solo necesita conocer la identidad de objeto, que puede entenderse a todos los efectos como una dirección lógica. Para llevar a cabo la transmisión de los datos se precisa de un endpoint. Éste encapsula la implementación del transporte sobre una tecnología o protocolo concreto: TCP, UDP, IP, Ethernet, Crossbow (XB OW), Bluetooth, etc. La elección del endpoint la realiza el encaminador en base a las restricciones de calidad de servicio especificadas por el cliente y de la disponibilidad de las interfaces físicas en el nodo en el que reside. La transmisión puede no ser posible si no se satisfacen estas condiciones. IDM proporciona mecanismos para localizar la dirección del endpoint de un objeto a partir de su identificador sin que sea necesario conocer su ubicación. Más concretamente, sirve para averiguar el endpoint del adaptador en el que está registrado el objeto destino. 7.2.1. Identidad del objeto Desde el punto de vista funcional, el identificador de objeto es una secuencia de bytes globalmente única con dos campos relevantes: Aplicación Identifica el propósito del servicio, es decir, el objetivo común de todos los objetos que la comparten. Ejemplos válidos podrían ser una red P2P, un conjunto de suscriptores a un servicio de streaming, etc. Debe entenderse como un filtro y, por ello, su uso no es obligatorio. Este campo puede ser utilizado por los encaminadores para dar un tratamiento especial a todos los mensajes que corresponden a una aplicación determinada, aplicando técnicas de traffic shaping o priorización por contenido. Nombre Identifica el objeto independientemente de la aplicación. Un objeto dado tiene el mismo nombre en todas las aplicaciones en la que esté involucrado, aunque también es posible que un mismo objeto tenga más de un nombre y, por tanto, varias identidades incluso dentro del contexto de la misma aplicación. El campo nombre debe utilizar necesariamente un esquema jerárquico, pues esa es la base del funcionamiento de las tablas de rutas que se emplean. Una de las características diferenciadoras es que este tipo de jerarquía puede ser funcional además de geográfica (ver figura 7.1). Esto aporta una gran flexibilidad y permite la migración transparente de nodos y encaminadores. Aunque pueden desplegarse encaminadores en cualquier punto de la red, es imprescindible que existan al menos en las fronteras entre redes distintas pues el objetivo de IDM es precisamente la interconexión de redes. 7.2.2. Un posible esquema de direccionamiento Para ilustrar el sistema de direccionamiento se propone un esquema concreto basado en IP V 6. Nótese que se trata únicamente de un ejemplo para ilustrar lo explicado en la sección anterior. El uso de este tipo de direcciones no implica utilizar ninguna de las restricciones documentadas en la RFC 2460 [DH98]. Se propone como un esquema de i i i i i i i i 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS 181 F IGURA 7.1: IDM: Ejemplo de encaminamiento funcional direccionamiento general. En principio IDM está diseñado como un protocolo genérico para el transporte de mensajes en aplicaciones distribuidas, no como un substituto de IP. Normalmente no serán necesarias direcciones tan grandes. En redes virtuales, de propósito específico o con un número reducido y acotado de nodos, es posible utilizar direcciones mucho más sencillas, de sólo unos pocos bytes. A partir del espacio de direccionamiento de 2128 definido en IP V 6, proponemos un esquema jerárquico multinivel similar al que se define en la RFC2073 [RLH+ 97]. La figura 7.2 representa ese formato. F IGURA 7.2: Un posible esquema de direccionamiento para IDM El espacio de direcciones queda dividido en los siguientes campos: Aplicación (32 bits). Tal como se indicaba se utiliza para identificar una aplicación o red lógica concreta. Organización (32 bits). Identifica la institución responsable o propietaria del objeto. Sección (8 bits). Niveles organizativos intermedios. Unidad (8 bits). Subred (16 bits). Nodo (16 bits). Identifica un nodo lógico dentro de la red. Un mismo dispositivo puede contener varios. Objeto (16 bits). Identifica un objeto dentro del nodo. Nótese que en ningún momento la utilización de este tipo de direcciones implica la necesidad de utilizar nada de IP V 6 en la capa de red, ni tan siquiera una pila de protocolos tipo TCP/IP. Es decir, no existe ninguna posibilidad de ambigüedad o colisión entre estos identificadores y la dirección lógica de la interfaz de red del dispositivo en que reside, incluso en el caso en que utilice una implementación real de IP V 6 en la capa de red. i i i i i i i i 182 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS 7.3. Endpoints Un endpoint es una estructura lógica independiente que encapsula todos los detalles del transporte de datos para una tecnología o protocolo subyacente. Bajo la perspectiva de IDM, no hay diferencias funcionales entre un endpoint que permite abrir y mantener una conexión TCP sobre una VPN, de otro que envía tramas SLIP sobre un cable RS-232. Las diferencias están en las prestaciones del endpoint, pero no en su uso. El endpoint es responsable de las siguientes tareas: Construye las tramas IDM, serializa y encapsula la invocación del usuario, calcula sumas de verificación, información redundante, autenticación, etc. Todo esto se realiza apoyándose lo máximo posible en los servicios proporcionados por el middleware. No tiene porqué suponer un trabajo excesivamente complejo. Oculta todos los detalles relacionados con el uso de un protocolo o interfaz de comunicaciones. Enumera y comprueba las prestaciones de Q O S que ofrece cada transporte y tecnología concreta. I CE incluye de serie únicamente tres tipos de endpoints: TCP, UDP y SSL. Nosotros hemos desarrollado algunos más: Socket UNIX, colas de mensajes y Crossbow. La figura 7.3 ilustra la relación que tiene IDM con el modelo tradicional de capas por medio de los distintos endpoints. Dicha figura refleja que la elección no está condicionada por el protocolo de bajo nivel o la capa a la que pertenezca sino por la funcionalidad que proporcione, es decir, sus prestaciones de Q O S. F IGURA 7.3: Relación de IDM con el modelo de capas de red tradicional Cada endpoint tiene una representación textual que especifica el protocolo de nivel inferior utilizado, la dirección lógica o física, el puerto o cualquier otra información necesaria para establecer la conexión o el envío, y otros datos como timeouts, certificados para cifrado, etc. En IDM existe un tipo de endpoint muy especial que se encarga de anteponer la cabecera IDM a los mensajes del protocolo inter-ORB convencionales. En el caso de I CE, eso simplifica el uso de IDM sobre la distribución software; no hay necesidad de modificar nada en el código que proporciona el fabricante. i i i i i i i i 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS 183 IDM podría utilizar el protocolo inter-ORB para codificar sus mensajes (como hace CMR) pero ello implica una sobrecarga muy importante que resulta prohibitiva para MTU S pequeñas. Por ese motivo se ha definido un formato de cabecera específico (ver listado 7.1). Los mensajes de reenvío (forward) —cuyo equivalente en CMR sería send_- request()— incluyen los siguientes campos: magic sequence – (3 bytes) Caracteres ‘I’,‘D’,‘M’. messageType – (1 byte) Tipo de mensaje. messageSize – (4 bytes) Tamaño total del mensaje incluyendo la carga útil. requestId – (4 bytes) Identificador de la petición para realizar la correspondencia con el mensaje de respuesta si lo hubiere. routerId – (2 bytes) Identidad del encaminador que debe reenviar este mensaje. dst – (16 bytes) La identidad del objeto destino. src – (16 bytes) La identidad del objeto que recibirá la respuesta. hopLimit – (1 byte) Un contador que el encaminador descuenta en cada salto. Evita bucles de encaminamiento de manera similar al campo del mismo nombre en IPv6. tos – (1 byte) Un código que identifica el T O S. El encaminador aplica un conjunto de restricciones de Q O S a cada tipo de servicio. Su función es similar al campo del mismo nombre en IP. flow – (4 bytes) Identifica una secuencia de mensajes que comparten un perfil de Q O S. mode – (1 byte) Características de entrega de la invocación: idempotente, one- way/twoway, respuesta requerida, etc. module IDM { struct HeaderData { byte magic_I , magic_D , magic_M ; byte messageType ; int messageSize ; int requestId ; byte routerId ; IDM :: Identity dst ; IDM :: Identity src ; byte hopLimit ; ToS tos ; int flow ; byte mode ; }; struct ForwardData { string operation ; Encapsulation params ; }; struct Forwa rdUserMs g { i i i i i i i i 184 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS struct HeaderData ; struct ForwardData ; }; struct ForwardRawMsg { struct HeaderData ; Ice :: ByteSeq payload ; }; }; L ISTADO 7.1: Formato de los mensajes IDM (notación pseudo-Slice) Nótese que el campo router no es una identidad IDM completa. Solo se requiere el sufijo —la identidad del objeto dentro del nodo— dado que el adaptador que lo aloja debe ser localizado por otro medio. Por ejemplo, IP no requiere identificar al encargado de procesar los paquetes puesto que únicamente hay un proceso de encaminamiento por host. Sin embargo, hay muchos motivos por los que puede resultar ventajoso que varios encaminadores IDM (objetos) convivan al tiempo en un nodo. A pesar de la mencionada sobrecarga, puede ser interesante definir este mensaje como un método del encaminador, empleando Slice y utilizando I CE P como formato. El caso más claro para decantarse por esta opción lo tenemos a la hora de prototipar algoritmos de encaminamiento dinámico o depurar protocolos de aplicación encapsulados sobre IDM. El motivo es que implementar y probar métodos convencionales del objeto es mucho más sencillo desde el punto de vista del desarrollo ya que los procesos de (de)serialización son realizados automáticamente por el middleware. En cuanto a la carga útil, IDM permite transportar mensajes de dos tipos: Raw – Ofrece al usuario un API similar a los sockets BSD para darle la posibilidad de transportar bloques de datos sin ningún tipo de semántica ni formato. User – Si se dispone de la especificación de la interfaz del objeto remoto, es posible realizar invocaciones a métodos. De ese modo se logra serialización/deserialización de parámetros, verificación de tipos, gestión de excepciones, etc. 7.4. Gestión de calidad de servicio Los requisitos de Q O S necesarios son especificados en el momento en que se solicita el acceso al objeto remoto. Algunos de ellos, como el cifrado o la autenticación pueden establecerse extremo a extremo, pero otros como el ancho de banda requerido deben satisfacerse a lo largo de toda la ruta. A continuación se listan algunos de los parámetros que hemos considerado, aunque varios no están disponibles en los prototipos actuales. Invocación oneway/twoway. Confirmación/Garantía de entrega. Ordenamiento de mensajes. Autenticación. i i i i i i i i 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS 185 Autorización. Latencia máxima. Ancho de banda mínimo. Encaminamiento fuente. El cliente también debe especificar qué ocurre cuando no es posible satisfacer alguno de los requisitos. Solicitar una política estricta puede implicar la imposibilidad de llevar a cabo el transporte. Se considera que los encaminadores pueden contar con un conjunto de T O S definidos junto con sus requisitos de Q O S. Adicionalmente, los encaminadores pueden implementar la interfaz IDM::QoS::Admin, que se utiliza para definir nuevos perfiles de Q O S. Esta interfaz (listado 7.2) tiene un método que permite registrar un perfil Q O S en base a un código de T O S o bien a un identificador de flujo. module IDM { module QoS { enum feature { maxLatency , minBandwidth , reliability }; dictionary < feature ,string > profile ; interface Admin { void setQoSbyToS ( profile qos , ToS tos ) ; profile getQoSbyToS ( ToS tos ) ; void setQoSbyFlow ( profile qos , int flow ) ; profile getQoSbyFlow (int flow ) ; }; }; }; L ISTADO 7.2: Interfaz para administración de perfiles de Q O S en encaminadores IDM 7.5. Entrega de mensajes IDM se ha concebido como un protocolo de red, de modo que se plantean los mismos problemas, con la salvedad de que deben resolverse en una capa de abstracción diferente: sobre el middleware en lugar de sobre la capa de enlace. Un problema básico en un protocolo de red es la descripción de los mecanismos de entrega de mensajes, tanto a vecinos de su red como a hosts fuera de ella. 7.5.1. Entrega directa El método más simple de entrega de mensajes involucra únicamente al cliente y al objeto o servidor; a esto se denomina normalmente entrega directa. Para lograrlo es necesario averiguar los endpoints de que dispone el adaptador al que pertenece el objeto destino y después comprobar si el host cliente cuenta con algún endpoint compatible. i i i i i i i i 186 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS F IGURA 7.4: Una inter-red IDM formada por 4 redes IDM Una red IDM es un conjunto de objetos directamente alcanzables por medio de un tipo de endpoint. No tiene porqué existir ninguna relación entre una red IDM y las redes físicas a las que está conectado el host. Puede ocurrir incluso que un adaptador de objetos cuente con varios tipos de endpoints a pesar de estar conectado a una sola red física. En el escenario más simple los encaminadores IDM se encuentran sólo en los nodos frontera entre redes con distintas tecnologías o protocolos de red incompatibles (ver figura 7.4). Eso proporciona conectividad entre todos los objetos y clientes IDM, pero hay otros usos posibles en los que pueden existir muchos más encaminadores, por ejemplo, en una MANET todos los nodos son encaminadores IDM. Para conocer los endpoints del adaptador al que pertenece un objeto se ha diseñado el protocolo Adapter Location Protocol (ALP). Es un protocolo general de descubrimiento de vecinos, pero asume que los actores son objetos accesibles mediante IDM. El listado 7.3 muestra la especificación de la interfaz que deben implementar los objetos que soportar este protocolo. module IDM { module ALP { exception O b j e c t N o t F o u n d E x c e p t i o n {}; interface Locator { void add (Object∗ prx ) ; void remove ( IDM :: Identity oid ) ; Object∗ resolve ( IDM :: Identity oid ) throws O b j e c t N o t F o u n d E x c e p t i o n ; }; interface Lookup { idempotent void request ( IDM :: Identity oid , Lookup ∗ callback ) ; idempotent void reply (Object∗ prx ) ; }; }; }; L ISTADO 7.3: Interfaz ALP para registro de objetos y localización de adaptadores (especificación Slice) i i i i i i i i 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS 187 Cada nodo de la red IDM debe disponer de un demonio local, llamado Servicio ALP, que implementa la interfaz ALP::Locator. Mediante la invocación del método lookup y conocida la identidad destino, el nodo cliente obtiene un proxy, que permite realizar invocaciones directamente sobre el objeto remoto. Nótese que sólo es posible localizar endpoints de adaptadores vecinos, es decir, que se correspondan a nodos de la misma red IDM. Existen diversas formas de implementar el servicio ALP. Para nuestros prototipos iniciales hemos considerado dos. La elección se hace por configuración y es transparente tanto para los clientes como para los objetos. Un servicio distribuido que permite a cualquier host interrogar a su segmento de red sobre la existencia de un objeto concreto. Este servicio utiliza los mecanismos multicast o broadcast específicos de los endpoints disponibles. El servicio en cada nodo debe atender los mensajes request() y los debe contestar mediante mensajes reply(). Estos mensajes pertenecen a la interfaz IDM::ALP::Lookup y en la práctica dicha interfaz se implementa como una faceta del Servicio ALP (ver figura 7.5). Utilizar las características de indirección que incorpore el middleware. En I CE la indirección de objetos se consigue por medio de un servicio llamado Ice Locator, que aunque centralizado puede estar replicado. IDM dispone de un adaptador para utilizar IceGrid::Locator con una sobrecarga mínima. Eso resulta muy útil en segmentos grandes de la red virtual y cuando los hosts dispongan de suficientes recursos de cómputo como para ejecutar un nodo IceGrid (véase § 2.3.4). Obviamente ofrece alguna desventaja respecto al anterior: todos los hosts deben conocer desde su arranque la referencia remota de al menos una de las réplicas del Locator y contar con un endpoint compatible con ella. En ambos casos, los hosts que deseen exportar objetos deben registrarlos en el servicio ALP para que puedan ser encontrados por otros nodos, independientemente si están implementados mediante IceGrid Locator o por el propio host. Ambos mecanismos pueden coexistir en la misma red. El servicio ALP cuenta con una caché que almacena temporalmente los endpoints resueltos, sin importar el modo en que se resolvieron. El propósito de la caché es reducir el impacto en el desempeño que implican los mecanismos de resolución. Cuando se utiliza un servicio ALP centralizado, el runtime IDM incorpora una caché local para evitar tener que repetir consultas al servicio remoto. 7.5.2. Entrega indirecta Se utiliza entrega indirecta para aquellos objetos que no son alcanzables a través de ninguno de los endpoints del cliente. En esos casos es necesaria la mediación de al menos un encaminador. Nótese que puede ocurrir un caso especial. Aún existiendo accesibilidad directa por medio de un endpoint, es posible que las restricciones de Q O S impidan su uso y obliguen a utilizar uno o varios encaminadores para llegar al destino. i i i i i i i i 188 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS F IGURA 7.5: Diagrama de bloques de IDM 7.6. Encaminamiento Todos los nodos que forman parte de una inter-red IDM requieren de una tabla de rutas que determina si la entrega de mensajes puede realizarse de forma directa o se necesita un encaminador. Éste también es un objeto distribuido convencional, similar a los nodos servidores; la principal diferencia es que puede aceptar y redirigir mensajes que no van dirigidos explícitamente a él. El listado 7.4 muestra la tabla de rutas de un encaminador. Se han utilizado identificadores textuales simplificados para mejorar la legibilidad. Esta tabla de rutas muestra lo siguiente: Los objetos con prefijo NetA.Subnet1 o NetA.Subnet2 son alcanzables directamente (entrega directa). Los objetos con prefijo NetB son alcanzables a través del encaminador NetA.Subnet1.R2. Para el resto de objetos se debe utilizar el encaminador NetA.Subnet2.R3 (ruta por defecto). Router . Row . NetA . Subnet1 .∗ Router . Row . NetA . Subnet2 .∗ Router . Row . NetB . ∗ Router . Row .∗ = = = = tcp , ∗ tcp , ∗ udp tcp , NetA . Subnet1 . R2 tcp , NetA . Subnet2 . R1 L ISTADO 7.4: Tabla de rutas IDM simplificada i i i i i i i i 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS 189 Cada fila de la tabla de rutas incluye una lista de tipos de endpoints que se pueden utilizar para contactar con objetos de esa red. Eso se debe a que cada red IDM está constituida por una o más redes físicas compatibles que utilizan un mismo protocolo (o conjunto de ellos). Para utilizar los mecanismos ALP de una red IDM es necesario conocer al menos un tipo de endpoint compatible con esa red. La figura 7.6 muestra las similitudes funcionales (salvando las distancias) entre los procesos de encapsulación en un encaminador IP y uno IDM. F IGURA 7.6: Comparación entre un encaminador IP y uno IDM 7.6.1. Encaminamiento dinámico Como los encaminadores son objetos distribuidos, resulta relativamente sencillo implementar algoritmos de encaminamiento dinámico de cualquier tipo. Cada mensaje del protocolo de encaminamiento elegido se define como un método del objeto en la interfaz específica. Para soportar un nuevo protocolo de encaminamiento es suficiente que implemente la interfaz correspondiente como una nueva faceta. Como ejemplo, el listado 7.5 muestra la interfaz para el protocolo RIP2 [Mal98]. En ambos métodos, el parámetro oids es una lista de identificadores de objetos, que puede estar vacía en el mensaje request(). El parámetro src es la identidad del encaminador que realiza la invocación. Este planteamiento permite implementar varios protocolos de encaminamiento dinámico en el mismo nodo, aunque de operar a la vez, debe definirse un criterio de prioridad para evitar conflictos en la actualización de la tabla de rutas. 7.6.2. Gestión de la red Dado que los encaminadores y los servidores son objetos distribuidos convencionales, es posible utilizar los servicios estándar para despliegue que proporciona el middleware (IceGrid en I CE). Con ello se consiguen muchas funcionalidades, algunas típicas de una i i i i i i i i 190 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS module Routing { sequence < Ice :: Identity > IdentitySeq ; interface RIP { void request ( IdentitySeq oids , Ice :: Identity src ) ; void response ( IdentitySeq oids , Ice :: Identity src ) ; }; }; L ISTADO 7.5: Interfaz Slice para el protocolo de encaminamiento RIP plataforma de gestión de red, pero con sobrecarga mínima y totalmente integradas en el funcionamiento de la propia red: Planificación Es posible diseñar la topología, analizar las necesidades y requerimientos de red y los usuarios, cuantificar los costes de mantenimiento y operación incluso antes de disponer físicamente de los hosts y el equipamiento de comunicaciones. Despliegue Permite realizar distribución de ficheros de configuración, bibliotecas y binarios a cada encaminador y, todo ello, a la medida de las prestaciones y tipo de arquitectura de cada nodo. Monitorización/contabilidad Se puede evaluar el rendimiento del sistema, consecución de las prestaciones, ancho de banda disponible/consumido, latencia y muchas otras variables de un modo sencillo en cada encaminador y servidor de la red. Gestión de la configuración Cuando se disponga de nuevas versiones del software, éste puede ser desplegado a los encaminadores, incluyendo implementación o mejoras de los protocolos de encaminamiento. También es sencillo añadir interfaces para administración de los equipos, definición de prioridades, políticas de seguridad, etc. 7.7. Integración con el middleware Una de nuestras prioridades es la integración del mecanismo de encaminamiento con el middleware. Para el programador, las diferencias entre usar un objeto IDM y un objeto distribuido convencional deberían ser mínimas. Por ese motivo, el reenvío de mensajes se utiliza únicamente entre encaminadores y no afecta a la interacción de estos con los clientes y los objetos. Cuando un cliente desea hacer un invocación a un objeto IDM remoto utiliza una clase especial para conseguir un proxy a su encaminador local (situado en el mismo nodo que el cliente). El cliente realiza la invocación utilizando este proxy como si se tratase realmente del objeto remoto. A continuación se explica en detalle el proceso completo para realizar una invocación a un objeto IDM remoto afectando al menos a un encaminador intermedio, es decir, i i i i i i i i 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS 191 potencialmente cliente y objeto destino podrían encontrarse en redes tecnológicamente distintas. La figura 7.7 ilustra todo ese proceso. F IGURA 7.7: IDM: Invocación de un objeto IDM remoto El encaminador local puede recibir invocaciones destinadas a cualquier objeto. Si la identidad destino es la suya propia, él procesa el mensaje; en caso contrario, encamina el mensaje hacia su destino. Cuando un encaminador recibe una invocación de un cliente local realiza los siguientes pasos: 1. Si el mensaje requiere respuesta, crea un objeto callback alojado en su espacio de memoria para poder recibir la respuesta. La referencia a este objeto es la que aparecerá como campo src de la estructura HeaderData. 2. Construye un mensaje según el formato de la estructura ForwardRawMsg o ForwardUserMsg (en adelante forward, por simplicidad) según el tipo de invocación elegida por el cliente. 3. Comprueba su tabla de encaminamiento y determina la identidad del siguiente encaminador y los endpoints de que dispone. 4. Filtra dichos endpoints según la información de Q O S de cada uno de ellos en relación al T O S al que corresponde la invocación procedente del cliente. Si no encuentra ninguno compatible retorna una excepción al cliente y aborta. 5. Utiliza el servicio ALP para determinar la información de direccionamiento del protocolo inferior que corresponda. 6. Utiliza dicho endpoint para enviar el mensaje forward al siguiente encaminador. Encaminador intermedio es aquel que recibe mensajes forward procedentes de cualquier otro encaminador. En este caso el procedimiento de trabajo incluye únicamente los puntos 3 a 6 de la lista anterior. El encaminador final debe encargarse de entregar invocaciones directamente a los objetos destino. Procede del siguiente modo: 1. Recibe un mensaje forward y comprueba su tabla de rutas para determinar si el destino es un objeto de la forma habitual. i i i i i i i i 192 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS 2. Mediante ALP obtiene los endpoints del objeto destino. Si ninguno de ellos fuera compatible con los requisitos de Q O S, en este momento generaría una excepción dirigida al objeto src. 3. A partir del contenido del mensaje forward crea un mensaje de invocación convencional (en el caso de I CE será un HeaderData y un RequestData del protocolo I CE P). 4. Ejecuta dicha invocación directamente sobre el cliente. Puede ser síncrono o no dependiendo del tipo de mensaje y el endpoint utilizado. 5. Si la invocación es síncrona y hay respuesta, el encaminador procede con los mismos pasos que se han descrito para el encaminador local, pero utilizando la referencia src contenida en el mensaje forward. Cuando la respuesta llega al objeto temporal que creó el encaminador local, éste crea una respuesta según el formato del protocolo inter-ORB y lo entrega al cliente por la misma conexión que se estableció para realizar la invocación. El cliente ha estado bloqueado durante todo el proceso a menos que utilice los mecanismos AMI proporcionados por el middleware. Los calificativos local, final e intermedio no determinan tipos de encaminadores sino roles. Todos los encaminadores pueden funcionar con cualquiera de esos roles. La distinción presentada aquí se debe a motivos de legibilidad y simplificación de las fases del procedimiento. Nótese que a diferencia de CMR, se asume que todo nodo que aloja clientes tiene un encaminador local, que es el único que recibe invocaciones directamente de los clientes. Es decir, un cliente no puede efectuar invocaciones convencionales (no-IDM) a encaminadores fuera de su nodo. Aunque esto implica un salto más, mejora la escalabilidad del sistema dado que los encaminadores tienen que almacenar objetos callback para sus clientes. De ese modo, es mucho más sencillo dimensionar las necesidades de memoria y procesamiento del nodo, y los encaminadores sin clientes ni objetos pueden ser mucho más sencillos pues están por diseño exentos de esa tarea. 7.7.1. API La intención es que IDM esté disponible como una biblioteca para servicios avanzados de comunicaciones extremo a extremo de forma transparente. Por ese motivo, se ha diseñado e implementado como un conjunto de clases que permite desarrollar objetos y clientes de una manera muy sencilla. Desde el punto de vista del programador de aplicaciones, para la implementación de servidores sólo es necesario tener en cuenta una pequeña diferencia respecto a la implementación de un servidor I CE convencional. Se debe utilizar un Adapter especial, llamado IDM::Adapter. Es un decorador1 que extiende la funcionalidad del Adapter I CE. Al crearse este adaptador, se registra automáticamente en el Servicio ALP disponible (tal como se haya especificado por configuración). El listado 7.6 muestra la implementación en lenguaje C++ de un objeto mínimo accesible mediante IDM. 1 en referencia al patrón de diseño decorator [GHJV96] i i i i i i i i 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS 193 class HelloI : virtual public Demo :: Hello { public: void sayHello (const string & name , const Ice :: Current & current ) { cout << " Hello from ’" << name << " ’" << endl ; } }; class SimpleServer : public Ice :: Application { public: int run (int argc , char∗ argv []) { Ice :: ObjectPtr serv = new HelloI ; IDM :: AdapterPtr adapter = new IDM :: Adapter ( communicator () , " testAdapter " ) ; adapter −>add ( serv , communicator ()−>s t r i n g T o I d e n t i t y ( argv [1]) ) ; adapter −>activate () ; communicator ()−>w ai tF or S hu td ow n () ; return EXIT_SUCCESS ; } }; int main (int argc , char∗ argv []) { SimpleServer app ; return app . main ( argc , argv ) ; } L ISTADO 7.6: Implementación de un servidor IDM mínimo El cliente IDM también requiere algunas modificaciones respecto a la implementación de un cliente I CE convencional. Es necesario crear una instancia de la clase IDM::Socket. Éste dispone de un método plug() que acepta un identificador de objeto y devuelve un proxy que permite enviar mensajes a ese objeto. Internamente, esa clase consulta la tabla de encaminamiento del nodo y utiliza el servicio ALP para conseguir la referencia ya sea para entrega directa o indirecta (primer salto). El listado 7.7 muestra la implementación de un cliente para acceder al servidor del listado 7.6. 7.8. Conclusiones Aunque a primera vista, el diseño e implementación de un protocolo de red por encima incluso de la capa de transporte pueda parecer un concepto contradictorio y un esfuerzo baldío, queda demostrado que las prestaciones que ofrece IDM pueden resultar muy valiosas en muchos escenarios diferentes. Algunas de las más importantes son: Direccionamiento lógico universal independiente de la tecnología. Transporte transparente extremo a extremo. Mejoras en la eficiencia al poder seleccionar transportes específicos con menor granularidad, que decide el diseñador de la aplicación. i i i i i i i i 194 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS class SimpleClient : public Ice :: Application { public: int run (int argc , char∗ argv []) { IDM :: SocketPtr sock = new IDM :: Socket ( communicator () ) ; Ice :: ObjectPrx obj = sock −>plug ( argv [1] , IDM :: QoS () ) ; Demo :: HelloPrx prx = Demo :: HelloPrx :: uncheckedCast ( obj ) ; prx −>sayHello ( " John " ) ; return EXIT_SUCCESS ; } }; int main (int argc , char∗ argv []) { SimpleClient app ; return app . main ( argc , argv ) ; } L ISTADO 7.7: Implementación de un cliente IDM mínimo Prestaciones adicionales transparentes y desacopladas del transporte como cifrado, contabilidad, autenticación, autorización, etc. Encaminamiento funcional. Migración de nodos y encaminadores. Aprovechando las posibilidades que ofrece IDM, estamos evaluando su aplicación a diversos campos: Redes MANET (Mobile Ad-hoc Network). Cada nodo de la red ad hoc puede incluir un encaminador IDM, homogeneizando el acceso desde la red troncal. Este enfoque permite incluso plantear redes ad hoc híbridas como, por ejemplo, una red IP y una red de sensores. Implementación del encaminador IDM en sistemas empotrados basados en microcontrolador y/o en FPGA para el desarrollo de encaminadores eficientes para redes SAN y grids heterogéneos [RDB+ 09]. Métricas del desempeño de la red y del servicio prestado. Red virtual para provisión de Q O S [UVV+ 09]. En lo referente al desarrollo de nuevos endpoints, cabe destacar que se encuentran en fase de desarrollo los que corresponden a protocolos tan variados como Zigbee, BlueTooth y Ethernet. Un concepto que creemos merece la pena abordar es lo que llamamos decoradores 2 de endpoints. Pueden añadir características opcionales a cualquier endpoint, como cifrado, garantía de entrega, contabilidad, etc. Estos decoradores facilitan la composición funcional de endpoints dando lugar a combinaciones muy interesantes. Por ejemplo, si se requiere transmitir audio en una red LAN Ethernet salvaguardando la privacidad, pero sin necesidad de garantizar la entrega, se podría utilizar un endpoint que realiza transporte directamente 2 También en referencia al patrón de diseño. i i i i i i i i 7. I NTEGRACIÓN DE REDES HETEROGÉNEAS 195 sobre tramas Ethernet y que está decorado con un endpoint que cifra los mensajes. De ese modo, se puede conseguir el transporte deseado sin la sobrecarga que implicarían las cabeceras IP y UDP. i i i i i i i i i i i i i i i i 88 Prototipos 8.1. 8.2. 8.3. 8.4. 8.5. 8.6. 8.7. 8.8. Dispositivos Máquina virtual TwinPanel Servicios Activos experimentales Análisis de protocolos Prototipos IDM Conclusiones A lo largo de este capítulo se describen algunos prototipos que sirven para validar las propuestas realizadas en torno al modelo de información DUO, el protocolo ASDF y su uso en picoObjetos. Se presentan varios escenarios concretos y algunos servicios de uso general que utilizan y se integran en la infraestructura. Se evalúan también prototipos preliminares de IDM. 8.1. Dispositivos En esta sección se describen brevemente algunos de los dispositivos utilizados para la implementación de los prototipos. Se han incluido fotografías y esquemas para dar una idea más exacta de su tamaño físico y complejidad. 8.1.1. Motas Crossbow Las motas de la empresa Crossbow son con toda seguridad los dispositivos más usados en la investigación, prototipado y desarrollo de aplicaciones con WSN. Ésta es razón suficiente para considerar la implementación de nuestros prototipos sobre dicha plataforma, a pesar de que sus capacidades y recursos de cómputo superan con creces las necesidades para la implementación de nuestra máquina virtual. Hemos realizado prototipos con los siguientes dispositivos concretos: Mota Crossbow IRIS (XM2210CA) Integra un microcontrolador Atmel ATmega1280 con 8 KiB de SRAM, 4 KiB de EEPROM y 128 KiB de Flash. Dispone de una interfaz de comunicaciones Zigbee 2.4GHz IEEE 802.15.4. La figura 8.1a muestra una fotografía de esta mota, indicando la situación los sensores que integra. Se alimenta con dos pilas AA convencionales. 197 i i i i i i i i 198 8. P ROTOTIPOS Mota Crossbow MICA2 (MPR400CB) Emplea un microcontrolador Atmel ATmega128 con 4 KiB de SRAM, 4 KiB de EEPROM y 128 KiB de Flash. Como interfaz de red utiliza un transductor de radio multicanal en la banda de 868/916 MHz. Se alimenta con dos pilas AA convencionales. Mota MICA2DOT (MPR500) Tiene prácticamente las mismas características que el modelo anterior pero con un formato más reducido. Integra un microcontrolador Atmel ATmega128L y se alimenta con una pila botón de 3V (ver figura 8.1b). Tarjeta de sensores Crossbow MTS310 Tiene un LDR, micrófono, magnetómetro, acelerómetro y zumbador. Tarjeta de sensores Crossbow MTS420 Dispone de barómetro, sensor de temperatura, LDR, acelerómetro y receptor GPS. Tarjeta de sensores Crossbow MDA300CA Dispone de 6 canales digitales, 6 canales analógicos, 2 entradas optoacopladas, sensor de humedad y sensor de temperatura. Otros sensores Utilizando tarjetas de expansión hemos integrado otros sensores como PIR (Passive Infra Red), sensores de inclinación, relé reed y pulsadores convencionales. (a) (b) F IGURA 8.1: Motas Crossbow IRIS (a) y MICA2DOT (b) 8.1.2. TINI El TINI (Tiny InterNet Interface) [TIN] es un dispositivo fabricado por Dallas Semiconductor. Está diseñado para aplicaciones empotradas orientadas a usos relacionados con Internet. Incorpora una implementación completa de la pila TCP/IP, ejecución nativa de bytecode Java y varias interfaces para control de dispositivos: 1-wire, RS232 y Ethernet 10 Base-T. i i i i i i i i 8. P ROTOTIPOS 199 El modelo concreto que utilizamos es el DSTINI1-512; está basado en el procesador DS80C390 que tiene 64 KiB de ROM, 512KB de SRAM y 1MB de Flash. Está montado en un módulo SIMM de 72 contactos que se conecta en una placa de expansión (el E10) que incluye las interfaces indicadas. La figura 8.2 muestra el módulo DSTINI1 montado en el socket E10. F IGURA 8.2: Módulo DSTINI1 en el socket E10 8.1.3. NXT El NXT [NXT] es parte de Lego Mindstorm, un kit de robótica con fines docentes y lúdicos. El brick es un dispositivo que incluye todo el hardware de control, el resto son periféricos y accesorios mecánicos. El microprocesador principal es un ARM7DMI de 32 bits a 48 MHz. Dispone de 64 KiB de RAM y 256 KiB de Flash. Además dispone de un microcontrolador ATmega48 de 8 bits a 4 KHz, 512 B de RAM y 4 KiB de Flash. Cuenta también con un controlador Bluetooth, LCD de 100x64 píxels, USB 2.0, 4 puertos de entrada y 3 de salida. Aunque existen varios sistemas para su programación, nuestros prototipos utilizan leJOS NXJ, un lenguaje basado en Java. La figura 8.3 muestra el aspecto del NXT y los sensores y actuadores con los que se distribuye. 8.1.4. XPort El XPort [XPo] (modelo XP1001001-03R) ofrece una interfaz RS232 con posibilidad de utilizar instrucciones Hayes. Dispone de una implementación completa de la pila TCP/IP pudiendo usar tanto UDP como TCP ya sea para conexiones pasivas o activas. Tiene un cliente DHCP integrado y posibilidad de configurar el tipo de control de flujo, paridad y otras opciones típicas de un puerto serie. También admite opciones básicas sobre la conectividad TCP/IP. La figura 8.4a muestra un ejemplar de XPort. i i i i i i i i 200 8. P ROTOTIPOS (a) (b) F IGURA 8.3: Brick NXT (a) y sus periféricos (b) 8.1.5. WIZnet WIZnet [WIZ] (modelo NM7010B) es una interfaz de red Ethernet similar a XPort aunque ofrece algunas ventajas sobre éste. Incorpora una implementación completa de la pila TCP/IP incluyendo IP multicast y medios 10/100 Base-T con auto-detección. Se muestra en la figura 8.4b. (a) (b) F IGURA 8.4: Interfaces Ethernet XPort(a) y WIZnet (b) 8.1.6. Cámaras En nuestros prototipos utilizamos cámaras de vídeo con distintas capacidades: AXIS 214 [AXIb] – Es una cámara Pan-Tilt-Zoom (PTZ) de gama media con servidor web incorporado y múltiples posibilidades de transporte, codecs de vídeo y otras posibilidades avanzadas, como detección de movimiento. AXIS 212 [AXIa] – Es un modelo algo más modesto que el anterior. Tiene la peculiaridad de ofrecer PTZ instantáneo ya que no tiene partes móviles, utiliza parte del CCD como si fuera la imagen completa. i i i i i i i i 8. P ROTOTIPOS 201 Canon VCC4 [VCC] – Es una cámara PTZ con gran calidad óptica. El control del pedestal se efectúa con un protocolo específico mediante una interfaz RS232. La imagen se obtiene de forma analógica por medio de una salida PAL convencional, de modo que es necesario una tarjeta de captura de vídeo. Logitech Sphere [Sph] – Es una webcam para uso doméstico, pero que permite giro e inclinación. Utiliza una interfaz USB tanto para acceder al framegrabber como para las instrucciones de control del pedestal. (a) (c) (b) (d) F IGURA 8.5: Algunas cámaras de vídeo utilizadas en los prototipos. AXIS 214 (a), AXIS 212 (b), Canon VCC4 (c) y Logitech Sphere (d) 8.2. Máquina virtual Se han realizado implementaciones de la máquina virtual FSM para distintas plataformas y lenguajes de programación, pero siguiendo la misma especificación funcional. A continuación se describen sus características concretas y su propósito: i i i i i i i i 202 8. P ROTOTIPOS Máquina Python La VM Python se ejecuta sobre un PC convencional. Se utiliza principalmente para la ejecución de baterías de pruebas para los compiladores ipkc y fsm2data; también para propósitos de depuración de las otras implementaciones de la máquina. Emplea un diseño orientado a objetos en el que el propio intérprete es una clase. Permite utilizar varios dispositivos como interfaz de red por medio de subclases: Socket TCP. Socket UDP. Interfaz serie RS-232 para conexión a través de XPort. Entrada/salida estándar para conectar a través de un programa externo como netcat. Utiliza el bucle de eventos de GNU Glib que permite registrar manejadores para las entradas y eventos de manera sencilla. La implementación completa supone 831 SLOC de las cuales 265 corresponden a la implementación de la ISA. El programa genera un registro detallado del funcionamiento incluyendo el contenido de los mensajes recibidos y transmitidos, contenido de los registros, activación de timers, etc. Máquina Java En este caso se ha realizado una única implementación del intérprete que no requiere ninguna biblioteca externa. El intérprete lo constituyen 514 SLOC. PC – Es una versión para ejecución de pruebas y ayuda para la depuración de las otras implementaciones Java. El módulo específico para PC tiene 259 SLOC. TINI – Aunque el TINI es un dispositivo potente que ejecuta nativamente bytecode Java, no soporta un ORB CORBA completo. Sin embargo, es posible ejecutar la VM de FSM sin ningún problema. TINI permite acceder a una red CAN y tiene puertos USB y RS-232. Puede utilizarse como bridge para acceder a transductores que utilicen estas interfaces. NXT – La versión para el NXT es muy similar a la anterior salvo porque utiliza leJOS FW v0.7 y comunicaciones Bluetooth. Requiere 270 SLOC adicionales. Su finalidad, a pesar de ser completamente funcional, está más orientada a ilustrar la versatilidad de la propuesta que a conseguir una plataforma de sensorización realmente útil, al menos con objetivos industriales. Máquina C Esta versión es la más versátil. El módulo que implementa la ISA está escrito en ANSI C, sin ninguna biblioteca o dependencia; ocupa unas 683 SLOC incluyendo abundante código de preprocesador que permite incluir sólo las instrucciones que se utilizan si así se desea. Existe una única implementación del intérprete que se compila junto a otros módulos para tareas dependientes de la plataforma (interfaz de red, timers, bucle de eventos, etc.) para así obtener una VM completa en cada una de las plataformas soportadas. i i i i i i i i 8. P ROTOTIPOS 203 PC – Emplea IO Channels de GNU Glib para la implementación del bucle de eventos y timers. Utiliza la E/S estándar como dispositivo de red. El fichero ejecutable resultante se utiliza conjuntamente con la utilidad netcat, socat o socket, disponibles en la mayoría de sistemas GNU. TinyOS – Esta versión está escrita en nesC [Nesa], el lenguaje típicamente usado en la plataforma TinyOS. El bucle de eventos y gestión de timers está construido sobre el sistema de tareas de este SO, así como el acceso a la interfaz de red. Se utiliza en varios tipos de mota (véase § 8.1.1). Atmel – En este caso se utiliza un sencillo ejecutivo cíclico como implementación del bucle de eventos. Para las comunicaciones se utiliza una biblioteca Zigbee que acompaña al kit de desarrollo que se ha utilizado para la implementación. Máquina en Ensamblador Esta es la implementación más simple que hemos realizado. Está destinada a microcontroladores Microchip de 8 bits. Tenemos prototipos para dos modelos: P16F876A – Reloj de 10/20 KHz, 368 B de RAM, 8 Kpalabras de memoria de programa, 256 B de EEPROM y 32 pines GPIO. Dispone de 2 timers de 8 bits y uno de 16 bits. P16F690 – Reloj de 20 KHz, 256 B de RAM, 256 B de EEPROM y 18 pines de GPIO. Tiene los mismos timers que el modelo anterior. No supondría un problema portarlo a otros modelos. Las únicas dependencias están en la comunicación con la UART/USART, la programación de timers y la gestión de la GPIO. De modo que el planteamiento en ese aspecto resulta muy similar a la versión C. La diferencia más importante en los prototipos realizados es el dispositivo utilizado como interfaz de red: Ethernet – Se han implementado versiones para dos dispositivos: el XPort y el WIZnet. WiFi – En este caso la única diferencia consiste en utilizar el dispositivo WiPort en lugar de XPort. RS-485 – El objetivo aquí es utilizar una red de datos de muy bajo coste para sistemas estáticos en los que sea factible realizar cableado físico. Se utiliza un transductor RS232 a RS485 (modelo SN75HVD08DR). Se pueden conectar hasta 256 nodos a un único bus. Requiere un árbitro implementado con un ATmega128. La tabla 8.1 muestra los requisitos mínimos necesarios para cada una de las implementaciones de la VM. Nótese que las versiones C y ensamblador pueden optimizarse para incorporar únicamente las instrucciones que realmente se usan en el FSM específico. En el caso de la mencionada tabla, se trata de una implementación completa sin este tipo de optimización, ya que se considera que de ese modo es más sencillo comparar en términos absolutos. En la versión ensamblador, el tamaño de programa está indicado en palabras (no bytes); en la versión C se indica el tamaño de los ficheros objeto y en la versión Java el de los .class. i i i i i i i i 204 8. P ROTOTIPOS La cantidad total de recursos necesarios para un nodo concreto se puede obtener sumando a los datos de esta tabla los requisitos concretos del bytecode y sirviente concretos. Las diferencias por sobrecarga u optimizaciones particulares deberían ser mínimas. Por este motivo, consideramos que el tamaño de la VM es en sí mismo un dato representativo. plataforma PIC + XPort (asm) PIC + RS485 (asm) Atmel + Zigbee (C) MICA (TinyOS, NesC) TINI (Java) NXT (leJOS) PC (C) PC (Python) PC (Java) VM bibliotecas SO RAM 1 824 1 824 4 667 5 199 30 230 23 000 9 360 35 699 32 074 819 360 4 261 687 lejOS GNU glib std lib JVM N/A N/A N/A 14 873 - 65 55 85 3 176 645 - C UADRO 8.1: Memoria requerida por la máquina virtual en cada plataforma (en bytes) 8.3. TwinPanel TwinPanel es una completa aplicación gráfica para inspección, depuración y diagnóstico del entorno inteligente con soporte específico para los protocolos e interfaces definidos en los capítulos anteriores. Utiliza un diseño extremadamente modular —basado en el patrón Model-ViewController (MVC)— que permite decidir automáticamente cuales son las posibilidades de visualización y actuación para un actor concreto. El usuario puede decidir cuál de las vistas posibles desea utilizar para interactuar con un actor o servicio. El soporte para cada interfaz o protocolo (los modelos) está encapsulado en un inspector y las alternativas de visualización (las vistas) en lo que llamamos skins. Todos ellos están disponibles como plugins que se cargan dinámicamente cuando se requieren. Toda la aplicación está escrita en lenguaje Python y hace uso extensivo de la biblioteca GTK, algo más de 10 600 SLOC incluyendo todos los plugins. Los inspectores específicos que cubren las funcionalidades relacionadas con las aportaciones de este trabajo son: I CE • Objetos genéricos • Canales de eventos • IceGrid DUO • • • • Interfaces escalares Objetos activos Contenedores Componentes i i i i i i i i 8. P ROTOTIPOS 205 • Objetos compuestos ASDF • Anunciamientos • Propiedades de un objeto • Búsqueda de servicios Otros • Cámaras de vídeo Existen además otros inspectores de uso general que pueden ser útiles para el sistema: Bluetooth Zeroconf UP N P La figura 8.6 muestra la apariencia de TwinPanel haciendo uso de ambos paneles. F IGURA 8.6: TwinPanel, aspecto general 8.4. Servicios En esta sección se describen algunos servicios de uso general implementados como servicios IceBox, y que aprovechan muchas de las pautas de diseño de DUO y ASDF. 8.4.1. PropertyServer Este servicio es una implementación directa de la interfaz PropertySetDef. Utiliza una base de datos Freeze accedida automáticamente desde un único sirviente. Para poder servir propiedades de muchos actores, utiliza un ServantLocator especial que emplea la identidad de objeto del proxy para indexar la base de datos. Esto significa que es una solución i i i i i i i i 206 8. P ROTOTIPOS muy escalable. La memoria requerida por el servidor no crece de manera significativa puesto que no es necesario crear nuevos objetos dinámicamente a pesar de que la base de datos incluya información sobre miles o millones de actores. El servicio se anuncia con ASDF aunque también puede estar registrado como un objeto bien conocido. Está escrito íntegramente en C++ y hace uso de las bibliotecas Freeze y IceStorm. Este servidor utiliza una biblioteca llamada libPropertyService. El objetivo de ésta es dotar de propiedades a cualquier actor sin más que enlazar la biblioteca y crear la instancia de la clase que proporciona. 8.4.2. ContextServer Se trata de una generalización del concepto de contenedor (véase § 3.3). Es una implementación directa de la interfaz DUO::Container::RW, pero además permite asignar propiedades a cualquier contenedor de la jerarquía. El método create() crea nuevos objetos iguales al raíz que se alojan en la memoria del propio servidor. También permite enlazar contenedores que residen en otras instancias de forma transparente. Podemos considerar que los contenedores definen contextos que agrupan objetos cualesquiera con la ayuda de propiedades. Por ejemplo, uno de los casos más representativos es la construcción de mapas conceptuales, es decir, representaciones visuales de un grupo de objetos. El contexto tiene una propiedad map que permite acceder a un fichero gráfico (SVG generalmente) y propiedades que indican la posición de cada objeto respecto a ese mapa. Por su parte, cada objeto tiene una propiedad icon para representar visualmente el objeto. Por supuesto, si se trata de dispositivos simples puede ser una cadena de texto que indica un icono de stock, y si son picoObjetos la propiedad estará en un servidor de propiedades y no en el propio objeto. La figura 8.7 muestra uno de estos contextos que incluye representación gráfica. 8.4.3. CacheService Es un servicio de registro automático para anunciamientos. Se puede utilizar como servicio de registro centralizado o híbrido en ASDF, tal como se explica en la sección 5.6.2. El servicio se encarga de clasificar automáticamente cada nuevo actor anunciado y lo elimina al despedirse. Por cada interfaz de servicio que implemente se registra en un contexto, que se crea automáticamente si no existe. Esta información no es persistente dado que puede cambiar con cierta frecuencia. Se anuncia y si encuentra el ContextServer se registra automáticamente. Implementa las interfaces DUO::Container::R y ASD::Listener. La figura 8.8 muestra una captura de TwinPanel inspeccionando el CacheService. El código específico supone alrededor de 200 SLOC de C++. 8.4.4. CameraServer Se trata de un servicio genérico para integrar fuentes multimedia (principalmente cámaras de vídeo) en el entorno inteligente. Una cámara se modela por medio de varias interfaces predefinidas. La declaración de la interfaz se muestra en el listado 8.1. La utilidad de cada una de esas interfaces heredadas se explica a continuación: i i i i i i i i 8. P ROTOTIPOS 207 F IGURA 8.7: TwinPanel inspeccionando un contexto alojado en un ContextServer F IGURA 8.8: TwinPanel inspeccionando el CacheService Service::Camera Es la interfaz que identifica el tipo de servicio proporcionado por el actor según la taxonomía (véase § 5.2.3). i i i i i i i i 208 8. P ROTOTIPOS DUO::Container::R La cámara es un contenedor que almacena referencias a otros actores. En este caso tiene una función muy concreta. Representa una relación de agregación en la que cada uno de los actores contenidos tiene una responsabilidad funcional específica pero opcional. En las cámaras PTZ, cada elemento con el que se puede interactuar se modela como otro objeto DUO que se incluye en el contenedor. Es posible añadir actores para pan, tilt, zoom, focus, preset, iris y muchos otros. AVStreams::MMDevice La transmisión de flujos multimedia está desacoplada del transporte utilizado por el middleware. Para ello se utiliza la especificación A/V Streams [Obj98] de OMG. La cámara se comporta como un Multimedia Device que puede negociar el tipo de transporte a utilizar con el otro extremo. Se han implementado transportes con RTSP y M-JPEG. TwinPanel dispone de un inspector de cámaras capaz de representar el flujo de vídeo utilizando libVLC. PropertyService::PropertySetDef El servicio proporciona almacenamiento y acceso a las propiedades de la cámara por medio de libPropertyService. interface Camera extends Service :: Camera , DUO :: Container :: R , AVStreams :: MMDevice , P ro pe rt y Se rv ic e :: Pro pertySetD ef {}; L ISTADO 8.1: Declaración de un actor que sirve una cámara de vídeo PTZ Tanto para el acceso al flujo multimedia como para el control del movimiento, el programa emplea plugins que se cargan en función de la configuración del servicio, mediante propiedades I CE. Puede gestionar cámaras que tienen su propio transporte de vídeo, como es el caso de las cámaras IP. Si el framebuffer es accesible localmente, utiliza VLC como servidor. Se han creado drivers para las cámaras AXIS 214, AXIS 212, Cannon VCC4 y Logitech Quickcam Orbit. Este servicio también se anuncia a través de ASDF y es un suscriptor del canal ASDS para poder responder a búsquedas. La implementación, incluyendo todos los drivers mencionados supone alrededor de 5 882 SLOC. La figura 8.9 muestra el aspecto de TwinPanel inspeccionando una cámara. En el panel derecho aparece el flujo de vídeo y los controles del pan-tilt y en el izquierdo aparece la misma cámara pero utilizando la vista de contenedor. 8.4.5. ChannelMonitor Es un servicio auxiliar para dotar de canales de eventos a los picoObjetos activos. Un actor convencional es capaz de interactuar con el servicio de eventos para crear su i i i i i i i i 8. P ROTOTIPOS 209 F IGURA 8.9: TwinPanel inspeccionando una cámara servida por CameraServer propio canal al que enviar sus actualizaciones de estado. Sin embargo, los picoObjetos por diseño, no pueden obtener el proxy a su canal aunque pudieran crearlo. Es necesario que un tercero se encargue de crear el canal y asignarlo al actor activo por medio de la interfaz DUO::Active::W. Cuando un picoObjeto activo arranca por primera vez, el proxy de su canal es nulo. CacheMonitor se encarga de la tarea de crear y asignar canales en esta situación. Existen dos posibilidades para su diseño: El servicio puede escuchar los anunciamientos de los actores, comprobar si son activos y tienen su canal asociado. Este mecanismo es transparente pero requiere que el servicio consulte a todos los actores que se anuncian, con el gasto que ello implica. La aplicación cliente que desea suscribirse a un objeto activo, y detecta que no tiene un canal válido, solicita al ChannelMonitor que le asigne uno. Esta opción es menos transparente porque los clientes deben contactar explícitamente con el servicio, pero escala mejor y no genera tráfico innecesario. Como siempre, la elección de uno u otro diseño depende de las necesidades concretas del entorno. En nuestros prototipos utilizamos la primera opción. 8.5. Activos experimentales Esta sección describe escenarios concretos de complejidad creciente. Para cada uno de ellos, se explica su utilidad y se incluye la definición correspondiente usando IcePick. En la sección 8.5.10 se ofrece un resumen de los requerimientos de memoria de los siguientes ejemplos. i i i i i i i i 210 8. P ROTOTIPOS 8.5.1. Actor mínimo El actor más simple que podemos crear es un actuador que implementa la interfaz DUO::Pulse::W y utiliza transporte oneway. Eso implica que no puede responder a ningún método y, por tanto, los mecanismos de introspección (métodos de la interfaz Ice::Object) son inútiles y puede ser excluidos. La definición de un nodo que aloja uno de estos objetos en una red TCP/IP podría ser la que muestra el listado 8.2. uses " DOBS / DUO . ice "; object DUO . Pulse . W minimo { mode = oneway ; }; local adapter node { endpoint = " tcp −p 12345"; objects = {" OBJ01 ": minimo }; }; L ISTADO 8.2: Objeto mínimo: DUO::Pulse::W con transporte oneway 8.5.2. Otros actores sencillos Cuando se cuenta con un transporte que permite responder a los mensajes (twoway) se pueden incorporar los mecanismos de introspección y el soporte básico de excepciones, asumiendo el coste correspondiente. El listado 8.3 muestra la especificación de un nodo con un sensor DUO::IBool::R y un actuador DUO::IBool::RW 1 . uses " DOBS / DUO . ice "; uses " picos . ice "; object DUO . IBool . R sensor ; object DUO . IBool . RW actuador ; local adapter node { endpoint = " tcp −p 12345"; objects = {" OBJ01 ": sensor , " OBJ02 ": actuador }; }; L ISTADO 8.3: Un sensor DUO::IBool::R y un actuador DUO::IBool::RW Para crear un sensor proactivo es necesario escribir una interfaz Slice que herede de alguna interfaz DUO escalar además de DUO::Active::R. El listado 8.4 muestra la declaración Slice de dicha interfaz para un sensor booleano activo (fichero boolactive-sensor.ice) y el listado 8.5 muestra la definición de un sensor proactivo que utiliza esa interfaz y además envía anuncios proactivos usando el método ASD::Listener::adv(). 1 Esta interfaz requiere heredar de DUO::IBool::R y DUO::IBool::W tal como se explicaba en 3.2 i i i i i i i i 8. P ROTOTIPOS 211 #include " DOBS / DUO . ice " module MySystem { interface BoolRactive extends DUO :: IBool :: R , DUO :: Active :: R {}; }; L ISTADO 8.4: Declaración de una interfaz Slice para un sensor activo uses " DOBS / DUO . ice "; uses " bool−active−sensor . ice "; uses " DOBS / ASDF . ice "; object MySystem . BoolRactive sensor ; local adapter node { endpoint = " tcp −p 12345"; objects = {" OBJ01 ": sensor }; }; object DUO . IBool . W sink ; object ASD . Listener ASDA ; remote adapter external { endpoint = " tcp −h 10.0.0.2 −p 9000"; objects = {" SINK04 ": sink , " IceStorm / ASDA . publish ": ASDA }; }; timer (30) { ASDA . adv ( sensor ) ; } event PRESE NCE_EVEN T do { sink . set ( sensor . get () , sensor . oid ) ; } L ISTADO 8.5: Definición de un sensor booleano proactivo Existen cientos de combinaciones útiles de las interfaces de DUO y ASDF. La tabla 8.2 recoge el tamaño de éstos y otros prototipos con el fin de ilustrar las necesidades en memoria que implica utilizar distintas características. 8.5.3. Cerradura inteligente Se trata de un prototipo muy sencillo, pero que se ha construido físicamente para su uso real. Implementa un actuador DUO::IBool::RW twoway con anunciamientos, que utiliza un PIC 16F690 y un módulo XPort. Permite accionar remotamente la cerradura y conocer su estado. Se puede integrar de forma muy sencilla con un servicio de seguridad y de autenticación de personas para acceso a una habitación. En la figura 8.10 se puede observar un montaje preliminar del prototipo. i i i i i i i i 212 8. P ROTOTIPOS F IGURA 8.10: Cerradura electrónica controlada por un picoObjeto 8.5.4. Control de consumo En este caso se exporta la funcionalidad de un interruptor electrónico de media potencia como un actuador. El objetivo es cortar la corriente de un aula de computadores durante los periodos de inactividad. Un PC convencional puede tener un consumo de hasta 40 W cuando está apagado porque realmente se mantiene en un estado de stand-by. Este prototipo se puede integrar en el cuadro eléctrico del aula y permite establecer un servicio que conoce los horarios de uso y puede apagar completamente todos los equipos del aula. (a) (b) F IGURA 8.11: Prototipo para control de consumo eléctrico Sería muy conveniente un servicio de este tipo para una escuela o todo un campus, puesto que algunas de las aulas se utilizan en periodos no lectivos para realizar rendering y otras actividades de cómputo intensivo. Realizar una conexión/desconexión manual sería administrativamente complejo, ineficaz y propenso a errores. Funcionalmente el nodo es un actuador booleano, pero estamos trabajando en un modelo que permite conocer además el consumo realizado por cada aula y así medir con precisión i i i i i i i i 8. P ROTOTIPOS 213 cuál es la previsión y el ahorro que realmente se consigue. Utiliza un PIC 16LF876A y un módulo XPort como interfaz de red. La figura 8.11 muestra una fotografía del prototipo. 8.5.5. Placas de prototipado Para la realización de prototipos sencillos basados en PIC utilizamos principalmente dos montajes: El primero está basado en el PICkit2, un kit extremadamente simple fabricado por Microchip, pero que con pequeñas modificaciones sirve perfectamente a nuestros propósitos. Esta es la placa que se muestra en la imagen de la figura 8.10. El segundo es un diseño propio, también muy sencillo, que integra dos displays de 7 segmentos y dos pulsadores. Puede verse en la figura 8.12. Utiliza un PIC 16LF876 y puede conectarse con XPort, WIZnet o línea serie. F IGURA 8.12: Placa de prototipado para picoObjetos (ALSO1) 8.5.6. Cableado virtual El escenario puede ser un salón de ferias y muestras en el que la colocación y tamaño de los stands de los anunciantes puede ser totalmente diferente en eventos distintos. Aunque la sala dispone de alumbrado permanente, raramente se acomoda a las necesidades concretas de cada stand, ya que el patrón de encendido es estático; se conectan puntos de luz por filas o columnas. Cuando una sala tiene decenas o centenares de ellos, es demasiado caro y aparatoso instalar interruptores para cada uno. Debe llevarse una línea de corriente a cada punto de luz como se hace habitualmente, pero en lugar de conectar un interruptor en un registro, proponemos instalar un actuador booleano que funcione como interruptor, de forma similar al prototipo de la sección 8.5.4, pero para una carga menor. Para evitar el cableado de una red de datos se puede utilizar una interfaz inalámbrica o bien PLC. i i i i i i i i 214 8. P ROTOTIPOS El control de todos estos puntos de luz puede hacerse desde cualquier dispositivo que puede enviar invocaciones a los actores; puede ser una interfaz gráfica en un PC, un panel de control centralizado, interruptores fijos instalados en el edificio o bien interruptores inalámbricos, como el que se muestra en la figura 8.13. Tal como vimos en la sección 3.7.1, cada interruptor individual puede actuar sobre un conjunto arbitrario de puntos de luz y es posible recablear las interconexiones lógicas en cualquier momento. Se pueden añadir interruptores y puntos de luz para cubrir las necesidades de cada evento de una forma muy sencilla, rápida y barata. F IGURA 8.13: Interruptor inalámbrico para cableado virtual 8.5.7. Termostato Planteamos un escenario en el que se debe controlar la temperatura de una habitación (por ejemplo, un CPD). El termostato debe poder fijar una temperatura máxima mediante interacción directa o remota sobre el control. Si la refrigeración falla y el umbral fijado se ve superado, el sistema dispara una señal que se puede utilizar para activar una alarma, avisar a un operario o apagar las máquinas susceptibles de sufrir daños por la temperatura excesiva. Hay tres nodos involucrados: Un sensor de temperatura. Es un sensor proactivo instalado en una mota IRIS. Un actuador que recibirá la señal de alerta cuando se supere el umbral establecido. Se implementa como un canal de eventos convencional ejecutándose en un PC. El panel de control. Representa la temperatura actual en un display y permite editar la temperatura máxima con dos pulsadores. Se instala en la placa ALSO1 (ver figura 8.12). El umbral, que también es un objeto, únicamente almacena el valor y puede ser consultado y modificado remotamente como un actuador. El listado 8.6 muestra la especificación IcePick para el panel de control. ByteRWSeq es una interfaz Slice que hereda de DUO::IByte::R, DUO::IByte::W y DUO::Func::Relative. i i i i i i i i 8. P ROTOTIPOS 1 2 3 uses " DOBS / DUO . ice "; uses " IceStorm / IceStorm . ice "; uses " MyApp . ice "; 5 6 object DUO . IByte . W display ; object MyApp . ByteRWSeq threshold ; 8 9 10 11 local adapter thermostat { endpoint = ""; objects = {" UUID1 ": display , " UUID2 ": threshold }; }; 13 14 object IceStorm . Topic t h e r m o m e t e r _ t o p i c ; object DUO . Pulse . W alarm ; 16 17 18 19 20 remote adapter events_server { endpoint = ""; objects = {" IceStorm / therm01 . topic ": thermometer_topic , " IceStorm / alarm01 . publish ": alarm }; }; 22 object DUO . IByte . R thermometer ; 24 25 26 27 remote adapter therm { endpoint = ""; objects = {" therm01 ": thermometer }; }; 29 30 31 boot { t h e r m o m e t e r _ t o p i c . subscribe ( display ) ; } 33 34 35 36 display_delay : timer (2) { thermometer . ice_ping () ; display_delay .enable( false ) ; } 38 39 40 41 show_ threshol d : function { display . set ( threshold . get () , "") ; display_delay .enable( true ) ; } 43 44 45 46 event UP_PUSH do { threshold . inc (1) ; show_ threshol d . run () ; } 48 49 50 51 event DOWN_PUSH do { threshold . inc (−1); show_ threshol d . run () ; } 53 54 55 when display . set ( v ) do { alarm . set ("") if ( v > threshold . get () ) ; } 215 L ISTADO 8.6: Especificación del nodo de control del termostato con alarma i i i i i i i i 216 8. P ROTOTIPOS En el arranque (boot) el display se subscribe al canal de eventos del termómetro, de modo que a partir de ese momento representará su valor de temperatura cada vez que cambie. Durante su funcionamiento, este nodo responde ante dos situaciones asíncronas: Cuando se pulse cualquiera de los dos pulsadores UP y DOWN se ejecutarán los triggers event respectivos; esos eventos son lanzados por el sirviente de los pulsadores. Esto provoca un cambio en el valor del objeto threshold por medio del método inc(). A continuación se ejecuta la función show_threshold. Esa función presenta el valor de threshold en el display y activa el temporizador display_timer. Transcurridos dos ticks se dispara la ejecución del código asociado que invoca el método ice_ping() sobre el termómetro. Como es un actor reactivo, enviará su valor de inmediato a su canal, provocando que el display deje de mostrar el valor del umbral —que se estaba editando— y presente el valor de la temperatura actual. A continuación display_delay se desactiva a sí mismo para evitar sucesivos disparos automáticos. Cuando llega un nuevo valor de temperatura procedente del termómetro (trigger when) evalúa si es mayor que el valor del objeto threshold. Si es así envía un mensaje set() al publicador del canal alarm, que recibirán todos los subscriptores, lo que les informa de que la temperatura ha superado el umbral. 8.5.8. Sensor día/noche Veamos una forma de implementar un sensor día/noche por medio de un sensor tipo LDR y la definición de rangos con el soporte que define DUO para activación condicional (véase § 3.4.3). El listado 8.7 muestra la especificación IcePick para este ejemplo. Un sensor proactivo con activación condicional por rango, como éste, envía eventos set() con su estado sólo cuando se produce un cambio en el valor que mide y éste se encuentra dentro del rango. Sin embargo, el sensor día/noche debe enviar un valor booleano indicando si es de día o de noche. Para lograrlo se crea un objeto intermedio (dummy), que no es accesible remotamente. Se configura ese objeto como publisher del verdadero sensor. El trigger when se encarga de «convertir» la condición de superación de ambos umbrales en un valor booleano. Nótese que el sensor sólo genera eventos cuando el valor está dentro de rango, es decir, no puede ocurrir que el when envíe dos eventos booleanos seguidos del mismo valor. 8.5.9. Detección de presencia polivalente Una de las aplicaciones más frecuentes hoy día de los detectores de presencia volumétricos y sensores PIR en oficinas y hogares es la activación de iluminación interior. Este prototipo desempeña esa función, encendiendo las luces sólo si es de noche, pero además se utilizan esos sensores para detección de intrusos si el sistema está en modo de seguridad. Con ello se pretende demostrar la versatilidad de nuestra solución evitando la necesidad de instalar sensores específicos para cada servicio (algo habitual en las soluciones domóticas tradicionales). Contamos con los siguientes elementos: i i i i i i i i 8. P ROTOTIPOS 1 2 uses " DOBS / DUO . ice "; uses " MyApp . ice "; 4 object DUO . IFloat . W dummy ; 6 7 8 object DUO . ActiveFloatR light_sensor { publisher = dummy ; }; 10 11 12 13 object DUO . IFloat . RW day_value { default = light_sensor ; facet = " range_max "; }; 15 16 17 18 object DUO . IFloat . RW night_value { default = light_sensor ; facet = " range_min "; }; 20 21 22 23 24 25 local adapter node { endpoint = ""; objects = {" LDR001 ": light_sensor , " LDR001 . day ": day_value , " LDR001 . night ": night_value }; }; 27 object DUO . IBool . W day_topic ; 29 30 31 32 remote adapter server { endpoint = ""; objects = {" IceStorm / day . publish ": day_topic }; }; 34 35 36 37 when dummy . set ( value ) do { day_topic . set ( False , "") if ( value > day_value . get () ) ; day_topic . set ( True , "") if ( value < night_value . get () ) ; } 217 L ISTADO 8.7: Sensor día/noche con activación condicional. La interfaz ActiveFloatR hereda de DUO.IFloat.R y DUO.Active.R i i i i i i i i 218 8. P ROTOTIPOS Un sensor noche/día. Podría haber varios para evitar fallos y utilizar un objeto compuesto (véase § 3.6) para agregar la información deseada. En cualquier caso, se considera un actor que envía mensajes DUO::IBool::set() siendo True el anochecer y False el amanecer. Sensores de presencia. Aunque implementados como picoObjetos, son sólo clientes, no objetos. Envían mensajes DUO::Pulse::W::set(). Control de iluminación. La iluminación de cada sala es independiente. Los sensores de presencia activan la iluminación de su sala. De cualquier modo, esto puede cambiar aplicando el cableado virtual. Alarma. Será una referencia a un canal de eventos al que pueden suscribirse todos aquellos que quieran ser alertados de una situación de intrusión, es decir, detección de presencia en modo emergencia. En el listado 8.8 especificamos el servicio que se instala en los nodos que integran el sensor de presencia. Al detectar presencia, el servicio conecta la iluminación local durante 15 ticks, después la apaga. Nótese que, con esta especificación, las luces no se encienden si es de día y tampoco en modo de seguridad. Cuando el nodo se conecta, se suscribe automáticamente al canal del sensor día/noche, de modo que estará operativo automáticamente. Si se desea, es posible que el modo de seguridad se propague por medio de un canal de eventos, caso en el que el nodo podría suscribirse del mismo modo. También es posible integrar el control de la iluminación de la zona en el mismo nodo con cambios mínimos. Si se quiere disponer globalmente de la información de presencia, sin que ello esté ligado a la señal de alarma e independientemente de que esté activado el modo de seguridad, basta con convertir el sensor de presencia en proactivo. Los canales de todos los sensores se pueden enlazar para que los suscriptores pueden saber qué sensor se ha activado en cada momento. Si los sensores tienen información de posición es sencillo realizar una representación gráfica. 8.5.10. Requisitos de memoria La tabla 8.2 muestra los recursos necesarios para la implementación de cada uno de los prototipos descritos en las secciones anteriores. Se incluyen algunos otros de diferente complejidad pero que, por su similitud, no se han descrito expresamente. Cada fila de la tabla describe un nodo con uno o varios objetos. Para cada uno, muestra la cantidad de memoria de programa (fsmCode), ROM (fsmData), Flash (fsmFlash) y RAM (tamaño del banco de registros). Para obtener los recursos necesarios para un nodo completo, hay que sumar a estas cantidades lo requerido por la máquina virtual sobre la que se ejecute (ver tabla 8.1) y el sirviente o drivers que se utilicen. i i i i i i i i 8. P ROTOTIPOS 1 2 3 uses " DOBS / DUO . ice "; uses " DOBS / ASD . ice "; uses " IceStorm / IceStorm . ice "; 5 6 object DUO . IBool . W ni ght_obse rver ; object DUO . IBool . RW service ; 8 9 10 11 12 local adapter presence_node { endpoint = ""; objects = {" UUID1 ": night_observer , " UUID2 ": service }; }; 14 15 16 object DUO . Pulse . W alarm ; object IceStorm . Topic night_topic ; object ASD . Listener ASDA ; 18 19 20 21 22 23 remote adapter event_server { endpoint = ""; objects = {" IceStorm / alarm . publish ": alarm , " IceStorm / night . topic ": night_topic , " IceStorm / ASDA . publich ": ASDA }; }; 25 object DUO . IBool . W light ; 27 28 29 30 remote adapter local_light { endpoint = ""; objects = {" UUID3 ": light }; }; 32 33 34 35 boot { auto_off .enable( False ) ; night_topic . subscribe ({} , nigh t_observ er ) ; } 37 38 39 timer (10) { ASDA . adv ( service ) ; } 41 42 43 44 auto_off : timer (15) { light . set ( False , service . oid ) ; auto_off .enable( False ) ; } 46 47 48 49 night : event PRES ENCE_EVE NT do { light . set ( True , service . oid ) ; auto_off . reset () ; } 51 52 53 security : event PRESE NCE_EVEN T do { alarm . set ( service . oid ) ; } 55 56 57 when nigh t_observ er . set ( v ) do { night .enable( v ) ; } 59 60 61 when service . set ( v ) do { security .enable( v ) ; } 219 L ISTADO 8.8: Detección de presencia polivalente (iluminación e intrusión) i i i i i i i i 220 8. P ROTOTIPOS prototipo endpoint adv #trig data code flash total RAM actor mínimo (Pulse.W) IBool.R + Bool.RW cerradura (Bool.RW) IBool.R + Active.R IString.RW IBool.RW + IByte.RW 3 × IBool.RW 3 × (IBool.RW + Active.R) 3 × IInt.RW, 3 × IInt.R, 1 × IBool.R termostato presencia polivalente oneway no 0 14 89 - 103 18 twoway twoway twoway twoway twoway twoway twoway no sí sí no sí no no 0 1 2 0 3 1 3 68 177 212 71 186 138 159 374 322 431 292 500 381 488 100 16 95 442 449 743 363 702 519 742 19 19 19 19 19 19 19 twoway sí 1 209 846 - 1 055 22 twoway twoway no no 5 7 250 248 626 657 - 876 905 20 19 C UADRO 8.2: Memoria requerida para varios prototipos (en bytes) 8.6. Análisis de protocolos En esta sección se analizan el formato y tamaño de los mensajes utilizados por DUO y ASDF con el fin de demostrar su idoneidad para su implementación en picoObjetos. 8.6.1. DUO Los mensajes para las interfaces escalares son extremadamente regulares. Un mensaje get() para cualquier módulo requiere únicamente 32 bytes más la identidad del objeto. En una red SAN, con identidades de 4 bytes, supone mensajes de 38 bytes (identidad + tamaño + categoría). Las respuestas a estos mensajes son siempre de 25 bytes más el tamaño del valor de retorno: 26 para bool y byte, 27 para short, etc. La interfaz DUO::Container maneja nombres de contenedores y proxies, por lo que el tamaño de los mensajes puede ser muy variable. Por ejemplo, la operación link() para enlazar un contenedor con un nombre de 4 letras y un proxy TCP requiere 92 bytes si se utilizan identidades de 4 bytes. El mensaje más costoso es la respuesta al método list() dado que devuelve una secuencia de proxies. Si éstos son TCP y tienen identidades de 4 bytes supone 48 bytes por cada uno. Es poco probable que un picoObjeto que actúe como contenedor tenga muchos hijos, y debe tenerse en cuenta que prácticamente todo el proxy es idéntico (solo cambia la identidad), de modo que para el picoObjeto el coste en memoria es mucho menor, solo tiene que guardar las identidades y una plantilla de proxy. La tabla 8.3 muestra el tamaño de los mensajes más importantes de DUO y también de los mensajes de I CE requeridos para la operación de los servicios típicos. Se suponen identidades de 4 bytes y proxies TCP. i i i i i i i i 8. P ROTOTIPOS 221 mensaje tamaño (bytes) Ice::Object::ice_ping Ice::Object::ice_isA (request) Ice::Object::ice_isA (reply) IceStorm::TopicManager::create IceStorm::Topic::subscribe IceStorm::Topic::link DUO::IByte::W::get (request) DUO::IByte::W::get (reply) DUO::IByte::W::set (request) DUO::IByte::W::set (reply) DUO::Container::list (request) DUO::Container::list (reply) DUO::Container::link DUO::Container::create DUO::Container::destroy DUO::Active::getCb (request) DUO::Active::getCb (reply) DUO::Active::getTopic (request) DUO::Active::getTopic (reply) DUO::Active::setCbTopic 43 42 + Type ID 26 41 + nombre 91 91 38 26 39 25 39 25 + (n.o proxies × 48) 87 + nombre 41 + nombre 42 40 88 43 88 141 (ambos no nulos) C UADRO 8.3: I CE y DUO: Tamaño de los mensajes 8.6.2. ASDF El listado 8.9 muestra el desglose del método adv() transportando un proxy con un endpoint TCP convencional. El mensaje completo ocupa 95 bytes. El tamaño del mensaje depende principalmente de dos cosas: la identidad del objeto anunciado («R309» en el ejemplo) y el tipo de endpoint que utiliza el proxy (24 bytes en este caso). De modo que el tamaño fijo mínimo del mensaje es de 49 bytes (usando IceStorm/ASDA.publish como destino), a los que hay que sumar lo requerido por esos dos elementos. Si se utilizan endpoints más simples, el tamaño puede verse sensiblemente reducido. Por ejemplo, el endpoint XBow sólo ocupa 3 bytes frente a los 24 del endpoint TCP. En una red SAN con identidades de 4 bytes, este mensaje ocuparía en torno a 55 bytes, lo suficientemente pequeño para enviarse en un solo mensaje (128 bytes por defecto en el protocolo XBow). Todo el contenido del mensaje es estático, a menos que se utilicen direcciones lógicas dinámicas. Eso significa que puede ser almacenado en memoria ROM del dispositivo, con la ventaja añadida de que varios fragmentos de este mensaje se pueden utilizar también en otras invocaciones o en las respuestas. Los dos únicos mensajes que deben implementar los picoObjetos son adv() de la interfaz ASD::Listener (como cliente) y getp() de la interfaz ASD::PropHldr (como servidor). Para éste último, el picoObjeto debe enviar respuestas, pero su formato y tamaño son muy similares a los del adv() puesto que también implican el envío de un proxy. i i i i i i i i 222 8. P ROTOTIPOS Internet Commu nication s Engine Protocol Magic Number : ’I ’ , ’c ’ , ’e ’ , ’P ’ Protocol : 1 ,0 − Encoding : 1 ,0 Message Type : Request (0) Compression Status : Uncompressed (0) Message Size : 95 Request Message Body Request Identifier : 1 Object Identity : IceStorm / ASDA . publish Facet Name : ( empty ) Operation Name : adv − Ice :: OperationMode : idempotent (2) Invocation Context : ( empty ) Input Parameters Size : 48 − Encoding : 1 ,0 Encapsulated parameters (42 bytes ) Object Identity : / R309 Facet Name : ( empty ) Mode : twoway (0) Secure : False (0) Endpoints (1) Type : TCP (1 ,0) Input Parameters Size : 30 − Encoding : 1 ,0 Encapsulation (24 bytes ) Host : 193.6 3.148. 188 (14 bytes ) Port : 37752 (4 bytes ) Timeout : Max (4 bytes ) Compress : False (0) L ISTADO 8.9: Disección de un mensaje ASD::Listener::adv() La tabla 8.4 muestra el tamaño del resto de los mensajes de ASDF para identidades de 4 bytes y endpoints TCP con direcciones de host de 15 bytes. El mensaje más caro es lookup() ya que incorpora un conjunto de propiedades. Sin embargo, gracias a la indirección que proporciona la interfaz ASD::PropHldr, estos mensajes nunca son gestionados por los nodos de la SAN. mensaje ASD::Listener::adv ASD::Listener::bye ASD::Search::lookup ASD::Search::discover ASD::PropHldr::getp (request) ASD::PropHldr::getp (reply) tamaño (bytes) 80 43 83 + consulta 85 32 73 C UADRO 8.4: ASDF: Tamaño de los mensajes 8.7. Prototipos IDM Hemos realizado algunos prototipos iniciales para ilustrar las posibilidades y para evaluar la sobrecarga al utilizar IDM. Se compara IDM con invocaciones I CE convencionales y con sockets TCP y UDP tradicionales. Los prototipos utilizan el middleware ZeroC i i i i i i i i 8. P ROTOTIPOS 223 I CE (versión 3.3). Los siguientes datos se han obtenido en un computador compatible IBM PC con procesador Intel Core2 Duo 2.33GHz, interfaz de red Ethernet 100 Mbps con un sistema operativo Debian GNU/Linux. Los ejemplos están implementados en C++ y compilados con GNU GCC 4.3. Estas pruebas de latencia y transferencia están inspiradas en las que ZeroC facilita en su página web [Zerb] así como en el código fuente utilizado para ellas. F IGURA 8.14: Topología de red utilizada para las pruebas de rendimiento La intención de estas pruebas es demostrar que la sobrecarga debida al uso de IDM no implica una degradación significativa de las prestaciones. Además, debe tenerse muy presente que se han empleado endpoints TCP y UDP para todas las conexiones. Cuando estén disponibles endpoints más adecuados será posible mejorar en muchos casos las prestaciones de I CE e, incluso, de la pila TCP/IP. Por ejemplo, si las restricciones de la aplicación lo permiten se podrá enviar un flujo multimedia multicast dentro de una LAN encapsulado directamente sobre tramas Ethernet, con el consiguiente ahorro de cabeceras y sobrecarga debida al cálculo de CRC, etc. El código fuente empleado para la realización de estas pruebas, la implementación de referencia de nuestro prototipo actual y otra información relevante está disponible para consulta en la página web de IDM [IDM]. 8.7.1. Latencia Las pruebas de latencia miden el tiempo necesario para realizar una invocación a un objeto remoto enviando una carga útil nula o muy pequeña. La tabla 8.5 muestra los tiempos medios por invocación de una serie de 100 000 invocaciones del método ice_ping(). Se trata del mensaje más simple que se puede implementar en I CE, no tiene parámetros ni valor de retorno. Para la comparación con los sockets BSD, se envían mensajes y respuestas de un byte. Se fuerza el envío de cada mensaje mediante flush() para evitar que el socket pueda optimizar el envío de varios mensajes en un solo segmento. Las invocaciones twoway requieren la recepción del mensaje de respuesta antes de enviar la siguiente petición, mientras que las invocaciones oneway permiten enviar el siguiente mensaje inmediatamente. i i i i i i i i 224 8. P ROTOTIPOS invocación (Twoway) Local Remoto (directo) Remoto (1 salto IP) Remoto (1 salto IDM) (Oneway) Local (oneway) Remoto (directo) Remoto (1 salto IDM) socket I CE IDM 23 268 312 N/A 31 274 360 N/A 32 278 384 2 537 8 76 N/A 13 98 N/A 15 112 1 049 C UADRO 8.5: Pruebas de latencia de IDM (en µs) 8.7.2. Rendimiento Las pruebas de rendimiento (tasa de transferencia) tratan de medir la eficiencia del protocolo enviando datos en crudo. La tabla 8.6 muestra los tiempos medios por invocación de un conjunto de 1 000 mensajes twoway que transportan secuencias de 500 kB. Todas las invocaciones son twoway. invocación Local Remoto (direct) Remoto (1 salto IDM) Remoto (2 saltos IDM) socket I CE IDM 292 42 394 N/A N/A 365 43 051 N/A N/A 485 43 276 98 291 101 265 C UADRO 8.6: Pruebas de rendimiento de IDM (en µs) 8.8. Conclusiones Los prototipos que se han descrito a lo largo de este capítulo demuestran la viabilidad de nuestros planteamientos. Hemos implementado con éxito picoObjetos tanto en plataformas comerciales como en dispositivos de diseño propio, utilizando varios lenguajes de implementación, y con niveles de complejidad y prestaciones muy diferentes. Los prototipos demuestran también la gran flexibilidad del modelo DUO, la interconexión de actores por medio del cableado virtual y el protocolo ASDF, incluso con servicios de una complejidad importante. i i i i i i i i Conclusiones y trabajo futuro 9.1. 9.2. 9.3. 9.4. 9.5. Infraestructura de integración Un middleware para WSN Resumen de contribuciones Publicaciones Nuevas líneas de trabajo 99 U NA vez abordados todos los componentes de la infraestructura de integración que nos planteábamos como objetivo, llega el momento de recapitular y analizar las ventajas que se obtienen al fusionar las soluciones a los problemas parciales que implica el uso de las redes de sensores bajo nuestro enfoque: el entorno inteligente como un sistema distribuido heterogéneo. Este capítulo comienza con la descripción de esa infraestructura, incluyendo un resumen de los elementos que la forman, y para cada uno de ellos se destacan las contribuciones concretas que aporta este trabajo. Por último, se plantean algunas líneas de trabajo que se abren como consecuencia de dichas aportaciones, y se describen algunas aplicaciones que pueden ser objeto de investigación en el futuro. 9.1. Infraestructura de integración El objetivo era la definición de una infraestructura completa, flexible y eficaz para resolver la mayoría de los problemas que aparecen de forma recurrente en la integración de redes SAN con una red troncal y/o entre redes SAN de distinta tecnología. Los principios de diseño para la construcción de esa infraestructura han sido los siguientes: Integración Adaptar otros middlewares, dispositivos o sistemas, incluso cerrados, a nuestra infraestructura. Especialización sin pérdida de generalidad Mediante la definición de interfaces adecuadas, abstrayendo las diferencias pero exponiendo la funcionalidad al sistema. 225 i i i i i i i i 226 9. C ONCLUSIONES Y TRABAJO FUTURO Reutilización Aprovechando cualquier trabajo previo disponible, ya sean dispositivos, protocolos, drivers, etc. Interoperabilidad a nivel de protocolo Consiguiendo de ese modo un buen nivel de compatibilidad e interacción transparente entre sistemas diferentes. Nodos autónomos La autonomía de los dispositivos es un aspecto clave para lograr tolerancia ante fallos. Propiciar que la inteligencia del sistema esté distribuida en lugar de residir en unos pocos componentes. Orientación a objetos El objeto es la unidad funcional básica para realizar cualquier tarea: todo es un objeto. Ese principio permite encapsular la funcionalidad, delimitar las responsabilidades sobre datos y procesos, y ocultar los detalles específicos. La figura 9.1 muestra los elementos que forman la infraestructura resultante. Los componentes relacionados con esta tesis (con fondo blanco) y su papel dentro de ella se resumen en el resto de la sección. Otros componentes de la arquitectura tratan aspectos como la gestión global de la Q O S o la composición automática de servicios, y no han sido abordados. La arquitectura completa se denomina DOBS (Distributed Object Based Services) [VVSL09] y su objetivo es proporcionar servicios avanzados en entornos inteligentes. F IGURA 9.1: Esquema general de la infraestructura de integración de redes SAN 9.1.1. Middleware orientado a objetos No proponemos un nuevo middleware; estamos convencidos que la cantidad y variedad de MDOO de propósito general es suficiente para encontrar alguno que se adapte razonablemente a la gran mayoría de las situaciones. Prácticamente todos los middlewares que se han considerado en la sección 2.5 proponen planteamientos muy especializados i i i i i i i i 9. C ONCLUSIONES Y TRABAJO FUTURO 227 que implican el diseño de sistemas completamente nuevos. Sin embargo, en muchos casos llegan a diseños con abstracciones muy similares a los MDOO clásicos. Nuestra estrategia en este aspecto es más parecida a la de nORB [SXGC03]. Si bien es cierto que las redes SAN tienen características y necesidades especiales, creemos que es mucho más conveniente emplear un MDOO convencional y añadir los servicios y componentes necesarios para cubrir los casos de uso no considerados en éste que realizar un nuevo diseño desde cero. Ello supone varias ventajas importantes: Orientación a objetos Un paradigma de programación ampliamente aceptado y que encaja perfectamente en el diseño e implementación de sistemas distribuidos dotando de abstracciones muy convenientes que permiten reducir el acoplamiento y aumentar la reutilización por medio de interfaces bien definidas a nivel del sistema. Heterogeneidad Muchos de estos middlewares proporcionan bibliotecas o bindings para ser utilizados desde varios lenguajes de programación y están diseñados de modo que es relativamente sencillo adaptarlos a nuevas plataformas y sistemas operativos. Independencia del transporte Aunque no es una característica presente en todos los MDOO, la posibilidad de abstraer la infraestructura de comunicaciones utilizada para el transporte de mensajes inter-ORB resulta especialmente útil. En cualquier caso, la necesidad de ese protocolo inter-ORB y una representación de datos independiente ofrece una interfaz de bajo nivel para interaccionar con el middleware, y esa es precisamente la característica que hace posible nuestros picoObjetos. Servicios comunes Prácticamente todos los middlewares veteranos disponen de un rico conjunto de servicios perfectamente integrados y probados. El desarrollo de cualquier aplicación final se ve a menudo favorecido por el ahorro de esfuerzo que suponen los mecanismos ya previstos por el fabricante del middleware. Experiencia Los principios de diseño en los que se basan los MDOO se vienen utilizando desde hace tiempo para crear grandes aplicaciones. Han demostrado ser una buena solución y adaptarse bien a los problemas que han ido apareciendo a lo largo de los años. Consideramos de vital importancia aprovechar los diseños, desarrollos y experiencia en torno a los sistemas previos. La inmensa cantidad de aplicaciones exitosas que se han venido desarrollando durante más de una década avalan los middlewares de propósito general, especialmente los MDOO. Por ejemplo, CORBA cuenta con el consenso de cientos de las más importantes empresas de la industria del software de todo el mundo. En nuestra propuesta, el middleware es la piedra angular de la infraestructura, pero ésta es lo suficientemente flexible como para adaptarse a middlewares considerablemente distintos i i i i i i i i 228 9. C ONCLUSIONES Y TRABAJO FUTURO siempre que respeten en mayor o menor medida el concepto de objeto o servicio distribuido y estén basados en el intercambio de mensajes o invocación de métodos remotos. 9.1.2. picoObjetos Se han descrito y analizado las ventajas prácticas y metodológicas que implica la construcción de objetos distribuidos empotrados con picoObjetos. Su utilización en las redes SAN ofrece la oportunidad de que cualquier transductor pueda ser integrado en una aplicación distribuida de forma completamente transparente, ocultando todos los detalles de fabricación del dispositivo, su funcionamiento interno o, incluso, paliando sus limitaciones funcionales cuando se requiera. Cada transductor es visto desde la red como un objeto autónomo al que se le pueden solicitar servicios sin intermediarios. Se han analizado en detalle las limitaciones y requisitos de interoperabilidad para dos casos concretos: CORBA e I CE, y se incluye una descripción del juego de instrucciones que permite describir máquinas de estados para reconocimiento y generación de mensajes conforme a sus respectivos formatos de protocolo. Se ha diseñado un lenguaje de alto nivel (IcePick) con el que es posible modelar servicios como interacciones simples, pero no triviales, entre objetos de un nodo o entre nodos diferentes, independientemente de si los objetos involucrados están o no implementados como picoObjetos. La descripción de interacción entre objetos de diferentes nodos permite, pero no limita, la definición de comportamiento global similar al que ofrecen los sistemas de macro-programación. El modelo de ejecución que se propone está basado en la utilización de una máquina virtual y la generación de bytecode (aunque no se descarta la posibilidad de generar código nativo). Se ha diseñado e implementado un compilador capaz de generar bytecode a partir de una descripción en IcePick. Proporcionamos implementaciones de referencia de la máquina virtual para un conjunto de plataformas lo suficientemente rico como para demostrar su viabilidad sobre prácticamente cualquier dispositivo de cómputo empotrado conectado a una red de datos. Se proporciona soporte al flujo de desarrollo completo de aplicaciones distribuidas en las que haya involucrados transductores implementados como picoObjetos. Este flujo abarca desde la especificación de las interfaces hasta las fases de prueba e implantación. El uso de bytecode hace posible plantear una solución general para despliegue y actualización de aplicaciones en los picoObjetos por medio de picoGrid (véase § 4.9). 9.1.3. Modelo de información DUO define un conjunto de servicios rico y flexible, orientado a satisfacer las necesidades funcionales de la mayoría de las aplicaciones que involucran redes SAN en entornos inteligentes. Es lo suficientemente sencillo como para ser implementado sin problema en dispositivos con capacidades muy reducidas, a la vez que es suficientemente potente como para construir servicios complejos como es el caso de cámaras de vídeo motorizadas. Proporciona utilidades para la creación y gestión dinámica de colecciones de objetos, mecanismos de notificación asíncrona mediante objetos activos, agregación transparente, activación condicional, etc. i i i i i i i i 9. C ONCLUSIONES Y TRABAJO FUTURO 229 Obviamente, su diseño está muy influenciado por las restricciones para las que están diseñados los picoObjetos, pero sin que eso suponga sacrificar sus posibilidades en sistemas o aplicaciones que no los requieren. Resulta muy útil para disponer de colecciones de objetos con interfaces muy ortogonales y genéricas, que dan lugar a características tan interesantes como el cableado virtual, que no serían posibles con interfaces especializadas. Hace posible la instanciación de servicios reactivos sin más infraestructura que los propios nodos y la necesaria red de comunicaciones. 9.1.4. Descubrimiento de servicios ASDF complementa el modelo de información de DUO aunque no depende de él. Dota al sistema de mecanismos para la búsqueda y descubrimiento de servicios. De nuevo, aunque se trata de un protocolo diseñado teniendo en cuenta las restricciones de los picoObjetos, no supone una desventaja para su adopción en el sistema completo. ASDF no es un SDP para la SAN sino para toda la red, para todos los servicios de la aplicación, involucren o no a redes de sensores. Su funcionamiento se fundamenta en una taxonomía de servicios y en la definición de conjuntos de propiedades. La distribución de información se realiza por medio de los canales de eventos proporcionados por el middleware, aunque dispone de una gran diversidad de alternativas para disposiciones distribuidas, centralizadas o mixtas en los mecanismos de anuncio, búsqueda y almacenamiento de las propiedades. Esto lo dota de una gran flexibilidad que le permite adaptarse a las necesidades de casi cualquier sistema. También dispone de un servicio de metamodelo que permite a las aplicaciones explorar programáticamente la descripción de los servicios de forma que, por ejemplo, un cliente puede listar los tipos de servicio disponibles o las propiedades válidas en cada uno de ellos —algo muy útil para la búsquedas— sin necesidad de conocimiento previo del entorno o la aplicación concreta. 9.1.5. Redes heterogéneas La interconexión de la red SAN con la red troncal se realiza normalmente por medio de estaciones base que operan como pasarelas de servicio. IDM propone una solución alternativa para lograr encaminamiento independiente de la capa de red, su tecnología o protocolos. Esto es posible gracias a que los nodos de la red SAN (los picoObjetos) son autónomos y no requieren entidades ajenas que los representen o que traduzcan su protocolo, como suele ocurrir en la gran mayoría de las propuestas previas. Simplifica o soluciona muchos de los problemas que implicaba el uso de pasarelas (véase § 2.6.2). Por ejemplo, hace posible la creación de redes de sensores multisink. IDM es un mecanismo universal de encaminamiento de mensajes. Aunque ha sido diseñado para solventar los problemas de acceso a las SAN, se ha hecho un esfuerzo considerable para que pueda aplicarse en cualquier circunstancia en la que se desee comunicar entre sí nodos de redes incompatibles. i i i i i i i i 230 9. C ONCLUSIONES Y TRABAJO FUTURO Incluye la definición del formato de los mensajes para el reenvío de invocaciones, la descripción del procedimiento completo para la entrega al objeto remoto y la devolución de la respuesta al cliente de forma transparente. 9.2. Un middleware para WSN Veamos a continuación en qué medida resuelve nuestra propuesta los problemas de los middlewares para SAN identificados en la bibliografía. ROMER [RKM02] sugiere una serie de requisitos que, en su experiencia, debería tener un middleware en el contexto concreto de las WSN. Consideramos que es una buena referencia para medir algunos de los logros conseguidos en esta tesis. Estas son las consideraciones más importantes: «El pequeño tamaño de los nodos implica también recursos reducidos (capacidad de cómputo, memoria, alcance y ancho de banda, etc.)». Una implementación completa de un racimo de picoObjetos, incluyendo la máquina virtual, ocupa una pequeña parte de la memoria disponible en la mayor parte de los dispositivos utilizados en redes WSN, al menos un orden de magnitud menos que cualquier sistema previo. Al ser una máquina dirigida por eventos (event-driven), el consumo de CPU se produce únicamente cuando es necesario. Los mensajes utilizados por las interfaces propuestas son pequeños y se soportan protocolos asíncronos, y envío multicast cuando la tecnología de red lo permite (habitual en redes wireless). «La red WSN puede estar formada por una gran cantidad de nodos diferentes, en términos de transductores utilizados, potencia de cómputo y memoria». En relación a la ejecución de código, el uso de una máquina virtual abstrae las peculiaridades de la arquitectura concreta de cada nodo. En las comunicaciones, el protocolo de transporte inter-ORB homogeneiza la invocación de cualquier servicio en cualquier nodo. «Comunicación centrada en los datos (data-centric). Los nodos de la red son, por lo general, meros productores o consumidores de datos. Eso mejora la robustez porque desacopla el dato del sensor que lo produce». Las interfaces DUO encajan perfectamente en este enfoque, pero además permiten ver los transductores como objetos y proporcionan mecanismos para crear colecciones, componentes e integración de servicios reactivos por medio de cableado virtual. Las interfaces DUO desacoplan el dato del transductor que lo produce, pero el consumidor puede obtener la identidad del objeto responsable si lo necesita. Eso permite implementar servicios de consulta masiva con una eficiencia razonable. «El middleware debe dar soporte al desarrollo, mantenimiento, despliegue de aplicaciones». i i i i i i i i 9. C ONCLUSIONES Y TRABAJO FUTURO 231 Se proporciona un entorno de desarrollo completo (capítulo 6) que permite el desarrollo de picoObjetos de un modo sencillo y que pueden ser probados antes de su implantación, separando claramente los roles del personal implicado en el desarrollo. Servicios proporcionados por I CE, como IceGrid o IcePatch2 pueden resultar muy útiles para tareas de mantenimiento y despliegue de aplicaciones. El despliegue de aplicaciones en la SAN se aborda con picoGrid, con un modelo de ejecución que encaja perfectamente con el funcionamiento de los picoObjetos. «debe proporcionar [...] mecanismos para especificar tareas de detección complejas, coordinación de sensores para dividir la tarea y distribuirla a los nodos sensores individuales, fusión y mezcla de los datos a partir de las lecturas individuales para conseguir datos de más alto nivel...». El lenguaje IcePick proporciona mecanismos básicos para especificar relaciones no triviales entre objetos del mismo o distintos nodos, de forma transparente. Por medio de canales de eventos y utilizando los servicios que proporciona ASDF es sencillo construir aplicaciones complejas: consultas selectivas, búsquedas por servicio, gestión de propiedades, etc. Con todo ello se pueden obtener datos de más alto nivel calculados a partir de las lecturas y teniendo en cuenta el contexto en que se realiza. Estos datos derivados se pueden ofrecer de nuevo a la red por medio de sensores virtuales [RMDS02]. Por ejemplo, un objeto compuesto (véase § 3.6) puede ofrecer la temperatura media de una habitación utilizando la misma interfaz que los sensores reales que hay en la sala. «El ámbito del middleware de la WSN no está restringido solo a la red, también debe cubrir dispositivos y redes conectados a la WSN. El middleware para la red de sensores debería proporcionar una visión holística de la WSN y las redes tradicionales, lo que supone un desafío para el diseño arquitectural y la implementación». Como se utiliza un middleware de propósito general, para la aplicación no hay ninguna diferencia en el acceso a un objeto dentro de una WSN o de cualquier otro dispositivo en cualquier red accesible. Con IDM se intenta llevar esta transparencia un paso más allá, de modo que se puedan encaminar eventos y peticiones a través de cualquier red independientemente de su protocolo o tecnología de red. Bajo este enfoque, todos los elementos son objetos distribuidos: nodos, transductores, encaminadores, consumidores, etc. Aunque ciertamente es un desafío, ya está parcialmente resuelto por los middlewares de comunicaciones para sistemas distribuidos heterogéneos. La necesidad aquí es adaptarlos a las características de las redes SAN, pero no es necesario plantear un diseño arquitectural o la implementación de middlewares completamente nuevos. i i i i i i i i 232 9. C ONCLUSIONES Y TRABAJO FUTURO Éste es un aspecto muy importante que plantean también otros autores. En [VHM+ 07, HMM+ ] se clasifican los middlewares dependiendo si se aplican a la SAN, la pasarela o la red troncal (backend) concluyendo que lo ideal sería un middleware para todo (end-to-end). Ese es precisamente nuestro planteamiento inicial y creemos que se ha logrado en buena medida. 9.3. Resumen de contribuciones Según se desprende de las secciones anteriores esta tesis aporta las siguientes contribuciones específicas: Una infraestructura de integración que resuelve los problemas de las redes SAN en un contexto heterogéneo de dispositivos, redes y servicios. Un middleware construido sobre cualquier MDOO de propósito general que aprovecha las ventajas de las soluciones estándar para computación distribuida heterogénea. Un conjunto de métodos, lenguajes, y herramientas de soporte para el desarrollo de objetos distribuidos diminutos, como mínimo un orden de magnitud más pequeños que las aproximaciones anteriores. Un modelo de información rico y flexible orientado al diseño de aplicaciones que involucran redes SAN. El modelo soporta una amplia variedad de modos de interacción, jerarquía, agregación, activación condicional e introspección avanzada. Un mecanismo de anunciamiento y descubrimiento de servicios que permite integrar muy fácilmente redes heterogéneas e incluso islas gestionadas con SDP incompatibles entre sí. El mecanismo se sustenta en una taxonomía que define el conjunto de propiedades y un metamodelo que proporciona mecanismos de introspección. Un mecanismo de encaminamiento heterogéneo de mensajes, que resuelve problemas de acceso a las SAN, pero que también puede ser usado para proporcionar calidad de servicio, incrementar la tolerancia a fallos, proporcionar transparencia de migración, etc. Todas estas contribuciones responden al diseño de una plataforma unificada para la construcción de aplicaciones, servicios e instalaciones que involucren a redes SAN, incluso las que integran dispositivos de muy bajo coste. De esta forma se proporciona una solución a la mayoría de los problemas identificados con anterioridad. 9.4. Publicaciones Derivados de los trabajos de esta tesis se han publicado algunos trabajos relevantes; bien como consecuencia directa de las aportaciones, bien como trabajo conjunto con otros miembros del grupo ARCO: i i i i i i i i 9. C ONCLUSIONES Y TRABAJO FUTURO 233 En [VML04] se plantea la posibilidad de generar autómatas reconocedores para mensajes GIOP y de ese modo conseguir interoperabilidad básica con clientes CORBA. Se analiza en detalle cómo salvar los problemas de interoperabilidad con el formato de los mensajes. En [VVM+ 05a] se generaliza el planteamiento para dar cabida a cualquier protocolo inter-ORB binario, dando detalles específicos tanto de CORBA como I CE. Por último, en [VVM+ 06a] se aportan prototipos funcionales de picoCORBA para PC (en C y Java), TINI y PIC12C509 (asm) y se comparan con prototipos de otros middlewares empotrados. En [VVM+ 07b] se describen las ventajas que el flujo de diseño con picoObjetos aporta al desarrollo de aplicaciones ubicuas y sus posibilidades de implementación mediante lógica reconfigurable. En [MVV+ 09] planteamos una solución completa para el uso de MDOO en redes de sensores incluyendo la posibilidad de implementar objetos distribuidos tanto en microcontroladores de gama baja como en dispositivos FPGA. También es destacable la solicitud de patente titulada «Método y dispositivo para interconexión de equipos heterogéneos con recursos limitados por medio de middlewares orientados a objeto» (Ref:200803715) que en estos momentos se encuentra pendiente de aprobación. En [VVM+ 05b, VVM+ 06b] se aborda el problema de la gestión de calidad de servicio en redes móviles ad hoc (MANET) en el contexto de los entornos inteligentes. En [VOV+ 06] se tratan los problemas de transmisión de flujos multimedia en este tipo de redes. El protocolo ASDF y sus características como SDP adecuado para redes de sensores se discuten en [VVM+ 07a, VVM+ 08a]. Se analizan los casos de uso soportados y los diferentes escenarios posibles que cubren la funcionalidad típica de los SDP S más utilizados. IDM y su aplicación para obtener acceso transparente a las redes de sensores se aborda en [VVM+ 08b] explicando los problemas de interoperabilidad y robustez que implican las pasarelas de servicios y cómo este enfoque ayuda a evitarlas. En [UVV+ 09] se aplican estos principios a la comunicación con redes de vehículos submarinos. Los métodos y herramientas desarrollados para la generación de picoObjetos tienen también aplicación a middlewares no orientados a objeto, como es el caso de los Web Services. En [VVM+ 09] se explora esta posibilidad de forma análoga a como se describe en el anexo B. Se incide en los procesos necesarios para dotar de autonomía a los nodos de una red de sensores que implementan por sí mismos todo lo necesario para proporcionar un servicio extremo a extremo. 9.5. Nuevas líneas de trabajo El trabajo realizado proporciona nuevos enfoques para la resolución de problemas, o bien para mejorar o simplificar otros ya resueltos. Algunos de ellos se describen a continuación. i i i i i i i i 234 9. C ONCLUSIONES Y TRABAJO FUTURO 9.5.1. Encaminamiento ad hoc con IDM Si bien IDM se ha concebido como una solución de interconexión de redes heterogéneas, se puede utilizar para conseguir encaminamiento en una red ad hoc (muy habitual en redes SAN). En este caso, cada nodo de la red debe incluir un encaminador IDM y un servicio que proporcione descubrimiento de vecinos mediante ALP. Este planteamiento tiene varias ventajas: El encaminamiento de invocaciones dentro y fuera de la red ad hoc es transparente. Para los objetos del nodo no hay diferencia entre invocar un objeto en otro nodo de la red ad hoc, la red troncal o una tercera red. Lo mismo puede aplicarse a un cliente en la red troncal. Es relativamente sencillo plantear soluciones de encaminamiento para redes híbridas. En estos momentos ya estamos trabajando en un escenario en el que una red de PDA S que forman una red ad hoc se comunica con redes de sensores y con una red troncal estática en la que puede haber computadores portátiles. Las invocaciones desde cualquier nodo, sea computador, PDA o nodo de la SAN pueden llegar a cualquier otro dispositivo encaminándose a través de cualquiera de las tres redes de forma transparente, gracias a IDM. El protocolo de encaminamiento (basado en AODV) se implementa sobre IDM. Es posible acceder fácil y remotamente a la información de encaminamiento dado que los encaminadores IDM son objetos distribuidos. No se necesitan mecanismos adicionales, el mismo middleware utilizado para acceder a los servicios se emplea para transportar los mensajes del protocolo de encaminamiento y acceder a los propios encaminadores. Los encaminadores IDM se pueden implementar como picoObjetos. En ese caso, las capacidades de los nodos deberían ser mayores que las consideradas para servir transductores. El encaminador puede requerir una cantidad relativamente importante de memoria RAM (en relación a los nodos sensores) para el mantenimiento de la tabla de rutas y el estado del algoritmo de encaminamiento. Los 128 bytes de RAM que eran suficientes para un picoObjeto resultan insuficientes en este caso. Incluso requiriendo una plataforma de 16 bits, el tamaño de estos encaminadores podría ser ostensiblemente menor que el de otras propuestas actuales y con la gran ventaja de permitir encaminamiento transparente fuera de la red. 9.5.2. Plataforma de gestión para redes heterogéneas Siguiendo nuestro planteamiento habitual de que todo es un objeto, proponemos el modelado de cualquier nodo de la red como un conjunto de objetos. No sólo sus transductores; cada componente funcional del host puede ser representado como un objeto, siguiendo un modelo de información similar a DUO. Por ejemplo, la memoria disponible, la energía restante o el número de mensajes recibidos podrían obtenerse remotamente por medio de invocaciones a métodos. No es una propuesta nueva. El modelo de información de TMN (Telecommunications Management Network) [TMN01] no dista mucho de esta idea. La ventaja aquí es que nuestra plataforma de gestión podría estar implementada como picoObjetos (cuando las limitaciones lo requieran), aunque eso no debería impedir su adaptación a cualquier otro nodo, incluso a PC S. i i i i i i i i 9. C ONCLUSIONES Y TRABAJO FUTURO 235 Una plataforma de este tipo sería muy útil para analizar y depurar algoritmos de encaminamiento o protocolos de comunicaciones experimentales en redes de dispositivos empotrados. Únicamente las variables a controlar serían realmente instaladas en el dispositivo, y con la posibilidad de utilizar picoGrid para desplegar versiones nuevas para cambiar el conjunto de variables accesibles. 9.5.3. Plataforma de despliegue heterogéneo En redes formadas por muy diversos dispositivos resultaría muy útil un servicio de despliegue único que permita enviar actualizaciones de configuración y programas de forma completamente independiente de la tecnología del nodo y de la red a la que esté conectado. La solución pasaría por integrar un servicio de despliegue para nodos convencionales (como IceGrid) junto con picoGrid, empleando IDM como medio de comunicación para homogeneizar el acceso a cualquier dispositivo. 9.5.4. Modelado semántico de servicios Nuestra experiencia en el uso del protocolo de búsqueda de servicios que proporciona ASDF ha puesto en evidencia algunos problemas principalmente en cuanto a flexibilidad. El más grave es que al emplear una taxonomía como diccionario de servicios, las posibilidades de incluir nuevos tipos de servicios en un sistema en operación son muy limitadas. Esto normalmente no es un problema si todos los servicios están definidos en la fase de diseño, pero sí puede serlo en otro caso. Se propone la definición de un modelo semántico, expresado mediante una ontología y descrito mediante un lenguaje formal, que permite a servicios y dispositivos definir nuevas instancias en contextos específicos. De este modo, cuando un cliente necesita un servicio envía una consulta que especifica un conjunto de enunciados que se deben cumplir, por ejemplo «captar imagen» y se puede acompañar de propiedades como la ubicación o la disponibilidad. El diccionario de verbos (captar) y objetos (imagen) puede estar disponible a través de un servicio específico. Las descripciones de los servicios y el vocabulario pueden cambiar incluso en un sistema en funcionamiento. Realmente no implica grandes cambios respecto a las propuestas realizadas en esta tesis. Seguimos teniendo propiedades tal como se han implementado en ASDF, un servicio de metamodelo para servir los vocabularios y las relaciones (MIS) y una descripción del servicio alojada en cada actor. Solo el método ASD::Search::lookup() necesita ser modificado para incluir una descripción de servicio más compleja, en lugar de simplemente una interfaz y un conjunto de propiedades. El resto del protocolo ASDF funcionaría tal como se ha explicado, pero la flexibilidad, riqueza y precisión de las búsquedas aumentaría sensiblemente. i i i i i i i i i i i i i i i i ANEXOS i i i i i i i i i i i i i i i i Repertorio de instrucciones FSM A A A continuación se detalla la finalidad y forma de uso de todas las instrucciones disponibles en el lenguaje FSM: nop() No ejecuta nada, sirve únicamente como relleno para el alineamiento de las páginas de bytecode (véase § 4.6.1). ejemplo: bytecode: nop() NOP reset() Inicializa el contexto de ejecución según los valores por defecto y salta al manejador del evento RESET que normalmente es una función principal indicada en el bloque de inicialización de la máquina. ejemplo: bytecode: reset() RESET goto(block) Salta a la dirección de comienzo del bloque block. ejemplo: bytecode: goto(‘reply’) GOTO ADDR goto_nz(block) Salta a la dirección de comienzo del bloque block si el registro de trabajo contiene un valor distinto de cero. ejemplo: bytecode: goto_nz(‘put_iface’) GOTO_NZ ADDR 239 i i i i i i i i 240 A. R EPERTORIO DE INSTRUCCIONES FSM goto_eq(block, reg) Salta a la dirección de comienzo del bloque block si el registro de trabajo y el registro reg contienen el mismo valor. ejemplo: bytecode: goto_eq(‘put_iface’, 8) GOTO_EQ ADDR REG goto_neq(block, reg) Salta a la dirección de comienzo del bloque block si el registro de trabajo y el registro reg contienen valores diferentes. ejemplo: bytecode: goto_neq(‘put_iface’, 8) GOTO_NEQ ADDR REG call(block) Almacena la dirección de la siguiente instrucción en el puntero de retorno y después salta a la dirección de comienzo del bloque block. ejemplo: bytecode: call(‘reply_header’) CALL ADDR ret() Salta a la dirección almacenada en el puntero de retorno y después pone su contenido a cero (dirección nula). Si al ejecutarse la instrucción ret() el puntero de retorno ya contiene la dirección nula, la instrucción termina sin realizar ninguna acción. Esto permite que un mismo bloque se pueda utilizar como subrutina y también como destino de salto convencional. ejemplo: bytecode: ret() RET set_event(block, event) Instala el bloque block como manejador para el evento event. La próxima vez que se ejecute la instrucción reset() saltará a la dirección de comienzo del bloque block si se ha producido el evento event durante ese lapso. Si se requiere desactivar un evento pendiente se debe invocar set_event(0, event). Indica que dicho evento tiene asignado el manejador nulo y, por tanto, no se ejecutará ninguna acción cuando el evento se produzca. ejemplo: bytecode: set_event(‘main’, INCOMING_EVENT) SET_EVENT ADDR EVENT skip() Lee y descarta un byte de la entrada. ejemplo: bytecode: skip() SKIP skip_mod_4() Lee y descarta de 1 a 4 bytes para conservar el alineamiento de 4 bytes para el siguiente dato. ejemplo: bytecode: skip_mod_4() SKIP_MOD_4 i i i i i i i i A. R EPERTORIO DE INSTRUCCIONES FSM 241 get_w() Lee un byte de la entrada y lo almacena en el registro de trabajo. ejemplo: bytecode: get_w() GET_W get_reg(reg, offset) Lee un byte de la entrada, le suma offset y lo almacena en el registro reg. ejemplo: bytecode: get_reg(8, -10) GET_REG REG OFFSET get_str(reg, max) Copia el valor del registro de trabajo en el registro reg. A continuación lee tantos bytes como indique dicho valor y los almacena a partir del registro reg+1. Para evitar desbordamiento del espacio reservado, la instrucción get_str() comprueba que el tamaño indicado en el registro de trabajo es menor o igual al parámetro max. En caso contrario, salta a la dirección de comienzo del bloque definido como manejador del evento ERROR. ejemplo: bytecode: get_str(8) GET_STR REG get_flash(reg, max) Igual que la anterior salvo que escribe el resultado en la zona Flash en lugar de en el banco de registros. assure(byte seq) En tiempo de compilación, la instrucción assure() obtiene el tamaño (t) y la suma de comprobación (c) de la secuencia de bytes indicada como parámetro. Esos valores son los que se generan como argumentos en el bytecode. Cuando se ejecuta la instrucción, la máquina consume de la entrada t bytes y al terminar comprueba que el valor del checksum de los bytes leídos corresponde con c. Si el checksum no corresponde, salta al manejador asociado al evento ERROR. ejemplo: bytecode: assure(‘IceP’,1,0,1,0) ASSURE SIZE DIGEST test_digest() Consume tantos bytes como indique el registro de trabajo, calcula un checksum sobre ellos y deja el resultado en el registro de trabajo. ejemplo: bytecode: test_digest() TEST_DIGEST put_val(value) Escribe a la salida el dato inmediato value. ejemplo: bytecode: put_val(2) PUT_VAL VALUE put_reg(reg) Escribe a la salida el contenido del registro reg. i i i i i i i i 242 A. R EPERTORIO DE INSTRUCCIONES FSM ejemplo: bytecode: put_reg(8) PUT_REG REG put_str(reg) El registro reg indica cuántos registros a partir de él deben escribirse en la salida. La cantidad propiamente dicha no se escribe. ejemplo: bytecode: put_str(12) PUT_STR REG put_data(addr) Escribe en la salida datos desde la zona DATA. La dirección addr indica cuántos bytes a partir de la dirección addr deben escribirse. La cantidad propiamente dicha no se escribe. ejemplo: bytecode: put_data(IceHeader) PUT_DATA ADDR put_flash(addr) Igual que la anterior salvo que lee los datos de la zona Flash. template(addr, offset) Igual que la instrucción put_data(), pero suma al byte que ocupa la posición offset el valor almacenado en el registro de trabajo. ejemplo: bytecode: template(IceHeader, 3) TEMPLATE ADDR OFFSET set_w(value) Almacena el valor value en el registro de trabajo. ejemplo: bytecode: set_w(4) SET_W VALUE move(dst, src) Copia el contenido del registo src al registro dst. ejemplo: bytecode: move(4, 0) MOVE REG REG set_val(reg, value) Almacena el dato inmediato value en el registro reg. ejemplo: bytecode: set_reg(8, 0) SET_REG REG VALUE add(reg, value) Suma el dato inmediato value al valor que contiene el registro reg. El resultado queda en reg. ejemplo: bytecode: add(8, 2) ADD REG VALUE i i i i i i i i A. R EPERTORIO DE INSTRUCCIONES FSM 243 set_timer(interval) Inicializa el timer para que genere el evento TIMEOUT con un intervalo de repetición determinado por interval. El timer puede ser desactivado con la instrucción set_timer(0). ejemplo: bytecode: set_timer(5) SET_TIMER VALUE cmp(reg) Si el contenido del registro de trabajo es mayor que el de reg el resultado es 1, si es menor el resultado es 2 y si son iguales el resultado es 0. El valor del resultado queda almacenado en el registro de trabajo. ejemplo: bytecode: cmp(5) CMP VALUE connect_data(addr) Inicia una conexión activa. A partir de ese momento y hasta que se ejecute la instrucción close(), la salida generada se enviará a través de esa conexión. La información necesaria para realizar la conexión se encuentra en la zona DATA a partir de la dirección addr. Utiliza la misma configuración que la instrucción put_data(). La información almacenada tiene distinto formato dependiendo del tipo de conector que se utilice. En el caso de TCP o UDP se trata de una dirección IP y un puerto. ejemplo: bytecode: connect(socket) CONNECT ADDR connect_flash(addr) Igual que la anterior salvo que lee los datos de conexión a partir de la zona Flash. close() Cierra la conexión actual, sea activa o pasiva. ejemplo: bytecode: close() CLOSE raise_event(event) Marca el evento event para su ejecución. ejemplo: bytecode: raise_event(PRESENCE_EVENT) RAISE_EVENT VALUE user_proc(n) Ejecuta el procedimiento de usuario que corresponde al código n. ejemplo: bytecode: user_proc(PROC_SET) USER_PROC VALUE debug(msg) Permite almacenar un mensaje de texto a efectos de depuración. El texto se imprimirá en la salida de error en el momento de su ejecución. Depende de la implementación concreta de la máquina virtual proporcionar o no soporte a esta instrucción. ejemplo: bytecode: debug(‘Evento Enviado’) DEBUG ADDR i i i i i i i i 244 A. R EPERTORIO DE INSTRUCCIONES FSM mnemotécnico tamaño (bytes) nop reset goto goto_nz goto_eq goto_neq call ret set_event skip skip_mod_4 get_w get_reg get_str get_flash assure test_digest put_val 1 1 2/3 2/3 3/4 3/4 2/3 1 3/4 1 1 1 3 3 3 3 1 2 mnemotécnico put_reg put_str put_data put_flash template set_w move set_val add set_timer cmp connect_data connect_flash close raise_event user_proc debug tamaño (bytes) 2 2 2 2 3 2 3 3 3 2 2 2 2 1 2 2 2 C UADRO A.1: FSM: Resumen del juego de instrucciones. En el tamaño, la barra indica salto corto/largo i i i i i i i i Servicios Web empotrados B.1. B.2. B.3. B.4. B.5. B.6. Introducción Servicios Web en la SAN Un enfoque ascendente Arquitectura de red Prototipos EWS Conclusiones B B Los denominados Servicios Web (en adelante WS) han tenido un gran auge en los últimos años gracias en buena parte al apoyo de la industria. Aunque siguen sufriendo grandes carencias y desventajas respecto a los MDOO tradicionales [dJ02, GKS02, Hen09], su relevancia en la comunidad investigadora y en el desarrollo profesional de sistemas distribuidos no puede ser ignorada. Los protocolos binarios como GIOP o I CE P, habituales en los MDOO, permiten aprovechar al máximo las posibilidades de los picoObjetos puesto que los mensajes requeridos son mucho más pequeños y regulares que sus equivalentes funcionales en protocolos como XML-RPC o SOAP (Simple Object Access Protocol), basados en XML. A pesar de que consideramos que los protocolos basados en XML son mucho más ineficientes que sus equivalentes binarios en términos de memoria, energía y ancho de banda, en este capítulo se introduce un mecanismo para conseguir implementaciones de WS aptas para dispositivos empotrados, con niveles de autonomía equiparables a los que exigimos a los picoObjetos, aunque obviamente con requerimientos de memoria mayores que aquellos. Nuestra intención con esta propuesta es proporcionar una alternativa viable para la construcción de WS autónomos empotrados, cuando las necesidades concretas de la aplicación lo impongan ya sea como medio para la integración con un sistema existente o como requisito del cliente. En otro caso, aconsejamos utilizar un middleware basado en un protocolo binario, especialmente en el caso de nodos de una red SAN, ya que ello permite la utilización de picoObjetos, más eficientes, con menos consumo y adecuados para dispositivos más sencillos. A los servicios web implementados con las directrices que se explican a continuación los denominamos EWS (Embedded Web Services). 245 i i i i i i i i 246 B. S ERVICIOS W EB EMPOTRADOS Como en el caso de los picoObjetos, los EWS consiguen un alto grado de interoperabilidad con sistemas basados en XML-RPC o SOAP con el único requisito de pasarelas sencillas, sin necesidad de delegados como entidades software residentes en ellas. B.1. Introducción Aunque es posible conseguir interoperabilidad a nivel de red mediante implementaciones reducidas de TCP/IP, en la capa de aplicación todavía puede ser un grave problema [PKGZ08]. Los WS aparecen como una solución interoperable, independiente del lenguaje y la plataforma para acceder a los servicios de una red SAN a través de Internet. Ello puede implicar una serie de interesantes ventajas que veremos a continuación. El uso de un protocolo como SOAP [GHM+ 03] dentro de una red SAN introduce una sobrecarga importante comparado con los protocolos binarios. Sin embargo, en algunos escenarios en los que el consumo de energía o el ancho de banda no son aspectos críticos puede ser admisible. En este caso, supondremos una instalación de control y diagnóstico para luces de emergencia en grandes edificios. En este escenario: Los nodos no tienen problemas de energía porque están conectados a la red eléctrica. Los nodos no se mueven. Utilizan comunicaciones inalámbricas para no depender de infraestructuras de comunicaciones ajenas al sistema. Esta red tiene poco tráfico, se utiliza únicamente para proporcionar acceso al diagnóstico de los nodos. Como ésta es una tarea planificada no es previsible que se produzca congestión ni grandes requerimientos de ancho de banda. El procedimiento de configuración debería ser lo más simple posible para reducir el coste de la instalación. En principio será posible una configuración remota como un servicio para todo el sistema. En este caso, o cualquier otro con características similares, los WS pueden ser una buena alternativa como solución al problema para proporcionar interoperabilidad en la capa de aplicación con sistemas externos preexistentes. B.2. Servicios Web en la SAN La mayoría de las propuestas previas toman datos directamente de la WSN usando protocolos propietarios y los exportan a través de WS residentes en la pasarela [KBL07, arc07]. El WS reside realmente en la pasarela y no en los nodos sensores. Cada nueva aplicación suele requerir nuevos desarrollos, y cada WS se convierte en un adaptador o envoltorio para un protocolo binario usado en la SAN. Nuestro enfoque pretende utilizar pasarelas genéricas (independientes de los dispositivos concretos que forman la red de sensores) reduciendo todo lo posible los procedimientos de configuración para conseguir que la información de los nodos esté accesible como WS. i i i i i i i i B. S ERVICIOS W EB EMPOTRADOS 247 La intención (como en ocasiones anteriores) es eliminar la necesidad de intermediarios a nivel de aplicación tal como el Sensor Collection Service descrito en [KBL07]. En [AYS07] se presenta un entorno para dar soporte al uso de SOAP en las WSN con especial énfasis en la reducción de la sobrecarga (p.ej. reduciendo el número de mensajes) utilizando técnicas de agregación de datos. Su implementación se ha probado en el simulador NS2, pero no se aporta información sobre una implementación en dispositivos reales. Otras propuestas [HX05] intentan empotrar la arquitectura de WS en dispositivos de bajo coste reduciendo el tamaño de la pila de protocolos (TCP/IP, XML, SOAP, etc.). Esos dispositivos de bajo coste exceden, sin embargo, la capacidad media de la mayoría de las plataformas para redes de sensores inalámbricas. EWS propone una forma diferente de empotrar servicios web mínimos en dispositivos WSN siguiendo un enfoque muy similar a los picoObjetos. En lugar de reducir el tamaño de implementaciones existentes de la pila de protocolos empleada en WS, definiremos el conjunto mínimo de prestaciones que necesita proporcionar un WS para que pueda seguir considerándose como tal, y partiremos de ese punto para añadir funcionalidad adicional cuando se requiera y sea posible. B.3. Un enfoque ascendente Aunque es importante que cada dispositivo se comporte como un WS, no es imprescindible la existencia de una implementación completa de TCP/IP, un servidor web o un reconocedor de XML. Si al recibir peticiones predefinidas, los dispositivos son capaces de generar respuestas coherentes el sistema puede funcionar tal como se espera. Para una especificación Web Services Definition Language (WSDL) [Win01] dada, los mensajes de petición y respuesta están perfectamente definidos por el protocolo de transporte elegido (SOAP o XML-RPC). Veamos una petición SOAP encapsulada en un mensaje HTTP (listado B.1) y su correspondiente respuesta para un protocolo de interacción muy simple similar a DUO: leer el estado de una luz de emergencia. Se muestran mensajes SOAP completos, a fin de que el comportamiento descrito en la figura B.1 resulte más fácil de comprender. POST / HTTP /1.0 Host: loc alhost:8 080 User−agent: SOAPpy 0.12.0 Content−type: text / xml ; charset = " UTF −8" Content−length: 336 SOAPAction: " get " <?xml version= " 1.0 " encoding = " UTF−8" ? > < SOAP−ENV:Envelope SOAP−E N V : e n c o d i n g S t y l e = " http: // schemas . xmlsoap . org / soap / encoding / " xmlns:SOAP−ENC = " http: // schemas . xmlsoap . org / soap / encoding / " xmlns:SOAP−ENV = " http: // schemas . xmlsoap . org / soap / envelope / " > < SOAP−ENV:Body > < get SOAP−ENC:root = " 1 " > </ get > i i i i i i i i 248 B. S ERVICIOS W EB EMPOTRADOS </ SOAP−ENV:Body > </ SOAP−ENV:Envelope > L ISTADO B.1: Ejemplo de petición SOAP Es fácil comprobar que SOAP resulta un protocolo bastante verboso en el que la mayoría de la información útil se encuentra en el elemento Body. Este mensaje se puede obtener a partir de la especificación WSDL del listado B.2. [...] < message name = " getRequest " > </ message > < message name = " getResponse " > < part name = " retval " type = " xs:boolean " / > </ message > [...] < operation name = " get " > < input message = " getRequest " / > < output message = " getResponse " / > </ operation > [...] L ISTADO B.2: Especificación WSDL para el ejemplo descrito Podemos implementar un reconocedor ad hoc tomando la especificación WSDL como punto de partida. Este reconocedor puede construir la respuesta adecuada a partir de plantillas (listado B.3). Puede verse fácilmente la equivalencia con las propuestas realizadas para los picoObjetos en el capítulo 4 si bien es necesario puntualizar algunas diferencias que se verán a continuación. HTTP /1.0 200 OK Content−type: text / xml ; charset = " UTF −8" Content−length: 501 <?xml version= " 1.0 " encoding = " UTF−8" ? > < SOAP−ENV:Envelope SOAP−E N V : e n c o d i n g S t y l e = " http: // schemas . xmlsoap . org / soap / encoding / " xmlns:SOAP−ENC = " http: // schemas . xmlsoap . org / soap / encoding / " xmlns:xsi = " http: // www . w3 . org /1999/ XMLSchema−instance " xmlns:SOAP−ENV = " http: // schemas . xmlsoap . org / soap / envelope / " xmlns:xsd = " http: // www . w3 . org /1999/ XMLSchema " > < SOAP−ENV:Body > < getResponse SOAP−ENC:root = " 1 " > < Result xsi:type = " xsd:boolean " > False </ Result > </ getResponse > </ SOAP−ENV:Body > </ SOAP−ENV:Envelope > L ISTADO B.3: Respuesta SOAP sintetizada Como en los capítulos precedentes, nuestro objetivo sigue siendo cubrir la funcionalidad de los transductores más habituales en las redes SAN y por esa razón planteamos un i i i i i i i i B. S ERVICIOS W EB EMPOTRADOS 249 conjunto de interfaces WSDL similar a DUO siguiendo el mismo diseño data-centric. Por supuesto, ésta es una estrategia para maximizar las posibilidades de implementación en dispositivos con graves limitaciones de memoria, pero como en aquel caso, no se trata de una restricción y es posible utilizar interfaces más complejas, asumiendo el coste correspondiente. El objetivo es minimizar la cantidad de memoria requerida para reconocer el conjunto de los posibles mensajes de entrada. Para conseguirlo, se emplean varias técnicas: Se genera una máquina de estados para reconocer una petición y construir una respuesta. El reconocedor ignora varios elementos sintácticos irrelevantes, como los espacios en blanco, saltos de línea, comentarios XML, etc. Nunca se almacenan ni comparan las etiquetas XML. En lugar de eso, se calculan checksums según el algoritmo CCITT-CRC 16 bits. El reconocedor únicamente compara resultados del CRC obtenidos a partir del mensaje con los almacenados en el dispositivo. Éstos fueron precalculados en tiempo de generación del autómata. Nunca se almacenan mensajes completos. Cada mensaje es analizado de forma incremental tal como se recibe, de manera similar a como haría un reconocedor SAX (Simple API for XML). Como ejemplo, para el mensaje de petición del listado B.1, se genera una máquina de estados similar a la de la figura B.1. Se calcula un CRC para cada etiqueta XML (delimitadas por ‘<>’). Desde el estado init se reconoce la entrada ignorando la cabecera HTML. Esa cabecera no incluye información relevante desde el punto de vista de los nodos de la SAN. El reconocedor ignora todos los datos de entrada hasta la llegada de la etiqueta <?xml ... ?>. Cuando ha llegado completamente se comprueba el checksum almacenado y se produce la transición al estado Start que decidirá entre los posibles mensajes de entrada. La entrada incluye algunas etiquetas de codificación seguidas de la operación que se desea invocar (get o set en el ejemplo). Dependiendo del CRC obtenido en las posiciones esperadas del flujo de entrada la transición lleva al estado en el que se leen los argumentos de la operación. Esas posiciones quedan definidas por el punto del flujo en el que aparece alguno de los caracteres ‘<>’. Las operaciones sin argumentos de entrada implican una transición directa al estado Tail. En este estado se valida el resto del mensaje de petición y se invoca el procedimiento de usuario correspondiente (el sirviente). Las operaciones con parámetros de entrada pasan por estados intermedios. Para el ejemplo, el estado Req Set reconoce y almacena temporalmente los parámetros asociados a la operación set antes de disparar la transición al estado Tail. Por último, después de comprobar la validez del resto del mensaje, se genera el mensaje de respuesta. Nótese que no es necesario almacenar nada del método invocado puesto que la cola de cada petición es diferente y se puede utilizar para discriminar entre los generadores de respuestas. En cada estado de generación de respuestas (Resp Set y Resp Get en el ejemplo), el usuario debe proporcionar una rutina que se ejecuta como consecuencia del mensaje reconocido y genera la respuesta apropiada. Aunque por legibilidad no se indica explícitamente en la figura B.1, cuando alguna etiqueta de entrada no corresponde con el checksum previsto, la máquina de estados i i i i i i i i 250 B. S ERVICIOS W EB EMPOTRADOS F IGURA B.1: Máquina de estados simplificada para los mensajes SOAP get y set retorna al estado inicial y cierra la conexión. Eso proporciona una protección sencilla pero razonable contra clientes defectuosos. B.3.1. Compilación Por los mismos motivos que se explicaban en el capítulo 6, se hace necesaria una forma sencilla de especificar las interfaces que implementa cada servicio, para que un compilador pueda generar el código del autómata. Para ello creamos un frontend de WSDL para el compilador ipkc, tal como estaba previsto en su diseño (véase § 6.3). La máquina de estados es un programa completo generado ad hoc. No se utiliza FSM puesto que los requisitos de memoria en este caso superan las posibilidades de direccionamiento de la ISA. En cualquier caso, la posibilidad de utilizar el mismo modelo de ejecución basado en máquina virtual que se propone para los picoObjetos resulta interesante también aquí. Para lograrlo se propone la utilización de una versión de FSM de 16 bits y algunas instrucciones adicionales para manejar secuencias de bytes delimitadas por banderas en lugar de por tamaños (que es lo habitual en los protocolos inter-ORB binarios). Por lo demás, no habría grandes diferencias en el funcionamiento de un reconocedor de mensajes SOAP respecto al que se propone para I CE P o GIOP. En este caso, las entradas para el compilador son: La especificación de la interfaz del servicio en formato WSDL. Los servicios proporcionados por el nodo deben estar descritos en este fichero. La implementación del sirviente, es decir, las porciones de código que realmente realizan operaciones sobre el hardware del nodo. Idealmente pueden ser drivers (véase § 6.4). La definición del servicio. El programador debe indicar qué servicios están disponibles en el nodo y las interfaces (portType) que expondrá cada transductor. i i i i i i i i B. S ERVICIOS W EB EMPOTRADOS 251 Este fichero utiliza el lenguaje IcePick (véase § 6.1). El listado B.4 muestra un ejemplo sencillo en el que se definen dos WS: uno local y otro remoto. Indica también la ejecución de una invocación periódica en la que se envía el estado y el endpoint del servicio. La especificación de la interfaz del sirviente proporcionado por el programador. Se utiliza para ello el mismo lenguaje SIS que se introdujo en la sección 6.2. uses " DUORW . wsdl "; object D U O I B o o l R W _ S e r v i c e svc1 ; local adapter myLocalEP { endpoint = " 1 2 0 . 3 0 . 4 0 . 1 0 : 8 0 6 0 " ; objects = { svc1 }; }; object D U O I B o o l R W _ S e r v i c e svc2 ; remote myRemoteEP { endpoint = " 1 2 0 . 3 0 . 4 0 . 1 0 : 8 0 7 0 " ; objects = { svc2 }; }; timer (5) { svc2 . set ( svc1 . status () , svc1 .endpoint) ; } L ISTADO B.4: Ejemplo de IcePick para un WS El compilador puede generar implementaciones de la máquina de estados para varias plataformas por medio de backends. Se ofrece soporte para motas MICA2 e IRIS con TinyOS, y para microcontroladores ATmega128 y 8051 sin sistema operativo. B.4. Arquitectura de red En nuestro caso de ejemplo, un centro de control externo gestiona y monitoriza edificios distribuidos en una gran extensión geográfica (varias ciudades). Son frecuentes edificios con cientos o incluso miles de luces de emergencia (aeropuertos, museos, estaciones, etc.). Cada instalación está conectada a una red externa común (p.ej. Internet) por medio de una o varias pasarelas (figura B.2). Cada pasarela realiza las siguientes tareas: Extrae mensajes SOAP desde el protocolo de transporte de la red externa (TCP en el ejemplo) y los encapsula en mensajes del protocolo de la red SAN, que no tiene porqué estar basado en TCP/IP. Y realiza el proceso inverso para los mensajes SOAP salientes. Esta tarea se ilustra en la figura B.3. Debe implementar un mecanismo de correspondencia unívoca bidireccional entre direcciones de transporte (puerto TCP) y el identificador de cada nodo. Éste es un aspecto crucial porque evita la necesidad de un procedimiento de configuración i i i i i i i i 252 B. S ERVICIOS W EB EMPOTRADOS F IGURA B.2: Topología de red para la gestión de luces de emergencia manual. Cuando se instala un nodo nuevo, la pasarela asigna un puerto TCP para cada identificador de nodo. Una consecuencia destacable es que este tipo de pasarelas no tiene ningún conocimiento previo de la red, no están ligadas a una aplicación concreta y, lo más importante, no realiza traducción de protocolos sino encapsulación. Esto implica además que puede haber varias pasarelas dando acceso a la misma red SAN puesto que no tienen estado. Lo único a tener en cuenta en ese caso es que la dirección del nodo será con toda seguridad diferente dependiendo de la pasarela que se utilice para contactar con el nodo. Eso puede solventarse con un algoritmo que garantice que dado un identificador de nodo se asocia siempre a la misma dirección externa. Por ejemplo, si utilizamos las direcciones de nodo de una red con protocolo XB OW, es posible hacer un mapping directo entre identificadores de nodo y puertos TCP puesto que ambos son números de 16 bits, y raramente una única SAN necesitará más de 216 nodos. La asociación establecida entre el puerto TCP y el identificador del nodo debe estar representada en el fichero WSDL. El fichero representa la interfaz del servicio para los usuarios y también sus propiedades, por ejemplo la localización (el endpoint). Los dos datos quedan plasmados en la etiqueta soap:address del fichero WSDL, tal como se muestra en el listado B.5. La pasarela necesita conocer los identificadores de nodo i i i i i i i i B. S ERVICIOS W EB EMPOTRADOS 253 F IGURA B.3: Proceso de encapsulación de la pasarela para generar el fichero WSDL correspondiente. Eso puede realizarse previamente si se conocen todos los identificadores posibles o bien utilizar un SDP. Concretamente es posible usar ASDF, aunque dentro de la red SAN. Cuando se conecta un nodo a la red, éste envía un anunciamiento. Las pasarelas interesadas en servir ese nodo hacia el exterior preguntan al nodo cuál es su identificador y las interfaces que implementa. Para ello se puede utilizar un MDOO binario puesto que es un proceso independiente y desacoplado del transporte de mensajes. La pasarela construye el fichero WSDL a partir de una plantilla que contiene la interfaz del servicio. En la sección sobre implementación de servicio incluimos información común sobre el entorno tal como la localización del nodo en formato legible, el identificador del nodo, etc. [...] <!−− Service to export −−> < service name = " E xi t D o o r _ S e r v i c e " > < port name = " IBoolRW_Port " binding = " IB oo lR W _B in di n g " > < soap:address location = " http: // example . com:7890 " / > </ port > </ service > [...] L ISTADO B.5: Fragmento WSDL para la localización de un nodo Los servicios pueden ser localizados también por medio del protocolo Universal Description Discovery and Integration (UDDI). El proceso de publicación de un WS asociado a un nodo en un registro UDDI es similar al de cualquier otro WS, es decir, la interfaz WS como estructura t-model y la implementación como servicio UDDI business. Además, es posible instalar otros servicios en la pasarela para proporcionar otras prestaciones como registro, autorización, etc. La pasarela puede generar los ficheros WSDL a partir de un conjunto de plantillas de cada una de las interfaces implementadas por los nodos de la red. Pero hay tres alternativas posibles: Las plantillas pueden estar almacenadas en las pasarelas. Cuando se instala un nodo con una interfaz nueva es necesario añadir una nueva plantilla a cada pasarela. Esta situación introduce acoplamiento entre las pasarelas y las aplicaciones desplegadas en la SAN pero no afecta a los nodos. i i i i i i i i 254 B. S ERVICIOS W EB EMPOTRADOS Cuando un nuevo nodo se anuncia, la pasarela puede solicitar la plantilla de las interfaces implementadas por el nodo, si es que las desconoce. Esto requiere almacenar la plantilla WSDL en los nodos e implementar una operación para obtenerla, lo que implica más memoria ROM o Flash en los nodos, aunque permite pasarelas más sencillas y completamente independientes. Una tercera alternativa es colocar las plantillas en un servidor remoto de modo que las pasarelas las puedan solicitar bajo demanda. No implica mayores necesidades de memoria en los nodos ni acoplamiento para las pasarelas, pero requiere de un host remoto conocido por todas las pasarelas. B.5. Prototipos EWS Utilizando las propuestas descritas, hemos desarrollado un conjunto de prototipos sobre las plataformas típicas en WSN: el Atmel ATmega128 con el sistema operativo TinyOS. También hemos realizado algunos prototipos sobre dispositivos sin sistema operativo. Comparamos el tamaño de distintas implementaciones de WS. En un primer paso, implementamos un servicio básico get/set (véase § B.3), usando dos bibliotecas ligeras de propósito general: csoap [cso] y libxml-rpc [lib]. Después implementamos el mismo servicio utilizando nuestra estrategia en tres plataformas diferentes: PC, MICA2 con TinyOS y un microcontrolador AVR sin sistema operativo. El tamaño de los binarios resultantes se muestra en la tabla B.1. Nótese que: Todos los prototipos x86 están enlazados estáticamente y se ejecutan en un PC convencional con SO Debian GNU/Linux. El tamaño del SO y sus dependencias no se han considerado. Los prototipos x86 de EWS son programas C puros con el soporte estándar de sockets. Los prototipos con MICA2 y AVR incluyen todos los componentes requeridos. Los datos que aparecen en la tabla se refieren al fichero que instalamos en el dispositivo. El prototipo AVR no utiliza SO, sólo un sencillo ejecutivo cíclico, mucho más pequeño que TinyOS, aunque obviamente a costa de sus prestaciones. software platform middleware C-SOAP libXML-RPC x86 EWS x86 SOAP XML-RPC SOAP XML-RPC SOAP XML-RPC SOAP XML-RPC TinyOS AVR binario (bytes) otros 1 731 508 768 536 507 676 504 772 35 150 11 216 1 068 1 182 OS OS OS OS ZigBee (4 261) ZigBee (4 261) C UADRO B.1: Comparativa de tamaños (en bytes) de un WS para un servicio get/set básico i i i i i i i i B. S ERVICIOS W EB EMPOTRADOS 255 El código fuente de todos los prototipos, la implementación de referencia y otros ficheros necesarios están disponibles en la página web de EWS [EWS]. B.6. Conclusiones EWS es una propuesta para implementar WS directamente en los nodos de una SAN o WSN. Hasta donde sabemos, no existe una estrategia previa que permita algo semejante en dispositivos con capacidad de cómputo tan limitada ya que lo habitual es exponer los WS únicamente desde la pasarela. Empotrar un WS directamente en el nodo SAN permite construir pasarelas genéricas independientes de la aplicación. De ese modo, se proporciona un despliegue físico de dispositivos con procedimientos de configuración mínimos. Se han implementado algunos prototipos con transporte SOAP y XML-RPC para demostrar la viabilidad de la solución propuesta (véase § B.5). En estos momentos, nuestro objetivo es mejorar el soporte para la generación y prueba de máquinas de estados mediante el compilador que permite la construcción de nodos listos para usar. También nos parece muy interesante diseñar una nueva FSM que permita unificar el desarrollo y despliegue de picoObjetos y WS en una misma red e, incluso, sobre los mismos nodos. i i i i i i i i i i i i i i i i C C El protocolo Ice C.1. Codificación de datos C.2. Proxies C.3. Mensajes del protocolo Este anexo es un resumen del capítulo The Ice Protocol de la referencia oficial de ZeroC I CE titulada «Distributed Programming with Ice» [HS08]. Se trata de una traducción parcial del citado capítulo, incluyendo las aclaraciones e incisos que se han considerado oportunos, pero excluyendo aquellas partes que quedan fuera de los objetivos del presente trabajo. Con ello se pretende facilitar al lector una visión detallada de los aspectos más relevantes del protocolo. La especificación del protocolo I CE consta de tres partes principales: Un conjunto de reglas de codificación para varios tipos de datos. El formato y función de los mensajes que intercambian cliente y servidor. Un conjunto de reglas que determinan cómo cliente y servidor negocian una versión del protocolo y de la codificación. C.1. Codificación de datos Los objetivos principales de la codificación de datos de I CE son la simplicidad y la eficiencia. Por ello, se tomaron las siguientes decisiones de diseño. No se fuerza el alineamiento de tipos básicos con los bordes de palabra. Eso simplifica la serialización, evita pérdida de datos y cantidad de tráfico en la red. Siempre se utiliza ordenamiento little endian para los datos numéricos. Con ello se mejora notablemente la eficiencia de servicios de distribución de datos que requieren varios saltos. En el caso en el que servidor o cliente se ejecuten en una máquina big endian se requiere la transformación, pero ello no supone un gran coste dentro 257 i i i i i i i i 258 C. E L PROTOCOLO I CE del proceso de deserialización y en la actualidad la mayoría de las arquitecturas de cómputo son little endian. C.1.1. Tamaños Muchos de los tipos de datos y algunas partes del propio protocolo tienen un tamaño asociado. Los tamaños se codifican con la siguiente regla: 1. Si el número de elementos es menor que 255, la cifra se codifica en un solo byte. 2. En otro caso, la cifra se codifica con un byte con valor 255, seguido de un entero indicando la cifra propiamente dicha. Con ello se consigue que para secuencias cortas se ahorren 3 bytes por cada tamaño, mientras que para secuencias largas el byte adicional puede ser irrelevante. C.1.2. Encapsulaciones Una encapsulación se utiliza para almacenar un tipo de dato de tamaño variable, pudiendo ser ese tipo desconocido para elementos intermedios sin que eso impida que pueda seguir su camino hasta el receptor. Las encapsulaciones se codifican del siguiente modo: struct Encapsulation { int size ; byte major ; byte minor ; // [... size − 6 bytes ...] }; L ISTADO C.1: Formato de codificación de una encapsulación Slice El campo size indica el tamaño de la encapsulación completa (en bytes). Los campos major y minor especifican la versión de la codificación utilizada para los datos. Al número de versión le sigue el tamaño de los datos menos los 6 bytes que ocupa la cabecera de la encapsulación, dado que dicho tamaño ocupa 4 bytes. La encapsulación es un bloque de datos autónomo que puede ser reenviado sin necesidad de conocer el formato de los datos que contiene. Permite anidamiento y es posible enviar encapsulaciones vacías que tendrán, por tanto, un tamaño de 6 bytes. C.1.3. Slices Una slice (rebanada) es un bloque de bytes precedido por un tamaño codificado como un entero de 4 bytes. Por lo que un slice vacío ocupa 4 bytes. Tanto las excepciones como las clases están formadas por slices. El objetivo es que al enviar una clase o excepción con determinada jerarquía de herencia, el receptor pueda pasar por alto las clases especializadas que no conoce y acceder a los datos de los tipos que sí conoce. i i i i i i i i C. E L PROTOCOLO I CE C.1.4. 259 Tipos básicos Los tipos básicos se codifican según se muestra en el Cuadro C.1. Los tipos en punto flotante usan formatos estándar de IEEE[IEE85]. Todos los tipos usan ordenamiento little endian. tipo tamaño notas bool byte short int long float double 1 byte 1 byte 2 bytes 4 bytes 8 bytes 4 bytes 8 bytes 0:falso, 1:verdadero 23 bits de mantisa, 8 de exponente, 1 de signo 52 bits de mantisa, 11 de exponente, 1 de signo C UADRO C.1: Tamaño de los tipos básicos de Slice C.1.5. Cadenas Las cadenas de texto se codifican con un tamaño (véase § C.1.3) y, a continuación, el contenido de la cadena codificado en formato UTF-8 [Uni00]. Las cadenas no contienen un valor nulo al final. Una cadena vacía es un tamaño con valor cero. C.1.6. Tipos agregados Secuencias Las secuencias se codifican como un tamaño (véase § C.1.3) que indica la cantidad de elementos en la secuencia seguido por los elementos codificados conforme a su tipo. Diccionarios Los diccionarios se codifican con un tamaño (véase § C.1.3) que indica la cantidad de pares clave-valor seguido por dichos pares. Cada par se codifica como una estructura con dos miembros: clave y valor, en ese orden. Enumeraciones La codificación de los enumerados depende de la cantidad de valores declarados. Hasta 127 valores se codifican como un byte. Más de 127 y hasta 32767 se codifican como un short. Si son más, se codifican como int. El valor de cada enumerado es el ordinal que le corresponda comenzando en cero. Estructuras Los miembros de una estructura se codifican en el mismo orden en el que aparecen en su declaración y siguiendo las reglas definidas para sus respectivos tipos. i i i i i i i i 260 C. E L PROTOCOLO I CE C.1.7. Identidades Todo objeto I CE tiene una identidad de objeto definida del siguiente modo: module Ice { struct Identity { string name ; string category ; }; }; L ISTADO C.2: Estructura de una identidad de objeto I CE La identidad consiste en dos cadenas: name y category. Para que dos identidades sean consideradas iguales ambos campos deben coincidir. La category normalmente es vacía salvo cuando se utilizan Servant locators (véase § 28.7 de [HS08]) C.2. Proxies El primer campo que se codifica es una identidad (tipo Ice::Identity). El protocolo permite especificar proxies nulos, en cuyo caso se incluye únicamente una identidad con sendas cadenas vacías para category y name (véase § C.1.7). Si el proxy no es nulo se incluyen un conjunto de parámetros generales y después pueden aparecer uno o varios endpoints. La parte común del proxy se codifica como una estructura con los siguientes campos: struct ProxyData { Ice :: Identity id ; Ice :: StringSeq facet ; byte mode ; bool secure ; }; L ISTADO C.3: Estructura común de un proxy I CE El significado de los miembros de esta estructura es el siguiente: id – La identidad de objeto. facet – El nombre de la faceta (una secuencia de cero o un elemento). La secuencia vacía corresponde con la faceta por defecto. mode – El modo del proxy: 0. 1. 2. 3. 4. twoway. oneway. batch oneway. datagram. batch datagram. i i i i i i i i C. E L PROTOCOLO I CE 261 secure – Es true si se requiere un endpoint seguro. El proxy puede indicar además una lista de endpoints (si es un proxy directo) o un identificador de adaptador (si es un proxy indirecto), en este segundo caso se codifica un byte con valor 0 y el identificador como una cadena. C.2.1. Endpoints Los endpoints se codifican inmediatamente después de la estructura indicada en la sección anterior. Primero, un tamaño indica el número de endpoints que aparecen después. Cada endpoint se codifica como un short que indica el tipo: 1. TCP 2. SSL 3. UDP y, a continuación, una encapsulación con los parámetros específicos de cada endpoint. Esto es así para que receptores que no conocen la estructura de ciertos tipos de endpoints puedan manejar el proxy completo a pesar de ello. Endpoints TCP Se codifican por medio de la siguiente estructura: struct T CP En dp o in tD at a { string host ; int port ; int timeout ; bool compress ; }; L ISTADO C.4: Estructura de un endpoint TCP cuyo significado es: host – El nombre del host que aloja el servidor o su dirección IP. port – El puerto al que está vinculado el servidor. timeout – El timeout especificado para los sockets (en ms). compress – Si debe utilizarse compresión. Endpoints UDP Se codifican según la siguiente estructura: i i i i i i i i 262 C. E L PROTOCOLO I CE struct U DP En dp o in tD at a { string host ; int port ; byte protocolMajor ; byte protocolMinor ; byte encodingMajor ; byte encodingMinor ; bool compress ; }; L ISTADO C.5: Estructura de un endpoint UDP cuyo significado es: host – El nombre del host que aloja el servidor o su dirección IP. port – El puerto al que está vinculado el servidor. protocolMajor/protocolMinor – Versión del protocolo soportado por el endpoint. encodingMajor/encodingMinor – Versión de la codificación soportada por el endpoint. compress – Si debe utilizarse compresión. Endpoints SSL Se codifican según la siguiente estructura: struct S SL En dp o in tD at a { string host ; int port ; int timeout ; bool compress ; }; L ISTADO C.6: Estructura de un endpoint SSL cuyo significado es idéntico al del endpoint TCP (véase § C.2.1). C.3. Mensajes del protocolo El protocolo I CE define 5 tipos de mensajes: 1. Petición (del cliente al servidor). 2. Petición por lotes (del cliente al servidor). 3. Respuesta (del servidor al cliente). Y en transportes orientados a conexión: i i i i i i i i C. E L PROTOCOLO I CE 263 4. Validación de conexión (del servidor al cliente). 5. Cierre de conexión (ambos sentidos). Los mensajes no requieren ningún tipo de alineamiento y constan de una cabecera y un cuerpo. C.3.1. Cabecera Todos los mensajes del protocolo I CE comienzan con una cabecera de 14 bytes según la siguiente estructura: struct HeaderData { int magic ; byte protocolMajor ; byte protocolMinor ; byte encodingMajor ; byte encodingMinor ; byte messageType ; byte c o m p r e s s i o n S t a t u s ; int messageSize ; }; L ISTADO C.7: Protocolo I CE: Formato de la cabecera El significado de cada miembro es el siguiente: magic – Una secuencia de 4 bytes con los códigos ASCII de los caracteres ‘I’,‘c’,‘e’,‘P’. protocolMajor/protocolMinor – Versión del protocolo. encodingMajor/encodingMinor – Versión de la codificación. messageType – Tipo de mensaje: 0. 1. 2. 3. 4. Petición. Petición por lotes. Respuesta. Validación de conexión. Cierre de conexión. compressionStatus – Indica si el mensaje está comprimido. messageSize – El tamaño total del mensaje incluyendo la cabecera. C.3.2. Cuerpo del mensaje de petición El cuerpo contiene toda la información necesaria para realizar la invocación a un método de un objeto remoto, lo cual incluye la identidad del objeto, el nombre de la operación y los parámetros de entrada. Se codifican conforme a la siguiente estructura: i i i i i i i i 264 C. E L PROTOCOLO I CE struct RequestData { int requestId ; Ice :: Identity id ; Ice :: StringSeq facet ; string operation ; byte mode ; Ice :: Context context ; Encapsulation params ; }; L ISTADO C.8: Protocolo I CE: Formato del mensaje de petición siendo: requestId – Identificador de la petición. En las invocaciones oneway tiene valor 0 e indica que no se debe responder al cliente. id – Identidad del objeto invocado. facet – Nombre de la faceta (cero o un elemento). operation – El nombre de la operación invocada. modo – Modo de operación: normal (0) o idempotente (2). context – Contexto de la invocación. params – Parámetros de entrada, en el orden en el que aparecen en la declaración de la operación. C.3.3. Cuerpo del mensaje de petición por lotes Un mensaje de petición por lotes contiene una o varias invocaciones oneway agrupadas. Se codifica como un entero que indica el número de invocaciones seguido de los cuerpos de los mensajes de petición codificados del siguiente modo: struct B a t c h R e q u e st D a t a { Ice :: Identity id ; Ice :: StringSeq facet ; string operation ; byte mode ; Ice :: Context context ; Encapsulation params ; }; L ISTADO C.9: Protocolo I CE: Formato del mensaje de petición por lotes El significado de los miembros es equivalente al del mensaje de petición (véase § C.3.2). i i i i i i i i C. E L PROTOCOLO I CE C.3.4. 265 Cuerpo del mensaje de respuesta El mensaje de respuesta contiene los resultados de una invocación twoway incluyendo el valor de retorno, los parámetros de salida o el contenido de una posible excepción. Se codifica según la siguiente estructura. struct ReplyData { int requestId ; byte replyStatus ; Encapsulation body ; // messageSize − 19 bytes }; L ISTADO C.10: Protocolo I CE: Formato del mensaje de respuesta El valor requestId debe corresponder con el campo del mismo nombre según se indicó en el mensaje de petición. El campo replyStatus indica un tipo de respuesta según la siguiente lista: 0. Invocación satisfactoria. 1. Excepción de usuario. 2. El objeto no existe. 3. La faceta no existe. 4. La operación no existe. 5. Excepción I CE local desconocida. 6. Excepción I CE de usuario desconocida. 7. Excepción desconocida. C.3.5. Mensaje de validación de conexión Cuando un servidor sobre un protocolo orientado a conexión recibe un intento de conexión siempre responde con un mensaje de validación de conexión sin que el cliente tenga que enviar nada. El cliente debe esperar este mensaje antes de poder enviar mensajes de petición. Este mensaje resuelve dos problemas: Informa al cliente de la versión del protocolo y codificación soportados por el servidor. Evita que el cliente escriba el mensaje en sus buffers locales antes de que el servidor haya comprobado que puede atender sus peticiones. Eso evita que el servidor acepte nuevas peticiones cuando se está apagando. C.3.6. Mensaje de cierre de conexión Este mensaje lo puede enviar tanto cliente como servidor para indicar que va a realizar el cierre de la conexión. Solo puede ocurrir cuando no quedan invocaciones por responder y únicamente cuando se utilizan transportes twoway. i i i i i i i i i i i i i i i i General Inter-ORB Protocol D.1. D.2. D.3. D.4. Visión general de GIOP Sintaxis de transferencia de CDR Formato de los mensajes GIOP Transporte de mensajes GIOP D D Este anexo es un resumen del capítulo General Inter-ORB Protocol del documento central de la especificación CORBA [COR02]. Una parte importante de este capítulo es una traducción más o menos libre del original, aplicando como criterio la claridad y la relación con el objetivo que nos ocupa. Se han omitido las secciones que tratan características no soportadas por picoCORBA, tales como serialización de tipos complejos, localización de objetos o GIOP bidireccional. D.1. Visión general de GIOP Después de las primeras versiones del estándar de CORBA se observó la necesidad de definir un protocolo común para comunicar varios ORB S. A partir de CORBA 2.0 se definió la arquitectura de interoperabilidad entre ORB S de distintos fabricantes sobre el protocolo GIOP. Sin embargo, se mantuvo la idea de poder utilizar, además de GIOP, cualquier otro protocolo propio del fabricante (ESIOP). Estas dos ideas se han respetado hasta el momento y son la base que permite la interoperabilidad entre ORB S de diferentes fabricantes. GIOP puede mapearse sobre cualquier protocolo de transporte orientado a conexión que cumpla unos mínimos requisitos. CORBA define un mapping de GIOP específico para conexiones TCP/IP llamado IIOP (Internet IOP) cuyo diagrama de capas aparece en la figura D.1. Los objetivos más importantes que se tuvieron en cuenta en el diseño de GIOP fueron: 267 i i i i i i i i 268 D. G ENERAL I NTER -ORB P ROTOCOL Objetos de la aplicación ORB IIOP TCP IP Ethernet Medio físico F IGURA D.1: Diagrama de capas de CORBA Disponibilidad GIOP está basado en el mecanismo de transporte más flexible y usado que existe (TCP/IP), y define un protocolo mínimo adicional para transmitir peticiones CORBA entre ORB S. Simplicidad GIOP está pensado para ser lo más simple posible siempre que cumpla los demás objetivos. La simplicidad asegura variedad de implementaciones independientes y compatibles. Escalabilidad GIOP/IIOP debería soportar ORB S y puentes (bridges) de ORB S dado el tamaño actual y futuro de Internet. Bajo coste Añadir soporte para GIOP a un ORB nuevo o existente debería requerir poco esfuerzo en desarrollo. Además, el coste requerido para soportar IIOP en un ORB en exploración debería ser mínimo. Generalidad El formato de los mensajes GIOP está diseñado para ser usado con cualquier protocolo de transporte orientado a conexión. Neutralidad arquitectural La especificación de GIOP hace suposiciones mínimas sobre la arquitectura de agentes que soporta. GIOP trata a los ORB S como entidades opacas con arquitecturas desconocidas. La especificación de GIOP consta de los siguientes elementos: Definición de CDR (Common Data Representation). CDR es un mapping de los tipos de datos de IDL a una representación bicanónica de bajo nivel para transferencias entre ORB S o entre puentes Inter-ORB (agentes). Formatos de mensajes GIOP. Los agentes intercambian mensajes GIOP para conseguir peticiones a objetos, localización de implementaciones y gestión de canales de comunicación. i i i i i i i i D. G ENERAL I NTER -ORB P ROTOCOL 269 Consideraciones sobre el transporte GIOP. La especificación GIOP describe ciertas condiciones generales que conciernen a cualquier protocolo de transporte que puede ser usado para transferir mensajes GIOP. También describe cómo gestionar las conexiones y las restricciones en la ordenación de mensajes. D.1.1. Representación común de datos (CDR) CDR tiene las siguientes características: Ordenación de bytes variable Las máquinas con una ordenación de bytes (byte order) común pueden intercambiar datos sin tener que realizar modificaciones en el ordenamiento. Cuando la comunicación se realiza entre máquinas con ordenación diferente, el emisor determina la ordenación de bytes en el mensaje, y el receptor es responsable de realizar el intercambio para que corresponda con su ordenamiento. Cada mensaje GIOP (y encapsulación CDR) contiene un flag que indica el ordenamiento. Tipos primitivos alineados Los tipos de datos primitivos de IDL se alinean a sus límites naturales dentro de los mensajes, permitiendo que los datos se puedan manejar de forma más eficiente por las arquitecturas que fuerzan el alineamiento de datos en memoria. Mapping completo de IDL CDR describe la representación de todos los tipos de datos de IDL, incluyendo pseudo-objetos como TypeCodes. D.1.2. Mensajes GIOP GIOP especifica el formato de los mensajes que se intercambian los ORB S. El formato de los mensajes GIOP tiene las siguientes características: Mensajes simples Con pocos mensajes, GIOP soporta la funcionalidad completa de CORBA entre ORB S, con capacidades extendidas que permiten servicio de localización de objetos, migración dinámica, gestión eficiente de comunicación de recursos. La semántica de GIOP no requiere negociación. En muchos casos, los clientes pueden invocar operaciones inmediatamente después de establecerse la conexión. Localización dinámica de objetos Muchas arquitecturas de ORB permiten que la implementación de un objeto sea activada desde un lugar diferente durante su ciclo de vida, y permite a los objetos migrar dinámicamente. Los mensajes GIOP dan soporte para la localización y migración de objetos. No se requiere que los ORB S implementen dichos mecanismos cuando sea innecesario o inapropiado. Soporte completo para CORBA Los mensajes GIOP posibilitan directamente todas las funciones y comportamientos requeridos por CORBA, incluyendo manipulación de excepciones, contextos de operación e invocaciones sobre referencias a objetos remotos. i i i i i i i i 270 D. G ENERAL I NTER -ORB P ROTOCOL GIOP también permite el paso de contextos propios de los servicios, tales como el contexto del servicio estándar de transacción. Este mecanismo está diseñado para soportar cualquier servicio que requiera información de contexto que tenga que ser enviada implícitamente en las peticiones. D.1.3. Transferencia de mensajes GIOP La especificación GIOP está diseñada para operar sobre cualquier protocolo de transporte que cumpla unas mínimas condiciones (véase § D.4). GIOP utiliza conexión de varias maneras: Uso asimétrico de conexión GIOP define dos roles diferentes con respecto a las conexiones: cliente y servidor. El cliente origina la conexión y envía petición a los objetos a través de esa conexión. El servidor recibe las peticiones y envía respuestas. Multiplexación de peticiones Si es necesario, varios clientes de un ORB pueden compartir una conexión para enviar peticiones a un ORB o servidor concreto. Cada petición únicamente identifica al objeto destino. Varias peticiones independientes para uno o varios objetos se pueden enviar sobre la misma conexión. Peticiones solapadas En general, la ordenación de mensajes GIOP es mínima. GIOP está diseñado para permitir el solapamiento de peticiones asíncronas. Los identificadores únicos permiten una adecuada correlación entre peticiones y respuestas. Las implementaciones son libres de imponer mecanismos de ordenación internos si las arquitecturas de sus ORB S lo requieren. Gestión de conexiones GIOP define mensajes para cancelación y finalización controlada de las conexiones. Estas características permiten a los ORB S reutilizar los recursos no ocupados. D.2. Sintaxis de transferencia de CDR La sintaxis de transferencia CDR es el formato en que GIOP representa los tipos de datos IDL en un flujo de octetos. Un flujo de octetos es una notación abstracta que corresponde con un buffer de memoria que debe ser transmitida a otro proceso con un mecanismo de comunicación entre procesos (IPC) o transporte de red. Un flujo de octetos es arbitrariamente largo (pero finito), formado por valores de 8 bits (octetos) y con un comienzo bien definido. Cada flujo puede ser indexado en una posición de 0 a n-1, siendo n el número de octetos del flujo. La posición que ocupa un octeto se llama índice; estos índices se usan para alinear los datos IDL dentro del flujo. GIOP define dos tipos de flujos de octetos, mensajes y encapsulaciones. Los mensajes son unidades básicas de información GIOP, que se describe en el sección D.3. Las encapsulaciones son tramas en las que las estructuras de datos IDL se pueden serializar i i i i i i i i D. G ENERAL I NTER -ORB P ROTOCOL 271 (marshall) independientemente de cualquier contexto del mensaje. Una vez que una estructura de datos está encapsulada, el flujo de octetos puede representarse como un tipo IDL sequence<octet> opaco, que se puede serializar en otro mensaje o encapsulación. La encapsulación permite constantes complejas (como los TypeCode); esto también permite que ciertos componentes del mensaje puedan usarse sin tener que realizar una deserialización completa. D.2.1. Tipos primitivos Los tipos primitivos están definidos en orden big-endian y en little-endian; tanto los mensajes como las encapsulaciones disponen de un flag en su cabecera que indica el tipo de ordenamiento que usan. Las encapsulaciones en el interior de los mensajes pueden tener un ordenamiento distinto al propio mensaje. Los tipos de datos primitivos se codifican en múltiplos de octeto. Alineamiento Para trasladar los tipos primitivos a las tramas de octetos se definen funciones específicas para cada uno de los tipos; CDR requiere que todos los tipos primitivos estén alineados a sus límites naturales. El alineamiento de los tipos primitivos es igual al tamaño del tipo en bytes. Un tipo primitivo de tamaño n debe comenzar en una posición de la trama múltiplo de n; en CDR, n puede ser 1, 2, 4 u 8. Cuando sea necesario, pueden aparecer huecos (alignment gap) antes de la representación de los datos. El valor de los octetos que conforman los huecos no está definido. En la tabla D.1 se muestra la alineación en octetos que deben tener los tipos primitivos. tipo char octet short unsigned short long unsigned long long long unsigned long long float double long double boolean enum alineamiento 1 1 1 2 4 4 8 8 4 8 8 1 4 C UADRO D.1: Alineación requerida para los tipos primitivos de IDL El alineamiento se define respecto al comienzo de la trama de octetos. El primer octeto de la trama tiene índice cero; todos los tipos de datos se almacenan comenzando por este i i i i i i i i 272 D. G ENERAL I NTER -ORB P ROTOCOL índice. La trama de octetos empieza con una cabecera de mensaje GIOP (véase § D.3.1) o con una encapsulación, incluso si está anidada en otra encapsulación. Tipos enteros En la tabla D.2 se muestra la ordenación de bytes, tanto en big-endian como en littleendian, para los enteros definidos en IDL, entre los que se encuentran los siguientes: short unsigned short long unsigned long long long unsigned long long short MSB LSB 0 1 LSB 0 1 2 3 LSB 0 1 LSB 0 1 2 3 MSB long MSB long long (a) Big-Endian MSB LSB MSB (b) Little-Endian 0 1 2 3 4 5 6 7 LSB MSB 0 1 2 3 4 5 6 7 C UADRO D.2: Tamaño y ordenamiento en codificaciones big endian y little endian de los tipos de datos enteros IDL, con y sin signo Tipos en punto flotante Un número en punto flotante está compuesto del bit de signo, el exponente y la parte fraccionaria de la mantisa, tal y como se define en el estándar IEEE para los números en punto flotante [IEE85]. La tabla D.3 representa los diferentes componentes para números en punto flotante: el bit de signo (s), el exponente (e) y la parte fraccionaria de la mantisa (f ). El bit de signo puede tomar valores 0 ó 1, representando positivo y negativo respectivamente. i i i i i i i i D. G ENERAL I NTER -ORB P ROTOCOL 273 float s e2 e1 f1 f2 f3 0 1 2 3 e1 f1 f2 f3 f4 f5 f6 f7 0 1 2 3 4 5 6 7 e1 e2 f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 e2 s f3 f2 f1 e1 0 1 2 3 e2 s f7 f6 f5 f4 f3 f2 f1 e1 7 6 5 4 3 2 1 0 s f14 f13 f12 f11 f10 f9 f8 f7 f6 f5 f4 f3 f2 f1 e2 e1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 double s e2 long double s C UADRO D.3: Tamaño y ordenamiento en codificaciones big endian y little endian de los tipos de datos de punto flotante de IDL, con y sin signo i i i i i i i i 274 D. G ENERAL I NTER -ORB P ROTOCOL Octetos El octeto es un valor de 8 bits no interpretado para el cual está garantizado que su contenido no se convertirá ni modificará durante la transmisión. A efectos de especificación se puede considerar a los octetos como enteros sin signo de 8 bits. Booleanos Están codificados como octetos simples, donde TRUE (cierto) es el valor 1, y FALSE (falso) es el valor 0. Caracteres Un carácter IDL se representa como un octeto simple, la tabla de códigos (code set) que se usa en la transmisión de caracteres entre los ORB S de un servidor y un cliente se determina en el propio proceso de transmisión. En caso de codificación multi-byte1 , una instancia del tipo carácter (char) sólo puede contener uno de los valores del multi-byte. La sintaxis de transferencia para caracteres anchos (wide char) depende de la versión de GIOP (véase §13.7, Code Set Conversion de [COR02]). D.2.2. Tipos compuestos Los tipos de datos compuestos se construyen a partir de los tipos primitivos usando medios definidos en el lenguaje IDL. Alineamiento Los tipos compuestos no tienen restricciones de alineamiento aparte de las de sus componentes primitivos. GIOP asume que los agentes construyen los tipos de datos estructurados copiando datos primitivos entre el buffer serializado y la estructura de datos en memoria para la implementación del mapping del lenguaje concreto. Estructuras (struct) Los elementos de una estructura se codifican en el orden de su declaración IDL. Cada componente se codifica según su propio tipo. Union Se codifican como una etiqueta discriminante (del tipo especificado en la declaración), seguido por la representación de miembros correspondientes a la etiqueta, codificados según su propio tipo. Array Se codifican como un vector de elementos en secuencia. Como la longitud del array es fija, no se incluyen valores de longitud. Cada elemento se codifica según su tipo. 1 Se utilizan varios bytes para codificar cada carácter. i i i i i i i i D. G ENERAL I NTER -ORB P ROTOCOL 275 En arrays multidimensionales, los elementos se ordenan de modo que el índice de la primera dimensión varía más despacio. Secuencias (Sequence) Se codifican como un valor unsigned long que indica el tamaño seguido por los elementos de la secuencia. Dichos elementos se codifican según su tipo. Enumeraciones (enum) Los valores de las enumeraciones se almacenan como unsigned long. El valor numérico asociado a cada identificador se determina por el orden de éstos en la definición del tipo comenzando con cero; el resto reciben valores en orden ascendente de izquierda a derecha. Cadenas Una cadena (string) se codifica como unsigned long que indica la longitud en octetos, seguido por el valor de los caracteres que forman la cadena ya sea en formato de caracteres simples o multi-byte; la representación es equivalente a una secuencia de octetos. La cadena incluye un carácter simple nulo que indica el fin; la longitud de la cadena incluye dicho carácter, de modo que el tamaño de una cadena vacía es 1. Tipos decimales en punto fijo El tipo IDL fixed no tiene restricciones de alineación. Cada octeto contiene dos dígitos decimales. Cada nibble2 codifica un dígito en hexadecimal. Si el tipo fijo tiene un número par de dígitos decimales, la representación empieza por el dígito más significativo; en otro caso, el primer nibble es un cero y el segundo es el dígito más significativo del número. La representación del signo es el último nibble: 0xD si es negativo y 0xC si es positivo o cero. El número de dígitos debe ser igual al número de dígitos significativos especificado en la definición IDL, con la excepción del nibble añadido en el caso de valores con un número impar de dígitos significativos. D.2.3. Encapsulación Los tipos de datos IDL se pueden serializar en encapsulaciones de tramas de octetos. La trama de octetos se representa con el tipo IDL sequence<octet>, que puede ser incluida en un mensaje GIOP o anidada en otra encapsulación. GIOP e IIOP utilizan encapsulaciones explícitamente en tres sitios: TypeCodes. Perfiles IIOP en el interior de IOR. Contextos específicos del servicio. 2 Semi-octeto. i i i i i i i i 276 D. G ENERAL I NTER -ORB P ROTOCOL Cuando se encapsulan tipos IDL, el primer octeto de la trama (índice 0) contiene un valor booleano que indica el ordenamiento de los datos encapsulados. Si el valor es FALSE (0), los datos encapsulados están codificados en big-endian; si es TRUE (1), se codifican en little-endian, es el mismo criterio que en las cabeceras GIOP (véase § D.3.1). Este valor no es parte de los datos encapsulados, pero es parte del flujo de octetos incluidos en la encapsulación. A continuación del flag de ordenamiento, los datos a encapsular se serializan en el buffer tal como indican las reglas de CDR. Los datos serializados se alinean con relación al comienzo del flujo de octetos (el primer octeto ocupado por el flag de ordenamiento). Cuando la encapsulación se codifica con el tipo sequence<octet> para su serialización, se coloca delante un unsigned long cuyo valor es el tamaño de la secuencia. El valor de la longitud no es parte de la encapsulación y no afecta al alineamiento de los datos. Esto garantiza un alineamiento de 4 bytes al comienzo de todos los datos en mensajes GIOP y encapsulaciones anidadas. D.3. Formato de los mensajes GIOP GIOP está restringido al modelo cliente/servidor en lo referente a inicialización y recepción de mensajes. Para las versiones 1.0 y 1.1 de GIOP, un cliente es un agente que abre una conexión y envía peticiones; un servidor es un agente que acepta conexiones y recibe dichas peticiones. Sin embargo, cuando se utiliza GIOP bidireccional en el protocolo GIOP versiones 1.2 y 1.3, cualquiera de los interlocutores puede originar mensajes tal como se especifica en la sección Bi-Directional GIOP en [COR02]. El cuadro D.4 resume todos los mensajes GIOP, indicando su nombre, el emisor (cliente, servidor o ambos) y el valor usado para identificar el mensaje en la cabecera del mensaje GIOP. mensaje Request Reply CancelRequest LocateRequest LocateReply CloseConnection MessageError Fragment origen valor cliente servidor cliente cliente servidor servidor ambos ambos 0 1 2 3 4 5 6 7 versión 1.0, 1.1, 1.2 1.0, 1.1, 1.2 1.0, 1.1, 1.2 1.0, 1.1, 1.2 1.0, 1.1, 1.2 1.0, 1.1, 1.2 1.0, 1.1, 1.2 1.1, 1.2 C UADRO D.4: GIOP: Tipos de mensajes En esta sección se describe sólo el formato y funcionamiento de GIOP versión 1.0, por ser la primera y más simple de las definidas hasta el momento por OMG. Las versiones posteriores: 1.1, 1.2 y 1.3 han incorporado mejoras y nuevas características al protocolo. Aún así, la esencia del mismo no ha cambiado y, por tanto, GIOP 1.0 es una referencia más que suficiente para comprender perfectamente la finalidad del protocolo. Para una i i i i i i i i D. G ENERAL I NTER -ORB P ROTOCOL 277 descripción detallada de versiones más recientes de GIOP, consultar [COR02]. El formato de los mensajes se describe en IDL conforme a la especificación original. D.3.1. Cabecera GIOP Todos los mensajes GIOP comienzan con una cabecera de tamaño fijo descrita en el listado D.1. module GIOP { struct Version { octet major ; octet minor ; }; enum MsgType_1_0 { Request , Reply , CancelRequest , LocateRequest , LocateReply , CloseConnection , MessageError }; struct M e s s a g e H e a d e r _ 1 _ 0 { char magic [4]; Version GIOP_version ; boolean byte_order ; octet message_type ; unsigned long message_size ; }; }; L ISTADO D.1: Formato de la cabecera GIOP La cabecera identifica el mensaje GIOP y su ordenación de bytes (byte-order). La cabecera es independiente de la ordenación excepto para los siguientes campos: magic – Identifica a los mensajes GIOP. El valor de este miembro es constante y corresponde con los caracteres «GIOP», en mayúsculas y codificados en ISO Latin-1 (8859.1). GIOP_version – Es el número de versión del protocolo GIOP usado en el mensaje. Éste se aplica a los elementos independientes del transporte, es decir, CDR y el formato de los mensajes. Es diferente de la versión de IIOP aunque tenga la misma estructura. Una implementación que soporte GIOP 1.n (con n > 0) debe también poder procesar mensajes GIOP de versiones anteriores. Un servidor que recibe una petición de una versión GIOP mayor de la que soporta debería responder con un mensaje de error con el número de versión mayor que soporta y, después, cerrar la conexión. Ningún cliente debería enviar un mensaje con una versión mayor que la publicada por el servidor en el perfil IIOP de su IOR. byte_order – Indica el ordenamiento del mensaje (incluyendo el campo message_size). Un valor 0 indica big-endian y un valor 1 indica little-endian. i i i i i i i i 278 D. G ENERAL I NTER -ORB P ROTOCOL message_type – Indica el tipo de mensaje de acuerdo con el cuadro D.4. Los valores posibles corresponden con el tipo MsgType. message_size – Contiene el número de octetos del mensaje (sin incluir la cabecera) codificados con el ordenamiento indicado por el campo byte_order. Indica el tamaño del cuerpo del mensaje, este valor incluye los octetos necesarios para los huecos de alineamiento (alignment gap), los parámetros de la petición o respuesta y los octetos de relleno al final del mensaje de modo que termine en un límite de 8 bytes. D.3.2. Mensaje de petición (Request) Los mensajes de petición codifican las invocaciones a objetos CORBA, incluyendo acceso a los atributos y operaciones de CORBA::Object como get_interface() y get_implementation(). Las peticiones fluyen del cliente hacia el servidor. Los mensajes de petición tienen tres elementos, codificados en este orden: Una cabecera de mensaje GIOP. Una cabecera de petición. El cuerpo de la petición. Cabecera de petición La cabecera de petición está definida como sigue: module GIOP { struct R e q u e s t H e a d e r _ 1 _ 0 { IOP :: S e r v i c e C o n t e x t L i s t unsigned long boolean sequence < otet > string CORBA :: OctetSeq } }; s er vi c e_ co nt e xt ; request_id ; response_expected ; object_key ; operation ; requesting_principal ; Los miembros tienen los siguientes significados: service_context – Contiene datos del ORB que se pasan del cliente al servidor tal como se explica en Object Service Context en [COR02]. request_id – Se usa para asociar los mensajes de respuesta con los de petición (inclu- yendo los mensajes LocateRequest). El cliente peticionario es el responsable de generar valores de forma que no haya ningún tipo de ambigüedad; específicamente, un cliente no debería reutilizar los mismos valores durante una conexión si: 1. La última petición que contenía el identificador aún está pendiente de respuesta. 2. La última petición que contenía el identificador fue cancelada y no se recibió respuesta. i i i i i i i i D. G ENERAL I NTER -ORB P ROTOCOL 279 response_expected – Indica que el cliente espera recibir una respuesta para la petición si su valor es TRUE. object_key – Identifica al objeto al que va dirigida la petición. Corresponde con el valor del campo object_key del perfil GIOP presente en la IOR para ese objeto. El cliente no debe modificar ni interpretar nunca este valor. operation – Es un identificador IDL en el contexto de la interfaz que implementa el objeto y que identifica el método que el cliente desea invocar. En el caso de accesores, los nombres de las operaciones son _get_<attribute> y _set_<attribute>. El valor de la operación debe corresponder con un nombre o atributo usado en la declaración de la interfaz IDL. Las operaciones definidas para CORBA::Object son: _interface. _is_a. _non_existent. _domain_managers. _component. requesting_principal – Es un campo que se utilizaba en implementaciones del BOA, predecesor del POA y que hoy está en desuso. Cuerpo de la petición En GIOP 1.0 y 1.1, el cuerpo de la petición se serializa en la encapsulación CDR inmediatamente después de la cabecera de petición. Los datos en el cuerpo de la petición incluyen los siguientes elementos en este orden: Todos los parámetros de entrada (in) y entrada/salida (inout), en el orden en que se especifiquen en la definición de la operación en IDL, de izquierda a derecha. Un pseudo-objeto opcional Context. Este elemento está presente sólo si la definición de la operación en IDL incluye una expresión de contexto y únicamente aparecen los miembros definidos en la expresión IDL. D.3.3. Mensaje de respuesta (Reply) Los mensajes de respuesta se devuelven al emisor del mensaje de petición sólo si el flag de response_expected tiene un valor TRUE. El mensaje de respuesta incluye los parámetros de salida, los de entrada/salida y el valor de retorno de la operación. En GIOP 1.0 y 1.1 los mensajes de respuesta fluyen sólo del servidor hacia el cliente. Los mensajes de respuesta tienen tres elementos, codificados en este orden: Una cabecera GIOP. Una cabecera de respuesta. El cuerpo de la respuesta. i i i i i i i i 280 D. G ENERAL I NTER -ORB P ROTOCOL Cabecera de respuesta La cabecera de respuesta está definida como sigue: module GIOP { enum R e p l y S t a t u s T y p e _ 1 _ 0 { NO_EXCEPTION , USER_EXCEPTION , SYSTEM_EXCEPTION , L O C A T I O N _ F OR W A R D }; struct R ep ly He a de r_ 1_ 0 { IOP :: S e r v i c e C o n t e x t L i s t unsigned long ReplyStatusType_1_0 }; s er vi c e_ co nt e xt ; request_id ; reply_status ; }; Siendo: request_id – Se usa para asociar las respuestas a las peticiones. Contiene el valor del campo del mismo nombre en la petición correspondiente. reply_status – Indica el estado de la petición asociada, y también determina parte del contenido del cuerpo del mensaje de respuesta. Si no ocurren excepciones y la operación se completa satisfactoriamente, el valor es NO_EXCEPTION y el cuerpo contiene los valores de retorno. En otro caso, el cuerpo puede: Contener una excepción, Indicar al cliente que redirija la petición a un objeto que se encuentra en otra localización, o Pedir al cliente que indique más información de direccionamiento. service_context – Es equivalente al campo del mismo nombre presente en la cabecera de petición. No se incluyen octetos de relleno (padding) cuando el cuerpo del mensaje de respuesta es vacío. Cuerpo del mensaje de respuesta En GIOP 1.0 y 1.1, el cuerpo del mensaje de respuesta está serializado en una encapsulación CDR que aparece inmediatamente a continuación de la cabecera de respuesta. El contenido del mensaje de respuesta está determinado por el valor del campo reply_status. El cuerpo puede ser de los siguientes tipos dependiendo del valor del campo reply_status: Si es NO_EXCEPTION, en el cuerpo se codifica primero el valor de retorno de la operación, si lo hubiere, después los parámetros entrada/salida y de salida en el orden en el que aparecen en la declaración de la operación en IDL, de izquierda a derecha. i i i i i i i i D. G ENERAL I NTER -ORB P ROTOCOL 281 Si es USER_EXCEPTION o SYSTEM_EXCEPTION, el cuerpo contiene la excepción levantada por la operación. Sólo se pueden levantar las excepciones de usuario que aparezcan en la definición de operación del IDL. Cuando el valor del campo reply_status es SYSTEM_EXCEPTION, el cuerpo de la respuesta tiene la siguiente estructura: module GIOP { struct S y s t e m E x c e p t i o n R e p l y B o d y { string exception_id ; unsigned long m i n o r _ c o d e _ va l u e ; unsigned long completion_status ; }; }; Si es LOCATION_FORWARD, el cuerpo contiene una referencia a objeto (IOR). El ORB cliente es responsable de reenviar la petición original al objeto asociado a dicha referencia. Este reenvío es transparente para el programa cliente que hace la petición. D.3.4. Mensaje de cancelación de petición (CancelRequest) En GIOP 1.0 y 1.1 son mensajes enviados por el cliente al servidor para notificar que el cliente no seguirá esperando la respuesta para un mensaje de petición pendiente. El mensaje de cancelación de petición tiene dos elementos: Una cabecera de mensaje GIOP. Una cabecera de mensaje de cancelación de petición. Cabecera de cancelación de petición Está definida del siguiente modo: module GIOP { struct C a n c e l R e q u e s t H e a d e r { unsigned long request_id ; }; }; request_id identifica el mensaje de petición, o petición de localización (LocateRequest), al que se aplica la cancelación. Este valor es el mismo que el especificado en el campo del mismo nombre en el mensaje de petición original. Cuando un cliente emite un mensaje de cancelación de petición sólo supone un aviso. El servidor puede hacer caso omiso y enviar el mensaje de respuesta de todos modos. El cliente no debería hacer suposiciones sobre si llegará o no la respuesta una vez enviado el mensaje de cancelación de petición. i i i i i i i i 282 D. G ENERAL I NTER -ORB P ROTOCOL D.3.5. Mensaje de petición de localización (LocateRequest) Estos mensajes pueden ser enviados por un cliente a un servidor para determinar las siguientes características sobre el objeto: Si el servidor es capaz de dirigir peticiones hacia la referencia a objeto, o no. Qué petición de dirección podría enviar para la referencia a objeto. Esta información también se obtiene a través de un mensaje de petición convencional, pero puede que algunos clientes no deseen retransmitir paquetes grandes cuando el mensaje de respuesta retorna el estado LOCATION_FORWARD. El cliente puede utilizar el mensaje de petición de localización para transmitir sus mensajes directamente a la localización correcta. El mensaje de petición de localización tiene dos elementos: Una cabecera de mensaje GIOP. Una cabecera de petición de localización. Cabecera de petición de localización Está definida como sigue: module GIOP { struct L o c a t e R e q u e s t H e a d e r _ 1 _ 0 { unsigned long request_id ; sequence <octet > object_key ; }; }; Los miembros tienen el significado habitual. D.3.6. Mensaje de respuesta de localización (LocateReply) Los mensajes de respuesta de localización los envían los servidores a los clientes como consecuencia de la recepción de un mensaje de petición de localización. Un mensaje de respuesta de localización tiene tres elementos, codificados en el siguiente orden: Una cabecera de mensaje GIOP. Una cabecera de respuesta de localización. El cuerpo de la respuesta de localización. Cabecera del mensaje de respuesta de localización Está definido tal como se indica a continuación: module GIOP { i i i i i i i i D. G ENERAL I NTER -ORB P ROTOCOL 283 enum L o c a t e S t a t u s T y p e _ 1 _ 0 { UNKNOWN_OBJECT , OBJECT_HERE , OBJEC T_FORWAR D }; struct L o c a t e R e p l y H e a d e r _ 1 _ 0 { unsigned long request_id ; LocateStatusType_1_0 locate_status ; }; }; Los miembros tienen la siguiente definición: request_id – Se usa para asociar la respuesta con la petición correspondiente. locate_status – Su valor determina el contenido del cuerpo del mensaje. Los valores que puede tomar son: UNKNOWN_OBJECT – El objeto especificado en el mensaje de petición de localiza- ción es desconocido para el servidor. No se incluye cuerpo en el mensaje. OBJECT_HERE – El servidor que emite el mensaje de respuesta de localización puede recibir directamente peticiones para el objeto especificado. No existe cuerpo en el mensaje. OBJECT_FORWARD – El cuerpo del mensaje contiene información. Cuerpo del mensaje de respuesta de localización El cuerpo del mensaje está vacío, excepto si el valor del campo locate_status es OBJECT_FORWARD. En ese caso, el cuerpo contiene una IOR que debe usarse para acceder al objeto especificado en el mensaje de petición de localización. El cuerpo del mensaje está serializado siguiendo inmediatamente a la cabecera. D.3.7. Mensaje de finalización de conexión (CloseConnection) Son mensajes procedentes de los servidores en GIOP 1.0 y 1.1. Este mensaje informa al cliente de que el servidor pretende cerrar la conexión y no debería esperar respuestas para las peticiones futuras. Además, el cliente no recibirá respuestas para las peticiones pendientes que ni siquiera serán procesadas. El mensaje de finalización de conexión está formado únicamente por una cabecera de mensaje GIOP que identifica el tipo de mensaje. D.3.8. Mensaje de error (MessageError) El mensaje de error se envía en respuesta a cualquier mensaje GIOP cuyo número de versión o tipo de mensaje sea desconocido para el receptor del mensaje. También se puede utilizar como respuesta al recibir un mensaje con una cabecera mal formada. El mensaje de error está compuesto únicamente por una cabecera GIOP que identifica el tipo de mensaje. i i i i i i i i 284 D. G ENERAL I NTER -ORB P ROTOCOL D.4. Transporte de mensajes GIOP GIOP está diseñado para ser implementable sobre una gran variedad de protocolos. La definición de GIOP hace las siguientes suposiciones sobre el comportamiento del transporte: El transporte está orientado a conexión. El transporte es fiable. Específicamente, el transporte garantiza que los bytes se entregan en el mismo orden que son enviados, al menos una vez, y que existe algún mecanismo que permite conocer la entrega exitosa. El transporte puede verse como un flujo de bytes. No se fuerzan limitaciones arbitrarias del tamaño de los mensajes, fragmentación o alineamiento. El transporte ofrece notificación de conexiones perdidas. El modelo de transporte para crear conexiones se puede mapear en el modelo general de TCP/IP. Un agente publica una dirección de red conocida en una IOR que el cliente usa cuando inicia la conexión. El servidor no inicia conexiones, pero está preparado para aceptar peticiones de conexión (accept en términos de TCP/IP). Otro agente que conoce la dirección (llamado cliente) puede intentar iniciar conexiones enviando peticiones de conexión a la dirección. El servidor puede aceptar la petición, creando una nueva y única conexión con el cliente, o puede rechazar la petición. Una vez abierta la conexión, cualquiera de los dos puede cerrar la conexión. i i i i i i i i E E Interfaces Slice E.1. E.2. E.3. DUO ASDF Property Service Aunque a lo largo del texto se han ido mostrando fragmentos de las especificaciones Slice relacionadas con el contexto de cada sección, consideramos adecuado incluir aquí las ficheros completos a efectos de completitud. E.1. DUO L ISTADO E.1: DUO.ice #include < Ice / B u i l t i n S e q u e n c e s . ice > #include < Ice / Identity . ice > #include < IceStorm / IceStorm . ice > module DUO { dictionary <string , Object∗> ObjectPrxDict ; module Pulse { interface W { void set ( Ice :: Identity oid ) ; }; }; module IBool { interface R { idempotent bool get () ; }; interface W { set (bool v , Ice :: Identity oid ) ; }; }; module IByte { interface R { idempotent byte get () ; }; interface W { void set (byte v , Ice :: Identity oid ) ; }; }; module IInt { interface R { idempotent int get () ; }; interface W { void set (int v , Ice :: Identity oid ) ; }; }; module ILong { interface R { idempotent long get () ; }; 285 i i i i i i i i 286 E. I NTERFACES S LICE interface W { void set ( long v , Ice :: Identity oid ) ; }; }; module IFloat { interface R { idempotent float get () ; }; interface W { void set (float v , Ice :: Identity oid ) ; }; }; module IString { interface R { idempotent string get () ; }; interface W { void set (string v , Ice :: Identity oid ) ; }; }; module IByteSeq { interface R { idempotent Ice :: ByteSeq get () ; }; interface W { void set ( Ice :: ByteSeq v , Ice :: Identity oid ) ; }; }; module IObject { interface R { idempotent Object∗ get () ; }; interface W { void set (Object∗ v , Ice :: Identity oid ) ; }; }; module Func { interface Relative { void inc (short nsteps ) ; }; }; module Container { exception A l r e a d y E x i s t s E x c e p t i o n { string key ; }; exception N o S u c h K e y E x c e p t i o n { string key ; }; exception O pe ra ti o nF ai le d { string reason ; }; interface RW ; interface R { [" freeze : read " , " ami "] idempotent ObjectPrxDict list () ; }; interface W { // Add and remove external items [" freeze : write " , " ami "] void link (string key , Object∗ value ) throws A l r e a d y E x i s t s E x c e p t i o n ; [" freeze : write " , " ami "] void unlink (string key ) throws N o S u c h K e y E x c e p t i o n ; // Create new Container ’ s in this object [" freeze : write " , " ami "] Container :: RW∗ create (string key ) throws A l r e a d y E x i s t s E x c e p t i o n ; // Destroy ∗ this ∗ object [" freeze : write " , " ami "] void destroy () ; }; interface RW extends R , W {}; }; interface Component { Ice :: StringSeq getAllFacets () ; }; module Composite { // Valid operations for byte , int, float , long const string MIN = " minimum "; // lowest value const string MAX = " maximum "; // highest value const string AVG = " average "; // sum (0.. n ) / n const string MED = " median "; // sort (0.. n ) [ n /2] const string HEI = " height "; // max−min i i i i i i i i E. I NTERFACES S LICE 287 // Valid operations for bool const string ANY = " any "; const string ALL = " all "; // true if any true // true if all true // Exceptions exception I n v a l i d T y p e E x c e p t i o n { string tid ; }; exception N o S u c h O b j e c t E x c e p t i o n { string oid ; }; // Public Factory to create Composites interface Factory { Object∗ create (string scalarType ) throws I n v a l i d T y p e E x c e p t i o n ; void destroy (Object∗ proxy ) throws N o S u c h O b j e c t E x c e p t i o n ; Ice :: StringSeq g e tA ll ow e dT yp es () ; }; interface R extends DUO :: Container :: R , DUO :: Component {}; interface W extends DUO :: Container :: RW , DUO :: Component {}; }; module Active { interface R { Object∗ getCb () ; IceStorm :: Topic ∗ getTopic () ; }; interface W { void setCbTopic (Object∗ publisher , IceStorm :: Topic ∗ topic ) ; }; }; }; E.2. ASDF L ISTADO E.2: ASDF.ice #include < Ice / B u i l t i n S e q u e n c e s . ice > #include < Ice / Identity . ice > #include " Pr op e rt yS er vi c e . ice " module ASD { interface Listener { idempotent void adv (Object∗ prx ) ; idempotent void bye ( Ice :: Identity oid ) ; }; interface Search { idempotent void lookup ( Listener ∗ cb , string tid , P ro pe rt y Se rv ic e :: Properties query ) ; idempotent void discover ( Listener ∗ cb ) ; }; interface PropHldr { idempotent P ro pe rt y Se rv ic e :: Pro pertySet Def ∗ getp () ; }; }; E.3. Property Service L ISTADO E.3: PropertyService.ice #include " PropertyType . ice " module P ro pe rt y Se rv ic e { i i i i i i i i 288 E. I NTERFACES S LICE struct Property { string propertyName ; P :: T propertyValue ; }; enum P r o p e r t y M o d e T y p e { NORMAL , READONLY , FIXEDNORMAL , FIXEDREADONLY , UNDEFINED }; struct PropertyDef { P :: T propertyValue ; P r o p e r t y M o d e T y pe propertyMode ; }; dictionary <string , P :: T > Properties ; dictionary <string , PropertyDef > PropertyDefs ; dictionary <string , PropertyModeType > PropertyModes ; interface interface interface interface interface PropertyNamesIterator ; PropertiesIterator ; PropertySetFactory ; Prope rtySetDe f ; PropertySet ; exception exception exception exception exception exception exception exception exception C o n s t r a i n t N o t S u p p o r t e d {}; I n v a l i d P r o p e r t y N a m e {}; C o n f l i c t i n g P r o p e r t y {}; P r o p e r t y N o t F o u nd {}; U n s u p p o r t e d T y p e C o d e {}; U n s u p p o r t e d P r o p e r t y {}; U ns up po r te dM od e {}; FixedProperty {}; R e a d O n l y P r o p e r ty {}; enum E xc ep ti o nR ea so n { rInvalidPropertyName , rConflictingProperty , rPropertyNotFound , rUnsupportedTypeCode , rUnsupportedProperty , rUnsupportedMode , rFixedProperty , rReadOnlyProperty }; struct P r o p e r t y E x c e p t i o n { E xc ep ti o nR ea so n reason ; string f a i l i n g P r o p e r t y N a m e ; }; sequence < PropertyException > P r o p e r t y E x c e p t i o n s ; exception M u l t i p l e E x c e p t i o n s { P r o p e r t y E x c e p t i o n s exceptions ; }; interface P r o p e r t y S e t F a c t o r y { PropertySet ∗ c r e a t e P r o p e r t y S e t () ; PropertySet ∗ c r e a t e C o n s t r a i n e d P r o p e r t y S e t ( Properties a l l o w e d P r o p e r t i e s ) throws C o n s t r a i n t N o t S u p p o r t e d ; PropertySet ∗ c r e a t e I n i t i a l P r o p e r t y S e t ( Properties i n i t i a l P r o p e r t i e s ) throws M u l t i p l e E x c e p t i o n s ; }; i i i i i i i i E. I NTERFACES S LICE 289 interface P r o p e r t y S e t D e f F a c t o r y { Prop ertySetD ef ∗ c r e a t e P r o p e r t y S e t D e f () ; Prop ertySetD ef ∗ c r e a t e C o n s t r a i n e d P r o p e r t y S e t D e f (\ PropertyDefs a l l o w e d P r o p e r t y D e f s ) throws C o n s t r a i n t N o t S u p p o r t e d ; Prop ertySetD ef ∗ c r e a t e I n i t i a l P r o p e r t y S e t D e f (\ PropertyDefs i n i t i a l P r o p e r t y D e f s ) throws M u l t i p l e E x c e p t i o n s ; }; interface PropertySet { void defin ePropert y (string theName , P :: T theValue ) throws InvalidPropertyName , ConflictingProperty , UnsupportedTypeCode , UnsupportedProperty , R e ad O n l y P r o p e r t y ; void d e f i n e P r o p e rt i e s ( Properties nproperties ) throws M u l t i p l e E x c e p t i o n s ; long g e t N u m b e r O f P r o p e r t i e s () ; void g e t A l l P r o p e r t y N a m e s ( long howMany , out Ice :: StringSeq theNames , out P r o p e r t y N a m e s I t e r a t o r ∗ rest ) ; P :: T g e t P r o p er t y V a l u e (string theName ) throws PropertyNotFound , I n v a l i d P r o p e r t y N a m e ; bool getProperties ( Ice :: StringSeq theNames , out Properties nproperties ) ; void g e t A l l P r o p e rt i e s ( long howMany , out Properties nproperties , out P r o p e r t i e s I t e r a t o r ∗ rest ) ; void delet ePropert y (string theName ) throws PropertyNotFound , InvalidPropertyName , FixedProperty ; void d e l e t e P r o p e rt i e s ( Ice :: StringSeq theNames ) throws M u l t i p l e E x c e p t i o n s ; bool d e l e t e A l l P r o p e r t i e s () ; bool i s P r o p e r t y D e f i n e d (string theName ) throws I n v a l i d P r o p e r t y N a m e ; }; interface Prop ertySetD ef extends PropertySet { void g e t A l l o w e d P r o p e r t i e s (out PropertyDefs allowedDefs ) ; void d e f i n e P r o p e r t y W i t h M o d e (string theName , P :: T theValue , P r o p e r t y M o d eT y p e theMode ) throws InvalidPropertyName , ConflictingProperty , UnsupportedTypeCode , UnsupportedProperty , UnsupportedMode , R e a d O n l y P r o p e r t y ; void d e f i n e P r o p e r t i e s W i t h M o d e s ( PropertyDefs theDefs ) throws M u l t i p l e E x c e p t i o n s ; P r o p e r t y M o d e T y pe ge tP ro p er ty Mo d e (string theName ) throws PropertyNotFound , I n v a l i d P r o p e r t y N a m e ; bool g e t P r o p e r t y Mo d e s ( Ice :: StringSeq theNames , out PropertyModes theModes ) ; void s et Pr op e rt yM od e (string theName , P r o pe r t y M o d e T y p e theMode ) throws InvalidPropertyName , PropertyNotFound , U ns u pp or te d Mo de ; void s e t P r o p e r t y Mo d e s ( PropertyModes theModes ) throws M u l t i p l e E x c e p t i o n s ; }; interface P r o p e r t y N a m e s I t e r a t o r { void reset () ; bool nextOne (out string theName ) ; bool nextN ( long howMany , out Ice :: StringSeq theNames ) ; void destroy () ; i i i i i i i i 290 E. I NTERFACES S LICE }; interface P r o p e r t i e s I t e r a t o r { void reset () ; bool nextOne (out Property aProperty ) ; bool nextN ( long howMany , out Properties nProperties ) ; void destroy () ; }; }; L ISTADO E.4: PropertyType.ice #include < Ice / B u i l t i n S e q u e n c e s . ice > module P { class T {}; class BoolT extends T { class ByteT extends T { class ByteSeqT extends T { class IntT extends T { class FloatT extends T { class StringT extends T { class StringSeqT extends T { class ObjectT extends T { }; bool value ; }; byte value ; }; Ice :: ByteSeq value ; }; int value ; }; float value ; }; string value ; }; Ice :: StringSeq value ; }; Object∗ value ; }; i i i i i i i i GNU Free Documentation License Version 1.3, 3 November 2008 c 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. <http://fsf.org/> Copyright F F Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. 0. PREAMBLE The purpose of this License is to make a manual, textbook, or other functional and useful document “free” in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others. This License is a kind of “copyleft”, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software. We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference. 1. APPLICABILITY AND DEFINITIONS This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The “Document”, below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as “you”. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law. A “Modified Version” of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language. A “Secondary Section” is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them. The “Invariant Sections” are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none. The “Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words. A “Transparent” copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage 291 i i i i i i i i 292 F. GNU F REE D OCUMENTATION L ICENSE subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not “Transparent” is called “Opaque”. Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only. The “Title Page” means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page” means the text near the most prominent appearance of the work’s title, preceding the beginning of the body of the text. The “publisher” means any person or entity that distributes copies of the Document to the public. A section “Entitled XYZ” means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as “Acknowledgements”, “Dedications”, “Endorsements”, or “History”.) To “Preserve the Title” of such a section when you modify the Document means that it remains a section “Entitled XYZ” according to this definition. The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License. 2. VERBATIM COPYING You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3. You may also lend copies, under the same conditions stated above, and you may publicly display copies. 3. COPYING IN QUANTITY If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document’s license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects. If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages. If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machinereadable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public. It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document. 4. MODIFICATIONS You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version: i i i i i i i i F. GNU F REE D OCUMENTATION L ICENSE 293 A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission. B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement. C. State on the Title page the name of the publisher of the Modified Version, as the publisher. D. Preserve all the copyright notices of the Document. E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below. G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document’s license notice. H. Include an unaltered copy of this License. I. Preserve the section Entitled “History”, Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled “History” in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence. J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the “History” section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission. K. For any section Entitled “Acknowledgements” or “Dedications”, Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein. L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles. M. Delete any section Entitled “Endorsements”. Such a section may not be included in the Modified Version. N. Do not retitle any existing section to be Entitled “Endorsements” or to conflict in title with any Invariant Section. O. Preserve any Warranty Disclaimers. If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version’s license notice. These titles must be distinct from any other section titles. You may add a section Entitled “Endorsements”, provided it contains nothing but endorsements of your Modified Version by various parties—for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard. You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one. The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version. 5. COMBINING DOCUMENTS You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers. The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work. In the combination, you must combine any sections Entitled “History” in the various original documents, forming one section Entitled “History”; likewise combine any sections Entitled “Acknowledgements”, and any sections Entitled “Dedications”. You must delete all sections Entitled “Endorsements”. i i i i i i i i 294 F. GNU F REE D OCUMENTATION L ICENSE 5. COLLECTIONS OF DOCUMENTS You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects. You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document. 6. AGGREGATION WITH INDEPENDENT WORKS A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an “aggregate” if the copyright resulting from the compilation is not used to limit the legal rights of the compilation’s users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document. If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document’s Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate. 7. TRANSLATION Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail. If a section in the Document is Entitled “Acknowledgements”, “Dedications”, or “History”, the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title. 8. TERMINATION You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute it is void, and will automatically terminate your rights under this License. However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it. 9. FUTURE REVISIONS OF THIS LICENSE The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See http://www.gnu.org/copyleft/. Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License “or any later version” applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free i i i i i i i i F. GNU F REE D OCUMENTATION L ICENSE 295 Software Foundation. If the Document specifies that a proxy can decide which future versions of this License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Document. 10. RELICENSING “Massive Multiauthor Collaboration Site” (or “MMC Site”) means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A “Massive Multiauthor Collaboration” (or “MMC”) contained in the site means any set of copyrightable works thus published on the MMC site. “CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization. “Incorporate” means to publish or republish a Document, in whole or in part, as part of another Document. An MMC is “eligible for relicensing” if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, and (2) were thus incorporated prior to November 1, 2008. The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing. i i i i i i i i i i i i i i i i Glosario actuador Dispositivo electrónico con capacidad para modificar el valor de una magnitud física. adaptador [de objetos] En un servidor, estructura ligada a uno o más puntos de conexión (endpoints) que permite acceder remotamente a uno o varios objetos distribuidos. co-localizado (colocated) Se aplica a objetos o servidores para indicar que su implementación comparte la misma máquina, proceso, espacio de memoria, etc., que un potencial cliente; circunstancias que permiten realizar optimizaciones en recursos y tiempo. domótica Conjunto de tecnologías orientadas al aumento del confort, la seguridad y el aprovechamiento de recursos en el hogar. e-health Aplicación de la tecnología para la asistencia de personas mediante cuidados médicos, normalmente fuera de las instalaciones sanitarias. endpoint Especifica un punto lógico de conexión en el que puede escuchar un servidor en espera de peticiones. inmótica Conjunto de tecnologías orientadas a la mejora del confort, la seguridad y la optimización de recursos en grandes edificios, comúnmente llamados inteligentes. observador Entidad software (objeto o función) que es invocado por una segunda entidad observable para notificar un cambio Ş Patrón de diseño [GHJV96] que especifica este comportamiento. retrollamada Es una referencia a una función o método, normalmente escrita por el usuario. Esta referencia se le pasa a una segunda entidad (como argumento de una función) para que sea invocada al producirse cierto evento o condición. 297 i i i i i i i i 298 F. GNU F REE D OCUMENTATION L ICENSE sensor Dispositivo electrónico capaz de detectar y/o medir una magnitud física para ofrecerla como un dato a un sistema de cómputo. serialización Procedimiento por el cual una entidad software de cualquier tipo se puede representar como una secuencia de bytes con objeto de ser almacenada o enviada a través de una red de comunicaciones. sirviente Es la porción de código encargada de realizar una tarea concreta como respuesta a la invocación de un método de un objeto remoto. En los MDOO el sirviente suele ser la instancia de una clase proporcionada por el usuario y que especializa las clases generadas por el compilador de interfaces (el esqueleto). transductor Un dispositivo que puede convertir una magnitud física o señal en, o a partir de, una señal electrónica. Engloba por tanto a sensores y actuadores. i i i i i i i i Bibliografía [Abd04] T. Abdelzaher, B. Blum, Q. Cao, Y. Chen, D. Evans, J. George, S. George, L. Gu, T. He, S. Krishnamurthy, L. Luo, S. Son, J. Stankovic, R. Stoleru, y A. Wood. EnviroTrack: towards an environmental computing paradigm for distributed sensor networks. En Distributed Computing Systems, 2004. Actas de 24th International Conference on, páginas 582–589, 2004. [All06] OSGi Alliance. OSGi Service Platform, Core Specification Release 4, Version 4.0.1. Technical report, Open Service Gateway Initiative, 2006. url: http://www.osgi. org/Release4/Download. [arc07] Arch Rock Primer Pack product gateway datasheet, 2007. Product Catalog. [AXIa] AXIS 212 Network Camera. url: http://www.axis.com/products/cam_212/. [AXIb] AXIS 214 Network Camera. url: http://www.axis.com/products/cam_214/. [AY05] K. Akkaya y M. Younis. A survey on routing protocols for wireless sensor networks. Ad Hoc Networks, 3(3):325–349, May 2005. [AYS07] A. Al-Yasiri y A. Sunley. Data aggregation and middleware in wireless sensor networks. En Sensor and theory applicatios XIV (SENSOR07), Journal of Physics: Conference Series 76, 2007., 2007. [Bak97] S. Baker. CORBA Distributed Objects. Addison-Wesley, 1997. + [BBD 02] R. Barr, J. C. Bicket, D. S. Dantas, B. Du, T. W. Danny, K. Bing, Z. Emin, y G. Sirer. On the Need for System-Level Support for Ad Hoc and Sensor Networks. Operating System Review, 36:1–5, 2002. [BBK02] M. Balazinska, H. Balakrishnan, y D. Karger. INS/Twine: A Scalable Peer-to-Peer Architecture for Intentional Resource Discovery. En Actas de First International Conference on Pervasive Computing, páginas 195–210, 2002. [BFG06] L. Benini, E. Farella, y C. Guiducci. Wireless sensor networks: Enabling technology for ambient intelligence. Microelectronics Journal, 37(12):1639–1649, December 2006. [BHS03] A. Boulis, C. C. Han, y M. B. Srivastava. Design and implementation of a framework for efficient and programmable sensor networks. En MobiSys ’03: Actas de 1st international conference on Mobile systems, applications and services, páginas 187– 200, New York, NY, USA, 2003. ACM. [BHSS07] A. Boulis, C. C. Han, R. Shea, y M. B. Srivastava. SensorWare: Programming sensor networks beyond code update and querying. Pervasive Mob. Comput., 3(4):386–412, 2007. 299 i i i i i i i i 300 BIBLIOGRAFÍA [BKN07] M. Brzozowski, R. Karnapke, y J. Nolte. IMPACT - A Family of Cross-Layer Transmission Protocols for Wireless Sensor Networks. En Performance, Computing, and Communications Conference, 2007. IPCCC 2007. IEEE Internationa, páginas 619–625, 2007. [BLV09] R. Bosman, J. Lukkien, y R. Verhoeven. An integral approach to programming sensor networks. En Actas de Consumer Communications and Networking Conference, IEEE, Enero 2009. url: http://www.win.tue.nl/san/wsp. [BN84] A. D. Birrell y B. J. Nelson. Implementing remote procedure calls. ACM Trans. Comput. Syst., 2(1):39–59, 1984. [BT04] Bluetooth SIG. Specification of the Bluetooth System v2.0, Noviembre 2004. url: http://www.bluetooth.org. [Cam02] C. Campo. Service Discovery in Pervasive Multi-Agent Systems. En Workshop on Ubiquitous Agents and embedded, wearable and mobile devices, 2002. [CCM06] Object Management Group. CORBA Component Model Specification, edición Versión 4.0, Abril 2006. url: http://www.omg.org/docs/formal/06-04-01.pdf. [CGG+ 05] C. Curino, M. Giani, M. Giorgetta, A. Giusti, A. L. Murphy, y G. P. Picco. TinyLIME: bridging mobile and sensor networks through middleware. Pervasive Computing and Communications, 2005. PerCom 2005. Third IEEE International Conference on, páginas 61–72, 2005. [CGMA06] C. Campo, C. García, A. Marín, y F. Almenárez. PDP: a lightweight discovery protocol for local-scope interactions in wireless ad hoc networks. Comput. Networks, 50(17):3264–3283, December 2006. [CJYF02] D. Chakraborty, A. Joshi, Y. Yesha, y T. Finin. GSD: A Novel Group-based Service Discovery Protocol for MANETS. En In 4th IEEE Conference on Mobile and Wireless Communications Networks (MWCN, páginas 140–144, 2002. [CMnP+ 05] C. Campo, M. Muñoz, J. C. Perea, A. Marin, y C. Garcia. PDP and GSDL: a new service discovery middleware to support spontaneous interactions in pervasive systems. En Third IEEE International Conference on Pervasive Computing and Communications Workshops, páginas 178–182, March 2005. [CMP06] P. Ciciriello, L. Mottola, y G. P. Picco. Building virtual sensors and actuators over logical neighborhoods. En MidSens ’06: Actas de International Workshop on Middleware for Sensor Networks, páginas 19–24, New York, NY, USA, 2006. ACM. [COR02] Object Management Group. The Common Object Request Broker: Architecture and Specification, edición 3.0, Junio 2002. url: http://www.omg.org/docs/formal/ 98-12-01.pdf. [Cou81] Xerox Corporation, Stamford, Connecticut. Courier: The remote procedure call protocol, Diciembre 1981. [CSAT06] A. Chalak, V. Sivaraman, N. Aydin, y D. Turgut. A Comparative Study of Routing Protocols in Wireless Sensor Networks. En Actas de IEEE Thirteenth International Conference on Telecommunications (ICT), May 2006. [cso] csoap client/server SOAP library in pure C. url: http://csoap.sourceforge. net/. [DAV04] A. Dunkels, J. Alonso, y T. Voigt. Making TCP/IP Viable for Wireless Sensor Networks. En Actas de The First European Workshop on Wireless Sensor Networks (EWSN), 2004. i i i i i i i i BIBLIOGRAFÍA 301 [DBS+ 01] K. Ducatel, M. Bogdanowicz, F. Scapolo, J. Leijten, y J. C. Burgelman. Scenarios for ambiente intelligence in 2010. Technical report, Information Society Technologies Advisory Group, Febrero 2001. [DH98] S. Deering y R. Hinden. Internet Protocol, Version 6 (IPv6) Specification. RFC 2460 (Draft Standard), Diciembre 1998. Updated by RFC 5095. url: http: //www.ietf.org/rfc/rfc2460.txt. [dJ02] I. de Jong. Web Services/SOAP and CORBA. Technical report, Abril 2002. url: http://www.xs4all.nl/~irmen/comp/CORBA_vs_SOAP.html. [DT80] L. P. Deutsch y E. A. Taft. Requirements for a exceptional programming environment. Technical report, Xerox Palo Alto Research Center, 1980. [Dun03] A. Dunkels. Full TCP/IP for 8-Bit Architectures. En Actas de First International Conference on Mobile Applications, Systems and Services, MOBISYS’03, Mayo 2003. [EGHK99] D. Estrin, R. Govindan, J. Heidemann, y S. Kumar. Next Century Challenges: Scalable Coordination in Sensor Networks. En Actas de ACM/IEEE International Conference on Mobile Computing and Networking, páginas 263–270, Seattle, Washington, USA, Agosto 1999. ACM. url: http://www.isi.edu/~johnh/PAPERS/Estrin99e. html. [EHK+ 07] L. Evers, P. J. M. Havinga, J. Kuper, M. E. M. Lijding, y N. Meratnia. SensorScheme: Supply chain management automation using Wireless Sensor Networks. En Emerging Technologies and Factory Automation, 2007. ETFA. IEEE Conference on, páginas 448–455, 2007. [Eis06] M. Eisler. XDR: External Data Representation Standard. RFC 4506 (Standard), Mayo 2006. url: http://www.ietf.org/rfc/rfc4506.txt. [eOR] OpenFusion e*ORB. url: http://www.prismtechnologies.com/. [EWS] EWS: Embedded Web Services, Grupo ARCO. url: http://arco.esi.uclm.es/ ews. [FHK04] C. Frank, V. Handziski, y H. Karl. Service Discovery in Wireless Sensor Networks. Technical report, Technical University Berlin, March 2004. [FRH04] C. L. Fok, G. C. Roman, y G. Hackmann. A Lightweight Coordination Middleware for Mobile Computing. páginas 135–151. 2004. [FRL05] C. L. Fok, G. C. Roman, y C. Lu. Mobile agent middleware for sensor networks: an application case study. En Information Processing in Sensor Networks, 2005. IPSN 2005. Fourth International Symposium on, páginas 382–387, 2005. [GEK08] Y. Gadallah y H. El-Kassabi. A WSN/MANET Hybrid Protocol for Routing Data in Heterogeneous Wireless Sensor Networks. En Wireless Communications and Mobile Computing Conference, 2008. IWCMC ’08, páginas 523–528, 2008. [Gel85] D. Gelernter. Generative communication in Linda. Programming Languages and Systems, 7:80–112, 1985. [GES+ 04] L. Girod, J. Elson, T. Stathopoulos, M. Lukac, y D. Estrin. Emstar: a software environment for developing and deploying wireless sensor networks. En Actas de 2004 USENIX Technical Conference, páginas 283–296, 2004. [GGG05] Ramakrishna G., Omprakash G., y Ramesh G. Macro-programming Wireless Sensor Networks using Kairos. En In DCOSS, páginas 126–140. Springer, 2005. [GHJV96] E. Gamma, R. Helm, R. Johnson, y J. Vlissides. Dessign Patterns. Addison-Wesley, 1996. ACM Transactions on i i i i i i i i 302 BIBLIOGRAFÍA [GHM+ 03] M. Gudgin, M. Hadley, N. Mendelsohn, J. Moreau, y H. F. Nielsen. SOAP Version 1.2 Part 1: Messaging Framework. World Wide Web Consortium, 2003. [Gib04] Bionic Buffalo Corporation. TatankaT M CORBA Tools and Components, 2004. url: http://www.tatanka.com/prod/info/gibraltar.html. [GKS02] A. Gokhale, B. Kumar, y A. Sahuguet. Reinventing the Wheel? CORBA vs. Web Services. En Actas de la 11o International World Wide Web Conference, Mayo 2002. url: http://www2002.org/CDROM/alternate/395/. [GPK99] E. Guttman, C. Perkins, y J. Kempf. Service Templates and Service: Schemes. RFC 2609 (Proposed Standard), Junio 1999. url: http://www.ietf.org/rfc/rfc2609. txt. [GPVD99] E. Guttman, C. Perkins, J. Veizades, y M. Day. Service Location Protocol, Version 2. RFC 2608 (Proposed Standard), Junio 1999. Updated by RFC 3224. url: http://www.ietf.org/rfc/rfc2608.txt. [Gro] Object Managemet Group. Catalog of OMG IDL / Language Mappings Specifications. url: http://www.omg.org/technology/documents/idl2x_spec_ catalog.htm. [GSP+ 03] C. Gill, V. Subramonian, J. Parsons, H. M. Huang, S. Torri, D. Niehaus, y D. Stuart. ORB middleware evolution for networked embedded systems. En Actas de Eighth International Workshop on Object-Oriented Real-Time Dependable Systems, 2003. (WORDS 2003)., páginas 169–176, Enero 2003. [Hae06] T. Haenselmann. Sensornetworks. 2006. [Hau01] O. Haugan. Configuration and Code Generation Tools for Middleware Targeting Small, Embedded Devices. Master’s thesis, Washington State University, Diciembre 2001. [Hen04] M. Henning. A New Approach to Object-Oriented Middleware. Internet Computing, IEEE, 8(1):66–75, 2004. [Hen09] M. Henning. Choosing Middleware: Why Performance and Scalability do (and do not) Matter, 2009. url: http://zeroc.com/articles/IcePerformanceWhitePaper. pdf. [HFRL06] G. Hackmann, C. L. Fok, G. C. Roman, y C. Lu. Agimone: Middleware Support for Seamless Integration of Sensor and IP Networks. 2006. [HKB99] W. R. Heinzelman, J. Kulik, y H. Balakrishnan. Adaptive protocols for information dissemination in wireless sensor networks. En MobiCom ’99: Actas de 5th Annual ACM/IEEE International Conference on Mobile Computing and Networking, páginas 174–185, New York, NY, USA, 1999. ACM. [HKFK03] V. Handziski, A. Kopke, C. Frank, y H. Karl. Semantic Addressing for Wireless Sensor Networks. Technical report, November 2003. [HM06] S. Hadim y N. Mohamed. Middleware: middleware challenges and approaches for wireless sensor networks. Distributed Systems Online, IEEE, 7(3):1–1, March 2006. [HMCP04] W. B. Heinzelman, A. L. Murphy, H. S. Carvalho, y M. A. Perillo. Middleware to support sensor network applications. IEEE Network, 18(1):6–14, 2004. [HMM+ ] W. Horré, S. Michiels, N. Matthys, W. Joosen, y P. Verbaeten. On the Integration of Sensor Networks and General Purpose IT Infrastructure. [HR06] K. Henricksen y R. Robinson. A survey of middleware for sensor networks: state-ofthe-art and future directions. En MidSens ’06: Actas de International Workshop on Middleware for Sensor Networks, páginas 60–65, New York, NY, USA, 2006. ACM. i i i i i i i i BIBLIOGRAFÍA [HS08] M. Henning y M. Spruiell. Distributed Programming with Ice. ZeroC Inc., Mayo 2008. Revision 3.3.0. [HV99] G. Holland y N. Vaidya. Analysis of TCP Performance over Mobile Ad Hoc Networks. En Actas de MOBISYS’99, Agosto 1999. [HX05] J. Helander y Y. Xiong. Secure Web services for low-cost devices. En Eighth IEEE International Symposium on Object-Oriented Real-Time Distributed Computing, 2005, 2005. [Ice] Embedded Ice. url: http://www.zeroc.com/icee/index.html. [IDM] IDM: Inter-Domain Messaging, Grupo ARCO. url: http://arco.esi.uclm.es/ IDM. [IEE85] Institute of Electrical y Electronic Engineers. IEEE 754-1985 Standard for Binary Floating-Point Arithmetic, ANSI/IEEE Standard 754-1985, 1985. [IGE00] C. Intanagonwiwat, R. Govindan, y D. Estrin. Directed Diffusion: A Scalable and Robust Communication Paradigm for Sensor Networks. En ACM International Conference on Mobile Computing and Networking (MOBICOM’00, páginas 56–67, 2000. [JOW+ 02] P. Juang, H. Oki, Y. Wang, M. Martonosi, L. S. Peh, y D. Rubenstein. Energy-Efficient Computing for Wildlife Tracking: Design Tradeoffs and Early Experiences with ZebraNet. En ASPLOS-X 2002: Actas de la 10a 10th international conference on Architectural support for programming languages and operating systems, volume 37, páginas 96–107, New York, NY, USA, Octubre 2002. ACM Press. [Kab06] S. Kabadayi. Middleware for On-Demand Access to Sensor Networks. Technical report, University of Texas, October 2006. [KBL07] T. Kobialka, R. Buyya, y C. Leckie. Open Sensor Web Architecture: Stateful Web Services. En Actas del Third International Conference on Intelligent Sensors, Sensor Networks and Information Processing (ISSNIP) 2007, 2007. [KCBC02] F. Kon, F. Costa, G. Blair, y R. Campbell. The Case for Reflective Middleware. Adaptive middleware (special issue), 45:33–38, Junio 2002. [KHH05] M. Kuorilehto, M. Hännikäinen, y T. D. Hämäläinen. A survey of application distribution in wireless sensor networks. EURASIP J. Wirel. Commun. Netw., 5(5):774– 788, 2005. url: http://portal.acm.org/citation.cfm?id=1115500. [KKKP99] J. M. Kahn, R. H. Katz, Katz, y K. S. J. Pister. Next Century Challenges: Mobile Networking for Smart Dust, 1999. [KKN07] M. Kruger, R. Karnapke, y J. Nolte. In-network processing and collective operations using the COCOS-framework. En Emerging Technologies and Factory Automation, 2007. ETFA. IEEE Conference on, páginas 1194–1201, 2007. [KMS07] N. Kushalnagar, G. Montenegro, y C. Schumacher. IPv6 over Low-Power Wireless Personal Area Networks (6LoWPANs): Overview, Assumptions, Problem Statement, and Goals. RFC 4919 (Informational), Agosto 2007. url: http://www.ietf.org/ rfc/rfc4919.txt. [KN06] R. Karnapke y J. Nolte. COPRA - A Communication Processing Architecture for Wireless Sensor Networks. En Euro-Par 2006 Parallel Processing, páginas 951–960, 2006. [KSSZ97] P. Kalyanasundaram, A. S. Sethi, C. M. Sherwin, y D. Zhu. A spreadsheet-based scripting environment for SNMP. En Integrated Network Management V, páginas 752–765. Chapman and Hall, 1997. 303 i i i i i i i i 304 BIBLIOGRAFÍA [LC02] P. Levis y D. Culler. Mate: A tiny virtual machine for sensor networks. En International Conference on Architectural Support for Programming Languages and Operating Systems, San Jose, CA, USA, Octubre 2002. [LGC05] P. Levis, D. Gay, y D. Culler. Active sensor networks. En NSDI’05: Actas de 2nd conference on Symposium on Networked Systems Design & Implementation, páginas 343–356, Berkeley, CA, USA, 2005. USENIX Association. [lib] XML-RPC for C and C++, A lightweight RPC library based on XML and HTTP. url: http://xmlrpc-c.sourceforge.net/. [LLS+ 03] S. Li, Y. Lin, S. H. Son, J. A. Stankovic, y Y. Wei. Event detection services using data service middleware in distributed sensor networks. En Information Processing in Sensor Networks, página 557. Springer, Enero 2003. [LM03] T. Liu y M. Martonosi. Impala: A Middleware System for Managing Autonomic, Parallel Sensor Systems. En In PPoPP ’03: Actas de la 9a ACM SIGPLAN symposium on Principles and practice of parallel programming, páginas 107–118. ACM Press, 2003. [LSZM04] T. Liu, C. M. Sadler, P. Zhang, y M. Martonosi. Implementing Software on ResourceConstrained Mobile Sensors: Experiences with Impala and ZebraNet. Princeton University, ACM, Junio 2004. [Mal98] G. Malkin. RIP Version 2. RFC 2453 (Standard), Noviembre 1998. Updated by RFC 4822. url: http://www.ietf.org/rfc/rfc2453.txt. [Mar05] P. J. Marrón. Middleware Approaches for Sensor Networks. Summer School on WSNs and Smart Objects, Agosto 2005. [Mar08] J. Martínez de Sousa. Ortografía y ortotipografía del español actual. Trea, 2008. [MFHH05] S. R. Madden, M. J. Franklin, J. M. Hellerstein, y W. Hong. TinyDB: an acquisitional query processing system for sensor networks. ACM Trans. Database Syst., 30(1):122– 173, 2005. [MKHC07] G. Montenegro, N. Kushalnagar, J. Hui, y D. Culler. Transmission of IPv6 Packets over IEEE 802.15.4 Networks. RFC 4944 (Proposed Standard), Septiembre 2007. url: http://www.ietf.org/rfc/rfc4944.txt. [ML02] F. Moya y J. C. López. SENDA: An Alternative to OSGi for Large Scale Domotics. En Actas de Networks, páginas 165–176. World Scientific Publishing, Agosto 2002. [MLM+ 05] P. J. Marrón, A. Lachenmann, D. Minder, J. Hähner, R. Sauter, y K. Rothermel. TinyCubus: A Flexible and Adaptive Framework for Sensor Networks. En Actas de Second European Workshop on Wireless Sensor Networks (EWSN 2005), páginas 278–289, January 2005. [MML02] J. Morena, F. Moya, y J. C. López. Implementación de un ORB para Dispositivos Empotrados. En Actas de Symposium on Informatics and Telecommunications, 2002. [Moy03] F. Moya. Infraestructura de comunicaciones para la creación, modelado y gestión de servicios y redes para el hogar. PhD thesis, Universidad Politécnica de Madrid, Escuela Técnica Superior de Ingenieros de Telecomunicación, 2003. [MPHS05] R. Marin-Perianu, P. Hartel, y H. Scholten. A Classification of Service Discovery Protocols. Technical report, University of Twente, The Netherlands, Junio 2005. url: http://eprints.eemcs.utwente.nl/735/. [MPSH06] R. S. Marin-Perianu, J. Scholten, y P. J. M. Havinga. Distributed Service Discovery for Heterogeneous Wireless Sensor Networks. Technical Report TR-CTIT-06-42, Enschede, Junio 2006. i i i i i i i i BIBLIOGRAFÍA 305 [MPSHH08] R. S. Marin-Perianu, J. Scholten, P. J. M. Havinga, y P. H. Hartel. Cluster-based service discovery for heterogeneous wireless sensor networks. International Journal of Parallel, Emergent and Distributed Systems, 23(4):325–346, Agosto 2008. [MVV+ 09] F. Moya, D. Villa, F. J. Villanueva, J. Barba, F. Rincón, y J. C. López. Embedding standard distributed object-oriented middlewares in wireless sensor networks. Wireless Communications and Mobile Computing, 9(3):335–345, 2009. [NA02] W. Nagel y N. Anderson. A Protocol for Representing Individual Hardware Devices as Objects in a CORBA Networt. En Actas de Real-time and Embedded Distributed Object Computing Workshop, 2002. [Nel81] B. J. Nelson. Remote Procedure Call. Technical report, Xerox Palo Alto Research Center, 1981. [Nesa] nesC: A Programming Language for Deeply Networked Systems. //nescc.sourceforge.net/. [NESb] NEST: Network Embedded Systems Technology. url: http://www.darpa.mil/ ipto/programs/nest/nest.asp. [NXT] Lego NXT technology. default.aspx. [Obj98] Object Managemet Group. CORBAtelecoms: Telecommunications Domain Specifications, Junio 1998. url: http://www.omg.org/cgi-bin/doc?formal/98-07-12. [Obj00] Object Managemet Group. Property Service Specification, Abril 2000. url: http: //www.omg.org/docs/formal/00-06-22.pdf. [Obj01a] Object Managemet Group. Event Service Specification, edición 1.1, Marzo 2001. url: http://www.omg.org/docs/formal/01-03-01.pdf. [Obj01b] Object Managemet Group. Naming Service Specification, Febrero 2001. http://www.omg.org/docs/formal/01-02-65.pdf. [Obj02] Object Management Group. Minimum CORBA Specification, edición 2.3, Agosto 2002. url: http://www.omg.org/docs/formal/02-08-01.pdf. [Obj03] Object Management Group. Smart Transducers Interface Specification, edición Versión 1.0, Enero 2003. url: http://www.omg.org/docs/formal/03-01-01. pdf. [Obj04] Object Management Group. Internet Inter-ORB Protocol, edición 3.0.3, Marzo 2004. url: http://www.omg.org/cgi-bin/doc?formal/04-03-12. [Obj08a] Object Management Group. CORBA Interoperability Architecture, edición Versión 3.1, Enero 2008. url: http://www.omg.org/spec/CORBA/3.1/Interoperability/ PDF. [Obj08b] Object Management Group. CORBA Messaging, edición Versión 3.1, Enero 2008. url: http://www.omg.org/spec/CORBA/3.1/Interfaces/PDF. [OKK04] C. S. Oh, Y. B. Ko, y J. H. Kim. A Hybrid Service Discovery for Improving Robustness in Mobile Ad Hoc Networks. En InternationalConference on Dependable Systems and Networks, July 2004. [OMG] Object Management Group. url: http://www.omg.org/. [Org06] Organization for the Advancement of Structured Information Standards. OASIS Reference Model for Service Oriented Architecture 1.0, Octubre 2006. url: http: //docs.oasis-open.org/soa-rm/v1.0/soa-rm.pdf. url: http: url: http://mindstorms.lego.com/eng/Overview/ url: i i i i i i i i 306 BIBLIOGRAFÍA [OVB05] F. Outay, V. Vêque, y R. Bouallègue. Survey of Service Discovery Protocols and Benefits of Combining Service and Route Discovery. International Journal of Computer Science and Networking Security, 7(11):85–92, 2005. [PH05] D. Puccinelli y M. Haenggi. Wireless sensor networks: applications and challenges of ubiquitous sensing. Circuits and Systems Magazine, IEEE, 5(3):19–31, 2005. [PH08] D. Puccinelli y M. Haenggi. Arbutus: Network-Layer Load Balancing for Wireless Sensor Networks. En Wireless Communications and Networking Conference, 2008. WCNC 2008. IEEE, páginas 2063–2068, 2008. [PK02] C. Perkins y R. Koodli. Service Discovery in On-Demand Ad Hoc Networks. Technical report, IETF, Octubre 2002. [PKGZ08] B. Priyantha, A. Kansal, M. Goraczko, y F. Zhao. Tiny Web Services for Sensor Device Interoperability. En IPSN ’08: Actas de 7th International Conference on Information Processing in Sensor Networks, páginas 567–568, Washington, DC, USA, 2008. IEEE Computer Society. [PRP05] A. Puder, K. Römer, y F. Pilhofer. Distributed Systems Architecture: A Middleware Approach. Morgan Kaufman, 2005. [PST07] E. J. Pauwels, A. A. Salah, y R. Tavenard. Sensor Networks for Ambient Intelligence. En Multimedia Signal Processing, 2007. MMSP 2007. IEEE 9th Workshop on, páginas 13–16, 2007. [Pyt] Python. url: http://www.python.org/. [R0̈4] K. Römer. Programming Paradigms and Middleware for Sensor Networks. En GI/ITG Workshop on Sensor Networks, páginas 49–54, 2004. [RBW01] G. Rivera, R. Brega, y F. H. Wullschleger. Light-Weight Distributed Computing for Embedded Systems. First-Hand Experiences with the Simple Object Access Protocol for Mobile Robots. En Actas de EUROBOT’2001, 2001. url: http: //xo2.org/Docs/eurobot01soap.pdf. [RDB+ 09] F. Rincón, J. Dondo, J. Barba, F. Moya, y J. C. López. Supporting Operating Systems for Reconfigurable Computing: A Distributed Service Oriented Approach. En International Conference on Engineering of Reconfigurable Systems and Algorithms, July 2009. [RFC03] G. Rodrigues, C. Ferraz, y S. V. Cavalcante. A CORBA–Based Surrogate Model on IP Networks. En Actas de 21st Brazilian Symposium on Computer Networks – Natal, RN, Brazil. Sociedade Brasileira de Computacao – SBC, Mayo 2003. [RKC01] M. Roman, F. Kon, y R. H. Campbell. Reflective middleware: From your desk to your hand. IEEE Distributed Systems Online, 2, 2001. [RKM02] K. Römer, O. Kasten, y F. Mattern. Middleware Challenges for Wireless Sensor Networks. SIGMOBILE: Mobile Computing and Communications Review, 6(4):59– 61, Octubre 2002. [RLH+ 97] Y. Rekhter, P. Lothberg, R. Hinden, S. Deering, y J. Postel. An IPv6 Provider-Based Unicast Address Format. RFC 2073 (Proposed Standard), Enero 1997. Obsoleted by RFC 2374. url: http://www.ietf.org/rfc/rfc2073.txt. [RMDS02] K. Römer, F. Mattern, T. Dübendorfer, y J. Senn. Infrastructure for Virtual Counterparts of Real World Objects. Technical report, 2002. [RMKC00] M. Roman, M. D. Mickunas, F. Kon, y R. Campbell. LegORB and ubiquitous CORBA. En Proc. IFIP/ACM Middleware’2000 Workshop on Reflective Middleware (RM2000, páginas 1–2, 2000. i i i i i i i i BIBLIOGRAFÍA 307 [Rod] P. Rodriguez. Sistemas Operativos Distribuidos y de Tiempo Real. E.T.S.E de Telecomunicación. url: http://alen.ait.uvigo.es/~pedro/pub/sodtr/ index.html. [RSC+ 99] M. Román, A. Singhai, D. Carvalho, C. K. Hess, y R. H. Campbell. Integrating PDAs into Distributed Systems: 2K and PalmORB. En HUC ’99: Actas de 1st international symposium on Handheld and Ubiquitous Computing, páginas 137–149, London, UK, 1999. Springer-Verlag. [SGaV+ 04] E. Souto, G. Guimarães, G. Vasconcelos, M. Vieira, N. Rosa, y C. Ferraz. A messageoriented middleware for sensor networks. En MPAC ’04: Actas de 2nd workshop on Middleware for pervasive and ad-hoc computing, páginas 127–134, New York, NY, USA, 2004. ACM. [SJS01] C. Srisathapornphat, C. Jaikaeo, y C. C. Shen. Sensor Information Networking Architecture and Applications. IEEE Personal Communications, 8:52–59, 2001. [SKLN08] T. Senner, R. Karnapke, A. Lagemann, y J. Nolte. A Combined Routing Layer for Wireless Sensor Networks and Mobile Ad-Hoc Networks. En SENSORCOMM ’08: Actas de 2008 Second International Conference on Sensor Technologies and Applications, páginas 147–153, Washington, DC, USA, 2008. IEEE Computer Society. [Sph] Logitech QuickCam Sphere. url: http://www.logitech.com/index.cfm/ webcam_communications/webcams/devices/3480&cl=roeu,en. [Sri95a] R. Srinivasan. RPC: Remote Procedure Call Protocol Specification Version 2. RFC 1831 (Proposed Standard), Agosto 1995. url: http://www.ietf.org/rfc/ rfc1831.txt. [Sri95b] R. Srinivasan. XDR: External Data Representation Standard. RFC 1832 (Draft Standard), Agosto 1995. Obsoleted by RFC 4506. url: http://www.ietf.org/ rfc/rfc1832.txt. [Sta] Crossbow Stargate. url: http://www.xbow.com/products/Product_pdf_ files/Wireless_pdf/Stargate_Datasheet.pdf. [Sun01] Sun Microsystems. Jini Architecture Specification, edición 1.2, Diciembre 2001. url: http://www.sun.com/. [Sun06] Sun Microsystems. Jini Technology Surrogate Architecture Specification, Junio 2006. url: https://surrogate.dev.java.net/. [SXG+ 04] V. Subramonian, G. Xing, C. Gill, C. Lu, y R. Cytron. Middleware specialization for memory-constrained networked embedded systems. En in 9th IEEE Real-Time and Embedded Technology and Applications Symposium, 2004. [SXGC03] V. Subramonian, G. Xing, C. Gill, y R. Cytron. The design and performance of special purpose middleware: A sensor networks case study. Enero 2003. [TIN] TINI: The InterNet Interface. microcontrollers/tini/. [TMN01] International Telecommunication Union. Telecommunications management network. ITU-T Recommendation M.3120. CORBA generic network and network element level information model, 2001. [Uni00] The Unicode Standard, Version 3.0, 2000. unicode/uni2book/u2.html. url: http://www.maxim-ic.com/products/ url: http://www.unicode.org/ [UPn00] UPnP Forum. Universal Plug and Play Device Architecture 1.0, Junio 2000. [UVV+ 09] G. Urzaiz, D. Villa, F. J. Villanueva, F. Moya, F. Rincon, J. C. Lopez, y L. A. Munoz. A novel communication platform to enable the collaboration of Autonomous Underwater Vehicles. En Actas de International Conference on Wireless Networks, Julio 2009. i i i i i i i i 308 BIBLIOGRAFÍA [VCC] Canon VCC4 Communication Camera. url: http://www.usa.canon.com/ consumer/controller?act=ModelInfoAct&fcategoryid=158&modelid= 7402. [VECGS92] T. Von Eicken, D. E. Culler, S. C. Goldstein, y K. E. Schauser. Active messages: a mechanism for integrated communication and computation. En Actas de 19th Annual International Symposium on Computer Architecture, páginas 256–266, 1992. [VGPK97] J. Veizades, E. Guttman, C. Perkins, y S. Kaplan. Service Location Protocol. RFC 2165 (Proposed Standard), Junio 1997. Updated by RFCs 2608, 2609. url: http://www.ietf.org/rfc/rfc2165.txt. [VHM+ 07] P. Verbaeten, W. Horré, N. Matthys, S. Michiels, y W. Joosen. A survey of middleware for wireless sensor networks. Technical report, Katholieke Universiteit Leuven, Agosto 2007. [Vil09] F. J. Villanueva. Despliegue eficiente de entornos inteligentes basado en redes inalámbricas. PhD thesis, Universidad de Castilla-La Mancha, 2009. [VML04] D. Villa, F. Moya, y J. C. López. Implementación mínima de objetos CORBA para dispositivos empotrados. En Actas de XIV Jornadas TELECOM I+D, 2004. [VOV+ 06] F. J. Villanueva, J. A. Olivera, D. Villa, F. Moya, F. Rincón, J. Barba, y J. C. López. Multimedia Data Transmission in MANETs for Intelligent Environments. En Actas de 2nd International Workshop on Ubiquitous Computing and Ambient Intelligence, páginas 35–44, Noviembre 2006. [VR05] M. S. Vieira y N. S. Rosa. A reconfigurable group management middleware service for wireless sensor networks. En MPAC ’05: Actas de 3rd international workshop on Middleware for pervasive and ad-hoc computing, páginas 1–8, New York, NY, USA, 2005. ACM. [VVM+ 05a] D. Villa, F. J. Villanueva, F. Moya, F. Rincón, J. Barba, y J. C. López. Spreading Pervasive Computing by Means of Small Distributed Objects. En Ubiquitous Computing and Ambient Intelligence, Septiembre 2005. [VVM+ 05b] F. J. Villanueva, D. Villa, F. Moya, F. Rincón, J. Barba, y J. C. López. A QoS Framework for Adaptative Context-Aware Applications in Mobile Ad-hoc Network -based Smart Buildings. En Actas del International Symposium on Ubiquitous Computing and Ambient Intelligence 2005, páginas 19–26, Septiembre 2005. [VVM+ 06a] D. Villa, F. J. Villanueva, F. Moya, F. Rincón, J. Barba, y J. C. López. Embedding a Middleware for Networked Hardware and Software Objects. En Actas de International Conference on Grid and Pervasive Computing. Springer, Mayo 2006. [VVM+ 06b] F. J. Villanueva, D. Villa, F. Moya, F. Rincón, J. Barba, y J. C. López. Context-Aware QoS Provision for Mobile Ad-hoc Network based Ambient Intelligent Environments. Journal of Universal Computer Science (JUCS), 12(3):315–327, Abril 2006. [VVM+ 07a] D. Villa, F. J. Villanueva, F. Moya, F. Rincón, J. Barba, y J. C. López. Minimalist Object Oriented Service Discovery Protocol for Wireless Sensor Networks. En Actas de International Conference on Grid and Pervasive Computing, páginas 472–483. Springer, Mayo 2007. [VVM+ 07b] F. J. Villanueva, D. Villa, F. Moya, F. Rincón, J. Barba, y J. C. López. Lightweight Middleware for Seamless HW-SW Interoperability, with Application to Wireless Sensor Networks. En Actas de Design, Automation and Test in Europe (DATE), páginas 1042–1047, Abril 2007. [VVM+ 08a] D. Villa, F. J. Villanueva, F. Moya, F. Rincón, J. Barba, y J. C. López. ASDF: an object oriented service discovery framework for wireless sensor networks. International i i i i i i i i BIBLIOGRAFÍA 309 Journal of Pervasive Computing and Communications (IJPCC), 4(4):371–389, Diciembre 2008. [VVM+ 08b] D. Villa, F. J. Villanueva, F. Moya, G. Urzaiz, F. Rincón, y J. C. López. Object Oriented Multi-Layer Router with Application on Wireless Sensor-Actuator Networks. En ICON 2008. 16th IEEE International Conference on Networks, 2008., páginas 1–7. IEEE, Diciembre 2008. [VVM+ 09] D. Villa, F. J. Villanueva, F. Moya, F. Rincón, J. Barba, y J. C. López. Web Services for deeply embedded extra low-cost devices. En Actas de International Conference on Grid and Pervasive Computing, páginas 400–409. Springer, Mayo 2009. [VVSL09] F. J. Villanueva, D. Villa, M. J. Santofimia, y J. C. López. A Framework for Advanced Home Service Design and Management. En Actas del International Conference on Consumer Electronics, Enero 2009. [WAS] WASP: Wirelessly Accesible Sensor Populations. url: http://www.wasp-project. org/. [WCLD08] M. M. Wang, J. N. Cao, J. Li, y S. K. Das. Middleware for Wireless Sensor Networks: A Survey. Journal Of Computer Science and Technology, páginas 305–326, Mayo 2008. [Whi75] J. E. White. High-level framework for network-based resource sharing. RFC 707, Diciembre 1975. url: http://www.ietf.org/rfc/rfc707.txt. [WIN] Rockwell WINS node. url: http://wins.rsc.rockwell.com/. [Win01] D. Winer. WSDL Specification. World Wide Web Consortium, 2001. url: http: //www.w3.org/TR/wsdl. [WIZ] WIZnet module. url: http://www.wiznet.co.kr/en/pro02.php?&ss[2] =2&page=1&num=77. [X10] The X10 PowerHouse Powerline Interface Two-Way Powerline Interface Model TW523. ftp://ftp.x10.com/pub/manuals/technicalnote.pdf. [XPo] Lantronix XPort. url: http://www.lantronix.com/device-networking/ embedded-device-servers/xport.html. [YG02] Y. Yao y J. Gehrke. The Cougar approach to in-network query processing in sensor networks. SIGMOD Record, 31:2002, 2002. [Yu004] Issues in designing middleware for wireless sensor networks. 18(1):15–21, Jan/Feb 2004. [ZE98] E. Zelkha y B. Epstein. From Devices to “Ambient Intelligence”. Digital Living Room Conference, Junio 1998. [Zera] ZeroC, Inc. url: http://www.zeroc.com/. [Zerb] Inc. ZeroC. Ice Performance Tests. url: http://www.zeroc.com/performance/. Model PL513 and Disponible en Network, IEEE, i i i i i i i i i i i i i i i i Índice alfabético actor, 84 activo, 89 compuesto, 94 proactivo, 92 reactivo, 91 adaptador, 18, 180 banco (de registros), 117 bloque, 121 bus lógico, 19 bytecode, 125 cableado virtual, 97 cliente, 18 componente, 93 contenedor, 88 corbaloc, 26 corbaname, 26 CORBAServices, 27 DATA (FSM), 119 digest, 120 DL, 23 domótica, 12 endpoint, 182 EnviroTrack, 64 ERROR_EVENT, 122 Event Service, 28 eventos, 122 Flash (FSM), 120 FSM, 120 fsmCode, 125 fsmData, 125 fsmFlash, 125 GIOPLite, 46, 109 Ice (ZeroC), 32 IDM, 177 Impala, 60 INCOMING_EVENT, 122 interfaz, 18 IOR, 26 Kairos, 65 lit, 120 Literal, 120 máquina virtual, 129 Magnet, 56 MiLAN, 58 MinimumCORBA, 38 Naming Service, 27 objeto, 18 OMA, 20 OMG, 20 ORB, 24 picoObjeto, 107 POA, 23 propiedad, 135 proxy, 19, 106 reactor, 123 referencia (a objeto), 25 311 i i i i i i i i 312 ÍNDICE ALFABÉTICO RESET_EVENT, 122 RMI, 17 RPC, 14 SAN, 4 servicio DUO, 84 reactivo, 98 SDP, 79 servidor, 18 sirviente, 18 subrutinas, 121 timer, 123 TinyCubus, 59 TinyLime, 63 variables FSM, 119 WIZnet, 200 XPort, 199 ZebraNet, 60 i i i i i i i i Este documento fue editado con GNU Emacs y tipografiado con LATEX en un sistema GNU. Las figuras fueron realizadas con Inkscape. Ciudad Real, julio de 2009. i i i i i i i i i i i i i i i i i i i i