From e0b84d8e8ef46702846bab2a2c0ea6fb01464c79 Mon Sep 17 00:00:00 2001 From: "peng.li24" <734991033@qq.com> Date: Fri, 11 Sep 2026 15:34:42 +0800 Subject: [PATCH] =?UTF-8?q?wip:=20=E5=88=A0=20kvspaceDisconnect/dis=5Fconn?= =?UTF-8?q?=20+=20coord/=E9=94=99=E8=AF=AF=E5=B8=B8=E9=87=8F/=E6=AD=BB?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=B8=85=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除 kvspaceDisconnect FFI 与 dis_conn trait 方法;删 coord 的 coord_in_dims/grow_dim/valid_member_name、一批 ERR_* 常量、fs/xvalue 死代码。进行中快照,未验证编译。 Co-Authored-By: Claude Opus 4.8 --- Cargo.toml | 2 +- README.md | 2 +- src/backend.rs | 11 ++--------- src/const.rs | 20 +++----------------- src/coord.rs | 31 ------------------------------- src/ffi.rs | 13 ------------- src/fs/kvspace.rs | 35 +++-------------------------------- src/kvspace.rs | 1 - src/lib.rs | 7 +------ src/redis/store.rs | 4 ++++ src/xvalue.rs | 27 --------------------------- src/xvalue_byte.rs | 6 ------ src/xvalue_int.rs | 18 ------------------ src/xvalue_uint.rs | 27 +-------------------------- 14 files changed, 16 insertions(+), 188 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ce45775..7334d60 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "kvspace-durable" version = "0.1.0" edition = "2021" license = "MIT" -description = "可嵌入的 KVSpace(Rust),严格翻译 kvspace-go;后端 redis/fs/s3" +description = "可嵌入的 KVSpace(Rust),对齐 kvspace ABI 与线格式;后端 redis/fs/s3" [lib] name = "kvspace_durable" diff --git a/README.md b/README.md index c3a7266..a34f330 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Crate types: `rlib`, `staticlib`, `cdylib` (`libkvspace_durable.so`). C ABI exported from the cdylib (`src/ffi.rs`): -- lifecycle: `kvspaceConnect`, `kvspaceClose`, `kvspaceDisconnect` +- lifecycle: `kvspaceConnect`, `kvspaceClose` - KV read/write (zero-copy borrow model, no free): `kvspaceGet` (borrow), `kvspaceWriteInPlace`, `kvspaceWriteNewPlace` - enumerate / delete / copy: `kvspaceListLen`, `kvspaceListAt`, `kvspaceDel`, `kvspaceDelTree`, `kvspaceCp`, `kvspaceCpTree` - directories / extindex: `kvspaceMkindex`, `kvspaceMkindexExt`, `kvspaceRmindexExt` diff --git a/src/backend.rs b/src/backend.rs index 6c012ff..28a61d5 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -3,11 +3,9 @@ use std::time::Duration; -use crate::coord::{grow_coord_dims, is_coord}; use crate::kvspace::{KVPair, KVSpace}; use crate::kvspace_common::{ - dir_exists, get_one, join_path, mk_index_recursive, sep_path, split_index, strip_dir_suf, - validate_ptr, watch_value, + join_path, mk_index_recursive, sep_path, split_index, strip_dir_suf, validate_ptr, watch_value, }; use crate::r#const::*; use crate::store::KVStore; @@ -16,7 +14,7 @@ use crate::xvalue::{ }; use crate::xvalue_index::{ encode_ext_index_grow, encode_index_grow, grow_cap, matrix_cap, matrix_width, new_ext_index, - new_index, new_map_index, + new_index, }; pub struct Backend { @@ -64,7 +62,6 @@ impl Backend { } } - // ── link 解析 ─────────────────────────────────────────────────── fn resolve_path(&self, path: &str) -> String { @@ -916,8 +913,4 @@ impl KVSpace for Backend { self.store.flush(); Ok(()) } - - fn dis_conn(&mut self) -> Result<(), String> { - Ok(()) - } } diff --git a/src/const.rs b/src/const.rs index 3305657..269a504 100644 --- a/src/const.rs +++ b/src/const.rs @@ -1,6 +1,5 @@ -// const.rs — 对齐 const.go -// 路径与成员分隔符统一管理。所有构造 KV 路径、解析限定名、成员访问的地方 -// 均须使用这些常量,禁止硬编码 "·" 等裸字符串。 +// const.rs — 路径/分隔符/错误消息/kind 常量。 +// 所有构造 KV 路径、解析限定名、成员访问的地方均须使用这些常量,禁止硬编码 "·" 等裸字符串。 // ── 路径结构 ────────────────────────────────────────────────────────────── @@ -10,30 +9,17 @@ pub const RUNTIME_MEMBER_SEP: &str = "‥"; // 运行时保留字段前缀(U+2 pub const INDEX_VALUE_SEP: &str = "\n"; // index XValueHead 中的路径分隔符 pub const EXT_INDEX_HEAD: &str = "…"; // extindex XValueHead bytes 首元素前缀,如 …/lib/init/ -// ── 错误(对齐 const.go 的 error 变量) ────────────────────────────────── +// ── 错误消息 ──────────────────────────────────────────────────────────── pub const ERR_DIR_MUST_END_WITH_SLASH: &str = "kvspace: index must end with /"; pub const ERR_INVALID_PATH: &str = "kvspace: path must be absolute and canonical"; -pub const ERR_INVALID_DIR_VALUE: &str = "kvspace: directory value must be kind=index"; -pub const ERR_INVALID_VALUE: &str = "kvspace: value cannot be encoded and decoded losslessly"; -pub const ERR_DISCONNECTED: &str = "kvspace: connection is disconnected"; -pub const ERR_GET: &str = "kvspace: GET"; -pub const ERR_PIPE_EXEC: &str = "kvspace: pipeline exec"; -pub const ERR_RESOLVE: &str = "kvspace: 路径解析 GET"; -pub const ERR_SCAN: &str = "kvspace: SCAN"; pub const ERR_EXT_WRITE: &str = "kvspace: 禁止对 extindex 只读路径执行写操作"; pub const ERR_EXT_DEL: &str = "kvspace: 禁止删除 extindex 只读路径"; -pub const ERR_NOT_DIR: &str = "kvspace: 父路径不是目录"; -pub const ERR_PARENT_NOT_FOUND: &str = "kvspace: 父目录不存在"; pub const ERR_EXT_CASCADE: &str = "kvspace: ExtIndex 不容许级联"; -pub const ERR_EXT_TARGET: &str = "kvspace: ExtIndex target must be an existing ordinary index"; -pub const ERR_EXT_COLLISION: &str = "kvspace: ExtIndex local and extension children overlap"; pub const ERR_LINK_TYPE_MISMATCH: &str = "kvspace: Link target 和 linkpath 类型不一致"; pub const ERR_MAP_NDIM: &str = "kvspace: stringkeymap 恒 ndim>=1,dims 不可为空"; pub const ERR_MAP_COORD: &str = "kvspace: stringkeymap 成员名必须是坐标段 [s0,s1,...]"; -pub const ERR_MEMBER_NAME: &str = "kvspace: 命名成员名含非法字符"; pub const ERR_MEMHEAD_MISSING: &str = "kvspace: memhead 不存在,禁止写 memitem"; -pub const ERR_LINK_PATH_EXISTS: &str = "kvspace: Link path already contains a non-link value"; // ── XValueHead kind ───────────────────────────────────────────────────────── diff --git a/src/coord.rs b/src/coord.rs index f47cddc..f46f44e 100644 --- a/src/coord.rs +++ b/src/coord.rs @@ -59,24 +59,6 @@ pub fn cmp_coord(a: &str, b: &str) -> Ordering { } } -/// 坐标是否落在 dims 内(维数相符且逐维小于)。 -pub fn coord_in_dims(coords: &[i64], dims: &[i32]) -> bool { - coords.len() == dims.len() - && coords - .iter() - .zip(dims) - .all(|(&c, &d)| c >= 0 && c < d as i64) -} - -/// 一维 dims 至少容纳坐标 v(max(dims[0], v+1)),dims 为空时起算为 1。 -pub fn grow_dim(dims: &[i32], v: i64) -> Vec { - if dims.is_empty() { - vec![v as i32 + 1] - } else { - vec![dims[0].max(v as i32 + 1)] - } -} - /// 一组坐标段的维数:逐段取最大整数坐标,dims 为空时按首个整数坐标段长度起算; /// 无任何整数坐标(纯小数/字符串坐标)时退化为 1 维、长度为成员数。 pub fn grow_coord_dims(dims: &[i32], names: &[String]) -> Vec { @@ -98,16 +80,3 @@ pub fn grow_coord_dims(dims: &[i32], names: &[String]) -> Vec { } d } - -/// 命名成员名字符约束:禁 / · [ ] \n \r \0 ‥ … 与 ASCII 控制字符,禁空串。 -/// '.' 已放开(小数/含点字符串可作 key),成员分隔符改为 ·(OBJ_SEP)。 -pub fn valid_member_name(name: &str) -> bool { - !name.is_empty() - && !name.contains(crate::r#const::OBJ_SEP) - && !name.chars().any(|c| { - matches!( - c, - '/' | '[' | ']' | '\n' | '\r' | '\0' | '\u{2025}' | '\u{2026}' - ) || (c as u32) < 0x20 - }) -} diff --git a/src/ffi.rs b/src/ffi.rs index af4912f..447d084 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -18,7 +18,6 @@ use std::time::Duration; use crate::conn::conn; use crate::kvspace::{KVPair, KVSpace}; -use crate::kvspace_common::get_one; use crate::xvalue::{decode_xvalue, decode_xvalue_head, encode_head, encode_head_perm, new_ptr}; use crate::xvalue_bool::new_bool; use crate::xvalue_byte::new_char_byte; @@ -785,18 +784,6 @@ pub extern "C" fn kvspaceClear(h: *mut Handle, err: *mut c_char, err_cap: u32) - result_to_code(catch_panic(|| kv.clear()), err, err_cap) } -#[no_mangle] -pub extern "C" fn kvspaceDisconnect(h: *mut Handle, err: *mut c_char, err_cap: u32) -> c_int { - let kv: &mut dyn KVSpace = match unsafe { kv_flush(h) } { - Ok(k) => k, - Err(e) => { - write_err(err, err_cap, &e); - return 1; - } - }; - result_to_code(catch_panic(|| kv.dis_conn()), err, err_cap) -} - // ── XValue 编解码(head/TLV + 标准标量构造器) ───────────────────────── /// 通用 TLV 编码(内联,ref=0)。dims/ndim 直接落盘:ndim=0 标量,dims 可为 NULL。 diff --git a/src/fs/kvspace.rs b/src/fs/kvspace.rs index 39b4242..3b88964 100644 --- a/src/fs/kvspace.rs +++ b/src/fs/kvspace.rs @@ -7,14 +7,14 @@ use std::os::unix::fs::FileExt; use std::path::{Path, PathBuf}; use std::time::Duration; -use crate::coord::{cmp_coord, grow_coord_dims, is_coord, parse_coord}; +use crate::coord::cmp_coord; use crate::kvspace::{KVPair, KVSpace}; use crate::kvspace_common::{ - join_path, sep_path, split_index, strip_dir_suf, validate_ptr, watch_value, SepKind, + join_path, sep_path, split_index, strip_dir_suf, validate_ptr, watch_value, }; use crate::r#const::*; use crate::xvalue::*; -use crate::xvalue_index::{new_ext_index, new_index, new_map_index}; +use crate::xvalue_index::{new_ext_index, new_index}; const EXTINDEX_MARKER: &str = "__extindex__"; const SELF_MARKER: &str = "__self__"; @@ -61,18 +61,6 @@ impl FsKVSpace { self.root.join(rel.trim_start_matches('/')) } - /// fs 路径 → kvspace key:'·/' → '·' - fn key_of(&self, path: &Path) -> String { - let rel = path.strip_prefix(&self.root).unwrap_or(path); - let pat = [OBJ_SEP, "/"].concat(); - let s = rel.to_string_lossy().replace(pat.as_str(), OBJ_SEP); - if s.is_empty() { - PATH_SEP.to_string() - } else { - format!("/{}", s) - } - } - fn is_dir_key(key: &str) -> bool { key.ends_with(DIR_INDEX_SUF) || key.ends_with(OBJ_SEP) } @@ -143,14 +131,6 @@ impl FsKVSpace { } } - fn suffix_for(key: &str) -> &'static str { - if key.ends_with(OBJ_SEP) && !key.ends_with(DIR_INDEX_SUF) { - OBJ_SEP - } else { - DIR_INDEX_SUF - } - } - fn parent_name(path: &str) -> (String, String) { let mut path = path.to_string(); if Self::is_dir_key(&path) && path != PATH_SEP { @@ -710,13 +690,4 @@ impl KVSpace for FsKVSpace { let _ = fs::create_dir_all(&self.root); Ok(()) } - - fn dis_conn(&mut self) -> Result<(), String> { - Ok(()) - } -} - -// 供测试用:返回 root 下的顶层条目数。 -pub fn top_level_count(kv: &FsKVSpace) -> usize { - fs::read_dir(&kv.root).map(|d| d.count()).unwrap_or(0) } diff --git a/src/kvspace.rs b/src/kvspace.rs index f1d7aac..e57d503 100644 --- a/src/kvspace.rs +++ b/src/kvspace.rs @@ -105,5 +105,4 @@ pub trait KVSpace { fn del_ext_index(&mut self, path: &str) -> Result<(), String>; fn clear(&mut self) -> Result<(), String>; - fn dis_conn(&mut self) -> Result<(), String>; } diff --git a/src/lib.rs b/src/lib.rs index cec5b65..3490fec 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,4 @@ -#![allow(unused)] -#![allow(non_snake_case)] - -// kvspace-durable — 严格翻译 kvspace-go。 -// 文件对应:const.go → const.rs,xvalue*.go → xvalue*.rs,kvspace.go → kvspace.rs, -// kvspace_common.go → kvspace_common.rs,conn.go → conn.rs,redis/kvspace.go → backend.rs + redis/store.rs。 +// kvspace-durable — 可嵌入的 KVSpace(Rust),对齐 kvspace ABI 与线格式。 // 后端:redis、fs(goheap/shm 不属本项目)。 pub mod r#const; diff --git a/src/redis/store.rs b/src/redis/store.rs index ad1ded0..6974093 100644 --- a/src/redis/store.rs +++ b/src/redis/store.rs @@ -106,7 +106,11 @@ impl RedisStore { } enum Resp { + // 字段 0 暂未被读取——Redis 错误文本当前被静默丢弃,待接入 Result 错误传播后启用(见 todo) + #[allow(dead_code)] Simple(String), + // 同上 + #[allow(dead_code)] Error(String), Integer(i64), Bulk(Option>), diff --git a/src/xvalue.rs b/src/xvalue.rs index cd2823d..37f686b 100644 --- a/src/xvalue.rs +++ b/src/xvalue.rs @@ -308,33 +308,6 @@ impl XValue { matches!(self, XValue::Ptr(_)) } - pub fn byte_len(&self) -> i32 { - match self { - XValue::None => 0, - XValue::Ptr(p) => p.target.len() as i32, - XValue::Bool(d) => d.data.len() as i32, - XValue::Int8(d) => d.data.len() as i32, - XValue::Int16(d) => (d.data.len() * 2) as i32, - XValue::Int32(d) => (d.data.len() * 4) as i32, - XValue::Int64(d) => (d.data.len() * 8) as i32, - XValue::Uint8(d) => d.data.len() as i32, - XValue::Uint16(d) => (d.data.len() * 2) as i32, - XValue::Uint32(d) => (d.data.len() * 4) as i32, - XValue::Uint64(d) => (d.data.len() * 8) as i32, - XValue::Float32(d) => (d.data.len() * 4) as i32, - XValue::Float64(d) => (d.data.len() * 8) as i32, - XValue::CharByte(d) => d.data.len() as i32, - XValue::CharAscii(d) => d.data.len() as i32, - XValue::Char32(d) => (d.data.len() * 4) as i32, - XValue::Map(_) => 1, - XValue::Index(d) => crate::xvalue_index::encode_index(d).1.len() as i32, - XValue::ExtIndex(e) => crate::xvalue_index::encode_ext_index(&e.ext_path, &e.childs) - .1 - .len() as i32, - XValue::Opaque(o) => o.body.len() as i32, - } - } - pub fn array_len(&self) -> i32 { match self { XValue::None => 0, diff --git a/src/xvalue_byte.rs b/src/xvalue_byte.rs index 97f5b8f..f8b6ec1 100644 --- a/src/xvalue_byte.rs +++ b/src/xvalue_byte.rs @@ -14,12 +14,6 @@ pub fn new_char_byte(v: &[u8]) -> XValue { dims: char_dims(v.len()), }) } -pub fn new_char_ascii(v: &[u8]) -> XValue { - XValue::CharAscii(Arr { - data: v.to_vec(), - dims: char_dims(v.len()), - }) -} pub fn new_char32(v: &[u32]) -> XValue { XValue::Char32(Arr { data: v.to_vec(), diff --git a/src/xvalue_int.rs b/src/xvalue_int.rs index 6e50c4d..e7f8100 100644 --- a/src/xvalue_int.rs +++ b/src/xvalue_int.rs @@ -3,24 +3,6 @@ use crate::r#const::*; use crate::xvalue::{dims_from_len, encode_head, Arr, XValue}; -pub fn new_int8(v: &[i8]) -> XValue { - XValue::Int8(Arr { - data: v.to_vec(), - dims: dims_from_len(v.len()), - }) -} -pub fn new_int16(v: &[i16]) -> XValue { - XValue::Int16(Arr { - data: v.to_vec(), - dims: dims_from_len(v.len()), - }) -} -pub fn new_int32(v: &[i32]) -> XValue { - XValue::Int32(Arr { - data: v.to_vec(), - dims: dims_from_len(v.len()), - }) -} pub fn new_int64(v: &[i64]) -> XValue { XValue::Int64(Arr { data: v.to_vec(), diff --git a/src/xvalue_uint.rs b/src/xvalue_uint.rs index 99c8598..d5fceae 100644 --- a/src/xvalue_uint.rs +++ b/src/xvalue_uint.rs @@ -1,32 +1,7 @@ // xvalue_uint.rs — 对齐 xvalue_uint.go use crate::r#const::*; -use crate::xvalue::{dims_from_len, encode_head, Arr, XValue}; - -pub fn new_uint8(v: &[u8]) -> XValue { - XValue::Uint8(Arr { - data: v.to_vec(), - dims: dims_from_len(v.len()), - }) -} -pub fn new_uint16(v: &[u16]) -> XValue { - XValue::Uint16(Arr { - data: v.to_vec(), - dims: dims_from_len(v.len()), - }) -} -pub fn new_uint32(v: &[u32]) -> XValue { - XValue::Uint32(Arr { - data: v.to_vec(), - dims: dims_from_len(v.len()), - }) -} -pub fn new_uint64(v: &[u64]) -> XValue { - XValue::Uint64(Arr { - data: v.to_vec(), - dims: dims_from_len(v.len()), - }) -} +use crate::xvalue::{encode_head, Arr}; pub fn decode_uint8(body: &[u8], dims: &[i32]) -> Arr { Arr {