http://en.wikipedia.org/wiki/Red-black_tree
在RB树里的数据节点包含了一个rb_node数据结构节点。如下:
struct ceph_pool_weight
{
struct rb_node node;
u32 pool_id;
u32 len;
u32 weight[1024];
};
其中rb_node的结构为:
struct rb_node
{
unsigned long rb_parent_color;
#define RB_RED 0
#define RB_BLACK 1
struct rb_node *rb_right;
struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
可以通过container_of宏取得包含了rb_node的数据结构。也可以通过
rb_entry(node,type,member)取得。
其实是#define rb_entry(node,type,member) container_of(node,type,member)
内核中RB树的一些接口:
rb_first()//返回第一个节点,如:rb_node *pnode = rb_first(root);
rb_next()//返回下一个节点。如rb_next(pnode);
rb_entry()//返回该节点的对应的数据类型。#define rb_entry(node,type,member) container_of(node,type,member)
rb_erase(&pool_weight->node, root);//擦除一个节点
RB_EMPTY_ROOT(root);//判断红黑树是否为空
创建RBtree节点(结构体):
struct ceph_pool_weight
{
struct rb_node node;
u32 pool_id;
u32 len;
u32 weight[1024];
};
创建一个RBtree:
struct ceph_pool_weight root;
root = RB_ROOT; //初始化红黑树
查找RBtree
static struct ceph_pool_weight *__lookup_new_weight_mapping(struct rb_root *root,u32 pool_id)
{
struct rb_node *n = root->rb_node;
struct ceph_pool_weight *pool_weight=NULL;
int c;
while (n)
{
pool_weight = rb_entry(n, struct ceph_pool_weight, node);
if(pool_weight)
{
c = pool_id_cmp(pool_id, pool_weight->pool_id);
if (c < 0)
{
n = n->rb_left;
}
else if (c > 0)
{
n = n->rb_right;
}
else
{
return pool_weight;
}
}
}
return NULL;
}
RBTree的插入:
static int __insert_pool_weight_mapping(struct ceph_pool_weight *pool_weight,
struct rb_root *root)
{
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
struct ceph_pool_weight *pw = NULL;
int c;
while (*p) {
parent = *p;
pw = rb_entry(parent, struct ceph_pool_weight, node);
c = pool_id_cmp(pool_weight->pool_id, pw->pool_id);
if (c < 0)
p = &(*p)->rb_left;
else if (c > 0)
p = &(*p)->rb_right;
else
return -EEXIST;
}
rb_link_node(&pool_weight->node, parent, p);
rb_insert_color(&pool_weight->node, root);
return 0;
}
删除RBtree节点
static int __remove_new_weight_mapping(struct rb_root *root, u32 pool_id)
{
//首先查找到需要删除的节点
struct ceph_pool_weight *pool_weight = __lookup_new_weight_mapping(root, pool_id);
if (pool_weight)
{
dout("__lookup_new_weight_mapping ;pool_id:%u. pool_weight=%p\n", pool_id, pool_weight);
rb_erase(&pool_weight->node, root); //将节点删除
kfree(pool_weight);
return 0;
}
dout("__lookup_new_weight_mapping ;pool_id:%u. pool_weight=%p\n", pool_id, pool_weight);
return -ENOENT;
}
遍历或者查找复合条件的节点
struct rb_node *pnode;
pnode = rb_first(&map->osd_new_weight);
struct ceph_pool_weight *cpw = rb_entry(pnode, struct ceph_pool_weight, node);
while(cpw)
{
if (cpw->pool_id !=1) //如果不符合条件
{
pnode = rb_next(pnode);
cpw = rb_entry(pnode, struct ceph_pool_weight, node);
pr_err("anxiangwen ********** poolid=%d; osd_len=%d weight=%d\n", cpw->pool_id, cpw->len,cpw->weight[0]);
}
else //符合条件
{
pr_err("anxiangwen ********** poolid=%d; osd_len=%d weight=%d\n", cpw->pool_id, cpw->len,cpw->weight[0]);
break;
}
}