news 2026/9/17 2:13:39

深入解读 MongoDB 内置 WiredTiger 的 C/C++ 编码规范与贡献流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入解读 MongoDB 内置 WiredTiger 的 C/C++ 编码规范与贡献流程

深入解读 MongoDB 内置 WiredTiger 的 C/C++ 编码规范与贡献流程

【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo

WiredTiger 是 MongoDB 默认的存储引擎,其完整源码以第三方库形式内嵌于本仓库的 src/third_party/wiredtiger 目录中。本文以该目录下的 CONTRIBUTING.rst 为骨架,系统梳理 WiredTiger 的社区贡献流程、C 与 C++ 双编码规范、命名体系、注释约定以及自动化校验工具s_all的用法,并结合仓库内真实源码给出可验证的示例,帮助你在向 WiredTiger 提交 PR 前写出风格统一、易于审查的代码。

读完本文,你将掌握:WiredTiger 的 PR 提交入口与 Jira 工单规则、C 代码必须遵守的缩进/命名/注释/错误处理约定、FIXME-WT-XXXX与自动旗标宏的用法,以及如何运行dist/s_all在本地完成提交前的一站式风格校验。

WiredTiger 项目与贡献入口

WiredTiger 12.0.0 版本随 MongoDB 一并分发,源码中附带的 README 明确了项目事实:完整源码与文档发布在 WiredTiger 官方网站,问题管理统一使用 WiredTiger 的 Jira 实例(issue 前缀为WT),并且不通过 GitHub Issues 报告问题

CONTRIBUTING.rst 开篇即表明态度:Pull requests 永远欢迎,WiredTiger 开发团队感激社区提供的任何帮助。关于贡献细节(提交 PR 前的完整流程、代码评审要求等),文档要求参考 WiredTiger Wiki 上专门的 "Contributing to WiredTiger" 页面。

从仓库结构看,WiredTiger 的工程化程度相当高,dist/目录下集中了数十个配套的检查与生成脚本(如s_clang_formats_styles_whitespaces_defines_docss_export等),配合dist/s_all一键执行全部预提交校验,这一点在后文专门展开。

为什么需要 C 与 C++ 两套编码风格

WiredTiger 对 C 和 C++ 分别维护编码规范,核心原因是:C 中很多合理甚至必要的写法,在 C++ 里恰恰是糟糕实践(bad practice)。例如 C 里常见的宏封装、void *自由转换、手工错误码传递等,在 C++ 中都有更安全的替代方案,强行套用反而掩盖问题。

具体分工如下:

  • C:WiredTiger 存储引擎主体,全部由 C 编写;
  • C++:面向开发者的辅助工具,例如cppsuite(C++ 测试套件)与workgen(负载生成工具)。

因此评审代码时,先确认目标文件属于引擎主体(C)还是工具(C++),再套用对应的规范,而不是笼统地用同一把尺子。

WiredTiger C 编码规范全解

文档明确指出:C 编码标准“松散地”基于 K&R 缩进风格,并交由Clang-Format统一格式化,因此下面列出的规则主要服务于人工阅读与命名纪律。遇到规则没有覆盖的模糊地带,最好的做法是在源码里找一个现成例子照抄——这是 WiredTiger 官方给出的建议,也说明仓库源码本身就是规范的最佳范本。

缩进、空白与字符集

  • 缩进一律使用空格而非制表符 Tab;
  • 行尾不得残留空白字符(trailing whitespace);
  • 源文件只允许7-bit ASCII字符;
  • 换行缩进(re-indent)固定为2 个空格
  • 行宽上限100 字符,换行时在运算符之后断开。

上述 100 列与 2 空格续行缩进在仓库根目录的 .clang-format 中得到印证:ColumnLimit: 100ContinuationIndentWidth: 2,同时UseTab: Never强制禁 Tab、PointerAlignment: Right将指针星号靠右对齐,与文档中“指针右对齐”的示例一致。

声明顺序与字母序

凡是成组的声明都应尽量按字母序排列,包括局部变量、旗标(flags)、统计字段(stat fields)等。文档给出的函数内声明顺序是:先放struct变量声明,再放WT_*结构声明,且WT_*之间按字母序:

struct timeval start, end; WT_CKPT *ckpt; WT_CONNECTION_IMPL *conn;

这一约定在真实源码中随处可见,例如 btmem.h 中WT_READ_*旗标宏按字母序连续排列。

注释规范

注释是 WiredTiger 风格检查的重点,要求如下:

  • 描述预期功能(intended functionality),而非记录已发生的事;
  • 尽量不引用变量名
  • 不得引用已关闭的 Jira 工单号,也不得引用 PR 编号;
  • 描述缺陷或改进机会时,使用FIXME-WT-XXXX关键字,且必须对应一个仍处于打开状态的 WiredTiger Jira 工单;工单一旦关闭,就要移除或重新定向该注释;
  • 必须写成完整句子
  • 使用 C 风格/* ... */注释,禁止C++ 风格的//双斜杠注释;
  • 单行注释的定界符与正文同行;多行注释的定界符独占一行,且正文每行以星号开头:
/* This is a valid comment. */ // This is not a valid comment. /* * This is a valid * multi-line comment. */ // This is not a // valid multi-line comment.

FIXME-WT-XXXX约定在源码中有大量真实落点,例如 block_open.c 的FIXME-WT-5832、block_cache.c 的FIXME-WT-15663、block_io.c 的FIXME-WT-14608。配套的 s_outdated_fixmes.py 脚本会专门扫描这些引用是否已失效,形成“写注释—工单绑定—自动校验”的闭环。

函数头注释与字段注释

每个函数定义之前都必须有固定格式的头注释:

/* * __wt_foo -- * One-sentence description of what the function does. */ int __wt_foo(WT_SESSION_IMPL *session, ...)

要点:函数名独占一行,后跟空格和--;描述正文相对星号缩进 4 个空格(即文本起始于第 8 列);多个段落之间用独立的*空行分隔。

结构体与 typedef 字段的注释采用行尾短名词短语:

uint32_t id; /* File ID, for logging */ const char *key_format; /* Key format */

分组级别的说明应放在结构体上方或字段组上方的块注释中,永远不要放在单个字段之上。另外,版权块与第一个#include之间不得放置任何文件级总览注释

旗标定义区间

旗标宏定义必须包裹在自动生成标记对之间:

/* AUTOMATIC FLAG VALUE GENERATION START 0 */ #define WT_READ_CACHE 0x00001u ... /* AUTOMATIC FLAG VALUE GENERATION STOP 32 */

真实例子见 btmem.h,dist/flags.py等生成脚本会维护这段区间内的位值,手工添加或修改其中的宏都会与自动生成逻辑冲突。

命名体系:前缀即作用域

WiredTiger 通过前缀精确表达符号的可见范围,这是理解其代码库的关键地图:

前缀作用域示例
wiredtiger公开 API 函数wiredtiger_open
WT_公开的宏与结构体 typedefWT_ERRWT_SESSION
__wt_跨文件、跨子系统使用的内部函数__wt_cursor_set_key
__wti_同一子系统目录内、跨文件使用的内部函数各子系统内共享函数
__(双下划线)静态函数子系统内部私有函数

__wt___wti_中的“前缀”是子系统标识符(如logbtree)。以__wt_cursor_set_key为例,它在 cur_backup_incr.c 等跨目录文件中被调用,符合“跨文件跨子系统使用__wt_”的规则。

同时,命名空间隔离还要求避免与应用程序代码和系统头文件冲突:公有 API 以wiredtiger开头,公有宏/类型以WT_开头,私有函数以__wt_开头。

函数签名与返回值约定

函数声明中返回值独占一行,函数名顶到左边界:

int __wt_square(int x) { return (x * x); }

输出参数命名p结尾,且放在参数列表末尾:

static inline void __ref_index_slot(WT_SESSION_IMPL *session, WT_REF *ref, WT_PAGE_INDEX **pindexp, uint32_t *slotp)

返回指针填充约定:若函数通过输出参数返回指针(如WT_FH **fhpp),且成功路径上总会填充该指针,则函数开头必须先把它置为 NULL。这样调用方无需自行初始化,也保证失败或异常路径上调用方永远不会读到随机数据。

变量命名与初始化

  • 使用描述性变量名与函数名,全小写加下划线分隔;常用 WiredTiger 结构有标准简称:WT_SESSION/WT_CONNECTION写作wt_session/wt_connWT_SESSION_IMPL/WT_CONNECTION_IMPL写作session/conn
  • 强烈建议(非强制)在使用处就近声明并初始化变量,把变量作用域压缩到最小;
  • 优先“声明即初始化”;若初始化并非必需、只是编译器要求,则用注释/* -Werror=maybe-uninitialized */标注。

表达式与语句习惯

  • 指针与NULL比较,写(p == NULL)不要(p == 0)(!p)
  • 无限循环用for(;;)不要while(true)
  • 函数返回值用括号包裹:return (0);
  • 单语句的 if/循环不加花括号,除非不加会引发歧义;
  • 换行时让后续行尽可能更长(successive lines are longer if possible),函数签名同样适用;拿不准就交给 Clang-Format 处理。

错误处理的两段式风格

文档给出了错误处理的两种标准形态,这是 WiredTiger 代码中最具辨识度的模式:

情形一:失败与非失败路径有共享代码,采用if (0) { err: ... }模式:

if (0) { err: <non-shared fail code> } <shared fail/non-fail code> return (ret);

情形二:失败与非失败路径无共享代码,采用跳转标签直落模式:

<non-fail code> return (0); err: <fail code> return (ret);

注意情形二中没有if (0)包装,直接以err:标签结束失败分支。结合WT_ERR宏(公开命名空间示例)理解,这种“错误码 + 标签跳转”是 WiredTiger 一贯的错误传播方式。

C++ 编码风格(cppsuite 与 workgen)

CONTRIBUTING.rst 明确说明 WiredTiger只为 C 提供独立规范章节,C++ 部分由cppsuiteworkgen等工具遵循各自的 C++ 惯例。仓库中 cppsuite 相关源码位于 src/third_party/wiredtiger/test 下的对应子目录,workgen作为基准测试工具同样使用 C++ 实现。撰写 C++ 代码时应遵循通用 C++ 最佳实践,并同样通过 Clang-Format(仓库 .clang-format 的Language: Cpp配置对 C/C++ 一并生效)保证格式一致。

提交前的终极校验:运行 dist/s_all

编码完成后,文档要求运行./s_all脚本(即仓库中的 dist/s_all),它会自动重排代码以贴合规范的大部分要求。文档同时提醒:没有任何工具能检查所有事项——比如“函数名是否足够描述性”,工具就无从判断,最终仍依赖人的审查。

s_all的实际能力远超单纯格式化。从 dist/s_all 脚本源码看,它是一站式预提交套件,内部先串行执行s_versions_readmes_installapi_config_gen.pyapi_err.pyflags.pystat.pys_copyrights_styles_clang_formatprototypes.pys_typedefruff_check.py等脚本,再并行跑s_defines_docss_exports_funcss_langs_longliness_whitespaces_charsets_include_guardss_bazel.py等二十余项检查,覆盖版权头、风格、空白、字符集、函数原型、typedef、导出符号、文档一致性、Python 代码(Ruff)等方方面面。

s_all 命令行选项

选项含义
-E失败时返回非零错误码(适合 CI 集成)
-f强制更新版本号相关文件
-F快速模式:仅处理从 develop 分支分叉后发生变更的文件
--no-interactive禁用交互式终端状态显示
-h, --help显示帮助

在本地开发流程中,-F快速模式适合改动较小时使用;提交 CI 前用-E确保脚本失败即报错。运行前置条件包括python3clang-format,脚本启动时会显式检查两者是否存在。

提交 PR 的完整工作流建议

综合文档与仓库工具链,向 WiredTiger 提交贡献的推荐流程如下:

  1. 对照本文规范自检:命名(wiredtiger/WT_/__wt_/__wti_/__)、注释(FIXME-WT-XXXX指向打开中的工单)、错误处理两段式、指针置 NULL 约定;
  2. 运行dist/s_all:在src/third_party/wiredtiger目录下执行./dist/s_all,或使用./dist/s_all -F快速模式、-E失败即报错模式,修复全部报错项;
  3. 提交 PR:按 WiredTiger Wiki 的贡献指南走完 Pull Request 流程;
  4. 工单纪律:涉及缺陷/改进点的注释必须绑定打开的 WiredTiger Jira 工单,工单关闭后及时清理对应FIXME-WT-XXXX注释。

结语

WiredTiger 的贡献规范与其代码库一样追求“机器可解析 + 人类可读”的双重目标:机器层面由dist/s_all与 Clang-Format 完成格式、空白、原型、符号等一切可自动化的检查;人的层面则依靠命名前缀、注释纪律与错误处理模式来传达代码意图。对 MongoDB 开发者而言,这套规范既是贡献 WiredTiger 的门槛,也是阅读 src/third_party/wiredtiger/src 海量引擎源码时最实用的“解码手册”。

【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 2:13:37

版本管理不只是一串数字:从SolidWorks PDM到对象级PLM的演进

1. 为什么版本管理总被当成“给文件名1”先说一个我亲眼见过的场景。工艺部门接到现场投诉&#xff1a;批量装配时发现一个支架零件装不上&#xff0c;防转销孔的位置差了不到 0.05mm。我去查图纸&#xff0c;发现发到车间的PDF图纸文件名是“支架_V2”&#xff0c;车间老张电脑…

作者头像 李华
网站建设 2026/9/17 2:12:51

灰狼算法优化VMD参数:MATLAB实现与故障诊断应用

简介&#xff1a;面向机械故障诊断与信号处理研究者的MATLAB工具包&#xff0c;提供基于灰狼优化算法&#xff08;GWO&#xff09;对变分模态分解&#xff08;VMD&#xff09;参数进行智能寻优的完整实现&#xff0c;可有效解决VMD分解中惩罚因子与模态个数依赖人工经验设定的难…

作者头像 李华
网站建设 2026/9/17 2:09:27

Notepad-- 插件更新:从查看版本到完成替换的完整操作路径

Notepad-- 插件更新&#xff1a;从查看版本到完成替换的完整操作路径 【免费下载链接】notepad-- 一个支持windows/linux/mac的文本编辑器&#xff0c;目标是做中国人自己的编辑器&#xff0c;来自中国。 项目地址: https://gitcode.com/GitHub_Trending/no/notepad-- N…

作者头像 李华
网站建设 2026/9/17 2:07:48

Nomo | 所见即所得的 Markdown 编辑器

链接&#xff1a;https://pan.quark.cn/s/8acd39e60ad7Nomo 是一款本地优先、Markdown-first 的桌面编辑器&#xff0c;支持 macOS 与 Windows。它以 Markdown 文本作为文档主数据&#xff0c;在语义编辑与源码模式之间保持一致&#xff0c;同时提供 TXT、JSON 大文件分段编辑、…

作者头像 李华
网站建设 2026/9/17 2:06:08

粒子群算法(PSO)优化PID参数整定:从仿真到工程落地

简介&#xff1a;面向自动控制与智能优化算法学习者&#xff0c;这份基于MATLAB/Simulink环境的压缩包提供了一个使用粒子群优化算法进行PID控制器参数整定的完整示例。资源共包含七个文件&#xff0c;其中两个脚本分别实现粒子群搜索逻辑与误差追踪评估&#xff0c;三个模型用…

作者头像 李华