diff --git a/include/kvspace/kvspace.h b/include/kvspace/kvspace.h index 6cf1bb2..30a8dee 100644 --- a/include/kvspace/kvspace.h +++ b/include/kvspace/kvspace.h @@ -68,6 +68,23 @@ 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, + 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 42d8f73..81bc4e2 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -48,6 +48,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 { @@ -140,6 +146,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; } @@ -168,6 +177,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);