失敗したファイル転送を再開できるプログラムは、データの追加を開始する場所をどのように知ることができますか?

失敗したファイル転送を再開できるプログラムは、データの追加を開始する場所をどのように知ることができますか?

一部のファイルコピープログラムは、失敗した転送/コピーを回復する可能性rsyncがあります。curl

このような失敗にはいくつかの原因があり、場合によってはプログラムが「クリーンアップ」し、場合によってはそうでない場合があります。

これらのプログラムが再起動すると、正常に転送されたファイル/データのサイズを計算してから、ソースから次のバイトを読み取ってファイルの断片に追加し始めるようです。

たとえば、ターゲットに「到着」するファイルスライスのサイズは1378バイトなので、元のファイルの1379バイトから読み取ってスライスに追加するだけです。

私の質問は、バイトがビットで構成されており、すべてのファイルがデータをクリーンなバイトサイズのチャンクに分割するわけではないことを知っていますが、これらのプログラムがデータの追加を開始することを選択したポイントが正しいかどうかはどうすればわかりますか?

ターゲットファイルに書き込むと、プログラム、カーネル、またはファイルシステムレベルで一種のSQLデータベースに似たバッファリングまたは「トランザクション」が発生し、きれいで正しい形式のバイトのみがデフォルトのブロックデバイスに渡されますか?
それとも、プログラムで最新のバイトが不完全であると仮定して破損していると仮定して削除し、バイトを再コピーしてからそこから追加を開始しますか?

すべてのデータがバイトで表されるわけではないことがわかると、これらの推測は間違っているようです。

これらのプログラムが「再開」したら、正しい場所から始まったかどうかはどうすればわかりますか?

答え1

明確にするために、実際のメカニズムは、より良いセキュリティを提供するためにより複雑です。次のディスクへの書き込み操作を想像できます。

  • 申請書の作成バイト(1)
  • カーネル(および/またはファイルシステムIOSS)はそれをバッファリングします。
  • バッファがいっぱいになるとフラッシュファイルシステムへ:
    • ブロックが割り当てられました(2)
    • ブロックが作成されました。 (3)
    • ファイルおよびブロック情報の更新(4)

プロセスが(1)で中断されると、ディスクには何も残らず、ファイルはそのまま残り、前のブロックで切り捨てられます。 5000バイトを送信し、ディスクには4096バイトのみがあり、オフセット4096で転送を再開します。

(2)の場合、メモリ以外には何も起こりません。 (1)と同じです。 (3)の場合、データが記録されます。しかし、それを覚えている人は誰もいません。。 9000バイトを送信し、4096バイトを記録し、4096バイトを記録しました。そして道を失った、残りは失われます。転送はオフセット4096で再開される。

(4)段階にある場合は、データをディスクにコミットする必要があります。ストリームの次のバイトが失われる可能性があります。 9000バイトが送信され、8192バイトが記録され、残りは失われ、転送はオフセット8192で再開されました。

これは簡単に取る。たとえば、手順3〜4の各「論理的」書き込みは「原子的」書き込みではありませんが、チャンクをターゲットデバイス(ハードディスクなど)に適したブロックに分割する別のシーケンス(#5で指定)を生成します。 ) はデバイスのホストコントローラに送信されます。キャッシュ機構もあります。、最終的にディスクに保存されます。このサブシーケンスは常にシステムで完全に制御できるわけではないため、データをハードディスクに送信することは、そのデータが実際に書き込まれ、再読み込みできることを保証しません。

複数のファイルシステムの実装日記を書く、最も脆弱な点(4)実際に脆弱なメタデータを作成すると推測できるように取引(5)段階で何が起こっても一貫して動作します。

トランザクション中にシステムがリセットされると、最新の完全チェックポイントに戻すことができます。作成されたデータは(1)と同様に失われますが、回復するとこの問題は解決されます。いいえ情報実際に迷子になりました。

答え2

rsync注:他のファイル転送ユーティリティのソースは見ていません。

ファイルの最後にジャンプして、その場所の位置をバイト単位で取得するCプログラムを書くのは簡単です。

どちらの操作も、標準のCライブラリ関数への単一の呼び出しで実行されます。lseek()lseek(fd, 0, SEEK_END)ファイル記述子に対して開かれたファイルの長さをfdバイト単位で返します)。

lseek()ターゲットファイルに対してこれを行うと、ソースファイルに対して同様の呼び出しを実行して適切な場所に移動できます。lseek(fd, pos, SEEK_SET)次に、ソースファイルの前の部分が変更されていないと識別されたと仮定します(他のユーティリティではこれを実行できます)。他の方法で)その時点で転送を続けることができます。

ファイルは次のようになります。断片化ただし、ファイルシステムはアプリケーションがファイルを連続したバイトシーケンスとして認識することを保証します。


コメントのビットとバイトについての議論に関して:ディスクに書き込むことができるデータの最小単位はバイト。バイトには少なくとも1バイトが必要です。詰まったディスクに割り当てるデータ。ブロックサイズはファイルシステムの種類によって異なり、管理者がファイルシステムを初期化するときに使用するパラメータによって異なりますが、通常、範囲は512バイトから4KiBです。書き込みはカーネル、基本Cライブラリ、またはアプリケーション自体によってバッファリングでき、最適化のためにディスクへの実際の書き込みは適切なブロックサイズの倍数で発生する可能性があります。

ファイルに単一ビットを書き込むことは不可能であり、書き込み操作が失敗した場合、ファイルに「半分書き込まれたバイト」は残りません。

答え3

カールやrsyncなどのプログラムは非常に異なるため、基本的に2つの質問です。

カールなどのHTTPクライアントの場合は、現在のファイルサイズを確認してから、リクエストとともにContent-Rangeヘッダーを送信します。サーバーは、206(正常に)代わりにステータスコード(部分コンテンツ)を含むファイルの範囲を転送して200ダウンロードを再開するか、ヘッダーを無視して最初から始めて、HTTPクライアントがすべてを再ダウンロードする必要があります。

また、サーバーはContent-Lengthヘッダーを送信することも送信しない場合もあります。一部のダウンロードでは、パーセンテージとファイルサイズが表示されないことがわかります。これらのダウンロードでは、サーバーはクライアントに長さを知らせないため、クライアントはダウンロード量だけを知り、後続のバイト数は不明です。

Content-Range次に始まるヘッダーを使用してください。そしてダウンロードマネージャの中には、ストップポイントを使用して複数のソースからファイルを一度にダウンロードし、各ミラー自体がネットワーク接続よりも遅い場合は転送速度を上げます。

一方、rsyncは増分ファイル転送のための高度なプロトコルです。サーバーとクライアントのファイル部分のチェックサムを生成し、どのバイトが等しいかを検出します。その後、違いを送信します。つまり、ダウンロードを再開できるだけでなく、ファイルを再ダウンロードする必要なく、非常に大きなファイルの途中で数バイトを変更すれば変更されたバイトもダウンロードできるという意味です。

転送を再開するための別のプロトコルはBitTorrentです。.torrentこのプロトコルにはファイル内のブロックのチェックサムのリストが含まれており、ブロックを他のソースから順番に関係なく並列にダウンロードして確認できます。

rsync と bittorent はディスク上の一部のデータを確認しますが、HTTP ダウンロードを再開すると確認しません。したがって、一部のデータが破損していると思われる場合は、最終ファイルのチェックサムを使用して整合性を確認する必要があります。ただし、単にダウンロードを中断したり、ネットワーク接続が失われたりすると、通常、一部のファイルは破損しませんが、転送中に停電が発生する可能性があります。

答え4

転送に使用されるプロトコルによって異なります。ただし、カールはファイルに現れる順番にデータを順次転送するhttpを使用します。したがって、部分的に完了した転送のファイルサイズに基づいてカールを再開できます。実際には、長さNのファイルを生成し、ファイルを部分的に完了したダウンロードとして処理するように要求して、最初のNバイトをスキップするように欺くことができます(その後、最初のNバイトを削除します)。

関連情報