# 機能設計書 63-スナップショット作成・管理

## 概要

本ドキュメントは、OpenSearchのスナップショット作成・管理機能に関する機能設計書である。本機能はインデックスのスナップショット（バックアップ）を作成・一覧表示・削除・クローンする機能を提供し、SnapshotsServiceクラスを中心に実装されている。

### 本機能の処理概要

**業務上の目的・背景**：データのバックアップとリストアはデータベース運用において不可欠である。スナップショットはインデックスの特定時点のコピーを作成し、データ損失やクラスタ障害からの復旧を可能にする。増分スナップショットにより、効率的なバックアップ運用を実現する。

**機能の利用シーン**：定期的なバックアップ、データセンター間のデータ移行、本番環境からテスト環境へのデータコピー、障害復旧等に利用される。

**主要な処理内容**：
1. スナップショットの作成（CreateSnapshotRequest処理）
2. スナップショットの一覧取得
3. スナップショットの削除
4. スナップショットのクローン（同一リポジトリ内でのコピー）
5. スナップショットステータスの取得
6. シャードレベルのスナップショット進行状況管理

**関連システム・外部連携**：スナップショットリポジトリ（S3、Azure、GCS、HDFS、共有ファイルシステム等）と連携する。RepositoriesServiceを通じてリポジトリにアクセスする。

**権限による制御**：スナップショットの作成・削除にはクラスタ管理者権限が必要。スナップショットの読み取りにはクラスタモニタ権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 120 | スナップショット作成 | 主機能 | リポジトリにスナップショットを作成する処理 |
| 121 | スナップショット取得 | 主機能 | スナップショットの情報を返す処理 |
| 122 | スナップショット削除 | 主機能 | スナップショットを削除する処理 |
| 123 | スナップショットクローン | 主機能 | スナップショットを同一リポジトリ内にクローンする処理 |
| 125 | スナップショットステータス | 主機能 | スナップショットのステータス情報を返す処理 |
| 162 | Cat スナップショット | 主機能 | 特定リポジトリの全スナップショットをテーブル形式で返す処理 |

## 機能種別

CRUD操作 / データ連携 / バックアップ・リストア

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| repository | String | Yes | リポジトリ名 | 登録済みリポジトリ名であること |
| snapshot | String | Yes | スナップショット名 | 有効な名前（小文字、ハイフン使用可）、既存名との重複なし |
| indices | String[] | No | 対象インデックス名のリスト | 存在するインデックスであること |
| ignore_unavailable | boolean | No | 利用不可インデックスを無視するか | デフォルトfalse |
| include_global_state | boolean | No | グローバル状態を含めるか | デフォルトtrue |
| partial | boolean | No | 部分スナップショットを許可するか | デフォルトfalse |
| wait_for_completion | boolean | No | 完了まで待機するか | デフォルトfalse |

### 入力データソース

REST API（PUT /_snapshot/{repository}/{snapshot}）、クラスタ状態（インデックスメタデータ、ルーティングテーブル）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| snapshot | String | スナップショット名 |
| uuid | String | スナップショットUUID |
| version_id | int | OpenSearchバージョンID |
| indices | String[] | スナップショットに含まれるインデックス一覧 |
| state | SnapshotState | スナップショット状態（IN_PROGRESS, SUCCESS, FAILED, PARTIAL, INCOMPATIBLE） |
| shards.total | int | 総シャード数 |
| shards.successful | int | 成功シャード数 |
| shards.failed | int | 失敗シャード数 |
| start_time | long | 開始時刻 |
| end_time | long | 終了時刻 |

### 出力先

REST APIレスポンス、リポジトリ（BlobStore）

## 処理フロー

### 処理シーケンス

```
1. クライアントからCreateSnapshotRequestを受信
   └─ TransportClusterManagerNodeActionで処理をクラスタマネージャに転送
2. スナップショット名のバリデーション
   └─ InvalidSnapshotNameExceptionの検証
3. 対象インデックスの解決
   └─ IndexNameExpressionResolverでインデックス名を解決
4. クラスタ状態にSnapshotsInProgressエントリを追加
   └─ ClusterStateUpdateTaskでクラスタ状態を更新
5. シャード単位のスナップショット実行
   └─ SnapshotShardsServiceがデータノードでシャードスナップショットを実行
6. 各シャードのスナップショット完了を追跡
   └─ UpdateSnapshotStatusActionで状態を更新
7. 全シャード完了後にスナップショットを確定
   └─ RepositoryData更新、SnapshotInfoの保存
8. クラスタ状態からSnapshotsInProgressエントリを削除
```

### フローチャート

```mermaid
flowchart TD
    A[CreateSnapshotRequest] --> B[スナップショット名バリデーション]
    B --> C[対象インデックス解決]
    C --> D[ClusterState更新: SnapshotsInProgress追加]
    D --> E[シャードスナップショット開始]
    E --> F{全シャード完了?}
    F -->|No| G[シャード状態更新]
    G --> F
    F -->|Yes| H[スナップショット確定]
    H --> I[RepositoryData更新]
    I --> J[SnapshotInfo保存]
    J --> K[ClusterState更新: SnapshotsInProgress削除]
    K --> L[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-63-01 | 増分スナップショット | 既にリポジトリに存在するセグメントはスキップし、変更分のみ保存 | スナップショット作成時 |
| BR-63-02 | 並行スナップショット制限 | 同一リポジトリに対する並行スナップショット操作は制限される | 複数スナップショット同時実行時 |
| BR-63-03 | スナップショット名の一意性 | 同一リポジトリ内でスナップショット名は一意でなければならない | スナップショット作成時 |
| BR-63-04 | 使用中スナップショットの削除制限 | リストア中のスナップショットは削除できない | スナップショット削除時 |

### 計算ロジック

特になし

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

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| スナップショット作成 | リポジトリBlobStore | WRITE | インデックスデータ、メタデータのスナップショット保存 |
| スナップショット削除 | リポジトリBlobStore | DELETE | スナップショットデータの削除 |
| 状態管理 | クラスタ状態 | UPDATE | SnapshotsInProgress、SnapshotDeletionsInProgressの更新 |
| リポジトリデータ更新 | リポジトリBlobStore | WRITE | RepositoryDataの更新 |

### テーブル別操作詳細

#### リポジトリBlobStore

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| WRITE | index-N (RepositoryData) | スナップショット一覧とインデックスメタデータ | 増分更新 |
| WRITE | snap-{snapshotUUID}.dat | SnapshotInfo | スナップショットメタデータ |
| WRITE | indices/{indexId}/{shardId} | シャードデータファイル | Luceneセグメントデータ |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| InvalidSnapshotNameException | バリデーションエラー | 無効なスナップショット名 | 有効な名前を指定 |
| ConcurrentSnapshotExecutionException | 並行実行エラー | 同一リポジトリでの同時操作 | 前の操作の完了を待機 |
| SnapshotInProgressException | 状態エラー | スナップショット実行中 | 完了を待機 |
| SnapshotMissingException | 存在エラー | 指定スナップショットが存在しない | スナップショット名を確認 |
| RepositoryMissingException | リポジトリエラー | 指定リポジトリが存在しない | リポジトリを登録 |
| SnapshotInUseDeletionException | 削除エラー | リストア中のスナップショットの削除 | リストア完了後に削除 |

### リトライ仕様

ClusterManagerTaskThrottlerによりタスクのスロットリングが行われ、スロットル時はTransportClusterManagerNodeActionからリトライされる。

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

スナップショット操作はクラスタ状態更新を通じて制御される。ClusterStateUpdateTaskで状態を更新し、状態の一貫性はクラスタマネージャのクラスタ状態管理機構により保証される。RepositoryDataの更新はアトミック操作として実装されている。

## パフォーマンス要件

- 増分スナップショットにより、変更データのみ転送することで帯域幅と時間を節約
- シャード単位の並列スナップショットにより大規模インデックスのスナップショットを高速化
- wait_for_completion=falseによる非同期実行をサポート

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

- スナップショット操作にはcluster:admin/snapshot権限が必要
- リポジトリへのアクセスはリポジトリ設定の認証情報で保護
- スナップショットにはインデックスデータが含まれるため、リポジトリストレージのアクセス制御が重要

## 備考

- SnapshotsServiceはAbstractLifecycleComponentを継承し、ライフサイクル管理される
- ClusterStateApplierインターフェースを実装し、クラスタ状態変更を監視
- Shallow Snapshot V2（リモートストアバックドインデックス向け）をサポート

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SnapshotInfo.java | `server/src/main/java/org/opensearch/snapshots/SnapshotInfo.java` | スナップショット情報のデータ構造 |
| 1-2 | SnapshotId.java | `server/src/main/java/org/opensearch/snapshots/SnapshotId.java` | スナップショットID（名前+UUID） |
| 1-3 | Snapshot.java | `server/src/main/java/org/opensearch/snapshots/Snapshot.java` | スナップショット識別子（リポジトリ名+SnapshotId） |
| 1-4 | SnapshotState.java | `server/src/main/java/org/opensearch/snapshots/SnapshotState.java` | スナップショットの状態列挙型 |
| 1-5 | RepositoryData.java | `server/src/main/java/org/opensearch/repositories/RepositoryData.java` | リポジトリ内のスナップショット・インデックスメタデータ |

**読解のコツ**: SnapshotInfoはToXContentObject/Writeableを実装しており、REST API応答やノード間通信で使用される。SnapshotStateはIN_PROGRESS、SUCCESS、FAILED、PARTIAL、INCOMPATIBLEの5状態を持つ。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SnapshotsService.java | `server/src/main/java/org/opensearch/snapshots/SnapshotsService.java` | スナップショット管理のメインサービス。createSnapshot、deleteSnapshot、cloneSnapshot等の主要メソッド |

**主要処理フロー**:
1. **157行目**: SnapshotsServiceクラス宣言、AbstractLifecycleComponentを継承、ClusterStateApplierを実装
2. **161行目**: UPDATE_SNAPSHOT_STATUS_ACTION_NAME定数
3. **163-167行目**: 主要依存関係（ClusterService, IndexNameExpressionResolver, RepositoriesService等）
4. **175-176行目**: snapshotCompletionListeners - スナップショット完了リスナーのConcurrentHashMap
5. **181行目**: snapshotDeletionListeners - 削除完了リスナー

#### Step 3: シャードスナップショットを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SnapshotShardsService.java | `server/src/main/java/org/opensearch/snapshots/SnapshotShardsService.java` | データノードでのシャード単位のスナップショット実行 |
| 3-2 | SnapshotShardPaths.java | `server/src/main/java/org/opensearch/snapshots/SnapshotShardPaths.java` | スナップショットシャードパスの管理 |

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

```
REST API (PUT /_snapshot/{repo}/{snap})
    |
    +-- TransportCreateSnapshotAction
            |
            +-- SnapshotsService.createSnapshot()
                    |
                    +-- ClusterStateUpdateTask
                    |       +-- SnapshotsInProgress更新
                    |
                    +-- SnapshotShardsService (データノード)
                    |       +-- Repository.snapshotShard()
                    |
                    +-- SnapshotsService.endSnapshot()
                            +-- Repository.finalizeSnapshot()
                            +-- RepositoryData更新
```

### データフロー図

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

CreateSnapshotRequest ──> SnapshotsService ──> リポジトリBlobStore
                              |                    (snap-{uuid}.dat)
                              +-- ClusterState更新     (index-N)
                              +-- シャードスナップショット  (indices/...)
                              +-- RepositoryData更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SnapshotsService.java | `server/src/main/java/org/opensearch/snapshots/SnapshotsService.java` | ソース | スナップショット管理のメインサービス |
| SnapshotShardsService.java | `server/src/main/java/org/opensearch/snapshots/SnapshotShardsService.java` | ソース | データノードでのシャードスナップショット |
| SnapshotInfo.java | `server/src/main/java/org/opensearch/snapshots/SnapshotInfo.java` | ソース | スナップショット情報モデル |
| SnapshotId.java | `server/src/main/java/org/opensearch/snapshots/SnapshotId.java` | ソース | スナップショットID |
| Snapshot.java | `server/src/main/java/org/opensearch/snapshots/Snapshot.java` | ソース | スナップショット識別子 |
| SnapshotState.java | `server/src/main/java/org/opensearch/snapshots/SnapshotState.java` | ソース | スナップショット状態列挙型 |
| RepositoryData.java | `server/src/main/java/org/opensearch/repositories/RepositoryData.java` | ソース | リポジトリデータ管理 |
| RestoreService.java | `server/src/main/java/org/opensearch/snapshots/RestoreService.java` | ソース | リストアサービス（関連機能） |
| SnapshotShardPaths.java | `server/src/main/java/org/opensearch/snapshots/SnapshotShardPaths.java` | ソース | シャードパス管理 |
| InFlightShardSnapshotStates.java | `server/src/main/java/org/opensearch/snapshots/InFlightShardSnapshotStates.java` | ソース | 実行中シャードスナップショット状態 |
| SnapshotUtils.java | `server/src/main/java/org/opensearch/snapshots/SnapshotUtils.java` | ソース | ユーティリティ |
