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§
- Frame
Header - Frame
Iter input全体を frame の sequence として parse、各 frame を yield する iterator。
Enums§
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-codecv0.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_totalbyte を下回っていれば、padding frame を追記してmin_totalbyte を超えさせる。最終dst.len()はmin_total + ε(ε は padding header 12 byte 分) を保証。- read_
frame inputの先頭から 1 フレーム読み出し、(header, payload, remainder)を返す。- write_
frame - 1 フレーム分を直列化: header + payload を
dstに追記。