# 通知設計書 12-FileSystemWatcher.Deleted

## 概要

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

### 本通知の処理概要

FileSystemWatcher.Deleted イベントは、監視対象のディレクトリ内のファイルまたはディレクトリが削除された際に発生するイベント通知機能を提供する。

**業務上の目的・背景**：ファイルの削除検知は、ファイル同期システムでの削除伝播、クリーンアップ処理のトリガー、監査ログの記録、一時ファイルの管理など、様々な業務シナリオで必要とされる。Deleted イベントは、ファイルやディレクトリの消失をリアルタイムに検知し、適切な後続処理を開始するための基盤機能を提供する。

**通知の送信タイミング**：監視対象ディレクトリ（Path プロパティで指定）内で、ファイルまたはディレクトリが削除された瞬間にイベントが発生する。IncludeSubdirectories が true の場合、サブディレクトリ内での削除も検知対象となる。

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

**通知内容の概要**：FileSystemEventArgs オブジェクトとして、変更種別（WatcherChangeTypes.Deleted）、削除されたファイル/ディレクトリの名前（Name）、フルパス（FullPath）が通知される。

**期待されるアクション**：受信者は通知を受け取り後、同期先での対応する削除処理、キャッシュの無効化、関連リソースの解放、監査ログへの記録などの業務処理を実行することが期待される。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

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

## 通知テンプレート

### イベント引数

| 項目 | 内容 |
|-----|------|
| イベント型 | FileSystemEventArgs |
| sender | FileSystemWatcher インスタンス |
| ChangeType | WatcherChangeTypes.Deleted |

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

```csharp
public class FileSystemEventArgs : EventArgs
{
    public WatcherChangeTypes ChangeType { get; }  // Deleted
    public string FullPath { get; }                 // 削除されたファイル/ディレクトリのフルパス
    public string? Name { get; }                    // 削除されたファイル/ディレクトリの名前
}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| ChangeType | 変更種別 | inotify/ReadDirectoryChangesW からのイベント種別 | Yes |
| FullPath | フルパス | 監視ディレクトリパス + ファイル名 | Yes |
| Name | ファイル/ディレクトリ名 | inotify イベントの name フィールド | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| OS通知 | ファイル/ディレクトリ削除 | EnableRaisingEvents == true かつ Filter/Filters にマッチ | 監視対象ディレクトリ内での削除を検知 |
| OS通知 | IN_DELETE (Linux) | EnableRaisingEvents == true | Linux inotify による削除イベント |
| OS通知 | IN_MOVED_FROM (Linux) | EnableRaisingEvents == true かつ移動先が監視外 | 監視外への移動は Deleted として扱う |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| EnableRaisingEvents == false | イベント発生が無効化されている |
| Filter/Filters 不一致 | ファイル名がフィルタパターンにマッチしない |
| NotifyFilters 不一致 | NotifyFilters.FileName/DirectoryName が設定されていない場合、該当種別は通知されない |
| Disposed | FileSystemWatcher が破棄済み |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[OS: ファイル削除検知] --> B{EnableRaisingEvents?}
    B -->|false| Z[通知スキップ]
    B -->|true| C{フィルタチェック}
    C -->|不一致| Z
    C -->|一致| D[FileSystemEventArgs 生成]
    D --> E{SynchronizingObject?}
    E -->|null| F[直接ハンドラ呼出]
    E -->|設定あり| G[BeginInvoke経由]
    F --> H[OnDeleted 実行]
    G --> H
    H --> I[終了]
```

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

### 参照テーブル一覧

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

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| InternalBufferOverflowException | 内部バッファがオーバーフローした場合 | Error イベントで通知、バッファサイズ増加を検討 |
| ObjectDisposedException | 破棄後のアクセス | アプリケーション側でライフサイクル管理 |
| ArgumentException | 無効なパス指定 | 監視開始前にパス検証 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし（イベントはリトライされない） |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（OSイベント依存） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

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

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

- ファイルパスにはファイルシステムのアクセス権限が適用される
- 監視対象ディレクトリへの読み取り権限が必要
- 削除されたファイルの内容は取得できない（パスと名前のみ通知）
- Linux では inotify インスタンス数とウォッチ数にユーザーごとの制限がある

## 備考

- Windows と Linux で内部実装が異なる（Windows: ReadDirectoryChangesW、Linux: inotify）
- 削除されたファイルの内容にアクセスすることはできない
- IN_MOVED_FROM イベントで移動先の IN_MOVED_TO がタイムアウト（2ms）内に到着しない場合、Deleted として処理される
- サブディレクトリの監視ウォッチは、削除時に自動的に解除される（IN_IGNORED）

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FileSystemEventArgs.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemEventArgs.cs` | イベント引数のデータ構造。ChangeType、FullPath、Name プロパティの実装 |
| 1-2 | WatcherChangeTypes.cs | `src/libraries/System.IO.FileSystem.Watcher/ref/System.IO.FileSystem.Watcher.cs` | Deleted を含む変更種別の列挙型定義 |

**読解のコツ**: FileSystemEventArgs は EventArgs を継承しており、Combine メソッドでディレクトリとファイル名からフルパスを構築している点に注目。

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

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

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

**主要処理フロー**:
1. **行 287-297**: Deleted イベントの add/remove アクセサ定義
2. **行 481-484**: OnDeleted メソッドによるイベント発火
3. **行 486-496**: InvokeOn メソッドによる SynchronizingObject 考慮のハンドラ呼び出し
4. **行 420-434**: GetHandler メソッドで WatcherChangeTypes.Deleted に対応するハンドラ取得

**読解のコツ**: _onDeletedHandler フィールドがデリゲートチェーンを保持し、InvokeOn メソッドで SynchronizingObject の有無によって呼び出し方法が分岐する点に注目。

#### Step 3: Linux 実装を理解する

Linux 環境での inotify を使用した実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | Linux 固有の inotify 実装 |
| 3-2 | Interop.INotify.cs | `src/libraries/Common/src/Interop/Linux/System.Native/Interop.INotify.cs` | inotify システムコールのP/Invoke定義 |

**主要処理フロー**:
- **行 683-684 (Linux.cs)**: IN_DELETE イベント受信時に WatcherEvent.Deleted を生成
- **行 585 (Linux.cs)**: IN_MOVED_FROM で移動先が見つからない場合も Deleted として処理
- **行 691 (Linux.cs)**: IN_MOVED_FROM 単独の場合も Deleted として処理
- **行 959-960 (Linux.cs)**: WatcherEvent.Deleted ファクトリメソッドの定義

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

```
FileSystemWatcher.Deleted イベント
    │
    ├─ OnDeleted(FileSystemEventArgs e)
    │      └─ InvokeOn(e, _onDeletedHandler)
    │             ├─ [SynchronizingObject == null] handler(this, e)
    │             └─ [SynchronizingObject != null] syncObj.BeginInvoke(handler, ...)
    │
    └─ NotifyFileSystemEventArgs(WatcherChangeTypes.Deleted, name)
           ├─ GetHandler(changeType) → _onDeletedHandler
           ├─ MatchPattern(name) → フィルタチェック
           └─ InvokeOn(new FileSystemEventArgs(...), handler)
```

### データフロー図

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

Linux inotify           INotify.ProcessEvent()
IN_DELETE event  ───▶   NotifyFileSystemEventArgs()  ───▶  FileSystemEventHandler
                        FileSystemEventArgs生成              デリゲート呼び出し
        │                     │
        ▼                     ▼
IN_MOVED_FROM ────▶    [タイムアウト判定]
(移動先なし)            WatcherEvent.Deleted生成
                              │
                              ▼
                        OnDeleted()
                              │
                              ▼
                        InvokeOn()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FileSystemWatcher.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs` | ソース | メインクラス、Deleted イベント定義 |
| FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | ソース | Linux 固有実装（inotify） |
| 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` | ソース | イベントハンドラデリゲート定義 |
| Interop.INotify.cs | `src/libraries/Common/src/Interop/Linux/System.Native/Interop.INotify.cs` | ソース | inotify P/Invoke 定義、IN_DELETE 定数 |
