首页 > 其他分享 >librados代码走读(1)

librados代码走读(1)

时间:2024-08-15 15:54:48浏览次数:7  
标签:std const int 走读 代码 object librados bufferlist pool

本文内容

本文主要介绍librados中关于C++部分的接口API调用。但并未深入到如何实现,有助于浅尝辄止的大概了解。

  1. RadosClient.h和RadosClient.cc是用于初始化RadosClient对象,一般用于客户端进行访问,主要操作:
  • 连接、断链存储集群
    int ping_monitor(std::string mon_id, std::string *result);
    //根据poolctx初始化monclient、msgr、objecter等
    int connect();
    void shutdown();
  • 存储池系列操作。RadosClient内部有poolctx对象
    //*io = new librados::IoCtxImpl(this, objecter, poolid, CEPH_NOSNAP);
    int create_ioctx(const char *name, IoCtxImpl **io);
    int create_ioctx(int64_t, IoCtxImpl **io);

    int get_fsid(std::string *s);
    int64_t lookup_pool(const char *name);
    bool pool_requires_alignment(int64_t pool_id);
    int pool_requires_alignment2(int64_t pool_id, bool *requires);
    uint64_t pool_required_alignment(int64_t pool_id);
    int pool_required_alignment2(int64_t pool_id, uint64_t *alignment);
    int pool_get_name(uint64_t pool_id, std::string *name, bool wait_latest_map = false);
    //列举存储池。
    int pool_list(std::list<std::pair<int64_t, std::string> >& ls);
    int get_pool_stats(std::list<std::string>& ls, std::map<std::string,::pool_stat_t> *result,
    bool *per_pool);
    int get_fs_stats(ceph_statfs& result);
    bool get_pool_is_selfmanaged_snaps_mode(const std::string& pool);
    //创建、删除存储池
    int pool_create(std::string& name, int16_t crush_rule=-1);
    int pool_create_async(std::string& name, PoolAsyncCompletionImpl *c, int16_t crush_rule=-1);
    int pool_get_base_tier(int64_t pool_id, int64_t* base_tier);
    int pool_delete(const char *name);

    int pool_delete_async(const char *name, PoolAsyncCompletionImpl *c);
  • commond操作。mgr、mon等操作接口,处理mon、mgr、log等命令
    int mon_command(const std::vector<std::string>& cmd, const bufferlist &inbl,
                bufferlist *outbl, std::string *outs);
    void mon_command_async(const std::vector<std::string>& cmd, const bufferlist &inbl,
                            bufferlist *outbl, std::string *outs, Context *on_finish);
    int mon_command(int rank,
            const std::vector<std::string>& cmd, const bufferlist &inbl,
                bufferlist *outbl, std::string *outs);
    int mon_command(std::string name,
            const std::vector<std::string>& cmd, const bufferlist &inbl,
                bufferlist *outbl, std::string *outs);
    int mgr_command(const std::vector<std::string>& cmd, const bufferlist &inbl,
                bufferlist *outbl, std::string *outs);
    int mgr_command(
    const std::string& name,
    const std::vector<std::string>& cmd, const bufferlist &inbl,
    bufferlist *outbl, std::string *outs);
    int osd_command(int osd, std::vector<std::string>& cmd, const bufferlist& inbl,
                    bufferlist *poutbl, std::string *prs);
    int pg_command(pg_t pgid, std::vector<std::string>& cmd, const bufferlist& inbl,
                bufferlist *poutbl, std::string *prs);

    void handle_log(MLog *m);
    int monitor_log(const std::string& level, rados_log_callback_t cb,
            rados_log_callback2_t cb2, void *arg);
  • 我们再看一个python的demo,就能明白上述接口
    import rados, sys
    //初始化Client对象,连接集群
    cluster = rados.Rados(conffile='ceph.conf')
    cluster.connect()
    cluster_stats = cluster.get_cluster_stats()
    //存储池的增删改查
    pools = cluster.list_pools()
    for pool in pools:
            print(pool)

    print("\nCreate 'test' Pool")
    print("------------------")
    cluster.create_pool('test')

    print("\nPool named 'test' exists: {}".format(str(cluster.pool_exists('test'))))
    print("\nVerify 'test' Pool Exists")
    print("-------------------------")
    pools = cluster.list_pools()

    for pool in pools:
            print(pool)

    print("\nDelete 'test' Pool")
    print("------------------")
    cluster.delete_pool('test')
    print("\nPool named 'test' exists: {}".format(str(cluster.pool_exists('test'))))

    //打开存储池的ioctx,并进行对象及其xattr的增删改查
    ioctx = cluster.open_ioctx2(pool_id)
    print("\nWriting object 'hw' with contents 'Hello World!' to pool 'data'.")
    ioctx.write_full("hw", "Hello World!")

    print("\n\nContents of object 'hw'\n------------------------\n")
    print(ioctx.read("hw"))

    print("\nRemoving object 'hw'")
    ioctx.remove_object("hw")
    print("\n\nWriting XATTR 'lang' with value 'en_US' to object 'hw'")
    ioctx.set_xattr("hw", "lang", "en_US")

    print("\n\nGetting XATTR 'lang' from object 'hw'\n")
    print(ioctx.get_xattr("hw", "lang"))
    object_iterator = ioctx.list_objects()

    while True :

            try :
                    rados_object = object_iterator.__next__()
                    print("Object contents = {}".format(rados_object.read()))

            except StopIteration :
                    break
    //关闭ioctx连接
    print("\nClosing the connection.")
    ioctx.close()
  • 另外在官方的test中,也能看到类似的接口访问,示例为测试mon的commond命令。
//src/test/librados/cmd.cc
TEST(LibRadosCmd, MonDescribe) {
  rados_t cluster;
  ASSERT_EQ("", connect_cluster(&cluster));

  char *buf, *st;
  size_t buflen, stlen;
  char *cmd[2];

  cmd[1] = NULL;

  cmd[0] = (char *)"{\"prefix\":\"get_command_descriptions\"}";
  ASSERT_EQ(0, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
  ASSERT_LT(0u, buflen);
  rados_buffer_free(buf);
  rados_buffer_free(st);

  cmd[0] = (char *)"get_command_descriptions";
  ASSERT_EQ(-EINVAL, rados_mon_command(cluster, (const char **)cmd, 1, "", 0, &buf, &buflen, &st, &stlen));
  rados_buffer_free(buf);
  rados_buffer_free(st);

  //ASSERT_LT(0u, stlen);
  rados_buffer_free(buf);
  rados_buffer_free(st);
  rados_shutdown(cluster);
}
  1. IoctxImpl.cc。原名为PoolCtx。针对存储池的上下文操作,从上文例子中我们可以看到,RadosClient中有create_ioctx接口。在操作对象的时候,会大量使用。
  • 先看示例,init中连接集群,然后调用ioctx的aio_write函数进行写操作
//test/librados/aio_cxx.cc
    TEST(LibRadosAio, SimpleWritePP) {
        char buf[128];
        memset(buf, 0xcc, sizeof(buf));
        bufferlist bl1;
        bl1.append(buf, sizeof(buf));
        AioTestDataPP test_data;
        //初始化集群
        ASSERT_EQ("", test_data.init());
        auto my_completion = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
        ASSERT_TRUE(my_completion);
        //写对象
        ASSERT_EQ(0, test_data.m_ioctx.aio_write("foo", my_completion.get(), bl1, sizeof(buf), 0));
    }
  • 常规接口
  void queue_aio_write(struct AioCompletionImpl *c);
  void complete_aio_write(struct AioCompletionImpl *c);
  void flush_aio_writes_async(AioCompletionImpl *c);
  void flush_aio_writes();

  int64_t get_id() {
    return poolid;
  }

  std::string get_cached_pool_name();

  int get_object_hash_position(const std::string& oid, uint32_t *hash_position);
  int get_object_pg_hash_position(const std::string& oid, uint32_t *pg_hash_position);

  ::ObjectOperation *prepare_assert_ops(::ObjectOperation *op);

  // snaps
  int snap_list(std::vector<uint64_t> *snaps);
  int snap_lookup(const char *name, uint64_t *snapid);
  int snap_get_name(uint64_t snapid, std::string *s);
  int snap_get_stamp(uint64_t snapid, time_t *t);
  int snap_create(const char* snapname);
  int selfmanaged_snap_create(uint64_t *snapid);
  void aio_selfmanaged_snap_create(uint64_t *snapid, AioCompletionImpl *c);
  int snap_remove(const char* snapname);
  int rollback(const object_t& oid, const char *snapName);
  int selfmanaged_snap_remove(uint64_t snapid);
  void aio_selfmanaged_snap_remove(uint64_t snapid, AioCompletionImpl *c);
  int selfmanaged_snap_rollback_object(const object_t& oid,
                                       ::SnapContext& snapc, uint64_t snapid);

  // 对象、对象xattr属性接口
  int nlist(Objecter::NListContext *context, int max_entries);
  uint32_t nlist_seek(Objecter::NListContext *context, uint32_t pos);
  uint32_t nlist_seek(Objecter::NListContext *context, const rados_object_list_cursor& cursor);
  rados_object_list_cursor nlist_get_cursor(Objecter::NListContext *context);
  void object_list_slice(
    const hobject_t start,
    const hobject_t finish,
    const size_t n,
    const size_t m,
    hobject_t *split_start,
    hobject_t *split_finish);

  int create(const object_t& oid, bool exclusive);
  int write(const object_t& oid, bufferlist& bl, size_t len, uint64_t off);
  int append(const object_t& oid, bufferlist& bl, size_t len);
  int write_full(const object_t& oid, bufferlist& bl);
  int writesame(const object_t& oid, bufferlist& bl,
        size_t write_len, uint64_t offset);
  int read(const object_t& oid, bufferlist& bl, size_t len, uint64_t off);
  int mapext(const object_t& oid, uint64_t off, size_t len,
         std::map<uint64_t,uint64_t>& m);
  int sparse_read(const object_t& oid, std::map<uint64_t,uint64_t>& m,
          bufferlist& bl, size_t len, uint64_t off);
  int checksum(const object_t& oid, uint8_t type, const bufferlist &init_value,
           size_t len, uint64_t off, size_t chunk_size, bufferlist *pbl);
  int remove(const object_t& oid);
  int remove(const object_t& oid, int flags);
  int stat(const object_t& oid, uint64_t *psize, time_t *pmtime);
  int stat2(const object_t& oid, uint64_t *psize, struct timespec *pts);
  int trunc(const object_t& oid, uint64_t size);
  int cmpext(const object_t& oid, uint64_t off, bufferlist& cmp_bl);

  int tmap_update(const object_t& oid, bufferlist& cmdbl);

  int exec(const object_t& oid, const char *cls, const char *method, bufferlist& inbl, bufferlist& outbl);

  int getxattr(const object_t& oid, const char *name, bufferlist& bl);
  int setxattr(const object_t& oid, const char *name, bufferlist& bl);
  int getxattrs(const object_t& oid, std::map<std::string, bufferlist>& attrset);
  int rmxattr(const object_t& oid, const char *name);

  int operate(const object_t& oid, ::ObjectOperation *o, ceph::real_time *pmtime, int flags=0);
  int operate_read(const object_t& oid, ::ObjectOperation *o, bufferlist *pbl, int flags=0);
  int aio_operate(const object_t& oid, ::ObjectOperation *o,
          AioCompletionImpl *c, const SnapContext& snap_context,
          int flags, const blkin_trace_info *trace_info = nullptr);
  int aio_operate_read(const object_t& oid, ::ObjectOperation *o,
               AioCompletionImpl *c, int flags, bufferlist *pbl, const blkin_trace_info *trace_info = nullptr);

  1. librados.hpp和librados_cxx.cc是针对ceph api的c++接口的实现。主要类为:ListObject、ObjectOperation、ObjectWriteOperation、ObjectReadOperation、IoCtx、Rados等等
  • 先看示例。读取配置,连接集群,初始化某个存储池的ioctx,即可调用io中的相关函数进行对象级别的操作。
    C代码demo
    err = rados_conf_read_file(cluster, "/path/to/myceph.conf");
    err = rados_connect(cluster);
    rados_ioctx_t io;
    char *poolname = "mypool";
    err = rados_ioctx_create(cluster, poolname, &io);
    err = rados_write_full(io, "greeting", "hello", 5);
    rados_ioctx_destroy(io);
    rados_shutdown(cluster);

C++代码demo

    //test/librados/aio_cxx.cc
    TEST(LibRadosAio, RoundTripWriteFullPP2)
    {
    Rados cluster;
    std::string pool_name = get_temp_pool_name();
    ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
    IoCtx ioctx;
    cluster.ioctx_create(pool_name.c_str(), ioctx);

    auto my_completion1 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
    ObjectWriteOperation op;
    char buf[128];
    memset(buf, 0xcc, sizeof(buf));
    bufferlist bl;
    bl.append(buf);

    op.write_full(bl);
    op.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED);
    ioctx.aio_operate("test_obj", my_completion1.get(), &op);
    {
        TestAlarm alarm;
        ASSERT_EQ(0, my_completion1->wait_for_complete());
    }
    EXPECT_EQ(0, my_completion1->get_return_value());

    auto my_completion2 = std::unique_ptr<AioCompletion>{Rados::aio_create_completion()};
    bl.clear();
    ObjectReadOperation op1;
    op1.read(0, sizeof(buf), &bl, NULL);
    op1.set_op_flags2(LIBRADOS_OP_FLAG_FADVISE_DONTNEED|LIBRADOS_OP_FLAG_FADVISE_RANDOM);
    ioctx.aio_operate("test_obj", my_completion2.get(), &op1, 0);
    {
        TestAlarm alarm;
        ASSERT_EQ(0, my_completion2->wait_for_complete());
    }
    EXPECT_EQ(0, my_completion2->get_return_value());
    ASSERT_EQ(0, memcmp(buf, bl.c_str(), sizeof(buf)));

    ioctx.remove("test_obj");
    destroy_one_pool_pp(pool_name, cluster);
    }
  • ListObject主要实现了object的list功能
    class CEPH_RADOS_API ListObject
    {
        public:
        const std::string& get_nspace() const;
        const std::string& get_oid() const;
        const std::string& get_locator() const;

        ListObject();
        ~ListObject();
        ListObject( const ListObject&);
        ListObject& operator=(const ListObject& rhs);
        private:
        ListObject(ListObjectImpl *impl);

        friend class librados::NObjectIteratorImpl;
        friend std::ostream& operator<<(std::ostream& out, const ListObject& lop);

        ListObjectImpl *impl;
    };
  • ObjectOperation,父类,由WriteOperation和ReadOperation继承并负责某些函数的具体实现
  • ObjectWriteOperation,负责写对象
  • ObjectReadOperation,负责读对象
  • IoCtx,负责对外接口,完成上述operation的op调用。

标签:std,const,int,走读,代码,object,librados,bufferlist,pool
From: https://www.cnblogs.com/whutao/p/18361128

相关文章

  • 5大低代码开源平台案例研究
    在当今快速发展的数字化时代,企业面临着越来越复杂的技术挑战和市场竞争。为了保持竞争力并加速业务创新,许多公司正在转向低代码开源平台。然而,选择合适的低代码平台并将其成功实施,依然是一个挑战。本文将深入探讨五个成功案例,展示如何通过低代码开源平台解决企业在不同领域面临的......
  • poi实现多个word文档的合并测试代码样例
    提供一个代码样例实现使用poi工具包合并多个word文档:工具类MergeDocUtilspackagecom.yootii.bdy.util.test;importorg.apache.commons.collections.CollectionUtils;importorg.apache.poi.openxml4j.opc.OPCPackage;importorg.apache.poi.xwpf.usermodel.BreakType;im......
  • Python教程:异常捕捉与代码重构
    异常pYthon使用被称为异常的特殊对象来管理程序执行期间发生的错误。每当发生让python不知所错的错误时,他都会创建一个异常对象。当你编写了处理改异常的代码,该程序将继续运行;如果你未对异常进行处理,程序停止,并显示一个traceback,其中包含有关异常的报告。异常是使用try-except代......
  • 入职第一天,看了公司代码,牛马沉默了。。
    作者:小红帽的大灰狼来源:juejin.cn/post/7371986999164928010入职第一天就干活的,就问还有谁,搬来一台N手电脑,第一分钟开机,第二分钟派活,第三分钟干活,巴适。。。打开代码发现问题不断1.读取配置文件居然读取两个配置文件,一个读一点,不清楚为什么不能一个配置文件进行配置一边......
  • 全平台7合一DIY小程序源码系统,一个系统全部搞定 带完整的安装代码包以及搭建部署教程
    系统概述全平台7合一DIY小程序源码系统,是一款集成了目前市场上主流七大平台(包括但不限于微信、支付宝、百度、字节跳动、QQ、京东、快应用)小程序开发能力的综合性源码解决方案。该系统采用模块化设计,支持快速定制与灵活扩展,让企业和开发者无需再为不同平台的小程序开发而烦恼,......
  • 基于PHP+MySQL组合开发的同城二手市场便民小程序源码系统 带完整的安装代码包以及搭建
    系统概述随着消费观念的转变和环保意识的增强,越来越多的人开始选择二手商品作为消费首选。然而,传统的二手交易方式往往存在信息不对称、交易效率低下等问题,严重制约了二手市场的发展。因此,开发一款集信息发布、搜索浏览、在线沟通、安全交易于一体的同城二手市场小程序,显得尤......
  • 万能分销商城小程序源码系统 带完整的安装代码包以及搭建部署教程
    系统概述随着移动互联网的普及,小程序成为了人们生活中不可或缺的一部分。企业和商家们逐渐意识到,拥有一个自己的分销商城小程序能够带来巨大的商业价值。然而,从零开始开发一个功能完备的分销商城小程序需要耗费大量的时间、人力和物力。为了解决这一问题,万能分销商城小程序源......
  • Python代码调用扣子平台大模型,结合wxauto优秀开源项目实现微信自动回复好友消息
    最近看到微信自动化回复,觉得很有意思,想接通大模型,自动回复好友消息。以下文章将对代码进行详细解释,文章末尾附源码1.在抖音扣子平台创建发布一个大模型智能问答助手,获取API-key等。在扣子平台有详细文档。2.wxauto安装。pipinstallwxauto项目地址是​​​​​​cluic/wxau......
  • Amazing-Py-Scripts:用Python代码脚本实现一键自动化,告别重复性工作,提升工作效率
    你是否厌倦了枯燥的重复性工作?是否渴望用代码创造出有趣的工具来提升效率?那么,Amazing-Python-Scripts将会成为你的秘密武器!这个GitHub仓库汇集了大量实用且有趣的Python脚本,涵盖从基础到高级,从自动化任务到娱乐应用,旨在帮助你轻松实现自动化、提高工作效率、并用代码点缀......
  • 代码随想录算法训练营第43天:动态规划part10:子序列问题
    300.最长递增子序列力扣题目链接(opensnewwindow)给你一个整数数组nums,找到其中最长严格递增子序列的长度。子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7]是数组[0,3,1,6,2,2,7]的子序列。示例1:输入:nums=[10,9,2......