crush_do_rule中,用了一个scratch空间来完成item的搜索。

scratch空间总共有3个max_result这么大,并且按照max_result长度划分为三个部分(下图中的a、b、c,其中c只在recursive_to_leaf时用到,本文不涉及)。

a、b两个部分就用来生成result。a、b两个部分分别由o、w两个数组指针来指向,在每完成一个select step后,o、w互换指向的位置,上一次的o将变成本次的w,成为本次step遍历的对象,而上次的w将变成本次的o用于存放本次step的output items。

以Sage Weil论文中的例子来演示此过程:

take(root)   ->root

select(1, row) ->row2   //图例step1

select(3, cabinet)  ->cab21 cab23 cab24   //图例step2

select(1, disk)  ->disk2107 disk2313 disk2437  //图例step3

emit    //图例step4 (从scratch数组中将选中的item拷贝到result数组中)

简化后的骨干代码如下:

1、省略了itemid的合法性校验代码

2、仅考虑firstn的情况(即仅考虑replica策略)

3、不考虑recursive_to_leaf的情况(此为工程优化,非Sage Weil论文的核心内容)

int crush_do_rule(const struct crush_map *map,
int ruleno, int x, int *result, int result_max,
const __u32 *weight, int weight_max,
int *scratch)
{
int osize, wsize = ;
int *w, *o;
w = scratch;
o = scratch + result_max; struct crush_rule *rule = map->rules[ruleno]; for (__u32 step = ; step < rule->len; step++) {
struct crush_rule_step *curstep = &rule->steps[step]; switch (curstep->op) {
case CRUSH_RULE_TAKE:
w[] = curstep->arg1;
wsize = ;
break; //Elar:
//1. only consider fistn's situation
//2. ignore recurse_to_leaf situation
case CRUSH_RULE_CHOOSELEAF_FIRSTN:
case CRUSH_RULE_CHOOSE_FIRSTN: /* reset output */
osize = ;
for (int i = ; i < wsize; i++) {
int numrep = curstep->arg1;
int outpos = ; int type = curstep->arg2;
int bno = - - w[i];//Elar: get bucketId
struct crush_bucket *bucket = map->buckets[bno];
osize += crush_choose_firstn(map, bucket, weight, weight_max, x, numrep, type, o+osize, outpos);
} /* swap o and w arrays */
int *tmp = o; o = w; w = tmp;
wsize = osize;
break; case CRUSH_RULE_EMIT:
int i = ;
result_len = ;
for (; i < wsize && result_len < result_max; i++) {
result[result_len] = w[i];
result_len++;
}
wsize = ;
break; default:
break;
}
}
return result_len;
} static int crush_choose_firstn(const struct crush_map *map,
struct crush_bucket *bucket,
const __u32 *weight,
int weight_max,
int x,
int numrep,
int type,
int *out)
{
for (int rep = ; rep < numrep; rep++) {
/* keep trying until we get a non-out, non-colliding item */
unsigned int ftotal = ;
bool skip_rep = ;
do {
unsigned int flocal = ;
bool retry_descent = false;
struct crush_bucket *in = bucket; do {
bool retry_bucket = false;
int r = rep + parent_r;
/* r' = r + f_total */
r += ftotal; /* bucket choose */
int item = crush_bucket_choose(in, x, r); int itemtype;
if (item < )//Elar: if item is a bucket, then get its type
itemtype = map->buckets[--item]->type;
else//Elar: if item is a device, then its type=0
itemtype = ; //Elar: if this item's type is not what we expected, then keep going until we get an match one!
if (itemtype != type) {
in = map->buckets[--item];
retry_bucket = ;
continue;
} // Elar: check if item has already been in the output array
bool collide = false;
for (i = ; i < outpos; i++) {
if (out[i] == item) {
collide = true;
break;
}
} bool reject = false;
if (itemtype == ){
//Elar: check if this item has been marked as "out"
reject = is_out(map, weight,weight_max,item, x);
}else{
reject = false;
} reject:
if (reject || collide) {
ftotal++;
flocal++; if still can try locally(with in the same bucket, try other items)
retry_bucket = true;
else if still can try descent(parent's or grandparent's sibling buckets)
/* then retry descent */
retry_descent = true;
else
/* else give up */
skip_rep = true;
}
} while (true == retry_bucket);
} while (true == retry_descent); if (true == skip_rep) {
continue;
} out[outpos] = item;
outpos++;
}
return outpos;
}

完整代码请移步git:

https://github.com/ceph/ceph/blob/master/src/crush/mapper.c

ceph crush 之 crush_do_rule的更多相关文章

  1. ceph crush的问题

    ceph crush的问题看一遍忘一遍,现将<ceph源码分析>一书中相关章节摘抄如下: 4.2.1 层级化的Cluster Map例4-1 Cluster Map定义层级化的Cluste ...

  2. ceph crush算法和crushmap浅析

    1 什么是crushmap crushmap就相当于是ceph集群的一张数据分布地图,crush算法通过该地图可以知道数据应该如何分布:找到数据存放位置从而直接与对应的osd进行数据访问和写入:故障域 ...

  3. ceph 的crush算法 straw

    很多年以前,Sage 在写CRUSH的原始算法的时候,写了不同的Bucket类型,可以选择不同的伪随机选择算法,大部分的模型是基于RJ Honicky写的RUSH algorithms 这个算法,这个 ...

  4. Ceph相关

    Ceph基础知识和基础架构简介 http://www.xuxiaopang.com/2020/10/09/list/#more大话Ceph http://www.xuxiaopang.com/2016 ...

  5. ceph结构详解

    引言 那么问题来了,把一份数据存到一群Server中分几步? Ceph的答案是:两步. 计算PG 计算OSD 计算PG 首先,要明确Ceph的一个规定:在Ceph中,一切皆对象. 不论是视频,文本,照 ...

  6. Ceph常规操作及常见问题梳理

    Ceph集群管理 每次用命令启动.重启.停止Ceph守护进程(或整个集群)时,必须指定至少一个选项和一个命令,还可能要指定守护进程类型或具体例程. **命令格式如 {commandline} [opt ...

  7. ceph笔记(一)

    一.ceph概述本质上是rados:可靠的.自动的.分布式对象存储特性:高效性(大型的网络raid,性能无限接近raid).统一性(支持文件存储.块存储.对象存储).可扩展性数据库的一个弱点:查表ce ...

  8. Ceph 概述和理论

    1.1 Ceph概述 官网地址:https://docs.ceph.com/docs/master/ 1.Ceph简介 概述:Ceph是可靠的.可扩展的.统一的.分布式的存储系统.同时提供对象存储RA ...

  9. Ceph介绍及原理架构分享

    https://www.jianshu.com/p/cc3ece850433 1. Ceph架构简介及使用场景介绍 1.1 Ceph简介 Ceph是一个统一的分布式存储系统,设计初衷是提供较好的性能. ...

随机推荐

  1. 081 Region的预分区

    1.预分区的方式 共有四种方式 2.帮助信息 help 'create' 3.第一种方式 4.在页面上查看效果(端口号:60010) 5.第二种方式 )创建文件,并在文件中书写分区的值 )创建表 6. ...

  2. curl 文件上传

    curl_file_create (带路径的文件名 [, 文件mimetype , 上传数据里的文件名] ) ; new cURLFile (带路径的文件名 [, 文件mimetype , 上传数据里 ...

  3. QT学习之菜单栏与工具栏

    QT学习之菜单栏与工具栏 目录 简单菜单栏 多级菜单栏 上下菜单栏 工具栏 简单菜单栏 程序示例 from PyQt5.QtWidgets import QApplication, QMainWind ...

  4. CentOS 6.4在运行XFS时系统crash的bug分析

    最近有一台CentOS 6.4的服务器发生多次crash,kernel version 是Linux 2.6.32-431.29.2.el6.x86_64.从vmcore-dmesg日志内容及cras ...

  5. 搭建elasticsearch可视化插件

    一,搭建本地elasticsearch服务 具体搭建流程,可以参考博客:https://www.cnblogs.com/vipchenwei/p/9156668.html elasticsearch搭 ...

  6. Project_Lemon测评系统使用经验

    Project_Lemon使用经验 如果您还没有安装Project_Lemon,那么请移步https://www.cnblogs.com/CreeperLKF/p/9201859.html去查阅安装教 ...

  7. POJ.2065.SETI(高斯消元 模线性方程组)

    题目链接 \(Description\) 求\(A_0,A_1,A_2,\cdots,A_{n-1}\),满足 \[A_0*1^0+A_1*1^1+\ldots+A_{n-1}*1^{n-1}\equ ...

  8. Python3练习题系列(10)——项目骨架构建

    目标: 如何创建<项目“骨架”目录> 包含:项目文件布局.自动化测试代码,模组,以及安装脚本. 由于编写一个Python文件可以作为一个模块,一个带__init__.py的目录算一个包. ...

  9. 学校的统一订书80%该烧掉——IT推荐书单

    学校的统一订书80%该烧掉——IT推荐书单 作者: 夏浅音.py 中文图书个人黑名单:清华大学出版社的国产作者,例如一段错n次的谭浩强.一页错n次的严蔚敏... 中文图书个人白名单:机械工业出版社.电 ...

  10. 报错:[__NSArrayI objectAtIndex:]: index 5 beyond bounds [0 .. 4]'

    报错内容:如下 分析: 遇到这种情况,说明超出了数组的范围 如要插入某组数据,但是这组数据只有10条:但是这里设置为20条.当第11个cell填充数据时就会报错, [__NSArrayI object ...