# 機能設計書 77-Pollハンドル初期化

## 概要

uv_poll_init()/uv_poll_init_socket()によりPollハンドルをFDまたはソケットで初期化する機能の設計書である。

### 本機能の処理概要

uv_poll_init()およびuv_poll_init_socket()は、ファイルディスクリプタまたはソケットを監視するためのPollハンドルを初期化する。Pollハンドルは、libuvのイベントループが提供するハンドル型の一つで、既存のファイルディスクリプタに対するI/Oイベント（読み取り可能、書き込み可能、切断、優先データ）の監視を可能にする。

**業務上の目的・背景**：libuvのストリームAPIを使用せずに、既存のファイルディスクリプタのI/Oイベントを監視する必要がある場合に使用する。例えば、サードパーティライブラリが管理するFD、特殊なデバイスファイル、epoll/kqueueの直接制御が必要なケースなどで利用される。libuvのイベントループとの統合を維持しつつ、低レベルなFD監視を実現する。

**機能の利用シーン**：
- サードパーティライブラリのFDをlibuvイベントループに統合
- 特殊なデバイスファイルの監視
- sysfsファイルの変更監視
- カスタムプロトコル実装でのFD監視

**主要な処理内容**：
1. FDの重複チェック（既に同じFDで別のwatcherが登録されていないか）
2. uv__io_check_fd()でFDの有効性を確認
3. FDをノンブロッキングモードに設定
4. uv__handle_init()でハンドル基本初期化
5. uv__io_init()でI/Owatcher初期化

**関連システム・外部連携**：OSのファイルディスクリプタ/ソケット。epoll/kqueue/IOCPバックエンドと連携。

**権限による制御**：対象FDへのアクセス権が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | Pollハンドル | 主機能 | uv_poll_init()/uv_poll_init_socket()によるPollハンドル初期化のAPI定義 |

## 機能種別

リソース初期化処理 - Pollハンドルの生成と初期設定

## 入力仕様

### 入力パラメータ

#### uv_poll_init()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| loop | uv_loop_t* | Yes | イベントループ | 初期化済みであること |
| handle | uv_poll_t* | Yes | 初期化するPollハンドル | 有効なメモリ領域 |
| fd | int | Yes | 監視するファイルディスクリプタ | 有効なFDであること |

#### uv_poll_init_socket()

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| loop | uv_loop_t* | Yes | イベントループ | 初期化済みであること |
| handle | uv_poll_t* | Yes | 初期化するPollハンドル | 有効なメモリ領域 |
| socket | uv_os_sock_t | Yes | 監視するソケット | 有効なソケットであること |

### 入力データソース

関数呼び出し時の引数として渡される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 成功時0、失敗時は負のエラーコード |
| handle->poll_cb | uv_poll_cb | NULLに初期化 |
| handle->io_watcher | uv__io_t | FDとコールバックで初期化 |

### 出力先

uv_poll_t構造体が初期化され、イベントループのハンドルキューに登録される。

## 処理フロー

### 処理シーケンス

```
uv_poll_init():
1. uv__fd_exists(loop, fd)で重複チェック
   └─ 既存ならUV_EEXIST返却
2. uv__io_check_fd(loop, fd)でFD有効性チェック
3. uv__nonblock(fd, 1)でノンブロッキングモード設定
   └─ IOCTLベースでENOTTYの場合はfcntlベースにフォールバック
4. uv__handle_init(loop, handle, UV_POLL)でハンドル初期化
5. uv__io_init(&handle->io_watcher, UV__POLL_IO, fd)
6. handle->poll_cb = NULL

uv_poll_init_socket():
1. uv_poll_init(loop, handle, socket)に委譲（Unixでは同一実装）
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{FD既存?}
    B -->|Yes| C[return UV_EEXIST]
    B -->|No| D[uv__io_check_fd]
    D --> E{有効?}
    E -->|No| F[return エラー]
    E -->|Yes| G[uv__nonblock fd, 1]
    G --> H{成功?}
    H -->|No ENOTTY| I[uv__nonblock_fcntl]
    H -->|成功| J[uv__handle_init]
    I --> J
    J --> K[uv__io_init]
    K --> L[poll_cb = NULL]
    L --> M[return 0]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-77-01 | FD重複防止 | 同一FDで複数のPollハンドルを作成できない | 常時 |
| BR-77-02 | ノンブロッキング必須 | 監視対象FDは自動的にノンブロッキングに設定される | 常時 |
| BR-77-03 | IOCTLフォールバック | ioctl(FIONBIO)がENOTTYの場合はfcntl(F_SETFL)にフォールバック | UV__NONBLOCK_IS_IOCTL定義時 |
| BR-77-04 | Unix同一実装 | Unixではuv_poll_init_socket()はuv_poll_init()に委譲される | Unix |

### 計算ロジック

特段の計算ロジックはない。

## データベース操作仕様

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EEXIST | 重複エラー | 同一FDが既に監視されている | 既存のハンドルを停止・クローズしてから再初期化 |
| UV_EBADF | パラメータエラー | 無効なFD | 有効なFDを指定する |
| UV_ENOTSOCK | パラメータエラー | ソケットでないFDでuv_poll_init_socket()を呼び出した（Windows） | uv_poll_init()を使用する |

### リトライ仕様

リトライは不要。

## トランザクション仕様

該当なし。

## パフォーマンス要件

初期化処理は軽量であり、特段の性能要件はない。

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

- 外部から渡されたFDをノンブロッキングに変更するため、呼び出し元への影響に注意

## 備考

- Windows版のuv_poll_init_socket()はWSASocketを使用した独自実装（src/win/poll.c L411以降）
- Pollハンドルは初期化後、uv_poll_start()で監視を開始する必要がある

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **L904-908**: uv_poll_s構造体。UV_HANDLE_FIELDS + poll_cb + UV_POLL_PRIVATE_FIELDS |
| 1-2 | uv.h | `include/uv.h` | **L910-915**: uv_poll_event列挙型。READABLE=1, WRITABLE=2, DISCONNECT=4, PRIORITIZED=8 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | poll.c | `src/unix/poll.c` | **L67-93**: uv_poll_init()の全実装 |
| 2-2 | poll.c | `src/unix/poll.c` | **L96-99**: uv_poll_init_socket() - uv_poll_init()への委譲 |

**主要処理フロー**:
1. **70-71行目**: uv__fd_exists(loop, fd)で重複チェック、UV_EEXIST返却
2. **73-75行目**: uv__io_check_fd(loop, fd)でFD有効性チェック
3. **80-84行目**: uv__nonblock()でノンブロッキング設定（ENOTTYフォールバック付き）
4. **89行目**: uv__handle_init(loop, handle, UV_POLL)
5. **90行目**: uv__io_init(&handle->io_watcher, UV__POLL_IO, fd)
6. **91行目**: handle->poll_cb = NULL

#### Step 3: I/Oコールバックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | poll.c | `src/unix/poll.c` | **L29-64**: uv__poll_io() - I/Oイベント発生時のコールバック。POLLINをUV_READABLEに変換等 |

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

```
uv_poll_init(loop, handle, fd)          [src/unix/poll.c L67]
    +-- uv__fd_exists(loop, fd)          [重複チェック]
    +-- uv__io_check_fd(loop, fd)        [FD有効性チェック]
    +-- uv__nonblock(fd, 1)              [ノンブロッキング設定]
    |   +-- uv__nonblock_fcntl()         [ENOTTYフォールバック]
    +-- uv__handle_init()                [ハンドル基本初期化]
    +-- uv__io_init()                    [I/Owatcher初期化]

uv_poll_init_socket(loop, handle, socket)  [src/unix/poll.c L96]
    +-- uv_poll_init(loop, handle, socket) [委譲]
```

### データフロー図

```
[入力]              [処理]                      [出力]
loop (ループ) ----> ハンドル初期化 -----------> handle (初期化済み)
fd (FD) ----------> ノンブロッキング設定 -----> io_watcher (FD登録)
                    ハンドルキュー登録 -------> poll_cb = NULL
                                        -----> 戻り値 (0 or エラー)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | uv_poll_t構造体・API宣言（L904-922） |
| poll.c | `src/unix/poll.c` | ソース | Unix版実装（L67-99） |
| poll.c | `src/win/poll.c` | ソース | Windows版実装（L406-511） |
