map_t buffer_map;
};
-enum class extent_2q_state_t : uint8_t {
+enum class extent_pin_state_t : uint8_t {
+ // shared state between LRU and 2Q impl
Fresh = 0,
+ // 2Q impl only
WarmIn,
Hot,
Max
};
+std::ostream &operator<<(std::ostream &, const extent_pin_state_t &);
class ExtentCommitter : public boost::intrusive_ref_counter<
ExtentCommitter, boost::thread_unsafe_counter> {
<< std::hex << ", length=0x" << get_length()
<< ", loaded=0x" << get_loaded_length() << std::dec
<< ", state=" << state
+ << ", pin_state=" << pin_state
<< ", last_committed_crc=" << last_committed_crc
<< ", refcount=" << use_count()
<< ", user_hint=" << user_hint
std::pair<bool, viewable_state_t>
is_viewable_by_trans(Transaction &t);
- extent_2q_state_t get_2q_state() const {
- assert("2Q" == crimson::common::get_conf<std::string>
- ("seastore_cachepin_type"));
- return cache_state;
+ extent_pin_state_t get_pin_state() const {
+#ifndef NDEBUG
+ using crimson::common::get_conf;
+ auto type = get_conf<std::string>("seastore_cachepin_type");
+ if (type == "LRU") {
+ assert(pin_state == extent_pin_state_t::Fresh);
+ } else if (type == "2Q") {
+ assert(pin_state < extent_pin_state_t::Max);
+ } else {
+ ceph_abort("invalid seastore_cachepin_type(LRU or 2Q)");
+ }
+#endif
+ return pin_state;
}
- void set_2q_state(extent_2q_state_t state) {
- assert("2Q" == crimson::common::get_conf<std::string>
- ("seastore_cachepin_type"));
- assert(state < extent_2q_state_t::Max);
- cache_state = state;
+ void set_pin_state(extent_pin_state_t state) {
+#ifndef NDEBUG
+ using crimson::common::get_conf;
+ auto type = get_conf<std::string>("seastore_cachepin_type");
+ if (type == "LRU") {
+ assert(pin_state == extent_pin_state_t::Fresh);
+ } else if (type == "2Q") {
+ assert(pin_state < extent_pin_state_t::Max);
+ } else {
+ ceph_abort("invalid seastore_cachepin_type(LRU or 2Q)");
+ }
+#endif
+ pin_state = state;
}
extent_len_t get_last_touch_end() const {
// see Cache::touch_extent_by_range() and ExtentPinboardTwoQ.
extent_len_t last_touch_end = 0;
- // This field is unused when the ExtentPinboard use LRU algorithm
- extent_2q_state_t cache_state = extent_2q_state_t::Fresh;
+ // This field is used by ExtentPinboard
+ extent_pin_state_t pin_state = extent_pin_state_t::Fresh;
ExtentCommitterRef committer;
template <> struct fmt::formatter<crimson::os::seastore::CachedExtent> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::os::seastore::CachedExtent::viewable_state_t> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::os::seastore::LogicalCachedExtent> : fmt::ostream_formatter {};
+template <> struct fmt::formatter<crimson::os::seastore::extent_pin_state_t> : fmt::ostream_formatter {};
#endif
-
-template <>
-struct fmt::formatter<crimson::os::seastore::extent_2q_state_t>
- : public fmt::formatter<std::string_view> {
- using State = crimson::os::seastore::extent_2q_state_t;
- auto format(const State &s, auto &ctx) const {
- switch (s) {
- case State::Fresh:
- return fmt::format_to(ctx.out(), "Fresh");
- case State::WarmIn:
- return fmt::format_to(ctx.out(), "WarmIn");
- case State::Hot:
- return fmt::format_to(ctx.out(), "Hot");
- case State::Max:
- return fmt::format_to(ctx.out(), "Max");
- default:
- __builtin_unreachable();
- return ctx.out();
- }
- }
-};
double seconds) const final;
void remove(CachedExtent &extent) final {
- auto s = extent.get_2q_state();
+ auto s = extent.get_pin_state();
if (extent.is_linked_to_list()) {
- if (s == extent_2q_state_t::WarmIn) {
+ if (s == extent_pin_state_t::WarmIn) {
warm_in.remove(extent);
} else {
- ceph_assert(s == extent_2q_state_t::Hot);
+ ceph_assert(s == extent_pin_state_t::Hot);
hot.remove(extent);
}
- extent.set_2q_state(extent_2q_state_t::Fresh);
+ extent.set_pin_state(extent_pin_state_t::Fresh);
} else {
- ceph_assert(s == extent_2q_state_t::Fresh);
+ ceph_assert(s == extent_pin_state_t::Fresh);
}
}
const Transaction::src_t* p_src,
extent_len_t load_start,
extent_len_t load_length) final {
- auto state = extent.get_2q_state();
+ auto state = extent.get_pin_state();
auto type = extent.get_type();
if (extent.is_linked_to_list()) {
- if (state == extent_2q_state_t::Hot) {
+ if (state == extent_pin_state_t::Hot) {
hot.move_to_top(extent, p_src);
hit_queue(overall_hits.hot_hits, p_src, type);
} else {
- ceph_assert(state == extent_2q_state_t::WarmIn);
+ ceph_assert(state == extent_pin_state_t::WarmIn);
hit_queue(overall_hits.warm_in_hits, p_src, type);
// warm_in is a FIFO queue, do nothing here
// In the standard 2Q algorithm, the extent won't be considerred
hit++;
} else if (!is_logical_type(extent.get_type())) {
// put physical extents to hot queue directly
- ceph_assert(state == extent_2q_state_t::Fresh);
- extent.set_2q_state(extent_2q_state_t::Hot);
+ ceph_assert(state == extent_pin_state_t::Fresh);
+ extent.set_pin_state(extent_pin_state_t::Hot);
auto trimmed_extents = hot.add_to_top(extent, p_src);
on_update_hot(trimmed_extents);
hit_queue(overall_hits.absent, p_src, type);
miss++;
} else { // the logical extent which is not in warm_in and not in hot
- ceph_assert(state == extent_2q_state_t::Fresh);
+ ceph_assert(state == extent_pin_state_t::Fresh);
auto lext = extent.cast<LogicalCachedExtent>();
auto m = warm_out.accessed_recently(lext->get_laddr(), load_start);
using AccessMode = IndexedFifoQueue::AccessMode;
if (m == AccessMode::Again) {
// This extent was accessed recently, consider it's hot enough to
// promote to hot queue.
- extent.set_2q_state(extent_2q_state_t::Hot);
+ extent.set_pin_state(extent_pin_state_t::Hot);
auto trimmed_extents = hot.add_to_top(extent, p_src);
on_update_hot(trimmed_extents);
hit_queue(overall_hits.hot_absent, p_src, type);
} else {
// This extent didn't be accessed recently, put it warm_in queue
// by default.
- extent.set_2q_state(extent_2q_state_t::WarmIn);
+ extent.set_pin_state(extent_pin_state_t::WarmIn);
auto trimmed_extents = warm_in.add_to_top(extent, p_src);
on_update_warm_in(trimmed_extents);
if (m == AccessMode::Missing) {
extent_len_t increased_length,
const Transaction::src_t* p_src) final {
if (extent.is_linked_to_list()) {
- auto state = extent.get_2q_state();
- if (state == extent_2q_state_t::WarmIn) {
+ auto state = extent.get_pin_state();
+ if (state == extent_pin_state_t::WarmIn) {
auto trimmed_extents = warm_in.increase_cached_size(
extent, increased_length, p_src);
on_update_warm_in(trimmed_extents);
} else {
- ceph_assert(state == extent_2q_state_t::Hot);
+ ceph_assert(state == extent_pin_state_t::Hot);
auto trimmed_extents = hot.increase_cached_size(
extent, increased_length, p_src);
on_update_hot(trimmed_extents);
private:
void on_update_hot(std::list<CachedExtentRef> &extents) {
for (auto extent : extents) {
- extent->set_2q_state(extent_2q_state_t::Fresh);
+ extent->set_pin_state(extent_pin_state_t::Fresh);
}
}
void on_update_warm_in(std::list<CachedExtentRef> &extents) {
for (auto extent : extents) {
ceph_assert(is_logical_type(extent->get_type()));
- extent->set_2q_state(extent_2q_state_t::Fresh);
+ extent->set_pin_state(extent_pin_state_t::Fresh);
auto len = extent->get_loaded_length();
if (len == 0) {
// The extent is possibly empty after being initially split/remapped