void on_delta_write(paddr_t record_block_offset) final {
// All in-memory relative addrs are necessarily record-relative
assert(get_prior_instance());
- assert(pending_for_transaction);
+ assert(t != nullptr);
resolve_relative_addrs(record_block_offset);
}
paddr_t addr,
base_child_t* nextent) {
LOG_PREFIX(FixedKVInternalNode::update);
+ assert(this->t != nullptr);
SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, {}",
- this->pending_for_transaction,
+ this->t->get_trans_id(),
iter.get_offset(),
(void*)nextent);
this->update_child_ptr(iter.get_offset(), nextent);
paddr_t addr,
base_child_t* nextent) {
LOG_PREFIX(FixedKVInternalNode::insert);
+ assert(this->t != nullptr);
SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, key {}, {}",
- this->pending_for_transaction,
+ this->t->get_trans_id(),
iter.get_offset(),
pivot,
(void*)nextent);
void remove(internal_const_iterator_t iter) {
LOG_PREFIX(FixedKVInternalNode::remove);
+ assert(this->t != nullptr);
SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, key {}",
- this->pending_for_transaction,
+ this->t->get_trans_id(),
iter.get_offset(),
iter.get_key());
this->remove_child_ptr(iter.get_offset());
paddr_t addr,
base_child_t* nextent) {
LOG_PREFIX(FixedKVInternalNode::replace);
+ assert(this->t != nullptr);
SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, old key {}, key {}, {}",
- this->pending_for_transaction,
+ this->t->get_trans_id(),
iter.get_offset(),
iter.get_key(),
pivot,
}
auto ret = i->duplicate_for_write(t);
- ret->pending_for_transaction = t.get_trans_id();
+ ret->t = &t;
ret->set_prior_instance(i);
if (!is_root_type(ret->get_type())) {
assert(ret->get_paddr().is_absolute());
}
assert(i->state == CachedExtent::extent_state_t::DIRTY);
assert(i->version > 0);
- assert(i->pending_for_transaction == TRANS_ID_NULL);
+ assert(i->t == nullptr);
assert(!i->prior_instance);
remove_from_dirty(i, &trans_src);
// set the version to zero because the extent state is now clean
assert(!i->prior_instance || t.get_src() == transaction_type_t::DEMOTE);
// no set_io_wait(), skip complete_commit()
assert(!i->is_pending_io());
- i->pending_for_transaction = TRANS_ID_NULL;
+ i->t = nullptr;
i->state = CachedExtent::extent_state_t::CLEAN;
} else {
assert(i->is_exist_mutation_pending());
assert(i->get_last_committed_crc() == CRC_NULL);
}
#endif
- i->pending_for_transaction = TRANS_ID_NULL;
+ i->t = nullptr;
i->on_initial_write();
const auto t_src = t.get_src();
if (should_use_no_conflict_publish(t, i->get_type())) {
TRACET("committing rewritten extent into "
"existing, inline={} -- {}, prior={}",
t, is_inline, *i, prior);
- prior.pending_for_transaction = TRANS_ID_NULL;
+ prior.t = nullptr;
committer.commit_state();
committer.sync_checksum();
committer.commit_and_share_paddr();
committer.sync_checksum();
committer.unblock_trans(t);
auto &prior = *i->prior_instance;
- prior.pending_for_transaction = TRANS_ID_NULL;
+ prior.t = nullptr;
ceph_assert(prior.is_valid());
if (is_lba_backref_node(i->get_type())) {
committer.commit_data();
prior.committer.reset();
}
- i->pending_for_transaction = TRANS_ID_NULL;
+ i->t = nullptr;
i->reset_prior_instance();
assert(i->version > 0);
i->complete_io();
TRACET("committing rewritten extent into "
"existing -- {}, prior={}",
t, *i, prior);
- prior.pending_for_transaction = TRANS_ID_NULL;
+ prior.t = nullptr;
if (auto shadow = prior.get_shadow(); shadow) {
committer.commit_shadow_demote(t);
prior.reset_shadow();
P_ADDR_ROOT,
PLACEMENT_HINT_NULL,
NULL_GENERATION,
- TRANS_ID_NULL,
+ nullptr,
write_policy_t::WRITE_BACK);
root->set_modify_time(seastar::lowres_system_clock::now());
INFO("init root -- {}", *root);
offset,
PLACEMENT_HINT_NULL,
NULL_GENERATION,
- TRANS_ID_NULL,
+ nullptr,
write_policy_t::WRITE_BACK);
DEBUGT("{} length=0x{:x} is absent, add extent ... -- {}",
t, type, length, *ret);
offset,
PLACEMENT_HINT_NULL,
NULL_GENERATION,
- TRANS_ID_NULL,
+ nullptr,
write_policy_t::WRITE_BACK);
SUBDEBUGT(seastore_cache,
"{} {}~0x{:x} is absent, add extent and reading range 0x{:x}~0x{:x} ... -- {}",
offset,
PLACEMENT_HINT_NULL,
NULL_GENERATION,
- TRANS_ID_NULL,
+ nullptr,
write_policy_t::WRITE_BACK);
SUBDEBUG(seastore_cache,
"{} {}~0x{:x} is absent, add extent and reading range 0x{:x}~0x{:x} ... -- {}",
result->paddr,
opt.hint,
result->gen,
- t.get_trans_id(),
+ &t,
write_policy_t::WRITE_BACK);
t.add_fresh_extent(ret);
SUBDEBUGT(seastore_cache,
result.paddr,
opt.hint,
result.gen,
- t.get_trans_id(),
+ &t,
opt.write_policy);
t.add_fresh_extent(ret);
SUBDEBUGT(seastore_cache,
remap_paddr,
PLACEMENT_HINT_NULL,
NULL_GENERATION,
- t.get_trans_id(),
+ &t,
write_policy_t::WRITE_BACK);
auto extent = ext->template cast<T>();
return ext.print(out);
}
+trans_spec_view_t::trans_spec_view_t(
+ Transaction &t) : t(&t) {}
+
+bool trans_spec_view_t::cmp_t::operator()(
+ const trans_spec_view_t &lhs,
+ const trans_spec_view_t &rhs) const
+{
+ transaction_id_t l = ((lhs.t == nullptr) ? 0 : lhs.t->get_trans_id());
+ transaction_id_t r = ((rhs.t == nullptr) ? 0 : rhs.t->get_trans_id());
+ return l < r;
+}
+
+bool trans_spec_view_t::cmp_t::operator()(
+ const transaction_id_t &lhs,
+ const trans_spec_view_t &rhs) const
+{
+ transaction_id_t r = ((rhs.t == nullptr) ? 0 : rhs.t->get_trans_id());
+ return lhs < r;
+}
+
+bool trans_spec_view_t::cmp_t::operator()(
+ const trans_spec_view_t &lhs,
+ const transaction_id_t &rhs) const
+{
+ transaction_id_t l = ((lhs.t == nullptr) ? 0 : lhs.t->get_trans_id());
+ return l < rhs;
+}
+
CachedExtent::~CachedExtent()
{
if (parent_index) {
return this;
}
+bool CachedExtent::is_pending_in_trans(transaction_id_t id) const {
+ auto trans_id = ((t == nullptr) ? 0 : t->get_trans_id());
+ return is_pending() && trans_id == id;
+}
+
+std::ostream &CachedExtent::print(std::ostream &out) const {
+ std::string prior_poffset_str = prior_poffset
+ ? fmt::format("{}", *prior_poffset)
+ : "nullopt";
+ out << "CachedExtent(addr=" << this
+ << ", type=" << get_type()
+ << ", trans=" << ((t == nullptr) ? 0 : t->get_trans_id())
+ << ", version=" << version
+ << ", dirty_from=" << dirty_from
+ << ", modify_time=" << sea_time_point_printer_t{modify_time}
+ << ", paddr=" << get_paddr()
+ << ", prior_paddr=" << prior_poffset_str
+ << 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
+ << ", write_policy=" << write_policy
+ << ", rewrite_gen=" << rewrite_gen_printer_t{rewrite_generation}
+ << ", pending_io=";
+ if (is_pending_io()) {
+ out << io_wait->from_state;
+ } else {
+ out << "N/A";
+ }
+ if (is_valid() && is_fully_loaded() && !is_stable_clean_pending()) {
+ print_detail(out);
+ }
+ return out << ")";
+}
+
std::ostream &LogicalCachedExtent::print_detail(std::ostream &out) const
{
out << ", laddr=" << laddr
SUBTRACET(seastore_cache, "{} prior={}",
t, extent, *extent.prior_instance);
auto &prior = *extent.prior_instance;
- prior.pending_for_transaction = extent.pending_for_transaction;
+ prior.t = extent.t;
prior.modify_time = extent.modify_time;
prior.last_committed_crc = extent.last_committed_crc;
prior.dirty_from = extent.dirty_from;
using read_trans_set_t = typename read_set_item_t<T>::trans_set_t;
struct trans_spec_view_t {
- // if the extent is pending, contains the id of the owning transaction;
- // TRANS_ID_NULL otherwise
- transaction_id_t pending_for_transaction = TRANS_ID_NULL;
+ // if the extent is pending, this points to the transaction
+ Transaction *t = nullptr;
trans_spec_view_t() = default;
- trans_spec_view_t(transaction_id_t id) : pending_for_transaction(id) {}
+ trans_spec_view_t(Transaction &t);
virtual ~trans_spec_view_t() = default;
struct cmp_t {
bool operator()(
const trans_spec_view_t &lhs,
- const trans_spec_view_t &rhs) const
- {
- return lhs.pending_for_transaction < rhs.pending_for_transaction;
- }
+ const trans_spec_view_t &rhs) const;
bool operator()(
const transaction_id_t &lhs,
- const trans_spec_view_t &rhs) const
- {
- return lhs < rhs.pending_for_transaction;
- }
+ const trans_spec_view_t &rhs) const;
bool operator()(
const trans_spec_view_t &lhs,
- const transaction_id_t &rhs) const
- {
- return lhs.pending_for_transaction < rhs;
- }
+ const transaction_id_t &rhs) const;
};
using trans_view_hook_t =
paddr_t paddr,
placement_hint_t hint,
rewrite_gen_t gen,
- transaction_id_t trans_id,
+ Transaction *trans,
write_policy_t policy) {
state = _state;
set_paddr(paddr);
user_hint = hint;
rewrite_generation = gen;
- pending_for_transaction = trans_id;
+ t = trans;
write_policy = policy;
}
friend std::ostream &operator<<(std::ostream &, extent_state_t);
virtual std::ostream &print_detail(std::ostream &out) const { return out; }
- std::ostream &print(std::ostream &out) const {
- std::string prior_poffset_str = prior_poffset
- ? fmt::format("{}", *prior_poffset)
- : "nullopt";
- out << "CachedExtent(addr=" << this
- << ", type=" << get_type()
- << ", trans=" << pending_for_transaction
- << ", version=" << version
- << ", dirty_from=" << dirty_from
- << ", modify_time=" << sea_time_point_printer_t{modify_time}
- << ", paddr=" << get_paddr()
- << ", prior_paddr=" << prior_poffset_str
- << 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
- << ", write_policy=" << write_policy
- << ", rewrite_gen=" << rewrite_gen_printer_t{rewrite_generation}
- << ", pending_io=";
- if (is_pending_io()) {
- out << io_wait->from_state;
- } else {
- out << "N/A";
- }
- if (is_valid() && is_fully_loaded() && !is_stable_clean_pending()) {
- print_detail(out);
- }
- return out << ")";
- }
+ std::ostream &print(std::ostream &out) const;
/**
* get_delta
}
/// Returns true if the extent part of the open transaction
- bool is_pending_in_trans(transaction_id_t id) const {
- return is_pending() && pending_for_transaction == id;
- }
+ bool is_pending_in_trans(transaction_id_t id) const;
enum class viewable_state_t {
stable, // viewable
// Otherwise, we have to search through each extent's "retired_transactions"
// to remove the transaction
trans_spec_view_t trans_view;
- trans_retired_extent_link_t(CachedExtentRef extent, transaction_id_t id)
- : extent(extent), trans_view{id}
+ trans_retired_extent_link_t(CachedExtentRef extent, Transaction &t)
+ : extent(extent), trans_view{t}
{
assert(extent->is_stable());
extent->retired_transactions.insert(trans_view);
modification_t mod)
{
LOG_PREFIX(LBALeafNode::update);
+ assert(this->t != nullptr);
SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}",
- this->pending_for_transaction,
+ this->t->get_trans_id(),
iter.get_offset());
if (likely(mod == modification_t::USER_MODIFY)) {
this->on_modify();
lba_map_val_t val)
{
LOG_PREFIX(LBALeafNode::insert);
+ assert(this->t != nullptr);
SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, key {}",
- this->pending_for_transaction,
+ this->t->get_trans_id(),
iter.get_offset(),
addr);
this->on_modify();
laddr_t pivot,
lba_map_val_t val) {
LOG_PREFIX(FixedKVInternalNode::replace);
+ assert(this->t != nullptr);
SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, old key {}, key {}",
- this->pending_for_transaction,
+ this->t->get_trans_id(),
iter.get_offset(),
iter.get_key(),
pivot);
void remove(internal_const_iterator_t iter) final {
LOG_PREFIX(LBALeafNode::remove);
+ assert(this->t != nullptr);
SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, key {}",
- this->pending_for_transaction,
+ this->t->get_trans_id(),
iter.get_offset(),
iter.get_key());
assert(iter != this->end());
auto pi = me.get_prior_instance();
auto &prior = *pi->template cast<T>();
ceph_assert(prior.parent_of_root);
- ceph_assert(me.pending_for_transaction);
+ ceph_assert(me.t != nullptr);
parent_of_root = prior.parent_of_root;
TreeRootLinker<ParentT, T>::link_root(parent_of_root, &me);
return;
// see Transaction::views
struct copy_dests_t : trans_spec_view_t {
std::set<TCachedExtentRef<T>, Comparator> dests_by_key;
- copy_dests_t(Transaction &t) : trans_spec_view_t{t.get_trans_id()} {}
+ copy_dests_t(Transaction &t) : trans_spec_view_t(t) {}
~copy_dests_t() {
LOG_PREFIX(~copy_dests_t);
SUBTRACE(seastore_fixedkv_tree, "copy_dests_t destroyed");
auto mut_iter = me.mutation_pending_extents.find(
t.get_trans_id(), trans_spec_view_t::cmp_t());
assert(mut_iter != me.mutation_pending_extents.end());
- assert(copy_dests_by_trans.find(t.get_trans_id()) ==
- copy_dests_by_trans.end());
+ assert(copy_dests_by_trans.find(
+ t.get_trans_id(), trans_spec_view_t::cmp_t()) ==
+ copy_dests_by_trans.end());
return static_cast<T*>(&(*mut_iter));
}
ceph_assert(hint == CachedExtent::viewable_state_t::stable_become_retired);
template <typename Func>
void for_each_copy_dest_set(Transaction &t, Func &&f) {
for (auto &dests : copy_dests_by_trans) {
- if (dests.pending_for_transaction == t.get_trans_id()) {
+ assert(dests.t != nullptr);
+ if (dests.t->get_trans_id() == t.get_trans_id()) {
continue;
}
auto ©_dests = static_cast<copy_dests_t&>(dests);
auto tid = t.get_trans_id();
auto iter = copy_dests_by_trans.lower_bound(
tid, trans_spec_view_t::cmp_t());
+ if (iter != copy_dests_by_trans.end()) {
+ assert(iter->t != nullptr);
+ }
if (iter == copy_dests_by_trans.end() ||
- iter->pending_for_transaction != tid) {
+ iter->t->get_trans_id() != tid) {
iter = copy_dests_by_trans.insert_before(
iter, t.add_transactional_view<copy_dests_t>(t));
}
auto &me = down_cast();
LOG_PREFIX(ParentNode::remove_child_ptr);
auto raw_children = children.data();
+ assert(me.t != nullptr);
SUBTRACE(seastore_fixedkv_tree, "trans.{}, pos {}, total size {}, extent {}",
- me.pending_for_transaction,
+ me.t->get_trans_id(),
offset,
me.get_size(),
(void*)raw_children[offset]);
ref->set_invalid(*this);
write_set.erase(*ref);
assert(ref->prior_instance);
- retired_set.emplace(ref->prior_instance, trans_id);
+ retired_set.emplace(ref->prior_instance, *this);
assert(read_set.count(ref->prior_instance->get_paddr(), extent_cmp_t{}));
ref->reset_prior_instance();
} else {
// XXX: prevent double retire -- retired_set.count(ref->get_paddr()) == 0
// If it's already in the set, insert here will be a noop,
// which is what we want.
- retired_set.emplace(ref, trans_id);
+ retired_set.emplace(ref, *this);
}
}
bool retired) {
read_set.insert(item);
if (retired) {
- retired_set.emplace(item.ref, trans_id);
+ retired_set.emplace(item.ref, *this);
}
}
void maybe_update_pending_paddr(