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的 基本操作 的 流程~。

posted @ 2022-08-05 15:59  liutimo  阅读(119)  评论(1编辑  收藏  举报