]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson: add necessary FuturizedStore APIs for data recovery
authorXuehan Xu <xxhdx1985126@163.com>
Wed, 4 Mar 2020 08:45:51 +0000 (16:45 +0800)
committerXuehan Xu <xxhdx1985126@163.com>
Fri, 27 Mar 2020 03:08:35 +0000 (11:08 +0800)
Signed-off-by: Xuehan Xu <xxhdx1985126@163.com>
src/crimson/os/alienstore/alien_collection.h
src/crimson/os/alienstore/alien_store.cc
src/crimson/os/alienstore/alien_store.h
src/crimson/os/cyanstore/cyan_object.h
src/crimson/os/cyanstore/cyan_store.cc
src/crimson/os/cyanstore/cyan_store.h
src/crimson/os/futurized_store.h

index 30364b80ff0194b87873a284e5f0461675b1c0ec..98b8fdef44ddeda8ffd3188727556e0543b9a318 100644 (file)
 
 namespace crimson::os {
 
-struct AlienCollection final : public FuturizedCollection {
-
-  ObjectStore::CollectionHandle collection;
-
+class AlienCollection final : public FuturizedCollection {
+public:
   AlienCollection(ObjectStore::CollectionHandle ch)
   : FuturizedCollection(ch->cid),
     collection(ch) {}
 
   ~AlienCollection() {}
-};
 
+private:
+  ObjectStore::CollectionHandle collection;
+  friend AlienStore;
+};
 }
index aa958aa140d6267c8e4a0a812f248fb4f6940192..2f64f993804ffa5da1686f8b1fc9f8e918ad71b9 100644 (file)
@@ -380,4 +380,121 @@ unsigned AlienStore::get_max_attr_name_length() const
   return 256;
 }
 
+seastar::future<struct stat> AlienStore::stat(
+  CollectionRef ch,
+  const ghobject_t& oid)
+{
+  return seastar::do_with((struct stat){}, [this, ch, oid](auto& st) {
+    return tp->submit([this, ch, oid, &st] {
+      auto c = static_cast<AlienCollection*>(ch.get());
+      store->stat(c->collection, oid, &st);
+      return st;
+    });
+  });
+}
+
+seastar::future<ceph::bufferlist> AlienStore::omap_get_header(
+  CollectionRef ch,
+  const ghobject_t& oid)
+{
+  return seastar::do_with(ceph::bufferlist(), [=](auto& bl) {
+    return tp->submit([=, &bl] {
+      auto c = static_cast<AlienCollection*>(ch.get());
+      return store->omap_get_header(c->collection, oid, &bl);
+    }).then([&bl] (int i) {
+      return seastar::make_ready_future<ceph::bufferlist>(std::move(bl));
+    });
+  });
+}
+
+seastar::future<std::map<uint64_t, uint64_t>> AlienStore::fiemap(
+  CollectionRef ch,
+  const ghobject_t& oid,
+  uint64_t off,
+  uint64_t len)
+{
+  return seastar::do_with(std::map<uint64_t, uint64_t>(), [=](auto& destmap) {
+    return tp->submit([=, &destmap] {
+      auto c = static_cast<AlienCollection*>(ch.get());
+      return store->fiemap(c->collection, oid, off, len, destmap);
+    }).then([&destmap] (int i) {
+      return seastar::make_ready_future
+         <std::map<uint64_t, uint64_t>>
+         (std::move(destmap));
+    });
+  });
+}
+
+seastar::future<FuturizedStore::OmapIteratorRef> AlienStore::get_omap_iterator(
+  CollectionRef ch,
+  const ghobject_t& oid)
+{
+  return tp->submit([=] {
+    auto c = static_cast<AlienCollection*>(ch.get());
+    auto iter = store->get_omap_iterator(c->collection, oid);
+    return FuturizedStore::OmapIteratorRef(
+             new AlienStore::AlienOmapIterator(iter,
+                                               this));
+  });
+}
+
+//TODO: each iterator op needs one submit, this is not efficient,
+//      needs further optimization.
+seastar::future<int> AlienStore::AlienOmapIterator::seek_to_first()
+{
+  return store->tp->submit([=] {
+    return iter->seek_to_first();
+  });
+}
+
+seastar::future<int> AlienStore::AlienOmapIterator::upper_bound(
+  const std::string& after)
+{
+  return store->tp->submit([this, after] {
+    return iter->upper_bound(after);
+  });
+}
+
+seastar::future<int> AlienStore::AlienOmapIterator::lower_bound(
+  const std::string& to)
+{
+  return store->tp->submit([this, to] {
+    return iter->lower_bound(to);
+  });
+}
+
+seastar::future<int> AlienStore::AlienOmapIterator::next()
+{
+  return store->tp->submit([this] {
+    return iter->next();
+  });
+}
+
+bool AlienStore::AlienOmapIterator::valid() const
+{
+  return iter->valid();
+}
+
+std::string AlienStore::AlienOmapIterator::key()
+{
+  return iter->key();
+}
+
+seastar::future<std::string> AlienStore::AlienOmapIterator::tail_key()
+{
+  return store->tp->submit([this] {
+    return iter->tail_key();
+  });
+}
+
+ceph::buffer::list AlienStore::AlienOmapIterator::value()
+{
+  return iter->value();
+}
+
+int AlienStore::AlienOmapIterator::status() const
+{
+  return iter->status();
+}
+
 }
index d8dd155b799263a94d89b43bb3d7a91b3e13aa0d..87f71bd89a39639c0e5f4f81e5fbb4de44c84e53 100644 (file)
@@ -21,6 +21,23 @@ class Transaction;
 namespace crimson::os {
 class AlienStore final : public FuturizedStore {
 public:
+  class AlienOmapIterator final : public OmapIterator {
+  public:
+    AlienOmapIterator(ObjectMap::ObjectMapIterator& it,
+       AlienStore* store) : iter(it), store(store) {}
+    seastar::future<int> seek_to_first();
+    seastar::future<int> upper_bound(const std::string& after);
+    seastar::future<int> lower_bound(const std::string& to);
+    bool valid() const;
+    seastar::future<int> next();
+    std::string key();
+    seastar::future<std::string> tail_key();
+    ceph::buffer::list value();
+    int status() const;
+  private:
+    ObjectMap::ObjectMapIterator iter;
+    AlienStore* store;
+  };
   mutable std::unique_ptr<crimson::thread::ThreadPool> tp;
   AlienStore(const std::string& path, const ConfigValues& values);
   ~AlienStore() final;
@@ -74,7 +91,20 @@ public:
   uuid_d get_fsid() const final;
   seastar::future<store_statfs_t> stat() const final;
   unsigned get_max_attr_name_length() const final;
-
+  seastar::future<struct stat> stat(
+    CollectionRef,
+    const ghobject_t&) final;
+  seastar::future<ceph::bufferlist> omap_get_header(
+    CollectionRef,
+    const ghobject_t&) final;
+  seastar::future<std::map<uint64_t, uint64_t>> fiemap(
+    CollectionRef,
+    const ghobject_t&,
+    uint64_t off,
+    uint64_t len) final;
+  seastar::future<FuturizedStore::OmapIteratorRef> get_omap_iterator(
+    CollectionRef ch,
+    const ghobject_t& oid) final;
 private:
   constexpr static unsigned MAX_KEYS_PER_OMAP_GET_CALL = 32;
   const std::string path;
index 912629de067ea78b2f3ceb4f35020c13f2dfd5f0..f19b8721280f429ccab9f48fe2a1687183fc129b 100644 (file)
@@ -1,10 +1,13 @@
 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
 // vim: ts=8 sw=2 smarttab
+#pragma once
+
 #include <cstddef>
 #include <map>
 #include <string>
 #include <boost/intrusive_ptr.hpp>
 #include <boost/smart_ptr/intrusive_ref_counter.hpp>
+
 #include "include/buffer.h"
 
 namespace crimson::os {
index b08859a43196de8c109a83312fc2362e50ac0cd5..efcd6e7a1f288b1aa2f8aadbfa706f439d3ce192 100644 (file)
@@ -276,6 +276,20 @@ CyanStore::omap_get_values(
     true, values);
 }
 
+seastar::future<ceph::bufferlist>
+CyanStore::omap_get_header(
+    CollectionRef ch,
+    const ghobject_t& oid
+  ) {
+  auto c = static_cast<Collection*>(ch.get());
+  auto o = c->get_object(oid);
+  if (!o) {
+    throw std::runtime_error(fmt::format("object does not exist: {}", oid));
+  }
+
+  return seastar::make_ready_future<ceph::bufferlist>(o->omap_header);
+}
+
 seastar::future<> CyanStore::do_transaction(CollectionRef ch,
                                             ceph::os::Transaction&& t)
 {
@@ -647,4 +661,79 @@ unsigned CyanStore::get_max_attr_name_length() const
   // arbitrary limitation exactly like in the case of MemStore.
   return 256;
 }
+
+seastar::future<FuturizedStore::OmapIteratorRef> CyanStore::get_omap_iterator(
+    CollectionRef ch,
+    const ghobject_t& oid)
+{
+  auto c = static_cast<Collection*>(ch.get());
+  auto o = c->get_object(oid);
+  if (!o) {
+    throw std::runtime_error(fmt::format("object does not exist: {}", oid));
+  }
+  return seastar::make_ready_future<FuturizedStore::OmapIteratorRef>(
+           new CyanStore::CyanOmapIterator(o));
+}
+
+seastar::future<std::map<uint64_t, uint64_t>>
+CyanStore::fiemap(
+    CollectionRef ch,
+    const ghobject_t& oid,
+    uint64_t off,
+    uint64_t len)
+{
+  auto c = static_cast<Collection*>(ch.get());
+
+  ObjectRef o = c->get_object(oid);
+  if (!o) {
+    throw std::runtime_error(fmt::format("object does not exist: {}", oid));
+  }
+  std::map<uint64_t, uint64_t> m{{0, o->get_size()}};
+  return seastar::make_ready_future<std::map<uint64_t, uint64_t>>(std::move(m));
+}
+
+seastar::future<struct stat>
+CyanStore::stat(
+  CollectionRef ch,
+  const ghobject_t& oid)
+{
+  auto c = static_cast<Collection*>(ch.get());
+  auto o = c->get_object(oid);
+  if (!o) {
+    throw std::runtime_error(fmt::format("object does not exist: {}", oid));
+  }
+  struct stat st;
+  st.st_size = o->get_size();
+  return seastar::make_ready_future<struct stat>(std::move(st));
+}
+
+seastar::future<int> CyanStore::CyanOmapIterator::seek_to_first()
+{
+  iter = obj->omap.begin();
+  return seastar::make_ready_future<int>(0);
+}
+
+seastar::future<int> CyanStore::CyanOmapIterator::upper_bound(const std::string& after)
+{
+  iter = obj->omap.upper_bound(after);
+  return seastar::make_ready_future<int>(0);
+}
+
+seastar::future<int> CyanStore::CyanOmapIterator::lower_bound(const std::string &to)
+{
+  iter = obj->omap.lower_bound(to);
+  return seastar::make_ready_future<int>(0);
+}
+
+bool CyanStore::CyanOmapIterator::valid() const
+{
+  return iter != obj->omap.end();
+}
+
+seastar::future<int> CyanStore::CyanOmapIterator::next()
+{
+  ++iter;
+  return seastar::make_ready_future<int>(0);
+}
+
 }
index d1172c679cfb6c9129b118c37305bc1b9e36342b..9af1cd640c888bb1995de21538df099b4c3a4d92 100644 (file)
@@ -16,6 +16,7 @@
 #include "osd/osd_types.h"
 #include "include/uuid.h"
 
+#include "crimson/os/cyanstore/cyan_object.h"
 #include "crimson/os/futurized_store.h"
 
 namespace ceph::os {
@@ -35,6 +36,34 @@ class CyanStore final : public FuturizedStore {
   uuid_d osd_fsid;
 
 public:
+  class CyanOmapIterator final : public OmapIterator {
+  public:
+    CyanOmapIterator() {}
+    CyanOmapIterator(ObjectRef obj) : obj(obj) {
+      iter = obj->omap.begin();
+    }
+    virtual seastar::future<int> seek_to_first();
+    virtual seastar::future<int> upper_bound(const std::string &after);
+    virtual seastar::future<int> lower_bound(const std::string &to);
+    virtual bool valid() const;
+    virtual seastar::future<int> next();
+    virtual std::string key() {
+      return iter->first;
+    }
+    virtual seastar::future<std::string> tail_key() {
+      return seastar::make_ready_future<std::string>((++obj->omap.end())->first);
+    }
+    virtual ceph::buffer::list value() {
+      return iter->second;
+    }
+    virtual int status() const {
+      return iter != obj->omap.end() ? 0 : -1;
+    }
+    virtual ~CyanOmapIterator() {}
+  private:
+    std::map<std::string, bufferlist>::const_iterator iter;
+    ObjectRef obj;
+  };
 
   CyanStore(const std::string& path);
   ~CyanStore() final;
@@ -45,6 +74,9 @@ public:
 
   seastar::future<> mkfs(uuid_d new_osd_fsid) final;
   seastar::future<store_statfs_t> stat() const final;
+  seastar::future<struct stat> stat(
+    CollectionRef c,
+    const ghobject_t& oid) final;
 
   read_errorator::future<ceph::bufferlist> read(
     CollectionRef c,
@@ -78,6 +110,10 @@ public:
     const std::optional<std::string> &start ///< [in] start, empty for begin
     ) final; ///< @return <done, values> values.empty() iff done
 
+  seastar::future<ceph::bufferlist> omap_get_header(
+    CollectionRef c,
+    const ghobject_t& oid) final;
+
   seastar::future<CollectionRef> create_new_collection(const coll_t& cid) final;
   seastar::future<CollectionRef> open_collection(const coll_t& cid) final;
   seastar::future<std::vector<coll_t>> list_collections() final;
@@ -91,6 +127,15 @@ public:
   uuid_d get_fsid() const final;
   unsigned get_max_attr_name_length() const final;
 
+  seastar::future<OmapIteratorRef> get_omap_iterator(
+    CollectionRef c,
+    const ghobject_t& oid);
+
+  seastar::future<std::map<uint64_t, uint64_t>> fiemap(CollectionRef c,
+                                                      const ghobject_t& oid,
+                                                      uint64_t off,
+                                                      uint64_t len);
+
 private:
   int _remove(const coll_t& cid, const ghobject_t& oid);
   int _touch(const coll_t& cid, const ghobject_t& oid);
index 5bc9d775bf3c39572665aec56ae45dd47d45ebf7..2a0078d0bc444ee6801e68ba7879acc8ba2687e6 100644 (file)
@@ -26,6 +26,43 @@ class FuturizedCollection;
 class FuturizedStore {
 
 public:
+  class OmapIterator {
+  public:
+    virtual seastar::future<int> seek_to_first() {
+      return seastar::make_ready_future<int>(0);
+    }
+    virtual seastar::future<int> upper_bound(const std::string &after) {
+      return seastar::make_ready_future<int>(0);
+    }
+    virtual seastar::future<int> lower_bound(const std::string &to) {
+      return seastar::make_ready_future<int>(0);
+    }
+    virtual bool valid() const {
+      return false;
+    }
+    virtual seastar::future<int> next() {
+      return seastar::make_ready_future<int>(0);
+    }
+    virtual std::string key() {
+      return {};
+    }
+    virtual seastar::future<std::string> tail_key() {
+      return seastar::make_ready_future<std::string>();
+    }
+    virtual ceph::buffer::list value() {
+      return {};
+    }
+    virtual int status() const {
+      return 0;
+    }
+    virtual ~OmapIterator() {}
+  private:
+    unsigned count = 0;
+    friend void intrusive_ptr_add_ref(FuturizedStore::OmapIterator* iter);
+    friend void intrusive_ptr_release(FuturizedStore::OmapIterator* iter);
+  };
+  using OmapIteratorRef = boost::intrusive_ptr<OmapIterator>;
+
   static std::unique_ptr<FuturizedStore> create(const std::string& type,
                                                 const std::string& data,
                                                 const ConfigValues& values);
@@ -70,6 +107,9 @@ public:
   virtual get_attrs_ertr::future<attrs_t> get_attrs(
     CollectionRef c,
     const ghobject_t& oid) = 0;
+  virtual seastar::future<struct stat> stat(
+    CollectionRef c,
+    const ghobject_t& oid) = 0;
 
   using omap_values_t = std::map<std::string, bufferlist, std::less<>>;
   using omap_keys_t = std::set<std::string>;
@@ -88,12 +128,24 @@ public:
     const std::optional<std::string> &start ///< [in] start, empty for begin
     ) = 0; ///< @return <done, values> values.empty() iff done
 
+  virtual seastar::future<bufferlist> omap_get_header(
+    CollectionRef c,
+    const ghobject_t& oid) = 0;
+
   virtual seastar::future<CollectionRef> create_new_collection(const coll_t& cid) = 0;
   virtual seastar::future<CollectionRef> open_collection(const coll_t& cid) = 0;
   virtual seastar::future<std::vector<coll_t>> list_collections() = 0;
 
   virtual seastar::future<> do_transaction(CollectionRef ch,
                                           ceph::os::Transaction&& txn) = 0;
+  virtual seastar::future<OmapIteratorRef> get_omap_iterator(
+    CollectionRef ch,
+    const ghobject_t& oid) = 0;
+  virtual seastar::future<std::map<uint64_t, uint64_t>> fiemap(
+    CollectionRef ch,
+    const ghobject_t& oid,
+    uint64_t off,
+    uint64_t len) = 0;
 
   virtual seastar::future<> write_meta(const std::string& key,
                                       const std::string& value) = 0;
@@ -102,4 +154,17 @@ public:
   virtual unsigned get_max_attr_name_length() const = 0;
 };
 
+inline void intrusive_ptr_add_ref(FuturizedStore::OmapIterator* iter) {
+  assert(iter);
+  iter->count++;
+}
+
+inline void intrusive_ptr_release(FuturizedStore::OmapIterator* iter) {
+  assert(iter);
+  assert(iter->count > 0);
+  if ((--iter->count) == 0) {
+    delete iter;
+  }
+}
+
 }