Skip to content

xvalue 改为 64 字节定长 head (#329) - #351

Closed
carsontung666 wants to merge 1 commit into
array2d:masterfrom
carsontung666:feat/issue-329-xvalue-head
Closed

carsontung666 wants to merge 1 commit into
array2d:masterfrom
carsontung666:feat/issue-329-xvalue-head

Conversation

@carsontung666

Copy link
Copy Markdown
Contributor

No description provided.

@carsontung666
carsontung666 force-pushed the feat/issue-329-xvalue-head branch from 3c3dd2e to d6cd101 Compare September 21, 2026 08:21
@miaobyte

Copy link
Copy Markdown
Contributor

回归确证:本 PR 让 test-fs 从 FAIL:3 变成 FAIL:217

分支 test-fs test-shm
master PASS:214 FAIL:3 PASS:213 FAIL:4
本 PR PASS:0 FAIL:217 fail

本地已复现:bin/kvlang tutorial/01-basics/hello.kv → 反复输出 kvlang: vthread 1 错误 rc=-1 :错误信息为空)。同一份代码在 master 上正常输出 hello kvlang

二分定位:问题只在 runtime/src/xvalue.c

实验 C 侧 xvalue.c Rust 侧 engine.rs 结果
A 本 PR(box64) master ❌ 失败
B master 本 PR ✅ 通过

所以 engine.rs 的改动单独存在时无害,触发点是 C 侧的 box64 编码器

根因:box64 的字节 0–1 被 kvspace 当成 headlen

kvlangXvalueEncodeBox()buf[0] = 0(硬编码)、buf[1] = storetype。而写值的路径 runtime/src/kvspace.c:529 用的是 kvspace 的 kvspaceDecodeHead,它按旧布局读 headlen = data[0] | data[1] << 8

C rwir 产出的值: len=69, byte0=0, byte1(storetype)=2
kvspace 旧布局算 headlen = data[0] | data[1]<<8 = 512   (实际 len=69)
kvspaceDecodeHead(box64 buffer) = 1                      ← kvspace.c:529 据此 continue

kvspace.c:520-541 是所有 C 侧值的唯一写出口:529 行解码取 ref/storetype/ro/vid/langtype/body,再交给 kvspaceWriteInPlace/NewPlace 由 kvspace 重建 head。现在第 529 行拿到 1(解码失败)→ 走 continue

kvspaceHead_t h;
/* Skip only if head decode fails. Empty langtype is still a valid Ptr. */
if (kvspaceDecodeHead(v->data, v->len, &h) != 0)
    continue;          // ← 静默丢弃,值根本没写进 kvspace

于是 C rwir 产出的每一个值都被静默丢弃,下游全部读到空 → rc=-1msg 为空 → 217 个用例全挂。

这不是「漏改一处」

唯一认识 box64 的解码器 kvlangXvalueDecodeHeadRawstaticxvalue.c:224),跨翻译单元根本调不到。也就是说 kvspace.c:529rwir_func.c:146 这两处直接调 kvspaceDecodeHead 的地方,在当前设计下没有修好的可能

同一个 PR 里现在并存两份 head codec:

  • kvspace 的 kvspaceDecodeHead(head 的权威定义,见 kvspace.h 顶部注释)
  • 本 PR 的 looks_head64() / decode_head64()

写方换了格式、读方只改了一部分,剩下的静默失败。head 的 codec 属于 kvspace 的职责(#329 目前仍是 OPEN RFC),建议先确认格式归属再动。

另有两处确认存在,但不是本次全挂的触发点

1. kind id 表错位(差 4 位)

写方 xvalue.ch64_kind_names[]FLOAT32, FLOAT64 之后是 FLOAT16, BFLOAT16, FLOAT8_E4M3, FLOAT8_E5M2,所以 char/utf32 落在 16(实测 kid=16)。读方 engine.rs:124-128 写的是:

12 => "char/utf32",   // 写方此处是 FLOAT16
13 => "char/utf8",    // BFLOAT16
14 => "char/ascii",   // FLOAT8_E4M3

我单独把 12/13/14 改成 16/17/18 重跑,hello.kv 仍然挂 —— 它不是本次全挂的原因,但仍然是错的:所有 char/* 值会落进 _ => ""

顺带一提,runtime_internal.h:239 已经有权威的 runtime id 表:

enum { KVLANG_LT_UNKNOWN = 0, KVLANG_LT_NONE, KVLANG_LT_BOOL, ...
       KVLANG_LT_FLOAT64, KVLANG_LT_CHAR_UTF32, ... };
int kvlangLangTypeId(const char *s, size_t len);
const char *kvlangLangTypeKind(int id);

本 PR 没有复用它,而是另造了 h64_kind_names[],又在 engine.rs 里硬编码了第三份。三张表三种编号,建议从 KVLANG_LT_* 单向导出。

2. 同文件两种格式并存 + 格式嗅探

构造器 走的编码路径 实测长度
kvlangXvalueNewTlv() box64 69
kvlangXvalueNewTlvDims() kvspaceTlvEncode(旧格式) 36

同一个文件里两个构造器写两种格式,读方只能靠 looks_head64() 猜。格式应当自描述,不宜靠启发式判定。


以上定位基于本地完整构建(C runtime + layout + runtime-rs,kvspace 三后端从源码编译),A/B 两组实验可复现。

@carsontung666

Copy link
Copy Markdown
Contributor Author

同意定位:box64 编码器与 kvspaceDecodeHead 不兼容,C rwir 产出的值在 kvspace.c 写出口被静默丢弃,所以 test-fs 从 FAIL:3 变成 FAIL:217。

head codec 属于 kvspace,#329 仍是 OPEN RFC(待裁决未填)。本 PR 另造了一份 looks_head64/h64_kind_names,和 KVLANG_LT_*、kvspace 权威布局三套编号并存,不适合在格式定案前合入。

先转为 draft,等 kvspace 侧格式定案后再从 kvspace 的 codec 单向导出,不再在 runtime 里并行编解码。

@carsontung666
carsontung666 marked this pull request as draft September 21, 2026 15:12
@carsontung666

Copy link
Copy Markdown
Contributor Author

#329 仍是 OPEN RFC,head codec 属于 kvspace,待裁决未填。本 PR 的 box64 编码器与 kvspaceDecodeHead 不兼容,先关闭。等 kvspace 格式定案后再开。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants