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
  1. Generar el timestamp del snapshot
  2. Generar el directorio oportuno atendiendo al timestamp
  3. Para cada elemento de la lista
    1. Extraer atributos del fichero o directorio
    2. Reconstruir, dentro del directorio del snapshot, la ruta hasta el archivo (o directorio, incluido este último)
    3. Si es un fichero
      1. Si la operación es modificar o crear
        1. Buscar ultimo integral en base de datos
        2. Si no se encuentra -> copiar fichero actual como integral.
        3. Si sí se encuentra -> crear diferencial respecto del fichero integral.
        4. Si el diferencial es superior en tamaño al archivo original -> copiar fichero actual como integral.
      2. Generar el fichero con el listado de archivos y atributos del directorio padre del fichero
    4. Si es un directorio
      1. Si la operación es modificar
        1. Generar el fichero con el listado de archivos del directorio y atributos
      2. Si la operación es borrar
        1. Generar el fichero con el listado de archivos y atributos del directorio padre del directorio
      3. Si la operación es crear
        1. Obtener todos los contenidos (de manera recursiva) del directorio
          1. Llamar a este algoritmo para esa lista
    5. 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.
    6. Escribir los atributos en base de datos
    7. 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
  1. Generar el timestamp del snapshot
  2. Generar el directorio oportuno atendiendo al timestamp
  3. Para cada elemento de la lista
    1. Extraer atributos del fichero o directorio
    2. Reconstruir, dentro del directorio del snapshot, la ruta hasta el archivo (o directorio, incluido este último)
    3. Si es un fichero
      1. Si la operación es modificar o crear
        1. Copiar el archivo como integral
      2. Generar el fichero con el listado de archivos y atributos del directorio padre del fichero
    4. Si es un directorio
      1. Si la operación es modificar
        1. Generar el fichero con el listado de archivos del directorio y atributos
      2. Si la operación es borrar
        1. Generar el fichero con el listado de archivos y atributos del directorio padre del directorio
      3. Si la operación es crear
        1. Obtener todos los contenidos (de manera recursiva) del directorio
          1. Llamar a este algoritmo para esa lista
    5. 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.
    6. Escribir los atributos en base de datos
    7. 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

Inicializamos carpeta actual a la carpeta del snapshot

  1. Obtener el listado de la carpeta actual.
  2. Por cada elemento de la lista anterior
    1. Si el elemento no se trata de '.' (ella misma) o '..' (su carpeta padre)
      1. Si es un directorio
        1. Llamar recursivamente a este método haciendo que carpeta actual sea el directorio
      2. Si es un fichero
        1. Directorio del fichero = Regenerar la ruta completa del fichero dentro del directorio destino
        2. Si es integral
          1. Copiar en el directorio del fichero eliminando la extensión .int
        3. Si es diferencial
          1. Buscar en BD el timestamp del último integral para este archivo (anterior o igual al timestamp pasado como parámetro)
            1. Si no existe
              1. No restaurar // Quiere decir que jamás fue administrado por HD Lorean
            2. Si sí existe
              1. Aplicar diferencial sobre el integral y copiar el resultado dentro del directorio del fichero.

Borrar un snapshot

Implementado en ¿Pasa por el scheduler? Usa threads
xdeltawrapper no

Versión 1

  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.
  2. En caso de ser un diferencial, simplemente se borra.
  3. 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.
  4. Se le pide a la base de datos que borre el snapshot pedido de la lista de snapshots.

Versión 2

  1. Marcar en DB como prohibidos todas las versiones integrales para el timestamp dado
  2. Recuperar un listado desde DB de todas las versiones diferenciales del timestamp dado
  3. Para cada elemento de la lista
    1. Borrar el diferencial de disco
  4. 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
  1. Seleccionar en BD todos los timestamp para la ruta en cuestión.
  2. Por cada timestamp
    1. Encontrar el archivo en el sistema de archivos
    2. Borrar el archivo
  3. 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
  1. Si es un directorio
    1. Crear una tabla hash con clave un timestamp y valor una lista de cadenas
    2. Recuperar un listado de todos los timestamp para el directorio dado
    3. Por cada timestamp de la lista
      1. Añadir a la tabla hash con clave el timestamp actual, el contenido del fichero de contenidos del directorio para el timestamp actual
  2. Si es un fichero
    1. 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)
    2. Recuperar una tabla desde BD con campos timestamp y operacion para el fichero dado
    3. Convertir esta tabla en la tabla hash
  3. Devolver la tabla hash
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License