Para Windows, tr_sys_path_rename
podría usar la bandera MOVEFILE_COPY_ALLOWED
lugar de su propio bucle integrado de "lectura y copia" de util.c:tr_moveFile
Entonces, la versión de Linux podría usar el copy_file_range
más moderno en lugar de recorrer cada uno.
tal vez algo como esto:
size_t tr_sys_file_copy(tr_sys_file_t infile, tr_sys_file_t outfile, size_t len, tr_error** error )
{
TR_ASSERT(outfile != NULL);
TR_ASSERT(infile != NULL);
bool ret = false;
unsigned int flags = 0;
size_t res;
res = copy_file_range(infile, NULL, outfile, NULL, &len, flags);
if (res) {
return res;
}
else {
set_system_error(error, errno);
return res;
}
}
Y tal vez un:
tr_sys_file_copy_fallback(tr_sys_file_t infile, tr_sys_file_t outfile, size_t len, tr_error** error ) {
TR_ASSERT(outfile != NULL);
TR_ASSERT(infile != NULL);
uint64_t bytesLeft = len;
size_t const buflen = 1024 * 128; /* 128 KiB buffer */
tr_sys_path_info info;
while (bytesLeft > 0)
{
uint64_t const bytesThisPass = MIN(bytesLeft, buflen);
uint64_t numRead;
uint64_t bytesWritten;
if (!tr_sys_file_read(infile, buf, bytesThisPass, &numRead, error))
{
break;
}
if (!tr_sys_file_write(outfile, buf, numRead, &bytesWritten, error))
{
break;
}
TR_ASSERT(numRead == bytesWritten);
TR_ASSERT(bytesWritten <= bytesLeft);
bytesLeft -= bytesWritten;
}
return bytesLeft;
}
Entonces, la versión de Linux podría usar el copy_file_range más moderno en lugar de recorrer cada uno.
Esto no se puede hacer solo con una llamada (o en un bucle simple):
If file_in is a sparse file, then copy_file_range() may expand any
holes existing in the requested range. Users may benefit from calling
copy_file_range() in a loop, and using the lseek(2) SEEK_DATA and
SEEK_HOLE operations to find the locations of data segments.
(hombre copy_file_range)
Idealmente, deberíamos asegurarnos de que los bloqueos sean adecuados y usar sendfile () en un hilo separado.
Es prácticamente lo mismo que el código actual de "mover archivo" cuando
rename
falla. Eso tampoco mantiene secciones dispersas, así que no
considérelo un problema a la hora de sustituirlo.
El domingo, 14 de julio de 2019 a las 10:41 p.m., andreygursky [email protected] escribió:
>
Entonces, la versión de Linux podría usar el copy_file_range más moderno en lugar de recorrer cada uno.
Esto no se puede hacer solo con una llamada (o en un bucle simple):
If file_in is a sparse file, then copy_file_range() may expand any holes existing in the requested range. Users may benefit from calling copy_file_range() in a loop, and using the lseek(2) SEEK_DATA and SEEK_HOLE operations to find the locations of data segments.
(hombre copy_file_range)
Idealmente, deberíamos asegurarnos de que los bloqueos sean adecuados y usar sendfile () en un hilo separado.
-
Estás recibiendo esto porque eres el autor del hilo.
Responda a este correo electrónico directamente, véalo en GitHub o silencia el hilo.
El "archivo de movimiento" actual vinculado como referencia
La función actual:
https://github.com/transmission/transmission/blob/master/libtransmission/utils.c#L1682
https://github.com/transmission/transmission/blob/master/libtransmission/utils.c#L1744
Eso tampoco mantiene secciones dispersas, así que no
considérelo un problema a la hora de sustituirlo.
Y falta preasignación para archivos normales.
Sí. Eso también. El mal comportamiento actual de "mover archivo" es suficiente para causar cargas absurdas en algunas configuraciones. Si es posible, parece que la solución alternativa en glibc copy_file_range también es una mejor implementación.
He jugado con esto. Es difícil hacerlo bien en una forma multiplataforma: no parece haber ninguna interfaz POSIX para una copia en el kernel. Pero creo que vale la pena usar una carcasa especial para cada sistema operativo porque a medida que los sistemas de archivos se vuelven más eficientes en las copias, queremos acceder a esas funciones automáticamente.
Tengo una implementación básica en funcionamiento en MacOSX y FreeBSD, pero necesito configurar algunos sistemas más para probarlo.
Creo que este trabajo es ortogonal para hacer que el archivo se mueva de forma asincrónica. Uno no debe interponerse en el camino del otro. Para los proyectos de voluntariado, la pérdida de alcance es enemiga de la productividad.
Los cambios están aquí: https://github.com/transmission/transmission/compare/master...RobCrowston : kernelcopy-wip
En resumen, creo una nueva abstracción llamada tr_sys_path_copy (). (Fui con una copia en lugar de un movimiento porque cuando hacemos de esto una operación asincrónica, puede ser necesario mantener el archivo original durante un período de tiempo indeterminado después de que se completa la copia para cerrar los identificadores de archivo en otros subprocesos).
Hasta ahora, he compilado y ejecutado la nueva prueba (transmisión-prueba-copia) en MacOS 10.15.1, Windows Server 2016, Linux 5.0 (Ubuntu 19.05), Linux 5.3 (Arch 2019-12-03), FreeBSD 12.1 (usa respaldo del espacio de usuario) y FreeBSD 13. En cada caso verifiqué con un depurador que estamos haciendo las llamadas al sistema apropiadas. Desafortunadamente, no pude obtener el código para construir en OpenBSD 6.5, NetBSD 8.1 o Solaris 10 debido a algunos problemas de libevent no relacionados, pero no estoy seguro de que estas sean plataformas compatibles con libtransmission. En cualquier caso, este cambio no debería afectar a esas plataformas.
Todavía por hacer:
Comentarios bienvenidos.
+1 para hacer que los movimientos de datos sean asincrónicos. Mover grandes torrents entre sistemas de archivos bloquea toda la aplicación .
Comentario más útil
+1 para hacer que los movimientos de datos sean asincrónicos. Mover grandes torrents entre sistemas de archivos bloquea toda la aplicación .