GlusterFS 编码规范

本文档详细介绍了GlusterFS项目的编码规范,包括变量声明、初始化、指针使用、系统调用处理等方面的要求,旨在提高代码质量和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GlusterFS 编码规范

1. 每个结构成员需要有一条能够说明其用途的注释

Bad:

         gf_lock_t lock; /* lock */

Good:

         DBTYPE access_mode; /* access mode for accessing

                                     *the databases, can be

                                     *DB_HASH, DB_BTREE

                                     *(option access-mode <mode>)

                                     */

 

2. 在函数的开始声明所有变量

所有函数中的局部变量必须在"{ "之后立刻声明,这样可以帮助跟踪在退出时需要free的内存,同时还有助于debug,因为gdb不能处理在循环或者类似的块中声明的变量

 

 

3. 永远要初始化变量

每个局部变量需要在声明的时候就被初始化到一个合理的初值,所有的指针需要初始化为NULL,所有的整数需要初始化为零,或者一个错误代码。

Good:

         int ret = 0;

         char *databuf = NULL;

         int _fd = -1;

 

4. 永远用常量来初始化

不要用一个表达式来初始化变量

Bad:

pid_t pid = frame->root->pid;

char *databuf = malloc (1024);

 

5. 验证函数的所有参数

需要检查所有指针类型的参数是否为NULL.

在common-utils.h中定义的宏 VALIDATE,可以验证一个参数是否为NULL,如果是,则写一条log然后跳到err标志处

 

Good:

VALIDATE(frame);

VALIDATE(this);

VALIDATE(inode);

 

6. 不要依赖于操作符优先级(健忘症者的福音)

这样的代码很难读,也许其它人没有你对优先级了解的那么多

 

Bad:

if (op_ret == -1 && errno != ENOENT)

Good:

if ((op_ret == -1) && (errno != ENOENT))

 

7. 使用精确的数据类型

使用库函数在manual中声明的返回类型,不要用他们的"等价类型"

Bad:

int len = strlen (path);

Good:

size_t len = strlen (path);

 

8. 不要写类似foo->bar->baz的 指针链

在使用之前需要检查所有指针是否为NULL

 

9. 检查所有的系统调用或者API函数的返回值(success|failure.

Bad:

close (fd);

Good:

op_ret = close (_fd);

if (op_ret == -1) {

gf_log (this->name, GF_LOG_ERROR,

"close on file %s failed (%s)", real_path,

strerror (errno));

op_errno = errno;

goto out;

}

 

10.优雅的处理malloc错误

GlusterFS不应该因为缺少内存crash或者退出,如果内存分配失败,调用应该被unwound,错误应该返回给用户

 

11. 使用返回参数,并且保留函数返回值,来说明函数的成功和失败

如果一个函数需要返回更多的数据,使用指针,返回值一般用来标识函数是否成功。

Bad:

int32_t dict_get_int32 (dict_t *this, char *key);

 

Good:

int dict_get_int32 (dict_t *this, char *key, int32_t *val);

 

12. 使用带“n”的字符串函数

 

Bad:

strcpy (entry_path, real_path);

Good:

strncpy (entry_path, real_path, entry_path_len);

 

13. 不应该有从来不被执行的代码,或者被注释掉得代码

 

14. 每个函数中只有一个地方可以UNWIND或者返回

 

15. 控制每个函数的规模

每个函数控制在2到3页(80行),超过这个规模可以写多个helper函数

 

helper函数的例子

static int

same_owner (posix_lock_t *l1, posix_lock_t *l2)

{

return ((l1->client_pid == l2->client_pid) &&

(l1->transport == l2->transport));

}

 

代码风格

括号的位置

使用K&R/Linux 风格

int some_function (...)
{

if (...) {

/* ... */

} else if (...) {

/* ... */

} else {

/* ... */

}

do {

/* ... */

} while (cond);

}

缩进

使用8个空格,并且保证代码中只有空格没有tab

 

注释

在每个函数之前写一个注释描述他的功能,参数和返回值,说明它是 一个内部函数还是函数

在每个结构之前写一个注释,对每个结构成员写注释

例子:

/**

* hash_name -hash function for filenames

* @par: parent inode number

* @name: basename of inode

* @mod: number of buckets in the hashtable

*

* @return: success: bucket number

* failure: -1

*

* Not for external use.

*/

 

 

突出显示竞争区域

 

 pthread_mutex_lock (&mutex);
{

/* code */

}
pthread_mutex_unlock (&mutex);

 

一个fop的代码框架

 

首先是初始化,然后是参数检查,所有的错误都会goto 到唯一点"out",在这个地方,代码将检查错误的类型,然后做相应的清理。

 

int32_t

sample_fop (call_frame_t *frame,

xlator_t *this,

...)

{

         char * var1 = NULL;

         int32_t op_ret = -1;

         int32_t op_errno = 0;

         DIR * dir = NULL;

         struct posix_fd * pfd =NULL;

         VALIDATE_OR_GOTO (frame,out);

         VALIDATE_OR_GOTO (this,out);

         /* other validations */

         dir = opendir (...);

         if (dir == NULL) {

                   op_errno = errno;

                   gf_log (this->name,GF_LOG_ERROR,

                   "opendirfailed on %s (%s)", loc->path,

                   strerror(op_errno));

                   goto out;

         }

         /* another system call */

         if (...) {

                   op_errno = ENOMEM;

                   gf_log(this->name, GF_LOG_ERROR,

                   "out ofmemory :(");

                   goto out;

         }

         /* ... */

out:

         if (op_ret == -1) {

         /* check for all the cleanupthat needs to be

                   done */

                   if (dir) {

         closedir (dir);

         dir = NULL;

         }

         if (pfd) {

                   if (pfd->path)

                   FREE(pfd->path);

                   FREE (pfd);

                   pfd = NULL;

         }

         }

         STACK_UNWIND (frame, op_ret,op_errno, fd);

         return 0;

}

 

 

资源下载链接为: https://pan.quark.cn/s/d9ef5828b597 在本文中,我们将探讨如何通过 Vue.js 实现一个带有动画效果的“回到顶部”功能。Vue.js 是一款用于构建用户界面的流行 JavaScript 框架,其组件化和响应式设计让实现这种交互功能变得十分便捷。 首先,我们来分析 HTML 代码。在这个示例中,存在一个 ID 为 back-to-top 的 div 元素,其中包含两个 span 标签,分别显示“回到”和“顶部”文字。该 div 元素绑定了 Vue.js 的 @click 事件处理器 backToTop,用于处理点击事件,同时还绑定了 v-show 指令来控制按钮的显示与隐藏。v-cloak 指令的作用是在 Vue 实例渲染完成之前隐藏该元素,避免出现闪烁现象。 CSS 部分(backTop.css)主要负责样式设计。它首先清除了一些默认的边距和填充,对 html 和 body 进行了全屏布局,并设置了相对定位。.back-to-top 类则定义了“回到顶部”按钮的样式,包括其位置、圆角、阴影、填充以及悬停时背景颜色的变化。此外,与 v-cloak 相关的 CSS 确保在 Vue 实例加载过程中隐藏该元素。每个 .page 类代表一个页面,每个页面的高度设置为 400px,用于模拟多页面的滚动效果。 接下来是 JavaScript 部分(backTop.js)。在这里,我们创建了一个 Vue 实例。实例的 el 属性指定 Vue 将挂载到的 DOM 元素(#back-to-top)。data 对象中包含三个属性:backTopShow 用于控制按钮的显示状态;backTopAllow 用于防止用户快速连续点击;backSeconds 定义了回到顶部所需的时间;showPx 则规定了滚动多少像素后显示“回到顶部”按钮。 在 V
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值