# 帳票設計書 1-全ハンドル一覧出力

## 概要

本ドキュメントは、libuvライブラリにおける `uv_print_all_handles()` API関数の帳票設計書である。イベントループに登録されている全ハンドルの情報をFILEストリームに出力するデバッグ用帳票について、出力形式・処理仕様・データ構造を定義する。

### 本帳票の処理概要

本帳票は、libuvイベントループ内に登録されている全てのハンドルの状態情報を、指定されたFILEストリームに一行一ハンドルで出力する機能を提供する。

**業務上の目的・背景**：libuvベースのアプリケーション開発・運用において、イベントループに登録されたハンドルの状態を一覧的に把握することは、リソースリーク（ハンドルのクローズ忘れ）やイベントループの停止不能（未解放ハンドルの残存）といった問題のデバッグに不可欠である。本帳票はこのような問題解析を迅速に行うためのデバッグ情報出力機能として設計されている。

**帳票の利用シーン**：開発時のデバッグセッションにおいて、イベントループが期待通りに終了しない場合や、メモリリークが疑われる場合に利用される。また、アプリケーションのシャットダウン前に残存ハンドルを確認する運用チェックにも活用できる。

**主要な出力内容**：
1. 参照状態フラグ（R/-）：ハンドルがイベントループを参照しているかどうか
2. アクティブ状態フラグ（A/-）：ハンドルがアクティブ（動作中）かどうか
3. 内部フラグ（I/-）：ハンドルがlibuv内部用かどうか
4. ハンドル型名（async, check, fs_event, idle, pipe, poll, prepare, process, stream, tcp, timer, tty, udp, signal等）
5. ハンドルのメモリアドレス（ポインタ値）

**帳票の出力タイミング**：プログラマが任意のタイミングで `uv_print_all_handles(loop, stream)` を呼び出した時点で即座に出力される。非同期ではなく同期的に処理される。

**帳票の利用者**：libuvベースのアプリケーション開発者、デバッグ担当者、品質保証エンジニア。

## 帳票種別

デバッグ一覧表（テキスト形式のストリーム出力）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | N/A（C API呼び出し） | N/A | `uv_print_all_handles(loop, stream)` 関数呼び出し |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（FILE*ストリーム出力） |
| 用紙サイズ | N/A（ストリーム出力） |
| 向き | N/A |
| ファイル名 | N/A（stdout/stderrまたは任意のFILE*ストリームに出力） |
| 出力方法 | FILE*ストリームへのfprintf出力 |
| 文字コード | ASCII |

### 出力フォーマット

各ハンドルにつき1行、以下の固定フォーマットで出力される：

```
[RAI] type     address
```

- 位置1（R/-）：UV_HANDLE_REFフラグの有無
- 位置2（A/-）：UV_HANDLE_ACTIVEフラグの有無
- 位置3（I/-）：UV_HANDLE_INTERNALフラグの有無
- type：ハンドル型名（左寄せ8文字幅）
- address：ハンドルのポインタアドレス（%p形式）

出力例：
```
[R--] timer    0x7ffee3c04a00
[RA-] tcp      0x7ffee3c04b20
[-A-] idle     0x7ffee3c04c40
```

## 帳票レイアウト

### レイアウト概要

本帳票はヘッダー・フッターを持たない行指向のフラットなテキスト出力である。各行が1つのハンドル情報に対応し、ループ内のhandle_queueを走査して全ハンドルを順次出力する。

```
┌──────────────────────────────────────────────────┐
│ [フラグ3文字] 型名(8文字)  アドレス              │  ← 1行目：ハンドル1
│ [フラグ3文字] 型名(8文字)  アドレス              │  ← 2行目：ハンドル2
│ ...                                              │
│ [フラグ3文字] 型名(8文字)  アドレス              │  ← N行目：ハンドルN
└──────────────────────────────────────────────────┘
```

### 明細部

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | 参照フラグ | ハンドルがループを参照しているか | h->flags & UV_HANDLE_REF | R/- | 1文字 |
| 2 | アクティブフラグ | ハンドルがアクティブか | h->flags & UV_HANDLE_ACTIVE | A/- | 1文字 |
| 3 | 内部フラグ | ハンドルがlibuv内部用か | h->flags & UV_HANDLE_INTERNAL | I/- | 1文字 |
| 4 | ハンドル型名 | ハンドルの種別 | h->type（UV_HANDLE_TYPE_MAPで変換） | 文字列（左寄せ） | 8文字 |
| 5 | アドレス | ハンドルのメモリアドレス | (void*)h | %p形式 | 可変 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| イベントループ | 出力対象のイベントループ（NULLの場合はデフォルトループ使用） | No |
| 出力ストリーム | FILE*ストリーム（NULLの場合はstderr使用） | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | handle_queueの登録順 | 登録順（キュー順序） |

### 改ページ条件

改ページ条件は存在しない（連続テキスト出力）。

## データベース参照仕様

### 参照テーブル一覧

本帳票はデータベースを参照しない。メモリ上のデータ構造を直接参照する。

| テーブル名（データ構造） | 用途 | 結合条件 |
|-----------|------|---------|
| uv_loop_t.handle_queue | ハンドルキューの走査 | N/A |
| uv_handle_t | 各ハンドルの情報取得 | handle_queueメンバ経由 |

### テーブル別参照項目詳細

#### uv_handle_t

| 参照項目（フィールド名） | 帳票項目との対応 | 取得条件 | 備考 |
|-------------------|----------------|---------|------|
| flags | 参照・アクティブ・内部フラグ | ビットマスク演算 | UV_HANDLE_REF=0x08, UV_HANDLE_ACTIVE=0x04, UV_HANDLE_INTERNAL=0x10 |
| type | ハンドル型名 | UV_HANDLE_TYPE_MAPマクロで文字列変換 | 未知の型は"<unknown>"と表示 |
| (void*)h | アドレス | ポインタ値をそのまま使用 | fprintf %p形式 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| 参照フラグ表示文字 | `"R-"[!(h->flags & UV_HANDLE_REF)]` | N/A | フラグがONなら'R'、OFFなら'-' |
| アクティブフラグ表示文字 | `"A-"[!(h->flags & UV_HANDLE_ACTIVE)]` | N/A | フラグがONなら'A'、OFFなら'-' |
| 内部フラグ表示文字 | `"I-"[!(h->flags & UV_HANDLE_INTERNAL)]` | N/A | フラグがONなら'I'、OFFなら'-' |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[uv_print_all_handles呼び出し] --> B{streamがNULL?}
    B -->|Yes| C[stream = stderr]
    B -->|No| D{loopがNULL?}
    C --> D
    D -->|Yes| E[loop = uv_default_loop]
    D -->|No| F[handle_queueを走査開始]
    E --> G{default_loopがNULL?}
    G -->|Yes| H[エラーメッセージ出力して終了]
    G -->|No| F
    F --> I{次のハンドルあり?}
    I -->|Yes| J[フラグ・型名・アドレスをfprintfで出力]
    J --> I
    I -->|No| K[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| デフォルトループ取得失敗 | loop==NULLかつuv_default_loop()がNULLを返した場合 | "uv_default_loop() failed\n" | stderrにメッセージ出力後、処理を終了 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数件〜数千件のハンドル |
| 目標出力時間 | ミリ秒オーダー（同期I/O） |
| 同時出力数上限 | N/A（シングルスレッドでの同期処理） |

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

本帳票はメモリアドレスを含むデバッグ情報を出力するため、本番環境での使用は推奨されない。ASLR（アドレス空間レイアウトランダム化）を迂回する情報漏洩のリスクがある。デバッグビルドまたは開発環境に限定して使用すべきである。公式ドキュメントでも「API/ABI stability guaranteed」ではないと明記されている。

## 備考

- 本関数はデバッグ用途であり、安定APIではない（uv.hのコメントに "Helpers for ad hoc debugging, no API/ABI stability guaranteed." と明記）
- No.2「アクティブハンドル一覧出力」と同一の内部関数 `uv__print_handles()` を使用し、`only_active` パラメータの違いで挙動を切り替える
- UV_HANDLE_INTERNALフラグが設定されたハンドルも出力対象に含まれる（No.2のアクティブ版と異なり、フィルタリングなし）

---

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

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

### 推奨読解順序

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

まず、ハンドルとイベントループのデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | uv_handle_t構造体（463-481行目）のフィールド定義、特にflags, type, handle_queueメンバを理解する |
| 1-2 | uv.h | `include/uv.h` | uv_loop_t構造体（1941-1956行目）のhandle_queueメンバがハンドルのリンクリストのルートであることを理解する |
| 1-3 | uv.h | `include/uv.h` | UV_HANDLE_TYPE_MAPマクロ（161-177行目）が全ハンドル型の列挙を定義していることを確認する |
| 1-4 | uv-common.h | `src/uv-common.h` | ハンドルフラグ定数（80-141行目）、特にUV_HANDLE_CLOSING, UV_HANDLE_ACTIVE, UV_HANDLE_REF, UV_HANDLE_INTERNALの値を確認する |

**読解のコツ**: UV_HANDLE_FIELDSマクロ（463-476行目）はuv_handle_t以外のハンドル型（tcp, udp等）でも共通で使用される基底フィールド群である。handle_queueフィールドはuv__queue型の双方向リンクリストのノードとして機能する。

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

処理の起点となるAPI関数と内部実装関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv.h | `include/uv.h` | uv_print_all_handles()のAPI宣言（501行目）を確認する |
| 2-2 | uv-common.c | `src/uv-common.c` | uv_print_all_handles()の実装（613-615行目）を確認し、uv__print_handles(loop, 0, stream)を呼び出していることを理解する |

**主要処理フロー**:
1. **613行目**: `uv_print_all_handles()` が呼び出される
2. **614行目**: 内部関数 `uv__print_handles(loop, 0, stream)` に委譲（only_active=0で全ハンドル出力）

#### Step 3: 内部実装の詳細を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | uv-common.c | `src/uv-common.c` | uv__print_handles()関数（573-610行目）の全体を読む。stream/loopのNULLチェック、キュー走査、フラグ判定、fprintf出力の流れを理解する |

**主要処理フロー**:
- **578-579行目**: streamがNULLならstderrをデフォルトとして使用
- **581-587行目**: loopがNULLならuv_default_loop()を使用（失敗時はエラーメッセージ出力）
- **589行目**: uv__queue_foreach()マクロでhandle_queueを走査開始
- **590行目**: uv__queue_data()マクロでキューノードからuv_handle_tポインタを取得
- **595-600行目**: UV_HANDLE_TYPE_MAPマクロを使ったswitch文でハンドル型名を文字列に変換
- **602-608行目**: fprintf()で `[RAI] type address` 形式の出力を生成

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

```
uv_print_all_handles(loop, stream)           [src/uv-common.c:613]
    |
    +-- uv__print_handles(loop, 0, stream)   [src/uv-common.c:573]
            |
            +-- uv_default_loop()            [src/uv-common.c:850]  ※loopがNULLの場合のみ
            |
            +-- uv__queue_foreach()          [src/queue.h]          ※handle_queueを走査
            |       |
            |       +-- uv__queue_data()     [src/queue.h]          ※キューノードからハンドルポインタ取得
            |
            +-- fprintf(stream, ...)         [標準ライブラリ]       ※1ハンドルにつき1回呼び出し
```

### データフロー図

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

uv_loop_t                     uv__print_handles()              FILE*ストリーム
  .handle_queue --------+     573-610行目                      (stdout/stderr/ファイル)
                        |
uv_handle_t             +---> キュー走査 -----> フラグ判定 ---> fprintf出力
  .flags                      |                  型名変換       "[RAI] type   addr\n"
  .type                       |                  アドレス取得
  .handle_queue               +---> 次のハンドル...
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | API宣言、データ構造定義、UV_HANDLE_TYPE_MAPマクロ定義 |
| uv-common.h | `src/uv-common.h` | 内部ヘッダ | ハンドルフラグ定数定義、内部マクロ定義 |
| uv-common.c | `src/uv-common.c` | ソース | uv_print_all_handles()およびuv__print_handles()の実装 |
| queue.h | `src/queue.h` | 内部ヘッダ | uv__queue_foreach、uv__queue_dataマクロ定義 |
