# 機能設計書 130-Store Subdirectory

## 概要

本ドキュメントは、OpenSearchにおけるサブディレクトリベースのストア管理モジュールの設計を記載する。

### 本機能の処理概要

本機能は、シャードデータパス内のサブディレクトリに配置されたファイルを適切に管理するカスタムストアプラグインを提供するモジュールである。

**業務上の目的・背景**：通常のOpenSearchストアはシャードのインデックスディレクトリ内のファイルのみを管理するが、一部のユースケース（例: Context Aware Segments等）ではサブディレクトリにファイルが配置される。本モジュールは、サブディレクトリ内のファイルも含めて統合的に管理し、ピアリカバリ時のファイル転送も正しく行えるようにする。

**機能の利用シーン**：サブディレクトリにセグメントファイルを配置する拡張機能の利用時、ピアリカバリ時のサブディレクトリファイル転送、サブディレクトリを含むストアのメタデータ管理時に利用される。

**主要な処理内容**：
1. SubdirectoryStorePluginによるカスタムストアファクトリの登録
2. SubdirectoryAwareStoreによるサブディレクトリ対応メタデータ管理
3. SubdirectoryAwareDirectoryによるファイルパス解決とI/O操作
4. サブディレクトリ内のセグメント情報の読み出し

**関連システム・外部連携**：Lucene Directory API、ピアリカバリ機能、Context Aware Segments機能。

**権限による制御**：インデックス設定（index.store.type）でストア種別を指定。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は内部モジュールであり、直接的な画面はない |

## 機能種別

ストレージプラグイン（内部基盤）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| index.store.type | String | No | "subdirectory_store"を指定してプラグインを有効化 | 登録済みストア種別名 |

### 入力データソース

シャードデータパス内のファイルシステム

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| MetadataSnapshot | Object | サブディレクトリを含む全ファイルのメタデータ情報 |

### 出力先

インメモリ（ストアメタデータ）、ピアリカバリ時のファイル転送

## 処理フロー

### 処理シーケンス

```
1. プラグイン登録
   └─ SubdirectoryStorePlugin.getStoreFactories()で"subdirectory_store"を登録
2. ストア生成
   └─ SubdirectoryStoreFactory.newStore()でSubdirectoryAwareStore生成
   └─ SubdirectoryAwareDirectoryでディレクトリラップ
3. メタデータ取得
   └─ getMetadata()で通常セグメント＋サブディレクトリセグメント情報を統合
   └─ loadSubdirectoryMetadata()でサブディレクトリのセグメント読み出し
4. ファイル操作
   └─ SubdirectoryAwareDirectory.listAll()でサブディレクトリを含む全ファイル列挙
   └─ parseFilePath()でパス解決
```

### フローチャート

```mermaid
flowchart TD
    A[インデックス作成 store.type=subdirectory_store] --> B[SubdirectoryStoreFactory]
    B --> C[SubdirectoryAwareStore生成]
    C --> D[SubdirectoryAwareDirectory生成]
    E[メタデータ要求] --> F[getMetadata]
    F --> G[通常セグメントメタデータ読み出し]
    F --> H[サブディレクトリメタデータ読み出し]
    G --> I[統合メタデータ返却]
    H --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 除外ディレクトリ | index/, translog/, _state/ はサブディレクトリ走査から除外 | listAll時 |
| BR-002 | パスプレフィックス | サブディレクトリ内のファイルは親ディレクトリからの相対パスで管理 | 常時 |
| BR-003 | セグメント情報読み出し | サブディレクトリ内のsegments_Nファイルを検出し、SegmentInfosを読み出す | メタデータ取得時 |
| BR-004 | チェックサム計算 | 非セグメントファイルに対してはCodecUtil.checksumEntireFile()でチェックサム算出 | メタデータ取得時 |

### 計算ロジック

- ファイルメタデータ: ファイルパス、サイズ、チェックサム、Luceneバージョンから構成
- チェックサム: CodecUtil.checksumEntireFile()で算出

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ファイル読み出し | ファイルシステム | SELECT | サブディレクトリ内ファイルの読み出し |
| ファイル書き込み | ファイルシステム | INSERT | サブディレクトリへのファイル書き込み（ディレクトリ自動作成含む） |

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

ファイルシステム上のサブディレクトリ内のLuceneセグメントファイルに対するI/O操作。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IOException | I/Oエラー | ファイル読み書き失敗 | ファイルシステム確認 |
| NoSuchFileException | ファイル未検出 | ファイル走査中のファイル削除 | デバッグログ出力しスキップ |

### リトライ仕様

NoSuchFileExceptionはファイル走査中に発生しうるため、スキップして処理を続行する。

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

ファイルシステム操作のため、Luceneのセグメント切り替え（commit）でアトミック性を確保。

## パフォーマンス要件

listAll()でFiles.walkFileTree()を使用するため、サブディレクトリ構造が深い場合はパフォーマンスに影響する可能性がある。

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

ファイルシステムアクセスはシャードパス内に限定される。

## 備考

本モジュールはContext Aware Segments機能のサポートとして開発された。

---

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

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

### 推奨読解順序

#### Step 1: プラグイン登録を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SubdirectoryStorePlugin.java | `modules/store-subdirectory/src/main/java/org/opensearch/plugin/store/subdirectory/SubdirectoryStorePlugin.java` | IndexStorePlugin実装。"subdirectory_store"ファクトリ登録 |

**主要処理フロー**:
- **48-52行目**: getStoreFactories()で"subdirectory_store"をSubdirectoryStoreFactoryとして登録
- **61-83行目**: SubdirectoryStoreFactory.newStore()でSubdirectoryAwareStoreを生成

#### Step 2: ストア実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SubdirectoryAwareStore.java | `modules/store-subdirectory/src/main/java/org/opensearch/plugin/store/subdirectory/SubdirectoryAwareStore.java` | Store拡張。メタデータ取得でサブディレクトリ対応 |

**主要処理フロー**:
- **74-83行目**: コンストラクタでSubdirectoryAwareDirectoryにラップ
- **117-131行目**: getMetadata()で通常＋サブディレクトリメタデータを統合
- **139-170行目**: loadSubdirectoryMetadata()でsegments_Nファイルと非セグメントファイルを分類処理
- **177-200行目**: loadMetadataFromSubdirectorySegmentsFile()でFSDirectory経由でSegmentInfos読み出し
- **240-251行目**: computeFileMetadata()で非セグメントファイルのチェックサム計算

#### Step 3: ディレクトリ実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SubdirectoryAwareDirectory (内部クラス) | 同上 | FilterDirectory拡張。パス解決とファイル走査 |

**主要処理フロー**:
- **260-273行目**: FilterDirectoryを継承、shardPathを保持
- **276-278行目**: openInput()でparseFilePath後にデリゲート
- **280-286行目**: createOutput()でディレクトリ作成後にデリゲート
- **309-318行目**: listAll()でデリゲート結果＋サブディレクトリファイルを統合
- **320-348行目**: addSubdirectoryFiles()でFiles.walkFileTree()による走査（除外ディレクトリあり）
- **350-358行目**: parseFilePath()でパス解決ロジック

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

```
SubdirectoryStorePlugin
    |
    +-- getStoreFactories()
            |
            +-- SubdirectoryStoreFactory.newStore()
                    |
                    +-- SubdirectoryAwareStore
                            |
                            +-- SubdirectoryAwareDirectory (FilterDirectory)
                            |       +-- openInput() / createOutput()
                            |       +-- listAll() (サブディレクトリ走査)
                            |       +-- parseFilePath() (パス解決)
                            |
                            +-- getMetadata()
                                    +-- loadSubdirectoryMetadata()
                                    +-- loadMetadataFromSubdirectorySegmentsFile()
                                    +-- computeFileMetadata()
```

### データフロー図

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

index.store.type -->  SubdirectoryStorePlugin   -->  SubdirectoryAwareStore
ファイルシステム  -->  SubdirectoryAwareDirectory -->  ファイルI/O
IndexCommit      -->  getMetadata()             -->  MetadataSnapshot
                      (通常 + サブディレクトリ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SubdirectoryStorePlugin.java | `modules/store-subdirectory/src/main/java/org/opensearch/plugin/store/subdirectory/` | ソース | プラグインエントリポイント |
| SubdirectoryAwareStore.java | 同上 | ソース | ストア実装（メタデータ＋ディレクトリ管理） |
| package-info.java | 同上 | ソース | パッケージ情報 |
