Windowsの場合、 tr_sys_path_rename
フラグを使用することができますMOVEFILE_COPY_ALLOWED
それは自分の組み込みのだから、 "読み取り&コピー"ループではなく、 util.c:tr_moveFile
次に、Linuxバージョンは、それぞれをループする代わりに、より新しいcopy_file_range
使用できます。
おそらくこのようなもの:
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;
}
}
そして多分:
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;
}
次に、Linuxバージョンは、それぞれをループする代わりに、より新しいcopy_file_rangeを使用できます。
これは、1回の呼び出しだけで(または単純なループで)実行することはできません。
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)
理想的には、適切にロックし、別のスレッドでsendfile()を使用する必要があります。
これは、現在の「ファイルの移動」コードとほとんど同じです。
rename
失敗します。 それもまばらなセクションを保持しないので、私はしませんでした
それを交換するときに問題を考慮してください。
22:41の日、2019年7月14日にはandreygursky [email protected]書きました:
>>
次に、Linuxバージョンは、それぞれをループする代わりに、より新しいcopy_file_rangeを使用できます。
これは、1回の呼び出しだけで(または単純なループで)実行することはできません。
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)
理想的には、適切にロックし、別のスレッドでsendfile()を使用する必要があります。
—
スレッドを作成したため、これを受け取っています。
このメールに直接返信するか、GitHubで表示するか、スレッドをミュートしてください。
それもまばらなセクションを保持しないので、私はしませんでした
それを交換するときに問題を考慮してください。
また、通常のファイルの事前割り当てがありません。
うん。 それも。 「ファイルの移動」の現在の悪い動作は、いくつかのセットアップでばかげた負荷を引き起こすのに十分です。 可能であれば、glibccopy_file_rangeのフォールバックソリューションもより良い実装であるように思われます。
私はこれで遊んだことがあります。 クロスプラットフォームの方法で正しく理解するのは難しいです。カーネル内コピー用のPOSIXインターフェースがないようです。 しかし、ファイルシステムがコピーでより効率的になるにつれて、それらの機能に自動的にアクセスしたいので、オペレーティングシステムごとに特別なケーシングをする価値があると思います。
私はMacOSXとFreeBSDで基本的な実装を実行していますが、それをテストするためにさらにいくつかのシステムをセットアップする必要があります。
この作業は、ファイルを非同期に移動させることと直交していると思います。 一方が他方の邪魔をしてはいけません。 ボランティアプロジェクトの場合、スコープクリープは生産性の敵です。
変更点は次のとおりです: https ://github.com/transmission/transmission/compare/master ... RobCrowston:kernelcopy-wip
簡単に言うと、tr_sys_path_copy()という新しい抽象化を作成します。 (これを非同期操作にすると、他のスレッドのファイルハンドルを閉じるために、コピーが完了した後、元のファイルを一定期間保持する必要がある場合があるため、移動ではなくコピーを使用しました。)
今日まで、私はMacOS 10.15.1、Windows Server 2016、Linux 5.0(Ubuntu 19.05)、Linux 5.3(Arch 2019-12-03)、FreeBSD 12.1で新しいテスト(transmission-test-copy)をコンパイルして実行しました。 (ユーザースペースフォールバックを使用)、およびFreeBSD 13.いずれの場合も、適切なシステム呼び出しを行っていることをデバッガーで確認しました。 残念ながら、関係のないlibeventの問題が原因で、OpenBSD 6.5、NetBSD 8.1、またはSolaris 10でコードをビルドすることができませんでしたが、これらがlibtransmissionでサポートされているプラットフォームであるかどうかはわかりません。 いずれにせよ、この変更はそれらのプラットフォームに影響を与えるべきではありません。
まだやるべきこと:
フィードバックを歓迎します。
データを非同期に移動させるための+1。 ファイルシステム間で大きなトレントを移動すると、アプリケーション全体がロックされます。
最も参考になるコメント
データを非同期に移動させるための+1。 ファイルシステム間で大きなトレントを移動すると、アプリケーション全体がロックされます。