| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 |
- package main
- import (
- "git.ycl.pub/yl32940/TsDB2/DB/core"
- "git.ycl.pub/yl32940/TsDB2/DB/core/types"
- "git.ycl.pub/yl32940/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{}
- // HeaderPage 字段偏移 (v11 重排): audit.go / main.go 里所有 hdr[...] 手写的
- // 读盘偏移。漏改的后果与其它结构体一样 —— 页面照常渲染, 读出来的全是错值。
- _ [HDR_FREE_END]byte = [unsafe.Offsetof(core.HeaderPage{}.FreePageEnd)]byte{}
- _ [HDR_CRC]byte = [unsafe.Offsetof(core.HeaderPage{}.HeaderCrc)]byte{}
- _ [12]byte = [unsafe.Offsetof(core.HeaderPage{}.NextFreePage)]byte{}
- _ [48]byte = [unsafe.Offsetof(core.HeaderPage{}.TablePage)]byte{}
- _ [56]byte = [unsafe.Offsetof(core.HeaderPage{}.FreePageStart)]byte{}
- _ [64]byte = [unsafe.Offsetof(core.HeaderPage{}.FreePageCount)]byte{}
- _ [68]byte = [unsafe.Offsetof(core.HeaderPage{}.FirstWALPage)]byte{}
- _ [332]byte = [unsafe.Offsetof(core.HeaderPage{}.Comment)]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 的判定不一致: 删除位读错会让已删的索引照常渲染")
- }
- }
|