root_t root;
- std::map<std::string, std::string> meta;
-
RootBlock() : CachedExtent(0) {}
RootBlock(const RootBlock &rhs) = default;
ceph::bufferlist bl = _bl;
bl.rebuild();
root = *reinterpret_cast<const root_t*>(bl.front().c_str());
- if (root.have_meta) {
- ceph::bufferlist meta_bl;
- meta_bl.rebuild(ceph::buffer::ptr_node::create(&root.meta[0], root_t::MAX_META_LENGTH));
- decode(meta, meta_bl);
- }
root.adjust_addrs_from_base(base);
}
{
LOG_PREFIX(SeaStore::write_meta);
DEBUG("key: {}; value: {}", key, value);
- return seastar::do_with(key, value,
- [this](auto& key, auto& value) {
- return repeat_eagain([this, &key, &value] {
- auto t = transaction_manager->create_transaction();
- return transaction_manager->get_root(*t).safe_then(
- [this, t=std::move(t), &key, &value](auto root) mutable {
- transaction_manager->update_root_meta(*t, key, value);
- return transaction_manager->submit_transaction(std::move(t));
+ return seastar::do_with(
+ TransactionRef(),
+ key,
+ value,
+ [this, FNAME](auto &t, auto& key, auto& value) {
+ return repeat_eagain([this, FNAME, &t, &key, &value] {
+ t = transaction_manager->create_transaction();
+ DEBUGT("Have transaction, key: {}; value: {}", *t, key, value);
+ return transaction_manager->update_root_meta(
+ *t, key, value
+ ).safe_then([this, &t] {
+ return transaction_manager->submit_transaction(std::move(t));
+ });
});
- });
- }).handle_error(
- crimson::ct_error::assert_all{"Invalid error in Seastar::write_meta"}
- );
+ }).handle_error(
+ crimson::ct_error::assert_all{"Invalid error in SeaStore::write_meta"}
+ );
}
seastar::future<std::tuple<int, std::string>> SeaStore::read_meta(const std::string& key)
{
LOG_PREFIX(SeaStore::read_meta);
DEBUG("key: {}", key);
- return seastar::do_with(transaction_manager->create_transaction(), key,
- [this](auto& t, auto& key) {
- return transaction_manager->get_root(*t).safe_then(
- [this, &key](auto root) {
- auto& meta = root->meta;
- auto it = meta.find(key);
- if (it != meta.end()) {
- return seastar::make_ready_future<std::tuple<int, std::string>>(
- std::make_tuple(0, it->second));
- }
- return seastar::make_ready_future<std::tuple<int, std::string>>(
- std::make_tuple(-1, std::string("")));
- });
- }).handle_error(
- crimson::ct_error::assert_all{"Invalid error in Seastar::write_meta"}
- );
+ return seastar::do_with(
+ std::tuple<int, std::string>(),
+ TransactionRef(),
+ key,
+ [this](auto &ret, auto &t, auto& key) {
+ return repeat_eagain([this, &ret, &t, &key] {
+ t = transaction_manager->create_transaction();
+ return transaction_manager->read_root_meta(
+ *t, key
+ ).safe_then([&ret](auto v) {
+ if (v) {
+ ret = std::make_tuple(0, std::move(*v));
+ } else {
+ ret = std::make_tuple(-1, std::string(""));
+ }
+ });
+ }).safe_then([&ret] {
+ return std::move(ret);
+ });
+ }).handle_error(
+ crimson::ct_error::assert_all{"Invalid error in SeaStore::read_meta"}
+ );
}
uuid_d SeaStore::get_fsid() const
* TODO: generalize this to permit more than one lba_manager implementation
*/
struct __attribute__((packed)) root_t {
+ using meta_t = std::map<std::string, std::string>;
static constexpr int MAX_META_LENGTH = 1024;
lba_root_t lba_root;
laddr_le_t onode_root;
coll_root_le_t collection_root;
+
char meta[MAX_META_LENGTH];
- bool have_meta = false;
+
+ root_t() {
+ set_meta(meta_t{});
+ }
void adjust_addrs_from_base(paddr_t base) {
lba_root.adjust_addrs_from_base(base);
}
+
+ meta_t get_meta() {
+ bufferlist bl;
+ bl.append(ceph::buffer::create_static(MAX_META_LENGTH, meta));
+ meta_t ret;
+ auto iter = bl.cbegin();
+ decode(ret, iter);
+ return ret;
+ }
+
+ void set_meta(const meta_t &m) {
+ ceph::bufferlist bl;
+ encode(m, bl);
+ ceph_assert(bl.length() < MAX_META_LENGTH);
+ bl.rebuild();
+ auto &bptr = bl.front();
+ ::memset(meta, 0, MAX_META_LENGTH);
+ ::memcpy(meta, bptr.c_str(), bl.length());
+ }
};
}
}
/**
- * get_root
+ * read_root_meta
*
- * Get root block's ondisk layout
+ * Read root block meta entry for key.
*/
- using get_root_ertr = base_ertr;
- using get_root_ret = get_root_ertr::future<RootBlockRef>;
- get_root_ret get_root(Transaction &t) {
- return cache->get_root(t);
+ using read_root_meta_ertr = base_ertr;
+ using read_root_meta_bare = std::optional<std::string>;
+ using read_root_meta_ret = read_root_meta_ertr::future<
+ read_root_meta_bare>;
+ read_root_meta_ret read_root_meta(
+ Transaction &t,
+ const std::string &key) {
+ return cache->get_root(
+ t
+ ).safe_then([&key](auto root) {
+ auto meta = root->root.get_meta();
+ auto iter = meta.find(key);
+ if (iter == meta.end()) {
+ return seastar::make_ready_future<read_root_meta_bare>(std::nullopt);
+ } else {
+ return seastar::make_ready_future<read_root_meta_bare>(iter->second);
+ }
+ });
}
/**
* update_root_meta
*
- * modify root block's meta field
+ * Update root block meta entry for key to value.
*/
- using update_root_meta_ertr = base_ertr::extend<
- crimson::ct_error::value_too_large>;
+ using update_root_meta_ertr = base_ertr;
using update_root_meta_ret = update_root_meta_ertr::future<>;
- update_root_meta_ret update_root_meta(Transaction& t,
- const std::string& key,
- const std::string& value) {
- auto root = cache->get_root_fast(t);
- root = cache->duplicate_for_write(t, root)->cast<RootBlock>();
- root->meta[key] = value;
-
- // calculate meta size
- // TODO: we probably need a uniformal interface for calcuting
- // the encoded size of data structures
- uint32_t meta_size = 4; // initial 4 bytes for std::map size
- for (auto& [key, val] : root->meta) {
- // sizes of length fields for key and val + sizes of key and val
- meta_size += 8 + key.length() + val.length();
- }
-
- if (meta_size > root_t::MAX_META_LENGTH) {
- return crimson::ct_error::value_too_large::make();
- }
-
- ceph::bufferlist bl(1);
- bl.rebuild(ceph::buffer::ptr_node::create(
- &root->get_root().meta[0], root_t::MAX_META_LENGTH));
- encode(root->meta, bl);
- root->get_root().have_meta = true;
- return update_root_meta_ertr::now();
+ update_root_meta_ret update_root_meta(
+ Transaction& t,
+ const std::string& key,
+ const std::string& value) {
+ return cache->get_root(
+ t
+ ).safe_then([this, &t, &key, &value](RootBlockRef root) {
+ root = cache->duplicate_for_write(t, root)->cast<RootBlock>();
+
+ auto meta = root->root.get_meta();
+ meta[key] = value;
+
+ root->root.set_meta(meta);
+ return seastar::now();
+ });
}
/**