# 通知設計書 10-FileSystemWatcher.Changed

## 概要

本ドキュメントは、.NET Runtimeにおける`FileSystemWatcher.Changed`イベント通知の設計を記述する。このイベントは、監視対象のファイルまたはディレクトリが変更された際に発生するイベントである。

### 本通知の処理概要

`FileSystemWatcher.Changed`イベントは、指定されたパス内のファイルまたはディレクトリの内容、属性、アクセス時間、セキュリティ設定などが変更された際にリスナーに通知するためのイベントである。ファイルシステムの変更をリアルタイムに監視し、アプリケーションが変更に対応できるようにする。

**業務上の目的・背景**：ファイルベースのアプリケーション（ログ監視、設定ファイルの自動リロード、同期ツール、バックアップシステムなど）では、ファイルシステムの変更を検出する必要がある。ポーリングによる監視はリソースを消費するため、`FileSystemWatcher`はOSのファイルシステム通知機能（Windows: ReadDirectoryChangesW、Linux: inotify、macOS: FSEvents）を利用して効率的な監視を実現する。

**通知の送信タイミング**：監視対象のファイルまたはディレクトリの内容が変更されたとき（書き込み完了時等）に発火する。`NotifyFilter`プロパティで監視対象の変更種別を指定できる。

**通知の受信者**：`Changed`イベントを購読しているすべてのイベントハンドラが受信者となる。`SynchronizingObject`プロパティで指定したオブジェクトのスレッドでイベントがマーシャリングされる。

**通知内容の概要**：`FileSystemEventArgs`オブジェクトを通じて、変更の種類（`ChangeType`）、影響を受けたファイル/ディレクトリの名前（`Name`）、フルパス（`FullPath`）が通知される。

**期待されるアクション**：受信者は変更されたファイルを再読み込み、設定を更新、ログを記録するなどの処理を行う。

## 通知種別

クラスイベント（システム通知のラッパー）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（スレッドプールスレッドから） |
| 優先度 | 中 |
| リトライ | なし（ただしイベント重複の可能性あり） |

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

`Changed`イベントに登録されているすべてのイベントハンドラに対して通知が行われる。`SynchronizingObject`が設定されている場合、そのオブジェクトの`BeginInvoke`メソッドを通じてマーシャリングされる。

## 通知テンプレート

### イベント引数

| 項目 | 内容 |
|-----|------|
| イベント型 | `FileSystemEventHandler` |
| 引数型 | `FileSystemEventArgs` |
| sender | `FileSystemWatcher`インスタンス |

### FileSystemWatcherクラス（関連部分）

```csharp
namespace System.IO
{
    public partial class FileSystemWatcher : Component, ISupportInitialize
    {
        public event FileSystemEventHandler? Changed;
        public event FileSystemEventHandler? Created;
        public event FileSystemEventHandler? Deleted;
        public event RenamedEventHandler? Renamed;
        public event ErrorEventHandler? Error;

        public string Path { get; set; }
        public string Filter { get; set; }
        public NotifyFilters NotifyFilter { get; set; }
        public bool IncludeSubdirectories { get; set; }
        public bool EnableRaisingEvents { get; set; }
        public int InternalBufferSize { get; set; }
        public ISynchronizeInvoke? SynchronizingObject { get; set; }

        protected void OnChanged(FileSystemEventArgs e);
    }
}
```

### FileSystemEventArgs

```csharp
public class FileSystemEventArgs : EventArgs
{
    public WatcherChangeTypes ChangeType { get; }
    public string FullPath { get; }
    public string? Name { get; }
}
```

### NotifyFilters列挙型

```csharp
[Flags]
public enum NotifyFilters
{
    FileName = 1,
    DirectoryName = 2,
    Attributes = 4,
    Size = 8,
    LastWrite = 16,
    LastAccess = 32,
    CreationTime = 64,
    Security = 256
}
```

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| ChangeType | 変更の種類（Changed） | ファイルシステム通知 | Yes |
| FullPath | 影響を受けたファイル/ディレクトリのフルパス | ファイルシステム通知 | Yes |
| Name | 影響を受けたファイル/ディレクトリの名前 | ファイルシステム通知 | No（nullの場合あり） |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ファイルシステム | ファイル内容の変更 | NotifyFilter.LastWriteが有効 | ファイルへの書き込み |
| ファイルシステム | ファイルサイズの変更 | NotifyFilter.Sizeが有効 | ファイルサイズの増減 |
| ファイルシステム | 属性の変更 | NotifyFilter.Attributesが有効 | 読み取り専用等の変更 |
| ファイルシステム | アクセス時間の変更 | NotifyFilter.LastAccessが有効 | ファイルアクセス |
| ファイルシステム | セキュリティ設定の変更 | NotifyFilter.Securityが有効 | ACLの変更 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| EnableRaisingEvents = false | イベント発火が無効化されている |
| フィルタに一致しない | Filterプロパティのパターンに一致しない |
| サブディレクトリ外 | IncludeSubdirectories = falseでサブディレクトリ内の変更 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ファイルシステム変更] --> B[OS通知API<br/>Windows:ReadDirectoryChangesW<br/>Linux:inotify<br/>macOS:FSEvents]
    B --> C[FileSystemWatcher内部処理]
    C --> D{EnableRaisingEvents?}
    D -->|false| E[終了]
    D -->|true| F{Filterに一致?}
    F -->|No| E
    F -->|Yes| G{NotifyFilterに一致?}
    G -->|No| E
    G -->|Yes| H[FileSystemEventArgs作成]
    H --> I[OnChangedメソッド呼び出し]
    I --> J{SynchronizingObject設定?}
    J -->|Yes| K[BeginInvokeでマーシャリング]
    J -->|No| L[直接ハンドラ呼び出し]
    K --> M[イベントハンドラ実行]
    L --> M
    M --> E
```

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

### 参照テーブル一覧

該当なし（ファイルシステム監視）

### 更新テーブル一覧

該当なし（ファイルシステム監視）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| InternalBufferOverflowException | 内部バッファがオーバーフロー | Errorイベントで通知、InternalBufferSizeを増加 |
| ArgumentException | 不正なPath指定 | 有効なパスを指定 |
| ObjectDisposedException | Dispose後のアクセス | 適切なライフサイクル管理 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（イベント再送なし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし（ただしバッファオーバーフローに注意） |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし（ファイルシステム変更発生時に即座に発火）

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

- 監視対象パスへのアクセス権限が必要
- フルパスに機密情報が含まれる可能性を考慮
- シンボリックリンクの追跡に注意
- ネットワークパスの監視は信頼性に欠ける場合がある

## 備考

- `System.IO`名前空間に定義
- Changedイベントは1回の変更で複数回発火する可能性がある（バッファリングを検討）
- デフォルトのNotifyFilterは`LastWrite | FileName | DirectoryName`
- InternalBufferSizeのデフォルトは8192バイト、最小は4096バイト
- プラットフォームにより動作が異なる場合がある（特にネットワークドライブ）
- WaitForChangedメソッドで同期的な待機も可能

---

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

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

### 推奨読解順序

#### Step 1: イベント引数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FileSystemEventArgs.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemEventArgs.cs` | ChangeType, FullPath, Nameプロパティの定義（行9-77） |

**読解のコツ**: `WatcherChangeTypes`列挙型（Created, Deleted, Changed, Renamed）も確認する。

**主要処理フロー**:
1. **行18-25**: コンストラクタ - changeType, directory, nameを設定
2. **行47-53**: `ChangeType`プロパティ
3. **行58-64**: `FullPath`プロパティ
4. **行70-76**: `Name`プロパティ

#### Step 2: FileSystemWatcherクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FileSystemWatcher.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs` | クラス定義とイベント宣言（行20-328） |

**主要処理フロー**:
- **行20**: クラス定義（Component, ISupportInitializeの継承/実装）
- **行48-52**: イベントハンドラフィールド
- **行257-267**: `Changed`イベントのadd/remove
- **行465-468**: `OnChanged`メソッド

#### Step 3: イベント発火メカニズムを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FileSystemWatcher.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs` | NotifyFileSystemEventArgs, InvokeOnメソッド（行439-496） |

**主要処理フロー**:
- **行439-460**: `NotifyFileSystemEventArgs` - フィルタリングとイベント発火
- **行486-496**: `InvokeOn` - SynchronizingObjectを考慮したハンドラ呼び出し

#### Step 4: プラットフォーム固有の実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | FileSystemWatcher.Win32.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs` | Windows固有の実装 |
| 4-2 | FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | Linux固有の実装（inotify） |
| 4-3 | FileSystemWatcher.OSX.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs` | macOS固有の実装（FSEvents） |

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

```
ファイルシステム変更（外部）
    │
    └─ OS通知API
           │
           ├─ Windows: ReadDirectoryChangesW
           │      └─ CompletionRoutine
           │
           ├─ Linux: inotify_read
           │      └─ イベント処理ループ
           │
           └─ macOS: FSEventStream callback
                  │
                  └─ NotifyFileSystemEventArgs(changeType, name)
                         │
                         ├─ GetHandler(changeType)
                         │      └─ _onChangedHandler（Changed用）
                         │
                         ├─ MatchPattern(name)
                         │      └─ Filterに一致チェック
                         │
                         └─ InvokeOn(e, handler)
                                │
                                ├─ SynchronizingObject?.BeginInvoke()
                                │
                                └─ handler(this, e)
```

### データフロー図

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

ファイル変更 ───▶ OS通知API ───▶ FileSystemWatcher内部
(書き込み等)           │                   │
        │              ▼                   ▼
        │        変更情報の取得       NotifyFileSystemEventArgs()
        │              │                   │
        │              ▼                   ▼
        │        FileSystemEventArgs   InvokeOn()
        │        (ChangeType,               │
        │         FullPath,                 ▼
        │         Name)             SynchronizingObject
        │              │             チェック
        │              │                   │
        ▼              ▼                   ▼
監視対象の変更     OnChanged() ───▶ イベントハンドラ実行
                                   (UIスレッド等)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FileSystemWatcher.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs` | ソース | メインクラス（共通部分） |
| FileSystemWatcher.Win32.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Win32.cs` | ソース | Windows固有実装 |
| FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | ソース | Linux固有実装 |
| FileSystemWatcher.OSX.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.OSX.cs` | ソース | macOS固有実装 |
| FileSystemEventArgs.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemEventArgs.cs` | ソース | イベント引数 |
| FileSystemEventHandler.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemEventHandler.cs` | ソース | イベントハンドラデリゲート |
| ErrorEventArgs.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/ErrorEventArgs.cs` | ソース | エラーイベント引数 |
