【lucene】SegmentInfos

SegmentInfos 类中文说明
------------------------------------

**一句话**
`SegmentInfos` 是 `segments_N` 文件的**内存表示**。它把磁盘上的 `segments_N` 读进来,变成一堆 `SegmentInfo` 的集合;当你增删改索引、合并段、提交时,再把它写回磁盘,生成新的 `segments_N`。
一个 segments_N 文件里保存了多个段(segment)的信息列表,每条记录包含段名、编解码器、删除代际等字段。

索引中当前活跃的段被保存在段信息文件 segments_N 中。索引目录里可能同时存在一个或多个 segments_N 文件;然而,只有代际号最大的那个才是活跃文件(当存在更旧的 segments_N 文件时,是因为它们暂时无法被删除,或正在使用自定义的 IndexDeletionPolicy)。该文件按名称列出每个段,并包含有关编解码器及删除代际的详细信息。

---

### 文件格式速览
文件名:`segments_N`(N 是递增的 long 值)
目录里可能有多个 `segments_N`,但**数字最大的那个是"当前活跃"的**。旧文件之所以还在,要么暂时删不掉,要么用了自定义 `IndexDeletionPolicy`。

#### 文件结构(按出现顺序)
| 字段 | 类型 | 说明 |
|---|---|---|
| Header | `IndexHeader` | 魔数、codec 名、版本 |
| LuceneVersion | 3 个 vInt | 写这次 commit 时用的 Lucene 主/次/补丁版本 |
| MinSegmentLuceneVersion | 3 个 vInt | **最老一段**的 Lucene 版本(≥1 段时才写) |
| NameCounter | int32 | 用来给**新段命名**的自增计数器(_0、_1...) |
| SegCount | int32 | 当前共有多少个段 |
| **循环 SegCount 次** | | |
| ‑ SegName | String | 段前缀名,如 _2 |
| ‑ SegID | byte[ID_LENGTH] | 该段 Codec 的唯一 id |
| ‑ SegCodec | String | 编码该段用的 Codec 名字 |
| ‑ DelGen | int64 | 删除文件的代际号;-1=无删除,>0=有删除 |
| ‑ DeletionCount | int32 | 该段内被删除的文档数 |
| ‑ FieldInfosGen | int64 | fieldInfos 更新代际号;-1=无更新 |
| ‑ DocValuesGen | int64 | DocValues 更新代际号;-1=无更新 |
| ‑ UpdatesFiles | Map<int32, Set<String>> | 每个字段对应的更新文件集合 |
| **循环结束** | | |
| CommitUserData | Map<String,String> | 用户自定义 KV,可通过 `IndexWriter.setLiveCommitData` 设置 |
| Footer | `CodecFooter` | 校验和、尾部魔数 |

---

### 字段速查

Version 记录通过添加或删除文档导致索引被修改的次数。

NameCounter 用于为新段文件生成名称。

SegName 是段的名称,用作构成该段索引的所有文件的文件名前缀。

DelGen 是删除文件的代际号。若为 -1,表示无删除;大于零表示存在由 LiveDocsFormat 存储的删除。

DeletionCount 记录该段中被删除的文档数。

SegCodec 是编码该段所用的编解码器名称。

SegID 是编码该段所用的编解码器标识符。

CommitUserData 存储可选的用户提供的透明 Map<String,String>,该 Map 通过 IndexWriter.setLiveCommitData(Iterable) 传入。

FieldInfosGen 是 fieldInfos 文件的代际号。若为 -1,表示该段无 fieldInfos 更新;大于零表示存在由 FieldInfosFormat 存储的 fieldInfos 更新。

DocValuesGen 是可更新 DocValues 的代际号。若为 -1,表示该段无 DocValues 更新;大于零表示存在由 DocValuesFormat 存储的 DocValues 更新。

UpdatesFiles 按字段存储在该段中被更新的文件集合。
- **Version**
每次增删文档都会自增,用来判断"索引是否发生变化"。

- **NameCounter**
保证新段文件名全局唯一。

- **SegName**
段文件前缀:_0.cfe、_0.cfs、_0.tim... 都靠它。

- **DelGen / DeletionCount**
配合 `LiveDocsFormat` 实现"软删除"或"硬删除"。

- **CommitUserData**
可存放业务标记(如时间戳、版本号),用于备份或审计。

- **FieldInfosGen / DocValuesGen**
支持"在线"更新字段属性或 DocValues,无需重新建索引。

---

### 使用场景
``

  • 启动时:SegmentInfos.readLatestCommit(dir) → 拿到当前所有段。
  • 提交时:IndexWriter.commit() → 更新 SegmentInfos 并写回磁盘生成新的 segments_N
  • 合并时:MergePolicy 修改 SegmentInfos.segments → 旧段被移除,新段加入。``