Actividad 7: Comunicación entre procesos: Directorios Espejos.
Implementa una aplicación, dir_espejos, que dados dos directorios A y B, asegura que B
es un directorio espejo (mirror) de A. En su versión más básica, si en A se crea o modifica
un archivo, el programa replicará en B tales cambios.
Requerimientos de programa:
1) Se implementará un proceso padre, Manager, responsable de:
a) Leer por consola los directorios A y B:
java -jar dir_espejos.jar ./origen ./destino
b) Lanzar el proceso Vigilante.
c) Lanzar el proceso Actualizador cada vez que se necesite actualizar un
fichero en el directorio B.
d) Indicar al usuario la existencia de modificaciones en el directorio A, y si se
han conseguido copiar correctamente al directorio B.
e) Eliminar el proceso Vigilante cuando el usuario decida cerrar la aplicación
(pulsando la tecla ‘q’).
SUGERENCIAS: revisar métodos de [Link] para eliminar un proceso anteriormente
creado, empleando su referencia (Process).
2) Se diseñará el proceso Vigilante, cuya misión será revisar cada X segundos si hay
nuevas modificaciones en el directorio A tras la última revisión.
f) En caso de detectar un archivo modificado, lo cotejará con el archivo
homólogo del directorio B, y si difieren en fecha o tamaño, avisará
convenientemente al proceso Manager.
g) El proceso Vigilante se lanzará una única vez, y él mismo se encargará de
dormirse y activarse periódicamente para realizar una nueva revisión.
h) Se destruirá cuando el proceso Manager lo indique.
SUGERENCIAS:
- Revisar la clase [Link], y sus métodos como File::listFiles() o File::isDirectory(), entre otros. La
clase [Link] podría ser otra opción.
2.1) OPCIONAL: el proceso detectará también los archivos borrados en A, y
avisará para que sean borrados también en B.
2.2) OPCIONAL: asegurar que el programa trabaja correctamente sobre
directorios anidados.
2.3) OPCIONAL: Cuando el proceso Manager dé la orden a Vigilante de concluir,
éste confirmará la recepción de la orden, y concluirá su ejecución.
3) Implementar el proceso, ‘Actualizador’, cuya misión será copiar (y borrar si procede)
los archivos modificados en A sobre el directorio B. En caso de error durante la copia,
repetirá en 3 ocasiones la operación, y al final indicará al padre el nº de reintentos, y si ha
sido posible o no realizar la operación de copiado (o borrado). El padre mostrará al
usuario por pantalla los siguientes mensajes:
- “Copiado de [archivo] CORRECTO tras [n] reintentos” si se consiguió
copiar el archivo
- “ERROR al copiar [archivo], a pesar de [n] reintentos”
SUGERENCIAS:
- Revisar la clase [Link] y sus métodos para realizar operaciones sobre archivos.
- Estudiar los métodos de [Link] que permiten al proceso padre leer el valor devuelto por
el hijo: Process::exitValue(), Process::waitFor()....
4) Los procesos tendrá sus propios archivos de registro o archivos log: [Link],
[Link] y [Link]; sobre los que se volcarán todos los mensajes de
depuración. Al lanzar la aplicación desde línea de comando, será posible escoger el nivel
de verbosidad de la aplicación sobre dicho archivo log: ALL, FINEST, INFO, WARNING,
SEVERE...
Ej: java -jar dir_espejos.jar ./origen ./destino INFO
- Desde los procesos se registrarán todos los eventos relevantes en el log.
- Se empleará la clase [Link] (tutorial en español)
IMPORTANTE: emplear el comando tail -f [Link] [Link] en una
ventana de terminal para monitorizar la ejecución simultánea de nuestros procesos
y facilitar la depuración (man tail | más información | tail en windows).
5) OPCIONAL: implementar una interfaz gráfica que permita seleccionar
los directorios, activar /desactivar el servicio de espejo entre directorios,
y visualizar los mensajes de salida para el usuario.
5.1) OPCIONAL: Mostrar sendos controles [Link] que
muestren lado a lado los dos directorios.
PLAZO DE ENTREGA: Viernes - 30 de noviembre
PLAZO DE DEFENSA: Viernes - 7 de diciembre
Entrega mediante repositorio GitHub:
Enlace para aceptar la actividad y activar repositorio GitHub:
[Link]
- se recomienda comenzar la implementación con estos pasos:
1) aceptar la actividad haciendo clic en el enlace anterior
2) Crear un directorio local de trabajo
3) En línea de comando en tu directorio local de trabajo:
git clone <url_a_tu_repositorio_personal_asignado>
- se realizarán al menos 5 commits (5 aportaciones de código al repositorio), con las
versiones intermedias de la aplicación.
- los mensajes de los commits serán breves pero descriptivos sobre la funcionalidad
añadida. Ejemplo: “funcionalidad (4) -> botón eliminar”
- se realizará un commit “versión X.X” una vez que la aplicación esté implementada y
probada. Posteriormente, se podrán realizar commits adicionales dentro del plazo
de defensa, aportando por ejemplo funcionalidad pendiente o funcionalidad
opcional.
- el orden de los commits será libre, no tiene porqué ser el orden de los
requerimientos del enunciado.
RECUERDA las dos formas vistas de lanzar un programa java desde línea de comando:
java -jar /ruta/[Link] parametro1 parametro2...
java -cp /ruta/[Link] paquete.clase_main parametro1 parametro2…
OBSERVACIONES SOBRE LA COMUNICACIÓN ENTRE PROCESOS EN JAVA:
La comunicación entre los procesos (IPC) Vigilante y Manager, dos procesos
distintos, implica una comunicación entre dos programas que se están ejecutando sobre
máquinas virtuales diferentes, y no comparten por tanto el mismo espacio de memoria.
Los procesos se podrían comunicar por distintos métodos y formas, algunas de ellas
dependientes del SO, y por tanto implicarían perder la portabilidad del código.
- Se sugiere utilizar flujos de entrada y salida (streams) para la comunicación, o el
método básico de archivo con bloqueo ‘cooperativo’ (creando un archivo .lck
junto al original cuando un proceso tome el control del archivo).
- Se podría también emplear sockets y librerías con protocolos de comunicación en
red (como veremos en unidades posteriores: RMI...), o soluciones dependientes del
SO, como el envío de señales en linux.
- La comunicación entre procesos por tuberías (pipe) se puede realizar en otros
lenguajes como C. Sin embargo [Link] sólo soporta comunicación entre
hilos (threads), que comparten el mismo espacio de memoria.