A algunos programas de copia de archivos les gusta rsync
y curl
tienen la capacidad de reanudar transferencias / copias fallidas.
Teniendo en cuenta que puede haber muchas causas de estas fallas, en algunos casos el programa puede hacer una "limpieza" y otros no.
Cuando estos programas se reanudan, parecen simplemente calcular el tamaño del archivo / datos que se transfirieron con éxito y simplemente comienzan a leer el siguiente byte de la fuente y se agregan al fragmento de archivo.
por ejemplo, el tamaño del fragmento de archivo que "llegó" al destino es de 1378 bytes, por lo que comienzan a leer desde el byte 1379 en el original y se agregan al fragmento.
Mi pregunta es, sabiendo que los bytes están formados por bits y no todos los archivos tienen sus datos segmentados en fragmentos limpios de bytes, ¿cómo saben estos programas que el punto que han elegido para comenzar a agregar datos es correcto?
Al escribir el archivo de destino, ¿se produce algún tipo de almacenamiento intermedio o "transacciones" similares a las bases de datos SQL, ya sea a nivel del programa, del núcleo o del sistema de archivos para garantizar que solo los bytes limpios y bien formados lleguen al dispositivo de bloque subyacente?
¿O los programas suponen que el último byte estaría potencialmente incompleto, por lo que lo eliminan suponiendo que es incorrecto, vuelven a copiar el byte y comienzan a agregar desde allí?
sabiendo que no todos los datos se representan como bytes, estas suposiciones parecen incorrectas.
Cuando estos programas "se reanudan", ¿cómo saben que están comenzando en el lugar correcto?
head -c 20480 /dev/zero | strace -e write tee foo >/dev/null
y luego el sistema operativo los almacenará en el búfer y los enviará al disco en fragmentos aún más grandes.fwrite()
?Respuestas:
En aras de la claridad, la mecánica real es más complicada para proporcionar una seguridad aún mejor, puede imaginar la operación de escritura en disco de esta manera:
Si el proceso se interrumpe en (1), no obtiene nada en el disco, el archivo está intacto y truncado en el bloque anterior. Envió 5000 bytes, solo 4096 están en el disco, reinicia la transferencia en el desplazamiento 4096.
Si en (2), no sucede nada excepto en la memoria. Igual que (1). Si en (3), los datos se escriben pero nadie los recuerda . Enviaste 9000 bytes, 4096 se escribieron, 4096 se escribieron y se perdieron , el resto simplemente se perdió. La transferencia se reanuda en el desplazamiento 4096.
Si está en (4), los datos ahora deberían haberse confirmado en el disco. Los siguientes bytes en la secuencia pueden perderse. Envió 9000 bytes, se escribieron 8192, el resto se pierde, la transferencia se reanuda en el desplazamiento 8192.
Esta es una toma simplificada . Por ejemplo, cada escritura "lógica" en las etapas 3-4 no es "atómica", sino que da lugar a otra secuencia (numeremos # 5) por la cual el bloque, subdividido en subbloques adecuados para el dispositivo de destino (por ejemplo, disco duro ) se envía al controlador host del dispositivo, que también tiene un mecanismo de almacenamiento en caché , y finalmente se almacena en la bandeja magnética. Esta subsecuencia no siempre está completamente bajo el control del sistema, por lo que el envío de datos al disco duro no garantiza que se haya escrito realmente y que se pueda volver a leer.
Varios sistemas de archivos implementan el registro en diario , para asegurarse de que el punto más vulnerable, (4), no sea realmente vulnerable, al escribir metadatos en, usted lo adivinó, transacciones que funcionarán de manera consistente pase lo que pase en la etapa (5).
Si el sistema se reinicia en medio de una transacción, puede reanudar su camino al punto de control intacto más cercano. Los datos escritos aún se pierden, igual que en el caso (1), pero la reanudación se encargará de eso. Ninguna información se pierde realmente.
fuente
fsync
) y el controlador del disco duro (a menudo roto, incluso en unidades supuestamente "empresariales"). Sinfsync
muchas operaciones de archivo, que están ordenadas de forma intuitiva y atómica no están garantizadas por POSIX: los archivos abiertosO_APPEND
pueden comportarse de manera diferente a los que no tienen etc. En la práctica, las claves más importantes para la coherencia de archivos son el sistema VFS del núcleo y el caché de disco. Todo lo demás es principalmente pelusa.Nota: No he visto las fuentes de
rsync
ninguna otra utilidad de transferencia de archivos.Es trivial escribir un programa en C que salte al final de un archivo y obtenga la posición de esa ubicación en bytes.
Ambas operaciones se realizan con una sola llamada a la función de biblioteca C estándar
lseek()
(lseek(fd, 0, SEEK_END)
devuelve la longitud del archivo abierto para el descriptor de archivofd
, medido en bytes).Una vez hecho esto para el archivo de destino, una llamada similar a
lseek()
puede realizarse en el archivo de origen para saltar a la posición adecuada:lseek(fd, pos, SEEK_SET)
. La transferencia puede continuar en ese punto, suponiendo que la parte anterior del archivo fuente se haya identificado como sin cambios (diferentes utilidades pueden hacer esto de diferentes maneras).Un archivo puede estar fragmentado en el disco, pero el sistema de archivos se asegurará de que una aplicación perciba el archivo como una secuencia secuencial de bytes.
Con respecto a la discusión en los comentarios sobre bits y bytes: la unidad de datos más pequeña que se puede escribir en el disco es un byte . Un solo byte requiere que se asigne al menos un bloque de datos en el disco. El tamaño de un bloque depende del tipo de sistema de archivos y posiblemente también de los parámetros utilizados por el administrador al inicializar el sistema de archivos, pero generalmente está entre 512 bytes y 4 KiB. Las operaciones de escritura pueden ser almacenadas por el kernel, la biblioteca C subyacente o por la aplicación misma y la escritura real en el disco puede ocurrir en múltiplos del tamaño de bloque apropiado como una optimización.
No es posible escribir bits individuales en un archivo y si falla una operación de escritura, no dejará "bytes medio escritos" en el archivo.
fuente
Estas son básicamente dos preguntas, porque los programas como curl y rsync son muy diferentes.
Para clientes HTTP como curl, verifican el tamaño del archivo actual y luego envían un
Content-Range
encabezado con su solicitud. El servidor reanuda el envío del rango del archivo usando el código de estado206
(contenido parcial) en lugar de200
(éxito) y la descarga se reanuda o ignora el encabezado y comienza desde el principio y el cliente HTTP no tiene otra opción que volver a descargar todo otra vez.Además, el servidor puede o no enviar un
Content-Length
encabezado. Es posible que haya notado que algunas descargas no muestran un porcentaje y un tamaño de archivo. Estas son descargas en las que el servidor no le dice al cliente la longitud, por lo que el cliente solo sabe la cantidad que descargó pero no cuántos bytes seguirán.Algunos gestores de descargas utilizan un
Content-Range
encabezado con posición de inicio y detención para descargar un archivo de diferentes fuentes a la vez, lo que acelera la transferencia si cada espejo es más lento que su conexión de red.rsync, por otro lado, es un protocolo avanzado para transferencias de archivos incrementales. Genera sumas de comprobación de partes del archivo en el lado del servidor y del cliente para detectar qué bytes son iguales. Entonces solo envía las diferencias. Esto significa que no solo puede reanudar una descarga, sino que incluso puede descargar los bytes modificados si cambia algunos bytes en medio de un archivo muy grande sin volver a descargar el archivo.
Otro protocolo hecho para reanudar las transferencias es bittorrent, donde el
.torrent
archivo contiene una lista de sumas de verificación para bloques del archivo, por lo que los bloques se pueden descargar y verificar en orden arbitrario y en paralelo desde diferentes fuentes.Tenga en cuenta que rsync y bittorent verificarán los datos parciales en su disco, mientras que reanudar una descarga HTTP no lo hará. Entonces, si sospecha que los datos parciales están dañados, debe verificar la integridad de lo contrario, es decir, usar una suma de verificación del archivo final. Pero solo interrumpir la descarga o perder la conexión de red generalmente no corrompe el archivo parcial, mientras que puede producirse un corte de energía durante la transferencia.
fuente
TL; DR: No pueden, a menos que el protocolo que utilizan lo permita.
Los programas no siempre pueden reanudarse desde una ubicación arbitraria: por ejemplo, las solicitudes HTTP solo se pueden reiniciar si el servidor lo admite y el cliente lo implementa: esto no es universal, así que revise la documentación de su programa. Si el servidor lo admite, los programas pueden reanudar la transferencia simplemente preguntando como parte del protocolo. Por lo general, verá transferencias parciales en su directorio de descargas (comúnmente están marcadas con una extensión ".partial" o algo similar).
Si la descarga de un archivo se detiene o se detiene, el cliente puede escribir el archivo en el disco y tener una idea clara de dónde reanudar. Si, por otro lado, el cliente falla o hay un error al escribir en el archivo, el cliente debe asumir que el archivo está dañado y comenzar de nuevo. BitTorrent mitiga esto un poco al dividir los archivos en "fragmentos" y realizar un seguimiento de cuáles se han descargado con éxito; Lo máximo que tendrá que rehacer son algunos trozos. Rsync hace algo similar.
¿Cómo saben los programas que el contenido es el mismo? Un método es verificar que algún identificador sea el mismo entre el cliente y el servidor. Algunos ejemplos de esto serían la marca de tiempo y el tamaño, pero existen mecanismos que pueden ser específicos de un protocolo. Si los identificadores coinciden, el cliente puede suponer que la reanudación funcionará.
Si desea una verificación más definitiva, HTTP y sus amigos no deberían ser su primera opción. Deberá utilizar un protocolo que también tenga una suma de comprobación o hash para todo el archivo y cada fragmento transferido para que pueda comparar la suma de comprobación de la descarga con la suma de comprobación de la computadora del servidor: todo lo que no coincida se volverá a descargar. Nuevamente, BitTorrent es un ejemplo de este tipo de protocolo; Opcionalmente, rsync también puede hacer esto.
fuente
Depende del protocolo utilizado para transferir. Pero curl usa http y transfiere datos secuencialmente en el orden en que aparecen en el archivo. Por lo tanto, curl puede reanudarse en función del tamaño del archivo de una transferencia parcialmente completada. De hecho, puede engañarlo para omitir los primeros N bytes creando un archivo de longitud N (de cualquier cosa) y pidiéndole que trate ese archivo como una descarga parcialmente completada (y luego descarte los primeros N bytes).
fuente