# 通知設計書 22-Interop.Sys.INotify (IN_Q_OVERFLOW)

## 概要

本ドキュメントは、Linux inotifyサブシステムにおけるIN_Q_OVERFLOW通知イベントの設計仕様を定義する。IN_Q_OVERFLOWは、inotifyイベントキューがオーバーフローし、一部のイベントが失われた際にカーネルから発生する重要なエラー通知である。

### 本通知の処理概要

IN_Q_OVERFLOW通知は、inotifyのイベントキューが上限に達し、新しいイベントを格納できなくなった場合に発生する緊急通知である。この通知を受け取ったアプリケーションは、イベントの損失が発生したことを認識し、適切なリカバリ処理を実行する必要がある。

**業務上の目的・背景**：ファイルシステム監視において、大量のファイル操作（一括削除、大規模なビルド処理など）が短時間に発生すると、inotifyのカーネルキューが溢れる可能性がある。この状況を検知できないと、アプリケーションは一部のファイル変更を見逃し、データ不整合やキャッシュの不一致が発生する。IN_Q_OVERFLOWはこのような状況を検知し、アプリケーションに再同期の機会を与えるための重要な通知である。

**通知の送信タイミング**：inotifyイベントキューがmax_queued_events（/proc/sys/fs/inotify/max_queued_events）で定義された上限に達し、新しいイベントをキューに追加できなくなった時点でカーネルから発生する。

**通知の受信者**：オーバーフローが発生したinotifyインスタンスのファイルディスクリプタを監視しているプロセス。.NETランタイムでは、FileSystemWatcherクラスがこの通知を受信し、InternalBufferOverflowExceptionとしてErrorイベントを発火する。

**通知内容の概要**：IN_Q_OVERFLOWイベントはwd（監視ディスクリプタ）が-1に設定され、特定のファイルやディレクトリに関連付けられない。maskフィールドにIN_Q_OVERFLOW（0x00004000）が設定される。

**期待されるアクション**：受信者はキャッシュの無効化、監視対象ディレクトリの再スキャン、またはアプリケーションの再起動などのリカバリ処理を実行する。.NETのFileSystemWatcherはErrorイベントを発火し、ユーザーに通知する。

## 通知種別

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

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（カーネルからユーザー空間へのエラー通知） |
| 優先度 | 高（イベント損失を示す重要な通知） |
| リトライ | 無（一度発生したオーバーフローは取り消せない） |

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

オーバーフローが発生したinotifyインスタンスを所有するプロセスに対してのみ通知が送信される。他のプロセスが同一ディレクトリを監視していても、それぞれのinotifyインスタンスは独立したキューを持つため、オーバーフローは個別に発生する。

## 通知テンプレート

### イベント構造体

```c
struct inotify_event {
    int      wd;       // -1（特定のディレクトリに関連しない）
    uint32_t mask;     // IN_Q_OVERFLOW = 0x00004000
    uint32_t cookie;   // 0（未使用）
    uint32_t len;      // 0（名前なし）
    char     name[];   // 空（名前フィールドなし）
};
```

### 本文テンプレート

```
イベント: IN_Q_OVERFLOW
監視ディスクリプタ: -1 (グローバルイベント)
イベントキューがオーバーフローしました。
一部のファイルシステムイベントが失われた可能性があります。
```

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| wd | 監視ディスクリプタ（常に-1） | カーネル固定値 | Yes |
| mask | イベントマスク（IN_Q_OVERFLOW） | カーネル設定値 | Yes |
| cookie | イベント関連付けID（常に0） | カーネル設定値 | Yes |
| len | 名前の長さ（常に0） | カーネル設定値 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| キューオーバーフロー | イベントキュー満杯 | キュー内イベント数 >= max_queued_events | 新規イベント追加不可時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| なし | オーバーフローが発生した場合、必ず通知される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ファイルシステムイベント発生] --> B[カーネルinotifyキュー確認]
    B -->|キュー空きあり| C[イベントをキューに追加]
    B -->|キュー満杯| D[IN_Q_OVERFLOWイベント生成]
    D --> E[オーバーフローイベントをキューに追加]
    E --> F[新規イベントは破棄]
    F --> G[read()でオーバーフロー検出]
    G --> H[FileSystemWatcher.ProcessEvent]
    H --> I[InternalBufferOverflowException生成]
    I --> J[Error イベント発火]
    J --> K[inotify停止・再起動処理]
```

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

### 参照テーブル一覧

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

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| InternalBufferOverflowException | IN_Q_OVERFLOW検出時 | FileSystemWatcher再起動、ディレクトリ再スキャン |
| イベント損失 | オーバーフロー発生時 | キャッシュ無効化、再同期処理 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | FileSystemWatcherは自動再起動を試みる |
| リトライ間隔 | 即座に再起動 |
| リトライ対象エラー | IN_Q_OVERFLOW |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| キューサイズ上限 | /proc/sys/fs/inotify/max_queued_events（デフォルト16384） |
| オーバーフロー通知 | キュー上限到達時に1回のみ発生 |

### 配信時間帯

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

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

- IN_Q_OVERFLOWは意図的に大量のファイル操作を行うことで誘発可能（DoS攻撃の一種）
- オーバーフローによりセキュリティ監視イベントが失われる可能性がある
- max_queued_eventsの適切な設定が重要

## 備考

- オーバーフローは一度発生すると、その間に発生したイベントは永久に失われる
- .NETのFileSystemWatcherはオーバーフロー後に自動的に再起動を試みる
- InternalBufferSizeプロパティはWindowsでのみ有効であり、Linuxではmax_queued_eventsで制御される

---

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

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

### 推奨読解順序

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

IN_Q_OVERFLOWの定義値を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | pal_io.h | `src/native/libs/System.Native/pal_io.h` | 行338: PAL_IN_Q_OVERFLOW = 0x00004000の定義 |

**読解のコツ**: IN_Q_OVERFLOWは他のイベントマスクと異なり、特定のファイル/ディレクトリに関連しないグローバルイベントである。

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

カーネル定数との一致検証を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pal_io.c | `src/native/libs/System.Native/pal_io.c` | 行192: c_static_assert(PAL_IN_Q_OVERFLOW == IN_Q_OVERFLOW) |

**主要処理フロー**:
- **行192**: 静的アサートでPAL定数とカーネル定数の一致を検証

#### Step 3: マネージド層でのオーバーフロー処理を理解する

FileSystemWatcherがIN_Q_OVERFLOWを処理する流れを追う。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | 行535-547: IN_Q_OVERFLOW検出とエラー処理 |
| 3-2 | FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | 行1136-1146: EmitEventでInternalBufferOverflowException処理 |

**主要処理フロー**:
- **行535**: `(mask & Interop.Sys.NotifyEvents.IN_Q_OVERFLOW) != 0` でオーバーフロー検出
- **行537-545**: StopINotify()を呼び出し、全watcherにエラーを通知
- **行543-544**: CreateBufferOverflowException()でエラー生成、QueueError()で配信
- **行1140-1146**: InternalBufferOverflowExceptionの場合、FileSystemWatcher.Restart()を呼び出し

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

```
[カーネル] inotify queue overflow
    |
    v
IN_Q_OVERFLOW イベント生成 (wd = -1)
    |
    v
ProcessEvent (行516)
    |
    ├─ (mask & IN_Q_OVERFLOW) != 0 判定 (行535)
    |
    └─ オーバーフロー処理 (行537-546)
           |
           ├─ StopINotify() (行539)
           |
           └─ foreach (watcher in _watchers) (行541)
                  |
                  └─ watcher.QueueError(CreateBufferOverflowException()) (行543-544)
                         |
                         v
                     EmitEvent (行1125)
                         |
                         ├─ @event.Type == WatcherEvent.ErrorType 判定 (行1135)
                         |
                         └─ fsw.OnError(new ErrorEventArgs(@event.Exception)) (行1136)
                                |
                                v
                            @event.Exception is InternalBufferOverflowException 判定 (行1140)
                                |
                                └─ fsw.Restart() (行1144)
```

### データフロー図

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

カーネルキュー満杯    ───▶  IN_Q_OVERFLOW生成          ───▶  inotify_event (wd=-1)
                            (カーネル内部)
    |                                                            |
    v                                                            v
新規イベント破棄       ───▶  ProcessEvent()              ───▶  オーバーフロー検出
                            (行535-546)                          |
                                                                 v
                                                            StopINotify()
                                                                 |
                                                                 v
                                                            QueueError()
                                                                 |
                                                                 v
                                                            EmitEvent()
                                                                 |
                                                                 v
                                                            ErrorEventArgs
                                                                 |
                                                                 v
                                                            fsw.Restart()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pal_io.h | `src/native/libs/System.Native/pal_io.h` | ヘッダ | PAL_IN_Q_OVERFLOW定義（行338） |
| pal_io.c | `src/native/libs/System.Native/pal_io.c` | ソース | 静的アサート（行192） |
| FileSystemWatcher.Linux.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.Linux.cs` | ソース | オーバーフロー検出・処理（行535-547, 1136-1146） |
| FileSystemWatcher.cs | `src/libraries/System.IO.FileSystem.Watcher/src/System/IO/FileSystemWatcher.cs` | ソース | Errorイベント定義 |
