Pour Windows, tr_sys_path_rename
pourrait utiliser le drapeau MOVEFILE_COPY_ALLOWED
plutôt que sa propre boucle "read©" intégrée à partir de util.c:tr_moveFile
Ensuite, la version Linux pourrait utiliser le copy_file_range
plus moderne au lieu de boucler sur chacun.
peut-être quelque chose comme ça :
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;
}
}
Et peut-être 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;
}
Ensuite, la version Linux pourrait utiliser le copy_file_range plus moderne au lieu de boucler sur chacun.
Cela ne peut pas se faire en un seul appel (ou en boucle 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.
(man copy_file_range)
Idéalement, nous devrions nous assurer que les verrous sont corrects et utiliser sendfile() dans un thread séparé.
C'est à peu près le même que le code "déplacer le fichier" actuel lorsque
rename
échoue. Cela ne garde pas non plus les sections clairsemées, donc je n'ai pas
considérez qu'il s'agit d'un problème lors de son remplacement.
Le dimanche 14 juillet 2019 à 22h41, andreygursky [email protected] a écrit :
>
Ensuite, la version Linux pourrait utiliser le copy_file_range plus moderne au lieu de boucler sur chacun.
Cela ne peut pas se faire en un seul appel (ou en boucle 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.
(man copy_file_range)
Idéalement, nous devrions nous assurer que les verrous sont corrects et utiliser sendfile() dans un thread séparé.
-
Vous recevez ceci parce que vous avez créé le fil.
Répondez directement à cet e-mail, affichez-le sur GitHub ou coupez le fil de discussion.
Le "déplacer le fichier" actuel lié comme référence
La fonction actuelle :
https://github.com/transmission/transmission/blob/master/libtransmission/utils.c#L1682
https://github.com/transmission/transmission/blob/master/libtransmission/utils.c#L1744
Cela ne garde pas non plus les sections clairsemées, donc je n'ai pas
considérez qu'il s'agit d'un problème lors de son remplacement.
Et il manque une préallocation pour les fichiers normaux.
Ouais. Ça aussi. Le mauvais comportement actuel de "déplacer le fichier" est suffisant pour provoquer des charges absurdes dans certaines configurations. Si possible, il semble que la solution de secours dans la glibc copy_file_range soit également une meilleure implémentation.
J'ai joué avec ça. Il est difficile d'y parvenir d'une manière multiplateforme : il ne semble pas y avoir d'interface POSIX pour une copie dans le noyau. Mais je pense qu'il vaut la peine d'avoir un boîtier spécial pour chaque système d'exploitation, car à mesure que les systèmes de fichiers deviennent plus efficaces au niveau des copies, nous souhaitons accéder automatiquement à ces fonctionnalités.
J'ai une implémentation de base opérationnelle sur MacOSX et FreeBSD, mais j'ai besoin de configurer quelques systèmes supplémentaires pour la tester.
Je pense que ce travail est orthogonal au déplacement asynchrone du fichier. L'un ne doit pas gêner l'autre. Pour les projets de volontariat, la dérive de la portée est l'ennemi de la productivité.
Les changements sont ici : https://github.com/transmission/transmission/compare/master...RobCrowston :kernelcopy-wip
En bref, je crée une nouvelle abstraction appelée tr_sys_path_copy(). (J'ai opté pour une copie au lieu d'un déplacement, car lorsque nous en faisons une opération asynchrone, il peut être nécessaire de conserver le fichier d'origine pendant une période indéterminée une fois la copie terminée pour fermer les descripteurs de fichiers dans d'autres threads.)
Jusqu'à présent, j'ai compilé et exécuté le nouveau test (transmission-test-copy) sur MacOS 10.15.1, Windows Server 2016, Linux 5.0 (Ubuntu 19.05), Linux 5.3 (Arch 2019-12-03), FreeBSD 12.1 (utilise le repli de l'espace utilisateur) et FreeBSD 13. Dans chaque cas, j'ai vérifié avec un débogueur que nous effectuons les appels système appropriés. Malheureusement, je n'ai pas pu obtenir le code pour construire sur OpenBSD 6.5, NetBSD 8.1 ou Solaris 10 en raison de problèmes de libevent non liés, mais je ne suis pas sûr que ce soient des plates-formes prises en charge pour la transmission de lib. En tout état de cause, ce changement ne devrait pas affecter ces plateformes.
Reste à faire :
Commentaires bienvenus.
+1 pour rendre les déplacements de données asynchrones. Déplacer de gros torrents entre les systèmes de fichiers verrouille l'ensemble de l'application .
Commentaire le plus utile
+1 pour rendre les déplacements de données asynchrones. Déplacer de gros torrents entre les systèmes de fichiers verrouille l'ensemble de l'application .