Para Windows, tr_sys_path_rename
poderia usar a sinalização MOVEFILE_COPY_ALLOWED
vez de seu próprio loop "ler e copiar" embutido de util.c:tr_moveFile
Então, a versão do Linux poderia usar o mais moderno copy_file_range
vez de fazer um loop sobre cada um.
talvez algo assim:
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;
}
}
E talvez um:
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;
}
Então, a versão do Linux poderia usar o copy_file_range mais moderno em vez de fazer um loop sobre cada um.
Isso não pode ser feito apenas com uma chamada (ou em loop simples):
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.
(man copy_file_range)
Idealmente, devemos garantir os bloqueios adequados e usar sendfile () em uma thread separada.
É praticamente o mesmo que o código atual de "mover arquivo" quando
rename
falha. Isso também não mantém seções esparsas, então eu não
considere isso um problema ao substituí-lo.
No domingo, 14 de julho de 2019 às 22h41, andreygursky [email protected] escreveu:
>
Então, a versão do Linux poderia usar o copy_file_range mais moderno em vez de fazer um loop sobre cada um.
Isso não pode ser feito apenas com uma chamada (ou em loop simples):
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.
(man copy_file_range)
Idealmente, devemos garantir os bloqueios adequados e usar sendfile () em uma thread separada.
-
Você está recebendo isto porque é o autor do tópico.
Responda a este e-mail diretamente, visualize-o no GitHub ou ignore a conversa.
O "arquivo de movimentação" atual vinculado como uma referência
A função atual:
https://github.com/transmission/transmission/blob/master/libtransmission/utils.c#L1682
https://github.com/transmission/transmission/blob/master/libtransmission/utils.c#L1744
Isso também não mantém seções esparsas, então eu não
considere isso um problema ao substituí-lo.
E está faltando pré-alocação para arquivos normais.
Sim. Isso também. O atual mau comportamento de "mover arquivo" é suficiente para causar cargas absurdas em algumas configurações. Se possível, parece que a solução de fallback em glibc copy_file_range é uma implementação melhor também.
Eu joguei com isso. É difícil acertar em uma plataforma cruzada: não parece haver nenhuma interface POSIX para uma cópia dentro do kernel. Mas acho que vale a pena usar um invólucro especial para cada sistema operacional porque, à medida que os sistemas de arquivos se tornam mais eficientes nas cópias, queremos acessar esses recursos automaticamente.
Tenho uma implementação básica instalada e em execução no MacOSX e no FreeBSD, mas preciso configurar mais alguns sistemas para testá-la.
Acho que este trabalho é ortogonal para fazer o movimento do arquivo de forma assíncrona. Um não deve atrapalhar o outro. Para projetos voluntários, o aumento do escopo é inimigo da produtividade.
As mudanças estão aqui: https://github.com/transmission/transmission/compare/master...RobCrowston : kernelcopy-wip
Em resumo, crio uma nova abstração chamada tr_sys_path_copy (). (Fiz uma cópia em vez de uma mudança porque, quando tornamos esta operação assíncrona, pode ser necessário manter o arquivo original por um período indeterminado de tempo após a cópia ser concluída para fechar os identificadores de arquivo em outros threads.)
Até agora, compilei e executei o novo teste (transmissão-teste-cópia) no MacOS 10.15.1, Windows Server 2016, Linux 5.0 (Ubuntu 19.05), Linux 5.3 (Arch 03-12-2019), FreeBSD 12.1 (usa fallback de espaço de usuário) e FreeBSD 13. Em cada caso, verifiquei com um depurador se estamos fazendo as chamadas de sistema apropriadas. Infelizmente, não consegui obter o código para compilar no OpenBSD 6.5, NetBSD 8.1 ou Solaris 10 por causa de alguns problemas não relacionados do libevent, mas não tenho mais certeza de que essas plataformas sejam mais suportadas para libtransmission. Em qualquer caso, esta mudança não deve afetar essas plataformas.
Ainda por fazer:
Feedback bem-vindo.
1 para tornar as movimentações de dados assíncronas. Mover torrents grandes entre sistemas de arquivos bloqueia todo o aplicativo .
Comentários muito úteis
1 para tornar as movimentações de dados assíncronas. Mover torrents grandes entre sistemas de arquivos bloqueia todo o aplicativo .