PROYECTO FINAL DE CARRERA SISTEMAS DISTRIBUIDOS DE CÁLCULO INTENSIVO Ponente: Sergio Gómez Alumno: Carmelo Aguilar García E.T.I.S. Septiembre 2005 1 1.- INTRODUCCIÓN Y OBJETIVOS 1.1.- INTRODUCCIÓN Actualmente el uso de programas informáticos para la investigación y resolución de problemas es algo normal, de echo muchas investigaciones no serían posibles sin un programa informático capaz de computar cualquier problema infinitamente más rápido que un ser humano normal... Aún así algunas investigaciones, por su complejidad requieren una potencia de cálculo mucho mayor que la que puede ofrecer el mejor superordenador que podamos imaginar... Es por eso que se ideó la “computación distribuida”, capaz de resolver problemas de computación masiva utilizando un gran número de ordenadores organizados en racimos incrustados en una infraestructura de telecomunicaciones distribuida.. como por ejemplo podría ser Internet. 1.2.- OBJETIVOS El objetivo de este proyecto es crear un programa Servidor-Cliente capaz de gestionar y llevar a cabo un proyecto-investigación de estas características. Es decir un Servidor que sea capaz de administrar toda la información que genere nuestro proyecto, tales como clientes registrados, trabajos disponibles, trabajos asignados, trabajos completados, así como ser capaz de corregir posibles fallos que impidan el correcto funcionamiento de dicho Servidor. Y un Cliente capaz de hacer peticiones al Servidor y además aprovechar la capacidad de procesamiento del ordenador remoto, conectado a cualquier punto de la red global, en que esté instalado para computar-procesar una aplicación con un coste de CPU demasiado elevado como para que pueda realizarse en un solo ordenador. Así pues crearemos nuestro propio proyecto de investigación que utilice la computación distribuida como herramienta de trabajo. Para que el Cliente pueda interactuar con el Servidor y realizar así su trabajo utilizaremos la tecnología RMI (Remote Method Invocation) que permite realizar llamadas a funciones de forma remota, es invocar funciones que se encuentran en otro ordenador. Así pues nuestro programa Servidor-Cliente tendrá las siguientes tareas.: El Servidor será el administrador de toda la información necesaria para el correcto funcionamiento de nuestra investigación. Es decir será el encargado de: Enviar los archivos disponibles a los clientes, asignar los archivos a los clientes, recibir los archivos computados de los clientes, guardar los archivos ya completados, controlar que un archivo no tarde demasiado en ser procesado, mantener una política de orden de envío de trabajos a partir de su prioridad, añadir nuevos archivos para analizar, dar de alta a nuevos clientes, llevar un registro “log” de los incidentes o sucesos que se puedan registrar a lo largo del día, borrar archivos de análisis o analizados que estén dañados, recuperar archivos perdidos a partir de copias de seguridad, avisar al administrador de que se ha producido un error critico, y sobretodo mantener toda esta información accesible en todo momento para que el administrador pueda hacer uso de ella, para ello utilizaremos una Base de Datos donde almacenaremos toda esta información, y una Interface gráfica lo suficientemente elocuente y clara para poder manejar todos estos datos. El trabajo del Cliente consistirá en: Descargar el fichero que le envíe el Servidor, analizar los datos (es decir aplicar sobre los datos nuestro programa de cálculo intensivo), y una vez acabado el análisis, enviar los datos obtenidos al programa Servidor para su almacenamiento. Todo ello debe poder realizarse sin que el usuario Cliente tenga que prestar ninguna a la aplicación, a no ser que el mismo usuario lo desee por cuestión de simple curiosidad, o para comprobar que esta realizando su ordenador. Una vez que nuestro Servidor-Cliente sea consistente y robusto, procederemos a crear una aplicación de calculo intensivo que se pueda ejecutar aprovechando la Interface que crea el cliente. Este programa debería ser independiente del cliente, es decir, que pudiéramos ejecutar cualquier programa desde el cliente sin tener que variar su código. 2 2.- ANTECEDENTES 2.1.- COMPUTACIÓN DISTRIBUIDA La computación distribuida o computación en grilla es un nuevo modelo para resolver problemas de computación masiva utilizando un gran número de ordenadores organizados en racimos incrustados en una infraestructura de telecomunicaciones distribuida. La informática en grilla consiste en compartir recursos heterogéneos (basadas en distintas plataformas, arquitecturas de equipos y programas, lenguajes de programación, etc...), situados en distintos lugares y pertenecientes a diferentes dominios de administración sobre una red que utiliza estándares abiertos. Dicho brevemente, consiste en virtualizar los recursos informáticos. Es decir crear un gigantesco ‘ordenador virtual’ capaz de una potencia de computación inimaginable. La computación distribuida o computación en grilla ha sido diseñada para resolver problemas demasiado grandes por cualquier simple superordenador, mientras mantiene la flexibilidad de trabajar en múltiples problemas más pequeños. Por tanto, la computación en grilla es naturalmente un entorno multi-usuario; debido a esta razón, las técnicas de autorización segura son esenciales para permitir que los recursos informáticos sean controlados por usuarios remotos (distantes). Este modelo de computación permite disponer de redes de ordenadores dedicados al análisis de datos que requieran una gran potencia de cómputo. Un ejemplo lo podemos encontrar en el proyecto BOINC (Berkeley Open Infrastructure for Network Computing), una plataforma de propósito general para proyectos de computación distribuida, que permite compartir el tiempo de sus contribuyentes con otros proyectos. Ciclos de CPU libres, ese es el concepto, mientras lees tu correo tu CPU no trabaja, pero puede contribuir al análisis de datos científicos. Desde cualquier ordenador personal se puede contribuir a cualquier proyecto de investigación científica basado en la tecnología BOINC. Únicamente es necesario bajarse el software BOINC y elegir uno de los proyectos disponibles: Algunos ejemplos de estos proyectos son: - Climateprediction.net → Estudia el cambio climático. - Einstein@home → Búsqueda de signos gravitacionales provenientes de pulsars. - SETI@home → Búsqueda de señales de radio que evidencien vida extraterrestre. - ... 3 2.2.- SETI@home Un ejemplo de estos proyectos es como ya hemos dicho SETI@home basado en el proyecto radio SETI: Radio SETI, usa radiotelescopios para escuchar señales de radio en banda estrecha provenientes del espacio. Éstas señales se sabe que no ocurren naturalmente, por lo que su detección sería la evidencia de una tecnología extraterrestre. Las señales de los radiotelescopios consisten fundamentalmente en ruidos (provenientes de fuentes celestiales y de la electrónica del receptor) y señales producidas por el hombre como las de estaciones de televisión, radares y satélites. Los proyectos modernos de radio SETI analizan éstos datos digitalmente aplicando diferentes operaciones tales como transformadas de fourier, gausianas, búsqueda de pulsos, deriva de Doppler... Una mayor potencia de cálculo permite que la búsqueda cubra un mayor rango de frecuencias con más sensibilidad. Es por eso que radio SETI, necesita una increíble potencia de cálculo. El modelo de computación de ciclos redundantes, también conocido como computación zombi, es el empleado por esta aplicación, consistente en que un servidor o grupo de servidores distribuyen trabajo de procesamiento a un grupo de computadoras voluntarias a ceder capacidad de procesamiento no utilizada. Básicamente, cuando dejamos nuestro ordenador encendido, pero sin utilizarlo, la capacidad de procesamiento se desperdicia por lo general en algún protector de pantalla, este tipo de procesamiento distribuido utiliza nuestra computadora cuando nosotros no la necesitamos, aprovechando al máximo la capacidad de procesamiento. 2.3.- APLICACIÓN SERVIDOR-CLIENTE La arquitectura servidor-cliente llamado modelo cliente-servidor o servidor-cliente es una forma de dividir y especializar programas y equipos de computo a fin de que la tarea que cada uno de ellos realiza se efectúe con la mayor eficiencia, y permita simplificar las actualizaciones y mantenimiento del sistema. En esta arquitectura la capacidad de proceso está repartida entre el servidor y los clientes. En la funcionalidad de un programa distribuido se pueden distinguir 3 capas o niveles: 1. Manejador de Base de Datos (Nivel de almacenamiento), 2. Procesador de aplicaciones o reglas del negocio (Nivel lógico) 3. Interface del usuario (Nivel de presentación) En una arquitectura monolítica no hay distribución; los tres niveles tienen lugar en el mismo equipo. En un comienzo, los mainframes (ordenadores centrales) concentraban la funcionalidad de almacenamiento (#1) y lógica (#2) y a ellos se conectaban terminales tontas (teclado + pantalla), posiblemente ubicadas en sitios remotos. En el modelo cliente-servidor, en cambio, el trabajo se reparte entre dos ordenadores. De acuerdo con la distribución de la lógica de la aplicación hay dos posibilidades: 1. Cliente delgado: si el cliente solo se hace cargo de la presentación. 2. Cliente pesado: si el cliente asume también la lógica del negocio. En la actualidad se suele hablar de arquitectura de tres niveles, donde la capa de almacenamiento y la de aplicación se ubican en (al menos) dos servidores diferentes, conocidos como servidores de datos y servidores de aplicaciones. Ventajas de la arquitectura cliente-servidor • El servidor no necesita tanta potencia de procesamiento, parte del proceso se reparte con los clientes. • Se reduce el tráfico de red considerablemente. Idealmente, el cliente se conecta al servidor cuando es estrictamente necesario, obtiene los datos que necesita y cierra la conexión dejando la red libre. 4 3.- TECNOLOGÍAS UTILIZADAS: 3.1.- JAVA Sun Microsystems es quien ha desarrolló el lenguaje Java, en un intento de resolver simultáneamente todos los problemas que se planteaban a los desarrolladores de software por la proliferación de arquitecturas incompatibles, tanto entre las diferentes máquinas como entre los diversos sistemas operativos y sistemas de ventanas que funcionaban sobre una misma máquina, añadiendo la dificultad de crear aplicaciones distribuidas en una red como Internet. Características de Java - Simple Java ofrece toda la funcionalidad de un lenguaje potente, pero sin las características menos usadas y más confusas de éstos. Java elimina muchas de las características de otros lenguajes como C++, para mantener reducidas las especificaciones del lenguaje y añadir características muy útiles como el garbage collector (reciclador de memoria dinámica. - Orientado a objetos Java trabaja con sus datos como objetos y con interfaces a esos objetos. Soporta las tres características propias del paradigma de la orientación a objetos: encapsulación, herencia y polimorfismo. - Distribuido Java se ha construido con extensas capacidades de interconexión TCP/IP. Existen librerías de rutinas para acceder e interactuar con protocolos como http y ftp. Java en sí no es distribuido, sino que proporciona las librerías y herramientas para que los programas puedan ser distribuidos. - Robusto Java realiza verificaciones en busca de problemas tanto en tiempo de compilación como en tiempo de ejecución. Además, para asegurar el funcionamiento de la aplicación, realiza una verificación de los byte-codes, que son el resultado de la compilación de un programa Java. Es un código de máquina virtual que es interpretado por el intérprete Java. - Arquitectura neutral Para establecer Java como parte integral de la red, el compilador Java compila su código a un fichero objeto de formato independiente de la arquitectura de la máquina en que se ejecutará. Cualquier máquina que tenga el sistema de ejecución (run-time) puede ejecutar ese código objeto, sin importar en modo alguno la máquina en que ha sido generado. - Seguro 5 El código Java pasa muchos tests antes de ejecutarse en una máquina. El código se pasa a través de un verificador de byte-codes que comprueba el formato de los fragmentos de código y aplica un probador de teoremas para detectar fragmentos de código ilegal -código que falsea punteros, viola derechos de acceso sobre objetos o intenta cambiar el tipo o clase de un objeto. - Portable Más allá de la portabilidad básica por ser de arquitectura independiente, Java implementa otros estándares de portabilidad para facilitar el desarrollo. Java construye sus interfaces de usuario a través de un sistema abstracto de ventanas de forma que las ventanas puedan ser implantadas en entornos Unix, Pc o Mac. - Interpretado El intérprete Java (sistema run-time) puede ejecutar directamente el código objeto. Enlazar (linkar) un programa, normalmente, consume menos recursos que compilarlo, por lo que los desarrolladores con Java pasarán más tiempo desarrollando y menos esperando por el ordenador. - Multithreaded Al ser multithreaded (multihilvanado, en mala traducción), Java permite muchas actividades simultáneas en un programa. El beneficio de ser multithreaded consiste en un mejor rendimiento interactivo y mejor comportamiento en tiempo real. - Dinámico Java no intenta conectar todos los módulos que comprenden una aplicación hasta el tiempo de ejecución. Las librería nuevas o actualizadas no paralizarán las aplicaciones actuales (siempre que mantengan el API anterior). 3.2.- RMI El sistema de Invocación Remota de Métodos (RMI) de Java permite a un objeto que se está ejecutando en una Máquina Virtual Java (VM) llamar a métodos de otro objeto que está en otra VM diferente. Las aplicaciones RMI normalmente comprenden dos programas separados: un servidor y un cliente. Una aplicación servidor típica crea un montón de objetos remotos, hace accesibles unas referencias a dichos objetos remotos, y espera a que los clientes llamen a estos métodos u objetos remotos. Una aplicación cliente típica obtiene una referencia remota de uno o más objetos remotos en el servidor y llama a sus métodos. RMI proporciona el mecanismo por el que se comunican y se pasan información del cliente al servidor y viceversa. Cuando es una aplicación algunas veces nos referimos a ella como Aplicación de Objetos Distribuidos. Las aplicaciones de objetos distribuidos necesitan. Localizar Objetos Remotos Puede registrar sus objetos remotos con la facilidad de nombrado de RMI rmiregistry. O puede pasar y devolver referencias de objetos remotos como parte de su operación normal. Comunicar con Objetos Remotos Los detalles de la comunicación son manejados por el RMI, para el programador, la comunicación remota se parecerá a una llamada estándar a un método Java. Cargar Bytecodes para objetos que son enviados. Como RMI permite al llamador pasar objetos Java a objetos remotos, RMI proporciona el mecanismo necesario para cargar el código del objeto, así como la transmisión de sus datos. 6 La siguiente ilustración muestra una aplicación RMI distribuida que utiliza el registro para obtener referencias a objetos remotos. El servidor llama al registro para asociar un nombre con un objeto remoto. El cliente busca el objeto remoto por su nombre en el registro del servidor y luego llama a un método. Esta ilustración también muestra que el sistema RMI utiliza una servidor Web existente para cargar los Bytecodes de la clase Java, desde el servidor al cliente y desde el cliente al servidor, para los objetos que necesita. Ventajas de la Carga Dinámica de Código Una de las principales y únicas características de RMI es la habilidad de descargar los bytecodes (o simplemente, código) de una clase de un objeto si la clase no está definida en la máquina virtual del receptor. RMI pasa los objetos por su tipo verdadero, por eso el comportamiento de dichos objetos no cambia cuando son enviados a otra máquina virtual. Una aplicación distribuida construida utilizando RMI de Java, al igual que otras aplicaciones Java, está compuesta por interfaces y clases. Los interfaces definen métodos, mientras que las clases implementan los métodos definidos en los interfaces. Los objetos que tienen métodos que pueden llamarse por distintas máquinas virtuales son los objetos remotos. Un objeto se convierte en remoto implementando un interface remoto. • Un interface remoto desciende del interface java.rmi.Remote. • Cada método del interface declara que lanza una java.rmi.RemoteException además de cualquier excepción específica de la aplicación. El RMI trata a un objeto remoto de forma diferente a como lo hace con los objetos noremotos cuando el objeto es pasado desde una máquina virtual a otra. En vez de hacer una copia de la implementación del objeto en la máquina virtual que lo recibe, RMI pasa un stub para un objeto remoto. El stub actúa como la representación local o proxy del objeto remoto y básicamente, para el llamador, es la referencia remota. El llamador invoca un método en el stub local que es responsable de llevar a cabo la llamada al objeto remoto. Un stub para un objeto remoto implementa el mismo conjunto de interfaces remotos que el objeto remoto. Esto permite que el stub sea tipado a cualquiera de los interfaces que el objeto remoto implementa. Sin embargo, esto también significa que sólo aquellos métodos definidos en un interface remoto están disponibles para ser llamados en la máquina virtual que lo recibe. 7 3.3.- SWING Para explicar Swing, explicaremos antes que es AWT. AWT es la biblioteca de clases Java para el desarrollo de Interfaces de Usuario Gráficas. La versión del AWT es la parte más débil de todo lo que representa Java como lenguaje. El entorno que ofrece es demasiado simple, no se han tenido en cuenta las ideas de entornos gráficos novedosos. Javasoft, en vista de la precariedad de que hace gala el AWT, y para asegurarse que los elementos que desarrolla para generar interfaces gráficas sean fácilmente transportables entre plataformas, se ha unido con Netscape, IBM y Lighthouse Design para crear un conjunto de clases que proporcionen una sensación visual agradable y sean más fáciles de utilizar por el programador. Esta colección de clases son las Java Foundation Classes (JFC), que están constituidas por cinco grupos de clases, al menos en este momento: AWT, Java 2D, Accesibilidad, Arrastrar y Soltar y Swing. AWT, engloba a todos los componentes del AWT que existían en la versión 1.1.2 del JDK y en los que se han incorporado en versiones posteriores: • Java 2D • Accesibilidad • Arrastrar y Soltar (Drag and Drop), son clases en las que se soporta Glasgow, que es la nueva generación de los JavaBeans • Swing, es la parte más importante y la que más desarrollada se encuentra. Ha sido creada en conjunción con Netscape y proporciona una serie de componentes muy bien descritos y especificados de forma que su presentación visual es independiente de la plataforma en que se ejecute el applet o la aplicación que utilice estas clases. Swing simplemente extiende el AWT añadiendo un conjunto de componentes, JComponents, y sus clases de soporte. La estructura básica del AWT se basa en Componentes y Contenedores. Estos últimos contienen Componentes posicionados a su respecto y son Componentes a su vez, de forma que los eventos pueden tratarse tanto en Contenedores como en Componentes, corriendo por cuenta del programador el encaje de todas las piezas, así como la seguridad de tratamiento de los eventos adecuados. Con Swing se va un paso más allá, ya que todos los JComponentes son subclases de Container, lo que hace posible que widgets Swing puedan contener otros componentes, tanto de AWT como de Swing. Cuando se empieza a utilizar Swing, se observa que JavaSoft ha dado un gran paso adelante respecto al AWT. Ahora los Componentes del interfaz gráfico son Beans y utilizan el nuevo modelo de Delegación de Eventos de Java. Swing proporciona un conjunto completo de Componentes, todos ellos lightweight, ya no se usan componentes "peer" dependientes del sistema operativo, y además, Swing está totalmente escrito en Java. Todo ello nos aporta una mayor funcionalidad en manos del programador, y en la posibilidad de mejorar en gran medida la cosmética de los interfaces gráficos de usuario. Son muchas las ventajas que ofrece el uso de Swing. Por ejemplo, la navegación con el teclado es automática, cualquier aplicación Swing se puede utilizar sin ratón, sin tener que escribir ni una línea de código adicional. Las etiquetas de información, o "tool tips", se pueden crear con una sola línea de código. Además, Swing aprovecha la circunstancia de que sus Componentes no están renderizados sobre la pantalla por el sistema operativo para soportar lo que llaman "pluggable look and feel", que la apariencia de la aplicación se adapta dinámicamente al sistema operativo y plataforma en que esté corriendo. Los Componentes Swing no soportan el modelo de Eventos de Propagación, sino solamente el modelo de Delegación incluido desde el JDK 1.1; por lo tanto, si se van a utilizar componentes Swing, se debe programar exclusivamente en el nuevo modelo. Es muy importante entender y asimilar el hecho de que Swing es una extensión del AWT, y no un sustituto encaminado a reemplazarlo 8 3.4.- MySQL MySQL es uno de los Sistemas gestores de Bases de Datos más populares desarrollados bajo la filosofía de código abierto. La desarrolla y mantiene la empresa MySQL AB pero puede utilizarse gratuitamente y su código fuente está disponible. Entre las características disponibles en las últimas versiones de MySQL se puede destacar: • Amplio subconjunto del lenguaje SQL. Algunas extensiones son incluidas igualmente. • Disponibilidad en gran cantidad de plataformas y sistemas. • Diferentes opciones de almacenamiento según si se desea velocidad en las operaciones o el mayor número de operaciones disponibles. • Transacciones y claves foráneas. • Conectividad segura. • Replicación. • Búsqueda e indexación de campos de texto. 3.5.- JDBC JDBC (Java DataBase Connectivity) es un API de Java que permite al programador ejecutar instrucciones en lenguaje estándar de acceso a Bases de Datos, SQL (Structured Query Language). Para que una aplicación pueda hacer operaciones en una Base de Datos, ha de tener una conexión con ella, que se establece a través de un driver, que convierte el lenguaje de alto nivel a sentencias de Base de Datos. Es decir, las tres acciones principales que realizará JDBC son las de establecer la conexión a una base de datos, enviar sentencias SQL a esa base de datos y procesar los resultados obtenidos de la base de datos. JDBC es una especificación de un conjunto de clases y métodos de operación que permiten a cualquier programa Java acceder a sistemas de bases de datos de forma homogénea. Lógicamente, al igual que ODBC, la aplicación de Java debe tener acceso a un driver JDBC adecuado. Este driver es el que implementa la funcionalidad de todas las clases de acceso a datos y proporciona la comunicación entre el API JDBC y la base de datos real. La necesidad de JDBC, a pesar de la existencia de ODBC, viene dada porque ODBC es un interfaz escrito en lenguaje C, que al no ser un lenguaje portable, haría que las aplicaciones Java también perdiesen la portabilidad. El Driver que nosotros utilizaremos será MySQL-connector-java-3.0.14-production que tiene las siguientes características, nos permitirá trabajar con el sistema de gestor de Base de Datos escogido que es MySQL. Es un driver realizado completamente en Java que se comunica con el servidor DBMS utilizando el protocolo de red nativo del servidor. De esta forma, el driver no necesita intermediarios para hablar con el servidor y convierte todas las peticiones JDBC en peticiones de red contra el servidor. La ventaja de este tipo de driver es que es una solución 100% Java y, por lo tanto, independiente de la máquina en la que se va a ejecutar el programa. La única desventaja de este tipo de drivers es que el cliente está ligado a un servidor DBMS concreto. Pero puesto que nuestro servidor DBMS es MySQL, no nos supone ningún inconveniente. 9 3.6. ECLIPSE El proyecto Eclipse.org, entre otras muchas cosas, es una plataforma de desarrollo de aplicaciones Java, que nos permite en todo momento tener controladas todas las Clases y Paquetes que utiliza nuestra aplicación así como crear proyectos con determinadas propiedades como Classpath, argumentos de ejecución, etc. Quizá Eclipse no sea la Herramienta más apropiada para el desarrollo de este programa, pero si que es la que más conocía, y de la que me resultaba más sencillo su manejo 3.7.- JSmooth JSmooth, es una aplicación que nos permite crear archivos ejecutables a partir de un fichero jar. Esta acción elimina una de las principales ventajas de Java que es la independencia de la plataforma en que se ejecute, pero la he usado por comodidad en la presentación. También existen otras aplicaciones que nos permiten pasar de código Java a ejecutables para otras plataformas. 10 4.- ANÁLISIS El objetivo de este proyecto es crear una aplicación Servidor-Cliente. El Servidor lleve a cabo toda la tarea administrativa de nuestro proyecto. Para ello construiremos una sencilla Base de Datos que pueda contener toda la información necesaria. Para hacerlo lo menos complicado posible crearemos dos tablas en nuestra base de datos, ya que considero que es suficiente para manejar la información del Servidor... Todas las tareas administrativas del Servidor se pueden agrupar en dos grandes grupos: 1. Operaciones con Clientes 2. Operaciones con Trabajos De hay las dos bases de datos, para las operaciones con clientes y trabajos, crearemos un campo en la tabla trabajos que referencie a Clientes. Además de la tarea administrativa, debe llevar a cabo una labor de mantenimiento de esta Base de Datos, así como un control de los posibles errores que se puedan producir bien en la transmisión de Datos, o en los accesos de Clientes. El Cliente por otra parte debe ser lo más autónomo posible, y ser capaz de funcionar sin la interacción del usuario remoto. Aún así debe disponer de unas funciones mínimas para su control, como la de ‘parar’ o ‘Continuar’ si el cliente lo desea, así como la opción de preguntar al usuario antes de establecer la conexión con el Servidor, ya que no todas las conexiones a Internet son iguales, y puede que el usuario necesite una serie de pasos antes de conectar. El programa de Cálculo Intensivo poder ser independiente del programa Cliente que lo llame, salvo alguna función necesaria para el funcionamiento del cliente que le pasaremos por una Interface. Para la comunicación entre Cliente y Servidor son necesarias, o al menos imprescindibles tres funciones: 1. Descargar Fichero. 2. Enviar Fichero. 3. Registrar Cliente. Estas son las tres funciones que implementaremos utilizando la tecnología RMI que como ya he dicho nos permite invocar métodos de forma remota, así pues el código de estas peticiones estará en el Servidor, y el cliente simplemente las llamará de manera remota. Aunque el programa Cliente sea lo menos interactivo posible, eso no quiere decir que debamos ejecutarlo en Background, ya que el usuario puede querer, simplemente por aburrimiento, comprobar cual es el progreso del programa, es por ello que tanto cliente como programa de cálculo deben presentar una apariencia lo más vistosa posible. Por último y para una mayor difusión de nuestro proyecto, ya que nos interesa que el mayor número de cliente se adhieran a él, nuestro programa cliente debería ser independiente de la plataforma en que se ejecute. Por ello hemos elegido JAVA para desarrollarlo, ya que gracias a su portabilidad de clases es posible ejecutarlo desde cualquier máquina, que disponga eso sí de un entorno JAVA como JRE. 11 4.1.- ANÁLISIS DE LA INTERACCIÓN CLIENTE-SERVIDOR Como ya he dicho la interacción entre Cliente y Servidor se hará mediante la tecnología RMI (Remote Method Invocation). Así pues el código fuente de las peticiones que le haga el Cliente al Servidor, estará contenido en el propio Servidor, mientras que el Cliente únicamente hace una llamada Remota a dicha petición pasándole unos parámetros necesarios para el Servidor, y recibiendo un resultado según el resultado de la acción. La comunicación entre ambos por otra parte debe ser la mínima e imprescindible, para así no colapsar al Servidor con peticiones que tarden mucho en procesarse, ocupando innecesariamente los recursos del Servidor. Por tanto estas peticiones serán cortas, y sólo mantendrán al Servidor ocupado el tiempo mínimo e imprescindible. Las peticiones imprescindibles que el Cliente necesita hacerle al Servidor para el correcto funcionamiento del conjunto son las siguientes: 4.1.1. Descargar Fichero : El Cliente necesita un fichero que contenga los datos que el Servidor necesita analizar/procesar. Por otra parte el Servidor necesita el login con el que el cliente esta registrado, para comprobar que realmente está registrado y para actualizar su Base de Datos. Una vez se establezca la conexión entre ambos ordenadores, el servidor pasara la petición a otro puerto, para dejar el puerto de aceptación de peticiones libre. Una vez completada la descarga, el Servidor devolverá al Cliente una cadena de caracteres con el resultado de la función: • Nombre del Fichero Descargado La operación ha sido realizada con éxito. • Error1 : El Servidor no dispone de trabajos para enviar en ese momento. El cliente al recibir este resultado para inmediatamente su ejecución, ya que en estos momento no puede hacer nada, e informa al usuario de lo que pasa para que el actúe en consecuencia. • Error2 : El Servidor ha detectado un acceso no autorizado, ya que no tiene registrado este cliente, así que antes de seguir le pide al cliente que se registre. Así que le pide que se registre de nuevo. El cliente despliega pues el dialogo de registro del cliente. • Error3 : El Servidor tiene problemas de mantenimiento y avisa al cliente que en ese momento no puede atender peticiones. El Cliente automáticamente se para y avisa al Servidor. • Error : Se ha producido un error, posiblemente ajeno servidor y cliente, durante la descarga. El cliente es informado, y vuelve a intentar la descarga. 12 4.1.2. Enviar Fichero : Una vez el Cliente ha completado todo el proceso de cálculo, se dispone a enviar el fichero donde ha guardado todos los datos obtenidos del análisis. De nuevo el Servidor necesita unos parámetros para poder llevar a cabo su gestión de la Base de Datos. Los parámetros son el nombre del fichero, y el login del usuario: el nombre del fichero para actualizar su registro a completado, y el login del usuario, primero para comprobar que dicho trabajo estaba asignado a ese usuario, y después para actualizar también el registro del Cliente. De nuevo una vez actualizada la Base de Datos, el Servidor enviará al Cliente un entero con el resultado de la operación, este entero puede registrar los siguientes valores: • 1 : La operación se ha realizado con éxito. • 2 : Debido al excesivo tiempo que el cliente ha tardado en completar el trabajo, el Servidor ha asignado el mismo trabajo a otro Cliente. El Cliente es informado, y comienza con un nuevo trabajo. • 3 : El Servidor ha perdido los datos de registro del usuario. Así que le pide que se registre de nuevo. El cliente despliega pues el dialogo de registro del cliente (En este caso, puesto que el Cliente tenía que hacer una conexión anterior para descargarse el fichero de trabajo, el Servidor asume que ha perdido sus datos). • 0 : El Servidor tiene problemas de mantenimiento y avisa al cliente que en ese momento no puede atender peticiones. El Cliente automáticamente se para y avisa al Servidor. 4.1.3. Registrar Cliente : Antes de empezar a procesar cualquier trabajo, lo primero que debe hacer un nuevo usuario del programa Cliente, es registrarse en el Servidor. Para tal operación, el cliente dispone de un diálogo de registro en que el Cliente debe introducir un login (10 caracteres) y su nombre (40 caracteres). En un principio el Programa nos indica si el Servidor está disponible en ese momento, si el así rellenamos los campos y enviamos la petición al Servidor. Los parámetros son los dos campos que acabamos de rellenar: login y nombre. El Servidor una vez registrado el nuevo usuario nos retorna un entero con el resultado de la operación. Los posibles resultados son: • 1 : La operación se ha realizado con éxito, El Servidor nos ha registrado como nuevo usuario. • 2 : Ya existe un Cliente con ese login: El Cliente es informado y pide al usuario que introduzca un login diferente para poder registrarse. • 0 : Se ha producido un error en el servidor: El Cliente informa al usuario de que el Servidor tiene problemas y le pide que lo intente más tarde. Con estas tres funciones, quedan cubiertas todas las demandas que el Cliente pueda requerir del Servidor y viceversa. 4.2 ANALISIS DEL CLIENTE Como ya he explicado, la aplicación Cliente debe ser un programa capaz de ejecutarse sin la interacción del usuario, ya que esa es la idea de la computación zombi, aprovechar la capacidad de procesamiento de un ordenador, cuando éste está encendido pero sin realizar ninguna tarea. Aun así lo ideal seria que el programa tuviese unos parámetros de configuración mínimos accesibles al usuario como por ejemplo poder parar o reanudar la ejecución del programa en cualquier momento, o bien pedir al programa que éste nos pida autorización siempre antes de conectarse a la red. Además de esto sería interesante que con un solo vistazo, el usuario pudiera comprobar sus propias estadísticas, así como el progreso que esta siguiendo el programa de cálculo intensivo. 13 Para llevar un registro de las estadísticas hay que guardar los datos permanentemente en un fichero al que el Cliente pueda acceder cada vez que se inicie. Estos datos, así como un registro de todos los sucesos que vayan sucediendo durante la ejecución del Cliente, se guardaran en cada iteración para no perder todos los datos en caso de un fallo del sistema. También el programa tiene que mantener un control sobre la disponibilidad del Servidor, y, si por cualquier motivo cayera el Servidor, o no pudiera atender las peticiones, el Cliente tiene que detectarlo, notificar al usuario de lo que esta ocurriendo (para que pueda actuar en consecuencia cuando vuelva) y parar la ejecución del programa, o al menos llevar una política de parar una vez intentada la operación n veces cada x minutos. Por último el Cliente debe detectar cualquier error que pueda generar el propio cliente y notificarlo al usuario, como por ejemplo, perdida de datos, perdida de algún fichero... Así pues nuestro programa Cliente constará de tres partes bien diferenciadas: 4.2.1. Bucle Principal: El Bucle principal, como su nombre indica es un Bucle infinito que el sólo y sin la interacción de ningún usuario pueda ir Descargando datos (Petición remota de Descarga al Servidor), Procesándolos (Iniciando el Thread de Cálculo Intensivo), y Enviándolos al Servidor (Petición remota de envío al Servidor), llevando de todo ello un registro que el usuario pueda consultar en cualquier momento. También controla en cada iteración que no se haya producido ningún error, y si es así comunicarlo al usuario. 4.2.2. Interficie Gráfica: Aunque el Bucle puede realizar todo el trabajo, en condiciones óptimas, sin ayuda del usuario, no está de más permitir que el usuario interaccione con el programa. Pueda parar y reanudar el programa, decidir el modo de conexión del programa, ver sus estadísticas, ver que sucesos han ocurrido en su ausencia, ver el progreso actual del Cálculo y sobretodo enterarse si todo ha funcionado de forma correcta mientras el no estaba. Para poder parar y reanudar el programa en cualquier momento Bucle principal y Programa de Cálculo Intensivo son Threads. 4.2.3 Programa de Calculo Intensivo: Nuestro programa Cliente será compatible con cualquier programa de Calculo que podemos introducir siguiendo unas mínimas reglas de comunicación entre ambos: El Programa de Cálculo tiene que poder comunicar al Prog. Cliente que ha finalizado, que está en pausa, que se reanuda, o bien que se ha producido un error durante su ejecución. Del mismo modo el Prog Cliente tiene que poder decirle al Prog de Cálculo cuando pararse, y cuando reanudar su ejecución, así como proporcionarle un espacio en la pantalla donde poder mostrar el estado actual de su proceso. 14 4.3. ANÁLISI DE LA APLICACIÓN SERVIDOR: Para analizar el programa Servidor en su conjunto, dividiremos su contenido en tres secciones: 1. La Base de Datos que necesita para poder gestionar correctamente toda la información. 2. Las Funciones Remotas 3. La Interficie Gráfica. 4.3.1.- BASE DE DATOS La Base de Datos que necesita nuestro Servidor es muy sencilla, ya que la escasa complejidad de los Datos que maneja no requiere algo más elaborado. Básicamente el Servidor maneja dos grandes Clases de Información: 1.- Información sobre Clientes: 2.- Información sobre Trabajos: En consecuencia es lógico crear únicamente dos Tablas en nuestra BD, una que guarde la información sobre cada trabajo disponible, asignado o completado en nuestro servidor, y otra que guarde los datos de los clientes registrados en él mismo. La información que necesitamos conocer sobre cada una de estas clases tampoco debe ser muy amplia. De los Trabajos necesitamos: El nombre del fichero asociado, Su prioridad, Su Estado actual, es decir, Pendiente de asignación, asignado a Cliente o Completado, El cliente al que está asignado, o por el que ha sido completado, su fecha de asignación o finalización, y su ubicación en el disco duro. De los Clientes únicamente necesitamos : Su login, Su Nombre, El nº de trabajos que ha completado con éxito, y la fecha de su ultima conexión. Con estos sencillos datos el Servidor podrá llevar a cabo un control de toda la información que necesita. Para ello necesitamos un conjunto de consultas SQL con las que podamos acceder rápidamente a todos los datos de todos los trabajos y clientes que guardamos, añadir nuevos clientes, añadir nuevos trabajos, actualizar el estado de un trabajo, incrementar los trabajos completados de un cliente o su fecha de conexión, borrar un trabajo, listar los trabajos según su estado, prioridad, fecha..., etc... Para esto usaremos el API de JDBC que nos permite ejecutar sentencias SQL en un entorno JAVA. 4.3.2 FUNCIONES REMOTAS Ya hemos descrito las funciones remotas en el punto de Interacción Cliente-Servidor. Para resolver la comunicación de dichas funciones con la Interficie gráfica del Servidor, crearemos una Interface a para que la funciones remotas puedan también comunicar sus resultados al administrador del Servidor Esta Interficie constará de las siguientes funciones: Incrementar y Decrementar las peticiones de Descarga, Transferencia y Registro, enviar un mensaje al Servidor, enviar un mensaje urgente, informar de que ha realizado una operación en la Base de Datos con éxito, y informar de que ha realizado una operación en la Base de Datos que no ha salido bien. Con estas funciones y las que hemos hecho sobre la Base de Datos, las funciones remotas podrán llevar a cabo el control de la Base de Datos, y comunicarse con el administrador. También hay que tener en cuenta, que para la Descarga/Transferencia de ficheros, no podemos usar el mismo puerto que el que usamos para aceptar las peticiones, ya que podemos tenerlo ocupado más tiempo del necesario limitando así las peticiones que podríamos aceptar. 15 4.3.3 INTERFICIE GRÁFICA Como ya he dicho el administrador del Servidor tiene que poder comprobar el estado actual del Servidor sólo con echar un simple vistazo a la pantalla. Tiene que saber si se ha producido un error crítico, se ha caído el Servidor, se ha perdido la conexión con al Base de Datos, se ha desconectado MySQL, hemos perdido el registro en el Servidor RMI... cualquiera de estos errores hacen que el Servidor no pueda cumplir su función y tenga que ser reparado inmediatamente para poder seguir atendiendo peticiones. El administrador también tiene que poder consultar todas las tablas de la Base de Datos de forma rápida y dinámica, y consultarla en un orden especifico para su mayor comodidad. Por eso toda la base de Datos debe estar visible en todo momento, y si no es así accesible rápidamente. La Base de Datos requiere también un mantenimiento, que el administrador debe poder efectuar de manera clara y desde la misma Interficie, por ello debemos diseñar diálogos que permitan efectuar todas las operaciones necesarias sobre la Base de Datos como: Añadir nuevos trabajos, Borrar Trabajos Pendientes, Cambiar la Prioridad de un Trabajo Pendiente, Comprobar la consistencia de la Base de Datos, o Consultar los datos de cualquier Trabajo, es decir, comprobar que cada trabajo tiene su archivo de Datos asignado. También debe saber cuando un trabajo lleva demasiado tiempo asignado, por lo que se retrasa su procesamiento, y poder asignarlo a un nuevo usuario para que este lo complete. Esta última función debería realizarse automáticamente todos los días una vez y cambiar el estado de estos trabajos a pendiente con máxima prioridad. Por último el administrador tiene que mantener un historial de todo lo que sucede con el Servidor a lo largo de su ejecución para poder consultarlo en el futuro, para ello hay que proporcionarle una forma ya sea automática o manual de poder guardar ficheros con el estado actual de la Base de Datos, y del los Sucesos que registra el Servidor, asimismo también hay que proporcionarle una herramienta gráfica con la que poder consultar esos archivos en el futuro. 16 5.- DISEÑO 5.1.- DISEÑO DE LAS FUNCIONES REMOTAS: Interface que le pasamos al Cliente mediante el fichero Servidor_Skel.class String descargaFitxer (String user) int enviarFitxer (String user, String nomFitxer) int registrarUser (String user, String nom) Estas son las funciones remotas a las que el Programa Cliente tendrá acceso mediante la Interface Remota ServidorI.class 5.1.1 Protocolo de Transferencia Puesto que las funciones de Descarga y Transferencia de fichero Requieren el envío de ficheros a través de la red, ya que un fichero no se puede pasar por parámetro, ni enviar como resultado, Es preciso que el cliente implemente además de una Interface con el Servidor dos clases capaces realizar la transferencia de ficheros con el servidor a través de sockets. Estas dos clases deben ejecutarse conjuntamente con la función remota pero en diferentes hilos de ejecución, por ello extenderán la clase Thread. Una vez tenemos ambas clases sólo nos restará crear un protocolo de transporte común a Servidor y Cliente para que se envíen los Datos. Estos son los protocolos una vez aceptada la petición inicial: Protocolo de Descarga: Servidor envía el nuevo puerto de Escucha Cliente recibe nuevo puerto Cliente envía ACK Servidor recibe ACK Cliente pide la conexión al nuevo puerto de escucha Servidor acepta conexión Mientras quede fichero Servidor envía Fichero Cliente recibe fichero Cliente envía ACK Servidor recibe ACK Fmientras Protocolo de Transferencia: Servidor envía el nuevo puerto de Escucha Cliente recibe nuevo puerto Cliente envía ACK Servidor recibe ACK Cliente pide la conexión al nuevo puerto de escucha Servidor acepta conexión Mientras quede fichero Cliente envía Fichero Servidor recibe fichero Servidor envía ACK Cliente recibe ACK Fmientras 17 La implementación de estas funciones se encuentra en el Servidor, y el Servidor accederá a ellas a través de la clase generada por RMI Servidor_Stub.class. El pseudocódigo de estas funciones es el siguiente: 5.1.2. Servidor.java Variables: interficie: nos permite tener acceso a la interficie Gráfica del Servidor socketServidor : es el socket que acepta las peticiones. String descargaFitxer(String user) { Result = ‘ERROR3’ Incrementamos las peticiones de Descarga en curso a través de interficie. Aceptamos la petición del cliente a través de socketServidor Creamos un nuevo socketServidor y enviamos al cliente en el que estamos escuchando, dejando así libre el de aceptación de peticiones. Si (user existe en nuestra Base de Datos) entonces Cogemos un nuevo Trabajo de la Tabla Treballs Si (Trabajo /= null) entonces Si existe el directorio ‘Treballs’ Enviamos trabajo al Cliente Cerramos sockets Si se ha producido ningún error Informamos al Servidor a través de interficie Sino Actualizamos el trabajo en la base de datos Estado = asignado Login = user Data = fecha de hoy Informamos al Servidor de los Cambios Realizados en la BD. Result = nombre del Trabajo Fsi Si hay algún error en la BD Devolvemos el trabajo a su estado anterior Informamos al Servidor del Error Fsi Sino Crear directorio ‘Treballs’ Informar al servidor que se han perdido todos los ficheros asociados a trabajos. Fsi Sino Result = ERROR1 Informa al Servidor de que la BD no dispone de Trabajos para enviar. Fsi Sino Result = ERROR2 Informa al Servidor que un cliente no autorizado ha intentado la conexión Fsi Control de Excepciones: Si se produce alguna excepción Informar al Servidor del problema Fin control de Excepciones Decrementar las peticiones de Descarga en curso Retornar (Result) } 18 int enviarFitxer(String user, String Trabajo) { Result = 0; Incrementar peticiones de Transferencia en curso Aceptamos la petición del cliente a través de socketServidor Creamos un nuevo socketServidor y enviamos al cliente en el que estamos escuchando, dejando así libre el de aceptación de peticiones. Si (user esta registrado) Si ( trabajo está asignado a user) Si no existe directorio ‘Completats’ Crear directorio y Informar al Servidor que se han perdido ficheros Completados Fsi Recibimos el Fichero Cerramos sockets Actualizamos el trabajo en nuestra BD Estado = asignado Login = user Data = fecha de hoy Informamos al Servidor del resultado Borramos el trabajo de su antigua ubicación Result = 1 Si se produce algún error durante la descarga Devolver el trabajo a su estado anterior Informar al Servidor del error Fsi Sino Result = 2 Informar al Servidor de que se había asignado el trabajo a otro user Fsi Sino Result = 3 Informar al Servidor de la perdida del registro del cliente Fsi Control de Excepciones: Si se produce alguna excepción Informar al Servidor del problema Fin control de Excepciones Decrementar las peticiones de Transferencia en curso Retornar (Result) } int registrarUser (String user, String nom) { Result = 0 Incrementar peticiones de Registro en curso Si user no está registrado Guardar nuevo usuario en la BD Result = 1 Sino Informar al Servidor de la repetición de login Result = 2 Fsi Control de Excepciones: Si se produce alguna excepción Informar al Servidor del problema Fin control de Excepciones Decrementar las peticiones de Registro en curso Retornar (Result) } 19 5.2.- DISEÑO DEL CLIENTE Las tres partes del Cliente, Bucle Principal, Programa de Cálculo e Interficie Gráfica tienen que poder comunicarse a través de variables Globales para conocer en todo momento el estado del Programa así como otros datos necesarios para su ejecución. Creamos la Clase Dades.java que contendrá estas variables así como las funciones necesarias para acceder a ellas. Todas estas variables y funciones serán estáticas, es decir ocuparan siempre el mismo lugar en memoria, para que todas las clases puedan acceder a ellas en todo momento Dades.java Variables Globales: Aturat : indica si el programa está parado o en ejecución. Intents : nº de intentos de conexión fallidos antes de parar el programa. Mode: indica el modo en que trabaja el programa (si pide autorización al conectar o no). Estat: estado actual del programa. Los valores de esta variable serán: ACABAT -> Listo para Descargar REBENT -> Descargando Fichero INICI -> Listo para Procesar EXECUCIO -> Procesando PAUSA -> Programa de Cálculo en pausa FI -> Listo para Transferir ENVIANT -> Transfiriendo fichero User: login del usuario. NomUser: nombre del usuario. Servidor = servidor actual al que nos conectamos. TempsCPU = tiempo de CPU total consumido. TempsTransf = tiempo total consumido en operaciones de transferencia de ficheros. NumTreballs = nº de trabajos completados por el usuario. NomFitxer = nombre del Trabajo actual que se está procesando. serverDefault = Servidor por defecto. Se carga al iniciar el programa a partir del fichero ‘server’ Funciones Globales Además de las funciones para modificar o acceder a cualquiera de estas variables. IniDades : Inicializa los valores de las variables a partir del Fichero ‘Data’ donde guardamos los valores de las variables para no perderlos CrearDades : Crea el fichero ‘Data’ e inicializa por defecto todas las variables. Esta función sólo se utiliza en la primera ejecución del Programa, o en caso de perdida del fichero ‘Data’. SalvarDades : Guarda en el Fichero ‘Data’ todas las variables, Esta función se realiza al apagar el programa, y también en cada iteración del Bucle principal, para que en caso de fallo del sistema no lo perdamos todo. Con estas funciones ya podemos llevar un control del programa desde todos sus diferentes bloques. 20 5.2.1.- DISEÑO DEL BUCLE PRINCIPAL Como ya he explicado el bucle principal es un bucle infinito que se limita a ir descargando trabajos, procesándolos y enviándolos al Servidor, todo ello comprobando en cada iteración que no se produzca ningún fallo en la conexión con el cliente, o bien algún fallo de perdida de los datos que el Cliente necesita para funcionar. Además de esto proporcionamos una serie de funciones en la interficie gráfica para que a través de las variables globales, ésta pueda interactuar con el bucle principal, así por ejemplo si el usuario para el programa con a través de la interficie gráfica, esta pone la variable ‘aturat’ a true, con lo que el bucle principal se pararía hasta que el usuario le indicara que continuase. La manera mas fácil de parar el bucle es poner la variable ‘aturat’ a true y en cada iteración del bucle comprobar el valor de la variable. Si es true, suspendemos el programa hasta nuevo aviso. Así pues el programa principal será un bucle que en cada iteración comprobará en que ‘estat’ se encuentra el programa, y según el estado ejecutará una de sus tres funciones. Al final de cada iteración, comprobará que no se haya producido ningún error grave como perdida del Registro, perdida de los Datos, indisponibilidad del Servidor, y si no es así continuará. En caso de necesitar conectarse con el Servidor, el programa comprobara el modo de trabajo del Cliente, si no necesita autorización, continuará, si la necesita, parará el programa en espera de que el usuario actúe. Para ello dotaremos al Bucle de varios diálogos para que pueda interactuar con el cliente de forma clara. Los diálogos serán los siguientes: 5.2.1.1. DialogNoConexio.java En caso de que el Servidor no esté disponible, el Bucle principal pasará a estado inactivo durante 10 minutos, pasados estos 10 minutos reintentará la conexión. Este proceso lo realizará un total de 5 veces (variable ‘intents’) antes de parar el programa. Este Diálogo es simplemente informativo, informa al usuario de lo que esta sucediendo y le muestra al usuario el nº de intentos que faltan para parar el programa. También informa de que si el usuario quiere prescindir de este proceso, parar el programa e intentarlo mas tarde, tiene que cerrar este dialogo y parar el Programa. 5.2.1.2. DialogFiIntents.java Una vez que se han agotado los 5 intentos de conexión, el programa se para. Este Diálogo, también informativo comunica al usuario que el programa ha agotado los 5 intentos de conexión y se ha parado. 5.2.1.3 DialogError.java Cuando el Bucle detecta algún error, como puede ser la perdida de un fichero, un error en la transferencia, etc... informa al usuario a través de este diálogo. Que simplemente informa del error. Si no es un error crítico, el programa sigue con su ejecución normal. Para informar del error, le pasamos como parámetro un String donde se vea reflejado. 21 5.2.1.4 DialogConfirmacio.java Antes de cada operación de transferencia el Bucle comprueba cual es el modo de trabajo del Cliente (Variable global ‘mode’). Si el modo es ‘Sin pedir autorización’ continúa, en caso contrario, el Bucle se detiene y muestra este diálogo. El diálogo de Confirmación pide al usuario si quiere que el Cliente se conecte a internet para iniciar una operación de transferencia, dándole a este dos opciones: 1. Conectar -> En cuyo caso se cierra el diálogo y el bucle continúa con su ejecución 2. Aturar -> En cuyo caso el bucle continúa suspendido a la espera de nuevas instrucciones del usuario. 5.2.1.5. DialogPerduaRegistre.java Si tras una de las peticiones al Servidor, éste nos indica que ha perdido nuestro registro. El Bucle al final de cada iteración comprueba que si esto ha pasado, en tal caso suspende la ejecución del Bucle y nos muestra este Diálogo. Este Diálogo, como el de Registro, pide al usuario que introduzca los datos de registro (login y nombre). Una vez ha rellenado los campos, el usuario tiene 3 opciones: 1. Enviar -> El Cliente ejecuta la función remota ‘registrarUser’. Y a través del display inferior del mismo diálogo informa del resultado de la operación. 2. Acceptar -> Si ya ha sido registrado, se cierra el diálogo y el usuario puede continuar con la ejecución del programa manualmente. 3. Cancelar -> El usuario decide no registrarse en ese momento, con lo que cada vez que intente un acceso al servidor se le volverá a mostrar el mismo diálogo. 5.2.1.6. DialogNoTreballs.java Es un tipo de error con un tratamiento especial. Cuando la petición de descarga nos retorna este resultado. El Bucle principal opta por suspender el programa y mostrar este diálogo. Este diálogo sólo informa de que el Servidor no puede ofrecernos trabajo y que la mejor opción seria finalizar el programa y volver a ejecutarlo mas tarde. Además de estos diálogos, el usuario puede llevar un registro de todo lo que va sucediendo durante la ejecución del programa. Para ello la interficie grafica proporciona un cuadro de texto donde el Bucle va anotando todos los sucesos. Para la ejecución del Programa de Cálculo intensivo proporcionaremos al paquete Cliente una Interface con la que poder comunicarse. Esta Interface lo único que contendrá será la función que pone en marcha el programa de Cálculo. int Simula(); Puesto que este bucle es un programa que necesitaremos parar o reanudar a nuestro gusto desde la misma interficie gráfica incluso, y que además queremos que se ejecute concurrentemente con todos los eventos que la interacción del usuario pueda generar, lo ideal es que esta clase sea también un Thread, y además que sea una variable estática, es decir que siempre ocupe el mismo lugar en memoria para que así se pueda acceder a ella desde todas las clases. Una vez sentadas estas bases procedemos a ver el pseudocódigo del Bucle Principal: 22 5.2.1.7. Bucle.java Variables: Disponible -> Indica si el servidor está disponible o no. PerduaReg -> Indica si hemos perdido el registro o no. //No olvidemos que además de estas tenemos todas las variables globales. Bucle principal Mientras (true) hacer Si aturat = true Suspender Ejecución Fsi Switch (estat) Caso ACABAT: Si mode = 0 Mostrar DialogConfirmacio Suspender Ejecución Fsi Si aturat = false Conectar con el Servidor Comprobar que Servidor RMI está en marcha Disponible = true Estat = REBENT Ejecutar Thread Receptor Resultado = Petición remota de Descarga de fichero Switch (resultado) Caso ‘ERROR’ Estat = ACABAT Aturat = true Informar usuario Caso ‘ERROR1’ Estat = ACABAT Aturat = true Informar al usuario Mostrar DialogNoTreballs Caso ‘ERROR2’ Estat = ACABAT Aturat = true Informar al usuario Mostrar DialogPerduaRegistre Caso ‘ERROR3’ Estat = ACABAT Aturat = true Informar al usuario Por Defecto Estat = INICI NomFitxer = resultado Informar al usuario que la operación se ha realizado con éxito Fswitch Fsi Control de Excepciones: No se puede establecer la conexión Estat = ACABAT Disponible = false Informar al usuario del tipo de Problema. Otras excepciones Estat = ACABAT 23 Informar al usuario del tipo de Problema. Mostrar DialogError Fcontrol de Excepciones Caso INICI: Si existe el fichero de Datos Estat = EXECUCIO Simula() Sino Estat = ACABAT Informar al usuario Fsi Control de Excepciones Si se produce algún problema Estat = ACABAT Informar al usuario Fsi Fcontrol Caso FI Si mode = 0 Mostrar DialogConfirmacio Suspender Ejecución Fsi Si aturat = false Si existe el Fichero de Resultados Conectar con el Servidor Comprobar que Servidor RMI está en marcha Disponible = true Estat = ENVIANT Ejecutar Thread Emisor Resultado = Petición remota de envío de fichero Switch (resultado) Caso 0: Aturat = true Estat = FI Informar al usuario Caso 2: Aturat = true Estat = ACABAT Informar al usuario Caso 3: Estat = FI PerduaReg = true Informar al usuario Caso 1: Estat = ACABAT Informar al usuario que el envío se ha realizado con éxito. Fswitch Sino Estat = INICI Informar al usuario que volvemos a procesar el trabajo Fsi Fsi 24 Control de excepciones No se puede establecer la conexión Estat = FI Disponible = false Informar al usuario del tipo de Problema. Otras excepciones Estat = FI Informar al usuario del tipo de Problema. Mostrar DialogError Fcontrol de Excepciones Fswitch Guardar copia del Registro SalvarDades Si no hay perdida de Registro Si Servidor disponible Intents = 5 Sino Si intents > 0 Mostrar DialogNoConexio Informar al usuario Intents -Dormir 15 minutos Sino Aturat = true Mostrar DialogFiIntents Informar al usuario Intents = 5 Fsi Fsi Sino Aturat = true Mostrar DialogPerduaRegistre Fsi Fmientras Fbucle Principal 25 5.2.2 DISEÑO DE LA INTERFICIE GRÁFICA DEL CLIENTE Para la implementación de toda la interficie gráfica, así como de todos los componentes gráficos del programa Cliente, tales como los Diálogos descritos en el apartado anterior, o la visualización del progreso del Programa de Cálculo usaremos la librería de JAVA Swing que es mucho mejor que el AWT como ya hemos explicado en el apartado 3. La interficie que permitirá al usuario interactuar con el Cliente debe ser lo más clara y sencilla posible, e incluir únicamente aquellas opciones que sean imprescindibles para el manejo del Programa. Como ya he dicho estas opciones serán 1. Continuar Continuará con la ejecución del programa Cliente. 2. Parar Detendrá la ejecución del programa Cliente. 3. Configuración Permitirá modificar el modo de trabajo del Programa, así como si el usuario lo desea cambiar el servidor al que nos conectamos. (La opción de cambiar el servidor no tendría por que existir, ya que se supone que el servidor será siempre el mismo, pero es mucho más cómoda para poder ejecutar el Servidor en cualquier máquina.) Además de estas tres opciones para controlar el programa el usuario tiene que ver en todo momento, si lo desea, sus propias estadísticas, un registro de los sucesos que acontecen en el programa, y por supuesto el progreso del Programa de Cálculo Intensivo. Así pues el componente gráfico principal de nuestro Cliente será un JFrame o Ventana sobre el que colocaremos toda la información que hemos ido mencionando. Dividiremos la ventana en dos Secciones. La de arriba será la sección de Control del Programa Cliente, y la de abajo la utilizaremos para visualizar el progreso del Programa de Cálculo Intensivo. Ambas secciones serán JPanels. El JPanel inferior será una clase importada del Paquete (package) calculIntensiu, así nos aseguramos que cualquier otro programa que queramos implementar para nuestro Cliente sea compatible definiendo un JPanel sobre el que visualizar su progreso. 26 La sección de control se dividirá en tres partes, sólo una de ellas servirá para la interacción con el usuario, las otras dos serán simplemente informativas: 5.2.2.1. PanelDaltEsqEtiqs.java Este panel situado a la izquierda mostrará información sobre los datos del usuario, así como las estadísticas que este ha acumulado desde que posee el programa Cliente. Los Datos se mostrarán en JLabels y serán: Estado del Programa Servidor Estado actual del Cliente Login del Cliente Nombre del Cliente Trabajos Completados Trabajo actual en Proceso Tiempo Total de CPU Tiempo total de Transferencia Además este Panel proporcionará una función al resto de clases del mismo package para que puedan actualizar dicha información a partir de la JLabel que quieren modificar. No se pueden modificar directamente las etiquetas desde otras clases, hay que modificar la Variable Global que nos muestran, y después indicar que etiqueta queremos actualizar. Tanto las etiquetas como la función que las modifica son estáticas, es decir ocupan el mismo sitio en memoria siempre. 5.2.2.2. PanelDaltDret.java Por último este panel situado a la derecha del todo muestra un registro de los sucesos que van pasando durante la ejecución del Cliente. El panel consta de un JScrollPane en el que visualizamos un área de Texto JTextArea donde desde el Bucle y desde algunos Diálogos vamos escribiendo todo lo que va pasando. Para escribir los sucesos, este panel proporciona una función afegirText(String). Tanto la función como el Área de texto son estáticos. También nos proporciona una función con la que guardar el contenido del Área de texto en un archivo de Log 27 5.2.2.3. PanelDaltEsqBotons.java Este panel es el único que permite la interacción del usuario. Estará en el centro del panel Superior. Consta de tres botones bastante claros acerca de su cometido. Continuar, Parar, Configuración. Al constructor de este panel se le pasa como complemento una referencia al Bucle Principal del programa, ya que desde este panel debemos ser capaces de reanudarlo, no así de pararlo, así nos aseguramos de que el Bucle principal acabe un ciclo antes de pararlo. Para que el usuario tenga mas fácil y claro lo que está haciendo la función de Configuración se presenta a través de un Diálogo. Ese diálogo sólo se podrá mostrar con el programa detenido. El pseudocódigo de este panel es el siguiente: Constructor (Bucle Principal bucle) Inicializa componentes Añadir JButton Continuar Añadir JButton Parar Añadir JButton Configuración Continuar.procesar Evento Si aturat = true Aturat = false Reanudar el Thread Bucle.java Sino Mostrar DialogError Fsi Parar.procesar Evento Si aturat = false Aturat = true Sino Mostrar DialogError Fsi Configuración.procesar Evento Si aturat = true Mostrar DialogConfiguracio Sino Mostrar DialogError Fsi Fin Constructor 5.2.2.4. DialogConfiguracio.java Este Diálogo tiene los siguientes componentes: Campo de Texto JTextField para introducir el nuevo Servidor Un JButton que recupera el servidor por defecto, almacenado en el fichero ‘Data’. Un grupo de 2 opciones: (los dos modos de Trabajo del Cliente) Opción 1 - > Consultar antes de conectar Opción 2 -> Conectar sin consultar Dos JButton más Aceptar -> Guarda los cambios realizados y cierra el Diálogo Cancelar -> Cierra el Diálogo sin guardar los cambios realizados 28 Además de las dos Secciones principales la ventana principal tendrá dos Diálogos más: 5.2.2.5. DialogFinal.java Este diálogo se muestra cuando pulsamos el comando de cerrar la ventana. Únicamente nos pregunta si estamos seguros de querer finalizar el Programa. Y nos da dos opciones: 1. Si -> Con lo que llamamos al DialogClose que se encarga de cerrarlo todo y guardar los datos 5.2.2.5.1. DialogClose.java Guarda el registro, Salva las Variables Globales (SalvarDades()) y sale de la aplicación. 2. No -> Vuelve a la ejecución Este diálogo sólo lo podemos mostrar con el programa parado, en caso contrario el Cliente nos indica que se ha producido un Error y nos muestra el DialogError. 5.2.2.6. DialogPerduaDades.java Este diálogo se muestra si al arrancar el programa cliente se detecta que el fichero donde guardamos los datos ‘Data’ ha desaparecido. El programa reacciona con la función crearDades() que inicializa todas las variables, pero el login y el nombre del usuario son desconocidos para el, por ello le pide al usuario que vuelva a introducir estos datos. Este diálogo consta pues de dos campos de texto uno para el login y otro para el nombre, un botón de aceptar, con el que guardamos los Datos en el archivo y como variables globales, cerramos el dialogo e indicamos al usuario que puede continuar con la ejecución del programa manualmente. Si no rellenamos correctamente los campos, dejamos alguno vacío, en la parte inferior del diálogo hay un display que nos lo indica. Todos los diálogos que hemos mencionado hasta ahora, que por si no lo he mencionado todavía son JDialogs, son diálogos modales, es decir mientras estén visibles, la ventana principal del programa, el JFrame está inactivo, es decir que no se puede acceder a el hasta que no se cierre el Diálogo. Además de la ventana principal dentro de la interficie gráfica, aunque no dependientes de la ventana principal encontramos dos diálogos más. Estos dos Diálogos son independientes de la ventana porque ésta no todavía no esta construida cuando los mostramos, ya que ambos diálogos son causa de, o bien un error durante el arranque del programa, o bien la primera ejecución del programa: 5.2.2.7. DialogNoArranc.java Este diálogo se muestrea si durante la carga de la interficie Gráfica (JFrame principal), o del Bucle Principal se detectan errores imposibles de solucionar. Excepcions Esta Diálogo nos indica que no puede cargar el programa, y nos invita a salir e intentarlo mas tarde a través del botón ‘Salir’ 29 5.2.2.8. DialogRegistre.java Este diálogo es muy similar al DialogPerduaRegistre, por no decir idéntico. Este dialogo se carga cuando desde el programa principal detectamos la ausencia del fichero ‘Config.ini’ que es un chivato que nos indica si la aplicación se ha ejecutado alguna vez o por el contrario esta es la primera. Este JDialog consta de cuatro partes: 1. Mensaje de bienvenida para el nuevo usuario. 2. En esta parte aparecen dos Campos de texto con sus respectivas etiquetas, uno para introducir el login, y otro para el nombre del usuario. 3. Un pequeño display donde se muestra el resultado de la petición de registro 4. Dos botones cuyas funciones describiremos a continuación: - Registrarse: Si estamos conectados Si los dos campos están llenos Resultado = enviar petición de registro Switch (Resultado) Caso 0 Informamos en el Display de que el Servidor no puede atendernos en este momento. Caso 1 Informamos en el Display de que estamos registrados como nuevos clientes. CrearDades() Aceptado = true; Caso 2 Informamos en el Display que ese login ya existe Fswitch Control de excepciones No se puede establecer la conexión Informamos en el Display que el Servidor no está disponible. Otras excepciones Informamos en el Display que no se puede realizar la operación. Fcontrol de Excepciones Sino Informamos en el Display que hay que llenar los dos campos. Fsi - Comenzar: Si aceptado = true Crear fichero ‘Config.ini’ Cargar el Programa Cliente Control de Excepciones Informamos en el Display que se ha producido un error en el arranque. Fcontrol Sino Informar en el Display que antes de empezar hay que registrarse. Fsi Si al cargar el Diálogo el cliente detecta que en ese momento el servidor no está disponible, informa en el Display. Por último nos dejamos un Thread que está en continua ejecución desde el inicio del programa que simplemente se encarga que ir actualizando las variables globales tempsCPU y tempsTransfer. Este Thread es Temps.java. 30 5.2.3.- DISEÑO DEL PROGRAMA DE CÁLCULO INTENSIVO El Programa de Cálculo intensivo que diseñemos debe constar de dos partes: El programa en sí que efectúa todos los cálculos necesarios para analizar los datos que obtiene del fichero ‘Treball.dat’. Y la visualización gráfica del progreso del Cálculo. Para la visualización gráfica tenemos que implementar una clase que extienda la clase JPanel y que para ser compatible con el package client debe llamarse PanelCalcul.java. En este panel el programa principal de cálculo irá reflejando lo que vaya haciendo. Este panel, se carga por defecto junto con toda la interficie Gráfica del programa Cliente, así que genera algún error al cargarse, el programa Cliente no se cargará. El programa principal de Cálculo que he escogido es un Simulador de Incendios. Existe un Territorio de 300 x 270 píxeles al que le afectan una serie de factores (Datos a analizar); Riesgo de Incendios Nº de incendios por año Crecimiento de la vegetación Capacidad de extinción de lo Bomberos Probabilidad de fallo humano Por cada año (iteración) se realizan las siguientes operaciones: 1. Se recorre cada píxel y si no tiene vegetación se deja crecer según la media de crecimiento 2. Se ponen sin vegetación todos los píxeles quemados el año anterior. 3. Mientras queden incendios 3.1. Se elige un píxel 3.2. Si tiene vegetación y supera el riesgo de incendio, se incendia 3.3. El incendio se propaga a los píxeles vecinos según la intensidad del incendio, los píxeles quemados de alrededor, y la meteorología de ese año. 3.4. En cada nueva propagación si los bomberos tienen capacidad y no hay ningún fallo humano, el incendio se apaga. Al final del Programa se guardan una serie de Datos que se han ido calculando durante la ejecución, cantidades, medias... en un archivo y se comunica al Cliente que hemos acabado. Se estudiará la evolución del terreno durante 45 años. 31 Para este programa necesitamos algunas variables globales, una estructura de Datos. 5.2,3.1. Variables.java Esta clase contendrá las variables globales así como las funciones para trabajar con ellas. Estas funciones serán synchronizable, es decir no pueden acceder a ellas más de un hilo de ejecución simultáneamente. //Datos que cogemos del fichero ‘Treball.dat’ riscIncendi creixVegetacio capExtincio incendisAnuals errorExtincio //Datos que devolveremos en el fichero ‘Resultat.dat’ incendis -> nº de incendios registrados mitjaIncendis -> media de incendios por año territoriCremat -> total de píxeles quemados mitjaCremat -> media de píxeles quemados por año incendisExt -> incendios extinguidos por los bomberos incendis10 -> incendios mayores de 10 píxeles incendis100 -> incendios mayores de 100 píxeles incendis1000 -> incendios mayores de 1000 píxeles //Otras variables meteorología -> meteorología de cada año, es un random grocs -> total de píxeles secos verds -> total de píxeles con vegetación roigs -> total de píxeles quemados intensitat -> intensidad del incendio //Estructuras de Datos territori -> Es una tabla de enteros que representa el territorio 300 x 270, cada entero puede tener 3 valores (GROC,VERD,ROIG), según su estado //Funciones Todas las funciones que se requieren para poder cambiar el valor, o acceder a cada una de estas variables están en esta clase. Tambien las funciones para acceder a ‘territori’. También incluye 4 funciones para inicializar, cargar o guardar las variables. - iniVariables() : inicializa las variables de ‘Treball.dat’ por defecto - getVariables() : carga las variables del fichero ‘Treball.dat’. - iniDades() : inicializa el resto de variables - guardarDades() : guarda los resultados en el fichero ‘Resultat.dat’. Funciones, variables y estructura de Datos son estáticas. Además de estas variables, el programa debido a la cantidad de información que maneja necesita otra estructura de Datos 5.2.3.2. Cua.java Esta clase implementa una estructura ‘Cola’. Con sus respectivas funciones de ‘encuar’ y ‘desencuar’. En esta cola iremos introduciendo todos los píxeles que se vayan incendiando durante la propagación para irlos tratando uno a uno. Lo ideal podría ser hacerlo con una función interna recursiva que tratase la propagación, pero requiere demasiado espacio de memoria, y colapsaría la pila. 32 Para poder comunicarse con la interficie Grafica del programa Cliente le pasamos a este programa una pequeña Interface. Esta comunicación es necesaria, ya que el simulador de incendios tiene que poder comunicar al Cliente que ha acabado, o bien que se ha detenido, o que se ha producido un error durante su ejecución... 5.2.3.3. InterficieCalcul.java: public interface InterficieCalculI { //Notificar que se ha finalizado el Trabajo, y actualizar // estado del Programa public void fiTreball(); //Notificar un Error public void error(); //Notificar error grave public void errorGreu(); //Retorna si el programa Cliente está parado o en marcha public boolean getEstat(); //Notificar que hemos parado el simulador y actualizar el // estado public void aturar(); //Notificar que reanudamos el simulador y actualizar el estado public void continuar(); } Por último el Simulador tiene que poder mostrarnos cual es el progreso de sus Cálculos, mostrarnos el aspecto del territorio año tras año, cuales son los datos parciales, y una gráfica con la evolución del terreno. El terreno será un panel de 300 x 270 que recorrerá la tabla ‘territori’ para su repintado. Este panel se añadirá a otro panel que nos proporcionará una función estática para actualizarlo. Territori.java y PanelTerritori.java La gráfica será un panel, con ‘años’ minipaneles añadidos. Cada año transcurrido se calcularan los porcentajes de cada tipo de píxel, y se guardaran en su miniPanel para posteriores repintados. Este panel se añadirá a otro panel que nos proporcionará una función estática para actualizar cada miniPanel Grafic.java y PanelGrafic.java Los cálculos parciales se mostraran en una serie de etiquetas. Las etiquetas se añadirán a otro panel que nos proporcionará una función estática para actualizar cada etiqueta. PanelEtiqs.java 33 Una vez diseñado todo lo necesario para la visualización y control del Simulador de incendios procedemos a implementarlo: 5.2.3.4. SimularIncendi.java Variables: Cua Cola InterficieCalcul interficie Funciones Locales CalculaPp (pixelsCremats) -> Calcula la probabilidad de que el fuego se propague a un píxel vecino a partir del riesgo de incendios, la meteorología, la intensidad del incendio y los píxeles ardiendo a su alrededor. Si se propaga, retorna ROIG, sino, retorna VERD CalcularPe -> Compara la capacidad de extinción de los bomberos con la intensidad del fuego, si la capacidad es mayor, calcula la probabilidad de que se produzca un fallo humano. Si no es así el fuego se apaga. Retorna true si apagamos el incendio y false sino. PropagarIncendi(x,y) -> Le pasamos las coordenadas del píxel desde el que se propaga el incendio. Explorar píxeles vecinos incendiados Por cada vecino Si vecino tiene vegetación Si CalcularPp(vecinos incendiados) = ROIG Encuar(vecino) Roigs ++ Fsi Fsi Fpor ImplantarVegetacio() -> Recorre toda la tabla ‘territori’ si el píxel está GROC, deja que haya vegetación según la probabilidad que le pasamos como Dato. Actualiza la variable ‘verds’ SecarCremats() -> Recorre toda la tabla pasando todos los píxeles ROIG a GROC. Actualiza la variables ‘grocs’ y la variable ‘roigs’ 34 Programa Principal: IniDades() GetVariables() Actualizar las etiquetas Actualizar grafica Actualizar territorio Por numero de años Si el Programa Cliente esta en marcha ImplantarVegetacio() SecarCremats() Calcular nueva meteorología Por incendisAnuals Elegir un píxel Si píxel es VERD Calcular la probabilidad de que se incendie Si se incendia Crear cola Encuar (píxel) Mientras no cola vacía & incendio no apagado Desencuar (píxel) PropagarIncendi (píxel) Fmientras Fsi Fsi Fpor Actualizar variables Actualizar etiquetas Actualizar grafica Actualizar territorio Sino Avisar de que estamos parados al Cliente Mientras Cliente Parado Dormir 1 segundo Fmientras Avisar de que continuamos con la ejecución al Cliente Fsi Fpor GuardarDades() Avisar al cliente de que hemos finalizado la ejecución Control de excepciones Si Error Avisar al cliente del Error Si Error Grave Avisar al cliente del Error Grave Fcontrol 35 5.3 DISEÑO DEL SERVIDOR Para administrar correctamente el programa Servidor, el administrador debe llevar a cabo una serie de funciones de mantenimiento. Una de sus misiones principales será mantener en todo momento el la Interface remota registrada en el Servidor RMI, ya que en el momento que deje de estar registrada, ningún cliente podría conectarse para hacer peticiones, por tanto debemos proporcionar una herramienta de control del Registro, a ser posible que no sea manual. Esta herramienta será un Thread que se ejecutará cada 15 minutos y comprobará que la nuestra Clase esté registrada en el Servidor RMI, en caso de que no lo esté debe informar inmediatamente al administrador mediante la interficie Gráfica, con un Diálogo de error, o una frase que destaque dentro de la interficie. Para ello proporcionaremos al administrador dos funciones: - Registrarse en el Servidor - Desregistrarse del Servidor. La Otra misión que tendrá el administrador como tal es mantener la Base de Datos en correcto funcionamiento mientras se ejecute el programa. Esto implica que debemos proporcionar al administrador herramientas gráficas con las que poder gestionar la Base de Datos y corregir errores en caso de que se produzcan. Para esta función se proporcionará al administrador una serie de funciones que ayuden a modificar o comprobar la consistencia de la Base de Datos. - Añadir un Trabajo - Añadir un Trabajo desde las copias de Seguridad - Borrar un Trabajo - Borrar un Cliente - Comprobar la consistencia de la Base de Datos - Renovar la conexión del Programa con la Base de Datos. - Retornar a Pendiente un trabajo que lleve demasiado tiempo Asignado Además de estas funciones el administrador tiene que poder echar un vistazo a la Base de Datos en cualquier momento y de forma clara. Para todas estas tareas lo más adecuado seria que se pudieran ejecutar desde JDialogs que el programa generase al llamarlas el administrador. Por otra parte el contenido de la Base de Datos debe estar en todo momento en pantalla, por ejemplo con un JTabbedPane que nos permitiera en todo momento consultar tanto los trabajos como los clientes de la Base de Datos y ordenados según el gusto del administrador. Para la última función lo mejor sería que se ejecutara sin necesidad de que el administrador la demandara. Podemos construir un Thread que compruebe que si hay trabajos de ese tipo, los actualice y en caso necesario informe al administrador. Esta tarea la podríamos ejecutar una vez al día. Todas estas funciones deben ser accesibles desde la Ventana principal de la interficie gráfica, y deben informar inmediatamente al usuario si detectan un fallo tal y como hacemos si se cae el Registro RMI. La última misión del Servidor será la de llevar un registro diario de los sucesos que se generen en nuestro Programa, tales como los registros de usuarios, las actualizaciones de los distintos trabajos, y cualquier operación que se realice con la base de Datos, debe quedar registrada para que el administrador pueda consultarlos en un futuro. También podemos dar la posibilidad al administrador de guardar una copia del estado de cualquiera de las Tablas de la Base de Datos para su posterior Consulta. Todos estos archivos de historial generados podríamos guardarlos en un directorio ‘Log’, y dentro de este en un directorio con la fecha en que se guardaron para facilitar la consulta posterior. Tampoco estaría de más dejar que el administrador consulte los propios trabajos, ya sean pendientes, asignados, o los resultados obtenidos de uno de ellos. 36 Por último hay que implementar herramientas gráficas para que el administrador pueda ejercer esas consultas de historial desde la ventana principal del programa Servidor, y no por ejemplo desde el explorador de archivos. Por lo tanto nos encontraríamos con las siguientes funciones: - Consultar un archivo de Log - Consultar un Trabajo. Todos los archivos de los trabajos de la BD tienen que estar guardados en sus directorios correspondientes para facilitar el acceso de las tareas del Servidor. Nosotros crearemos 4 directorios en nuestro Servidor: - Treballs -> Contendrá todos los trabajos no completados, es decir, los pendientes y los asignados. - Completats -> Contendrá todos los trabajos completados. - NoAfegits -> Contendrá los trabajos que no están contenidos todavía en nuestra BD. - Backup -> Contendra una copia de todos los trabajos antes de ser completados para que en caso de que uno se extravíe podamos recuperarlo. Además de todo esto contaremos al igual que en el Cliente con una serie de Variables globales y funciones para modificarlas desde las diferentes Clases. Dades.java estat -> Estado actual del Servidor RMI peticions -> Nº de peticiones en curso petDescarrega -> Peticiones de Descarga en Curso petTransfer -> Peticiones de Envío en Curso petRegistre -> Peticiones de Registro en Curso Además de las funciones para modificarlas o acceder a ellas, todas ellas estáticas. Una vez visto todo esto procedemos a diseñar las dos partes del Servidor: 1. Base de Datos 2. Interficie Grafica El diseño de las funciones Remotas ya lo hemos visto en el apartado 5.1 37 5.3.1 DISEÑO DE LA BASE DE DATOS Para la Base de Datos del Programa sólo son necesarios dos tablas, una para guardar los Trabajos, y otra para guardar los Clientes. 1. Tabla Treballs: En esta tabla guardaremos toda la información concerniente a los trabajos que tenemos. La descripción de la Tabla será: Campo NomFitxer Tipo Descripción Clave Primaria, es el nombre del fichero asociado al trabajo con este mismo nombre. Indica la prioridad con que se descargará el trabajo Indica si el trabajo está pendiente de ser asignado (0), asignado (1), o Completado (2) Es el login del Cliente al que está asignado el trabajo, o por el que ha sido completado Fecha en que se asignó, o se completó el trabajo varchar(20) Prioritat varchar(1) Estat int User varchar(10) Data date 2. Tabla Clients En esta tabla almacenaremos a los clientes que se registren en nuestra Base de Datos. Campo user Tipo Descripción Clave Primaria, es el login del Cliente. Es el nombre que del usuario cliente. nº de trabajos que el cliente ha completado. Es la última fecha en que el cliente hizo una petición de función remota. varchar(10) Nom TrebComp varchar(40) int Data date 38 Además debemos proporcionar al Programa una serie de funciones que nos permitan trabajar con estas Tablas. Para ello implementamos la Clase MetodesBD donde implementaremos estas funciones. Todas estás funciones serán Estáticas y síncronas: 5.3.1.1. MetodesBD.java IniBD() Establece la conexión con la base de Datos a través de API de JDBC com.MySQL.driver. String agafarTreball() retorna el nombre del primer trabajo disponible según la prioridad. int comprobarUser(String user) retorna 1 si el usuario existe en la Base de Datos, y 0 sino existe int comprobarAssignacio(String user, String nomTreball) retorna 1, si el campo user del trabajo que le pasamos por parámetro es igual al String user que le pasamos, 0 sino. int guardarUser(String user, String nomClient) retorna 1 si ha guardado al nuevo usuario y 0 si ya existe un usuario con ese login int guardarPendent(String nomTreball, String Prioritat) guarda el nuevo trabajo en la BD con la prioridad indicada. El campo user por defecto es ‘zzzzzzzzz’ y el campo data es ‘null. El campo estat como es obvio es ‘PENDENT’. 1 si todo bien, 0 si el trabajo ya existe int guardarAssignat(String user, String nomTreball) del trabajo indicado actualiza los campos estat ‘ASIGNAT’, user -> user, data -> captura la fecha de ese día. También del Cliente user, actualiza el campo data con la fecha de ese día. 1 si todo bien, 0 si el trabajo no existe. int guardarComplet(String user, String nomTreball) del trabajo indicado actualiza los campos estat ‘COMPLET’, data -> captura la fecha de ese día. 1 si todo bien, 0 si el trabajo no existe. int tornarAPendent(String nomTreball) actualiza el trabajo a pendiente inicializando los campos user y data, estat -> PENDENT 1 si todo bien, 0 si no existe el trabajo int actualitzarUser(String user) Aumenta los trabajos completados del cliente user y actualiza la fecha de conexión 1 si todo bien, 0 si no existe el cliente. int actualitzarPrioritat(String nomTreball, String Prioritat) cambia la prioridad del trabajo nomTreball. 1 todo bien, 0 el trabajo no existe 39 int decUser(String user) decrementa en 1 los trabajos completados del Cliente user, ya actualizamos la fecha. 1 todo bien, 0 el Cliente no existe int borrarClient(String user) Elimina de la tabla Clients al Cliente user. 1 todo bien, 0 el cliente no existe int borrarTreball(String nomTreball) Elimina de la tabla Treballs el trabajo nomTreball 1 todo bien, 0 el trabajo no existe String[][] llistarClients(int mode) Retorna una tabla con los datos de todos los clientes ordenados según mode. Mode 1 -> login del Cliente Mode 2 -> nombre del Cliente Mode 3 -> nº de trabajos completados Mode 4 -> fecha String[][] llistarPendents(int mode) Retorna una tabla con los datos de todos los trabajos donde estat = ‘PENDENT’. Ordenados según mode. Mode 1 -> nombre del Trabajo Mode 2 -> Prioridad del Trabajo String[][] llistarAssignats(int mode) Retorna una tabla con los datos de todos los trabajos donde estat = ‘ASSIGNAT’. Ordenados según mode. Mode 1 -> nombre del Trabajo Mode 2 -> login del Cliente Mode 3 -> fecha de asignación String[][] llistarCompletats(int mode) Retorna una tabla con los datos de todos los trabajos donde estat = ‘COMPLET’. Ordenados según mode. Mode 1 -> nombre del Trabajo Mode 2 -> login del Cliente Mode 3 -> fecha de asignación String[][] llistarTreballs(int mode) Retorna una tabla con información de todos los trabajos de la BD. Ordenados según mode Mode 1 -> nombre del Trabajo Mode 2 -> Prioridad del Trabajo Mode 3 -> login del Cliente Mode 4 -> fecha de asignación Mode 5 -> estado del trabajo int nombreClients() retorna el nº de Clientes que contiene la Tabla. int nombrePendents() retorna el nº de trabajos pendientes que contiene la Tabla int nombreAssignats() 40 retorna el nº de trabajos asignados que contiene la Tabla int nombreCompletats() retorna el nº de trabajos completados que contiene la Tabla int nombreTreballs() retorna el nº de trabajos que contiene la Tabla String[][] TreballsCaducats() Esta función retorna una tabla con todos los trabajos cuyo campo estat = ‘ASSIGNAT’ y cuya fecha sea menor o igual a la fecha de hace 5 días. int revisarBD() Por cada trabajo que se encuentre en la base de datos, comprueba que el fichero asociado está donde debe estar, si no es así, borra el trabajo, e informa al usuario a través de un fichero de log. void recuperarConexio() Restablece la conexión con la base de Datos a través de API de JDBC com.MySQL.driver. Esta función debe ejecutarse si en algún momento se cae MySQL. void tancarConexio() Cierra la conexión con el API Como vemos el control de la Base de Datos requiere muchas más funciones de las que podríamos pensar debido a la sencillez de la tablas. Todas las funciones generan la excepción SQLException, que es tratada fuera de esta clase por la Clase que utiliza las funciones. Si esta excepción fuera generada, el Servidor tiene que informar inmediatamente al administrador que la conexión que MySQL se ha perdido, o bien que MySQL no está en funcionamiento, para que el administrador resuelva el problema lo antes que pueda. 41 5.3.2 DISEÑO DE LA INTERFICIE GRÁFICA DEL SERVIDOR La interficie gráfica con la que el administrador trabajará será una ventana principal JFrame desde la cual se podrá acceder rápidamente a todas las funciones que hemos descrito. Dividiremos la interficie en tres partes: 5.3.2.1. Barra de Menús: La Barra de menús como en toda aplicación ocupará la parte superior de la pantalla y constituirá la herramienta principal para gestionar la Base de Datos, Registrar o Anular el registro en el Servidor RMI, y consultar los archivos de Trabajo o de Log. Puesto que se trata de tres tareas diferenciadas crearemos tres menús: 5.3.2.1.1. Menú Servidor: Desde este menú podremos registrar o anular el registro RMI. Antes de describir estas dos funciones veremos el diseño del Thread descrito anteriormente que se encarga de comprobar que estamos registrados en el Servidor cada 15 minutos, ya que esta muy relacionado con estas dos funciones. ComprovacioRMI.java Run() Parar = false mientras (no parar) Dormir 15 minutos Comprobar registro Control de Excepciones Si registro no encontrado Parar = true Estat = ATURAT Avisar al administrador de que se ha perdido el Registro y tiene que volver a Registrarse. Fcontrol Fmientras Destroy() Parar = true Ahora si pasamos a describir las dos funciones: 42 Iniciar Servidor RMI Si estat = ATURAT Registrar nuestro Servidor en el Servidor RMI Crear nuevo comprovacioRMI Iniciar comprovacioRMI Estat = ENGEGAT Informar al administrador Sino Si estat = ACTUALITZANT Informar al administrador que en estos momentos el Programa esta realizando tareas de mantenimiento y no puede registrar al Servidor Sino Informar al administrador que nuestro servidor ya esta registrado. Fsi Fsi Control de excepciones Si no encontramos Servidor RMI Estat = ATURAT Informar al administrador que RMI no está en marcha. Fcontrol Parar Servidor RMI Si estat = ENGEGAT Si no hay peticiones en curso Anular el registro RMI Destruir comprovacioRMI Estat = ATURAT Sino Mostrar DialogPeticionsEnCurs Fsi Informar al administrador Sino Informar al administrador que nuestro servidor ya está anulado. Fsi Control de excepciones Si no encontramos Servidor RMI Estat = ATURAT Informar al administrador que RMI no está en marcha. Fcontrol Para informar al administrado en estas dos funciones utilizamos un área de Texto básicamente, un DialogError básicamente iguales a los que utilizamos en el Programa Cliente y además una Etiqueta que se distingue en la pantalla por se de Color Rojo y más grande que el Resto (Esta etiqueta solo se muestra en caso de errores críticos). DialogPeticionsEnCurs.java Este Diálogo nos informa de que en estos momentos el Servidor RMI tiene peticiones remotas que están atendiéndose. Y nos pregunta si queremos parar RMI igualmente. En caso de que aceptemos, se realiza la misma acción que hemos visto en la función ‘parar el programa’, con el mismo control de excepciones. 43 5.3.2.1.2. Menú BD Este menú nos permite realizar todas las operaciones que hemos mencionado anteriormente con al Base de Datos. Así pues como ya hemos dicho antes las funciones de este menú serán: Añadir Trabajo DialogAfegir.java Este diálogo constará de 4 partes: Tabla de Trabajos: Campo que nos muestra el nombre del trabajo seleccionado Combo donde podemos seleccionar la prioridad Botones -> aceptar, cancelar, backup Al mostrar este diálogo hacemos lo siguiente: Si directorio ‘NoAfegits’ existe Contenido de la Tabla = Contenido del Directorio Si hay Contenido Cargar Tabla Combo = 0 Mostrar Dialogo Sino Informar al administrador que no hay trabajos para añadir. Fsi Sino Crear directorio NoAfegits Aviso Importante Informar al administrador que se han perdido los trabajos para añadir Fsi El botón ‘backup’ nos permite acceder al contenido del Directorio ‘Backup’ que contiene las copias de seguridad de todos los archivos del Servidor. Por lo tanto pulsándolo realizamos la misma operación sobre el mismo diálogo pero mostrando el contenido de este directorio. Desde el que también podemos añadir cualquier fichero. Una vez hemos seleccionado el fichero que queremos añadir, ya sea un trabajo no añadido o una copia de Seguridad, y su prioridad tenemos dos opciones Aceptar Ocultar diálogo Si existe el directorio ‘NoAfegits’ o ‘Backup’ (depende que hagamos) Si MetodesBD.guardarPendent(trabajo, prioridad) = 1 Actualizar registro de sucesos Actualizar datos mostrados por pantalla Si existe directorio ‘Treballs’ Mover fichero de NoAfegits a Treballs ó Copiar fichero de Backup a Treballs Sino Crear directorio Treballs Actualizar Registro Avisar de Error Critico Mostrar DialogError (Perdidos todos los trabajos pendientes y asignados) Fsi 44 Sino Actualizar registro Error crítico (puede haber inconsistencia en la BD) Mostrar DialogError(El trabajo ya existe en la BD) Fsi Sino Crear directorio que pertoque Actualizar registro Avisar Error Critico Mostrar DialogError (Perdidos trabajos no añadidos, o copias de seguridad) Fsi Control de excepciones Si ExcepciónSQL Actualizar registro Avisar error crítico Mostrar DialogError(SQL no esta en marcha o perdida la conexión) Si Excepcion Actualizar registro Avisar error crítico Mostrar DialogError(Error al añadir trabajo) Fcontrol Cancelar Ocultar diálogo. 45 Borrar Trabajo DialogBorrar.java Este diálogo tendrá 4 partes Tabla de Trabajos Campo de texto que nos muestra el trabajo elegido Opción de borrar también el fichero asociado Botones -> borrar, cancelar Mostrar: Si existen los directorios ‘Treballs’ y ‘Completats’ Contenido Tabla = MetodesBD.llistarTreballs(1) Opción no seleccionada Sino Crear directorio Treballs o Completats o ambos Actualizar registro Aviso error crítico Mostrar DialogError (Perdida de trabajos) Fsi Control de excepciones Si ExcepciónSQL Actualizar registro Avisar error crítico Mostrar DialogError(SQL no esta en marcha o perdida la conexión) Fcontrol Borrar Ocultar dialogo Si MetodesBD.borrarTreball(trabajo) = 1 Si existe el fichero asociado Si opción está marcada Borrar Fichero Actualizar registro Sino Si estat = pendent o assignat Mover fichero de Treballs a NoAfegits Actualizar registro Fsi Sino Mostrar DialogError(perdido fichero de trabajo) Fsi Sino Actualizar registro Mostrar DialogError(el trabajo ya existe) Fsi Control de excepciones Si ExcepciónSQL Actualizar registro Avisar error crítico Mostrar DialogError(SQL no esta en marcha o perdida la conexión) Si Excepcion Actualizar registro Avisar error crítico Mostrar DialogError(Error al borrar trabajo) Fcontrol 46 Borrar Cliente DialogBorrarClient.java Consta de tres partes Tabla de Clientes Campo de texto Botones -> aceptar y cancelar Mostrar Si hay clientes Contenido tabla = MetodesBD.llistarClients(1) Sino Actualizar registro Mostrar DialogError (tabla clientes vacía) Fsi Control de excepciones Si ExcepciónSQL Actualizar registro Avisar error crítico Mostrar DialogError(SQL no está en marcha o perdida la conexión) Fcontrol Aceptar Ocultar Diálogo Si MetodesBD.borrarClient (selección) = 1 Actualizar registro Sino Actualizar registro Mostrar DialogError (Cliente no existe) Fsi Control de excepciones Si ExcepciónSQL Actualizar registro Avisar error crítico Mostrar DialogError(SQL no está en marcha o perdida la conexión) Si Excepción Actualizar registro Avisar error crítico Mostrar DialogError(Error al borrar cliente) Fcontrol 47 Cambiar la prioridad de un Trabajo DialogCanviPrioritat.java Las partes de este diálogo son idénticas a las del DialogAfegir, pero sin el botón de Backup. Sólo podemos cambiar la prioridad de un trabajo pendiente. Mostrar Si existe el directorio ‘Treballs’ Contenido Tabla = MetodesBD.llistarPendents(1) Prioridad = leer prioridad de la tabla Sino Crear directorio Actualizar registro Aviso error crítico Mostrar DialogError (Perdidos trabajos pendientes y asignados) Fsi Control de excepciones Si ExcepciónSQL Actualizar registro Avisar error crítico Mostrar DialogError(SQL no está en marcha o perdida la conexión) Si Excepción Actualizar registro Avisar error crítico Mostrar DialogError(Error al cambiar prioridad) Fcontrol Aceptar Ocultar diálogo Si MetodesBD.canviarPrioritat(trabajo,prioridad) = 1 Actualizar registro Sino Error crítico (puede haber inconsistencia en la BD) Mostrar DialogError (El trabajo no existe) Fsi Control de excepciones Si ExcepciónSQL Actualizar registro Avisar error crítico Mostrar DialogError(SQL no está en marcha o perdida la conexión) Si Excepción Actualizar registro Avisar error crítico Mostrar DialogError(Error al cambiar prioridad) Fcontrol 48 Revisar la Base de Datos Esta función no necesita Diálogo ya que es un proceso de recorrido de la tabla Treballs de la BD. Mejor la construiremos como un Thread, para que su ejecución sea más dinámica conjuntamente con la interficie gráfica. RevisarBD.java Run() Result = MetodesBD.revisarBD() Si result = 1 Actualizar registro, no hay ninguna incosistencia Sino Actualizar registro Mostrar DialogError (Se han detectado inconsistencias en la BD, consulta el fichero de hoy ‘revisioBD’) Fsi Control de excepciones Si ExcepciónSQL Actualizar registro Avisar error crítico Mostrar DialogError(SQL no está en marcha o perdida la conexión) Si Excepción Actualizar registro Avisar error crítico Mostrar DialogError(Error al revisar la BD) Fcontrol Recuperar la Conexión Esta función tampoco necesita Dialogo ya que es muy rápida y sencilla Únicamente ejecuta la función MetodesBD.recuperarConexio() haciendo un control de excepciones como los vistos hasta ahora. Ya fuera del menú BD pero directamente relacionado encontramos también una tarea que trabaja con la BD. Esta tarea se encargará una vez al día de repasar los trabajos asignados que tenemos en nuestra BD y aquellos que lleven más de 5 días asignados, se modificará su estado a Pendiente. Es una forma de asegurarnos que ningún trabajo se quedará sin realizar a causa de que un cliente decida darse de baja. Será un Thread que se ejecute cada hora, si estamos entre las 11 y las 12 de la noche se ejecuta, sino, vuelve a dormir. Aprovechando que se ejecutar 1 vez al día, guardaremos una copia del registro, y lo inicializaremos. 49 ComprovacioCaducitat.java Mientras true Si hora actual entre 23 y 24 Guardar Registro Inicializar Registro Actualizar Registro Si estat = ENGEGAT CompRMI.destroy() Anular registro RMI Fsi Estat = ACTUALITZANT Contenido = MetodesBD.TreballsCaducats Si contenido no es nulo Por cada trabajo MetodesBD.tornarAPendent() Actualizar Registro Anotar en el fichero renovacióBD.log todos los cambios que se efectúen Actualizar Registro Sino Anotar en el fichero que no hay cambios en la BD Actualizar Registro Fsi Actualizar Registro (hemos acabado) Si hemos parado el Servidor RMI Registrarnos en el Servidor Iniciar ComprovacioRMI Estat = ENGEGAT Sino Estat = ATURAT Fsi Control de excepciones Si no encontramos Servidor RMI Estat = ATURAT Actualizar registro Avisar error crítico Mostrar DialogError(RMI parado) Si ExcepciónSQL Actualizar registro Avisar error crítico Mostrar DialogError(SQL no está en marcha o perdida la conexión) Si Excepción Actualizar registro Avisar error crítico Mostrar DialogError(Error al renovar la BD) Fcontrol Sino Dormir 1 hora Fsi FMientras 50 5.3.2.1.3. Menú Consulta Por último este menú es el que nos permite consultar los datos referentes al historial de nuestro programa y también el contenido de los trabajos que tenemos almacenados en nuestra base de Datos. Las acciones que podremos realizar desde este menú serán las siguientes: Consultar un archivo de ‘Log’ Para hacer más accesible al administrados esta función la realizaremos como todas las anteriores mediante Diálogos. Por lo visto hasta ahora nos podemos encontrar con los siguientes tipos de archivos log: - Archivos de contenido de Base de Datos • Trabajos • Trabajos pendientes • Trabajos asignados • Trabajos completados • Clientes - Archivos de sucesos • Registro de sucesos • Registro de errores críticos • Revisión de la Base de Datos • Registro de trabajos actualizados por estar caducados DialogConsulta.java Este Diálogo nos permitirá acceder a un pequeño explorador de archivos de fabricación propia que consiste en una tabla que nos muestra el contenido del Directorio ‘Log’, después nos permite abrir sus directorios y mostrar su contenido, o bien volver atrás al directorio ‘Log’. Una vez seleccionado el archivo a mostrar, cerraremos este dialogo y abriremos otro con el contenido del fichero. Así pues este dialogo tendrá tres partes - Tabla -> Explorador de archivos - Campo con la selección - Botones -> Subir un nivel, abrir, cancelar Mostrar Si existe directorio ‘Log’ Contenido de Tabla = contenido del Directorio Sino Crear directorio Actualizar registro Aviso error crítico Mostrar DialogError (Perdido historial) Fsi Subir un nivel Si no estamos en el directorio ‘Log’ Si existe directorio ‘Log’ Contenido de Tabla = contenido del Directorio Sino Crear directorio Actualizar registro Aviso error crítico Mostrar DialogError (Perdido historial) Fsi Fsi 51 Abrir Si estamos en directorio ‘Log’ Si directorio seleccionado es correcto y existe Contenido Tabla = contenido directorio seleccionado Sino Volver a Directorio ‘Log’ Fsi Sino Ocultar Dialogo Mostrar DialogVeureArxiu (fichero seleccionado) Fsi Control de excepciones Si Fichero no existe Actualizar registro Avisar error crítico Mostrar DialogError(Fichero de Log perdido) Si Fichero alterado Actualizar registro Avisar error crítico Mostrar DialogError(Fichero de Log alterado) Si otra excepción Actualizar registro Avisar error crítico Mostrar DialogError(Error al mostrar fichero) Fcontrol DialogVeureArxiu.java Este Diálogo tiene dos modalidades. Según tenga que mostrar un fichero de contenido de BD, o uno de texto. Para los archivos de BD, el diálogo se presenta con una Tabla que muestra el contenido, y un botón para cerrar el diálogo. Para los archivos de texto el modelo es el mismo, pero en lugar de una tabla los datos se presentan en un área de Texto. 52 Consultar un Trabajo En el menú de consulta dejaremos que el administrador decida que tipo de trabajo quiere consultar. El Diálogo que mostraremos en cada caso será el mismo, pero con distinto parámetro, según el Dialogo. DialogResultats.java Tendrá tres partes: - Una tabla en la que se muestran los archivos que podemos ver - Campo de selección - Botones -> aceptar, cancelar Mostrar Si directorios Treballs y Completats existen Si mostramos trabajos completados Contenido Tabla = Trabajos Completados Si mostramos trabajos asignados Contenido Tabla = Trabajos asignados Si mostramos trabajos pendientes Contenido Tabla = Trabajos pendientes Sino Crear directorio Actualizar registro Aviso error crítico Mostrar DialogError (Perdidos trabajos) Fsi Control de excepciones Si ExcepciónSQL Actualizar registro Avisar error crítico Mostrar DialogError(SQL no está en marcha o perdida la conexión) Fcontrol Aceptar Ocultar Dialogo Mostrar DialogVeureTreball Control de excepciones Si Fichero no existe Actualizar registro Avisar error crítico Mostrar DialogError(Fichero de Log perdido) Si Fichero alterado Actualizar registro Avisar error crítico Mostrar DialogError(Fichero de Log alterado) Si otra excepción Actualizar registro Avisar error crítico Mostrar DialogError(Error al mostrar fichero) Fcontrol DialogVeureTreball.java Es básicamente igual que el DialogVeureArxiu, pero solo necesita un área de texto para mostrar ficheros, ya que no necesita mostrar contenido de BD. 53 5.3.2.2. Zona de Control del Estado del Servidor. Esta zona ocupara el la mitad superior de la ventana principal de la Aplicación. Constará de dos partes o paneles: - En el panel izquierdo mostraremos todos los datos que maneja el programa mediante etiquetas que serán los siguientes: Estado del Servidor Peticiones en Curso Peticiones de Descarga Peticiones de Envío Peticiones de Registro Clientes Registrados Trabajos en la BD Trabajos Pendientes Trabajos Asignados a Clientes Trabajos Completados Alarma Esta última etiqueta se pone en rojo cuando se produce un error considerado como crítico para el funcionamiento de la Base de Datos. El administrador debe reaccionar rápidamente y arreglarlo. PanelDaltEsq.java Además de estas etiquetas el panel proporciona una función para cambiar su contenido indicando el número de la etiqueta que queremos cambiar, no podemos cambiarla directamente. Cada vez que desde alguna de las clases se cambie el valor de alguno de estos campos, se procederá a actualizar su etiqueta correspondiente. En el panel Derecho mostraremos un área de texto donde irán apareciendo todos los sucesos que ocurren durante la ejecución. Dicha área de texto no es editable. PanelDaltDret.java Además del Área de texto, para escribir dichos mensajes, este panel nos proporciona la función ‘afegirText(text)’ que nos permite escribir en el área de texto desde cualquier clase. En los pseudocódigos vistos hasta ahora se ha puesto como “Actualizar Registro”, o Informar al Administrador. Cada vez que se produzca un evento, ya sea un error, una petición, una operación en la BD, aparecerá reflejada en este registro. Además de esta función este panel también nos proporciona la función ‘guardarRegistre()’ que guarda el contenido del registro en el archivo ‘/Log/fecha/incidencies.txt’ para una posterior consulta del administrador. Esta función además de ejecutarse cada vez que se cierra el programa. Se Ejecuta cada día al menos una vez mediante el Thread ComCaducita.java, que veremos más adelante. También permite inicializar el área de texto mediante la función ‘iniRegistre()’. 54 5.3.2.3. Zona de Control de la Base de Datos. Esta zona ocupa el resto de la ventana, es decir, la mitad inferior. Desde esta zona, podemos consultar en un momento el contenido de cualquiera de las Tablas de que disponemos en nuestra Base de Datos, ordenarla a nuestro gusto para encontrar antes lo que buscamos, y realizar copias del contenido actual de las Bases de Datos. Esta zona esta compuesta de un JTabbedPane en el que colocaremos hasta 6 paneles en los que añadiremos la información descrita en el párrafo anterior. Esta clase será Selector.java. Y los 6 paneles que contendrá serán los siguientes: - PanePanel1 -> Todos los Trabajos PanePanel2 -> Trabajos Pendientes PanePanel3 -> Trabajos Asignados PanePanel4 -> Trabajos Completados PanePanel5 -> Clientes Registrados PanePanel6 -> Éste se sale un poco de la dinámica de esta zona, ya que nos muestra los avisos considerados como Error Crítico Procederemos ahora a describir los paneles. PanePanel1.java El panel contiene la siguiente información - Tabla con el contendido de la Tabla Treballs que ocupa la mayor parte del panel. Esta tabla no es editable ni da acceso a ninguna función de la Base de Datos, es simplemente una herramienta de Consulta, o Control del contenido de la Tabla. - Opciones de ordenación de la Tabla. En la parte derecha superior del panel. El panel te permite ordenar la tabla según distintos campos. En este caso: • Nombre del Trabajo • Prioridad • Login del Cliente • Fecha de asignación / finalización • Estado del Trabajo - Botón Guardar en la parte derecha inferior. Este botón muestra el dialogo DialogGuardarFitxer, que se encarga de guardar toda la información de la tabla en el Fichero /Log/fecha/Treballs.txt. Para su posterior Consulta. El Constructor del panel, carga la tabla con la función MetodesBD.llistarTreballs(1) que ordena la tabla según el nombre. Cada vez que cambiamos el orden con que queremos visualizar la tabla, se genera un evento que tratamos en el panel actualizando la Tabla. Esto se hace llamando de nuevo a la función MetodesBD.llistarTreballs(opción). El resultado de la función se carga en la Tabla. El Panel también nos proporciona una función para que podamos actualizar la Tabla desde las demás Clases. La función ActualizarPane1() la usan el resto de clases cada vez que realizan una operación en la BD. Así nos aseguramos que los datos mostrados por la tabla son en tiempo real. Por último, el botón Guardar nos muestra el Diálog DialogGuardarFitxer, que es un diálogo por simple cuestión estética, ya que no permite hacer nada, simplemente muestra un pequeño diálogo vacío con el título “Guardando Datos” Si el Panel al cargar una de las Tablas detecta un Error SQL, informa inmediatamente al administrador de que SQL no funciona o se ha perdido la conexión, y muestra la ‘Alarma’. 55 La implementación de los 5 primeros paneles es muy parecida, y sólo varia el numero de columnas de la Tabla, y las opciones de ordenación disponibles. Por supuesto también varia la función de MetodesBD que utilizamos para llenar el Contenido de la Tabla en cada panel, pero eso resulta obvio. El resto de Características son las mismas. PanePanel2.java - Modos de ordenación • Nombre del Trabajo • Prioridad Fichero que guarda -> TreballsPendents.txt Función de la BD que utiliza -> MetodesBD.llistarPendents(mode) PanePanel3.java - - Modos de ordenación • Nombre del Trabajo • Login del Cliente • Fecha de Asignación Fichero que guarda -> TreballsAssignats.txt Función de la BD que utiliza -> MetodesBD.llistarAssignats(mode) PanePanel4.java - - Modos de ordenación • Nombre del Trabajo • Login del Cliente • Fecha de Asignación Fichero que guarda -> TreballsCompletats.txt Función de la BD que utiliza -> MetodesBD.llistarCompletats(mode) PanePanel5.java - - Modos de ordenación • Login del Cliente • Nombre del Cliente • Trabajos Completados • Fecha última conexión Fichero que guarda -> Clients.txt Función de la BD que utiliza -> MetodesBD.llistarClients(mode) PanePanel6.java Como ya hemos dicho este panel es distinto al resto, tiene el título de “Avisos Importantes”. Es básicamente un registro igual que el de la Zona de Control del Servidor, pero sólo muestra los mensajes que se deben a errores críticos en el Servidor. Además ofrece la posibilidad de Guardar los datos en un Fichero, y también de Borrar el contenido del Registro. Sus componentes son pues: - Área de texto donde se escriben los errores - Dos botones -> borrar y guardar. Cuando mostramos este panel, se ‘apaga la alarma de avisos críticos, ya que se entiende que el administrador los ha visto. 56 La interficie gráfica de la aplicación carga al ejecutarse estas tres zonas para que el administrador pueda en todo momento disponer de ellas. Además de todo esto, la interficie necesita de algunos diálogos más para su correcta comunicación con el administrador: DialogError.java Es el mismo para todas las clases, se pasa por parámetro a todos los constructores, así nos aseguramos que tenemos siempre controlada su visibilidad. Cuando ejecutamos la opción de salir del programa pueden darse 2 supuestos. • Que el Servidor RMI este registrado. El Programa informa al administrador que no puede cerrar el Programa sin antes anular el registro en el Servidor RMI mediante un DialogError. • Ninguna de las dos anteriores. El Programa nos muestra un DialogFinal que es básicamente igual que el del Programa Cliente. DialogFinal.java Si elegimos la opción ‘SI’ el DialogFinal se oculta, el Frame principal también se oculta, y la interficie gráfica nos muestra un pequeño diálogo mientras guarda todos los datos del Programa. DialogTancament.java Lo único que hace es guardar una copia del Registro en los archivos de ‘Log’ Por último necesitamos unos Frames especiales que se desplieguen en caso de que al Cargar el programa Cliente nos encontremos con Errores críticos que no nos permitan su correcto funcionamiento. Todos ellos una vez cerrados, salen del programa: Estos son DialogNoInici.java Nos comunica que ya existe una aplicación Servidor en funcionamiento y por lo tanto no se puede ejecutar una copia. DialogNoSQL.java MySQL no está en funcionamiento, por lo tanto es imposible cargar la BD, con lo que no se puede ejecutar el Servidor. Necesitamos poner en marcha SQL. Unos últimos apuntes sobre la interficie gráfica. - Todos los Diálogos gracias a Swing se pueden controlar mediante el Teclado, sin necesidad del Ratón - Todos los Diálogos son modales, es decir mientras estén visibles la Ventana principal esta inactiva 57 6. CONCLUSIONES En líneas generales se han cumplido todas las expectativas que me había marcado al iniciar este proyecto. El Programa Servidor de Trabajos proporciona todas las herramientas necesarias para llevar a cabo una correcta gestión y actualización de una considerable cantidad de información, ya que la Base de Datos actual almacena unos 7000 trabajos. Además el hecho de almacenar en la Base de Datos únicamente la información que necesita el Servidor, dejando en los fichero la información propia del trabajo, dota al Servidor de una considerable independencia del tipo de estudio que realicemos. En caso de funcionamiento óptimo, el administrador no tiene que preocuparse de nada, ya que el Servidor por si sólo es capaz de registrar clientes, enviar y recibir trabajos, y actualizar toda la información, y llevar a cabo una política de actualización de trabajos que corren el peligro de no ser completados. Por otra parte es un programa muy robusto capaz de detectar todos los errores que se pueden producir, corregirlos en su caso, y avisar inmediatamente al administrador en caso de que se le necesite para resolver el problema. Podría haberse mejorado el Servidor haciendo que la Base de Datos fuese mucho más estricta, por ejemplo impidiendo repeticiones de Nombre de los clientes, o impidiendo que un cliente pudiera tener más de dos trabajos asignados, y en caso de que se fuera a dar ese caso, el servidor reaccionar reenviándole el trabajo que tenía anteriormente, etc... El Programa Cliente por su parte cumple de sobras su función distributiva, y puede realizar su función sin que el usuario tenga que estar pendiente de su trabajo, únicamente se le pide que lo encienda, y que lo pare. También es capaz de detectar los errores de conexión con el Servidor y parar el programa en caso de no obtener respuesta. Por otra parte, tanto el Cliente como el Servidor, son casi completamente independientes del tipo de estudio que queramos realizar. Quizá la única pega que podríamos encontrar en este sentido es el hecho de que las funciones de mostrar los trabajos son especificas para este ‘estudio’, se podrían haber puesto en un paquete independiente para que pudiésemos cambiar el tipo de Trabajo con sólo cambiar este paquete. El resto de operaciones tanto del Servidor, como del Cliente son válidas para cualquier tipo de trabajo, siempre que este trabaje con ficheros, y no necesite mostrar más información de que muestra este. En cuanto a la utilización de RMI para la comunicación entre Servidor y Cliente ha sido una elección acertada, ya que nos proporciona una manera de pasarnos información entre ambos, con la facilidad que supone llamar a un simple método, sin la necesidad de que el programador tenga que usar funciones específicas de red. La función de Registrar usuario por ejemplo se realiza íntegramente con parámetros de entrada y de Salida. Para las funciones de transferencia y Dado el tipo de trabajo que realizamos, podríamos decir que desaprovechamos la funcionalidad de RMI al utilizar sockets para la transferencia de ficheros, podríamos haber enviado o devuelto la información a través de Strings que fueran luego tratados en la máquina de destino. Pero de esta forma perderíamos la independencia del Trabajo de que hemos hablado anteriormente ya que con un trabajo de tratamiento de imágenes por ejemplo, no podríamos retornar el resultado mediante un parámetro serializable, ni enviar los de entrada tampoco. La interfaz gráfica tanto del usuario como del cliente es muy completa, y permite al Servidor tener acceso a todo el contenido de la Base de Datos rápidamente, así como a todas las funciones, mientras que el cliente puede entretenerse simplemente mirando el progreso del simulador. También puede considerarse un tremendo acierto el uso de Swing para el diseño de la interfaz gráfica. Al inicio del proyecto la diseñé con AWT, lo cual ofrecía un aspecto mucho más precario, y el modelo de delegación de eventos era más rudimentario. Swing aparte de ser compatible con cualquier plataforma da una apariencia mucho más agradable a la interfaz. 58 Todo y no ser una de las partes más importantes del proyecto, el programa de Cálculo intensivo a realizar resultó una de las tareas más complicadas del proyecto, no por la complejidad que requiere, sino por elegir el apropiado. Tras muchos intentos con procesamiento de video o imágenes, me decidí por este simulador de incendios a partir de una pagina de la facultad de ciencias medioambientales de la UAB, ya que podía construir uno propio a partir de las instrucciones de su funcionamiento, sin necesidad de estudiar ninguna librería de java acerca del procesamiento de video por ejemplo. Al final ha sido una elección acertada ya que en determinados momentos de ejecución alcanza el 100% de utilización de la CPU, y se ha hecho de manera que el programa en si sea semiindependiente de la interfaz del Cliente y del programa principal, necesitando sólo una serie de funciones para comunicarse con el estado actual de este, comunicar su propio estado al cliente, e implementar una visualización gráfica acorde con las condiciones del cliente. Como posible mejora estaría el hecho de poder accionar su funcionamiento mediante un salvapantallas tal y como hace el programa SETI@home, lo que haría completamente innecesaria la función de un usuario salvo que este lo deseara. Otro pequeño problema que presenta la aplicación, es que la comunicación entre distintas máquinas es un poco lenta, pero la investigación de estos problemas de la red no formaba parte de los objetivos que me había marcado. Resumiendo creo que la Aplicación es capaz de gestionar y realizar de manera bastante eficiente cualquier problema que necesite de computación distribuida para llevar a cabo su estudio. 59 7.- BIBLIOGRAFIA Tanto para el Desarrollo de la Aplicación Servidor Cliente como para la elaboración de este informe me he basado en la información que he sacado de las siguientes URLs: http://java.sun.com http://www.programacion.com/java/tutorial http://www.programacion.com/java/tutorial/rmi http://www.itapizaco.edu.mx/paginas/JavaTut http://www.eclipse.org http://www.mysql.com http://www.gridcomputin.com http://boinc.berkeley.edu/ http://setiathome.berkeley.edu/sah_bout.php http://jsmooth.sourceforge.net/index.php Además de otras muchas páginas que he consultado a lo largo de la elaboración del proyecto sobretodo tutoriales y foros de los cuales no recuerdo el nombre. 60 ANEXO A : MANUAL DEL CLIENTE A.1. Instalación y Requisitos Al no genera código ejecutable, un programa Java necesita de una maquina virtual java para ejecutarse, o lo que es lo mismo un entorno (run-time). Por lo tanto para que el Cliente funcione, lo único que necesitamos es que nuestro ordenador posea dicho entorno. Tenemos que instalar JRE (Java Runtime Enviroment) si nuestro ordenador no lo posee. También al ser un programa que realiza llamadas a funciones remotas, necesitamos el API de Java que nos permite realizarlas. Podemos coger la librería de java generation.jar. Por último también necesitamos las clases de la interfaz remota que el servidor nos proporciona a través del archivo server.jar que contiene las clases donde el cliente encontrará las funciones remotas. Para la instalación y ejecución del programa en si podemos optar por dos opciones: 1. Ejecutar el programa con la maquina virtual Java Para esto necesitamos tener en el mismo directorio todos los paquetes que va a utilizar nuestro programa. Así pues pondremos en el mismo directorio los paquetes calculIntesiu, client, interfaceRMI, il(generation.jar). este último es el fichero generation.jar descomprimido. Seguidamente ejecutamos la instrucción java -Djava.security.policy=java.policy client.ProgramaClient y pondremos en marcha el programa. java.policy es un archivo que contiene los permisos que otorgamos al programa. Es el siguiente: grant { permission java.net.SocketPermission "*:1000-65535" , "connect,accept"; permission java.io.FilePermission "C:\\-" , "read,write,delete"; }; 2. Generar un fichero ejecutable Existen aplicaciones que generan archivos .exe a partir de Bytecodes Java. Uno de estos programas es Jsmooth, que a partir de un fichero .jar construye un ejecutable. Una vez generado el ejecutable, lo ponemos en el mismo directorio donde tengamos el paquete il, interfaceRMI (estos dos paquetes siguen necesitándose aparte), el fichero java.policy, y el fichero server (donde escribimos el servidor por defecto). Y ya podemos ejecutarlo. De esta forma perdemos una de las principales características de java, que es su independencia de la plataforma en que la ejecutemos, pero es más cómodo para el usuario de windows. Nota : El fichero ‘server’ lo necesitaremos en ambos casos. 61 A.2. Bienvenido al Programa. La Primera vez que ejecutemos el Programa esta será la imagen que nos encontraremos en la pantalla. Este es el Diálogo de presentación del programa. Como vemos consta de un cuadro en el que se nos da la Bienvenida como nuevos clientes de este grupo de Trabajo, y se nos pide un login y un nombre para poder registrarnos. La parte de abajo nos mostrará el resultado de la operación de registro según la efectuemos correctamente o no, y según la disponibilidad o no del Servidor. Estos pueden ser los posibles errores que nos podemos encontrar, y las distintas reacciones que tendrá el programa: 1. Intentar comenzar sin estar registrados. 2. Intentar registrarnos sin rellenar los campos: 3. Que no Tengamos conexión a internet 62 4. Que el Servidor no esté Disponible en ese momento. 5. Que nuestro login ya este en uso en la BD del Servidor Los Errores 2 y 4 también nos los podemos encontrar cuando cargamos el programa, por ese motivo si esto pasa, el display ya nos muestra el error antes de hacer nada. Para que no nos molestemos en intentar hacer el Registro. A.3. Registro Completado Si Todo va bien y el Servidor está disponible, nuestra conexión a internet funciona correctamente, rellenamos los campos, y nuestro login no está repetido, nos aparecerá el siguiente mensaje, y ya podremos empezar la ejecución del programa Cliente. 63 A.4. Primera Ejecución: Al elegir la opción de empezar el programa nos encontramos con la ventana principal del Programa Cliente. Este es su aspecto en nuestra primera ejecución: Observemos los componentes del Programa uno a uno: En la parte superior izquierda nos aparece este cuadro que nos muestra cual el es estado actual del programa así como también los datos del Cliente. Login, Nombre, Trabajos completados, Trabajo actual en proceso, tiempo de CPU, y de transferencia. 64 En la parte superior central nos encontramos con este pequeño recuadro que permite al usuario controlar el programa. Si miramos ahora a la parte superior derecha, observamos el registro de sucesos, en esta parte irá apareciendo conforme se produzca información de qué es lo que está haciendo el Programa en cualquier momento. Por último la parte inferior de la pantalla está reservada al Simulador de Incendios. Esta zona nos muestra información sobre cual es el estado actual de la Simulación. Como vemos es bastante llamativa, para que capte rápidamente la atención del usuario. 65 A.5. Configuración del Programa: Aunque pocos, el programa cliente nos permite configurar una serie de parámetros para nuestra comodidad. Así pues pulsando el botón de configuración nos aparece el siguiente diálogo: Con este diálogo podemos hacer dos cosas, cambiar el servidor al que nos conectamos, cosa no muy recomendable, ya que podemos elegir un servidor no válido, de ahí el botón que nos permite recuperar el Servidor por defecto. La otra opción configurable es el modo de ejecución del programa: Hay dos opciones. La opción uno para el programa cada vez que necesitemos realizar una conexión con la base de datos, esta opción se incluye para equipos con una conexión a internet por horas, o algún otro tipo de impedimento, o simplemente porque el usuario lo desee así. La opción 2 es el modo ideal de trabajo de este programa. Consiste en ponerlo en marcha y olvidarse completamente de él. El programa continuará con haciendo su función hasta que el usuario decida pararlo. Una vez que hayamos configurado estas opciones aceptamos y podemos ‘Continuar’ con el programa eso si, manualmente, es decir utilizando la opción de Control del programa que tiene ese título. Si cancelamos la operación, ninguno de los cambios realizados tendrá efecto. La configuración del programa sólo puede realizarse con el programa completamente parado. Por ello antes de ejecutar la opción configuración debemos darle a la opción ‘Parar’ en caso contrario, el programa no nos dejará y nos lo advertirá generando un aviso de error. 66 A.6. Ejecución del Programa: Como ya hemos visto en el Apartado anterior, la ejecución del programa está condicionada a la configuración del programa. El modo en que estemos influye en el programa del siguiente modo. Si estamos en el modo 1, es decir, requerimos que la aplicación nos pida autorización antes de realizar cualquier contacto con el Servidor, el Programa cada vez que tenga que efectuar una transferencia, parará el Programa y mostrará el Siguiente mensaje: Este mensaje, que continuara en la pantalla hasta que el usuario reaccione, pide la autorización para conectarse con el servidor. También nos ofrece la posibilidad de parar el programa, y recuerda al usuario la posibilidad de cambiar el modo de funcionamiento. Si todo está en orden elegiremos la opción de conectar. Si todo va bien, y la conexión y el Servidor están disponibles pasamos a Descargarnos un fichero de Trabajo. El Cliente realiza su petición al Servidor, el Servidor la recibe y nos envía un fichero, si la descarga es correcta nos encontramos con la siguiente situación: Podemos ver que el registro de sucesos ha cambiado y en el aparecen los pasos que el programa ha realizado (Parte derecha). Por otro lado también vemos que la parte izquierda también nos muestra datos distintos. Así, una vez descargado el fichero, el programa está listo para procesar. Y en la etiqueta de Trabajo actual en proceso nos aparece el nombre del trabajo que estamos simulando. 67 El siguiente paso que da el programa es el de ejecutar el Simulador de incendios sin pedir autorización ni demorarse en ninguna otra cosa: Así pues podemos observar que la parte inferior de la pantalla nos muestra el progreso de la simulación: Podemos ver como en el registro de sucesos nos indican que hemos iniciado el proceso de Cálculo, mientras en la parte izquierda vemos que nuestro estado actual es Procesando, y el tiempo de CPU va aumentando conforme avanza la simulación. Como el usuario puede comprobar la visualización del proceso de simulación es bastante llamativa e interesante de observar, este proceso es innecesario, ya que el Servidor sólo necesita los Datos que aparecen en la parte inferior derecha, pero se ha optado por esta presentación ya que hace que el usuario la encuentre más atractiva, y da una motivación más para ejecutar el programa, que no únicamente la de mantener al ordenador ocupado. Si todo va bien y no decidimos detenerlo, el simulador continua con el proceso hasta que termina con los 45 años de simulación. 68 Una vez que el simulador ha terminado, nos encontramos con esta pantalla: Vemos que de nuevo el registro de Sucesos nos advierte de un evento, la finalización del Simulador, mientras que el estado actual del cliente ahora ha pasado a preparado para Transferir. También vemos todo el tiempo que el simulador ha consumido de CPU. Una vez estamos listos para efectuar la transferencia, en caso de que continuemos en el modo 1 de trabajo, el Programa nos volverá a mostrar el mismo mensaje que en el caso de la Descarga, y el usuario podrá proceder de igual modo, si estamos en el modo 2, pasaremos directamente a enviar el fichero de resultados. El Fichero de resultados tiene el siguiente aspecto: ‘Resultat.dat’ Amb les Dades: Risc d'incendi: Creixement Vegetació: Error d'extinció: Incendis Anuals: Capacitat Extinció: 60 10 92 75 0 Els Resultats són els Següents Incendis Registrats al Territori: Mitja Real d'incendis registrats: Territori Cremat pels Incendis: Territori Cremat per any: Incendis extingits pels Bombers: Incendis majors a 10 hect.: Incendis majors a 100 hect.: Incendis majors a 1000 hect.: 69 1430 31 639333 14207 0 228 190 86 El Programa se dispone pues a enviar este fichero. Vemos que esta vez los cambios en la pantalla han sido mínimos. Nuestro estado ahora es de preparados para iniciar una descarga, también podemos ver que el panel izquierdo nos indica que hemos completado un trabajo, y el registro de sucesos tiene constancia de la transferencia. Una vez hecho esto ya hemos completado un ciclo normal de finalización de un trabajo, ahora el programa volverá a iniciar una descarga y vuelta a empezar con el mismo procedimiento. 70 A.7. Manejando el Control del Programa: Para empezar hay que decir que el control es simple, pero aún así se presta a errores, ya hemos explicado como usar la configuración del Programa. Las otras dos opciones son bastante claras, aún así, si las usamos de manera incorrecta: Continuar cuando estamos en Marcha, o Parar cuando estamos parados, la aplicación nos lo dirá con un mensaje. Si usamos bien los controles, y paramos el programa en mitad de la simulación, ocurrirá lo siguiente: El estado actual pasa a estar pausado, y el registro deja constancia de nuestra acción. 71 Si ahora decidimos continuar: Nuestro estado vuelve a pasar a procesando, el registro se actualiza y volvemos a simular. 72 A.8.- Posibles errores en el Funcionamiento: Con el primer error que nos podemos encontrar durante un ciclo de ejecución es con que tengamos problemas para descargar un trabajo, ya sea por culpa nuestra, o por la del Servidor. El programa está preparado para reaccionar ante cualquiera de estos problemas, informar al usuario debidamente y actuar del mejor modo posible. Pasaremos ahora a enumerar los posibles errores de conexión y ver como reacciona la aplicación: A.8.1. El equipo no tiene conexión a internet: La aplicación detecta el fallo, para la ejecución del programa e informa al usuario de que no detecta la conexión a internet con un mensaje de error. El registro también deja constancia de este hecho. 73 A.8.2. La aplicación no puede conectar con el Servidor. Si el Programa Servidor está apagado, o porque el Servidor RMI no está registrado, o simplemente, el Servidor al que intentamos acceder es erróneo, nuestra aplicación Cliente detecta el problema y inicia un periodo de espera de 10 minutos antes de volver a intentar la conexión, ya que puede ser que el Servidor este realizando tareas de mantenimiento y vuelva a estar disponible en breve. Igualmente informa al usuario de que es lo que está haciendo mediante el siguiente mensaje: Como hemos visto a lo largo de todo el manual, el registro de sucesos toma nota de lo sucedido. Se informa al usuario de que el Programa Cliente volverá a intentar conectar con el Servidor después de 10 minutos. Realizará hasta 5 reintentos que se irán viendo reflejados en la pantalla a través de un leve cambio en el mensaje que nos muestran: 74 Si Transcurridos los 5 intentos, el Programa Cliente no ha conseguido establecer la comunicación con el Servidor, El Programa se parará inmediatamente e informará al usuario con el siguiente mensaje: Como podemos observar, toda esta secuencia de acontecimientos queda registrada nuestro archivo: 75 A.8.3. El Servidor tiene problemas de Mantenimiento: Detectamos al Servidor, y podemos comunicarnos con el, pero durante la descarga, el Servidor detecta errores graves que le impiden llevar a cabo la operación. El Servidor informa al cliente de lo sucedido, y el Cliente parará inmediatamente el programa e informará al usuario a través del siguiente mensaje. Registro: Vemos que el programa ha realizado la petición remota, y la respuesta que ha recibido del Servidor: 76 A.8.4. El Servidor no Dispone de Trabajos en este momento: En esta situación, lo mejor es parar el programa Cliente, ya que por muchas peticiones que enviemos, el Servidor no podrá atenderlas debidamente hasta que introduzca nuevos trabajos en su BD. Por lo tanto el Cliente informa al usuario de lo que pasa y para el programa: Registro: De nuevo vemos la petición enviada y la respuesta del Servidor: 77 A.8.5. Perdida del Fichero de Datos antes de iniciar el Programa: Al carecer del Fichero ‘Treball.dat’ es imposible que el simulador pueda cargar los datos para computarlos. Por tanto la mejor opción es volver a descargar un nuevo trabajo. Así que pasamos al estado -> Preparado para Descargar. Registro se actualiza e informa del problema que se ha producido: A.8.6. Hemos Tardado demasiado en completar el trabajo: Esto sucede cuando tardamos más de 5 días en completar un Trabajo. Es una medida de seguridad del Servidor para asegurarse que todos los trabajos se completen. En este caso simplemente el Cliente informa al usuario de la respuesta del Servidor a través del registro. Y Pasa inmediatamente a Descargar un nuevo Trabajo. Este caso no aumentará nuestros trabajos completados . 78 A.8.7. Perdida del Fichero de Resultados. El mejor modo de resolver este problema consiste en volver a Simular los mismos datos que acabamos de simular. Así pues El Cliente pasa al estado Preparados para procesar e inicia el simulador. Toda esta operación queda registrada 79 A.8.8. Perdida de los Datos del Cliente: Este error se detecta al cargar la Aplicación, ya que es el momento en que el programa inicializa las variables que contienen estos Datos a partir de un fichero. En caso de perder el fichero, el programa al arrancar nos mostraría el siguiente mensaje: Con este Diálogo el programa pide al usuario que vuelva a introducir los datos de su registro para que el programa los pueda cargar. Nos Recuerda también que si introducimos mal los datos, perderemos nuestro registro anterior. Si antes de completar este diálogo observamos la ventana principal, la zona reservada a nuestros datos, veremos que ha cambiado. Todas las variables estadísticas están a 0, y nuestros Datos en Blanco: Si no rellenáramos los dos campos de registro, nos aparecería el siguiente mensaje en el display inferior: 80 Si Volvemos a rellenar los datos correctamente y pulsamos aceptar, podremos continuar con la simulación en el punto donde la dejamos antes de perder los datos. Y podremos observar que la zona de Datos vuelve a estar completa. Si por el contrario rellenamos mal, bueno, con otro nombre el campo login, nos encontraremos con un nuevo error. 81 A.8.9. Perdida del Nuestro Registro Cliente en el Servidor Este error puede ser fruto de que hayamos rellenado mal los campos del error anterior, o simplemente de que el Servidor haya borrado o perdido nuestros datos. En ambos casos la respuesta del cliente será la misma: Nos invitará a registrarnos de nuevo, al hacerlo perderemos nuestros antiguos datos, pero en realidad, ya estaban perdidos antes. Este Diálogo tiene el mismo funcionamiento que el Diálogo de registro, solo que también nos permite salir de el y parar el programa, ya que continuar no podremos sin tener un registro en el Servidor. Todo queda registrado 82 A.9. Salir del Programa Para salir del Programa debemos seleccionar la opción de cerrar la ventana. Eso si, el Cliente nos exige que antes de hacerlo hayamos parado el programa, si lo intentamos hacer con el programa en ejecución nos encontraremos el siguiente mensaje: 83 Si por el contrario, primero paramos el programa, como podemos observar en la zona de datos, está parado, nos encontraremos con el Mensaje siguiente: Este mensaje nos pregunta si realmente queremos finalizar el programa. Si la respuesta es no, volveremos a la ventana principal, y podremos continuar el simulador mediante el ‘Control del Programa’. Si la respuesta es SI, el programa guardará todos los datos y se Cerrará. Hay que tener en cuenta por último que este programa no guarda el estado de la simulación, es decir, si finalizamos el programa en medio de una simulación, al volver a ejecutar la aplicación cliente volveremos a iniciar la misma simulación desde el principio. Lo mismo ocurre con una descarga, o una transferencia. 84 A.10. Programa SimularIncendio Este es el aspecto que tiene una simulación normal una vez finalizada. Describiremos sus diferentes componentes: Datos a Procesar: Estas son las constantes con las que el simulador trabaja, son las que descargamos del Servidor. Territorio: Aquí podemos ver cual es la evolución, territorio quemado, vegetación, año tras año. Gráfica: La gráfica nos muestra la evolución que sufre el territorio a lo largo del tiempo. 85 Resultados: Aquí podemos ir viendo cuales son los datos que recogemos mediante la simulación y que al finalizar enviaremos al Servidor. 86 ANEXO B : MANUAL DEL SERVIDOR B.1. Instalación y Requisitos Para poder ejecutar el servidor en cualquier maquina, además de la máquina virtual Java (JRE) necesitamos tener instalado mySQL, ya que sino no podremos ni crear la Base de Datos, ni gestionarla. Por supuesto tenemos que tener creada una Base de Datos. Para esto ultimo utilizaremos un sencillo programa Java que hará lo siguiente: public class BD { public static void main(String[] args) { Connection conexio; Statement sentencia; String name; String prioritat; Random prior; try { Class.forName("com.mysql.jdbc.Driver"); } catch (Exception e) { System.out.println("No s'ha pogut carregar el driver de MySQL."); return; } try { prior = new Random(); conexio = DriverManager.getConnection("jdbc:mysql://localhost/test"); sentencia = conexio.createStatement(); sentencia.execute( "CREATE TABLE Clients (" + " user VARCHAR(10) PRIMARY KEY NOT NULL, " + " nom VARCHAR(40) NOT NULL, " + " trebComp INTEGER DEFAULT 0, " + " data DATE)"); sentencia.execute( "CREATE TABLE Treballs (" + " nomTreball VARCHAR(20) PRIMARY KEY NOT NULL, " + " prioritat VARCHAR(1) NOT NULL, " + " estat INTEGER DEFAULT 0, " + " user VARCHAR(10) NOT NULL, " + " data DATE)"); for (int i = 0; i < 7000; i++) { name = "Simulador" + i + ".txt"; prioritat = "" + prior.nextInt(10); sentencia.execute( "INSERT INTO Treballs " + "VALUES ('"+ name + "','" + prioritat + "',0, 'zzzzzzzzzz',null)"); } } catch (Exception e) { e.printStackTrace(); } System.out.println("Creacion finalizada."); } } Crea las dos tablas e introduce todos los trabajos pendientes que tenemos en el directorio ‘Treballs’. 87 Necesitamos también contar con las librerías de Java que nos permiten por un lado servir aplicaciones RMI, y por otro manejar la Base de Datos a través con mySQL: Estas dos librerías son generation.jar y mysql-connector-java-3.0.14-productionbin.jar respectivamente. Para ejecutar la aplicación necesitamos tener en el mismo directorio los siguientes directorios: - Treballs -> contiene todos los trabajos pendientes - Completats -> contendrá todos los trabajos completados - NoAfegits -> Trabajos no añadidos a la BD - Backup -> Copias de Seguridad - Com -> contiene las clases de la librería de mysql-connector-java-3.0.14-productionbin.jar - Il -> contiene las clases de la librería generation.jar - Por último el fichero java.policy Por último antes de ejecutar el servidor tenemos que ejecutar el fichero ‘rmiregistry.bat’ que viene en el mismo directorio que el programa servidor para poder iniciar así el registro RMI. De nuevo podemos ejecutar el Servidor de dos formas: 1. Con la maquina virtual java: Colocando todos los paquetes en el mismo path y que los directorios anteriores y escribiendo la instrucción: java -Djava.security.policy=java.policy server.ProgramaServidor 2. Fichero Ejecutable Generando un fichero ejecutable y colocándolo en el mismo sitio. Nota: Tanto en el cliente como en el Servidor, podemos ahorrarnos los paquetes il y com podemos modificando la variable CLASSPATH para indicar donde cual es su path, he decidido hacerlo así para que el usuario final sólo tenga en ambos casos que ejecutar un fichero para iniciar la aplicación y no tenga que preocuparse de nada más. 88 B.2. Aspecto El Programa Servidor en su inicio presenta el siguiente aspecto: Vemos que podríamos dividir la interficie que se nos ofrece en 4 partes: B.2.1. La Barra de Tareas: Contiene Todas las operaciones que es capaz de efectuar el Servidor: Como vemos se divide en tres menús: - Servidor : Las operaciones que podemos realizar con el Servidor. - Mantenimiento de la BD : Operaciones que podemos realizar sobre la Base de Datos del programa - Consultar Registre : Operaciones de Consulta de archivos Log o de Trabajos. 89 B.2.2. Zona de Datos Ocupa la mitad superior izquierda y en ella podemos observar cual es el estado actual del Servidor. Si esta en marcha o no, cuantos trabajos tenemos en la BD, de que tipo, que peticiones hay sirviéndose, cuantos clientes hay registrados. Incluso contiene una ‘ALARMA’ que nos indica cuando se producen errores graves que afectan al funcionamiento del Servidor: B.2.3. Zona de Registro Ocupa la mitad superior derecha, en esta zona en blanco se van registrando todos los sucesos que ocurren mientras el Programa Servidor esta encendido. Dicha información se guarda una vez al día al menos, y se reinicia el registro. 90 B.2.4. Zona de Consulta de la Base de Datos: Es la zona más completa de la interficie, nos muestra en todo momento y en tiempo real cual es el contenido de nuestra Base de Datos. Cada vez que se efectúa un cambio, las tablas que vemos en esta zona se actualizan. Podemos observar que hay varios apartados en esta parte. Todos ellos tienen un título bastante aclarativo, aún así describiremos cada pestaña: - Treballs Es la pestaña que aparece en pantalla por defecto, como vemos consta de una tabla, un conjunto de opciones para ordenarla, y un botón que reza ‘Guardar’. Este botón sirve para guardar toda la información que hay en la tabla en un archivo de ‘Log’ para su posterior consulta. En cuanto a las opciones, son formas de mostrar la tabla ordenada según sus campos. La tabla presenta 6 columnas, con las que mostramos todas las características de cada trabajo. Su nombre, prioridad, Estado, Cliente (en el caso de que este asignado o completado), fecha (idem), y ubicación (Solo puede tener 2, /Treballs, o /Completats). Podemos ver que por defecto la tabla se ordena según el nombre del trabajo, pero veamos que sucede si cambiamos el modo de ordenación, elegiremos prioridad: Vemos que el orden ha cambiado, y que los primeros trabajos que aparecen, son aquellos cuya prioridad es más alta ( 9 ). El resto de pestañas ofrecen un aspecto idéntico, sólo variando en cada caso la tabla que nos muestran, y las opciones de ordenación. 91 - Treballs Pendents Nos muestra los trabajos pendientes. La tabla solo tiene 4 columnas, ya que estos trabajos no tienen ni Cliente asignado, ni fecha. Por tanto solo pueden ordenarse bajo estas dos opciones, Nombre y prioridad. - Treballs Assignats Trabajos asignados, permiten ser ordenados por nombre, cliente y fecha, por prioridad no es interesante, ya que la prioridad es un factor que se tiene en cuenta solo en los trabajos pendientes. Obsérvese que se presenta ordenado por el Login del Cliente. - Treballs Completats Trabajos completados, igual que los asignados. Obsérvese que se presenta ordenado por la fecha de finalización. 92 - Clients Esta otra tabla nos muestra cuales son los clientes que tenemos registrados en la Base de Datos, así como los datos que conocemos de ellos, es decir, su Login, nombre, trabajos que ha completado y la última fecha en que se conectaron. Estos son, en esta tabla, los posibles parámetros de ordenación - Avisos Importants. Esta pestaña difiere y mucho de las anteriores ya que no se trata de una tabla. Consiste en un registro de avisos críticos, es decir, avisos que afectan al funcionamiento del programa y deben ser corregidos inmediatamente. Se complementa con la ALARMA que hemos visto en la ‘Zona de Datos’, y nos permite borrar el contenido del registro, y también, como el resto de pestañas, guardarlo en un fichero. Cuando se produce un error Critico, la ALARMA (flecha 1), que cambia a ROJO, nos indica que se ha producido, y en la segunda flecha, aparecerá reflejado el problema. Una vez visualicemos el problema, la alarma se apagará. Una vez hemos visto cuales son las componentes de la interficie, vamos a ver como actúan. 93 B.3. Funciones de la Barra Veremos las funciones de la Barra a través de cada uno de sus Menús. B.3.1. Funciones del Menú Servidor Empezaremos por ver cuales son las funciones que nos ofrece este menú: Podemos efectuar dos acciones: - Iniciar el Registro RMI Esta función nos permite registrar nuestro Servidor en RMI, con lo que estamos listos para aceptar peticiones remotas. El registro de sucesos actualiza sus datos, mientras que el estado de nuestro Servidor pasa a ser ‘En marcha’. - Parar el Registro RMI Esta función anula nuestro registro en RMI, con lo que ya no podemos aceptar peticiones remotas, esto se refleja gráficamente de la siguiente forma: 94 Son unas funciones muy simples y sencillas, aún así pueden usarse mal, si esto ocurre, el Servidor simplemente nos lo indica con un Mensaje de Error Si lo paramos y está parado encendido Si 95 lo encendemos y esta B.3.2. Funciones del Menú de Mantenimiento de la BD Estas son las operaciones que este menú nos proporciona: Podemos ver que este menú es algo más completo que el anterior, ya que la Base de Datos requiere una atención mucho más compleja que el registro del Servidor. Vemos que es un abanico bastante completo de funciones, quizá podemos pensar que falte la de insertar un cliente, pero esa ya se efectúa directamente con la función remota que lleva ese nombre. Pasaremos a ver que ocurre cuando efectuamos cada una de estas operaciones: - Añadir un Trabajo: Esta operación despliega ante nosotros el siguiente Dialogo: El Diálogo consta de una tabla donde podemos encontrar todos los trabajos que el Servidor tiene disponibles para ser añadidos a nuestra Base de Datos, son los que se encuentran en el Directorio ‘NoAfegits’, también nos permite seleccionar la prioridad con que queremos que se guarde el nuevo trabajo. 96 El Botón Backup, nos permite acceder al directorio que contiene todas las copias de seguridad de todos los trabajos que contiene la BD, y de los que se pueden añadir. Y desde allí añadir el fichero a nuestra BD. Esto es para casos de perdida o deterioro de los ficheros asociados a los trabajos. El funcionamiento de la operación para este caso seria el mismo que el anterior, seleccionar un trabajo, una prioridad y pulsar la opción aceptar. La opción cancelar deja nuestra operación sin validez. En caso de que la operación se realice con éxito, por ejemplo, “insertar el trabajo Simulador7010 con prioridad 9”, el programa lo reflejaría de la siguiente manera: Podemos observar que dejamos constancia de la operación en el registro de sucesos, y que el trabajo aparece inmediatamente en su respectiva tabla. También se modifican los campos ‘Trabajos totales’ y ‘Trabajos pendientes’ de la zona de datos, aumentando ambos en 1. 97 - Borrar un Trabajo Desplegamos el siguiente cuadro: Este cuadro nos presenta una tabla en donde se listan todos los trabajos que contiene nuestra base de Datos, tanto los pendientes, los asignados como los completados. Es decir, podemos elegir cualquier trabajo para borrar. También nos ofrece la posibilidad de borrar el fichero asociado, en cuyo caso eliminaremos el fichero del directorio ‘Treballs’, en caso de que no eliminemos el fichero, este pasará a ‘NoAfegits, para añadirlo posteriormente si se desea. 98 Veamos que sucede si borramos el trabajo Simulador7010 con prioridad 9, pero no borramos su fichero asociado. Como vemos el fichero ha desaparecido de la Base de Datos, y el registro de sucesos ha tomado nota de nuestra operación. Los Trabajos Totales, y Pendientes también han sido modificados. 99 Veamos pero que pasaría si eligiéramos la opción de borrar también el fichero asociado, es decir marcar la siguiente casilla: Este sería el resultado: Como vemos, el mensaje que ahora aparece en el registro es diferente, y nos indica que su fichero asociado también se ha borrado. El resto es igual que en el caso anterior. Esta vez, ya no encontraremos el fichero Simulador7010 para añadirlo a no ser que elijamos la opción ‘Backup’. 100 - Cambiar la prioridad de un Trabajo El Diálogo de cambio de prioridad es bastante parecido en su aspecto al de añadir un fichero. En este en cambio, los trabajos que se muestran en la tabla son los trabajos pendientes, y cada uno de ellos con su prioridad. Para efectuar la operación, únicamente tenemos que seleccionar un trabajo y elegir su nueva prioridad mediante el combo y seleccionar aceptar. En caso de arrepentirnos, podemos pulsar cancelar, con lo que anularemos la operación. 101 Este sería el resultado de cambiar la prioridad del trabajo Simulador1 a 9. De nuevo, el registro se actualiza con los nuevos acontecimientos, y también observamos que la tabla de Trabajos pendientes se ha actualizado con el cambio, la tabla de Trabajos, también se ha actualizado. 102 - Borrar un Cliente Esta operación puede realizarse para liberar espacio en nuestra BD, por ejemplo si observamos que un cliente lleva mucho tiempo sin conectar, podemos suponer que ya no ejecuta su programa Cliente. Si Elegimos esta operación, esta será la pantalla que aparecerá: 103 Podemos ver que en este caso la Tabla nos muestra a todos los clientes que tenemos registrados en nuestra BD. Si por ejemplo elegimos borrar al Cliente Frikimen, Este sería el resultado que observaríamos gráficamente: Como cada operación, esta también se registra en los sucesos. Además observamos que la tabla clientes ya está actualizada, puesto que no aparece ‘Frikimen’ y el campo Clientes Registrados ha disminuido en una unidad. 104 - Revisar la Base de Datos Es una función que hay que realizarla cuando desde el Servidor se nos indica que puede haber anomalías en la BD. Tales como trabajos sin fichero o cosas así. Esta función recorre la Tabla Treballs comprobando que todo este en orden. Podemos encontrarnos con dos posibles resultados de esta operación: 1. No encontramos ninguna anomalía: En este caso lo único que sucede es que actualizamos el registro de sucesos: 2. O bien que el Servidor encuentra anomalías en la BD y las corrige: 105 Como vemos este Resultado es mucho más llamativo, para llamar la atención del administrador. Vemos que aparece un Diálogo de Error, una nota en el Registro de Sucesos, incluso se enciende la ALARMA de sucesos Críticos. No es que vaya a dejar de funcionar el Servidor, pero se intenta que el administrador tenga en cuenta este resultado. El Mensaje de Error nos dice que consultemos el fichero de Log donde ha dejado los datos de las correcciones. - Recuperar la Conexión Esta última opción es muy simple, pero de vital importancia. Lo único que hace es restablecer la conexión del programa con la BD, al hacerlo permite el funcionamiento de Servidor. Se debe accionar siempre que el Servidor nos informe que se ha producido un error con MySQL, o siempre que reiniciemos el propio MySQL. Lo único que ocurre gráficamente es que se actualiza el registro: 106 B.3.3. Funciones del Menú de Consulta - Ver Archivo de Log En cualquier momento el administrador puede tener la necesidad de saber que ocurrió con una determinada situación en el pasado, o simplemente ojear datos de días anteriores, para esto el Servidor lleva un registro de todo lo que acontece en el Programa, y además se ofrece la posibilidad al administrador de realizar determinadas operaciones que también generan archivos de Log. Revisar la BD, Guardar Tablas... El Diálogo que nos permite acceder a este contenido nos muestra en principio el contenido del Directorio Log, que consiste en un montón de fechas que corresponden a los días en que el Servidor ha estado activo. Seleccionamos el día que queremos consultar y pulsamos ‘Abrir’. 107 En ese momento el Cuadro principal del Diálogo cambiará para mostrarnos los archivos Log que tenemos guardados de ese día: Si tenemos todos los archivos el aspecto del Diálogo será el siguiente: Podemos ver aquí todos los archivos de Log de que podemos disponer. Si nos arrepentimos y queremos volver atrás, no tenemos más que elegir la opción ‘Subir un Nivel’ en ese caso volveremos a la situación anterior. Estos son los tipos de archivo de Log que nos podemos encontrar y como nos los muestra el Servidor: 108 • AvisosImportants.log • ClientsRegistrats.log 109 • Incidencies.log • RenovacióBD.log 110 • RevisioBD.log • Treballs.log 111 • TreballsAssignats.log • TreballsPendents.log 112 • TreballsCompletats.log Todos estos diálogos son simplemente de consulta, no podemos realizar ninguna operación con ellos. Una vez hemos encontrado lo que buscamos, pulsamos aceptar y volvemos a la ventana principal del Servidor. 113 - Ver Trabajo Las tres operaciones restantes se desarrollan del mismo modo. Tanto si elegimos ver un archivo Pendiente, Asignado, o Completado, el cuadro que nos aparecerá será el que vemos a continuación. Solo Cambiará el contenido de la Tabla. Que nos listará los trabajos que hayamos solicitado en cada caso. 114 Así pues una vez hemos seleccionado el trabajo que deseamos visionar nos encontramos con lo siguiente: • Si hemos elegido visionar un Trabajo Pendiente, o Asignado veremos algo así: Este es el contenido de cualquier trabajo de este tipo, el valor de las 5 variables que el simulador del programa cliente necesita para Simular Incendios. • Si hemos elegido visionar un Trabajo Completado nos aparecerá lo siguiente: Cualquier trabajo completado nos mostrará los siguientes datos, que son el resultado de una Simulación completa de 45 años sobre un territorio aplicando a ese territorio las variables que aparecen arriba. 115 B.4. Tratamiento de los Trabajos Caducados Ya hemos visto algo de este apartado en este informe, concretamente el fichero de log que se genera al realizar esta Tarea. En este aparatado explicaremos en que consiste esta función: La principal misión del Servidor es, además de que todo funcione correctamente en todo momento, procurar que todos los trabajos se completen lo antes posible, un impedimento para esta tarea es el hecho de que algún cliente deje de utilizar la aplicación, y tenga un trabajo asignado, este trabajo no se completaría nunca, ya que el Servidor sólo puede enviar trabajos pendientes. El sistema ideado para solucionar esto es ejecutar una vez al día una tarea que vuelva a dejar en el estado de pendientes todos aquellos trabajos que lleven más de 5 días asignados. De esta forma podremos volver a enviar el trabajo. Esta tarea se ejecuta una vez al día entre las 23 y las 0 horas y deja constancia de su actuación en el registro. - Si no encuentra Trabajos de este tipo el único rastro que dejará esta tarea estará en el registro: 116 - Si en cambio la tarea encuentra trabajos caducados el administrador se encontrará con este mensaje: Por supuesto también se actualizarán todas las tablas correspondientes, Trabajos, Pendientes y Asignados, así como en los Datos del Servidor, las etiquetas que se refieren a estos trabajos. 117 B.5. Comunicación entre la Funciones Remotas y el Administrador: A continuación veremos los diferentes mensajes que el Servidor puede dejar en el registro, y en caso de errores graves, como avisa al administrador: B.5.1. La operación se realiza con éxito En este caso nos podemos encontrar con los siguientes mensajes en el registro, dependiendo de la función remota de que se trate: Aquí podemos ver una secuencia completa de las 3 operaciones remotas realizadas con éxito. Primero el registro del nuevo Cliente, después la petición de descarga, y por ultimo la petición de transferencia B.5.2. El Trabajo enviado, estaba caducado Este dato es irrelevante para el administrador, aún así queda constancia de ello en el registro. 118 B.5.3. Acceso no autorizado Cuando un cliente no registrado intenta acceder al Servidor, este se lo impide, y le da orden al Cliente de que registre al usuario antes de seguir, el mensaje tanto en descargas como en envíos queda en el registro. En descargas se asume que es el cliente el que no esta registrado, y en envíos se da por echo que es el Servidor el que ha perdido los datos, el resultado es el mismo. B.5.4. El Servidor se ha quedado sin Trabajos Este tipo de situación es más grave, ya que el administrador debe reaccionar y añadir nuevos trabajos para que los clientes puedan descargar, ya que sino los tendría a todos desaprovechados. Por este motivo este error activa la ALARMA ya que se trata de una situación que hay que remediar rápidamente 119 B.5.5 No se puede encontrar un directorio Este caso es similar al otro, ya que la perdida de un directorio entero nos impide acceder a los ficheros asignados a los trabajos, y por tanto, nos impide enviar ficheros a los clientes. Por tanto el administrador debe recuperar todos los ficheros a partir de las copias de seguridad. Resumiendo, tenemos que activar la alarma. 120 B.5.6 Perdida de un fichero Este no es un error crítico, pero se activa la alarma igualmente para que el administrador tenga constancia de este hecho y pueda recuperar el fichero más tarde. El trabajo se elimina de la Base de Datos precisamente para poder recuperarlo más tarde. 121 B.5.7. Error de acceso a la BD De nuevo nos encontramos con un error crítico, ya que si no tenemos acceso a la Base de Datos no podemos acceder ni a trabajos, ni a Clientes, y el Servidor pierde toda su funcionalidad. Por ello este error, de nuevo crítico tiene que hacer reaccionar al administrador rápidamente, así que activamos la alarma y mostramos un mensaje de error por pantalla para captar la atención del administrador. Si abrimos la pestaña de avisos importantes, nos encontraremos con este mensaje: Obsérvese que al abrir la pestaña, la alarma desaparece. 122 B.6. Errores durante las operaciones de Mantenimiento Durante las operaciones de mantenimiento de la Base de Datos se pueden producir tres tipos de errores que ya hemos visto en el apartado anterior. La reacción del programa ante estos errores será muy similar al que hemos visto, pero complementarán el aviso con un mensaje de texto sobre la pantalla: Estos son los errores que nos podemos encontrar mientras realizamos operaciones de mantenimiento, y las respuestas del Programa: B.6.1. Perdida de la conexión con la Base de Datos. Este error también se genera cuando se detecta cualquier tipo de fallo de acceso a la Base de Datos cuando estamos consultando las Bases de Datos a través de la tablas de la Zona de Consulta de la Base de Datos. 123 B.6.2. Perdida del Fichero B.6.3. Perdida de un Directorio (NoAfegits, Backup, Treballs o Completats) 124 B.7. Errores en la Consulta de archivos Al Consultar un archivo nos podemos encontrar de nuevo con 3 tipos de Errores, dos los hemos tratado ya en el apartado anterior, y la reacción del programa es la misma, aunque difieren los mensajes que se registran en sucesos. Son la perdida del fichero, y la perdida del directorio. (Treball, Completas, o Log). El único error nuevo que nos podemos encontrar al consultar un fichero, es que este haya sido modificado. En este caso el programa nos informara de la alteración con un mensaje de error y registrándolo. No se activará la alarme ya que no es un error tan grave, ni siquiera que merezca reparación. 125 B.8. RMI no Registrado Un error muy frecuente que nos podemos encontrar es que nos olvidemos de poner en marcha RMI antes de ejecutar la aplicación Servidor, o bien que el Servidor RMI se caigo (esto es poco frecuente). En este caso el administrador debe ser avisado inmediatamente para que corrija el problema ejecutando RMI, ya que sino no podremos registrar nuestro Servidor. También contamos con una tarea que cada 15 minutos comprueba que RMI este funcionando, y nuestro Servidor Registrado. Si no es así avisa al administrador. La manera de hacerlo es la de siempre, ALARMA, Mensaje de Texto y registrarlo. 126 B.9. Errores de Arranque Por último trataremos los 2 errores que podemos encontrarnos al Arrancar la aplicación. En cualquier error de este tipo, el programa nos mostrará una pequeña pantalla con el tipo de error y nos invitará a Salir, ya que es imposible que se cargue el programa bajo esas condiciones. Una vez hayamos arreglado el problema, podremos ejecutar la aplicación. Podemos tener dos problemas: - MySQL no está en funcionamiento - Ya existe una copia del Programa Servidor en Funcionamiento Ya como último apunte me gustaría comentar que todos los diálogos, al igual que en el Cliente son manejable con el teclado. 127 B.10. Salir del Programa Para salir del Programa Servidor tenemos que utilizar la opción de Cerrar la ventana principal del Programa. Para poder Salir, el Servidor RMI tiene que estar parado, en caso contrario, el Programa no nos dejará cerrar. Si Primero paramos el Servidor RMI y luego Salimos el resultado será este. Si queremos Cerrar pulsaremos Si, y si queremos volver al Programa pulsaremos no. 128 0.- INDICE 1. Introducción y Objetivos 1.1. Introducción 1.2. Objetivos 1 1 1 2. Antecedentes 2.1. Computación Distribuida 2.2. SETI@home 2.3. Aplicación Servidor-Cliente 2 2 3 3 3. Tecnologías utilizadas 3.1. Java 3.2. RMI 3.3. Swing 3.4. mySQL 3.5. JDBC 3.6. Eclipse 3.7. Jsmooth 4 4 5 7 8 8 9 9 4. Análisis 4.1. Análisis de la interacción Cliente-Servidor 4.1.1. Descargar Fichero 4.1.2. Enviar Fichero 4.1.3 Registrar Cliente 4.2. Análisis del Cliente 4.2.1. Bucle Principal 4.2.2. interfazGráfica 4.2.3. Programa de Cálculo Intensivo 4.3. Análisis del Servidor 4.3.1. Base de Datos 4.3.2. Funciones Remotas 4.3.3. interfazGráfica 10 11 11 12 12 13 13 13 13 14 14 14 15 5. Diseño 5.1. Diseño de las Funciones Remotas 5.1.1 Protocolo de Transferencia 5.1.2. Servidor.java 5.2. Diseño del Cliente Dades.java 5.2.1. Diseño del Bucle Principal 5.2.1.1. DialogNoConexio.java 5.2.1.2. DialogFiIntents.java 5.2.1.3. DialogError.java 5.2.1.4. DialogConfirmacio.java 5.2.1.5. DialogPerduaRegistre 5.2.1.6. DialogNoTreballs 5.2.1.7. Bucle.java 5.2.2. Diseño de la interfazGráfica del Cliente 5.2.2.1. PanelDaltEsqEtiqs.java 5.2.2.2. PanelDaltDret.java 5.2.2.3. PanelDaltEsqBotons.java 5.2.2.4. DialogConfiguracio.java 5.2.2.5. DialogFinal.java 5.2.2.5.1. DialogClose.java 16 16 16 17 19 19 20 20 20 20 21 21 21 22 25 26 26 27 27 28 28 129 5.2.2.6. DialogPerduaDades.java 5.2.2.7. DialogNoArranc 5.2.2.8. DialogRegistre 5.2.3. Diseño del Programa de Calculo Intensivo 5.2.3.1. Variables.java 5.2.3.2. Cua.java 5.2.3.3. InterficieCalcul.java 5.2.3.4. SimularIncendis.java 5.3. Diseño del Servidor Dades.java 5.3.1. Diseño de la Base de Datos 5.3.1.1. MetodesBD.java 5.3.2. Diseño de la interfazGráfica del Servidor 5.3.2.1. Barra de Menús 5.3.2.1.1. Menú Servidor ComprovacioRMI.java Iniciar Servidor Parar Servidor DialogPeticioEnCurs.java 5.3.2.1.2. Menu BD Añadir Trabajo DialogAfegir.java Borrar Trabajo DialogBorrar.java Borrar Cliente DialogBorrarClient.java Cambiar la Prioridad de un Trabajo DialogCanviPrioritat.java Revisar la Base de Datos RevisarBD.java Recuperar la conexión RecuperarConexio.java ComprovacioCaducitat.java 5.3.2.1.3. Menu Consulta Consultar una archivo de Log DialogConsulta.java DialogVeureArxiu.java Consultar un Trabajo DialogResultats.java DialogVeureTreball.java 5.3.2.2. Zona de Control del Estado del Servidor PanelDaltEsq.java DanelDalDret.java 5.3.2.3. Zona de Control de la Base de Datos PanePanel1.java PanePanel2.java PanePanel3.java PanePanel4.java PanePanel5.java PanePanel6.java DialogError.java DialogFinal.java DialogTancament.java DialogNoInici.java DialogNoSQL.java 130 28 28 29 30 31 31 32 33 35 36 37 38 41 41 41 41 42 42 42 43 43 43 45 45 46 46 47 47 48 48 48 48 49 50 50 50 51 52 52 52 53 53 53 54 54 55 55 55 55 55 56 56 56 56 56 6. Conclusiones 57 7. Bibliografía 59 Anexo A : Manual del Cliente A.1. Instalación y Requisitos A.2. Bienvenido al Programa A.3. Registro Completado A.4. Primera Ejecución A.5. Configuración del Programa A.6. Ejecución del Programa A.7. Manejando el Control del Programa A.8. Posibles Errores en el funcionamiento A.8.1. El Equipo no tiene conexión al internet A.8.2. La Aplicación no puede conectar con el Servidor A.8.3. El Servidor tiene problemas de Mantenimiento A.8.4. El Servidor no dispone de Trabajos en este momento A.8.5. Perdida del Fichero de Datos A.8.6. Hemos tardado demasiado en Finalizar un Trabajo A.8.7. Perdida del Fichero de Resultados A.8.8. Perdida de los Datos del Cliente A.8.9. Perdida de nuestro Registro Cliente en el Servidor A.9. Salir del Programa A.10. Programa Simular Incendio Anexo B : Manual del Servidor B.1. Instalación y Requisitos B.2. Aspecto B.2.1. La Barra de Tareas B.2.2. Zona de Datos B.2.3. Zona de Registro B.2.4. Zona de Control de la Base de Datos Trabajos Trabajos Pendientes Trabajos Asignados Trabajos Completados Clientes Avisos Importantes B.3. Funciones de la Barra B.3.1. Funciones del Menu Servidor Iniciar el Registro RMI Parar el Registro RMI B.3.2. Funciones del Menu de la BD Añadir Trabajo Borrar Trabajo Cambiar la Prioridad e un Trabajo Borrar un Cliente Revisar la Base de Datos Recuperar la Conexión B.3.3. Funciones del Menú de Consulta Ver un archivo de Log Ver un archivo de Trabajo B.4. Tratamiento de los Trabajos Caducados B.5. Comunicación entre Funciones Remotas y Administrador B.5.1. La operación se Realiza con éxito B.5.2. El Trabajo enviado estaba Caducado 131 60 60 61 62 63 65 66 70 72 72 73 75 76 77 77 78 79 81 82 84 85 85 87 87 88 88 89 89 90 90 90 91 91 92 92 92 92 94 94 96 99 101 103 104 105 105 112 114 116 116 116 B.5.3. Acceso no autorizado B.5.4. El servidor se ha quedado sin Trabajos B.5.5. No se puede encontrar un directorio B.5.6. Perdida de un Fichero B.5.7. Error de acceso a la BD B.6. Errores durante el Mantenimiento de la BD B.6.1. Perdida de la Conexión con la BD B.6.2. Perdida del Fichero B.6.3. Perdida de un Directorio B.7. Errores en la Consulta de Archivos B.8. RMI no Registrado B.9. Errores de Arranque B.10. Salir del Programa 132 117 117 118 119 120 121 121 122 122 123 124 125 126