多模冗余 XMR API
多模冗余(X-Modular Redundancy)投票层:把「N 份冗余 + 投票选举」收敛为按组名 join 的位置透明角色。两个变体(Full / Tiny)均支持,头文件
onepath_xmr.h。可靠性模型与能力边界见 多模冗余(XMR)。
数据类型
onepath_xmr_t
typedef struct onepath_xmr *onepath_xmr_t;XMR 长驻角色句柄(worker / 投票消费端 / 存储副本),不透明。由 onepath_xmr_compute / onepath_xmr_consume / onepath_xmr_store 创建,由 onepath_xmr_close 销毁。
onepath_xmr_sink_t
typedef struct onepath_xmr_sink onepath_xmr_sink_t;worker 计算结果输出汇,不透明。由 XMR 在调用 worker 计算函数时传入,worker 通过 onepath_xmr_emit() 向其发射结果。
onepath_xmr_result_t
选举结果,作为投票消费端 / 读端选举回调的参数。data 指向选举出的值,仅在回调期间有效。
typedef struct {
const char *group; /* 组名 */
uint64_t seq; /* 计算: 任务序号; 存储: 0 */
const char *sign; /* 存储: 数据键; 计算: NULL */
const void *data; /* 选举出的值 */
size_t data_len; /* 值长度 (字节) */
int votes; /* 与胜者一致的票数 */
int n; /* 参与投票的候选数 (已剔除 CRC 失败者) */
int agreed; /* 1 = 达到多数 (可靠); 0 = 无定论 (DMR 检出分歧) */
} onepath_xmr_result_t;| 字段 | 类型 | 含义 |
|---|---|---|
group | const char * | 组名 |
seq | uint64_t | 计算场景:任务序号;存储场景:0 |
sign | const char * | 存储场景:数据键(组内相对 sign);计算场景:NULL |
data | const void * | 选举出的值(仅回调期间有效) |
data_len | size_t | 值长度(字节) |
votes | int | 与胜者一致的票数 |
n | int | 参与投票的候选数(已剔除 CRC 失败者) |
agreed | int | 1 = 达到多数(结果可靠);0 = 无定论(DMR 检出分歧) |
agreed=0 时结果不应被当作可靠结果(见 多模冗余(XMR))。
onepath_xmr_result_cb
typedef void (*onepath_xmr_result_cb)(void *ud, const onepath_xmr_result_t *r);选举结果回调。onepath_xmr_consume 在每次选举出计算结果时调用,onepath_xmr_get 对每个选举出的键调用一次。
- 参数:
ud— 用户上下文(创建时透传)r— 选举结果,仅回调期间有效
onepath_xmr_compute_fn
typedef void (*onepath_xmr_compute_fn)(void *ud, const void *in, size_t in_len,
onepath_xmr_sink_t *sink);worker 计算函数:对一条任务输入产出一份结果,经 onepath_xmr_emit() 发射到 sink。
- 参数:
ud— 用户上下文(onepath_xmr_compute创建时透传)in— 任务输入指针in_len— 任务输入长度(字节)sink— 结果输出汇,传给onepath_xmr_emit()
onepath_xmr_candidate_t
一个投票候选,供自定义投票函数使用。
typedef struct {
const void *data; /* 候选值指针 */
size_t len; /* 候选值长度 */
} onepath_xmr_candidate_t;| 字段 | 类型 | 含义 |
|---|---|---|
data | const void * | 候选值指针 |
len | size_t | 候选值长度 |
onepath_xmr_vote_fn
typedef int (*onepath_xmr_vote_fn)(void *ud, const onepath_xmr_candidate_t *c,
size_t n, size_t *winner);自定义投票函数。从 n 个候选中选出胜者,写入胜者索引到 *winner 并返回 ONEPATH_OK;无定论时返回非 0。传 NULL 表示使用默认精确多数投票。
- 参数:
ud— 用户上下文(vote_ud透传)c— 候选数组n— 候选数量winner— 输出胜者索引
- 返回值:
ONEPATH_OK选出胜者,非 0 无定论
选项
onepath_xmr_opts_t
typedef struct {
int expected;
int quorum;
uint32_t window_ms;
onepath_xmr_vote_fn vote_fn;
void *vote_ud;
int integrity;
const char *republish_sign;
const char *node_id;
const char *encoding;
} onepath_xmr_opts_t;XMR 选项。传 NULL 给各入口即全部取默认值。
| 字段 | 类型 | 含义 | 默认 |
|---|---|---|---|
expected | int | 钉死 N;0 = 存活感知自动计数 | 0(auto) |
quorum | int | 需多少票一致;0 = 多数 ⌊N/2⌋+1 | 0 |
window_ms | uint32_t | 一次选举的收齐超时(毫秒);0 = 默认 2000 | 0(2000 ms) |
vote_fn | onepath_xmr_vote_fn | 自定义投票函数;NULL = 精确多数 | NULL |
vote_ud | void * | 透传给 vote_fn 的上下文 | NULL |
integrity | int | 端到端校验模式:ONEPATH_XMR_CRC32 / ONEPATH_XMR_NONE | ONEPATH_XMR_CRC32 |
republish_sign | const char * | 消费端非空则把选举结果转发到此 sign 供下游扇出;NULL = 仅回调 | NULL |
node_id | const char * | 覆盖自动服务 ID(sid)编号;NULL = 用本节点 sid | NULL |
encoding | const char * | 发布编码;NULL = 默认 | NULL |
同组一致性
同一组内各角色的 integrity 设置应一致(默认全开即一致)。
ONEPATH_XMR_OPTS_DEFAULT
#define ONEPATH_XMR_OPTS_DEFAULT \
{ 0, 0, 0, NULL, NULL, ONEPATH_XMR_CRC32, NULL, NULL, NULL }onepath_xmr_opts_t 的默认初始化宏,按字段顺序展开为:expected=0、quorum=0、window_ms=0、vote_fn=NULL、vote_ud=NULL、integrity=ONEPATH_XMR_CRC32、republish_sign=NULL、node_id=NULL、encoding=NULL。等价于传 NULL 给各入口。
计算 NMR
onepath_xmr_submit
int onepath_xmr_submit(onepath_session_t s, const char *group,
const void *data, size_t len);生产者:向 XMR 组提交一条计算任务。任务被组内全部 worker 订阅,每次调用自增内部任务序号。
- 参数:
s— 会话句柄group— 组名data— 任务数据指针len— 任务数据长度(字节)
- 返回值:
ONEPATH_OK成功,ONEPATH_ERR_PARAM参数无效
onepath_xmr_compute
int onepath_xmr_compute(onepath_session_t s, onepath_xmr_t *out,
const char *group,
onepath_xmr_compute_fn fn, void *ud,
const onepath_xmr_opts_t *opts);worker:加入 XMR 组,订阅任务并发布计算结果。可在任意机器上 spawn 任意多个;自动声明存活感知供投票端感知 N。
- 参数:
s— 会话句柄out— 成功时写入角色句柄group— 组名fn— 计算函数(见 onepath_xmr_compute_fn)ud— 透传给fn的上下文opts— 选项,传NULL使用全默认
- 返回值:
ONEPATH_OK成功,ONEPATH_ERR_PARAM参数无效,ONEPATH_ERR声明失败 - 注意:使用完毕后须调用
onepath_xmr_close()销毁
onepath_xmr_consume
int onepath_xmr_consume(onepath_session_t s, onepath_xmr_t *out,
const char *group,
onepath_xmr_result_cb cb, void *ud,
const onepath_xmr_opts_t *opts);投票消费端(= voter + consumer 合并):订阅组内全部 worker 结果,按任务序号分组,CRC 校验剔除被翻转者,达到多数(或 window_ms 超时)即投票并回调选举结果。这是「边缘投票」:在消费侧本地完成,不依赖单独的投票节点(无单点)。opts->republish_sign 非空时同时把选举结果转发到该 sign 供下游扇出。
- 参数:
s— 会话句柄out— 成功时写入角色句柄group— 组名cb— 选举结果回调(见 onepath_xmr_result_cb)ud— 透传给cb的上下文opts— 选项,传NULL使用全默认
- 返回值:
ONEPATH_OK成功,ONEPATH_ERR_PARAM参数无效,ONEPATH_ERR声明失败 - 注意:使用完毕后须调用
onepath_xmr_close()销毁
onepath_xmr_emit
int onepath_xmr_emit(onepath_xmr_sink_t *sink,
const void *out, size_t len);在 worker 计算函数内产出一份结果,发射到传入的 sink。
- 参数:
sink— 传入计算函数的输出汇out— 结果数据指针len— 结果数据长度(字节)
- 返回值:
ONEPATH_OK成功,ONEPATH_ERR_PARAM参数无效
存储 NMR
onepath_xmr_store
int onepath_xmr_store(onepath_session_t s, onepath_xmr_t *out,
const char *group,
const onepath_xmr_opts_t *opts);存储副本:加入 XMR 组,订阅写入并存储,应答读取查询。可在任意机器 spawn 任意多个组成冗余副本。
- 参数:
s— 会话句柄out— 成功时写入角色句柄group— 组名opts— 选项,传NULL使用全默认
- 返回值:
ONEPATH_OK成功,ONEPATH_ERR_PARAM参数无效,ONEPATH_ERR声明失败 - 注意:使用完毕后须调用
onepath_xmr_close()销毁
onepath_xmr_put
int onepath_xmr_put(onepath_session_t s, const char *group,
const char *sign, const void *data, size_t len);写入:向 XMR 组写一个键值,广播到全部副本。
- 参数:
s— 会话句柄group— 组名sign— 数据键(组内相对 sign,如"sensor/temp")data— 值数据指针len— 值长度(字节)
- 返回值:
ONEPATH_OK成功,ONEPATH_ERR_PARAM参数无效
onepath_xmr_get
int onepath_xmr_get(onepath_session_t s, const char *group,
const char *sign,
const onepath_xmr_opts_t *opts,
onepath_xmr_result_cb cb, void *ud);读取并选举:查询全部副本,按键投票选出可靠值(读端边缘投票)。CRC 校验剔除被翻转的回复后投票,对每个选举出的键回调一次 cb。
- 参数:
s— 会话句柄group— 组名sign— 组内相对 sign(通配或具体键)opts— 选项,传NULL使用全默认cb— 每个选举键的结果回调(见 onepath_xmr_result_cb)ud— 透传给cb的上下文
- 返回值:选举出的键数(
>=0),或负的错误码
通用
onepath_xmr_close
void onepath_xmr_close(onepath_xmr_t h);关闭并销毁 XMR 角色句柄(worker / 投票消费端 / 存储副本通用)。
- 参数:
h— 角色句柄,可为NULL
常量
完整性校验模式,用于 onepath_xmr_opts_t.integrity。
| 常量 | 值 | 含义 |
|---|---|---|
ONEPATH_XMR_NONE | 0 | 不加端到端校验 |
ONEPATH_XMR_CRC32 | 1 | 每份结果带 CRC32(默认) |
内存与所有权
- 句柄创建 / 销毁配对:
onepath_xmr_compute/onepath_xmr_consume/onepath_xmr_store创建的角色句柄,均须由onepath_xmr_close()销毁;onepath_xmr_close(NULL)安全。 - 结果生命周期:
onepath_xmr_result_t.data及回调内指针仅在回调期间有效,如需保留请自行拷贝。 - 选项所有权:
onepath_xmr_opts_t中字符串字段(republish_sign/node_id/encoding)由调用方持有;入口在创建时按需拷贝,调用返回后调用方即可释放原字符串。 - 会话关闭顺序:销毁角色句柄应在关闭会话之前完成。资源销毁顺序见 内存管理。
相关指南
- 多模冗余(XMR) — 设计要点、N / quorum / 投票策略、可靠性模型与能力边界、跨节点快速开始。