# 機能設計書 97-MemoryMappedViewStream

## 概要

本ドキュメントは、VBCorLibライブラリにおけるMemoryMappedViewStream機能の設計を記述するものである。MemoryMappedViewStreamは、メモリマップトファイルをシーケンシャルアクセスするストリームを提供するクラスである。

### 本機能の処理概要

MemoryMappedViewStreamクラスは、メモリマップトファイルの特定領域をStreamインターフェースを通じてシーケンシャルにアクセスする機能を提供する。位置を自動的に追跡し、従来のストリーム操作と同様の方法でメモリマップト領域を読み書きできる。

**業務上の目的・背景**：既存のストリームベースのコードとの互換性を保ちながら、メモリマップトファイルの高速アクセスを活用したい場合に使用する。Streamインターフェースを実装しているため、StreamReader/StreamWriterなど既存のストリームユーティリティと組み合わせて使用できる。

**機能の利用シーン**：ログファイルの高速読み込み、ストリーム処理パイプラインへの組み込み、シーケンシャルなバイナリデータ処理、既存ストリームAPIとの互換性維持に使用される。

**主要な処理内容**：
1. バイト読み取り（ReadByte/ReadBlock）- ストリームからデータを読み取り
2. バイト書き込み（WriteByte/WriteBlock）- ストリームにデータを書き込み
3. 位置操作（Position/SeekPosition）- ストリーム位置の取得・設定・移動
4. ストリーム情報（Length/Capacity/CanRead/CanWrite/CanSeek）
5. 非同期操作（BeginRead/EndRead/BeginWrite/EndWrite）
6. リソース管理（CloseStream/Flush）

**関連システム・外部連携**：Windows API（MapViewOfFile、FlushViewOfFile、UnmapViewOfFile）を使用。内部でMemoryStreamをラップ。

**権限による制御**：CanRead/CanWrite/CanSeekプロパティでアクセス能力を確認。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 1 | Simply VB Unit Runner | 参照画面 | MemoryMappedViewStream関連テストの実行 |

## 機能種別

ストリームアクセス / メモリ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| Buffer | Byte() | Yes（Read/Write） | 読み書き用バッファ | Null禁止 |
| Offset | Long | Yes（Read/Write） | バッファ内オフセット | 有効範囲内 |
| Count | Long | Yes（Read/Write） | バイト数 | 0以上 |
| Value | Byte | Yes（WriteByte） | 書き込むバイト値 | - |
| SeekOffset | Currency | Yes（SeekPosition） | シーク位置 | - |
| Origin | SeekOrigin | Yes（SeekPosition） | シーク基準（Begin/Current/End） | - |
| Destination | Stream | Yes（CopyTo） | コピー先ストリーム | Nothing禁止 |
| BufferSize | Long | No（CopyTo） | バッファサイズ（デフォルト: 81920） | 0より大きい |

### 入力データソース

- メモリマップトファイルのビュー領域
- 内部MemoryStream

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ReadByte | Long | 読み取ったバイト（-1は終端） |
| ReadBlock | Long | 実際に読み取ったバイト数 |
| Position | Currency | 現在のストリーム位置 |
| Length | Long | ストリームのデータ長 |
| Capacity | Long | ストリームの容量 |
| CanRead | Boolean | 読み取り可能か |
| CanWrite | Boolean | 書き込み可能か |
| CanSeek | Boolean | シーク可能か |
| CanTimeout | Boolean | タイムアウト可能か（常にFalse） |

### 出力先

- 呼び出し元への戻り値
- 引数として渡されたバッファ

## 処理フロー

### 処理シーケンス

```
1. Init呼び出し（MemoryMappedFile.CreateViewStream経由）
   └─ ページ境界調整を計算
   └─ MapViewOfFileでビューをマップ
   └─ SetCapacityで容量設定
   └─ InitViewDataでMemoryStreamを作成

2. ReadBlock呼び出し
   └─ CanReadを確認
   └─ mViewStream.ReadBlockに委譲

3. WriteBlock呼び出し
   └─ CanWriteを確認
   └─ mViewStream.WriteBlockに委譲

4. SeekPosition呼び出し
   └─ mViewStream.SeekPositionに委譲

5. CloseStream呼び出し
   └─ mViewStream.CloseStreamを呼び出し
   └─ ReleaseViewDataでビューを解放

6. Flush呼び出し
   └─ FlushViewOfFileでディスクに書き込み
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{操作種別}
    B -->|ReadBlock| C{CanRead?}
    C -->|No| D[NotSupportedException]
    C -->|Yes| E[mViewStream.ReadBlock]
    E --> F[読み取りバイト数返却]
    B -->|WriteBlock| G{CanWrite?}
    G -->|No| D
    G -->|Yes| H[mViewStream.WriteBlock]
    H --> I[終了]
    B -->|SeekPosition| J[mViewStream.SeekPosition]
    J --> K[新しい位置返却]
    B -->|SetLength| L[NotSupportedException]
    D --> M[終了]
    F --> M
    I --> M
    K --> M
    L --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-97-01 | 読み取り権限チェック | CanReadがFalseの場合、Read操作は失敗 | ReadBlock/ReadByte呼び出し時 |
| BR-97-02 | 書き込み権限チェック | CanWriteがFalseの場合、Write操作は失敗 | WriteBlock/WriteByte呼び出し時 |
| BR-97-03 | 長さ変更禁止 | SetLengthは常にNotSupportedException | SetLength呼び出し時 |
| BR-97-04 | タイムアウト非対応 | CanTimeoutは常にFalse | ReadTimeout/WriteTimeoutアクセス時はInvalidOperationException |
| BR-97-05 | 終端でのReadByte | ストリーム終端では-1を返却 | ReadByte呼び出し時 |

### 計算ロジック

```
位置調整（Init時）:
PageAlignedOffset = Int(Offset / AllocationGranularity) * AllocationGranularity
StartIndex = Offset Mod AllocationGranularity
```

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

### 操作別データベース影響一覧

該当なし

### テーブル別操作詳細

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NotSupported_UnreadableStream | NotSupportedException | CanRead=Falseで読み取り | ReadWrite/ReadOnlyアクセスで作成 |
| NotSupported_UnwritableStream | NotSupportedException | CanWrite=Falseで書き込み | ReadWrite/WriteOnlyアクセスで作成 |
| NotSupported_MMViewStreamsFixedLength | NotSupportedException | SetLength呼び出し | 適切なサイズでビューを作成 |
| InvalidOperation | InvalidOperationException | ReadTimeout/WriteTimeoutアクセス | タイムアウトは使用不可 |
| ArgumentNull | ArgumentNullException | NullバッファまたはNull Destination | 有効なオブジェクトを渡す |
| ObjectDisposed | ObjectDisposedException | 閉じたストリームへのアクセス | 閉じる前に操作を完了 |

### リトライ仕様

特になし

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

該当なし

## パフォーマンス要件

- 内部MemoryStreamを経由するため、直接アクセスよりわずかにオーバーヘッドあり
- Flushを頻繁に呼ぶとパフォーマンスが低下
- CopyToのデフォルトバッファサイズは81920バイト

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

- ViewAccessorと同様、適切な権限で保護すること

## 備考

- .NET FrameworkのSystem.IO.MemoryMappedFiles.MemoryMappedViewStreamクラスに対応
- Streamインターフェースを実装しているため、StreamReader等と組み合わせ可能
- SetLengthはサポートされない（ビューサイズは固定）

---

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

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

### 推奨読解順序

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

MemoryMappedViewStreamの内部状態を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | MemoryMappedViewStream.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewStream.cls` | プライベート変数（44-51行目）：mViewStream、mViewData、mCapacity、mCanRead、mCanWrite |

**読解のコツ**: mViewStreamはMemoryStreamインスタンスで、実際の読み書き操作はこれに委譲される。

#### Step 2: 初期化処理を理解する

Initメソッドでビューとストリームがどのように作成されるかを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | MemoryMappedViewStream.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewStream.cls` | Init（632-665行目）でビュー作成 |

**主要処理フロー**:
- **638-654行目**: ページ境界調整 - ViewAccessorと同様のロジック
- **656-658行目**: MapViewOfFileでビューをマップ
- **663-664行目**: SetCapacityとInitViewDataで内部MemoryStreamを初期化

#### Step 3: Read/Write操作を理解する

ストリーム読み書きの実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | MemoryMappedViewStream.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewStream.cls` | ReadBlock（396-401行目）で読み取り |
| 3-2 | MemoryMappedViewStream.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewStream.cls` | WriteBlock（522-527行目）で書き込み |
| 3-3 | MemoryMappedViewStream.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewStream.cls` | ReadByte（421-426行目）で1バイト読み取り |

**主要処理フロー**:
- **396-401行目**: ReadBlock - CanReadチェック後、mViewStream.ReadBlockに委譲
- **522-527行目**: WriteBlock - CanWriteチェック後、mViewStream.WriteBlockに委譲
- **421-426行目**: ReadByte - CanReadチェック後、mViewStream.ReadByteに委譲

#### Step 4: Streamインターフェース実装を理解する

Streamインターフェースの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | MemoryMappedViewStream.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewStream.cls` | Stream_*メソッド（755-864行目）でインターフェース実装 |

**主要処理フロー**:
- **755-864行目**: Stream_*メソッドはすべて対応するパブリックメソッドに委譲
- これにより、Streamインターフェースを期待する任意のコードで使用可能

#### Step 5: リソース解放を理解する

CloseStreamとFlushの実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | MemoryMappedViewStream.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewStream.cls` | CloseStream（147-153行目）でストリーム閉じる |
| 5-2 | MemoryMappedViewStream.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewStream.cls` | Flush（356-358行目）でディスク書き込み |

**主要処理フロー**:
- **147-153行目**: CloseStream - mViewStream.CloseStreamを呼び出し、ReleaseViewDataでビューを解放
- **356-358行目**: Flush - FlushViewOfFileでメモリ内容をディスクに書き込み

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

```
MemoryMappedFile.CreateViewStream
    │
    └─ MemoryMappedViewStream.Init
           │
           ├─ GetSystemInfo（Windows API）
           │
           ├─ MapViewOfFile（Windows API）
           │
           ├─ SetCapacity
           │
           └─ InitViewData
                  └─ Cor.NewMemoryStream

MemoryMappedViewStream.ReadBlock
    │
    ├─ CanRead チェック
    │
    └─ mViewStream.ReadBlock
           └─ 内部MemoryStream読み取り

MemoryMappedViewStream.WriteBlock
    │
    ├─ CanWrite チェック
    │
    └─ mViewStream.WriteBlock
           └─ 内部MemoryStream書き込み

MemoryMappedViewStream.CloseStream
    │
    ├─ mViewStream.CloseStream
    │
    └─ ReleaseViewData
           └─ UnmapViewOfFile（Windows API）
```

### データフロー図

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

Buffer/Offset/Count ────▶ ReadBlock ───────────────────▶ 読み取りバイト数
                              │
                              ▼
                        CanReadチェック
                              │
                              ▼
                        mViewStream.ReadBlock

Buffer/Offset/Count ────▶ WriteBlock ──────────────────▶ （なし）
                              │
                              ▼
                        CanWriteチェック
                              │
                              ▼
                        mViewStream.WriteBlock
                              │
                              ▼
                        mViewData更新

SeekOffset/Origin ──────▶ SeekPosition ────────────────▶ 新しい位置
                              │
                              ▼
                        mViewStream.SeekPosition
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| MemoryMappedViewStream.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedViewStream.cls` | ソース | ストリームアクセスビューの実装 |
| MemoryMappedFile.cls | `Source/CorLib/System.IO.MemoryMappedFiles/MemoryMappedFile.cls` | ソース | 親クラス（CreateViewStream） |
| MemoryStream.cls | `Source/CorLib/System.IO/MemoryStream.cls` | ソース | 内部で使用するストリーム |
