Transmission: [Verbesserung] Seien Sie beim Verschieben von Dateien klüger

Erstellt am 14. Juli 2019  ·  8Kommentare  ·  Quelle: transmission/transmission

Für Windows könnte tr_sys_path_rename das Flag MOVEFILE_COPY_ALLOWED anstelle der eigenen eingebauten "read&copy"-Schleife von util.c:tr_moveFile

Dann könnte die Linux-Version das modernere copy_file_range anstatt jede Schleife zu durchlaufen.

vielleicht sowas:

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;
        }
}

Und vielleicht ein:

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;
}
core enhancement pr welcome

Hilfreichster Kommentar

+1 für asynchrone Datenverschiebungen. Das Verschieben großer Torrents zwischen Dateisystemen sperrt die gesamte Anwendung .

Alle 8 Kommentare

Dann könnte die Linux-Version den moderneren copy_file_range verwenden, anstatt jede Schleife zu durchlaufen.

Dies ist nicht mit nur einem Aufruf (oder in einer einfachen Schleife) möglich:

       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)

Idealerweise sollten wir die Sperren ordnungsgemäß sicherstellen und sendfile() in einem separaten Thread verwenden.

Das ist so ziemlich das gleiche wie der aktuelle Code für "Datei verschieben", wenn
rename schlägt fehl. Das hält auch keine spärlichen Abschnitte, also habe ich es nicht getan
Betrachten Sie das als Problem beim Austausch.

Am So, 14. Juli 2019 um 22:41 Uhr schrieb andreygursky [email protected] :
>

Dann könnte die Linux-Version den moderneren copy_file_range verwenden, anstatt jede Schleife zu durchlaufen.

Dies ist nicht mit nur einem Aufruf (oder in einer einfachen Schleife) möglich:

   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)

Idealerweise sollten wir die Sperren ordnungsgemäß sicherstellen und sendfile() in einem separaten Thread verwenden.


Sie erhalten dies, weil Sie den Thread verfasst haben.
Antworten Sie direkt auf diese E-Mail, zeigen Sie sie auf GitHub an oder schalten Sie den Thread stumm.

Das hält auch keine spärlichen Abschnitte, also habe ich es nicht getan
Betrachten Sie das als Problem beim Austausch.

Und es fehlt die Vorabzuweisung für normale Dateien.

Ja. Das auch. Das derzeitige schlechte Verhalten von "Datei verschieben" reicht aus, um in einigen Setups absurde Lasten zu verursachen. Wenn möglich, scheint die Fallback-Lösung in glibc copy_file_range auch eine bessere Implementierung zu sein.

Ich habe damit gespielt. Es ist schwierig, plattformübergreifend richtig zu sein: Es scheint keine POSIX-Schnittstelle für eine In-Kernel-Kopie zu geben. Aber ich denke, es lohnt sich, für jedes Betriebssystem eine spezielle Schreibweise zu verwenden, da wir, wenn Dateisysteme beim Kopieren effizienter werden, automatisch auf diese Funktionen zugreifen möchten.

Ich habe eine grundlegende Implementierung unter MacOSX und FreeBSD, aber ich muss noch ein paar weitere Systeme einrichten, um sie zu testen.

Ich denke, diese Arbeit ist orthogonal dazu, dass die Datei asynchron verschoben wird. Das eine sollte dem anderen nicht im Weg stehen. Bei Freiwilligenprojekten ist Scope Creep der Feind der Produktivität.

Änderungen sind hier: https://github.com/transmission/transmission/compare/master...RobCrowston :kernelcopy-wip

Kurz gesagt erstelle ich eine neue Abstraktion namens tr_sys_path_copy(). (Ich habe eine Kopie anstelle einer Verschiebung gewählt, da es bei einem asynchronen Vorgang möglicherweise erforderlich ist, die Originaldatei nach Abschluss der Kopie für einen unbestimmten Zeitraum beizubehalten, um Dateihandles in anderen Threads zu schließen.)

Heute habe ich den neuen Test (Transmission-Test-Copy) auf MacOS 10.15.1, Windows Server 2016, Linux 5.0 (Ubuntu 19.05), Linux 5.3 (Arch 2019-12-03), FreeBSD 12.1 kompiliert und ausgeführt (verwendet Userspace-Fallback) und FreeBSD 13. In jedem Fall habe ich mit einem Debugger überprüft, ob wir die entsprechenden Systemaufrufe durchführen. Leider war es mir nicht möglich, den Code zum Erstellen auf OpenBSD 6.5, NetBSD 8.1 oder Solaris 10 aufgrund einiger nicht verwandter libevent-Probleme zu erhalten, aber ich bin mir nicht sicher, ob diese Plattformen für libtransmission mehr unterstützt werden. Auf jeden Fall sollte sich diese Änderung nicht auf diese Plattformen auswirken.

Noch zu tun:

  • Testen Sie auf einem älteren Windows-Kernel. Dazu muss eine VM-Entwicklungsumgebung konfiguriert werden.
  • Testen Sie die volumenübergreifende Kopie (da uns das wichtig ist). Ich bin mir jedoch nicht sicher, wie man das als automatisierten Test macht.
  • Testen Sie die Datei tr_sys_path_copy() für eine einigermaßen große Datei (> 100 GB). Kann wahrscheinlich nicht als automatisierter Test durchgeführt werden.
  • Testen Sie in situ, anstatt nur tr_sys_path_copy() isoliert zu testen.
  • Ersetzen Sie einen meiner Bit-Torrent-Server für eine Weile durch diesen Code, und sehen Sie, wie er sich in der realen Welt verhält.

Rückmeldung erwünscht.

+1 für asynchrone Datenverschiebungen. Das Verschieben großer Torrents zwischen Dateisystemen sperrt die gesamte Anwendung .

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen