# 機能設計書: 56-memfiles（メモリマップトファイル）

## 1. 概要

### 1.1 業務上の目的・背景

memfilesモジュールは、メモリマップトファイル（Posixのmmap）機能を提供する。ファイルをメモリ空間に直接マッピングすることで、大容量ファイルの効率的なアクセスを実現する。また、テキストファイルの高速な行単位イテレーションも提供する。

### 1.2 機能の利用シーン

- 大容量ファイルの効率的な読み書き
- ゼロコピーファイル処理による高性能データ解析
- 複数プロセス間でのメモリ共有
- 大規模テキストファイルの高速行処理
- バイナリファイルの直接メモリアクセス

### 1.3 主要な処理内容

1. ファイルオープン: `open` - ファイルをメモリにマッピング
2. 領域マッピング: `mapMem` - 追加領域のマッピング
3. 領域アンマップ: `unmapMem` - マッピング解除
4. フラッシュ: `flush` - 変更をディスクに書き出し
5. リサイズ: `resize` - マッピングサイズ変更
6. クローズ: `close` - マッピング解除とリソース解放
7. 行イテレーション: `lines`, `memSlices` - 高速行処理

### 1.4 関連するデータ/ファイル

- マッピング対象ファイル
- メモリマップ領域
- OSページサイズ（オフセットの制約）

### 1.5 バッチ/オンライン区分

オンライン（ファイルI/O）

## 2. 関連画面

- ログ解析ツール
- 大容量ファイルビューア
- データベースエンジン
- 高性能データ処理システム

## 3. 機能種別

- [x] データ操作
- [ ] 帳票出力
- [ ] 外部連携
- [x] バッチ処理
- [x] リアルタイム処理

## 4. 入力仕様

### 4.1 open関数パラメータ

| 項目名 | 型 | 説明 | 必須 | デフォルト |
|--------|-----|------|------|-----------|
| filename | string | ファイルパス | Yes | - |
| mode | FileMode | アクセスモード | No | fmRead |
| mappedSize | int | マッピングサイズ（-1で全体） | No | -1 |
| offset | int | オフセット（ページサイズの倍数） | No | 0 |
| newFileSize | int | 新規ファイルサイズ | No | -1 |
| allowRemap | bool | 追加マッピング許可 | No | false |
| mapFlags | cint | プラットフォーム固有フラグ | No | -1 |

### 4.2 FileMode

| モード | 説明 |
|--------|------|
| fmRead | 読み取り専用 |
| fmWrite | 書き込み専用 |
| fmReadWrite | 読み書き |
| fmAppend | 追記（非対応） |

### 4.3 入力チェック仕様

| チェック項目 | 内容 | エラー処理 |
|-------------|------|-----------|
| fmAppend | 追記モードは非対応 | IOError発生 |
| newFileSize | fmRead時は-1のみ可 | assert失敗 |
| offset | ページサイズの倍数 | OSError発生 |
| resize | newFileSize >= 1 | IOError発生 |

## 5. 出力仕様

### 5.1 MemFile型

| フィールド | 型 | 説明 |
|-----------|-----|------|
| mem | pointer | マッピングされたメモリへのポインタ |
| size | int | マッピングサイズ |
| fHandle (Windows) | Handle | ファイルハンドル |
| mapHandle (Windows) | Handle | マッピングハンドル |
| wasOpened (Windows) | bool | オープン済みフラグ |
| handle (POSIX) | cint | ファイルディスクリプタ |
| flags (POSIX) | cint | マッピングフラグ |

### 5.2 MemSlice型

| フィールド | 型 | 説明 |
|-----------|-----|------|
| data | pointer | データへのポインタ |
| size | int | データサイズ |

### 5.3 MemMapFileStream型

| フィールド | 型 | 説明 |
|-----------|-----|------|
| mf | MemFile | 内部MemFile |
| mode | FileMode | アクセスモード |
| pos | int | 現在位置 |

## 6. 処理フロー

### 6.1 ファイルオープンフロー

```mermaid
flowchart TD
    A[open呼び出し] --> B{mode == fmAppend?}
    B -->|Yes| C[IOError発生]
    B -->|No| D{Windows?}
    D -->|Yes| E[CreateFileW]
    D -->|No| F[posix.open]
    E --> G{newFileSize指定?}
    F --> G
    G -->|Yes| H[setFileSize]
    G -->|No| I[ファイルサイズ取得]
    H --> I
    I --> J{Windows?}
    J -->|Yes| K[CreateFileMappingW]
    J -->|No| L[mmap]
    K --> M[MapViewOfFileEx]
    L --> N[MemFile返却]
    M --> N
```

### 6.2 フラッシュフロー

```mermaid
flowchart TD
    A[flush呼び出し] --> B{リトライループ開始}
    B --> C{Windows?}
    C -->|Yes| D[FlushViewOfFile]
    C -->|No| E[msync MS_SYNC]
    D --> F{成功?}
    E --> F
    F -->|Yes| G[完了]
    F -->|No| H{リトライ可能エラー?}
    H -->|Yes| I[リトライ]
    H -->|No| J[OSError発生]
    I --> B
```

### 6.3 リサイズフロー（Linux）

```mermaid
flowchart TD
    A[resize呼び出し] --> B{newFileSize < 1?}
    B -->|Yes| C[IOError発生]
    B -->|No| D{allowRemap有効?}
    D -->|No| E[IOError発生]
    D -->|Yes| F[setFileSize]
    F --> G{Linux?}
    G -->|Yes| H[mremap]
    G -->|No| I[munmap + mmap]
    H --> J[f.mem/f.size更新]
    I --> J
```

### 6.4 memSlicesイテレーションフロー

```mermaid
flowchart TD
    A[memSlices開始] --> B{remaining > 0?}
    B -->|No| C[完了]
    B -->|Yes| D[c_memchr でデリミタ検索]
    D --> E{見つかった?}
    E -->|No| F[残りを最終スライスとしてyield]
    F --> C
    E -->|Yes| G[スライスサイズ計算]
    G --> H{eat文字あり?}
    H -->|Yes| I[末尾eat文字を除去]
    H -->|No| J[スライスをyield]
    I --> J
    J --> K[次の位置に移動]
    K --> B
```

## 7. ビジネスルール

### 7.1 マッピングルール

| 条件 | ルール |
|------|--------|
| offset | OSのページサイズの倍数であること |
| mappedSize = -1 | ファイル全体をマッピング |
| newFileSize指定 | mode != fmRead であること |
| allowRemap = false | open後にmapMemは呼び出し不可 |

### 7.2 マッピングフラグ

| フラグ | 説明 |
|--------|------|
| MAP_SHARED | 変更がファイルに反映（デフォルト） |
| MAP_PRIVATE | Copy-on-Write、ファイルに反映されない |

### 7.3 フラッシュ動作

| プラットフォーム | リトライ対象エラー |
|-----------------|------------------|
| Windows | ERROR_LOCK_VIOLATION |
| POSIX | EBUSY |

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

該当なし（ファイルシステム操作のみ）

## 9. エラー処理

### 9.1 エラー一覧

| エラー条件 | 発生関数 | 処理 |
|-----------|---------|------|
| fmAppendモード | open, mapMem | IOError発生 |
| ファイルオープン失敗 | open | OSError発生 |
| マッピング失敗 | open, mapMem | OSError発生 |
| リサイズ失敗 | resize | OSError/IOError発生 |
| フラッシュ失敗 | flush | OSError発生 |

### 9.2 エラーコード

| コード | 意味 |
|--------|------|
| MAP_FAILED | マッピング失敗（POSIX） |
| INVALID_HANDLE_VALUE | 無効なハンドル（Windows） |
| ERROR_LOCK_VIOLATION | ロック競合（Windows） |
| EBUSY | リソースビジー（POSIX） |
| EINTR | シグナル割り込み |
| EINVAL | 無効なパラメータ |

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

該当なし（ファイルシステム操作はトランザクション対象外）

## 11. パフォーマンス要件

| 項目 | 特性 |
|------|------|
| ゼロコピー | memSlicesは文字列コピー不要 |
| 遅延読み込み | ページフォールト時にのみディスク読み込み |
| mremap（Linux） | munmap+mmapより100倍以上高速 |
| memchr | C標準ライブラリの最適化された検索 |

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

### 12.1 メモリアクセス

| リスク | 対策 |
|--------|------|
| バッファオーバーラン | MemSliceのサイズ確認必須 |
| 境界外アクセス | Nimの安全な文字列への変換 |
| ファイル権限 | OSのファイルアクセス権限に依存 |

### 12.2 共有メモリ

| リスク | 対策 |
|--------|------|
| 競合状態 | MAP_SHAREDでの同時書き込み注意 |
| データ整合性 | flush呼び出しで明示的な同期 |
| 機密データ | マッピング解除後もページが残る可能性 |

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

### 13.1 関連ファイル一覧

| ファイルパス | 概要 | 行数 |
|-------------|------|------|
| lib/pure/memfiles.nim | メモリマップトファイルモジュール | 572行 |
| lib/pure/streams.nim | ストリーム抽象（依存） | - |
| lib/pure/oserrors.nim | OSエラー処理（依存） | - |

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

```
memfiles.nim
├── open (139-298行)
│   ├── [Windows] CreateFileW (212行)
│   ├── [Windows] setFileSize (217-218行)
│   ├── [Windows] CreateFileMappingW (222-225行)
│   ├── [Windows] MapViewOfFileEx (230-236行)
│   ├── [POSIX] posix.open (266/271行)
│   ├── [POSIX] fstat (280行)
│   └── [POSIX] mmap (291行)
├── mapMem (88-123行)
│   ├── [Windows] MapViewOfFileEx (99-105行)
│   └── [POSIX] mmap (116-121行)
├── unmapMem (126-136行)
│   ├── [Windows] UnmapViewOfFile (134行)
│   └── [POSIX] munmap (136行)
├── flush (299-319行)
│   ├── [Windows] FlushViewOfFile (306行)
│   └── [POSIX] msync (314行)
├── resize (321-373行)
│   ├── [Windows] UnmapViewOfFile + CreateFileMappingW + MapViewOfFileEx
│   └── [Linux] mremap (360-364行)
├── close (375-408行)
│   ├── [Windows] UnmapViewOfFile + CloseHandle
│   └── [POSIX] munmap + close
├── memSlices iterator (424-471行)
│   └── c_memchr (461行)
├── lines iterator (473-505行)
│   └── memSlices呼び出し
└── newMemMapFileStream (552-571行)
    └── open呼び出し
```

### 13.3 データフロー図

```
[ファイルパス]
       │
       ▼
┌─────────────────────────────────────────┐
│ open                                     │
│  ├─ ファイルオープン                      │
│  ├─ ファイルサイズ設定（オプション）        │
│  └─ メモリマッピング作成                   │
└─────────────────────────────────────────┘
       │
       ▼
   [MemFile]
       │
       ├───────────────┬───────────────┬───────────────┐
       ▼               ▼               ▼               ▼
    mem直接        memSlices       lines          mapMem
    アクセス       イテレータ      イテレータ      追加領域
       │               │               │               │
       ▼               ▼               ▼               ▼
  [データ操作]    [MemSlice]     [string]      [pointer]
       │               │               │               │
       └───────────────┴───────────────┴───────────────┘
                               │
                               ▼
                           flush
                          (同期)
                               │
                               ▼
                           close
                        (リソース解放)
```

### 13.4 読み解くべき重要なコード

1. **MemFile型定義（72-86行）**: プラットフォーム別のフィールド構成
2. **open関数（139-298行）**: Windows/POSIXでのマッピング処理全体
3. **setFileSize（38-70行）**: posix_fallocate/ftruncateの使い分け
4. **memSlicesイテレータ（424-471行）**: ゼロコピー高速行処理
5. **resize（321-373行）**: Linuxのmremapによる高速リサイズ

### 13.5 推奨リーディング順序

1. MemFile型定義（72-86行）- データ構造の理解
2. open関数（139-298行）- 基本的なマッピング処理
3. close関数（375-408行）- リソース解放
4. memSlicesイテレータ（424-471行）- 高速イテレーション
5. resize関数（321-373行）- 動的サイズ変更
6. MemMapFileStream（507-571行）- ストリーム抽象
