return parent->has_been_invalidated();
}
- bool is_unviewable_by_trans(CachedExtent& extent, Transaction &t) const {
- if (!extent.is_valid()) {
- return true;
- }
- if (extent.is_pending()) {
- assert(extent.is_pending_in_trans(t.get_trans_id()));
- return false;
- }
- auto &pendings = extent.mutation_pending_extents;
- auto trans_id = t.get_trans_id();
- bool unviewable = (pendings.find(trans_id, trans_spec_view_t::cmp_t()) !=
- pendings.end());
- if (!unviewable) {
- auto &trans = extent.retired_transactions;
- unviewable = (trans.find(trans_id, trans_spec_view_t::cmp_t()) !=
- trans.end());
- assert(unviewable ==
- t.is_stable_extent_retired(extent.get_paddr(), extent.get_length()));
- }
- return unviewable;
- }
-
bool is_parent_viewable() const final {
ceph_assert(parent);
- if (!parent->is_valid()) {
- return false;
- }
- return !is_unviewable_by_trans(*parent, ctx.trans);
+ return parent->is_viewable_by_trans(ctx.trans).first;
}
bool is_parent_valid() const final {
ceph_assert(parent);
: mapping.get_key();
}
+std::pair<bool, CachedExtent::viewable_state_t>
+CachedExtent::is_viewable_by_trans(Transaction &t) {
+ if (!is_valid()) {
+ return std::make_pair(false, viewable_state_t::invalid);
+ }
+
+ auto trans_id = t.get_trans_id();
+ if (is_pending()) {
+ ceph_assert(is_pending_in_trans(trans_id));
+ return std::make_pair(true, viewable_state_t::pending);
+ }
+
+ // shared by multiple transactions
+ assert(t.is_in_read_set(this));
+ assert(is_stable_written());
+
+ auto cmp = trans_spec_view_t::cmp_t();
+ if (mutation_pending_extents.find(trans_id, cmp) !=
+ mutation_pending_extents.end()) {
+ return std::make_pair(false, viewable_state_t::stable_become_pending);
+ }
+
+ if (retired_transactions.find(trans_id, cmp) !=
+ retired_transactions.end()) {
+ assert(t.is_stable_extent_retired(get_paddr(), get_length()));
+ return std::make_pair(false, viewable_state_t::stable_become_retired);
+ }
+
+ return std::make_pair(true, viewable_state_t::stable);
+}
+
+std::ostream &operator<<(
+ std::ostream &out,
+ CachedExtent::viewable_state_t state)
+{
+ switch(state) {
+ case CachedExtent::viewable_state_t::stable:
+ return out << "stable";
+ case CachedExtent::viewable_state_t::pending:
+ return out << "pending";
+ case CachedExtent::viewable_state_t::invalid:
+ return out << "invalid";
+ case CachedExtent::viewable_state_t::stable_become_retired:
+ return out << "stable_become_retired";
+ case CachedExtent::viewable_state_t::stable_become_pending:
+ return out << "stable_become_pending";
+ default:
+ __builtin_unreachable();
+ }
+}
+
bool BufferSpace::is_range_loaded(extent_len_t offset, extent_len_t length) const
{
assert(length > 0);
return is_pending() && pending_for_transaction == id;
}
+ enum class viewable_state_t {
+ stable, // viewable
+ pending, // viewable
+ invalid, // unviewable
+ stable_become_retired, // unviewable
+ stable_become_pending, // unviewable
+ };
+
+ /**
+ * is_viewable_by_trans
+ *
+ * Check if this extent is still viewable by transaction t.
+ *
+ * Precondition: *this was previously visible to t, which indicates
+ * this extent is either in the read set of t or created(pending) by t.
+ */
+ std::pair<bool, viewable_state_t>
+ is_viewable_by_trans(Transaction &t);
+
private:
template <typename T>
friend class read_set_item_t;
};
std::ostream &operator<<(std::ostream &, CachedExtent::extent_state_t);
+std::ostream &operator<<(std::ostream &, CachedExtent::viewable_state_t);
std::ostream &operator<<(std::ostream &, const CachedExtent&);
/// Compare extents by paddr
#if FMT_VERSION >= 90000
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 {};
#endif
return do_add_to_read_set(ref);
}
+ bool is_in_read_set(CachedExtentRef extent) const {
+ return lookup_read_set(extent).first;
+ }
+
void add_to_read_set(CachedExtentRef ref) {
assert(ref->get_paddr().is_absolute()
|| ref->get_paddr().is_root());
}
}
- auto lookup_read_set(CachedExtentRef ref) const {
+ auto lookup_read_set(CachedExtentRef ref) const
+ -> std::pair<bool, read_trans_set_t<Transaction>::const_iterator> {
assert(ref->is_valid());
assert(!is_weak());
auto it = ref->read_transactions.lower_bound(