# 通知設計書 14-FileSystemWatcher.Error

## 概要

本ドキュメントは、.NET の `System.IO.FileSystemWatcher` クラスが提供する `Error` イベントについて、その設計仕様と実装詳細を記述した通知設計書である。

### 本通知の処理概要

FileSystemWatcher.Error イベントは、FileSystemWatcher の内部バッファがオーバーフローした場合や、その他のエラーが発生した場合に発生するイベント通知機能を提供する。

**業務上の目的・背景**：ファイルシステム監視においてエラーが発生した場合、アプリケーションはその状況を把握し、適切な対処（監視の再開、ログ記録、ユーザー通知など）を行う必要がある。Error イベントは、監視処理中に発生した問題をアプリケーションに通知し、リカバリー処理のトリガーとなる重要な機能を提供する。

**通知の送信タイミング**：内部バッファオーバーフロー（InternalBufferOverflowException）が発生した場合、または監視処理中にその他の例外が発生した場合にイベントが発生する。高頻度のファイル変更やシステムリソースの制限超過時に発生しやすい。

**通知の受信者**：FileSystemWatcher インスタンスの Error イベントにハンドラを登録したアプリケーションコード。SynchronizingObject プロパティが設定されている場合、指定されたスレッドコンテキストでハンドラが呼び出される。

**通知内容の概要**：ErrorEventArgs オブジェクトとして、発生した例外（Exception）が通知される。GetException() メソッドで例外オブジェクトを取得できる。

**期待されるアクション**：受信者は通知を受け取り後、エラーログの記録、監視の再起動、バッファサイズの調整、管理者への通知、グレースフルデグラデーションなどの対処を実行することが期待される。

## 通知種別

アプリ内通知（イベント通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（ThreadPool経由） |
| 優先度 | 高（エラー通知） |
| リトライ | なし（イベントは一度のみ配信） |

### 送信先決定ロジック

Error イベントに登録された ErrorEventHandler デリゲートが送信先となる。複数のハンドラが登録されている場合、マルチキャストデリゲートとして順次呼び出される。SynchronizingObject が設定されている場合は BeginInvoke 経由で非同期呼び出しが行われる。

## 通知テンプレート

### イベント引数

| 項目 | 内容 |
|-----|------|
| イベント型 | ErrorEventArgs |
| sender | FileSystemWatcher インスタンス |
| 例外 | GetException() で取得 |

### イベントデータ構造

```csharp
public class ErrorEventArgs : EventArgs
{
    private readonly Exception _exception;

    public ErrorEventArgs(Exception exception) { ... }

    public virtual Exception GetException() => _exception;
}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| Exception | 発生した例外 | 内部処理で発生した例外オブジェクト | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 内部エラー | InternalBufferOverflowException | _onErrorHandler != null | 内部バッファがオーバーフローした場合 |
| 内部エラー | IOException（inotify関連） | _onErrorHandler != null | inotify インスタンス数超過、ウォッチ数超過など |
| 内部エラー | IN_Q_OVERFLOW (Linux) | _onErrorHandler != null | inotify イベントキューがオーバーフローした場合 |
| 内部エラー | その他の例外 | _onErrorHandler != null | 監視処理中に発生した予期しない例外 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| _onErrorHandler == null | Error イベントにハンドラが登録されていない |
| Disposed | FileSystemWatcher が破棄済み |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[エラー発生] --> B{エラー種別判定}
    B -->|バッファオーバーフロー| C[InternalBufferOverflowException 生成]
    B -->|inotifyエラー| D[IOException 生成]
    B -->|キューオーバーフロー| E[InternalBufferOverflowException 生成]
    B -->|その他| F[例外をそのまま使用]
    C --> G[ErrorEventArgs 生成]
    D --> G
    E --> G
    F --> G
    G --> H{_onErrorHandler?}
    H -->|null| I[通知スキップ]
    H -->|設定あり| J{SynchronizingObject?}
    J -->|null| K[直接ハンドラ呼出]
    J -->|設定あり| L[BeginInvoke経由]
    K --> M[OnError 実行]
    L --> M
    M --> N[終了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（ファイルシステム通知のためデータベースを使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| InternalBufferOverflowException | ファイル変更が高頻度で内部バッファが溢れた | InternalBufferSize の増加、フィルタの絞り込み |
| IOException (EMFILE) | inotify インスタンス数がユーザー上限を超えた | 他の FileSystemWatcher の削減、システム設定の調整 |
| IOException (ENOSPC) | inotify ウォッチ数がユーザー上限を超えた | IncludeSubdirectories の見直し、監視対象の絞り込み |
| IOException (ENFILE) | システム全体の inotify インスタンス上限超過 | システム管理者への連絡 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（アプリケーション側で判断） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | アプリケーション側で Restart() を呼び出すことで再試行可能 |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（エラー発生頻度依存） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（24時間監視可能）

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

- 例外オブジェクトにはファイルパスやシステム情報が含まれる可能性がある
- エラーログ出力時はセンシティブ情報のマスキングを検討
- 例外メッセージの外部公開には注意が必要

## 備考

- InternalBufferOverflowException 発生後、Linux 実装では監視が自動的に再起動される
- バッファサイズは InternalBufferSize プロパティで調整可能（最小4096バイト）
- Linux では /proc/sys/fs/inotify/max_user_instances、/proc/sys/fs/inotify/max_user_watches で上限を確認・調整可能
- WaitForChanged メソッドでは Error イベントは登録されない

---

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

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

### 推奨読解順序

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

まず、エラー通知で使用されるデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ErrorEventArgs.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/ErrorEventArgs.cs` | エラーイベント引数。Exception の保持と GetException() メソッド |
| 1-2 | ErrorEventHandler.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/ErrorEventHandler.cs` | ErrorEventHandler デリゲートの定義 |

**読解のコツ**: ErrorEventArgs は EventArgs を継承し、例外オブジェクトを保持する単純な構造。GetException() が virtual である点に注目。

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

処理の起点となる FileSystemWatcher クラスのイベント定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FileSystemWatcher.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs` | Error イベントの定義と OnError メソッドの実装 |

**主要処理フロー**:
1. **行 302-312**: Error イベントの add/remove アクセサ定義
2. **行 501-512**: OnError メソッドによるイベント発火（SynchronizingObject 考慮）
3. **行 396-406**: NotifyInternalBufferOverflowEvent メソッドでバッファオーバーフロー通知
4. **行 404-405**: CreateBufferOverflowException で InternalBufferOverflowException 生成

**読解のコツ**: _onErrorHandler が null の場合は NotifyInternalBufferOverflowEvent で早期リターンする点、OnError は SynchronizingObject を考慮して呼び出し方法を分岐する点に注目。

#### Step 3: Linux 実装でのエラー処理を理解する

Linux 環境での inotify を使用したエラー処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | inotify 関連のエラー処理 |
| 3-2 | Interop.INotify.cs | `src/libraries/Common/src/Interop/Linux/System.Native/Interop.INotify.cs` | IN_Q_OVERFLOW 定数定義 |

**主要処理フロー**:
- **行 535-546 (Linux.cs)**: IN_Q_OVERFLOW イベント受信時の処理
- **行 156-166 (Linux.cs)**: inotify_init 失敗時のエラー処理（EMFILE、ENFILE）
- **行 272-287 (Linux.cs)**: inotify_add_watch 失敗時のエラー処理（ENOSPC）
- **行 1221-1227 (Linux.cs)**: QueueError メソッドでエラーをキューに追加
- **行 1136 (Linux.cs)**: EmitEvent での ErrorType 処理

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

```
FileSystemWatcher.Error イベント
    │
    ├─ OnError(ErrorEventArgs e)
    │      └─ [SynchronizingObject判定]
    │             ├─ handler(this, e)
    │             └─ syncObj.BeginInvoke(handler, ...)
    │
    ├─ NotifyInternalBufferOverflowEvent()
    │      ├─ [_onErrorHandler == null] → return
    │      └─ OnError(new ErrorEventArgs(CreateBufferOverflowException()))
    │
    └─ [Linux] Watcher.QueueError(Exception)
           └─ _eventQueue.Writer.TryWrite(WatcherEvent.Error(exception))
                  │
                  ▼
           EmitEvent() → fsw.OnError(new ErrorEventArgs(...))
```

### データフロー図

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

バッファオーバーフロー    CreateBufferOverflowException()
    │                           │
    ▼                           ▼
IN_Q_OVERFLOW  ───────▶  WatcherEvent.Error 生成  ───▶  ErrorEventHandler
                               │                        デリゲート呼び出し
                               ▼
inotify エラー  ──────▶  QueueError()
(EMFILE/ENOSPC)                │
                               ▼
                         EmitEvent()
                               │
                               ▼
                         OnError()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FileSystemWatcher.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs` | ソース | メインクラス、Error イベント定義 |
| FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | ソース | Linux 固有エラー処理（inotify） |
| ErrorEventArgs.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/ErrorEventArgs.cs` | ソース | エラーイベント引数クラス |
| ErrorEventHandler.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/ErrorEventHandler.cs` | ソース | エラーイベントハンドラデリゲート定義 |
| Interop.INotify.cs | `src/libraries/Common/src/Interop/Linux/System.Native/Interop.INotify.cs` | ソース | IN_Q_OVERFLOW 定数定義 |
| Strings.resx | `src/libraries/System.IO.FileSystem.Watcher/src/Resources/Strings.resx` | リソース | エラーメッセージ文字列（FSW_BufferOverflow など） |
