# 機能設計書 153-システム稼働時間取得

## 概要

本ドキュメントは、libuvライブラリにおけるuv_uptime()関数によるシステム稼働時間取得機能の設計を記述する。

### 本機能の処理概要

uv_uptime()関数は、システムが起動してからの経過時間（秒単位、double型）をクロスプラットフォームで取得する機能を提供する。

**業務上の目的・背景**：システム監視、稼働率計算、再起動検知など、システムの稼働時間を把握する必要がある場面は多い。各プラットフォームではsysctl、/proc/uptime、clock_gettime(CLOCK_BOOTTIME)、GetTickCount64()など異なる方法で稼働時間を取得するが、libuvはこれらを統一的なAPIで提供する。

**機能の利用シーン**：サーバー稼働時間の監視・ログ出力、ヘルスチェックエンドポイントでのuptime報告、システム再起動の検知、パフォーマンスレポートの一部としての稼働情報表示などに利用される。

**主要な処理内容**：
1. プラットフォーム固有のAPIを使用してブート時刻または稼働時間を取得
2. 必要に応じて現在時刻とブート時刻の差分を計算
3. 結果をdouble型で呼び出し元に返す

**関連システム・外部連携**：
- macOS/BSD: sysctl(CTL_KERN, KERN_BOOTTIME)
- Linux: /proc/uptime またはclock_gettime(CLOCK_BOOTTIME)
- Windows: GetTickCount64()

**権限による制御**：特別な権限は不要。一般ユーザー権限で実行可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 29 | その他ユーティリティ | 主機能 | uv_uptime()によるシステム稼働時間取得のAPI定義 |

## 機能種別

データ取得処理（システム稼働時間の読み取り）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| uptime | double* | Yes | 稼働時間（秒）を格納するポインタ | 暗黙的に有効なポインタが必要 |

### 入力データソース

OSカーネルからシステムブート時刻または稼働時間を取得する。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| *uptime | double | システム稼働時間（秒単位） |
| 戻り値 | int | 成功時0、失敗時負のエラーコード |

### 出力先

呼び出し元が提供するdouble変数に書き込む。

## 処理フロー

### 処理シーケンス

```
1. [macOS/BSD] sysctl(KERN_BOOTTIME)でブート時刻を取得
   ├─ 失敗時はerrnoをlibuvエラーに変換
   ├─ time(NULL)で現在時刻を取得
   └─ *uptime = now - info.tv_sec
2. [Linux] /proc/uptimeファイルを読み取り
   ├─ 成功: sscanf()で数値をパース
   └─ 失敗: clock_gettime(CLOCK_BOOTTIME)にフォールバック
3. [Windows] GetTickCount64()で稼働時間（ミリ秒）を取得
   └─ *uptime = GetTickCount64() / 1000.0
4. 正常完了（0を返す）
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{プラットフォーム}
    B -->|macOS/BSD| C[sysctl KERN_BOOTTIME]
    B -->|Linux| D[/proc/uptime 読み取り]
    B -->|Windows| E[GetTickCount64]
    C --> F{sysctl成功?}
    F -->|No| G[return UV__ERR errno]
    F -->|Yes| H[now = time NULL]
    H --> I[*uptime = now - boottime]
    D --> J{読み取り成功?}
    J -->|Yes| K[sscanf でパース]
    J -->|No| L[clock_gettime CLOCK_BOOTTIME]
    L --> M{成功?}
    M -->|No| N[return UV__ERR errno]
    M -->|Yes| O[*uptime = tv_sec]
    K --> P[return 0]
    I --> P
    O --> P
    E --> Q[*uptime = ticks / 1000.0]
    Q --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-153-01 | Linuxフォールバック | /proc/uptimeの読み取り失敗時はCLOCK_BOOTTIMEにフォールバック | Linuxプラットフォーム |
| BR-153-02 | コンテナ対応 | OpenVZ等のコンテナ環境ではCLOCK_BOOTTIMEが正しい値を返さない場合がある | Linux コンテナ環境 |
| BR-153-03 | 単位変換 | WindowsではGetTickCount64()の戻り値（ミリ秒）を1000で割って秒に変換 | Windowsプラットフォーム |

### 計算ロジック

- macOS/BSD: `*uptime = time(NULL) - boottime.tv_sec`
- Linux: `/proc/uptime`の第1フィールド、またはCLOCK_BOOTTIMEのtv_sec
- Windows: `GetTickCount64() / 1000.0`

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

該当なし（データベース操作は行わない）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV__ERR(errno) | システムエラー | sysctl()またはclock_gettime()失敗 | OSの状態を確認 |

### リトライ仕様

リトライは不要。

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

該当なし。

## パフォーマンス要件

軽量な処理であり即座に完了する。Linuxでは/proc/uptimeの読み取りを優先し、ファイルI/Oのオーバーヘッドがあるが無視できるレベル。

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

システム稼働時間は一般的に機密情報ではないが、攻撃者がシステムの再起動タイミングを推測する材料になる可能性がある。

## 備考

- Linuxで/proc/uptimeを優先する理由は、ソースコードコメントによると「OpenVZ等のコンテナ環境でclock_gettime()が正しい結果を返さない場合がある」ため。
- 各プラットフォーム（AIX, FreeBSD, NetBSD, OpenBSD, Haiku, QNX等）にそれぞれ固有の実装がある。

---

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

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

### 推奨読解順序

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

uv_uptime()は単純なdouble*を出力とするため、特別なデータ構造はない。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | uv_uptime()のAPI宣言（1287行目） |

**読解のコツ**: `UV_EXTERN int uv_uptime(double* uptime);` - 戻り値はエラーコード、実際の稼働時間は引数のポインタ経由で返す。

#### Step 2: macOS/BSD実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | darwin.c | `src/unix/darwin.c` | macOS版uv_uptime()実装 |

**主要処理フロー**:
- **175行目**: 関数エントリーポイント
- **179行目**: sysctl引数 `{CTL_KERN, KERN_BOOTTIME}` 定義
- **181行目**: sysctl()呼び出しでブート時刻を取得
- **184行目**: `time(NULL)`で現在時刻取得
- **185行目**: `*uptime = now - info.tv_sec` で稼働時間計算

#### Step 3: Linux実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | linux.c | `src/unix/linux.c` | Linux版uv_uptime()実装 |

**主要処理フロー**:
- **1675行目**: 関数エントリーポイント
- **1679-1681行目**: コメント - /proc/uptimeを優先する理由（コンテナ対応）
- **1683-1685行目**: `/proc/uptime`からの読み取りとsscanfパース
- **1687-1688行目**: フォールバックとしてclock_gettime(CLOCK_BOOTTIME)
- **1690行目**: `*uptime = now.tv_sec`

#### Step 4: Windows実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | util.c | `src/win/util.c` | Windows版uv_uptime()実装 |

**主要処理フロー**:
- **502行目**: 関数エントリーポイント
- **503行目**: `*uptime = GetTickCount64() / 1000.0;` - ミリ秒を秒に変換

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

```
uv_uptime(uptime)
    |
    +-- [macOS/BSD] sysctl(CTL_KERN, KERN_BOOTTIME)
    |       +-- time(NULL)
    |       +-- 差分計算
    |
    +-- [Linux] uv__slurp("/proc/uptime")
    |       +-- sscanf(buf, "%lf", uptime)
    |       +-- [フォールバック] clock_gettime(CLOCK_BOOTTIME)
    |
    +-- [Windows] GetTickCount64()
            +-- ミリ秒→秒変換
```

### データフロー図

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

uptime (double*) ----> uv_uptime()                 ---> *uptime (秒)
                       |                                 戻り値: 0 or error
                       +-- sysctl / /proc/uptime /
                           GetTickCount64()
                           (プラットフォーム固有API)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | API宣言 |
| darwin.c | `src/unix/darwin.c` | ソース | macOS版uv_uptime()実装 |
| linux.c | `src/unix/linux.c` | ソース | Linux版uv_uptime()実装 |
| freebsd.c | `src/unix/freebsd.c` | ソース | FreeBSD版uv_uptime()実装 |
| netbsd.c | `src/unix/netbsd.c` | ソース | NetBSD版uv_uptime()実装 |
| openbsd.c | `src/unix/openbsd.c` | ソース | OpenBSD版uv_uptime()実装 |
| aix.c | `src/unix/aix.c` | ソース | AIX版uv_uptime()実装 |
| sunos.c | `src/unix/sunos.c` | ソース | Solaris版uv_uptime()実装 |
| util.c | `src/win/util.c` | ソース | Windows版uv_uptime()実装 |
