# 機能設計書 115-Mmap

## 概要

本ドキュメントは、Julia標準ライブラリ `Mmap` モジュールの機能設計を記述する。メモリマップドI/O（Mmap.mmap）を提供し、ファイルの内容をメモリ上の配列として直接アクセスする機能を実装するモジュールである。

### 本機能の処理概要

**業務上の目的・背景**：大規模なデータファイルを扱う場合、ファイル全体をメモリに読み込むのは非効率的であり、メモリ不足を引き起こす可能性がある。メモリマップドI/O（mmap）は、OSの仮想メモリ機構を利用して、ファイルの内容をプロセスのアドレス空間に直接マッピングし、必要なページのみをオンデマンドでメモリにロードする。これにより、物理メモリ以上のサイズのファイルも効率的に処理できる。Mmapモジュールは、このOS機能をJuliaの配列インタフェースとシームレスに統合する。

**機能の利用シーン**：大規模数値データファイルの読み書き、SharedArraysの内部実装におけるプロセス間メモリ共有、バイナリファイルの効率的なランダムアクセス、データベースファイルのマッピング。

**主要な処理内容**：
1. ファイルをメモリマップして配列としてアクセス（mmap関数）
2. 匿名メモリマッピング（Anonymous構造体による共有メモリセグメント）
3. メモリマップ配列の同期（sync!関数によるディスクへの書き戻し）
4. マッピングの解放（munmap/finalizerによるアンマッピング）

**関連システム・外部連携**：OSのmmap/munmapシステムコール（POSIX）、CreateFileMapping/MapViewOfFile（Windows）、SharedArraysモジュール。

**権限による制御**：ファイルのアクセス権限に依存する。読み取り専用ファイルは読み取り専用マッピングとなる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | REPL | 参照画面 | mmap()の対話的実行 |

## 機能種別

I/O操作 / メモリ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| io | IO | Yes (ファイルmmap時) | マッピング対象のIOストリーム | 有効なファイルディスクリプタであること |
| type | Type | No | 配列の要素型。デフォルトはVector{UInt8} | isbitstype(T)がtrueであること |
| dims | Tuple | No | 配列の次元。デフォルトはファイルサイズから算出 | 正の整数のタプル |
| offset | Integer | No | ファイル先頭からのオフセット（バイト）。デフォルト=0 | 非負整数、mmapのページ境界制約に従う |
| grow | Bool | No | ファイルが小さい場合に拡張するか。デフォルト=true | - |
| shared | Bool | No | 他プロセスとマッピングを共有するか。デフォルト=true | - |

### 入力データソース

- ファイルシステム上のファイル（IOStream経由）
- 匿名メモリセグメント（Anonymous構造体経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| mapped_array | Array{T,N} | メモリマップされた配列。通常の配列と同様にアクセス可能 |

### 出力先

- 戻り値としてArray{T,N}を返却
- ファイルへの書き戻し（shared=true時、配列への書き込みがファイルに反映）

## 処理フロー

### 処理シーケンス

```
1. mmap(io, Array{T,N}, dims, offset) 呼び出し
   └─ ファイルの情報取得（fd, サイズ）
   └─ 必要に応じてファイルサイズを拡張（grow=true時）
   └─ OS mmapシステムコール実行
   └─ Juliaの配列オブジェクトとしてラップ
   └─ finalizerを登録（GC時にmunmap）
2. 配列アクセス
   └─ 通常の配列インデクシングでアクセス
   └─ OSがページフォールト時にファイルからロード
3. sync!(array) でディスクに同期
   └─ msyncシステムコール実行
4. GC時またはfinalize時
   └─ munmapでマッピングを解放
```

### フローチャート

```mermaid
flowchart TD
    A["mmap(io, type, dims, offset)"] --> B["ファイル情報取得"]
    B --> C{"ファイルサイズ十分?"}
    C -->|No, grow=true| D["ファイルサイズ拡張"]
    C -->|Yes| E["mmap システムコール"]
    D --> E
    E --> F["Julia Array としてラップ"]
    F --> G["finalizer登録"]
    G --> H["配列を返却"]
    H --> I["配列アクセス（読み書き）"]
    I --> J{"sync!呼び出し?"}
    J -->|Yes| K["msync でディスク同期"]
    J -->|No| L["GC/finalizeで munmap"]
    K --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-115-01 | isbitstype制約 | メモリマップする要素型はisbitstype(T)がtrueである必要がある | mmap呼び出し時 |
| BR-115-02 | ページ境界アライメント | オフセットはOSのページサイズの倍数である必要がある（内部で自動調整） | mmap呼び出し時 |
| BR-115-03 | 共有マッピング | shared=trueの場合、複数プロセスが同じファイルを共有可能 | SharedArrays等での使用時 |
| BR-115-04 | ファイル拡張 | grow=trueの場合、マッピングに必要なサイズまでファイルを自動拡張 | ファイルサイズ不足時 |

### 計算ロジック

- 必要なファイルサイズ = offset + sizeof(T) * prod(dims)
- ページ境界オフセット = offset - (offset % page_size)

## データベース操作仕様

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ArgumentError | 型制約違反 | isbitstype(T)がfalseの場合 | isbitstype(T)がtrueの型を使用 |
| SystemError | OS エラー | mmapシステムコール失敗（メモリ不足等） | マッピングサイズを縮小、またはシステムリソースを確認 |
| - | ファイルアクセスエラー | 読み取り権限がないファイルをマッピング | ファイルの権限を確認 |

### リトライ仕様

リトライ不要。

## トランザクション仕様

該当なし。ただし、shared=trueのマッピングでは複数プロセスからの同時書き込みに対する排他制御はユーザーの責任。

## パフォーマンス要件

- mmapはOSの仮想メモリ機構を使用するため、物理メモリ以上のファイルも扱える
- ランダムアクセスのパフォーマンスはOSのページキャッシュに依存
- シーケンシャルアクセスではread()と同等以上のパフォーマンス

## セキュリティ考慮事項

- メモリマップされた配列はプロセスのアドレス空間にマッピングされるため、他プロセスからのアクセスに注意
- shared=trueのマッピングは他プロセスと共有されるため、機密データの取り扱いに注意

## 備考

- Mmap.Anonymousは共有メモリセグメントの作成に使用される（SharedArraysの内部実装）
- Windows環境ではCreateFileMapping/MapViewOfFileを使用
- finalizerによりGC時に自動的にmunmapが呼ばれる

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

Anonymous構造体を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Mmap.jl | `stdlib/Mmap/src/Mmap.jl` | Anonymous構造体の定義 -- 名前、読み取り専用フラグ、作成フラグを保持 |

**読解のコツ**: Mmap.jlは単一ファイルにまとまっている。POSIX mmapとWindows CreateFileMappingの両方を`@static if`で分岐している。

#### Step 2: エントリーポイントを理解する

mmap()関数がメインのエントリーポイント。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Mmap.jl | `stdlib/Mmap/src/Mmap.jl` | mmap関数のメインディスパッチ -- IOストリーム、型、次元、オフセットを受け取り配列を返す |

**主要処理フロー**:
1. ファイルディスクリプタの取得（fd(io)）
2. ファイルサイズの確認と必要に応じた拡張
3. ccall(:jl_mmap, ...)でOSのmmapを呼び出し
4. unsafe_wrap(Array, ptr, dims)でJulia配列としてラップ
5. finalizerの登録

#### Step 3: sync!とmunmapを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Mmap.jl | `stdlib/Mmap/src/Mmap.jl` | sync!関数 -- msyncシステムコール呼び出しによるディスク同期 |

### プログラム呼び出し階層図

```
Mmap.mmap(io, Array{T,N}, dims, offset)
    |
    +-- fd(io)                          # ファイルディスクリプタ取得
    +-- filesize(io)                    # ファイルサイズ確認
    +-- truncate(io, required_size)     # 必要に応じてファイル拡張
    +-- ccall(:jl_mmap, ...)            # OS mmapシステムコール
    +-- unsafe_wrap(Array, ptr, dims)   # Julia配列ラップ
    +-- finalizer(munmap_cleanup, arr)  # GC時のクリーンアップ登録

Mmap.sync!(array)
    +-- ccall(:msync, ...)              # ディスク同期
```

### データフロー図

```
[入力]               [処理]                          [出力]

ファイル(IO)   ───▶  mmap()                    ───▶  Array{T,N}
                     OS仮想メモリマッピング            (メモリマップ配列)

配列書き込み   ───▶  sync!()                   ───▶  ファイル更新
                     msyncシステムコール               (ディスク反映)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Mmap.jl | `stdlib/Mmap/src/Mmap.jl` | ソース | メインモジュール。mmap, sync!, Anonymous等の全実装 |
| Project.toml | `stdlib/Mmap/Project.toml` | 設定 | パッケージ依存関係定義 |
| runtests.jl | `stdlib/Mmap/test/runtests.jl` | テスト | ユニットテスト |
