From e185c10f8e1160c40f035352eece7b2f65b78491 Mon Sep 17 00:00:00 2001 From: AmuroEita <1071307515@qq.com> Date: Thu, 10 Sep 2026 20:54:22 +0800 Subject: [PATCH 1/2] =?UTF-8?q?ABI:=20=E5=AF=BC=E5=87=BA=20ResolveRef/GetB?= =?UTF-8?q?yRef/SetPartByRef=EF=BC=8C=E5=90=8E=E7=AB=AF=E5=8F=AF=E9=80=89?= =?UTF-8?q?=20dlsym=EF=BC=88#268=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/kvspace/kvspace.h | 11 +++++++++++ src/frontend.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/include/kvspace/kvspace.h b/include/kvspace/kvspace.h index e43aa0e..283d852 100644 --- a/include/kvspace/kvspace.h +++ b/include/kvspace/kvspace.h @@ -69,6 +69,17 @@ int kvspaceDisconnect(void *h, char *err, uint32_t err_cap); * 调用方不得 free。resolve=1 穿透 link。key 不存在/空值 → *out=NULL、*out_len=0、返回 0。 */ int kvspaceGet(void *h, const char *key, int resolve, uint8_t **out, uint32_t *out_len); +typedef struct { + uint32_t block_id; + uint32_t gen; +} kvspaceRef_t; +int kvspaceResolveRef(void *h, const char *key, kvspaceRef_t *ref); +int kvspaceGetByRef(void *h, kvspaceRef_t *ref, const char *key_fallback, + uint8_t **out, uint32_t *out_len); +int kvspaceSetPartByRef(void *h, kvspaceRef_t *ref, const char *key_fallback, + uint32_t offset, const uint8_t *buf, uint32_t buf_len, + char *err, uint32_t err_cap); + /* 指令边界回收读借用池:VM 每条指令执行完调用一次。此后本指令内 Get/GetPart 借出的 * 指针一律失效。shm 常驻映射侧为 no-op;durable 惰性写不清池,全靠本调用回收。 */ void kvspaceReadReset(void *h); diff --git a/src/frontend.c b/src/frontend.c index 611d51c..2b14f74 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -49,6 +49,12 @@ typedef struct { int (*clear)(void *h, char *err, uint32_t err_cap); int (*watch)(void *h, const char *key, const uint8_t *target, uint32_t target_len, uint64_t tick_ns, uint8_t **out, uint32_t *out_len); + int (*resolveref)(void *h, const char *key, kvspaceRef_t *ref); + int (*getbyref)(void *h, kvspaceRef_t *ref, const char *key_fallback, + uint8_t **out, uint32_t *out_len); + int (*setpartbyref)(void *h, kvspaceRef_t *ref, const char *key_fallback, + uint32_t offset, const uint8_t *buf, uint32_t buf_len, + char *err, uint32_t err_cap); } kvspace_vt; typedef struct { @@ -130,6 +136,9 @@ void *kvspaceConnect(const char *dsn) { LOAD(clear, "kvspaceClear"); LOAD(watch, "kvspaceWatch"); #undef LOAD + *(void **)&vt->resolveref = dlsym(dl, "kvspaceResolveRef"); + *(void **)&vt->getbyref = dlsym(dl, "kvspaceGetByRef"); + *(void **)&vt->setpartbyref = dlsym(dl, "kvspaceSetPartByRef"); void *(*connect)(const char *) = dlsym(dl, "kvspaceConnect"); if (!connect) { free(vt); dlclose(dl); return NULL; } @@ -163,6 +172,33 @@ int kvspaceGet(void *h, const char *key, int resolve, uint8_t **out, uint32_t *o return x->vt->get(x->backend, key, resolve, out, out_len); } +int kvspaceResolveRef(void *h, const char *key, kvspaceRef_t *ref) { + kvspace_handle *x = H(h); + if (!x->vt->resolveref) return 1; + return x->vt->resolveref(x->backend, key, ref); +} + +int kvspaceGetByRef(void *h, kvspaceRef_t *ref, const char *key_fallback, + uint8_t **out, uint32_t *out_len) { + kvspace_handle *x = H(h); + if (x->vt->getbyref) + return x->vt->getbyref(x->backend, ref, key_fallback, out, out_len); + if (!key_fallback) { *out = NULL; *out_len = 0; return 0; } + return x->vt->get(x->backend, key_fallback, 0, out, out_len); +} + +int kvspaceSetPartByRef(void *h, kvspaceRef_t *ref, const char *key_fallback, + uint32_t offset, const uint8_t *buf, uint32_t buf_len, + char *err, uint32_t err_cap) { + kvspace_handle *x = H(h); + if (x->vt->setpartbyref) + return x->vt->setpartbyref(x->backend, ref, key_fallback, offset, buf, + buf_len, err, err_cap); + if (err && err_cap) + snprintf(err, err_cap, "kvspace: set-part-by-ref unsupported"); + return 1; +} + void kvspaceReadReset(void *h) { kvspace_handle *x = H(h); if (x->vt->readreset) x->vt->readreset(x->backend); From 4a7386cf8146e1361a7f2ad263dd2867b6162145 Mon Sep 17 00:00:00 2001 From: AmuroEita <1071307515@qq.com> Date: Sun, 13 Sep 2026 21:40:12 +0800 Subject: [PATCH 2/2] =?UTF-8?q?ABI:=20kvspaceRef=5Ft=20=E5=A2=9E=20parent?= =?UTF-8?q?=5Fid/depth=EF=BC=88#268=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ResolveRef 填目录祖先;GetByRef(gen>0) 从父节点续走剩余 key。 --- include/kvspace/kvspace.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/kvspace/kvspace.h b/include/kvspace/kvspace.h index 5d0a51d..30a8dee 100644 --- a/include/kvspace/kvspace.h +++ b/include/kvspace/kvspace.h @@ -68,9 +68,15 @@ void kvspaceClose(void *h); * 调用方不得 free。resolve=1 穿透 link。key 不存在/空值 → *out=NULL、*out_len=0、返回 0。 */ int kvspaceGet(void *h, const char *key, int resolve, uint8_t **out, uint32_t *out_len); +/* ResolveRef:block_id=叶子、gen=0;parent_id=目录祖先 ART 节点, + * depth=进入该节点时 key 已消费字节数。GetByRef:gen==0 直取叶子; + * gen>0 则 block_id 为父节点、gen 为 depth,从该处续走剩余字节。 + * 后端未实现父节点时 parent_id 保持 0。 */ typedef struct { uint32_t block_id; uint32_t gen; + uint32_t parent_id; + uint32_t depth; } kvspaceRef_t; int kvspaceResolveRef(void *h, const char *key, kvspaceRef_t *ref); int kvspaceGetByRef(void *h, kvspaceRef_t *ref, const char *key_fallback,