キャッシュファイル

考慮する点。

@ ダウンロードで

  • キャッシュはできるだけ先頭ブロックからDLするが多重ダウンロードなどの影響で必ず順番にDLされるとは限らない
  • 随時追加書き込み可能で、固定長のヘッダ部を更新できなきゃだめ
  • できるだけ途中でソートしない
  • バッファリングできると吉(64KB単位で書き込むのはHDDに害あり)

@ アップロードで

  • キャッシュはきちんとブロックNoでソートされており、ヘッダサイズ+ブロックナンバー×ブロックサイズで取り出したいブロックに高速アクセスできるのが望ましい

ダウンロードする優先順位などうまく管理できるなら、mmapしたいところ。

@ フォーマット

基本的にalign(4)。1ビットで表せるメンバに4バイト使うこともためらわない。

  • キャッシュヘッダ (全体として固定長)
    • ヘッダ部バイト長
    • バージョン、タイプ
    • 完全キャッシュかどうか(アップロードファイルもこれ)
    • ファイル全体ハッシュ値(MD5)
    • データサイズ
    • データ名(ファイル名)有効バイト長(↓がどこまで有効か)
    • データ名(ファイル名) :(固定長とする:utf8で1024bytesくらい?)
  • ビットマップ


/*
* キャッシュビットマップ
*
* キャッシュは先頭から128MB単位でDLする
* 先頭128MBがDL完了すると次の128MBをDLすることができる
* countは、128MB単位のブロック保持率を表す(0- 0xffffffff)
* mapの各ビットは、64KB単位のブロック保有箇所を表す
* countが1進むたびにキャッシュファイルは2048ブロック内でソートされる
* count * 128MB より前のブロックはソート済みなため
* 安心して高速なランダムアクセスを行うことができる
*/
struct CacheBitmap
{
align(1):
uint count; // 128MB単位でのカウンタ
uint map[64];// 65536bytes * 32 * 64 => 134,217,728bytes (0-2048block)
}

ものすごい巨大データまで考えているが、実際には2GBまでしか使わない(Winnyがそうなので)

# 境界があると、多重ダウンロードなどでめんどくさくなりそうなので考えを変えるかも。

  • データブロック

struct CacheBlock
{
align(1):
uint blockNo; // ブロックNo 0-
ubyte[16] hash; // ブロックのMD5ハッシュ値
ubyte[0x10000] data; // ブロックデータ
}