RGW Bucket信息是如何保存在RADOS中的
在RGW User信息是如何保存在RADOS中的中,我们知道RGW是如何将User信息保存在RADOS中的。
这一节主要探寻如何通过uid获取与之关联的桶信息。
和User相似,Bucket信息也记录在meta池:
liuzheng@liuzheng-MS-7B23:~/ceph/build$ s3cmd mb s3://bucket_test
Bucket 's3://bucket_test/' created
liuzheng@liuzheng-MS-7B23:~/ceph/build$ ./bin/rados ls -p default.rgw.meta --all
users.uid liuzheng
users.uid liuzheng.buckets
root bucket_test
users.uid test
root .bucket.meta.bucket_test:7134480e-d818-43de-895d-1c2ddcc9b43c.4181.1
可以看到,在创建一个名为bucket_test的bucket后,meta池中多了三个item:
- users.uid:liuzheng.buckets: 记录用户下所有的桶名称,保存在omap中~
- root:bucket_test: ???
- root:.bucket.meta.XXX:XXX: ???
同User,我们将通过librados来读取这些数据来。
code
//
// Created by liuzheng on 22-7-28.
//
#include <iostream>
#include <gtest/gtest.h>
#include "include/rados/librados.hpp"
#include "rgw/rgw_common.h"
TEST(RGW_RADOS_BUCKET, GET_BUCKET_INFO) {
librados::Rados rados;
EXPECT_EQ(0, rados.init2("client.admin", "ceph", 0));
EXPECT_EQ(0, rados.conf_read_file(CEPH_CONF));
EXPECT_EQ(0, rados.connect());
librados::IoCtx ioctx;
EXPECT_EQ(0, rados.ioctx_create("default.rgw.meta", ioctx));
ioctx.set_namespace("users.uid");
librados::ObjectReadOperation rop1;
uint64_t size = 0;
struct timespec mtime{};
bufferlist outbl;
rop1.stat2(&size, &mtime, nullptr);
ioctx.operate(OID_BUCKETS, &rop1, &outbl);
//liuzheng.buckets对象的内容为空
EXPECT_EQ(0, size);
librados::ObjectReadOperation rop2;
std::map<std::string, bufferlist> attrs;
rop2.getxattrs(&attrs, nullptr);
ioctx.operate(OID_BUCKETS, &rop2, &outbl);
//liuzheng.buckets对象的xattrs为空
EXPECT_EQ(0, attrs.size());
librados::ObjectReadOperation rop3;
bufferlist header;
std::set<std::string> keys;
rop3.omap_get_header(&header, nullptr);
rop3.omap_get_keys2("", -1, &keys, nullptr, nullptr);
ioctx.operate(OID_BUCKETS, &rop3, &outbl);
//我们只创建了一个名为 bucket_test 的bucket。
#define BUCKET_NAME "bucket_test"
EXPECT_EQ(1, keys.size());
EXPECT_EQ(BUCKET_NAME, *keys.begin());
std::map<std::string, bufferlist> vals;
ioctx.omap_get_vals_by_keys(OID_BUCKETS, keys, &vals);
EXPECT_EQ(*keys.begin(), vals.begin()->first);
//可见,{uid}.buckets 的omap中:
// key 表示bucket name
// val 表示的是cls_user_bucket_entry
cls_user_bucket_entry bucket;
auto iter = vals.begin()->second.cbegin();
bucket.decode(iter);
EXPECT_EQ(BUCKET_NAME, bucket.bucket.name);
// 回到 root 命名空间,存在两个对象,一个对象名和桶名一致,一个很长~
ioctx.set_namespace("root");
size = 0;
EXPECT_EQ(0, ioctx.stat2(BUCKET_NAME, &size, nullptr));
EXPECT_LE(0, size);
bufferlist bl;
EXPECT_EQ(size, ioctx.read(BUCKET_NAME, bl, size, 0));
RGWBucketEntryPoint point;
iter = bl.cbegin();
point.decode(iter);
EXPECT_EQ(BUCKET_NAME, point.bucket.name);
EXPECT_EQ(OID_USERNAME, point.owner.id);
//我们通过point构造第2个对象
#define OID_BUCKET_INFO ".bucket.meta.bucket_test:c1672b05-e73f-4302-a988-ae513ac05659.4163.1"
//RGW_BUCKET_INSTANCE_MD_PREFIX 定义在 rgw_rados.h
std::string oid_ = ".bucket.meta." + point.bucket.get_key(':');
EXPECT_EQ(OID_BUCKET_INFO, oid_);
std::cout << point.bucket.bucket_id << std::endl;
size = 0;
bl.clear();
EXPECT_EQ(0, ioctx.stat2(oid_, &size, nullptr));
EXPECT_LE(0, size);
EXPECT_EQ(size, ioctx.read(oid_, bl, size, 0));
RGWBucketInfo bucket_info;
iter = bl.cbegin();
bucket_info.decode(iter);
rados.shutdown();
}
总结
通过对 default.rgw.meta池的分析,其bucket相关的信息如下:
namespace | oid | value | xattr | omap |
---|---|---|---|---|
users.uid | {username}.buckets | NULL | NULL | key为桶名,val为 cls_user_bucket_entry |
root | 对象内容为RGWBucketEntryPoint |
VERSION | NULL | |
root | .bucket.meta.{bucket_name}: | RGWBucketInfo |
VERSION && acl相关 | NULL |
接下来需要进一步学习rgw对 bucket的 基本操作 的 流程~。