Skip to main content

Module multipart

Module multipart 

Source
Expand description

Multipart upload で使う on-the-wire フレーム形式。

§課題

AWS S3 multipart upload は各 part を独立にアップロードし、CompleteMultipartUpload で順番に concat した bytes が最終 object になる。S4 が per-part で圧縮すると、 最終 object は N 個の圧縮済 chunk の concat。GET 時に「どこからどこまでが 1 chunk か」を知るためのメタが必要だが、object metadata には全 chunk の境界を 入れる容量がない (S3 metadata 上限 2 KB、1000 parts × 8 byte = 8 KB で溢れる)。

§解決策: in-band frame header

各 part bytes の先頭に固定 24 byte のフレームヘッダを置き、続く compressed_size バイトが圧縮済 payload。GET は object 全体を読み込み、先頭から frame を順に parse し各 chunk を解凍 → 連結する。

┌──────────────────────────── 24 bytes ────────────────────────────┐
│ magic    │ orig_size │ compressed_size │ crc32c │   ── then payload ──
│ "S4F1"   │  u64 LE   │     u64 LE      │ u32 LE │ [compressed_size bytes]
└──────────┴───────────┴─────────────────┴────────┘
  • codec は object metadata の s4-codec全 part 共通 (CreateMultipartUpload で固定)。Phase 2 で per-frame codec 化を検討可。
  • object metadata に s4-multipart=true を立てておき、GET 側はそれを見て frame parse を有効化する。

§制限事項 (Phase 1)

  • Range GET 非対応: chunk 境界と byte offset の対応を計算しないので、 client が Range を指定しても無視 (もしくは下流の Range を尊重して invalid 解凍になる) — 実装上は Range を S4 で reject する方が安全。Phase 2 で対応。
  • per-part 別 codec 非対応: 上記 frame format に codec ID を入れるか、 object metadata を per-part に拡張するかの判断は Phase 2 で。

Structs§

FrameHeader
FrameIter
input 全体を frame の sequence として parse、各 frame を yield する iterator。

Enums§

FrameError

Constants§

FRAME_HEADER_BYTES
4 (magic) + 4 (codec_id) + 8 (orig_size) + 8 (compressed_size) + 4 (crc32c) = 28
FRAME_MAGIC
Frame magic = ASCII “S4F2” (S4 Frame, version 2)。 v1 (S4F1) との違い: 4 byte の codec_id field を header に追加し、per-frame codec dispatch を可能にした。s4-codec v0.0.x は v1 を読まない (released 前 なので backward compat 不要)。
PADDING_HEADER_BYTES
PADDING_MAGIC
Padding frame magic = ASCII “S4P1” (S4 Padding, version 1)。
S3_MULTIPART_MIN_PART_BYTES
AWS S3 の non-final multipart part の最小サイズ (5 MiB)。

Functions§

pad_to_minimum
dst の現在サイズが min_total byte を下回っていれば、padding frame を追記して min_total byte を超えさせる。最終 dst.len()min_total + ε (ε は padding header 12 byte 分) を保証。
read_frame
input の先頭から 1 フレーム読み出し、(header, payload, remainder) を返す。
write_frame
1 フレーム分を直列化: header + payload を dst に追記。