#include "pg_meta.h" #include #include "crimson/os/cyan_collection.h" #include "crimson/os/cyan_store.h" // prefix pgmeta_oid keys with _ so that PGLog::read_log_and_missing() can // easily skip them static const string_view infover_key = "_infover"sv; static const string_view info_key = "_info"sv; static const string_view biginfo_key = "_biginfo"sv; static const string_view epoch_key = "_epoch"sv; static const string_view fastinfo_key = "_fastinfo"sv; using ceph::os::CyanStore; PGMeta::PGMeta(CyanStore* store, spg_t pgid) : store{store}, pgid{pgid} {} namespace { template std::optional find_value(const CyanStore::omap_values_t& values, string_view key) { auto found = values.find(key); if (found == values.end()) { return {}; } auto p = found->second.cbegin(); T value; decode(value, p); return std::make_optional(std::move(value)); } } seastar::future PGMeta::get_epoch() { auto ch = store->open_collection(coll_t{pgid}); return store->omap_get_values(ch, pgid.make_pgmeta_oid(), {string{infover_key}, string{epoch_key}}).then( [](auto&& values) { { // sanity check auto infover = find_value<__u8>(values, infover_key); assert(infover); if (*infover < 10) { throw std::runtime_error("incompatible pg meta"); } } { auto epoch = find_value(values, epoch_key); assert(epoch); return seastar::make_ready_future(*epoch); } }); } seastar::future PGMeta::load() { auto ch = store->open_collection(coll_t{pgid}); return store->omap_get_values(ch, pgid.make_pgmeta_oid(), {string{infover_key}, string{info_key}, string{biginfo_key}, string{fastinfo_key}}).then( [this](auto&& values) { { // sanity check auto infover = find_value<__u8>(values, infover_key); assert(infover); if (infover < 10) { throw std::runtime_error("incompatible pg meta"); } } pg_info_t info; { auto found = find_value(values, info_key); assert(found); info = *std::move(found); } PastIntervals past_intervals; { using biginfo_t = std::pair; auto big_info = find_value(values, biginfo_key); assert(big_info); past_intervals = std::move(big_info->first); info.purged_snaps = std::move(big_info->second); } { auto fast_info = find_value(values, fastinfo_key); assert(fast_info); fast_info->try_apply_to(&info); } return seastar::make_ready_future( std::move(info), std::move(past_intervals)); }); }