#include "seastore.h"
+#include <algorithm>
+
#include <boost/algorithm/string/trim.hpp>
#include <fmt/format.h>
#include <fmt/ostream.h>
seastar::future<> SeaStore::stop()
{
- return seastar::now();
+ return transaction_manager->close(
+ ).handle_error(
+ crimson::ct_error::assert_all{
+ "Invalid error in SeaStore::stop"
+ }
+ );
+
}
seastar::future<> SeaStore::mount()
{
- return seastar::now();
+ return transaction_manager->mount(
+ ).handle_error(
+ crimson::ct_error::assert_all{
+ "Invalid error in SeaStore::mount"
+ }
+ );
}
seastar::future<> SeaStore::umount()
seastar::future<> SeaStore::mkfs(uuid_d new_osd_fsid)
{
- return seastar::now();
+ return transaction_manager->mkfs(
+ ).safe_then([this] {
+ return seastar::do_with(
+ make_transaction(),
+ [this](auto &t) {
+ return onode_manager->mkfs(*t
+ ).safe_then([this, &t] {
+ return collection_manager->mkfs(*t);
+ }).safe_then([this, &t](auto coll_root) {
+ transaction_manager->write_collection_root(
+ *t,
+ coll_root);
+ return transaction_manager->submit_transaction(
+ std::move(t));
+ });
+ });
+ }).handle_error(
+ crimson::ct_error::assert_all{
+ "Invalid error in SeaStore::mkfs"
+ }
+ );
}
seastar::future<store_statfs_t> SeaStore::stat() const
seastar::future<CollectionRef> SeaStore::create_new_collection(const coll_t& cid)
{
auto c = _get_collection(cid);
- return seastar::make_ready_future<CollectionRef>(c);
+ return repeat_with_internal_context(
+ c,
+ ceph::os::Transaction{},
+ [this, cid](auto &ctx) {
+ return _create_collection(
+ ctx,
+ cid,
+ 4 /* TODO */
+ ).safe_then([this, &ctx] {
+ return transaction_manager->submit_transaction(std::move(ctx.transaction));
+ });
+ }).then([c] {
+ return CollectionRef(c);
+ });
}
seastar::future<CollectionRef> SeaStore::open_collection(const coll_t& cid)
seastar::future<std::vector<coll_t>> SeaStore::list_collections()
{
- return seastar::make_ready_future<std::vector<coll_t>>();
+ return seastar::do_with(
+ std::vector<coll_t>(),
+ [this](auto &ret) {
+ return repeat_eagain([this, &ret] {
+
+ return seastar::do_with(
+ make_transaction(),
+ [this, &ret](auto &t) {
+ return transaction_manager->read_collection_root(*t
+ ).safe_then([this, &ret, &t](auto coll_root) {
+ return collection_manager->list(
+ coll_root,
+ *t);
+ }).safe_then([this, &ret, &t](auto colls) {
+ ret.resize(colls.size());
+ std::transform(
+ colls.begin(), colls.end(), ret.begin(),
+ [](auto p) { return p.first; });
+ });
+ });
+ }).safe_then([&ret] {
+ return seastar::make_ready_future<std::vector<coll_t>>(ret);
+ });
+ }).handle_error(
+ crimson::ct_error::assert_all{
+ "Invalid error in SeaStore::list_collections"
+ }
+ );
}
SeaStore::read_errorator::future<ceph::bufferlist> SeaStore::read(
return crimson::ct_error::enoent::make();
}
-seastar::future<struct stat> stat(
- CollectionRef c,
- const ghobject_t& oid)
-{
- return seastar::make_ready_future<struct stat>();
-}
-
-
seastar::future<struct stat> SeaStore::stat(
CollectionRef c,
const ghobject_t& oid)
{
- struct stat st;
- return seastar::make_ready_future<struct stat>(st);
+ return repeat_with_onode<struct stat>(
+ c,
+ oid,
+ [=](auto &t, auto &onode) {
+ struct stat st;
+ auto &olayout = onode.get_layout();
+ st.st_size = olayout.size;
+ st.st_blksize = 4096;
+ st.st_blocks = (st.st_size + st.st_blksize - 1) / st.st_blksize;
+ st.st_nlink = 1;
+ return seastar::make_ready_future<struct stat>();
+ }).handle_error(
+ crimson::ct_error::assert_all{
+ "Invalid error in SeaStore::stat"
+ }
+ );
}
auto
return _create_collection(ctx, cid, op->split_bits);
}
break;
+ case Transaction::OP_RMCOLL:
+ {
+ coll_t cid = i.get_cid(op->cid);
+ return _remove_collection(ctx, cid);
+ }
+ break;
case Transaction::OP_OMAP_SETKEYS:
{
std::map<std::string, ceph::bufferlist> aset;
logger().debug("{}: {} {} ~ {}",
__func__, *onode, offset, len);
assert(len == bl.length());
-
-/*
- return onode_manager->get_or_create_onode(cid, oid).safe_then([=, &bl](auto ref) {
- return;
- }).handle_error(
- crimson::ct_error::enoent::handle([]() {
- return;
- }),
- OnodeManager::open_ertr::pass_further{}
- );
- */
return tm_ertr::now();
}
internal_context_t &ctx,
const coll_t& cid, int bits)
{
- return tm_ertr::now();
+ return transaction_manager->read_collection_root(
+ *ctx.transaction
+ ).safe_then([=, &ctx](auto _cmroot) {
+ return seastar::do_with(
+ _cmroot,
+ [=, &ctx](auto &cmroot) {
+ return collection_manager->create(
+ cmroot,
+ *ctx.transaction,
+ cid,
+ bits
+ ).safe_then([=, &ctx, &cmroot] {
+ if (cmroot.must_update()) {
+ transaction_manager->write_collection_root(
+ *ctx.transaction,
+ cmroot);
+ }
+ });
+ });
+ }).handle_error(
+ tm_ertr::pass_further{},
+ crimson::ct_error::assert_all{
+ "Invalid error in SeaStore::_create_collection"
+ }
+ );
+}
+
+SeaStore::tm_ret SeaStore::_remove_collection(
+ internal_context_t &ctx,
+ const coll_t& cid)
+{
+ return transaction_manager->read_collection_root(
+ *ctx.transaction
+ ).safe_then([=, &ctx](auto _cmroot) {
+ return seastar::do_with(
+ _cmroot,
+ [=, &ctx](auto &cmroot) {
+ return collection_manager->remove(
+ cmroot,
+ *ctx.transaction,
+ cid
+ ).safe_then([=, &ctx, &cmroot] {
+ // param here denotes whether it already existed, probably error
+ if (cmroot.must_update()) {
+ transaction_manager->write_collection_root(
+ *ctx.transaction,
+ cmroot);
+ }
+ });
+ });
+ }).handle_error(
+ tm_ertr::pass_further{},
+ crimson::ct_error::assert_all{
+ "Invalid error in SeaStore::_create_collection"
+ }
+ );
}
boost::intrusive_ptr<SeastoreCollection> SeaStore::_get_collection(const coll_t& cid)
#include "include/uuid.h"
#include "os/Transaction.h"
+#include "crimson/os/futurized_collection.h"
#include "crimson/os/futurized_store.h"
#include "crimson/os/seastore/transaction.h"
#include "crimson/os/seastore/onode_manager.h"
});
}
+ template <typename Ret, typename F>
+ auto repeat_with_onode(
+ CollectionRef ch,
+ const ghobject_t &oid,
+ F &&f) {
+ return seastar::do_with(
+ oid,
+ Ret{},
+ TransactionRef(),
+ OnodeRef(),
+ std::forward<F>(f),
+ [=](auto &oid, auto &ret, auto &t, auto &onode, auto &f) {
+ return repeat_eagain([&, this] {
+ t = make_transaction();
+ return onode_manager->get_onode(
+ *t, oid
+ ).safe_then([&, this](auto onode_ret) {
+ onode = std::move(onode_ret);
+ return f(*t, *onode);
+ }).safe_then([&ret](auto _ret) {
+ ret = _ret;
+ });
+ }).safe_then([&ret] {
+ return seastar::make_ready_future<Ret>(ret);
+ });
+ });
+ }
+
TransactionManagerRef transaction_manager;
CollectionManagerRef collection_manager;
OnodeManagerRef onode_manager;
tm_ret _create_collection(
internal_context_t &ctx,
const coll_t& cid, int bits);
+ tm_ret _remove_collection(
+ internal_context_t &ctx,
+ const coll_t& cid);
boost::intrusive_ptr<SeastoreCollection> _get_collection(const coll_t& cid);
};
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include <string>
+#include <iostream>
+#include <sstream>
+
+#include "test/crimson/gtest_seastar.h"
+
+#include "test/crimson/seastore/transaction_manager_test_state.h"
+
+#include "crimson/os/futurized_collection.h"
+#include "crimson/os/seastore/seastore.h"
+
+using namespace crimson;
+using namespace crimson::os;
+using namespace crimson::os::seastore;
+using CTransaction = ceph::os::Transaction;
+using namespace std;
+
+namespace {
+ [[maybe_unused]] seastar::logger& logger() {
+ return crimson::get_logger(ceph_subsys_test);
+ }
+}
+
+
+struct seastore_test_t :
+ public seastar_test_suite_t,
+ SeaStoreTestState {
+
+ coll_t coll_name{spg_t{pg_t{0, 0}}};
+ CollectionRef coll;
+
+ seastore_test_t() {}
+
+ seastar::future<> set_up_fut() final {
+ return tm_setup(
+ ).then([this] {
+ return seastore->create_new_collection(coll_name);
+ }).then([this](auto coll_ref) {
+ coll = coll_ref;
+ });
+ }
+
+ seastar::future<> tear_down_fut() final {
+ return tm_teardown();
+ }
+
+ void do_transaction(CTransaction &&t) {
+ return seastore->do_transaction(
+ coll,
+ std::move(t)).get0();
+ }
+};
+
+ghobject_t make_oid(int i) {
+ stringstream ss;
+ ss << "object_" << i;
+ auto ret = ghobject_t(
+ hobject_t(
+ sobject_t(ss.str(), CEPH_NOSNAP)));
+ ret.hobj.nspace = "asdf";
+ return ret;
+}
+
+template <typename T, typename V>
+auto contains(const T &t, const V &v) {
+ return std::find(
+ t.begin(),
+ t.end(),
+ v) != t.end();
+}
+
+TEST_F(seastore_test_t, collection_create_list_remove)
+{
+ run_async([this] {
+ coll_t test_coll{spg_t{pg_t{1, 0}}};
+ {
+ seastore->create_new_collection(test_coll).get0();
+ auto collections = seastore->list_collections().get0();
+ EXPECT_EQ(collections.size(), 2);
+ EXPECT_TRUE(contains(collections, coll_name));
+ EXPECT_TRUE(contains(collections, test_coll));
+ }
+
+ {
+ CTransaction t;
+ t.remove_collection(test_coll);
+ do_transaction(std::move(t));
+ auto collections = seastore->list_collections().get0();
+ EXPECT_EQ(collections.size(), 1);
+ EXPECT_TRUE(contains(collections, coll_name));
+ }
+ });
+}
+
+TEST_F(seastore_test_t, touch_stat)
+{
+ run_async([this] {
+ auto test = make_oid(0);
+ {
+ CTransaction t;
+ t.touch(coll_name, test);
+ do_transaction(std::move(t));
+
+ auto result = seastore->stat(
+ coll,
+ test).get0();
+ EXPECT_EQ(result.st_size, 0);
+ }
+ });
+}
#include "crimson/os/seastore/cache.h"
#include "crimson/os/seastore/transaction_manager.h"
#include "crimson/os/seastore/segment_manager/ephemeral.h"
+#include "crimson/os/seastore/seastore.h"
#include "crimson/os/seastore/segment_manager.h"
+#include "crimson/os/seastore/collection_manager/flat_collection_manager.h"
+#include "crimson/os/seastore/onode_manager/staged-fltree/fltree_onode_manager.h"
using namespace crimson;
using namespace crimson::os;
return ret;
}
+auto get_seastore(
+ SegmentManager &segment_manager
+) {
+ auto segment_cleaner = std::make_unique<SegmentCleaner>(
+ SegmentCleaner::config_t::default_from_segment_manager(
+ segment_manager),
+ true);
+ auto journal = std::make_unique<Journal>(segment_manager);
+ auto cache = std::make_unique<Cache>(segment_manager);
+ auto lba_manager = lba_manager::create_lba_manager(segment_manager, *cache);
+
+ journal->set_segment_provider(&*segment_cleaner);
+
+ auto tm = get_transaction_manager(segment_manager);
+ auto cm = std::make_unique<collection_manager::FlatCollectionManager>(*tm);
+ return std::make_unique<SeaStore>(
+ std::move(tm),
+ std::move(cm),
+ std::make_unique<crimson::os::seastore::onode::FLTreeOnodeManager>(*tm));
+}
+
+
class TMTestState : public EphemeralTestState {
protected:
std::unique_ptr<TransactionManager> tm;
);
}
};
+
+class SeaStoreTestState : public EphemeralTestState {
+protected:
+ std::unique_ptr<SeaStore> seastore;
+
+ SeaStoreTestState() : EphemeralTestState() {}
+
+ virtual void _init() {
+ seastore = get_seastore(*segment_manager);
+ }
+
+ virtual void _destroy() {
+ seastore.reset();
+ }
+
+ virtual seastar::future<> _teardown() {
+ return seastore->stop();
+ }
+
+ virtual seastar::future<> _mount() {
+ return seastore->mount();
+ }
+
+ virtual seastar::future<> _mkfs() {
+ return seastore->mkfs(uuid_d{});
+ }
+};