Universidad Complutense Facultad de Informática Sistemas Informaticos 2009/2010 Icaro-D: Infraestructura Multiagente Distribuida Autores: Andrés Picazo Cuesta Arturo Mazon Tribiño Alejandro Fernández Carrión Supervisores: Juan Pavón Mestras Francisco Garijo 11 Junio 2010 Índice 1. Introducción 7 1.1. Motivación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.2. Qué es Icaro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.3. Objetivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.4. Publico y beneficios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.5. Plan de proyecto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 1.5.1. Recursos necesarios . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.6. Cuestiones legales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.7. Plan de Validación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 2. Requisitos y Especificaciones 15 2.1. Requisitos del usuario . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.2. Especificación de Requisitos de software . . . . . . . . . . . . . . . . . 15 2.2.1. Arranque del sistema . . . . . . . . . . . . . . . . . . . . . . . . 16 2.2.2. Notas sobre las especificaciones . . . . . . . . . . . . . . . . . . 26 3. Análisis y Diseño 27 3.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.2. Arquitectura Icaro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 3.3. Arquitectura RMI: Java Remote Method Invocation . . . . . . . . . . . 30 3.3.1. Modelo de Capas RMI . . . . . . . . . . . . . . . . . . . . . . . 30 3.4. Arquitectura para la distribución . . . . . . . . . . . . . . . . . . . . . 31 3.4.1. Introducción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 3.4.2. Comunicación Agentes y Directorio . . . . . . . . . . . . . . . . 32 3.4.3. ControlRMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 3.4.4. Gestor de Comunicaciones . . . . . . . . . . . . . . . . . . . . . 35 3.4.5. Mensajes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 3.4.6. Gestor de Nodo . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 3.5. Interfaz del usuario, las trazas . . . . . . . . . . . . . . . . . . . . . . . 38 Icaro Distribuido 4. Implementacion 40 4.1. Organización del código . . . . . . . . . . . . . . . . . . . . . . . . . . 40 4.2. Uso de Java RMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 4.3. Implementación de los componentes diseñados . . . . . . . . . . . . . . 44 4.3.1. GestorAplicaciónComunicación . . . . . . . . . . . . . . . . . . 44 4.3.2. Mensaje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 4.3.3. Comunicación Agentes . . . . . . . . . . . . . . . . . . . . . . . 50 4.3.4. Control RMI . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 4.3.5. Gestor Nodo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 4.4. Implementación de las trazas . . . . . . . . . . . . . . . . . . . . . . . . 53 4.4.1. Detalles de implementacion . . . . . . . . . . . . . . . . . . . . 53 4.4.2. Uso de la nueva implementacion . . . . . . . . . . . . . . . . . . 54 4.4.3. Nueva visualizacion . . . . . . . . . . . . . . . . . . . . . . . . . 54 4.5. Aplicaciones distribuidas . . . . . . . . . . . . . . . . . . . . . . . . . . 57 4.5.1. Gúıa de ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 4.6. Detalles de Implementación . . . . . . . . . . . . . . . . . . . . . . . . 65 4.6.1. Modificaciones de la Infraestructura . . . . . . . . . . . . . . . . 65 4.6.2. Arranque de aplicaciones . . . . . . . . . . . . . . . . . . . . . . 66 5. Validacion 68 5.1. Aplicaciones ejemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 5.1.1. Chat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 5.1.2. MasterIA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 6. Conclusiones y trabajo futuro 86 6.1. Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 6.2. Trabajo futuro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 6.2.1. Tratamiento de Trazas . . . . . . . . . . . . . . . . . . . . . . . 86 6.2.2. Gestión de fallos en nodos . . . . . . . . . . . . . . . . . . . . . 87 6.2.3. Control de la carga de comunicaciones . . . . . . . . . . . . . . 88 6.2.4. Arranque parcial . . . . . . . . . . . . . . . . . . . . . . . . . . 88 3 Icaro Distribuido 6.2.5. Ventana de arranque . . . . . . . . . . . . . . . . . . . . . . . . 88 6.2.6. Mejorar empaquetado . . . . . . . . . . . . . . . . . . . . . . . 88 6.2.7. Creación dinámica de agentes . . . . . . . . . . . . . . . . . . . 89 7. Referencias y enlaces 89 7.1. Referencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 7.2. Descargando el proyecto . . . . . . . . . . . . . . . . . . . . . . . . . . 89 4 Icaro Distribuido Autorización Legal Los abajo firmantes, matriculados en la asignatura de Sistemas Informáticos de la Facultad de Informática, autorizan a la Universidad Complutense de Madrid a difundir y utilizar con fines académicos, no comerciales y mencionando expresamente a los au- tores el presente trabajo de proyecto de Sistemas Informáticos: “Icaro-D: Infraestruc- tura Multiagente Distribuida”, realizado durante el curso académico 2009-2010, bajo la dirección de Juan Pavón Mestras (UCM) y Francisco Garijo, incluyendo la propia memoria, el código, la documentación y el prototipo desarrollado. También autorizan a la biblioteca de la Universidad Complutense de Madrid, a depositarlo en el archivo institucional E-Prints Complutense, con el objeto de incre- mentar la difusión, uso e impacto del trabajo en internet y garantizar su preservación y acceso a largo plazo. Andrés Picazo Arturo Mazón Alejandro Fernández 5 Icaro Distribuido Resumen El presente trabajo parte de la infraestructura Icaro para sistemas multi-agente y pretende ampliarlo incluyendo un sistema de comunicación entre agentes que facilite la distribución de los componentes de Icaro (agentes y recursos) en una red, simplificando el problema de las comunicaciones. Con este objetivo se ha incorporado un nuevo componente, un gestor de comunicaciones, que realiza esta tarea de forma transparente a los desarrolladores. También se ha incorporado tres nuevas clases que reducen la carga de trabajo de un desarrollador, simplificando el uso de la infraestructura como puede comprobarse en los ejemplos incluidos. Adicionalmente se han introducido en paralelo diversas mejoras en el codigo original de Icaro, entre las que destacan la simplificación y depuración de métodos, y la implementación de un nuevo sistema de trazas más completo que el original. Para validar el presente trabajo se han desarrollado dos aplicaciones, un chat, que sirva como demostrador de todas las funcionalidades implementadas, y una aplicación que sirva para ilustrar la guia de ejemplo incluida en esta documentación. Finalmente se ha usado una aplicación ya existente, masterIA, para mostrar el proceso de migración de un modelo centralizado a uno distribuido. Actualmente las aplicaciones distribuidas son muy utilizadas e importantes, y este proyecto aporta una herramienta que facilita la tarea de crear aplicaciones distribuidas eliminando la necesidad de partir de cero. Palabras clave: Agente, Multiagente, Distribuido, Java, Icaro, RMI, Infraestruc- tura, Organización, Sistemas multiagente, Aplicaciones inteligentes. Abstract The developed work is based on the software multi-agent system Icaro. Its purpose is extending it with the comunication layer between agents facilitating the distribution for Icaro components (agents and resources), in a computer network. With this objective it has been incorporated a new component, the comunications manager, to implement this task. Also, three new clases have been implemented to reduce the workload of developers, simplifying the use of the platform as can be seen in the validation chapter. Aditionally, several upgrades has been introduced in the original Icaro source code, highlighting the simplification and grouping of methods, and the implementation of a new visual tracing system. To validate this work it has been developed two applications, a chat, to serve as a testbench of the new functionality, and another to illustrate the tutorial present in this documentation. Finally, it has been used an existing application, masterIA, to demostrate the migration from centralized to distributed. Distributed applications today are very important and widespread, and this project provides a tool which facilitates the task of creating distributed applications, removing the need to start from zero. Keywords: Agent, Mullti-agent, Java, Distributed, RMI, Icaro, Organization, In- fraestructure, Multi-agent systems, Inteligent aplications. 6 Icaro Distribuido 1. Introducción 1.1. Motivación El proyecto Icaro-D, surgie a ráız del trabajo realizado en la asignatura de inge- nieŕıa del software, donde se desarrollo una aplicación (gestion de una PYME) para una empresa utilizando la infraestructura ICARO-Mini. Durante el desarrollo de ese proyecto surgieron ideas de como mejorar la infraestructura Icaro, que se implementan en este trabajo. La principal carencia que se encuentra en Icaro durante este periodo es la ausencia de un sistema que permita distribuir los componentes de Icaro en distintos nodos de una red de ordenadores, detalle que se considera, según algunas definiciones (por ejemplo, la que puede encontrarse en pagina de wikipedia), como algo imprescindible para los sistemas multi agente. Dado que la distribución de aplicaciones es además una solución empleada comúnmente para resolver problemas durante el desarrollo de algunas aplicaciones que pueden ser empleadas por varios usuarios a la vez, y que necesiten establecer una forma de asegurar la sincronización de los datos, se considera que esta aportación resulta una importante mejora sobre la versión original de Icaro. Las alternativas existentes a Icaro, como por ejemplo Jade o Semantic Agent ya implementan este modelo, sin embargo son aplicaciones que requieren una mayor curva de aprendizaje, y en muchos casos, resultan más pesadas y complejas de utilizar. Por ello se considera necesario incluir esta funcionalidad en Icaro, más ligero y basado en conceptos más familiares a la mayoria de desarrolladores, para poder convertirse en una alternativa atractiva, e incluso didáctica, para sus potenciales usuarios. 1.2. Qué es Icaro Icaro-T (nombre original) es una infraestructura software ligera, basada en el lengua- je de programación Java, para el desarrollo de sistemas multiagente mediante organi- zaciones de agentes. Estas organizaciones suponen una de las grandes diferencias entre Icaro y otras plataformas, como podŕıa ser Jade. Cada aplicación que se implementa con Icaro utiliza una descripción de organización, escrita en formato xml, en la que se detallan que agentes y recursos componen la aplicación, sus modelos y sus instancias, asi como su integración dentro de una organización de control (gestores). Mientras que otras plataformas multi agentes se centran en seguir un estándar para las comunicaciones, como KQML o FIPA, Icaro se centra en ofrecer componentes de alto nivel que faciliten el desarrollo de agentes capaces de coordinarse entre śı. Esto simplifica el desarrollo de los propios agentes y recursos, pero en cambio no implementa ningún estándar de comunicación como hacen la mayoŕıa de plataformas, cuestión que se aborda en este trabajo. Icaro esta modelado en tres capas: control, recursos e información. En este modelo la capa de control, formada por gestores y agentes especializados, con idéntica estruc- tura a un agente normal, pero con disferente rol en la infraestructura, estos gestores son responsables de las tareas de gestión de una aplicación, tales como configuración, 7 Icaro Distribuido activación y monitorización. Los agentes especializados son los encargados de llevar a cabo la funcionalidad propia de la aplicación para lo cual son capaces de colaborar entre ellos. La capa de recursos contiene los elementos que proveen a la aplicación de funcionalidades e información para alcanzar sus objetivos. Finalmente la capa de infor- mación contiene las entidades que modelan los datos de las aplicaciones. Puede verse en la figura siguiente esta estructura de capas de forma gráfica. Además incluye ejemplos de utilización en proyectos software concretos para ayudar en el aprendizaje del uso de esta infraestructura. Estas aplicaciones se encuentran dentro del paquete “aplicaciones”, como se detalla en el apartado “organizacion del código”. Un sistema multiagente podria definirse como un sistema distribuido en el cual los nodos o elementos son sistemas de inteligencia artificial, o bien un sistema distribuido donde la conducta combinada de dichos elementos produce un resultado en conjunto inteligente. (http://es.wikipedia.org/wiki/Sistema multi agente). Figura 1: Modelo de capas de Icaro 8 Icaro Distribuido 1.3. Objetivos El objetivo principal planteado para este proyecto es integrar en Icaro la capacidad de distribuir sus componentes (agentes), entre los distintos nodos de una red de orde- nadores, convirtiendo Icaro en una plataforma atractiva para futuros desarrolladores de aplicaciones distribuidas. Se pretende aislar la infraestructura del programador de forma que solo tenga que preocuparse de desarrollar su aplicación, y no de la infraestructura en la que se apoya. Promover el uso de esta infraestructura para el desarrollo de todo tipo de aplica- ciones futuras. Ofreciendo una base de software sencilla de utilizar y que permita una depuración sencilla de las aplicaciones desarrolladas sobre esta. Como objetivo adi- cional, se pretende además complementar la formación de los autores en materia de sistemas distribuidos. Hacer que las aplicaciones hechas con ICARO funcionen de manera distribuida. Permitir el uso de distintos protocolos de comunicación. Permitir al programador definir protocolos nuevos y/o editar los existentes. Representar gráficamente la comunicación entre agentes. Implementar un recurso para la comunicación entre agentes genérico transparente al programador. Implementar la posibilidad de ejecutar acciones de los agentes desde la ventana de trazas. Implementar un sistema de seguimiento de errores de comunicación. Implementación de una aplicación de simulación de redes de computadores como demostrador tecnológico. Mejorar la visualización de todos los agentes y recursos de las aplicaciones aśı co- mo de la infraestructura. Mejorar el sistema de trazas de ICARO haciéndolo más claro y detallado para que sea más fácil analizar y depurar el software. Para el desarrollo de este proyecto se dispuso de un tiempo de 8 meses, con una dedicación media de 12 horas semanales por cada uno de los tres integrantes del grupo de proyecto. 1.4. Publico y beneficios Dado que este proyecto es en realidad la actualización y mejora de Icaro, seguirá es- tando disponible al mismo público que antes: programadores Java y grupos de desarrollo de aplicaciones en Java. 9 Icaro Distribuido ICARO-D proporciona a los desarrolladores de aplicaciones distribuidas una in- fraestructura que evite tener que controlar cada detalle de comunicaciones y despliegue distribuidos de sus aplicaciones. Para esto se añade una capa de abstración que se en- cargua de realizar el trabajo más complejo, proporcionando métodos sencillos para realizar las tareas más complejas inherentes a los sistemas distribuidos, de modo que se puedan centrar en el desarrollo aunque no tengan mucha experiencia en este tipo de trabajo. Además se intenta mejorar en lo posible otros aspectos de la infraestructura, como la ventana de trazas, o la organización y limpieza del código. El proyecto se distribuye bajo una licencia de software libre GNU-GPL, y se pub- licará en la página ofical de la forja morfeo, donde podrán encontrarse, además, ver- siones anteriores y la documentación completa de uso y desarrollo de Icaro. La dirección de la página es: http://icaro.morfeo-project.org/preguntas-frecuentes. La licencia GNU-GPL puede consultarse en las siguientes direcciones: Versión oficial (Ingles): http://www.gnu.org/copyleft/gpl.html Versión español (traducción no oficial): http://www.viti.es/gnu/licenses/gpl.html 1.5. Plan de proyecto Para este proyecto de sistemas informáticos se dispuso de ocho meses de trabajo y un equipo de tres personas. durante este tiempo se han dedicado una media de 12 horas semanales por cada miembro del equipo. Con estas limitaciones en cuenta se plantea la planificación que se muestra en la tabla que se encuentra más adelante. La organización del tiempo de trabajo se ha basado en periodos de puesta en común del trabajo realizado, estudio individual de los aspectos desconocidos (como RMI) y reparto de trabajo en función del tiempo disponible, ya que dependiendo de la fecha hay integrantes del grupo con más tiempo y otros con menos. Aśı la mayor carga de trabajo se ha conseguido repartir de forma uniforme a lo largo de todo el año. Para alojar el proyecto, asi como para proporcionar otros recursos de colaboración, como listas de correo y un repositorio de subversion, se ha seleccionado la plataforma Kenai, propiedad de Sun, ya que nos ofrece todas los recursos necesarios, e incluso más, como wiki, varios repositorios y todas las listas de correo que necesitemos. Se puede acceder a esta plataforma desde la direccion http://www.kenai.com La coordinación se ha realizado mediante las listas de correo de Kenai y un sistema de control de versiones, ambos de la plataforma Kenai. Teniendo muy en cuenta que todos los d́ıas de trabajo se realizará una reunión para tomar decisiones y discutir sobre un plan común de desarrollo. Además se cuenta con hacer reuniones periódicas con los coordinadores para revisar el estado del trabajo realizado, asi como para discutir las opciones disponibles para resolver los problemas que se encuentren. Para el objetivo de distribuir ICARO se utiliza la API de Java RMI como mid- dleware. Se elige esta opción sobre otras alternativas como CORBA o ICE ya que el proyecto se implementa en Java y RMI minimiza las dependencias del proyecto, a pe- sar de ser algo más limitado, por ejemplo, siendo válido unicamente para comunicar 10 Icaro Distribuido objetos Java. El proyecto se distribuye bajo una licencia de software libre GNU-GPL. La plani- ficación del proyecto se ha dividido en las siguientes fases: 1. Especificación del proyecto Se deciden las funcionalidades que deb́ıa ofrecer la imple- mentación de este proyecto, decidiendo finalmente pasar por las fases especificadas a continuación. 2. Integración de RMI en Icaro Se integra RMI en los patrones de agente existentes en Icaro. En esta fase se incluye la decisión de la infraestructura a uti- lizar para las comunicaciones, decidiendo finalmente el uso de RMI. 3. Desarrollo de nueva ventana de trazas Se implementa la nueva ventana de trazas que se ha comen- tado más arriba, con el objetivo de tener una herramienta lo más completa posible para ayudar a la depuracion de la integración de RMI que se realiza en la fase siguiente 4. Imple- mentación de aplicación de chat Con RMI integrado y una ventana de trazas más completa, se desarrolla durante esta fase la aplicación de chat especificada anteriormente, el objetivo es probar el funcionamiento de las comunicaciones entre dos ordenadores a traves de una red uti- lizando los elementos básicos que proporciona RMI. También durante esta fase se implementan la clase controlRMI, para agrupar los métodos más habituales en una única clase. 5. Creación del gestor de comu- nicaciones Se diseña y se implementa el gestor de comunicaciones que se encargará de proporcionar el servicio de comunicaciones a los demás agentes, este gestor utiliza las controlRMI y co- municacionAgentes, para ofrecer funcionalidad adicional a las comunicaciones, como son los mensajes a grupos. 6. Paso de cen- tralizado a dis- tribuido Se coge una aplicación existente desarrollada en Icaro, mas- terIA, y se prueba a cambiar su modelo centralizado por uno distribuido. 7. Imple- mentación del gestor de nodo Se desarrolla el gestor de nodo, encargado de esperar por el despliiegue de aplicaciones. También se prueban métodos para desplegar aplicaciones que compartan un mismo fichero de descripción de organización. Se realizan las pruebas usando la aplicación de chats. 8. Imple- mentación de la aplicación de ejemplo Se desarrolla una sencilla aplicación, con el objetivo de usarse como tutorial para ilustrar la guia de ejemplo incluida en esta documentación en el apartado del mismo nombre 9. Redacción de la docu- mentación En esta fase, con todos los componentes nuevos implementa- dos, integrados y probados, pasamos a redactar la presente documentación 1.5.1. Recursos necesarios En base a la experiencia de desarrollo, los recursos hardware necesarios para llevar a cabo los objetivos del proyecto son los siguientes : 11 Icaro Distribuido 3 Pcs de media potencia como sistema operativo Windows o Linux: Dado que el proyecto trata de un sistema distribuido se ha considerado necesario un mı́nimo de dos equipos para realizar las pruebas del desarrollo, que finalmente han sido tres, uno por cada integrante del equipo. Conexión a internet: Para poder hacer las pruebas con más de un equipo es imprescindible disponer de una conexión a traves de la cual mandar los mensajes habituales para un sistema distribuido. Además, se han utilizado los siguientes recursos software: Plataforma de desarrollo: Dado que se trata de un proyecto de cierta envergadura consideró necesario el uso de un entorno que facilite el trabajo, por ello se selec- cionó el entorno Netbeans IDE versión 6.8, ya que se encuentra integrado con el servidor usado para alojar el proyecto. Alojamiento en un servidor: Con el fin de coordinar al grupo se empleó un repos- itorio en el que alojar el proyecto para poder trabajar de forma independiente. Se ha utilizado la plataforma Kenai (http://www.Kenai.com), de Sun, para esta tarea, que proporciona tanto el repositorio de subversion como el acceso a lis- tas de correo, servidor ftp y cualquier otro recurso que pudiera haber resultado necesario. La versión de trabajo del proyecto se encuentra alojada con el t́ıtulo “Infraestructura Distribuida Icaro”. Listas de distribución de correo: Para poder comunicarnos entre nosotros y con nuestros coordinadores de proyecto se ha utilizado una lista de correo, propor- cionada también por la plataforma Kenai. Los conocimientos necesarios de los desarrolladores han sido: Experiencia en desarrollo con el lenguaje de programación Java y en el uso de la API RMI. Conocimientos en ingenieŕıa del software. Uso y gestión de redes de computadores, al menos al nivel necesario para com- probar el estado de las conexiones de la red. Diseño de sistemas distribuidos. Experiencia en el uso de la plataforma Icaro. Entender los conceptos de agente, recurso y sistema multiagentes. 1.6. Cuestiones legales El proyecto es totalmente libre, de código abierto y por lo tanto es público para el uso de cualquier persona. En concreto se autoriza a la Universidad Complutense a difundir y utilizar con fines académicos, no comerciales y mencionando expresamente a 12 Icaro Distribuido sus autores, tanto la propia memoria, como el código, la documentación y/o el prototipo desarrollado. La licencia sobre la que se distribuye es GNU-GPL, que puede consultarse (en Inglés) en la página: http://www.gnu.org/copyleft/gpl.html 1.7. Plan de Validación Para comprobar las mejoras que se han implementado, asi como su funcionalidad, se han implementado dos aplicaciones: la principal, un sencillo chat que sirviera tanto de banco de pruebas para los diferentes métodos de comunicaciones que se iban desar- rollando, como un punto único donde puedan encontrarse ejemplos de cómo utilizar dichos métodos, comentados en el caṕıtulo de implementación. Adicionalmente se ha incluido otra aplicación, que sirviera de tutorial a los nuevos desarrolladores, esta apli- cación tiene lo mı́nimo necesario para mostrar, al menos en ĺıneas generales, todos los pasos necesarios y las recomendaciones de los autores para crear una aplicación con esta infraestructura. Esta aplicación se utiliza como ejemplo en el apartado “guia de ejem- plo”, de esta documentación. Finalmente se incluye una última aplicación, MasterIA, que sigue el modelo centralizado, para demostrar como se puede migrar una aplicación ya existente, desarrollada con versiones anteriores de Icaro, al modelo distribuido. Estos ejemplos pueden consultarse en el caṕıtulo “validación”. Utilizando estas aplicaciones se ha probado su correcto funcionamiento en distintas redes (cable y wifi, tanto en red local como en internet), cada vez que se completa algún objetivo del proyecto, para asegurar que se mantiene el mismo comportamiento, concretamente la aplicación “chat” ha sido la utilizada en todas las pruebas, utilizando las otras dos únicamente para probar su propio comportamiento, contando ya con garant́ıas del comportamiento de la infraestructura. Adicionalmente se han realizado revisiones de código, tanto del nuevo como del original. Durante este proceso se han eliminado errores nuevos y antiguos, existentes en la versión de Icaro sobre la cual se han implementado las mejoras de este proyecto, y se ha intentado organizar el código lo mejor posible, encapsulando todo lo posible las clases del proyecto, con el objetivo de tener un código legible y claro. Este tra- bajo está orientado a los interesados en desarrollar aplicaciones con Icaro, aśı como a aquellos que deseen realizar otras mejoras sobre esta infraestructura. En el caṕıtulo “conclusiones y lineas abiertas” se detallan posibles mejoras sobre el presente trabajo. Finalmente, se puede observar al trabajar con Icaro que se generan una gran can- tidad de trazas durante la ejecución, incluso en el caso de aplicaciones de escasa com- plejidad, como pueden ser las desarrolladas para en apartado de validación. Icaro ya dispońıa de un recurso gráfico, la ventana de trazas, para permitir la depuración me- diante las trazas, sin embargo resultaba algo farragoso y poco flexible, por lo que adicionalmente se ha implementado una nueva ventana, basada en tablas de Java, en la que se organiza mejor la información y que hace más sencillo el seguimiento de trazas, mediante funciones de ordenación y filtrado. Como ya se ha comentado, los resultados de esta validación pueden consultarse en el caṕıtulo “Validación”, más adelante en esta documentación. También pueden 13 Icaro Distribuido encontrarse referencias a las aplicaciones usadas como ejemplo en el apartado de “im- plementación”, ya que se han usado para poner ejemplos de uso de las nuevas fun- cionalidades. 14 Icaro Distribuido 2. Requisitos y Especificaciones 2.1. Requisitos del usuario Este proyecto como se ha mencionado antes, esta orientado a programadores con los siguientes requisitos: Encapsulamiento de funcionalidad para poder utilizar una infraestructura multi- agente transparente. Uso de Java para el desarrollo de su trabajo. Opcionalmente el desarrollador puede necesitar que la aplicación funcione de manera distribuida en redes de ordenadores como por ejemplo Internet. Utilizar agentes reactivos para el control de la aplicación y recursos. Utilizar tecnoloǵıa RMI para la distribución de la aplicación y su integración con otras aplicaciones que ya esten usando RMI. Proyectos de Ingenieŕıa del Software. 2.2. Especificación de Requisitos de software Las aplicaciones desarrolladas con ICARO-D deberán poder funcionar en redes de ordenadores, tanto locales como en Internet. La base de la comunicación requiere que los terminales(Nodos) tengan sus respectivas direcciones IP y todas la infraestructura arrancada. Para el uso de Icaro-D hay que definir tres tipos de actores: el primero es el usuario estándar de las aplicaciones desarrolladas con la infraestructura, el segundo es el ad- ministrador, responsable del despliegue del sistema, nodos y aplicaciones, y el tercero es interno a la infraestructura, un agente o recurso (ajeno al usuario en śı) que se llamará componente. Estos son los actores presentes en los casos de usos que a contin- uación se describen. Los siguientes casos de uso corresponden a las acciones realizadas por los actores f́ısicos en relación al arranque y terminación del sistema, y al uso de las trazas. 15 Icaro Distribuido 2.2.1. Arranque del sistema CU-01 Arrancar infraestructura Objetivo en contexto Arrancar en un nodo una aplicación entera o parte de una aplicación distribuida. Precondiciones Hay que tener bien configurado el fichero de descripción de organización XML que se vaya a utilizar. Postcondiciones si éxi- to Se arranca la aplicación según el descriptor de organización utilizado como parámetro. También arranca la infraestructura y se empieza a trazar en el recurso de trazas. Postcondiciones si fal- lo Se avisa del fallo por la salida (estándar y la ventana de trazas) mostrando una traza con la información correspondiente de dicho fallo. Actores Usuario, Administrador Secuencia normal 1. Se carga el recurso de trazas. 2. Se carga el recurso de configuración. 3. Se crea el gestor de organización y se arranca, asum- iendo el control de la ejecución. Al crearse el gestor de comunicaciones se activa el registro RMI. 4. Se muestra la ventana de trazas. 5. Se crean los gestores (agentes, recursos y comunica- ciones) . 6. Se arrancan en orden (comunica- ciones,agentes,recursos). El gestor de organización espera el éxito del arranque de cada uno de los gestores anteriores antes de pasar al arranque del siguiente. En el caso del gestor de agentes se irán arrancando en orden los agentes descritos en la descripción de organización y se registran en el registro RMI. 7. Estado de monitorización en espera de eventos. Secuencias alternati- vas Si hay fallo al cargar el sistema en alguno de los puntos anteriores, se informa del error. Una vez mostrada la ventana de trazas se muestran los errores por ella. 16 Icaro Distribuido Figura 2: Arranque de los gestores. Diagrama de colaboración. CU-02 Terminar infraestructura Objetivo en contexto Cerrar de forma ordenada las aplicaciones de un nodo y toda la infraestructura. Precondiciones La infraestructura tiene que estar arrancada y activa. Postcondiciones si éxi- to Se cierran todos los componentes de la aplicación o parte de la aplicación en caso distribuido (Agentes, Recursos) y toda la infraestructura por debajo. Postcondiciones si fal- lo Se visualiza en el recurso de trazas todos los acontecimientos y errores que hayan podido llevar al fallo del sistema. Actores Usuario, Administrador Secuencia normal 1. El actor activa la terminación haciendo click en el botón “TERMINAR” o el botón de cierre genérico de la apli- cación. 2. Le llega al gestor de organización el evento “peti- cion terminar todo” , momento en el que env́ıa al resto de gestores la orden de terminar. 3. Los gestores terminan cada uno de sus componentes ges- tionados y cierran ordenadamente toda la aplicación y la infraestructura. 4. Se cierra el registro de RMI cuando el gestor de agentes ha finalizado todos sus componentes gestionados. 5. Desaparecen todas las visualizaciones de la pantalla. Secuencias alternati- vas Si hay fallos en el cierre del sistema se trazan dichos errores en la ventana de trazas. Y se fuerza el cierre del sistema. 17 Icaro Distribuido CU-03 Lanzar aplicación Objetivo en contexto Ejecutar la aplicación deseada con la descripción de organi- zación especificada. Precondiciones En caso de usar comunicaciones remotas, contar con conexión a la red en la que se encuentran desplegados los nodos a usar en la aplicación. Postcondiciones si éxi- to Se ejecuta la aplicación deseada mostrando en primer lugar la ventana de trazas, en la que se monitorizan las trazas gen- eradas tanto por la aplicación como por la infraestructura, y posteriormente el recurso de visualización (si lo hay) de dicha aplicación. Postcondiciones si fal- lo Se visualiza en el recurso de trazas todos los acontecimientos y errores que hayan podido llevar al fallo del sistema. Actores Usuario, Administrador Secuencia normal 1. El actor lanza la aplicación con la descripción de orga- nización de la aplicación deseada como parámetro. 2. Se arranca el sistema (CU-01). 3. Se ejecuta la aplicación mostrando los componentes de visualización si los hubiera. 4. La aplicación se queda en espera de las acciones del actor en cuestión. Secuencias alternati- vas Si hay fallos se trazan dichos errores en la ventana de trazas. 18 Icaro Distribuido CU-04 Despliegue de nodo Objetivo en contexto Arrancar un nodo para la posterior ejecución de una apli- cación en él. Precondiciones No debe haber sido desplegado anteriormente un nodo en la máquina en la que se quiera desplegar. Postcondiciones si éxi- to Se arranca el nodo en la máquina deseada y se queda en estado de espera . Postcondiciones si fal- lo Se visualiza en el recurso de trazas todos los acontecimientos y errores que hayan podido llevar al fallo del sistema. Actores Administrador Secuencia normal 1. El actor ejecuta Icaro-D con el parámetro “-nodo”. 2. El gestor de nodo arranca un registro RMI y se incluye aśı mismo en él. 3. La aplicación se queda en espera de una petición de arranque de una aplicación en dicho nodo. Secuencias alternati- vas Si hay fallos se trazan dichos errores en la ventana de trazas. 19 Icaro Distribuido CU-05 Despliegue de aplicación Objetivo en contexto Arrancar una aplicación en los nodos ya desplegados que están a la espera. Precondiciones Deben existir los nodos requeridos y estar a la espera, y además contener una copia de Icaro-D y de la descripción de aplicación ejecutada. Postcondiciones si éxi- to Se arranca la aplicación seǵın el despliegue deseado. Postcondiciones si fal- lo Se visualiza en el recurso de trazas todos los acontecimientos y errores que hayan podido llevar al fallo del sistema. Actores Administrador Secuencia normal 1. El actor ejecuta Icaro-D con “-desplegar” y la descrip- ción de organizacióon de la aplicación deseada como parámetros. 2. Se arranca el sistema (CU-01). 3. Se muestra en el nodo del actor una ventana que muestra el progreso del despliegue de la aplicación, en la que se informa del estado de cada nodo y de los posibles errores. 4. Se env́ıa a todos los gestores de nodos remotos una peti- ción de arranque con la descripción de aplicación desea- da. 5. Se despliega la aplicación en los nodos especificados. 6. Cada uno de los nodos ejecuta la aplicación según la descripción de organización, y notifican el resultado de dicha operación. Secuencias alternati- vas Si hay fallos se trazan dichos errores en la ventana de trazas de cada uno de los nodos, y se notifica el error al nodo del administrador quien lo visualizará en la ven- tana de progreso del desplieque. 20 Icaro Distribuido CU-06 Filtrado de las trazas según el tipo de componente Objetivo en contexto Visualizar las trazas de un sólo tipo de componente (gestor, agente, recurso) en vez de todas a la vez. Precondiciones El sistema debe estar arrancado y la ventana de trazas debe estar visible y activa. Postcondiciones si éxi- to Se muestran las trazas del tipo de componente elegido en la pestaña correspondiente. Postcondiciones si fal- lo Cierre del sistema. Actores Usuario, Administrador Secuencia normal 1. El actor elige el tipo de componente que quiere filtrar (Gestores, Agentes,Recursos o Errores). 2. Pulsa sobre la pestaña correspondiente a dicho tipo de componente. 3. Visualiza en el panel de esa pestaña solo las trazas rela- cionadas con el tipo de componente requerido. Secuencias alternati- vas Este proceso también puede ser realizado usando el textField “Filtro” de la ventana de trazas y escribir en él el tipo de componente deseado. 21 Icaro Distribuido CU-07 Visualización de las trazas de un componente en concreto. Objetivo en contexto Visualizar las trazas de un sólo componente. Precondiciones El sistema debe estar arrancado y la ventana de trazas debe estar visible y activa. Postcondiciones si éxi- to Se muestran las trazas del componente elegido en la pestaña correspondiente. Postcondiciones si fal- lo Cierre del sistema. Actores Usuario, Administrador Secuencia normal 1. El actor pulsa en la pestaña del tipo correspondiente al componente en cuestión. 2. En esa pestaña aparece un panel lateral con el nombre de los componentes del tipo elegido. El actor pulsa sobre el nombre del componente deseado. 3. Se muestran sólo las trazas del componente elegido. Secuencias alternati- vas Este proceso también puede ser realizado si el actor pul- sa dos veces sobre el nombre del componente. El resul- tado de esta acción es la visualización de una nueva ven- tana solamente con las trazas del componente elegido. 22 Icaro Distribuido CU-08 Guardar todas las trazas en un fichero de texto. Objetivo en contexto Guardar las trazas en su totalidad en un fichero txt. Precondiciones El sistema debe estar arrancado y la ventana de trazas debe estar visible y activa. Postcondiciones si éxi- to Se guardan las trazas en la carpeta log del sistema. Postcondiciones si fal- lo No se guarda ningún fichero y se notifica el fallo. Actores Usuario, Administrador Secuencia normal 1. El actor pulsa en la pestaña principal de la ventana de trazas, en la que se muestran todas las trazas generadas por el sistema. 2. El actor pulsa sobre el menú “Archivo” y al desplegarse pulsa sobre el submenú “Guardar Todas las Trazas” . 3. Se crea el fichero “ficheroTrazas.txt” en la carpeta log del proyecto y se guardan todas las trazas en dicho fichero. 4. Se muestra un diálogo que informa del éxito de la op- eración. Secuencias alternati- vas 4a Se muestra un diálogo que informa del fallo de la op- eración. 23 Icaro Distribuido CU-09 Guardar las trazas de un determinado tipo de componente en un fichero de texto. Objetivo en contexto Guardar las trazas de un determinado tipo de componente (Gestores, Recursos o Agentes) en un fichero txt. Precondiciones El sistema debe estar arrancado y la ventana de trazas debe estar visible y activa. Postcondiciones si éxi- to Se guardan las trazas en la carpeta log del sistema. Postcondiciones si fal- lo No se guarda ningún fichero y se notifica el fallo. Actores Usuario, Administrador Secuencia normal 1. El actor pulsa en la pestaña correspondiente al tipo de componente deseado en la ventana de trazas, en la que se sólo se muestran las trazas generadas el tipo de com- ponente elegido. 2. El actor pulsa sobre el menú “Archivo” y al desplegarse pulsa sobre el submenú “Guardar Trazas de X ” donde X es el tipo de componente elegido (Gestores, Recursos o Agentes). 3. Se crea el fichero “ficheroTrazasX.txt” en la carpeta log del proyecto donde X es el tipo de componente elegido (Gestores, Recursos o Agentes) y se guardan todas las trazas en dicho fichero. 4. Se muestra un diálogo que informa del éxito de la op- eración. Secuencias alternati- vas 4a Se muestra un diálogo que informa del fallo de la op- eración. Los siguientes casos de uso corresponden a acciones internas a la infraestructura transparentes totalmente al usuario. 24 Icaro Distribuido CU-010 Env́ıo de mensaje a un agente ya sea remoto o no Objetivo en contexto Enviar un mensaje desde un componente origen a un compo- nente cuyo nombre sea conocido, pero no necesariamente su ubicación. Precondiciones El mensaje a enviar debe estar bien formado por medio de la clase Mensaje (crearInputBasico). Postcondiciones si éxi- to Se env́ıa el mensaje al destino y se notifica el éxito. Postcondiciones si fal- lo Se visualiza en el recurso de trazas todos los acontecimientos y errores que hayan podido llevar al fallo del sistema. Actores Componente Secuencia normal 1. El componente env́ıa el mensaje a su gestor de comuni- caciones por medio de ComunicacionAgentes. 2. Se busca el destino en el nodo local. Si se encuentra, se env́ıa el mensaje al destino local por medio de Comuni- cacionAgentes. 3. Si el destino es conocido y remoto, se env́ıa por medio de ControlRMI desde el gestor de comunicaciones del nodo origen al gestor de comunicaciones del nodo destino. 4. Si el destino es desconocido y remoto, ControlRMI bus- cará por medio de buscaInterfazRemota por todos los nodos registrados en el registro RMI hasta encontrar el destino. Cuando lo hace,se env́ıa por medio de Control- RMI desde el gestor de comunicaciones del nodo origen al gestor de comunicaciones del nodo destino. 5. Se notifica el env́ıo del mensaje. 6. El gestor de comunicaciones del nodo destino env́ıa lo- calmente al componente destino el mensaje por medio de su ComunicacionAgentes. 7. Se notifica la recepción del mensaje. Secuencias alternati- vas Si hay fallos se trazan dichos errores en la ventana de trazas de cada uno de los nodos. 4a Si no se encuentra el destino en ninguno de los nodos, se notifica por medio de la ventana de trazas en el nodo origen. La figura 12 del punto 3.4.4 representa el caso de uso anterior mediante un diagrama de secuencia. 25 Icaro Distribuido CU-11 Env́ıo de mensaje a un grupo de agentes ya sean remotos o no Objetivo en contexto Enviar un mensaje desde un componente origen a un grupo de componentes. Precondiciones El mensaje a enviar debe estar bien formado por medio de la clase Mensaje (crearInputParaGrupo) y el grupo destino debe estar especificado en la descripción de aplicación. Postcondiciones si éxi- to Se env́ıa el mensaje al grupo de destino y se notifica el éxito de cada uno de los componentes del grupo. Postcondiciones si fal- lo Se visualiza en el recurso de trazas de cada uno de los nodos todos los acontecimientos y errores que hayan podido llevar al fallo del sistema. Actores Componente Secuencia normal 1. El componente busca en la descripción de aplicación los componentes pertenecientes al grupo destino. 2. Una vez identificados, realiza las acciones del caso de uso anterior CU-06 para cada uno de los componentes del grupo destino. Secuencias alternati- vas Si hay fallos se trazan dichos errores en la ventana de trazas de cada uno de los nodos. 2.2.2. Notas sobre las especificaciones Caracteŕıstica Descripción Idioma Castellano Plataforma de desar- rollo Netbeans IDE 6.8 Plataforma Java JDK 1.6 Dominio Sistemas Multiagentes XML Versión 1.0, encoding UTF-8 Autómatas Todos las maquinas de estados están implementadas como Autómatas Finitos Deterministas. Interfaces gráficas java.swing, java.awt Modelo Recursos-Agentes 26 Icaro Distribuido 3. Análisis y Diseño 3.1. Introducción ICARO-D añade una capa de funcionalidad adicional a ICARO que le permite gestionar las comunicaciones entre agentes de una aplicación a través de RMI. Se podrán realizar fácilmente aplicaciones distribuidas según un modelo de despliegue establecido y todas las comunicaciones serán controladas por la infraestructura. Se ha utilizado una arquitectura basada en gestores que se encargan de controlar todas las capas de las aplicaciones y un gestor de organización que se encarga de controlar los demás gestores. 3.2. Arquitectura Icaro La infraestructura tiene la estructura de directorios que puede verse en la figura 3, que debe mantenerse para el correcto funcionamiento de la infraestrcutura, la estructura concreta y las restriccionesde nombrado pueden verse en el apartado “organización del código”, en el caṕıtulo de “Implementación”. La estructura de paquetes del código fuente contenido de la carpeta src se muestra desplegado en la figura 4 . Refleja el modelo de diseño, que está inspirado en una organización cuyo objetivo consiste en implementar la funcionalidad de la aplicación, como se ha explicado en el apartado 1.2 (“Que es Icaro”). Figura 3: Estructura de directorios Icaro El código está estructurado en dos capas: 27 Icaro Distribuido Figura 4: Estructura del directorio src de Icaro La capa de aplicación: Contiene los elementos –código y ficheros- que modelan las aplicaciones como organizaciones de agentes y recursos. La capa de aplica- ciones contiene los siguientes tipos de paquetes: • Agentes: Contienen la descripción del comportamiento de los agentes que pueden utilizarse en las aplicaciones. Un agente puede tener varios compor- tamientos definidos en los paquetes correspondientes. • Información: contiene clases que modelan diferentes entidades de los do- minios de aplicación. El paquete esta estructurado en tres paquetes para almacenar clases de dominio, objetivos y tareas. • Recursos: Contienen el código de los recursos. Hay dos tipos de recursos comunes a gran parte de las aplicaciones: los recursos de visualización o de forma más genérica de interfaces gráficas y los recurso de persistencia. Pueden añadirse otros recursos según el tipo de aplicaciones. • Descripciones: Contiene los documentos que describen las aplicaciones como organizaciones de agentes, recursos y entidades computacionales co- munes. La capa del marco de trabajo: Contiene la infraestructura computacional necesaria para que el marco de trabajo funcione. Esta formada por los gestores 28 Icaro Distribuido - agentes con un comportamiento ya definido - y por la infraestructura que contiene componentes y clases para la implementación de las organizaciones. La figura 5 representa las dos capas y las dependencias entre los componentes de cada capa. Los paquetes de la capa de marco de trabajo son: • Gestores: Contiene agentes predefinidos para gestionar los componentes que implementan las organizaciones o aplicaciones construidas por los usuar- ios. Se proporcionan tres agentes gestores: Gestor de Organización (GO) Gestor de Agentes (GA) y Gestor de Recursos (GR). • Infraestructura: De la organización, donde se encuentran los patrones que sirven para generar los agentes y los recursos de las aplicaciones, recursos de la organización y componentes básicos que hacen posible la implementación de los agentes y de los recursos. Figura 5: Estructura de Icaro 29 Icaro Distribuido 3.3. Arquitectura RMI: Java Remote Method Invocation Es un mecanismo ofrecido por java para invocar un método de manera remota. Forma parte del entorno estándar de ejecución de Java y provee de un mecanismo simple para la comunicación de servidores en aplicaciones distribuidas basadas exclusivamente en Java. Proporciona paso de objetos por referencia , recolección de basura distribuida y paso de tipos arbitrarios. Por medio de RMI, un programa Java puede exportar un objeto, lo que significa que éste queda accesible a través de la red y el programa permanece a la espera de peticiones en un puerto TCP. A partir de este momento, un cliente puede conectarse e invocar los métodos proporcionados por el objeto. La invocación se compone de los siguientes pasos: Encapsulado (marshalling) de los parámetros (utilizando la funcionalidad de se- rialización de Java). Invocación del método (del cliente sobre el servidor). El invocador se queda es- perando una respuesta. Al terminar la ejecución, el servidor serializa el valor de retorno (si lo hay) y lo env́ıa al cliente. El código cliente recibe la respuesta y continúa como si la invocación hubiera sido local. 3.3.1. Modelo de Capas RMI La arquitectura RMI puede implementa un modelo de cuatro capas, que puede verse en la figura 6: Figura 6: Arquitectura de capas RMI 30 Icaro Distribuido 1. La primera capa es la de aplicación y se corresponde con la implementación real de las aplicaciones cliente y servidor. Aqúı tienen lugar las llamadas a alto nivel para acceder y exportar objetos remotos. Cualquier aplicación que quiera que sus métodos estén disponibles para su acceso por clientes remotos debe declarar di- chos métodos en una interfaz que extienda java.rmi.Remote. Dicha interfaz se usa básicamente para “marcar” un objeto como remotamente accesible. Una vez que los métodos han sido implementados, el objeto debe ser exportado. Esto puede hacerse de forma impĺıcita si el objeto extiende la clase UnicastRemoteObject (paquete java.rmi.server), o puede hacerse de forma expĺıcita con una llamada al método exportObject() del mismo paquete. 2. La capa 2 es la capa proxy, o capa stub-skeleton. Esta capa es la que interactúa directamente con la capa de aplicación. Todas las llamadas a objetos remotos y acciones junto con sus parámetros y retorno de objetos tienen lugar en esta capa. 3. La capa 3 es la de referencia remota, y es responsable del manejo de la parte semántica de las invocaciones remotas. También es responsable de la gestión de la replicación de objetos y realización de tareas espećıficas de la implementación con los objetos remotos, como el establecimiento de las persistencias semánticas y estrategias adecuadas para la recuperación de conexiones perdidas. En esta capa se espera una conexión de tipo stream (stream-oriented connection) desde la capa de transporte. 4. La capa 4 es la de transporte. Es la responsable de realizar las conexiones nece- sarias y manejo del transporte de los datos de una máquina a otra. El protocolo de transporte subyacente para RMI es JRMP (Java Remote Method Protocol). Pueden verse ejemplos de cómo implementar el uso de RMI en una aplicación en el apartado 4.2, “utilizando Java RMI”, en el caṕıtulo de “Implementación”. En dicho apartado se muestran ejemplos comentados sobre cómo realizar las tareas comunes asociadas a RMI, como crear el registro o acceder a los objetos remotos. 3.4. Arquitectura para la distribución 3.4.1. Introducción La ampliación de la arquitectura de ICARO para hacer que las aplicaciones puedan ser distribuidas sigue las mismas pautas que ICARO normal. Se ha añadido un nuevo gestor capaz de gestionar la redirección de los mensajes (gestorAplicacionComunica- cion) entre nodos, con el objetivo de simplificar las comunicaciones entre agentes y entre nodos. Este gestor trabaja con objetos de la clase Mensaje detallada más ade- lante. Estos objetos son los que se env́ıan entre nodos para las comunicaciones. Estamos llamando nodo a una maquina en la que se ejecuta una o más aplicaciones Icaro, puede verse la estructura de un nodo en la figura 8, que obviamente coincide con la arquitec- tura Icaro. También es importante señalar que cada nodo despliega una infraestructura Icaro completa, que se encargará de gestionar el nodo con normalidad, de la misma manera que si fuera centralizado. 31 Icaro Distribuido También se han simplificado las comunicaciones locales a través de la clase Co- municacionAgentes y se ha encapsulado toda la funcionalidad de RMI con la clase ControlRMI. Puede verse un diagrama de la parte de de comunicaciones en la figura 8. Figura 7: Estructura de un nodo en Icaro 3.4.2. Comunicación Agentes y Directorio Ubicación: icaro.infraestructura.entidadesBasicas. La clase comunicaciónAgentes sirve para comunicar a agentes de un nodo(locales). El env́ıo de inputs locales pasa a través de esta clase que busca al destinatario en el repositorio de interfaces y le env́ıa el input que se pasa. En esta funcionalidad están incluidas todas las comunicaciones locales tanto entra agentes, entre gestores o entre agentes y gestores. Aunque esta clase puede utilizarse libremente, se recomienda que se deje su uso al gestor de agentes, empleando el método “enviarMensaje”, presente el patrón de agente reactivo. En cuanto a la clase Directorio, su funcionalidad es sencillamente agrupar en una sola clase el acceso a recursos de la organización, como el repositorio, las trazas y la configuración Icaro. Esta clase se presenta como una solución intermedia a la reestruc- turación de los recursos de organización. Para esto dispone de métodos que permitan acceder de forma sencilla a los servicios más frecuentes que ofrecen estos recursos, además de permitir el acceso a los propios recursos desde aqui. 32 Icaro Distribuido Figura 8: Diagrama de envio de un mensaje local 3.4.3. ControlRMI Ubicación: icaro.infraestructura.entidadesBasicas. Esta clase está para encapsular toda la funcionalidad de RMI, de forma que se instancia cada vez que se quiera utilizar RMI para relizar las siguientes acciones: Asignar un puerto de comunicaciones. Inicializar RMI localizando el registro de RMI en el puerto indicado. Exportar objetos al registro RMI. Eliminar objetos del registro RMI. Obtener la dirección IP del nodo local. Enviar inputs remotos. Cuando se inicia RMI, se crea un icono en la barra de estado para poder visualizar todo lo que haya en el registro de RMI, como puede verse en la figura 9. Al igual que la clase ComunicacionAgentes, se recomienda no emplear directamente esta clase, empleando en su lugar el gestor de comunicaciones. Abajo a la derecha se puede observar el icono en la barra de estado. Si se hace click en alguno de los elementos listados, se saca del registro de RMI. Cualquier agente puede utilizar ControlRMI para enviar inputs remotos, pero la arquitectura que se detalla más arriba está pensada para que todo pase a través del gestor de comunicaciones. Esto 33 Icaro Distribuido Figura 9: Icono de RMI está hecho aśı para dejar libertad a los desarrolladores por si quieren enviar inputs remotos sin tener que utilizar los gestores de comunicaciones. En el diagrama de secuencia que viene a continuación se muestra el env́ıo de un input remoto de un agente a otro. Normalmente estos agentes serán los gestores de comunicación. Notese también que por lo menos el agente destinatario ha de estar localizado en el registro de RMI para recibir el mensaje. Figura 10: Envio de un input mediante control RMI 34 Icaro Distribuido 3.4.4. Gestor de Comunicaciones Ubicación: icaro.gestores.gestorAplicacionComunicacion.comportamiento. El gestor de comunicaciones sirve para controlar el flujo de mensajes que circulan entre los nodos. Principalmente esta clase implementada como un agente reactivo trabaja con objetos de tipo Mensaje, en los cuales entraremos en detalle más adelante. Se recomienda uti- lizar esta clase de forma exclusiva para realizar las comunicaciones, ya que simplifica el código y permite la redirección de mensajes de forma automática, liberando al desar- rollador de saber si el destinatario es local o remoto. Además simplifica enormemente la migración de una aplicación del modelo centralizado al distribuido, como puede verse en el caṕıtulo de validación, en el apartado en el que se migra la aplicación masterIA a distribuido. Como los otros gestores, este también utiliza el fichero de descripción de organi- zación, que es el fichero utilizado por Icaro para declarar la estructura de la aplicación, localizado en la carpeta “config” de la infraestructura. Para más información acerca de cómo editar este archivo, consultar el manual de uso de Icaro. En concreto el gestor de comunicaciones utilizará el contenido de este archivo, contenido en tiempo de eje- cución en el recurso “configuracion” de Icaro, para consultar en que nodo se encuentra el agente destinatario, y donde puede encontrar dicho nodo. Toda la información del despliegue de la aplicación viene escrita este fichero. Viene información de nodos de la aplicación, direcciones IP de cada nodo, agentes y recursos desplegados en cada nodo y otras propiedades como la pertenencia a un grupo. La arquitectura que hemos desarrollado está pensada para que todas las comunica- ciones pasen a través de este gestor. Tanto comunicación local como remota. La idea es que cuando un agente quiera enviar un input a otro, se lo pasa a su gestor de comu- nicaciones local y este con la información del mensaje ya es capaz de redireccionarlo a su destinatario, ya esté en el mismo nodo o en otro. Esto es lo que hace que la infraestructura ICARO-D haga que sea fácil de utilizar para desarrollar aplicaciones distribuidas, este nivel de transparencia para el programador, le permite poder hacer aplicaciones distribuidas sin tener que preocuparse de las comunicaciones entre agentes. Puede verse el autómata del gestor de comunicaciones en la figura 11. En este diagrama puede verse cómo despues del arranque el gestor, éste simplemente espera peticiones, aplicando en cada caso el método apropiado para redirigir el mensaje, quedandose en estado de espera únicamente en los casos en los que el mensaje requiera una respuesta por parte del destinatario y bloqueandose mientras atiende una petición, permitiendo que los mensajes se encolen y se vayan atendiendo según disponibilidad. Esta carac- teristica de bloqueo durante una operación es la razón por la que se implementa esta funcionalidad como un gestor en lugar de como un recurso, el encolado de mensajes ya está implementado en el patron de agentes, y además la existencia de un autóma- ta permite que más adelante se pueda refinar el funcionamiento de la redirección de mensajes de forma sencilla. En esta maquina de estados se representa el gestor con todas sus acciones y posibles inputs. El método que hay que usar para el redireccionamiento de inputs es el de enviarMensaje(). Hay otros tantos métodos que también sirven, pero trabajan con otro tipo de información, utilizan una clase mensaje, que fue el una primera versión para realizar la comunicación, simplemente ese código se ha dejado por si sirviera a 35 Icaro Distribuido Figura 11: Maquina de estados del gestor de comunicaciones algún programador en el futuro, pero nosotros utilizamos mensajes para el traspaso de información y de eso se encarga el método de enviarMensaje(). En caso de necesitar comunicar recursos, será necesario (o mejor dicho, está re- comendado) crear un agente que lo gestione, quedando como única alternativa a esto que el desarrollador cree el recurso encargándose él de que el objeto que se instancie sea remoto, como puede verse en el apartado “Arquitectura RMI”. Esto se debe al modelo de uso del propio RMI, en el caso de un recurso, su interfaz no tiene porque seguir un modelo estandarizado, como si lo hacen los agentes, lo que imposibilita integrar su adaptación remota dentro de la infraestructura, por lo que debe hacerse “a mano” dentro de la aplicación que se esté desarrollando. Tener un agente controlando a un recurso nos ofrece a cambio un mejor control sobre el recurso, pudiendo gestionar, por ejemplo, errores en el mismo, de forma automática. El proceso habitual que se sigue para enviar un mensaje es el siguiente: Un agente crea el mensaje que quiere enviar utilizando alguna de las constructoras de la clase Mensaje Con el mensaje listo, solicita envialo al gestor de comunicaciones, utilizando como se recomienda, el metodo enviarMensaje(Mensaje m). El método enviarMensaje(Mensaje m) utiliza la clase comunicacionAgentes para hacer llegar al gestor de comunicaciones del nodo el mensaje que se quiere enviar. El gestor de comunicaciones recibe un nuevo mensaje y evalúa que debe hacer con el, su destinatario y su contenido. 36 Icaro Distribuido Figura 12: Diagrama de secuencia para el envio de un Mensaje Tomada la decisión sobre como redirigir el mensaje, el gestor utiliza, o bien comu- nicacionAgentes, si el destinatario es local, o bien controlRMI, si es remoto, para enviar el mensaje al destinatario correspondiente, quedando libre para atender otras peticiones 3.4.5. Mensajes Ubicación: icaro.gestores.gestorAplicacionComunicacion.comportamiento. Los ob- jetos creados a partir de la clase Mensaje son los que nos sirven para el env́ıo de información remota. Cuando varios nodos de una aplicación están conectados en red y correctamente configurados en los descriptores de organización, agentes de diferentes nodos(gestores de comunicación) se comunican mediante el env́ıo de objetos de la clase Mensaje. Estos son lo que circulan por RMI. Los mensajes a parte de contener el in- put normal, contienen una seria de datos adicionales, como direcciones IP o fecha de creación, esto es para facilitar todo tipo de datos a la hora de distribuir el mensaje. 3.4.6. Gestor de Nodo Ubicación: icaro.gestores.gestorNodo.comportamiento: Este gestor se implementa para el caso en que queramos tener algún nodo en espera, para poder lanzar la apli- cación completa desde otro nodo, en lugar de lanzar manualmente cada nodo en el momento. Aún seguira siendo necesario lanzar manualmente el gestor de nodo, pero no será necesario indicarle qué debe ejecutar, puesto que la petición llega desde otro lado. 37 Icaro Distribuido 3.5. Interfaz del usuario, las trazas La interfaz de usuario de Icaro es el recurso de trazas. Parte del proyecto ha sido el desarrollo e implementación de un nuevo recurso de trazas que mejorara el ya existente. Para que el lector aprecie las diferencias adjuntamos en primer lugar una imagen con la antigua visualización de este recurso, que puede verse en la figura 13. Figura 13: Visualizacion de trazas original El grupo del proyecto tuvo que trabajar con estas trazas para un proyecto anterior y se detectaron una serie de debilidades que se han querido subsanar. Por ello, se decidió desarrollar un nuevo recurso de trazas que a continuación se describirá. El gran defecto de las antiguas trazas es el excesivo tiempo que tarda en generar y mostrar las trazas. En este aspecto, el nuevo recurso es sensiblemente mejor. Otro aspecto a mejorar era el formato de visualización de las trazas. Como se puede observar en la figura 13 hay un marcado desorden. Además, se agrupan las trazas de todos los componentes (gestores,agentes,recursos) en la misma ventana. Todo esto hace de la tarea de seguir una simple ĺınea de trazas de una aplicación más complicado de lo que debiera. Como tareas añadidas, se han incluido funcionalidades tales como guardar las trazas en ficheros .txt y acelerar el proceso de terminación de una aplicación por medio del botón terminar. Con estas bases, se dispuso a desarrollar el nuevo recurso partiendo de cero, y el resultado ha sido el que se puede observar en las figuras 14 y 15. En el apartado de “Implementación de las trazas” en el punto 4, se describen en detalle todos los nuevos componentes y funcionalidades. 38 Icaro Distribuido Figura 14: Visualizacion de trazas nueva, panel principal Figura 15: Visualizacion de trazas nueva, panel especificol 39 Icaro Distribuido 4. Implementacion En este apartado se tratará la implementación espećıfica de los principales com- ponentes que se han desarrollado, no se incluyen todas las modificaciones que se han hecho en los patrones dado que en su mayoria se trata de cambios pequeños, en otro caso se tratará en el punto “Detalles de Implementación”, mas adelante, se recomienda consultar previamente el manual de Icaro-T, ya que el contenido de este manual debe tratarse en muchos aspectos, como una ampliación del anterior, y no como un sustituto del mismo. 4.1. Organización del código La organización del código completa puede verse en la documentación general de Icaro-T, que puede encontrarse en la web: http://icaro.morfeo-project.org/documentacion/lng/es. También puede encontrarse una descripción de como se han implementado los com- ponentes principales diseñados para establecer la comunicación en el apartado Imple- mentación de los componentes diseñados, más adelante en este mismo caṕıtulo. La organización general del código el la siguiente Aplicaciones: Contiene las aplicaciones basadas en la infraestructura. Nótese que no esta divido en aplicaciones, en el caso en que el mismo proyecto contenga varias. Se incluyen aqui los ejemplos desarrollados para la fase de validación. • Agentes: Contiene la implementación de los agentes, cada agente debe estar contenido en un paquete llamado, obligatoriamente, “agenteAplicacion” + + “Reactivo”, por ejemplo “agenteAplicacionAccesoRe- activo”. La implementación de sus acciones semánticas y su autómata, en el caso de los agentes reactivos deberá estar en un paquete, llamado por defecto “comportamiento”. En cualquier caso se puede utilizar un nombre distinto si se especifica en la descripción de la organización, aunque no se recomienda. Consultar el manual de uso de Icaro para más información. • Recursos: Contiene la implementación de los recursos, al contrario que los agentes el nombre del paquete en que debe ir cada recurso no es fijo, pero se recomienda que su contenido sea una interfaz, cuyo nombre debe ser “ItfUso” + , y un paquete “imp”, que contenga la implementación del interfaz, cuyo nombre debe ser “claseGeneradora” + . • Informacion: Contiene las clases de dominio para la aplicación, es decir, que información se env́ıa. Gestores: Contiene los agentes que se encargan de gestionar la infraestructura • GestorOrganizacion: Se encarga de lanzar y gestionar a los demás ge- stores, y realiza el arranque y parada de la aplicación. 40 Icaro Distribuido • GestorAgentes: Gestiona los agentes de la aplicación • GestoresRecursos: Gestiona los recursos de la aplicación • GestorAplicacionComunicacion: Este es el gestor implementado para simplificar las comunicaciones distribuidas entre nodos. Contiene además la implementación de la clase Mensaje. • GestorNodo: Se encarga de lanzar instancias de aplicaciones por petición remota. Es el único que, en principio, puede funcionar de manera indepen- diente, a la espera de peticiones de arranque remotas. Infraestructura: Contiene los patrones y clases de apoyo de la infraestructura. Mencionar sólo dos paquetes importantes: • entidadesBasicas: Contiene las clases ComunicacionAgentes , ControlRMI y Directorio, entre otras. • clasesGeneradorasOrganizacion: Contiene las clases que arrancan la apli- cación, es decir preparan las trazas, leen la descripción de organización y arrancan el gestor de organización. A continuación expondremos brevemente la forma en que se ha utilizado Java RMI. 4.2. Uso de Java RMI El mecanismo RMI de Java ha sido el medio elegido para implementar las comuni- caciones entre distintos agentes, este mecanismo permite tratar con objetos Java que estan ejecutandose en un entorno remote como si fueran locales, ocultando gran parte del trabajo tedioso que supone establecer conexiones TCP. Java RMI ha sido elegido por encima de otras alternativas, como CORBA o ICE por los siguientes motivos: RMI esta integrado en Java, por lo que no son necesarias infraestructuras a parte, lo que evidentemente facilita su integración con el resto de codigo Java, usado en la implementación de Icaro-D No se requiere software externo. Aunque versiones anteriores de Java RMI nece- sitaban que los usuarios ejecutaran programas ajenos a la aplicación, como eran rmic o rmiregistry, Estos se encuentran ahora disponibles como parte de la API de RMI, y por lo tanto pueden controlarse programaticamente, lo que hace mas compacta la implementación. No se requieren skeletons ni stubs: Estos dos conceptos, muy utilizados en COR- BA, ICE, y versiones anteriores de RMI requerian de un esfuerzo adicional por parte de los programadores e incrementaban el numero de clases Java requeridas. Java RMI realiza este trabajo de forma transparente, sin necesidad de inter- vención explicita por parte del usuario, ni tampoco precompilarlos para poder usarlos. El envio de objetos Java con RMI es muy sencillo, solo es necesario asegurarse de que los mismos sean serializables, lo que permite que la ejecución de métodos de 41 Icaro Distribuido objetos remotos mediante reflexión (el mecanismo usado por los agentes reactivos de Icaro para realizar acciones). A pesar de estas ventajas, existe una dificultad con Java RMI que hace que valga la pena dedicar un espacio aqui a explicar su funcionamiento, y es que prácticamente no existe documentación actualizada acerca del mismo, haciendo referencia la mayor parte de la documentación encontrada a procedimientos obsoletos para emplear RMI, incluida gran parte de la documentación que puede encontrarse en la propia página de Sun. Por esta razón, vamos a explicar brevemente como debe usarse RMI con un ejemplo sencillo: Arquitectura RMI La arquitectura básica usada en RMI puede verse en la figura 16, teniendo en cuenta que el propio sistema RMI gestionará los skeletons y stubs, por lo que podremos considerar RMI como una caja negra. Su funcionamiento depende de dos componentes basicos: los clientes y el registro RMI. El registro RMI es donde se van a encontrar aquellos objectos Java que queramos que estén disponibles para otros objetos, locales o remotos. Este registro se encargará de gestionar las conexiones y de mantener los enlaces entre el registro de nombres (NameRegistry) y los objetos que se registran en el, su propósito a efectos practicos es establecer un puente para poder acceder a los métodos de los objetos remotos. Figura 16: Arquitectura básica RMI En cuanto a los clientes hay que tener en cuenta que no todos sus metodos estarán disponibles de forma remota, si no sólo aquellos marcados para lanzar excepciones re- motas, del tipo java.rmi.RemoteException. Para marcar un método de una clase Java como accesible de forma remota debe, a parte de lanzar las excepciones de tipo Re- moteException antes mencionadas la clase debe implementar un interfaz que extienda Remote, lo que etiqueta el método como accesible remotamente. La secuencia puede verse en la figura 17. Una vez hecho esto la secuencia para acceder a un metodo remoto es: Buscar el registro RMI: Un ejemplo de como se hace esto seria: 42 Icaro Distribuido Registry regCliente = LocateRegistry.getRegistry(ip, puerto); Nótese que esta es solo una forma de hacerlo, se puede omitir el puerto, la ip, o incluso ambos. El puerto RMI reservado oficialmente es el 1099. Obtener el objeto remoto que queramos, por ejemplo, en el caso de Icaro, para pedir un agente: ItfUsoAgenteReactivo agenteRemoto = (ItfUsoAgenteReactivo) regCliente.lookup(nombreAgente); Nótese que el registro RMI devuelve Objetos, lo que hace necesario hacer un casting a la clase que esperamos. Además cuanto pedimos al registro un objeto lo hacemos indicando all registro el nombre con el cual fue registrado el objeto (Ver más adelante como se registran objetos). Figura 17: Ciclo de uso RMI En cuanto al registro de objetos, el procedimiento a seguir es el siguiente: Si no se ha creado el registro RMI, crearlo, por ejemplo, con la siguiente sentencia: int puertoRMI = 1099; /* Puerto por defecto */ Registry registroRMI = LocateRegistry.createRegistry(puertoRMI); Con el registro disponible, registrar los objetos String nombreDeRegistro = "objetoRemotoA"; ItfObjetoRemoto objetoPorRegistrar = new objetoRemoto(); registroRMI.rebind(nombreDeRegistro, objetoPorRegistrar); 43 Icaro Distribuido Nota: Estamos usando el método rebind en lugar de bind, esto sacará del registro a cualquier objeto que pudiera estar registrado previamente Para eliminar un elemento del registro se usa la sentencia: registroRMI.unbind(nombreElemento); 4.3. Implementación de los componentes diseñados Comentaremos aqui los detalles de implementación de los componentes diseñados para implementar las comunicaciones y la distribución, lo referente a la ventana de trazas se tratará en un punto a parte ya que es independiente del resot del desarrollo. También se tratará en un punto a parte un ejemplo de como se puede desarrollar una aplicación distribuida desde cero utilizando las mejoras implementadas en este proyecto. 4.3.1. GestorAplicaciónComunicación Este nuevo gestor se integra para facilitar la comunicación entre agentes y simplificar de esta manera la distribución de los elementos del software. Para la implementación de cualquier aplicación candidata a ser distribuida se recomienda el uso de este gestor para TODAS las comunicaciones, ya que él mismo se encargará de buscar los agentes solicitados y entregarles los mensajes que se les env́ıen. A continuación se detallan algunos elementos de su implementación, el diagrama general de la clase que lo imple- menta puede verse en la figura 18 y sus clases directamente relacionadas en la figura 19. Además puede verse las relaciones completas de esta clase en la figura 8, mostrada anteriormente. Esta clase requiere de las clases de ComunicacionAgentes, ControlRMI y Mensaje. Este gestor es el primero que arrancará después del gestor de organización, esto es necesario para poder utilizar este gestor para las comunicaciones de los gestores de agentes y/o de recursos. Además evita posibles errores en caso de que al arrancar los agentes supervisados por otro gestor estos intenten enviar algún mensaje y se genere una excepción al no encontrar al gestor de comunicaciones. Este gestor implementa dis- tintos métodos para gestionar la comunicaciones, pensados para amoldarse a la manera particular que tengan los desarrolladores para escribir su código fuente, sin embargo se recomienda hacer uso únicamente del método enviar_mensaje, ya que es el más sencillo de entender y el que más transparencia ofrece a los desarrolladores, este méto- do utiliza como mensajes objetos de la clase mensaje, que contiene datos del origen de la comunicación, asi como otros detalles para facilitar su gestión (esta clase se detal- lará más adelante). Nótese que, dado que tanto el gestor como el agente destinatario tienen su propio autómata, y por tanto, su propio conjunto de eventos reconocidos, aunque pretendamos mandar un evento “E1” a un agente cualquiera, este evento de- berá estar encapsulado dentro de otro evento “E2”, diferente, que es el que enviaremos realmente al gestor, por ello se recomienda el uso del método enviar_mensaje, cuyo funcionamiento se detalla a continuación: 44 Icaro Distribuido Figura 18: Diagrama de clase del gestor de comunicaciones public void enviar mensaje(Mensaje p): Este método es el recomendado para la gestión de las comunicaciones, trabaja de forma conjunta con el método private void enviarPaqueteDirecto(Mensaje p), que se encargará de la comunicación efectiva, mien- tras que el primero gestionara la redirección del mensaje. De esta forma, el metodo enviar_mensaje recibe un objeto de la clase mensaje, creado previamente como se explicará mas adelante, y determinará que hacer con el usando el campo tipoMensaje, este campo contendrá un objeto de tipo String que identificará el propósito del mensaje, se ha preferido usar el tipo String sobre los habituales integers para que sea mas fácil mostrar los errores. Hay tres tipos principales de mensajes y según el tipo detectado se realizarán las siguientes redirecciones: TIPO INPUT DESTINO CONOCIDO : La forma básica de comunicación, se us- ará el método “enviarPaqueteDirecto” para hacerlo llegar a su destino. TIPO INPUT A GRUPO : Implementado para simplificar el envio de un mensaje a un grupo de agentes definido durante el desarrollo, al detectar este tipo de men- saje el gestor buscará todos los agentes definidos en la configuración cuyo grupo coincida con el especificado en el campo “destinoDatos” del mensaje, exceptuan- do por supuesto al que ha originado la comunicación. Para hacer esto por cada agente que encuentre creará un clon del mensaje a enviar y lo manipulará para que crea ser un mensaje “normal” con un único destinatario y lo redirigirá a su destino. Para poder usar esta caracteŕıstica, los agentes deberan tener definido su grupo en su lista de propiedades de la forma “grupo” “nombreDeGrupo”, puede consultarse esta funcionalidad con más detalle en los ejemplos que se incluyen en el apartado de validación. TIPO INPUT A LISTA DE AGENTES : Cuando no sepamos los componentes 45 Icaro Distribuido Figura 19: Relaciones de la clase AccionesSemanticasGestorAplicacionComunicaciones de un grupo en tiempo de desarrollo o estos vayan variando mucho podemos hacer uso de este tipo de mensaje, al que pasaremos una lista de destinatarios para que el gestor les haga llegar un mensaje. private void enviarPaqueteDirecto(Mensaje p): Este método es el que se encarga de hacer efectiva la entrega de mensajes, a un único destinatario, primero buscará el destinatario del mensaje en su propio nodo (la maquina donde se esté ejecutando), en caso de no encontrarlo se ocupará de buscarlo en todos los nodos que conozca, es decir, todos aquellos nodos que hayan sido declarados en las propiedades generales de la descripción de la aplicacion (fichero xml). Es posible añadir nuevos nodos en tiempo de ejecución pasándoselos a la configuración existente (Objeto), accesible, por ejemplo, mediante la clase Directorio. Otras formas de comunicación Como hemos dicho el método enviar mensaje es el más recomendado, pero no el único, a continuación vamos a indicar otros métodos para poder enviar mensajes entre agentes. El ejemplo del chat incluido en la parte de validación contiene muchas formas distintas de realizar la comunicación, asi que haremos referencia aqui a dicho ejemplo. Los elementos se listan según el mensaje que debe recibir el gestor de comunicaciones 46 Icaro Distribuido para interpretar los datos pasados correctamente, no el nombre de los métodos que se ejecutan, estos pueden consultarse en el fichero “automata.xml” en el paquete de comportamiento del gestor de comunicaciones. enviar msg a destinatario conocido: Este método y sus demas métodos sobrecar- gados se encargan de enviar mensajes a un destinatario especificado de forma parecida a enviar mensaje, pero especificando los parámetros manualmente. Lo ilustraremos primero con un ejemplo, tomado del fichero AccionesSemanticas- AgenteAplicacionClienteChat.java, de la carpeta aplicaciones del proyecto. Este método requiere la ip del destinatario, luego intentará enviar el mensaje directa- mente, el siguiente método no requiere este información. public void enviarMensaje (String mensaje) { String gestorComunicaciones = NombresPredefinidos. NOMBRE_GESTOR_APLICACION_COMUNICACION; Object [] params = {miIP, mensaje}; Object [] input = {"enviarMensaje", params, nombreAgente, agenteServidor, sala, miIP}; trazar ("Enviando mensaje: " + nombreCliente + ":" + mensaje); ComunicacionAgentes.enviarInput(" enviar_msg_a_destinatario_conocido", input, nombreAgente, gestorComunicaciones); chat.limpiarMensaje(); } En este ejemplo puede verse que es necesario encapsular el mensaje a entregar al destinatario final dentro de otro mensaje, que enviaremos al gestor de comu- nicaciones. Primero encapsulamos los parámetros que deseamos hacer llegar al destinatario final, con la instrucción Object [] params = miIP, mensaje;, esto es, enviamos el mensaje que queremos hacer llegar y nuestra IP como identifi- cador del origen del mensaje. A continuacion encapsulamos el mensaje comple- to que queremos hacer llegar en otro objeto, mediante la instrucción Object [] input = “enviarMensaje”, params, nombreAgente, agenteServidor, sala, miIP, téngase en cuenta que los eventos recibidos son del tipo EventoRecAgente, con- sulte el manual de Icaro si desea sabe más acerca de ellos. Finalmente, teniendo ya el mensaje a enviar al gestor se lo hacemos llegar a traves de un método de la clase estática ComunicaciónAgentes, con el formato apropiado, que es “en- viar msg a destinatario conocido”, como petición al gestor, esto informa al gestor de que es lo que queremos que haga con los datos contenidos en el objeto “input”, finalmente le pasamos la cadena de texto “nombreAgente” como origen de los datos y gestorComunicaciones como destinatario, ya que ComunicacionAgentes no tiene sino otra forma de saber donde debe entregar el mensaje. enviar msg al aire: Se comporta de forma parecida al enterior con una importante salvedad, no necesita que se le indique donde se encuentra el destinatario (aunque si tendremos que indicarle quien), sino que se encargará él mismo de buscar el destino, el método que se ejecutará es “enviar input entre gestores(...)”, éste primero intentará buscar el destinatario entre los agentes locales a él mismo, es decir, que están ejecutando dentro de su misma máquina virtual, en caso de encontrarlo en este contexto enviará directamente el mensaje y esperará un nuevo mensaje que entregar. En caso contrario sacará la descripción del agente 47 Icaro Distribuido destinatario y buscará en que nodo se ha indicado que debe ejecutarse, si lo hay, con este dato utiliza la clase controlRMI para enviar el input remoto al destinatario final del mensaje. Un ejemplo de uso seŕıa el siguiente: public void enviarMensaje (String mensaje) { String gestorComunicaciones = NombresPredefinidos. NOMBRE_GESTOR_APLICACION_COMUNICACION; Object [] params = {miIP, mensaje}; /* Este es el mensaje que debe procesar el gestor */ Object [] input = {"enviarMensaje", params, nombreAgente, nombreServidor}; trazar ("Enviando mensaje: " + nombreCliente + ":" + mensaje); /* Esto es lo que llega al gestor */ ComunicacionAgentes.enviarInput("enviar_msg_al_aire", input, nombreAgente, gestorComunicaciones); chat.limpiarMensaje(); } busquedaLocalSinRespuesta: Este método se utiliza de forma análoga a Comu- nicacionAgentes, envia un mensaje a otro agente local (del mismo nodo). Un ejemplo de uso seŕıa el siguiente: String mensaje = "estoyListo"; Object [] parametros = {"noHayProblemas",0}; ComunicacionAgentes.enviarInput("busquedaLocalSinRespuesta", mensaje, parametros, nombreAgente, gestorComunicaciones, ipOrigen, ipDestino); busquedaLocalConRespuesta: Es mensaje sirve para indicar que debemos entregar un mensaje localmente, pero que el origen es remoto y esta esperando que le in- diquemos que ha ocurrido con el mensaje. Primero intentará entregar el mensaje local, y a continuación consultará el origen del mensaje e intentará enviar una respuesta al origen del mensaje. Las respuestas enviadas seran mensajes de tipo ‘eventoAceptado” en caso de éxito y “eventoRechazado” en caso de fallo, ambos sin parámetros. Su uso es idéntico al anterior, cambiando únicamente el texto del mensaje enviado al gestor de “busquedaLocalSinRespuesta” a “busquedaLo- calConRespuesta”. Para que la respuesta tenga se env́ıe correctamente hay que ajustar correctamente el origen y la ipOrigen del mensaje, además con esto se pueden desviar las respuestas a un destinatario diferente al origen real de los mensajes, para poder gestionar a parte los sucesos en las comunicaciones. Otros metodos : Existen otros métodos para enviar mensajes entre agentes, pero no requieren del gestor de comunicaciones, ver las secciones “ComunicacionAgentes” para envio de mensajes locales y “ControlRMI” para los remotos, más adelante en este mismo caṕıtulo. 4.3.2. Mensaje Esta clase implementa los objetos tipo mensaje que se han mencionado en el aparta- do anterior, básicamente sirven para englobar los datos que se quieran enviar, y se encargan de recoger algunos datos extra de información acerca del origen del mensaje. 48 Icaro Distribuido Existen múltiples métodos para crear mensajes y modificar sus datos, además se in- cluyen métodos para crear automáticamente los tipos de mensajes más comunes para implementar la comunicación entre agentes reactivos de Icaro. De esta forma, se indica a continuación las acciones más comunes y como crear (y enviar), los mensajes t́ıpicos usando mensajes. Puede verse una descripcion de la clase mensaje completa en la figura 20, mientras que las clases que dependen de ella pueden verse en la figura 19. Figura 20: Diagrama de la clase Mensaje Enviar un mensaje a un agente: El más habitual, crearemos un mensaje que contenga un evento para un agente, asi como los parametros que pudieran ser necesarios, si los hay, el método para crear un mensaje de este tipo es crearInput- Basico, a continuación se indica un ejemplo de su uso, nótese sin embargo que este método admite un número variable de parámetros, el primero de los cuales DEBE ser el nombre dele evento que deseamos hacer llegar (Ejemplo correspondiente al ejemplo chat del apartado Validación): /* Primera forma: utilizando comunicacionAgentes */ Mensaje p; p = Mensaje.crearInputBasico( nombreAgente, agenteServidor, "peticionConexion", nombreCliente, miIP, nombreAgente ); /* Le pido a comunicacion agentes que envie el mensaje a mi gestor */ ComunicacionAgentes.enviarInput( "enviar_mensaje", p, nombreAgente, gestorComunicaciones); 49 Icaro Distribuido También se puede obviar el paso de enviarInput al gestor si se usa el método enviarMensaje(Mensaje p), incluido en las acciones semánticas existentes por defecto en cualquier tipo de agente, quedando el código asi: /* Segunda forma: utilizando metodo incluido */ Mensaje p = Mensaje.crearInputBasico( nombreAgente, agenteServidor, "peticionConexion", nombreCliente, miIP, nombreAgente ); enviarMensaje(p); Enviar un mensaje a un grupo: Cuando el destino es un grupo de agentes descrito en la descripción de la aplicación, podemos crear el mensaje de la forma siguiente (Ejemplo correspondiente al ejemplo MasterIA, del apartado de Validación) /* Segunda forma: utilizando metodo incluido */ Mensaje p = Mensaje.crearInputParaGrupo( nombreAgente, "ROBOTS", mensaje, parametro1 ); enviarMensaje(p); Enviar un mensaje a una lista: Cuando queramos enviar un mismo mensaje a un grupo de agentes no definido previamente, usaremos este método, que difiere un poco de los demas, ya que primero se crea un mensaje normal y después se le indica su nuevo cometido (destinatarios), un ejemplo seria: Mensaje p = Mensaje.crearInputBasico( nombreAgente, "", "peticionConexion", nombreCliente, miIP, nombreAgente); /* Ponemos lista de destinatarios, aqui solo 2, pero puede ser cualquier numero*/ p.setListaDestinatarios (destinatario1, destinatario2); enviarMensaje(p); Nótese que el método setListaDestinatarios admite un número variable de parámet- ros, y que cualquier destinatario que pudieramos haber establecido previamente durante la creación del mensaje sera ignorado, a menos que volvamos a incluirlo dentro de los parametros del método setListaDestinatarios. 4.3.3. Comunicación Agentes Esta clase está pensada meramente para hacer un poco más transparente el envio de mensajes a un agente (sin usar el gestor), contiene métodos estáticos, es decir, que no es necesario instanciar un objeto de esta clase para usar sus métodos, no es necesario usarla directamente si se utiliza el método sugerido con anterioridad (uso de mensajes), sin embargo no debe eliminarse, ya que el gestor de comunicaciones depende de ella. El ejemplo del chat incluido en el apartado de validación incluye muchos ejemplos de como se utiliza esta clase, en cualquier caso, un ejemplo sencillo seria el siguiente (ya puesto anteriormente): /* Primera forma: utilizando comunicacionAgentes */ 50 Icaro Distribuido Mensaje p = Mensaje.crearInputBasico(nombreAgente, agenteServidor, " peticionConexion", nombreCliente, miIP, nombreAgente); // Le pido a comunicacion agentes que envie el mensaje a mi gestor ComunicacionAgentes.enviarInput("enviar_mensaje", p, nombreAgente, gestorComunicaciones); Nótese que los metodos de esta clase no admiten un número variable de parámetros, lo que puede obligar a incluir los parámetros dentro de un objeto previamente a enviar el mensaje, como, por ejemplo, en el método enviarMensaje, incluido en el fichero AccionesSemanticasAgenteAplicacionClienteChat, que reproducimos a continuación: Object [] params = {miIP, mensaje}; Object [] input = {"enviarMensaje", params, nombreAgente, agenteServidor, sala, miIP}; trazar ("Enviando mensaje: " + nombreCliente + ":" + mensaje); ComunicacionAgentes.enviarInput("enviar_msg_a_destinatario_conocido", input, nombreAgente, gestorComunicaciones); 4.3.4. Control RMI De forma análoga a ComunicacionAgentes, ControlRMI contiene un conjunto de métodos estáticos para ayudar a simplificar el uso de RMI, no es necesario usar esta clase en absoluto si se utiliza el gestor de comunicaciones, pero debe tenerse en cuenta que el gestor de comunicaciones, asi como otros gestores, como por ejemplo el gestor de organizacion, si utilizan esta clase para realizar distintas tareas, algunas de ellas durante el arranque o parada del sistema, por lo que no debe eliminarse aunque no se piense utilizar. Los métodos que ofrece son los siguientes: public static boolean startRMI(): Se encarga de crear, si es necesario, un nuevo registro en el puerto 1099, si este no se ha modificado previamente a realizar la llamada a este método. Cabe destacar que esta llamada provacará un intento por parte de controlRMI de añadir un icono a la barra de tareas, si se trata de un entorno windows, para indicar que se ha activado RMI, pulsando sobre el icono se obtendrá un menu con la lista de objetos registrados en RMI, ademas se tendra la opcion de cerrar RMI, lo que provocara que TODOS los elementos se eliminen del registro RMI (lo que no los elimina de la maquina virtual), final- mente desaparecerá el icono que indica que RMI esta activo. Para hacer pruebas a un sistema pueden añadirse acciones a realizar si se selecciona algún elemen- to del menu que proporciona, esto puede hacerse modificando la clase interna MenuItemIcaro, contenida en el mismo fichero que controlRMI. setPuertoRMI(int puerto): Cambia el puerto donde debe crearse el registro RMI. Esta caracteŕıstica debe usarse con sumo cuidado, ya que el puerto que esta marcado por defecto, el 1099 esta reservado de forma oficial para el servicio RMI, y por lo tanto muchas aplicaciones, e incluso parte de la API de Java solo consideran este puerto como válido, lo que puede provocar fallos dif́ıciles de depurar si se modifica. 51 Icaro Distribuido public static boolean export(String element, Remote obj): Exporta un objeto, lo que equivale a registrar el objeto “obj” en el registro RMI bajo el identificador “element” public static boolean fire(String element): “despide” un objeto del registro, esto elimina la asociacion con el objeto que existe en la maquina virtual, pero no lo elimina. public static boolean fireAll (): Parecido a fire, solo que este método eliminara to- das las asociaciones que hubiera en RMI, limpiandolo por completo. Este es otro método que debe usarse con cuidado, ya que el registro RMI puede estar com- partido por varias aplicaciones, lanzar este método puede provocar inestabilidad en otras aplicaciones. public static void createTray(): Crea el icono para la bandeja de entrada explicado con anterioridad. protected static Image createImage(String path, String description): Se encarga de crear la imagen que se usa en el icono para la barra de tareas. public static String getIPLocal (): Devuelve la dirección IP de la máquina en que se ejecuta private static class MenuItemIcaro extends MenuItem: Esta clase privada se en- carga de implementar los elementos que se mostrarán en el menú activado desde el icono creado en la barra de tareas, contiene un ActionListener, activado cuan- do se pulsa sobre el elemento que representa, y que puede modificarse para que realize multiples acciones, por defecto eliminar el agente de RMI. public static ItfUsoAgenteReactivo buscarAgenteRemoto(String ip, String nom- breAgente): Este método se encarga de buscar un agente registrado con el identi- ficador “nombreAgente” en la dirección ip especificada, que puede ser la misma en que se ejecuta. De encontrarlo, devolverá una referencia con un interfaz ItfU- soAgenteReactivo, que podrá usarse para acceder a los métodos marcados como remotos previamente (Ver capitulo acerca de RMI, previamente en este manual), en otro caso devolverá null. Este método tiene otro más sobrecargado, al que tambien se le puede indicar el puerto donde estará escuchando el registro RMI del otro extremo, pero por las mismas razones explicadas antes sobre el cambio del puerto RMI, no se aconseja utilizar esta opción. public static boolean enviarInputRemoto(String input, Object[] param, String nom- breRecurso, ItfUsoAgenteReactivo remoto): Una vez obtenido un interfaz de uso de agente válido, puede usarse este método u otro de los demas métodos sobrecar- gados sobre este, para enviar un mensaje de forma remota, de la misma manera que se hacia mediante la clase estática ComunicacionAgentes. 4.3.5. Gestor Nodo Este gestor arranca de manera diferente al resto de descripciones, gestor nodo es capaz de arrancar por si mismo, sin necesidad de lanzar primero un gestor de organi- zación, ni tampoco necesita un fichero de descripcion xml que le diga lo que tiene que 52 Icaro Distribuido hacer. Esto se hace debido a que su funcionalidad es muy sencilla y a que normalmente es un proceso que queremos tener en espera de que se le indique que se desea realizar alguna tarea, o lo que es lo mismo, que se le indique que aplicación icaro-d se desea arrancar. Para realizar su trabajo, el nodo (máquina) donde se arranca este gestor debe disponer de todo lo necesario para lanzar sus aplicaciones por si mismo, ya que la única información que le va a llegar para iniciar su trabajo es el nombre de la descripción de aplicación que debe ejecutarse, por lo que debe disponer localmente tanto de los ficheros de descripción xml como del código fuente necesario. Existen dos formas de pedir el arranque remoto, arrancarAplicacion, que lanza el resto de elementos dentro de la misma maquina virtual donde esta ejecutándose el gestor de nodo, y executeApp, que lanzará un proceso separado para la aplicación solicitada. El efecto diferenciador es que en el primer caso cerrar la aplicación finaliza también el gestor del nodo, mientras que en la segunda el gestor es capaz de sobrevivir a la aplicación que ha lanzado. Para lanzar un gestorNodo se debe ejecutar icaro-d con la opción -nodo, indiferente a mayúsculas o minúsculas. 4.4. Implementación de las trazas Para nuestro proyecto hemos diseñado una nueva visualización de las trazas que creemos que mejora la anterior versión. Primero comentaremos su implementación. 4.4.1. Detalles de implementacion La anterior versión de las trazas estaba implementada en su totalidad en el paquete imp de icaro/infraestructura/recursosOrganizacion/recursoTrazas. En este paquete se incluyen la claseGeneradora, la gui y todo lo necesario para el buen funcionamiento del componente. La nueva versión de las trazas se encuentran en el paquete imp2 en la misma ruta anteriormente dada. Como se ve en la imagen, el paquete consta de Tabs para implementar cada uno de los paneles del JTabbedPane que más tarde comentaremos, componentes para im- plementar la tabla de las trazas a mostrar, el recursoTrazasImp2 que hereda de la claseGeneradora, y la ventanaTrazas que contiene la implementación de la visualización y usa tanto Tabs como componentes. Nota: la claseGeneradora es la misma que en la versión anterior; es decir, para usarla habrá que importarla del paquete imp: La localizacion de la version previa del recurso de trazas es la siguiente: import icaro.infraestructura.recursosOrganizacion.recursoTrazas .imp.ClaseGeneradoraRecursoTrazas; 53 Icaro Distribuido Figura 21: Jerarquia del paquete de trazas 4.4.2. Uso de la nueva implementacion Como primer paso, hay que señalar que el recurso de las trazas se crea en las clases generadoras de organización, ArranqueSistemaConCrtlGestorO y ArranqueSistemaSi- nAsistente. En estas dos clases, se hace la llamada a la clase generadora del recurso de trazas de la siguiente forma: ItfUsoRecursoTrazas recursoTrazas = ClaseGeneradoraRecursoTrazas.instance(); Este método devuelve una instancia de la visualización que queremos usar de la siguiente manera: instance = new RecursoTrazasImp2( NombresPredefinidos.RECURSO_TRAZAS); Es en el punto recién descrito donde el usuario podrá cambiar la versión de la visual- ización que quiera usar. NOTA: en el código fuente se puede observar que la creación de RecursoTrazasImp está comentado. 4.4.3. Nueva visualizacion En este apartado describiremos el uso de las nuevas trazas mediante capturas de pantalla. La principal diferencia entre estas trazas y las anteriores reside en que nosotros hemos separado las trazas de agentes, recursos y gestores, en pestañas distintas. En la actualidad, la pestaña Diagrama Temporal está sin implementar. Además, mostramos en todo momento en cada una de ellas en un panel lateral una lista de los componentes de cada clase dependiendo de la pestaña en la que nos encontremos. 54 Icaro Distribuido Figura 22: Cabecera de la ventana de trazas Figura 23: Ventana de trazas Si selecccionamos uno de los componentes del panel lateral, se mostrarán sólo las trazas de dicho componente, usando de forma automática el filtro “Filtrar Filas” que hemos incorporado a la visualización como una herramienta adicional. Este filtro po- drá ser usado por el usuario para buscar lo que quiera en las trazas de manera rápida y sencilla. Si el usuario quiere visualizar las trazas de un sólo componente en una ventana auxiliar sólo tendrá que hacer doble click sobre uno de los componentes del panel lateral, y aparecerá una ventana como esta: Ahora, la información que aparece en cada traza es la siguiente: Emisor (el compo- nente que env́ıa la traza) , Nivel (debug,info,error) , Mensaje (el contenido de la traza) y Recepción (momento exacto de llegada de la traza). Nota: Como se ve en la figura las columnas están más compactas para que cupiera la imagen en el documento. Esta opción es muy útil ya que permite al usuario ver las trazas a su antojo ajustando el tamaño de las trazas al mensaje mostrado. Por esta razón, aconsejamos no excederse en el tamaño del mensaje de la traza, ya que si se llega al tamaño máximo no se podrá mostrar. Otro detalle que hemos añadido a la visualización es que al seleccionar una traza, aparecerá en la parte inferior del panel la información del mensaje seleccionado. Esto 55 Icaro Distribuido Figura 24: Visualizacion de las trazas de un componente en una ventana a parte Figura 25: Columnas de la ventana de trazas puede ser útil si el tamaño de la traza es excesivamente grande: Hemos añadido también la utilidad de guardar las trazas en un fichero de texto en el menú Arrchivo en la parte superior izquierda del panel. Se puede seleccionar guardar todas las trazas o lo de un sólo componente a elegir. En cuanto al botón “Terminar” en la parte inferior del panel, explicaremos a contin- uación lo que hace y cómo lo hace. Al hacer click sobre este botón, se cerrarán TODAS la ventanas y aplicaciones abiertas con Icaro. Esto ocurre porque en la implementa