# 通知設計書 21-Interop.Sys.INotify (IN_DELETE)

## 概要

本ドキュメントは、Linux inotifyサブシステムにおけるIN_DELETE通知イベントの設計仕様を定義する。IN_DELETEは、監視対象ディレクトリ内でファイルまたはサブディレクトリが削除された際に発生するカーネルレベルの通知機構である。

### 本通知の処理概要

IN_DELETE通知は、Linuxファイルシステム監視機能の中核を担うinotify APIが提供する削除検知イベントである。この通知により、アプリケーションはファイルシステムの変更をリアルタイムで把握し、適切な処理を実行できる。

**業務上の目的・背景**：ファイルシステムの変更を監視する必要があるアプリケーション（バックアップツール、同期ツール、ファイルマネージャー、IDEなど）において、ファイルやディレクトリの削除をリアルタイムで検知することは重要な機能である。ポーリングベースの監視と比較して、inotifyはカーネルレベルで効率的にイベントを通知するため、CPU使用率を抑えつつ即座に変更を検知できる。

**通知の送信タイミング**：監視対象ディレクトリ（inotify_add_watchで登録されたディレクトリ）内でunlink()、rmdir()、またはrename()（移動元として）システムコールが実行され、ファイルまたはディレクトリが削除された時点でカーネルから通知が発生する。

**通知の受信者**：inotify_initで作成されたinotifyインスタンスのファイルディスクリプタを監視しているプロセス。.NETランタイムでは、FileSystemWatcherクラスがこの通知を受信し、Deletedイベントとしてアプリケーションに伝播する。

**通知内容の概要**：削除されたファイル/ディレクトリの名前、監視ディスクリプタ（wd）、イベントマスク（IN_DELETE）、およびオプションでIN_ISDIRフラグ（ディレクトリの場合）が含まれる。

**期待されるアクション**：受信者はイベントを処理し、必要に応じてキャッシュの更新、UIの再描画、同期処理の実行、またはログ記録などを行う。再帰的監視の場合、削除されたサブディレクトリの監視を解除する必要がある。

## 通知種別

システムコール通知（カーネルイベント）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（カーネルからユーザー空間へのイベント配信） |
| 優先度 | 中（通常のファイルシステムイベント） |
| リトライ | 無（イベントはキューに蓄積、オーバーフロー時は通知） |

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

inotify_add_watchシステムコールで監視を登録したすべてのプロセスに対して、該当ディレクトリで削除が発生した場合にイベントが送信される。複数のプロセスが同一ディレクトリを監視している場合、各プロセスのinotifyキューにイベントがコピーされる。

## 通知テンプレート

### イベント構造体

```c
struct inotify_event {
    int      wd;       // 監視ディスクリプタ
    uint32_t mask;     // イベントマスク（IN_DELETE = 0x00000200）
    uint32_t cookie;   // 関連イベントの関連付け用（削除では未使用）
    uint32_t len;      // 名前フィールドの長さ
    char     name[];   // 削除されたファイル/ディレクトリ名（NULL終端）
};
```

### 本文テンプレート

```
イベント: IN_DELETE
監視ディスクリプタ: {wd}
削除対象: {name}
ディレクトリフラグ: {IN_ISDIR が設定されている場合は "Yes"}
```

### 添付ファイル

なし（バイナリイベントデータのみ）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| wd | 監視ディスクリプタ | inotify_add_watchの戻り値 | Yes |
| mask | イベントマスク | カーネル設定値 | Yes |
| cookie | イベント関連付けID | カーネル設定値（削除では0） | Yes |
| len | 名前の長さ | カーネル計算値 | Yes |
| name | 削除されたエントリ名 | ファイルシステム | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| システムコール | unlink() | 監視対象ディレクトリ内のファイル削除 | ファイル削除時 |
| システムコール | rmdir() | 監視対象ディレクトリ内のサブディレクトリ削除 | 空ディレクトリ削除時 |
| システムコール | rename() | 監視対象ディレクトリからの移動 | 移動元ディレクトリでIN_DELETE相当の扱い |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 監視未登録 | inotify_add_watchでIN_DELETEマスクが設定されていない場合 |
| IN_EXCL_UNLINK | 既にunlinkされたファイルに対するイベントを抑止 |
| IN_ONESHOT | 最初のイベント後に監視が自動削除される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ファイル/ディレクトリ削除操作] --> B[カーネルVFSレイヤー]
    B --> C[inotify_fsnotify_mark確認]
    C -->|監視あり| D[inotify_eventキューへ追加]
    C -->|監視なし| E[処理終了]
    D --> F[read()可能状態に]
    F --> G[ユーザープロセスがread()でイベント取得]
    G --> H[FileSystemWatcher.Linuxがイベント解析]
    H --> I[Deletedイベント発火]
    I --> J[ユーザーイベントハンドラ実行]
```

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

### 参照テーブル一覧

該当なし（カーネルレベルの通知機構であり、データベースは使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| EBADF | 無効なinotifyファイルディスクリプタ | inotifyインスタンスを再作成 |
| EINVAL | read()バッファサイズが小さすぎる | バッファサイズを増加 |
| ENOMEM | カーネルメモリ不足 | システムリソースの確認 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（カーネルイベントはリトライ不可） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| キューサイズ上限 | /proc/sys/fs/inotify/max_queued_events（デフォルト16384） |
| 監視数上限 | /proc/sys/fs/inotify/max_user_watches |

### 配信時間帯

制限なし（リアルタイム配信）

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

- inotifyは監視対象ディレクトリへの読み取り権限が必要
- 削除されたファイル名のみが通知され、ファイル内容は含まれない
- 特権プロセスでない限り、自身がアクセス可能なディレクトリのみ監視可能

## 備考

- IN_DELETEは削除されたエントリの名前を提供するが、親ディレクトリのwdから相対パスを構築する必要がある
- .NETのFileSystemWatcherは内部でIN_DELETEを処理し、WatcherChangeTypes.Deletedとしてマネージドイベントを発火する
- 大量の削除操作が発生する場合、IN_Q_OVERFLOWに注意が必要

---

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

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

### 推奨読解順序

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

inotifyイベントの定義と.NET側での表現を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | pal_io.h | `src/native/libs/System.Native/pal_io.h` | 行328-344: NotifyEvents列挙型でPAL_IN_DELETE = 0x00000200を確認 |

**読解のコツ**: C言語のenumとC#のマネージド型のマッピングを意識する。PAL_プレフィックスはPlatform Abstraction Layerを示す。

#### Step 2: ネイティブ層を理解する

システムコールラッパーの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pal_io.c | `src/native/libs/System.Native/pal_io.c` | 行1476-1521: INotify関連関数（Init, AddWatch, RemoveWatch）の実装 |
| 2-2 | pal_io.c | `src/native/libs/System.Native/pal_io.c` | 行184-200: NotifyEventsの静的アサートでカーネル定数との一致を検証 |

**主要処理フロー**:
1. **行1476-1484**: SystemNative_INotifyInit - inotify_init1(IN_CLOEXEC)を呼び出し
2. **行1486-1501**: SystemNative_INotifyAddWatch - inotify_add_watchでマスクを設定
3. **行1503-1521**: SystemNative_INotifyRemoveWatch - 監視解除

#### Step 3: マネージド層（FileSystemWatcher）を理解する

.NETのFileSystemWatcherがinotifyイベントを処理する流れを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | 行516-773: ProcessEvent関数でIN_DELETEの処理 |
| 3-2 | FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | 行682-683: IN_DELETEケースでWatcherEvent.Deletedを生成 |
| 3-3 | FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | 行1245-1258: TranslateFilters関数でIN_DELETEフィルタ設定 |

**主要処理フロー**:
- **行519-523**: FileDirEventsマスクにIN_DELETEが含まれる
- **行682-683**: mask & IN_DELETEの場合、WatcherEvent.Deleted()を呼び出し
- **行1149-1165**: EmitEvent関数でDeletedイベントをFileSystemWatcherに通知

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

```
[カーネル] inotify subsystem
    |
    v
SystemNative_INotifyAddWatch (pal_io.c:1486)
    |
    v
FileSystemWatcher.Linux.INotify.AddOrUpdateWatchedDirectory (行218)
    |
    └─ Interop.Sys.INotifyAddWatch (P/Invoke)
           |
           v
ProcessEvents (行472)
    |
    ├─ TryReadEvent (行837) - イベント読み取り
    |
    └─ ProcessEvent (行516)
           |
           ├─ mask & IN_DELETE 判定 (行682)
           |
           └─ WatcherEvent.Deleted (行959)
                  |
                  v
              EmitEvent (行1125)
                  |
                  v
              FileSystemWatcher.Deleted イベント発火
```

### データフロー図

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

カーネルinotify        SystemNative_INotifyAddWatch      WatchedDirectory作成
イベントキュー    ───▶   (P/Invoke経由)             ───▶
    |                                                       |
    v                                                       v
struct inotify_event   TryReadEvent()                  NotifyEvent構造体
(wd, mask, name)  ───▶  (バッファから解析)          ───▶  (マネージド表現)
    |                                                       |
    v                                                       v
IN_DELETE検出      ───▶  ProcessEvent()              ───▶  WatcherEvent.Deleted
                         (イベント種別判定)                  |
                                                            v
                                                       EmitEvent()
                                                            |
                                                            v
                                                       FileSystemEventArgs
                                                            |
                                                            v
                                                       ユーザーハンドラ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pal_io.h | `src/native/libs/System.Native/pal_io.h` | ヘッダ | NotifyEvents列挙型定義 |
| pal_io.c | `src/native/libs/System.Native/pal_io.c` | ソース | inotifyシステムコールラッパー |
| FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | ソース | マネージドFileSystemWatcherのLinux実装 |
| FileSystemWatcher.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs` | ソース | FileSystemWatcher基底クラス |
