# 帳票設計書 2-アクティブハンドル一覧出力

## 概要

本ドキュメントは、libuvライブラリにおける `uv_print_active_handles()` API関数の帳票設計書である。イベントループ内でアクティブ状態のハンドルのみを抽出し、参照状態・アクティブ状態・内部フラグ・ハンドル型・アドレスをFILEストリームに出力するデバッグ用帳票について定義する。

### 本帳票の処理概要

本帳票は、libuvイベントループ内に登録されているハンドルのうち、アクティブ状態（UV_HANDLE_ACTIVEフラグがON）のもののみをフィルタリングして出力する機能を提供する。

**業務上の目的・背景**：イベントループが停止しない原因調査において、全ハンドルではなくアクティブなハンドルのみに絞り込んで確認したい場合に使用する。アクティブなハンドルはイベントループの実行を維持する原因となるため、ループが`uv_run()`から返らない問題のデバッグに直接的に役立つ。No.1「全ハンドル一覧出力」と同一の内部関数を使用するが、フィルタリング条件が異なる。

**帳票の利用シーン**：`uv_run()`が返らない場合の原因調査、アプリケーション終了前の残存アクティブハンドルの確認、イベントループのライフサイクル管理に利用される。

**主要な出力内容**：
1. 参照状態フラグ（R/-）
2. アクティブ状態フラグ（A/-）：本帳票ではフィルタ済みのため常にA
3. 内部フラグ（I/-）
4. ハンドル型名
5. ハンドルのメモリアドレス

**帳票の出力タイミング**：プログラマが `uv_print_active_handles(loop, stream)` を呼び出した時点で同期的に出力される。

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

## 帳票種別

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

## 利用画面

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

## 出力形式

### 基本仕様

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

### 出力フォーマット

No.1「全ハンドル一覧出力」と同一フォーマット。ただしアクティブなハンドルのみ出力される。

```
[RAI] type     address
```

## 帳票レイアウト

### レイアウト概要

No.1と同一の行指向フラットテキスト出力。ただしアクティブ状態のハンドルのみが出力対象となる。

### 明細部

| 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 | 文字列（左寄せ） | 8文字 |
| 5 | アドレス | ハンドルのメモリアドレス | (void*)h | %p形式 | 可変 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| イベントループ | 出力対象のイベントループ（NULLの場合はデフォルトループ使用） | No |
| 出力ストリーム | FILE*ストリーム（NULLの場合はstderr使用） | No |
| アクティブフィルタ | UV_HANDLE_ACTIVEフラグがONのハンドルのみ出力 | Yes（内部固定条件） |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | handle_queueの登録順 | 登録順 |

### 改ページ条件

改ページ条件は存在しない。

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

No.1と同一。メモリ上のuv_loop_t.handle_queueとuv_handle_tを参照する。

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| アクティブ判定 | `uv__is_active(h)` → `(h->flags & UV_HANDLE_ACTIVE) != 0` | N/A | falseの場合はcontinueでスキップ |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[uv_print_active_handles呼び出し] --> B[uv__print_handles loop 1 stream]
    B --> C{streamがNULL?}
    C -->|Yes| D[stream = stderr]
    C -->|No| E{loopがNULL?}
    D --> E
    E -->|Yes| F[loop = uv_default_loop]
    E -->|No| G[handle_queueを走査開始]
    F --> G
    G --> H{次のハンドルあり?}
    H -->|Yes| I{アクティブか?}
    I -->|No| H
    I -->|Yes| J[フラグ・型名・アドレスをfprintfで出力]
    J --> H
    H -->|No| K[終了]
```

## エラー処理

### エラーケース一覧

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

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 全ハンドル走査、アクティブのみ出力 |
| 目標出力時間 | ミリ秒オーダー（同期I/O） |
| 同時出力数上限 | N/A |

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

No.1と同様。メモリアドレスを含むデバッグ情報のため本番環境での使用は非推奨。

## 備考

- No.1「全ハンドル一覧出力」と同一の内部関数 `uv__print_handles()` を `only_active=1` で呼び出す
- アクティブ判定は `uv__is_active(h)` マクロ（uv-common.h:274行目）で行われる

---

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

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

### 推奨読解順序

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

No.1と同一のデータ構造を使用する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | uv_handle_t構造体のflags, typeメンバ |
| 1-2 | uv-common.h | `src/uv-common.h` | UV_HANDLE_ACTIVEフラグ（0x00000004）の定義（84行目） |
| 1-3 | uv-common.h | `src/uv-common.h` | uv__is_active()マクロの定義（274行目） |

**読解のコツ**: `only_active`パラメータが1の場合、`uv__is_active(h)`がfalseのハンドルはcontinueでスキップされる点がNo.1との唯一の差異である。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv-common.c | `src/uv-common.c` | uv_print_active_handles()（618-620行目）がuv__print_handles(loop, 1, stream)を呼び出すことを確認 |

**主要処理フロー**:
1. **618行目**: `uv_print_active_handles()` が呼び出される
2. **619行目**: 内部関数 `uv__print_handles(loop, 1, stream)` に委譲（only_active=1）

#### Step 3: フィルタリングロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | uv-common.c | `src/uv-common.c` | uv__print_handles()の592-593行目で `if (only_active && !uv__is_active(h)) continue;` によるフィルタリングを確認 |

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

```
uv_print_active_handles(loop, stream)        [src/uv-common.c:618]
    |
    +-- uv__print_handles(loop, 1, stream)   [src/uv-common.c:573]
            |
            +-- uv__is_active(h)             [src/uv-common.h:274]  ※フィルタ判定
            |
            +-- fprintf(stream, ...)         [標準ライブラリ]       ※アクティブなハンドルのみ
```

### データフロー図

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

uv_loop_t                     uv__print_handles()              FILE*ストリーム
  .handle_queue --------+     (only_active=1)
                        |
uv_handle_t             +---> キュー走査 ---> アクティブ判定 --> fprintf出力
  .flags                      |               (非アクティブ     "[RAI] type   addr\n"
  .type                       |                はスキップ)
                              +---> 次のハンドル...
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | API宣言 |
| uv-common.h | `src/uv-common.h` | 内部ヘッダ | フラグ定数、uv__is_active()マクロ |
| uv-common.c | `src/uv-common.c` | ソース | uv_print_active_handles()およびuv__print_handles()実装 |
| queue.h | `src/queue.h` | 内部ヘッダ | キュー操作マクロ |
