| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475 |
- package main
- import (
- "TsDB2/DB/core"
- "TsDB2/DB/core/types"
- "TsDB2/DB/core/util"
- "unsafe"
- )
- // 编译期断言: 把 analyzer 里硬编码的盘上布局 (META_SZ / TINFO_SZ / TI_* / IM_*)
- // 与 DB/core 中的真实结构体逐个钉在一起。
- //
- // 为什么需要这个文件:
- //
- // analyzer 在自己的模块里手写偏移直接读盘。过去这件事只能靠 DB/core 的注释约束
- // (「改布局时记得同步 analyzer/main.go 的 TI_*」) —— 而漏改的后果不是报错, 而是
- // **静默读错**: 把索引名数组的高位字节当成 IndexType、把别的字段当成 EntryPage,
- // 页面照常渲染但数据全错, 极难发现。
- //
- // analyzer 的 go.mod 已有 `replace TsDB2 => ../`, 可以直接引用真实结构体, 于是把这层
- // 依赖交给编译器: 任何一边改了布局, 这里当场编译失败。
- //
- // 断言写法:
- // - [a - b]struct{} 与 [b - a]struct{} 同时成立 ⇔ a == b (差值为负时数组长度非法);
- // - _ [N]byte = [unsafe.Offsetof(...)]byte{} ⇔ 偏移恰好等于 N (长度不等则类型不符)。
- var (
- // 结构体整体尺寸
- _ [int(unsafe.Sizeof(core.IndexMeta{})) - META_SZ]struct{}
- _ [META_SZ - int(unsafe.Sizeof(core.IndexMeta{}))]struct{}
- _ [int(unsafe.Sizeof(core.TableInfo{})) - TINFO_SZ]struct{}
- _ [TINFO_SZ - int(unsafe.Sizeof(core.TableInfo{}))]struct{}
- // TableInfo 字段偏移
- _ [TI_FLAG]byte = [unsafe.Offsetof(core.TableInfo{}.Flag)]byte{}
- _ [TI_HPCNT]byte = [unsafe.Offsetof(core.TableInfo{}.HeapPageCount)]byte{}
- _ [TI_ROWS]byte = [unsafe.Offsetof(core.TableInfo{}.TotalRows)]byte{}
- _ [TI_FHEAP]byte = [unsafe.Offsetof(core.TableInfo{}.FirstHeap)]byte{}
- _ [TI_FDATA]byte = [unsafe.Offsetof(core.TableInfo{}.FirstData)]byte{}
- _ [TI_ROWSZ]byte = [unsafe.Offsetof(core.TableInfo{}.RowSize)]byte{}
- _ [TI_ALLOC]byte = [unsafe.Offsetof(core.TableInfo{}.FieldAllocateSize)]byte{}
- _ [TI_FIDX]byte = [unsafe.Offsetof(core.TableInfo{}.FirstIndexID)]byte{}
- _ [TI_EXTPG]byte = [unsafe.Offsetof(core.TableInfo{}.ExtPage)]byte{}
- _ [TI_EXTOFF]byte = [unsafe.Offsetof(core.TableInfo{}.ExtOff)]byte{}
- // IndexMeta 字段偏移 (这些会随 IndexNameSize 整体平移)
- _ [IM_NAMSZ]byte = [unsafe.Sizeof(core.IndexMeta{}.IndexName)]byte{}
- _ [IM_TYPE]byte = [unsafe.Offsetof(core.IndexMeta{}.IndexType)]byte{}
- _ [IM_FCNT]byte = [unsafe.Offsetof(core.IndexMeta{}.FieldCnt)]byte{}
- _ [IM_FLDS]byte = [unsafe.Offsetof(core.IndexMeta{}.FieldIDs)]byte{}
- _ [IM_EP]byte = [unsafe.Offsetof(core.IndexMeta{}.EntryPage)]byte{}
- _ [IM_FLAG]byte = [unsafe.Offsetof(core.IndexMeta{}.Flag)]byte{}
- // 位掩码同样是"读盘约定": analyzer 里手写的位必须与 core 的常量一致。
- // 读错位的后果和读错偏移一样安静 —— 列 / 索引照样渲染出来, 只是"可空"
- // 读成了"非空"、"唯一"读成了"普通"。
- _ [FLAG_DELETED - int(types.FlagDeleted)]struct{}
- _ [int(types.FlagDeleted) - FLAG_DELETED]struct{}
- _ [FLAG_NULLABLE - int(types.FlagNullable)]struct{}
- _ [int(types.FlagNullable) - FLAG_NULLABLE]struct{}
- _ [FLAG_UNIQUE - int(types.FlagUnique)]struct{}
- _ [int(types.FlagUnique) - FLAG_UNIQUE]struct{}
- _ [FLAG_SCALE - int(types.FlagScaleMask)]struct{}
- _ [int(types.FlagScaleMask) - FLAG_SCALE]struct{}
- _ [IM_FLAG_UNIQUE - int(core.IndexFlagUnique)]struct{}
- _ [int(core.IndexFlagUnique) - IM_FLAG_UNIQUE]struct{}
- )
- // init 兜底: core 没有给"这一位是删除位"单列常量 (那一位的语义由 util.IsHighBitSet
- // 表达), 所以它只能用运行时断言。只跑一次, 不在热路径上。
- func init() {
- if !util.IsHighBitSet(IM_FLAG_DELETED) {
- panic("IM_FLAG_DELETED 与 core/util.IsHighBitSet 的判定不一致: 删除位读错会让已删的索引照常渲染")
- }
- }
|