Table of Contents
|
Planificación de fase
Planificación de fase
Hitos principales:
- Octubre: Definición del proyecto, requisitos, casos de uso, riesgos
Al terminar octubre tenemos una idea general de cómo será nuestra aplicación: funcionalidades básicas, planificación sobre cómo llevarla a cabo, límites de hardware, de dispositivos, etc. En definitiva, el ámbito general del proyecto.
- Noviembre: Investigación principal de tecnologías
Habremos decidido qué lenguaje de programación utilizaremos, al menos para el núcleo del programa, así como las tecnologías de cada uno de los módulos del proyecto, o al menos varias opciones de implementación, para poder elegir más tarde con cual quedarse. Las tecnologías más importantes a investigar son: entorno gráfico que usaremos, tecnologías para el núcleo de copia de seguridad, de base de datos, y de comunicación interna y externa.
- Diciembre: Prototipo Alpha (prueba de integración)
Se tendrá el núcleo de la aplicación, o al menos ciertos módulos para comenzar a integrar. De este modo tendremos el esqueleto de la arquitectura, con las principales tecnologías investigadas por completo e implementadas para más adelante continuar con funcionalidades menos críticas.
- Enero: Fase de investigación; procedimiento de integración cerrado.
Subsiguiente prototipo de investigación de tecnologías (comunicación frontend / backend, planificación de tareas), si bien carente de la crítica de backup, restore, eliminación de copias, etc. Finalización del proceso de integración de bases de código distintas, quedando preparadas las metodologias para las fases de desarrollo posteriores.
Los principales riesgos tecnológicos están ya localizados. La arquitectura se ha desarrollado hasta quedar prácticamente cerrada, a falta de algunas apis importantes.
- Febrero: Repaso de documentación e investigación sobre funcionalidades adicionales
Esta iteración se centrará en documentar los nuevos procesos desarrollados y completar la documentación existente, pero dada la falta de tiempo por los exámenes, se reduce la cantidad de tiempo para el proyecto, con lo que no se esperan grandes avances. Se dedica a la investigación también porque, en nuestra experiencia, los exámenes son época de trastear con las más extrañas tecnologías en los ratos muertos que se debieran aprovechar para estudiar.
- Marzo: Prototipo Beta (funcionalidad crítica). Replanificación y reevaluación de viabilidad. Reasignación de personal.
Eliminados los riesgos tecnológicos, es necesario replantearse la planificación y la viabilidad de los casos de uso menos importantes para el tiempo existente. Se deberá concluir la construcción de la aplicación y sus funcionalidades críticas, con vistas a poder comenzar cuanto antes el mantenimiento y testeo de esta funcionalidad, que se preve largo; en los tres meses desde Enero la arquitectura está más que fijada y desarrollar debería ser previsible en tiempo y esfuerzo, al contar con prototipos funcionales de todas las tecnologías. Se tratará de avanzar en funcionalidad menos importante (al menos estudiando su viabilidad).
La semana santa dificultará la planificación, en función del personal y su disponibilidad por viajes, prácticas, etc.
Además, se debe tratar de completar lo más posible la documentación, en particular todos los tipos de diagramas UML utilizables en nuestro proyecto, así como identificar patrones de diseño tanto preexistentes en nuestro código pero no explicitados, como susceptibles de ser aplicados.
- Abril: Beta 2 (funcionalidad decidida completa). Mantenimiento, pruebas de usabilidad con usuario real, optimización en general, pruebas de empaquetado para distribuir.
Completar la funcionalidad ausente en la anterior iteración. Asimismo, preparar el despliegue de la aplicación, y iniciar un proceso de prueba intensiva, lo más automatizada que sea posible y razonable; consumido el margen de tiempo, se debe tratar de testear lo más posible durante el desarrollo de la aplicación -y no exclusivamente en Abril- para conseguir la máxima fiabilidad del programa, lo que es importante para su éxito.
- Mayo: Release: Empaquetar, y preparar la entrega (diapositivas, vídeo, web, presentación…). Mejorar la calidad todo lo que de tiempo (que será poco por la proximidad de los exámenes).
Perfil de personal
Adri
Administrador de sistemas y hábil en general. Autogestionado. Encargado de la gestión de sistemas del infierno, si se lo propone. Si es fácil, no es para él… C++ -er. Analista en general. Entusiasta donde los haya. Sincero ;). Buen gestor de personal; manejo del látigo eficaz, en particular del de 9 colas, lo que le convierte en el jefe de release ideal.
Carlos
Programador por encargo. Viciado en general. Viajero incansable.
Daniel
Primera baja del proyecto. M.I.A.
David
Databaser. Autogestionado. Programador por encargo bastante rápido; trabaja bajo presión. Asiduo del copy-paste (algo dadaista).
Diana
Analiza tus frases y suelta verdades como puños. Gran consejera. Programadora por encargo.
Eze
Gestor de todo lo gestionable. Maestro en tecnologías varias habidas y por haber. Hijo del bleeding edge (si funciona, actualiza). Capitán diccionario. Analista en general. Arquitecto (le falta la barba blanca solo). Entusiasta pero muy limitado en tiempo.
Fede
Líder nato y relaciones públicas. GNU master. Analista en general. Mejora la moral de la tropa. Hospitalario ^^. Hermano de Eze (por aquello de que también es hijo del bleeding edge). Fuente incansable de ideas a añadir a la apretada agenda.
Jorge
Autogestionado. Programador altamente competente. Tú fast, tú furious.
Mario
Redacta diversos tipos de documentos, observando escrupulosamente las reglas de redacción y ortografía (teniente diccionario, digamos). Programador por encargo. Relajado (paz, hermano).
Rober
Programador por encargo. Mejora notablemente la moral de la tropa. Formateador de cerebros. Currante nato.
Salva
Analista en general. Lead developer estilo ninja (no hace ruido, nadie le ve, pero aparecen sus líneas de código de repente). Master (del universo, digamos). Competente como programador. Entusiasta del proyecto, pero limitado en tiempo. Altamente experimentado. En ocasiones desvaría y hay que meterle en cintura ;) (por ejemplo, con el citado látigo de 9 colas).
Tabas
Programador por encargo. Dbusman y showman en general. Caja de sorprrresas.
Carmen
El nuevo fichaje. Programadora por encargo. Escritora hipermaniática. Friki en sus ratos libres (el resto lo es a tiempo completo)
Planificación iteración Febrero
Tipo de iteración
Elaboración
Objetivos generales
La iteración de Febrero, como estaba previsto en los riesgos de proyecto, no permitirá generar demasiados resultados debido a la presencia de exámenes en las tres cuartas partes del mes. Por tanto se dedicará a cerrar flecos que, por falta de tiempo, hayan quedado cerca de completar en la de Enero. Relegaremos a Marzo el conseguir un prototipo de funcionalidad crítica, así como reasignar recursos de personal, y revisar la viabilidad de los casos de uso, en concreto externalizar backups a medios como CD o discos duros externos, y la integración y usabilidad del interfaz. Además otro objetivo para Marzo será identificar claramente los patrones presentes en nuestro diseño y explicitarlos, y desarrollar los distintos diagramas UML por completo.
Completar módulos Watcher y clase ConfigFileManager
Estas clases son ya funcionales y solo falta terminar de documentarlas, añadir detalles como la detección automática de cambios a mano en el archivo de configuración, y en el caso del gestor de configuración cambiar los accesores genéricos por específicos para poder estandarizar el nombre y valores posibles de las opciones del programa, a fin de reducir los riesgos derivados de la no estandarización y de cubrir del todo la responsabilidad asignada a esta clase.
Unificar la jerarquía de excepciones del programa
En la misma línea del anterior objetivo, se buscará unificar la jerarquía de excepciones usada en el programa y documentarla, a fin de hacer HD Lorean más robusto y legible.
Migrar la información de depuración a la clase HDLogger
A fin de poder tener la información sobre el programa unificada en un único archivo de log y evitar tener que parsear salida por consola, lo cual no es viable para un demonio que debe correr en background, será necesario migrar toda la información de depuración que generemos para que utilice la nueva clase de logging. Ello debería ser sencillo, pero por el volumen de la base de código es probable que no se llegue a finalizar para Febrero. Unificar el logging permitirá, junto con las excepciones, automatizar los tests sobre la aplicación más fácilmente.
Concluir la integración de las bases de código
Si bien la integración se realizó durante la pasada iteración, queda sencillamente avisar a los distintos equipos de desarrollo del nuevo modelo de trabajo y migrar los repositorios para que todo el mundo trabaje con la base común de código. Será necesario por tanto actualizar la documentación de los procesos de trabajo para reflejar este nuevo hecho. Además se ha considerado deseable -de cara a facilitar las pruebas y el análisis sobre la aplicación- que dicha base de código común sea funcional como un proyecto de pydev (el plugin de desarrollo python para el IDE eclipse), trabajo que aún está pendiente de hacer.
Revisión de calidad de la documentación
El grueso del trabajo de revisión está centrado en los documentos de clases y su interacción de la iteración de Diciembre, pero por falta de un módulo no fue posible tener esta revisión lista para Enero. Se tratará de actualizar para esta iteración.
Decisión de la licencia final del código
Dado que utilizamos código diverso del mundo del software libre, habrá que investigar la licencia definitiva que podemos usar, que probablemente será GPLv2. Sería también conveniente configurar el entorno de desarrollo para que genere los nuevos archivos con una cabecera de licencia, y añadirla a los existentes (algo fácilmente automatizable).
Investigación sobre integración con nautilus y unit tests de python
A fin de poder desarrollar cuanto antes el análisis de viabilidad de Marzo, se intentará investigar en la última semana de febrero sobre las posibilidades prácticas de la integración con el navegador de archivos de Gnome. Asímismo se comenzará la investigación y documentación sobre la funcionalidad de unit test que ofrece python, con vistas a automatizar esos tests cada noche del mismo modo que está automatizada la generación de documentación.
Reparto de trabajo
Al no haber objetivos nuevos se mantiene el reparto de trabajo de la anterior iteración, con vistas a renovarlo y realizar movimientos de personal en la siguiente iteración de Marzo, probablemente reasignando responsables de grupo. Es probable que sean necesarias ayudas de todo el equipo con la documentación, ya que forma el grueso de los objetivos para Febrero y es responsabilidad de una única persona.
Estimaciones de tiempo
- 12 de febrero: Proyecto pydev listo sobre la base común de código .
- 25 de febrero: Todos hemos concluido exámenes. Iniciar preparación de la entrega, que debe consistir sobre todo en documentación y la planificación para Marzo.
- 29 de febrero: Entrega
Seguimiento
Seguimiento Enero
Objetivos cumplidos
Integración de bases de código
Si bien el código del equipo de desarrollo del formato de snapshots no ha podido llegar a tiempo a la integración, las distintas bases de código ya están juntas en una única, de la que los distintos equipos harán branches independientes para trabajar en adelante. Para el equipo de desarrolladores trabajar sobre ramas de desarrollo separadas, y únicamente permitir acceso a los integradores en la rama conjunta y "de entregas" del código nos permitirá mucho más control de calidad que trabajar sobre un único repositorio, sin aumentar los riesgos derivados de ello ya que sí son posibles integraciones de código parciales entre código de los equipos, y todo el mundo tiene una versión razonablemente actualizada del código de los demás para poder probar. Además tener la aplicación completa permitirá una mayor visión de conjunto a todo el mundo de la función de sus respectivos subsistemas en el global de la aplicación.
Módulo Watcher
El módulo Watcher, a falta de retoques finales- como que se detecten automáticamente cambios hechos a mano en la configuración-, está finalizado. La lógica de planificación por ahora no existe por no ser crítica y depender de pruebas en condiciones reales, pero todo el código está listo para que pase por el planificador y por tanto es factible no realizar backups si no se está conectado a la corriente, o si la carga de CPU o E/S es demasiado alta. Ello permitirá reasignar a sus componentes de personal a grupos más necesitados de personal.
Wrapper base de datos
Los componentes dependientes de una tecnología concreta han sido abstraidos a un módulo wrapper que encapsula y abstrae los lenguajes propios de sqlite al resto de la aplicación. Esto, con poco coste de desarrollo y sobrecarga, nos permite reducir al mínimo el riesgo de que sqlite no de la talla para nuestros requisitos, facilitándonos un futuro cambio de tecnología de base de datos que durante el desarrollo se temió (sin llegar a confirmarse) necesario. Quedan por fijar las consultas finales que se harán desde las distintas tablas a la base de datos, que no están fijadas aún en código por no saberse fijas, pero que también irán en sitios concretos y abstraerán la funcionalidad que proporcionan las bases de datos del código SQL necesario para las mismas.
Especificación del formato de backups
Tras un importante esfuerzo de desarrollo se ha completado una especificación del formato de snapshots que esperamos sea lo bastante completa para el resto del trabajo que queda por hacer. Se adjunta al final de la entrega de Enero.
Tabla de historia
La tabla de historia, donde se guarda toda la información de los snapshots que almacena el sistema y donde se diseñaron las operaciones más críticas, está diseñada e implementada en los diversos módulos.
Comunicación frontend / backend
Con mayores dificultades de las previstas en el desarrollo, dbus ha cumplido su cometido y nos permitirá separar la aplicación en un demonio que corra siempre y un gui. Quedan por limar detalles de la implementación (como que si se lanza el gui sin un demonio corriendo arranque al demonio), pero el problema ha quedado solventado. Ello además conlleva modificaciones del diseño UML, ya que el propio sistema dbus actúa como proxy y elimina la funcionalidad del módulo DbusManager.
Cron
Un módulo sencillo que ha complicado el desarrollo del watcher por problemas con su nula integración con dbus para poder pasar mensajes al backend de la aplicación. Su desarrollo completo (incluyendo funcionalidad de realizar las tareas pendientes si el equipo estaba apagado) permite en adelante una planificación adecuada de backups, con funcionalidad como p.e. generar backups integrales por seguridad cada mes con la que se contaba en la planificación inicial de requisitos de HD Lorean.
Requisitos tiempo y espacio
Se han realizado las estimaciones pedidas de tiempo y espacio de la aplicación, que se adjuntan en la entrega de documentación de Enero.
Generación automática de documentación
Un script en la máquina de un miembro del equipo permitirá que, cada noche, se genere automáticamente la documentación de todos los módulos de HD Lorean, lo que sin duda facilitará el desarrollo y la comunicación entre equipos. Dicha documentación se encuentra en http://www.hdlorean.com .
Revisión de calidad de la documentación
Aunque aún no se encuentre finalizada, se ha efectuado una revisión en profundidad de los documentos de clases e interacciones de clases que se generaron la anterior iteración, y todos los problemas detectados se corregirán tan pronto como se terminen de concretar las clases que finalmente quedarán en el proyecto.
Objetivos no alcanzados
Reducir el riesgo del núcleo de la aplicación
El riesgo de rdiff-backup se ha mostrado crítico, tal y como se previo en la planificación del mismo. Finalmente dicha aplicación no cubre ni nuestros casos de uso (en particular borrados), ni nuestras restricciones informales de tiempo y espacio. La dificultad ha venido de que estos problemas no aparecieron en la fase de investigación debido a pruebas insuficientes para revelarlos, lo cual, junto a otra serie de problemas que se mencionan en "nuevos riesgos", ha impedido lograr los principales objetivos planificados para esta iteración y obligarán a modificar notablemente el plan de fase, y probablemente el alcance previsto de HD Lorean.
Primer prototipo funcional
Al no tener un módulo funcionando que hiciera los snapshots, nuestro siguiente prototipo es incompleto y solo se ha podido desarrollar funcionalidad periférica.
Interfaz de navegación de archivos
Los citados problemas de comunicación entre equipos, unidos al retraso del grupo encargado de los snapshots y a una dificultad imprevista para el grupo de GUI en desarrollar una interfaz más allá de las posibilidades del diseñador de interfaces Glade han paralizado casi por completo el desarrollo de la interfaz. Al no haber snapshots funcionando aún, no estaba claro qué se debía mostrar, y al no poder desarrollar tampoco la interfaz a tiempo el resultado ha sido no tener un API claro con los datos que tiene -o tendrá- el sistema de backups almacenados dentro.
Fijar la arquitectura del sistema.
Pese a que la arquitectura preliminar se ha mostrado bastante acertada, aún quedan flecos por concretar en los módulos por terminar, y APIs por definir entre módulos como la citada en el apartado anterior sobre información de un snapshot. Dichas APIs habrán de esperar para ser estables a que el núcleo de la aplicación esté concluido y funcionando, pero se está trabajando en aproximaciones cuanto antes a ellas.
UML
Tras cerca de dos semanas de investigación, se ha concluido que, debido a las características altamente dinámicas de python como lenguaje (reescritura de los diccionarios de funciones de las clases, por poner un ejemplo), no existen -o no se han logrado localizar- herramientas libres y de calidad que generen automáticamente ningún tipo de diagrama UML lo suficientemente completo y útil a partir del código existente. Ello ha ralentizado y frenará en el futuro el crear documentación en este lenguaje, ya que ha de ser mantenida a mano por cada equipo de desarrollo y está muy desacoplado del código fuente. A falta de investigar algunas alternativas de última hora que se han localizado, el UML se está generando a mano mediante la herramienta umbrello, que permite crear todos los tipos de diagramas necesarios; no obstante nos limitaremos a una descripción lo más de alto nivel posible (algo menos que subsistema, pero sin llegar a *todas* las clases necesarias) para que nos sea útil sin dificultar el trabajo.
Un ejemplo del trabajo realizado son las siguientes dos instantáneas:
Diagrama de interacción (parcial) para el caso de uso 2: Añadir nueva carpeta a indexar
Fijar prioridades de los casos de uso
Por falta de tiempo no se ha realizado de un modo formal y consensuado, quedando implícito que la funcionalidad prioritaria es realizar y restaurar un snapshot, así como borrarlos para poder mitigar el impacto en espacio de la aplicación, que se preve el más crítico. Queda por tanto pendiente.
Investigación tecnologías (beagle, nautilus, HAL)
La falta de tiempo general ha provocado que haya sido imposible la investigación de tecnologías adicionales. Exceptuando nautilus, que se considera mucho más deseable de cara a la usabilidad de la aplicación, es probable que el resto queden fuera de alcance en la revisión que se haga del mismo en la próxima iteración.
Documentación adicional
De la documentación adicional faltan aún las guidelines de python y las de integración, aunque sobre python ya hemos concretado aspectos importantes como por ejemplo cómo guardar registros de errores / debug. Se han retrasado por problemas de incomunicación durante el periodo estival entre responsables, y se ha decidido esperar a concluir la integración en una sola base de código para simplificar la tarea a todos los miembros del grupo.
Riesgos reducidos
Sqlite
Al disponer de un wrapper según el diseño de la arquitectura, ya no dependemos tanto de esa tecnología específica y sería más sencillo cambiar a otra más potente como mysql.
Rdiff-backup
Al no usar esta tecnología, tras haber mostrado sus consecuencias su riesgo desaparece.
Problemas de definición de la arquitectura
La arquitectura diseñada parece responder a las necesidades de la aplicación correctamente, lo cual ha sido un éxito de diseño conseguido gracias a la interacción de clases con tarjetas CRC. En general el equipo es más consciente de la misma.
Investigación instalador
Se ha investigado la tecnología de instalación de python (distutils), lo que ha contruibuido a la viabilidad de integrar todas las distintas bases de código en una y facilitará el proceso de despliegue hacia el final del proyecto.
Integración de código (buscar por "bazaar").
Ya está claro y probado cómo se realizará la integración del código de los distintos equipos, y solo queda generar la documentación pertinente.
Demonio y frontend corriendo independientementes
El riesgo tecnológico que presentaba dbus como tecnología de interconexión está controlado y resuelto; ya tenemos la aplicación separada en demonio y frontend.
Nuevos riesgos
Aumenta: no lograr cubrir los casos de uso requeridos por la aplicación, por las nuevas dificultades de desarrollo en el backend. Ya no tenemos el colchón de seguridad que proporcionaba basarnos en una aplicación ya probada.
Aumenta: no lograr que HD Lorean sea lo bastante intuitivo y transparente al usuario, por falta de tiempo en el desarrollo que haga imposible lograr suficiente integración con el escritorio.
Nuevo riesgo tecnológico: por las tentativas que hay de formato de backups se ha detectado que usa un gran número de archivos. El número de inodos posibles en un sistema de ficheros está limitado, y si no se tiene cuidado podemos toparnos con él.
Aumenta: Falta de tiempo; el segundo cuatrimestre dos miembros del equipo se han incorporado a sendos trabajos, y además hay una optativa con prácticas que muchos de nosotros cursaremos que nos robará aún más tiempo.
Tiempo real empleado
Menor del deseable y planificado, ya que la planificación para las navidades no era realista y casi nadie ha sacado el tiempo necesario.
Conclusiones
Esta iteración ha resultado poco exitosa por la unión de varios factores. El principal problema que hemos debido afrontar ha sido el riesgo tecnológico de rdiff-backup, tecnología que no supimos detectar a tiempo que no era suficiente para nuestros propósitos porque nuestras pruebas fueron demasiado reducidas en ámbito; sencillamente no ha habido suficiente tiempo para finalizar el desarrollo de una tecnología nueva de snapshot desde cero. Por otra parte, en general todos hemos trabajado sensiblemente menos de lo planificado, lo cual nos servirá para futuras estimaciones de tiempo en presencia de otras fiestas de guardar. Además ha habido problemas importantes de comunicación entre equipos, y entre miembros de equipos, que han parado completamente el desarrollo durante las vacaciones; no se han sabido resolver los interbloqueos con propuestas de compromiso de API, lo cual ha detenido mucho al grupo de GUI, que por otra parte se ha encontrado en su desarrollo con más problemas de los esperados al comenzar con la funcionalidad más compleja del mismo. Asimismo, la sensación general ha sido de moderado desánimo, provocado por el cansancio, por haber encontrado las primeras dificultades de cierta envergadura en el desarrollo, y también en parte por una falta de delimitación de tareas claras que en ocasiones dejaba a la gente desocupada, esperando instrucciones sobre qué hacer que se creían entendidas.
Para solucionar estos problemas, en Marzo haremos una revisión profunda de procesos de desarrollo y reasignaremos al personal de Watcher, para mejorar esos problemas de comunicación y centrar los esfuerzos de programación en las zonas más necesitadas. Intentaremos recuperar el máximo posible del tiempo gastado de la planificación de fase original, para conseguir completar el máximo de funcionalidad posible. En cuanto al reparto de tareas, se espera que teniendo el código unificado sea más claro quién tiene que hacer qué y en qué momento, a lo que también contribuirán los movimientos de responsables en el personal.
Además será necesario reevaluar en profundidad las planificaciones, lo que probablemente obligará a reducir el alcance de la aplicación y la viabilidad del desarrollo de algunos de sus casos de uso.
Estimaciones de tiempo y espacio
Estimación de espacio
HD Lorean es una aplicación de backup basada en diferenciales. Esto es, si sus ficheros han cambiado, HD Lorean no los copiará de nuevo, sólo considerará los cambios realizados desde la última vez, lo que permite ahorrar espacio en su disco duro. Si no han cambiado, sencillamente no los copiará y no gastará ningún tipo de espacio extra. Sin embargo, en ocasiones las modificaciones son tan grandes que los archivos de diferencias ocupan más que el archivo original; esta situación es detectada por HD Lorean, que sencillamente realiza una nueva copia. Además, los archivos de diferencia también deben guardar información extra que indique si se ha eliminado, añadido o cambiado información, y esta información extra también conlleva sobrecarga de espacio.
Por lo general, para documentos de texto, la realización de archivos de diferencia es una práctica muy eficiente y, suponiendo que los archivos de texto de un usuario aumenten de manera lineal (o un poquito cada día) el tamaño $T$ ocupado en disco al cabo de $n$ copias de seguridad viene dado por la expresión:
(1)En esta expresión, $c$ es la cantidad de bytes añadidos por cada copia de seguridad y $\delta$ es un valor entre 0 y 1 que indica cuánto mejor es el programa de creación de archivos de diferencias. Esto es, cuanto más cerca de 0, mejor. Un valor típico es 0.1 y usaremos este para las simulaciones.
Como se puede observar, el crecimiento del tamaño es parabólico y la siguiente tabla refleja algunos resultados esperados para archivos de diferente tamaño inicial al cabo de 30 diferenciales (uno al día durante un mes) en los que, cada vez, se han añadido 4000 bytes de información nueva.
$T_{inicial}$ | $T_{con\_diferenciales}$ | $T_{sin\_diferenciales}$ | Espacio de disco ahorrado |
---|---|---|---|
8KB | 2MB | 1.9MB | 5% |
80KB | 4.1MB | 2MB | 51% |
800KB | 21.2MB | 2.7MB | 87% |
Los resultados son, a la vista, muy buenos.
Ahora bien, los archivos de otros tipos multimedia como la música, las imágenes o los vídeos vienen muchas veces comprimidos lo que impide realizar diferenciales de manera eficiente. No obstante la edición de estos archivos es mucho más esporádica, y localizada en áreas pequeñas del mismo (EXIF, ID3, etc). En cualquier caso, si se llegasen a cambiar probablemente lo más rentable sea realizar una copia en vez de un archivo de diferencias. Por tanto para este tipo de archivos el tamaño ocupado en disco es de la forma:
(2)Aunque pudiera parecer un inconveniente, la experiencia confirma que son los archivos de texto los más susceptibles a cambios mientras que los archivos multimedia se editan poco. Este equilibrio unido a la potencia de los archivos de diferencias hace de HD Lorean la aplicación ideal en su género en cuanto a consumo de espacio en disco.
Estimación de tiempo
HD Lorean puede realizar copias de seguridad integrales (esto es, copiar el archivo tal cual) en cuyo caso la velocidad del snapshot vendrá determinada por el número de archivos que lo compongan y el tamaño de los mismos así como la velocidad de acceso, lectura y escritura del hardware. O bien puede realizar copias incrementales, en cuyo caso la velocidad depende por un lado del tiempo necesario para crear el diferencial (que depende a su vez del tamaño del archivo) y por otro lado de los parámetros ya citados.
De esta forma, la expresión que rige el tiempo $t$ tardado por un snapshot viene dado por la expresión:
(3)Donde $t_{sistema}$ es el retraso debido al hardware y considerando que existen $dif$ archivos sobre los que se va a crear un diferencial y $int - dif$ archivos que se copiarán íntegramente. Para los archivos de los que se creará un diferencia, el tamaño del mismo se encuentra multiplicado por el retraso en la creación de dicho diferencial $t_{diferencial}$.
La estimación en tiempo, lineal respecto del número de archivos esta vez, puede parecer simple y previsible pero también hay que tener en cuenta que HD Lorean monitoriza los archivos en uso de manera constante y por lo tanto, a excepción de la primera copia de seguridad que probablemente se realice sobre todo el sistema, el resto de copias quedará reducido al conjunto de archivos que cambien. Y esto precisamente reducirá el tiempo empleado por snapshot del sistema.
Conclusiones
De esta forma, se concluye que la eficiencia en el uso del espacio es significativamente mejor cuanto más copias de seguridad se realicen sobre un archivo grande (debido a la creación de archivos de diferencias) o, en el peor de los casos, tan buena como guardar todas las versiones del archivo.
Por otro lado el coste en tiempo es lineal respecto del número de elementos que compongan el snapshot.
Especificación del formato de snapshots
Este documento pretende explicar, de cara a nuestros propios desarrolladores o a terceros, cómo HD Lorean organiza la información de las copias de seguridad y cómo operan las distintas operaciones disponibles.
Glosario
- backup: copia de seguridad de un archivo o directorio, bien sea en forma de copia o en forma de incremental.
- sistema de copias de seguridad: un sistema de copias de seguridad permite restaurar parte de un sistema de archivos a un estado anterior denominado snapshot.
- snapshot: unidad mínima del sistema de copias de seguridad. Formado por los ficheros necesarios para la recuperación de archivos y directorios en el instante de la creación del mismo además de otros ficheros de mantenimiento.
- snapshot-incremental: snapshot en el que los backup necesarios para la recuperación de archivos son diferenciales sobre el original, optimizando así el uso del espacio.
- snapshot-íntegro: snapshot en el que los backup necesarios para la recuperación de archivos son versiones íntegras de esos archivos en ese instante.
- snapshot-core: módulo encargado de la creación y mantenimeinto de los snapshot de HD-Lorean.
- timestamp: o sello de tiempo es una cadena de caracteres que representa el instante actual. Se utiliza como una marca única para identificar un instante de tiempo dado y puede actuar a varias resoluciones. La resolución puede ser anual si sólo se determina el año; mensual, si se determina además el mes; diaria, si añadimos el dia o incluso mayor si contabilizamos horas, minutos y segundos.
- versión: versión de un fichero o directorio en un instante dado. La lista de las versiones de un fichero nos indica como ha ido variando el contenido del fichero. La lista de las versiones de un directorio comprende cada versión de los ficheros y directorios que estén contenidos en ella. De esta manera, si se produce una nueva versión de un fichero, se produce una nueva versión del directorio que lo contiene, y del que contiene a éste, y así de forma recursiva hasta '/', por lo tanto, '/' cambia cuando se modifica cualquiera de los ficheros del sistema.
Timestamps
Un snapshot ocurre en un determinado momento caracterizado por una marca de tiempo o timestamp de la forma AAAA-MM-DD@HH:mm:SS+/-D [DST] donde:
- AAAA es el año de cuatro dígitos.
- MM es el número de mes dentro del año, de dos cifras.
- DD es el día del mes.
- HH es la hora del día en formato 24H.
- mm es el minuto de esa hora.
- SS es el segundo del minuto anterior.
- +/-D es la diferencia al tiempo global o GMT.
- DST es opcional e indica si se aplica el horario de verano.
En HD Lorean los timestamp no sólo se limitan a registrar el momento en el que sucede un snapshot sino que también los clasifican como veremos en el próximo apartado.
Directorio de snapshots
El directorio de almacenamiento de snapshots o sencillamente, directorio de snapshots, es el lugar indicado por el usuario donde se almacenan los snapshots. Por defecto, se encuentra en el home del usuario
/home/usuario/.hdlorean/snapshots/
En su interior se crea una estructura arbórea de carpetas basada en el timestamp del snapshot de la forma
./snapshots/AAAA/MM/DD/HH-mm-SS+D/
Y en último término se reconstruyen las rutas desde la raíz hasta cada uno de los archivos parte del snapshot y se almacenan en esta ubicación. Así, un snapshot del directorio /home/salvador/pruebas/ ocurrido el día 16 de Enerro de 2007 en España a las seis y media de la tarde se almacenaría bajo la siguiente ruta.
/home/usuario/.hdlorean/snapshots/2008/01/16/18-30-01+1/home/salvador/pruebas/
/home/usuario/.hdlorean/snapshots/2008/01/16/18-30-01+1/home/salvador/pruebas/archivoA.txt.diff
/home/usuario/.hdlorean/snapshots/2008/01/16/18-30-01+1/home/salvador/pruebas/archivoB.txt.int
/home/usuario/.hdlorean/snapshots/2008/01/16/18-30-01+1/home/salvador/pruebas/mas pruebas/
/home/usuario/.hdlorean/snapshots/2008/01/16/18-30-01+1/home/salvador/pruebas/mas pruebas/archivoC.txt.int
/home/usuario/.hdlorean/snapshots/2008/01/16/18-30-01+1/home/salvador/pruebas/mas pruebas/archivoD.txt.diff
Los archivos almacenados en cada snapshot no son copias de los archivos originales, sino backups integros o diferenciales generados tal y como se describe a continuación.
Ficheros del snapshot
Una versión se realiza sobre un conjunto de archivos y directorios ubicados en algún punto del sistema. Buscando en versiones anteriores, HD Lorean comprueba para cada archivo la existencia de una versión íntegra y de encontrarlo, realiza un diferencial de la versión anterior respecto de la última integral y guarda este diferencial añadiendo la extensión .diff al archivo. Si no existe una versión íntegra o el diferencial supera en tamaño la versión actual del archivo, entonces HD Lorean copia el archivo tal cual y le añade la extensión .int indicando así que se trata de un backup íntegro del archivo.
Resumiendo, las extensiones posibles son:
- .diff se trata de una versión diferencial respecto de la versión integral más cercana en el pasado.
- .int se trata de una versión integral, o lo que es lo mismo, una copia del archivo en ese momento.
De esta manera, en el ejemplo anterior, eran diferenciales los archivos
/home/usuario/.hdlorean/snapshots/2008/01/16/18-30-01+1/home/salvador/pruebas/archivoA.txt.diff
/home/usuario/.hdlorean/snapshots/2008/01/16/18-30-01+1/home/salvador/pruebas/mas pruebas/archivoD.txt.diff
Mientras que integrales eran
/home/usuario/.hdlorean/snapshots/2008/01/16/18-30-01+1/home/salvador/pruebas/archivoB.txt.int
/home/usuario/.hdlorean/snapshots/2008/01/16/18-30-01+1/home/salvador/pruebas/mas pruebas/archivoC.txt.int
Además, por cada carpeta parte del snapshot como podrían se en el ejemplo las carpetas
/home/usuario/.hdlorean/snapshots/2008/01/16/18-30-01+1/home/salvador/pruebas/
/home/usuario/.hdlorean/snapshots/2008/01/16/18-30-01+1/home/salvador/pruebas/mas pruebas/
HD Lorean almacena en su interior un fichero nombrado this.content con un listado (no recursivo) de los archivos y directorios (además de sus atributos como permisos y demás) del directorio en el instante de realizar el snapshot. Este fichero cobrará verdadera importancia a la hora de implementar las opciones de recuperación de snapshots.
El resto de datos útiles asociados a los ficheros, como los atributos se almacenan en una estructura externa o tabla de la base de datos.
Interacción con base de datos
Para entender esta sección se requiere un dominio avanzado del flujo de ejecución de HD Lorean.
HD Lorean emplea un método basado en journal para garantizar snapshots monolíticos y permitir recomenzar un snapshot en caso de falla durante el proceso. Para ello, el planificador deja constancia del comienzo de un nuevo snapshot mediante la inserción de un testigo en el journal. El testigo indica que todos los ficheros y directorios no escritos presentes en el journal anteriores al resgistro testigo forman parte del snapshot actual. Es interesante observar que los archivos pertenecientes a un snapshot en particular se encuentran en el journal en las filas delimitadas por ese snapshot (por delante) y el anterior (por detrás). El journal usa un testigo fantasma como centinela al comienzo de la tabla y así mantiene la regularidad.
Conforme los archivos sean procesados, el constructor de snapshots los marcará como escritos. Una vez todos los archivos hayan sido procesados, el testigo será marcado como finalizado y se dará por finalizada la operación.
En caso de fallo, el estado del journal nos ayudará a recuperarnos del error. Estos son los posibles casos:
- Testigo NO TERMINADO y presencia de archivos NO ESCRITOS - ha habido una falla durante el proceso. El módulo de recuperación de snapshots (parte del planificador) decide qué hacer con el snapshot. Por ejemplo, continuar o recomenzar.
- Testigo NO TERMINADO y todos los archivos ESCRITOS - ha habido una falla justo al final del proceso. El planificador vuelve a hacerse cargo, sin embargo se recomienda que el testigo se marque como TERMINADO y no se haga más.
- Testigo TERMINADO y todos los archivos ESCRITOS - snapshot completado con éxito.
- Testigo TERMINADO y presencia de archivos NO ESCRITOS - error, puesto que el testigo sólo se marca como escrito sólo si todos los archivos precedentes ya han sido escritos.
Operaciones sobre snapshots
Crear un snapshot para un conjunto de ficheros y directorios
A la hora de crear un fichero, el planificador enviará una lista de tuplas con los siguientes campos extraídos directamente del journal:
[<identificador del fichero o directorio cambiado, timestamp, operación sobre la ruta, ruta1, ruta2>]
El identificador es necesario para ver qué archivo estamos tratando. El timestamp refleja el momento en el que ocurrió la operación dada por el campo operación. Esta operación puede ser del tipo creación, borrado o modificación1. La ruta1 es la ruta sobre la que tiene lugar la operación y ruta2 la ignoraremos por ahora.
Implementado en | ¿Pasa por el scheduler? | Usa threads |
---|---|---|
xdeltawrapper | si | no |
- Generar el timestamp del snapshot
- Generar el directorio oportuno atendiendo al timestamp
- Para cada elemento de la lista
- Extraer atributos del fichero o directorio
- Reconstruir, dentro del directorio del snapshot, la ruta hasta el archivo (o directorio, incluido este último)
- Si es un fichero
- Si la operación es modificar o crear
- Buscar ultimo integral en base de datos
- Si no se encuentra -> copiar fichero actual como integral.
- Si sí se encuentra -> crear diferencial respecto del fichero integral.
- Si el diferencial es superior en tamaño al archivo original -> copiar fichero actual como integral.
- Generar el fichero con el listado de archivos y atributos del directorio padre del fichero
- Si la operación es modificar o crear
- Si es un directorio
- Si la operación es modificar
- Generar el fichero con el listado de archivos del directorio y atributos
- Si la operación es borrar
- Generar el fichero con el listado de archivos y atributos del directorio padre del directorio
- Si la operación es crear
- Obtener todos los contenidos (de manera recursiva) del directorio
- Llamar a este algoritmo para esa lista
- Obtener todos los contenidos (de manera recursiva) del directorio
- Si la operación es modificar
- Escribir (en el journal) en la entrada correspondiente al identificador, si la versión fue integral o diferencial y sustituir su timestamp por el del snapshot.
- Escribir los atributos en base de datos
- Marcar (en el journal) el fichero (o directorio) como procesado.
Crear un snapshot forzando el hecho de que todos los backups sean integrales
Ver consideraciones iniciales del apartado anterior.
Implementado en | ¿Pasa por el scheduler? | Usa threads |
---|---|---|
xdeltawrapper | si | no |
- Generar el timestamp del snapshot
- Generar el directorio oportuno atendiendo al timestamp
- Para cada elemento de la lista
- Extraer atributos del fichero o directorio
- Reconstruir, dentro del directorio del snapshot, la ruta hasta el archivo (o directorio, incluido este último)
- Si es un fichero
- Si la operación es modificar o crear
- Copiar el archivo como integral
- Generar el fichero con el listado de archivos y atributos del directorio padre del fichero
- Si la operación es modificar o crear
- Si es un directorio
- Si la operación es modificar
- Generar el fichero con el listado de archivos del directorio y atributos
- Si la operación es borrar
- Generar el fichero con el listado de archivos y atributos del directorio padre del directorio
- Si la operación es crear
- Obtener todos los contenidos (de manera recursiva) del directorio
- Llamar a este algoritmo para esa lista
- Obtener todos los contenidos (de manera recursiva) del directorio
- Si la operación es modificar
- Escribir (en el journal) en la entrada correspondiente al identificador, si la versión fue integral o diferencial y sustituir su timestamp por el del snapshot.
- Escribir los atributos en base de datos
- Marcar (en el journal) el fichero (o directorio) como procesado.
Recuperar un snapshot a una carpeta dada
Implementado en | ¿Pasa por el scheduler? | Usa threads |
---|---|---|
xdeltawrapper | no | sí |
Inicializamos carpeta actual a la carpeta del snapshot
- Obtener el listado de la carpeta actual.
- Por cada elemento de la lista anterior
- Si el elemento no se trata de '.' (ella misma) o '..' (su carpeta padre)
- Si es un directorio
- Llamar recursivamente a este método haciendo que carpeta actual sea el directorio
- Si es un fichero
- Directorio del fichero = Regenerar la ruta completa del fichero dentro del directorio destino
- Si es integral
- Copiar en el directorio del fichero eliminando la extensión .int
- Si es diferencial
- Buscar en BD el timestamp del último integral para este archivo (anterior o igual al timestamp pasado como parámetro)
- Si no existe
- No restaurar // Quiere decir que jamás fue administrado por HD Lorean
- Si sí existe
- Aplicar diferencial sobre el integral y copiar el resultado dentro del directorio del fichero.
- Si no existe
- Buscar en BD el timestamp del último integral para este archivo (anterior o igual al timestamp pasado como parámetro)
- Si es un directorio
- Si el elemento no se trata de '.' (ella misma) o '..' (su carpeta padre)
Borrar un snapshot
Implementado en | ¿Pasa por el scheduler? | Usa threads |
---|---|---|
xdeltawrapper | no | sí |
Versión 1
- Se envia el timestamp del snapshot seleccionado para borrar a la base de datos, preguntando si es integral o no. Y se le pide el timestamp del siguiente integral si existe.
- En caso de ser un diferencial, simplemente se borra.
- En caso de ser un integral, y si hay al menos un diferencial antes del timestamp del siguiente integral, se procede a montar el siguiente snapshot, el del timestamp+1, para dejarlo como nuevo integral. Se le pide que este nuevo integral se cambie de diferencial a integral en la base de datos. Tambien hay que ir reconstruyendo cada versión posterior, para hacer el diferencial respecto al nuevo integral, para todas las versiones hasta llegar al siguiente integral.
- Se le pide a la base de datos que borre el snapshot pedido de la lista de snapshots.
Versión 2
- Marcar en DB como prohibidos todas las versiones integrales para el timestamp dado
- Recuperar un listado desde DB de todas las versiones diferenciales del timestamp dado
- Para cada elemento de la lista
- Borrar el diferencial de disco
- Borrar las entradas de DB
Justificación por qué es mejor la versión 2
Borrar toda la línea temporal de un archivo
Implementado en | ¿Pasa por el scheduler? | Usa threads |
---|---|---|
xdeltawrapper | no | sí |
- Seleccionar en BD todos los timestamp para la ruta en cuestión.
- Por cada timestamp
- Encontrar el archivo en el sistema de archivos
- Borrar el archivo
- Eliminar los archivos de la base de datos
Recuperar el histórico de un fichero o directorio
Implementado en | ¿Pasa por el scheduler? | Usa threads |
---|---|---|
xdeltawrapper | no | sí |
- Si es un directorio
- Crear una tabla hash con clave un timestamp y valor una lista de cadenas
- Recuperar un listado de todos los timestamp para el directorio dado
- Por cada timestamp de la lista
- Añadir a la tabla hash con clave el timestamp actual, el contenido del fichero de contenidos del directorio para el timestamp actual
- Si es un fichero
- Crear una tabla hash con clave un timestamp y valor un enumerado con las operaciones posibles sobre un fichero (a saber y por ahora: CREADO, BORRADO, MODIFICADO)
- Recuperar una tabla desde BD con campos timestamp y operacion para el fichero dado
- Convertir esta tabla en la tabla hash
- Devolver la tabla hash