ext->init(CachedExtent::extent_state_t::CLEAN,
addr,
PLACEMENT_HINT_NULL,
- NULL_GENERATION);
+ NULL_GENERATION,
+ TRANS_ID_NULL);
DEBUGT("retire {}~{} as placeholder, add extent -- {}",
t, addr, length, *ext);
const auto t_src = t.get_src();
}
auto ret = i->duplicate_for_write();
+ ret->pending_for_transaction = t.get_trans_id();
ret->prior_instance = i;
// duplicate_for_write won't occur after ool write finished
assert(!i->prior_poffset);
i->set_paddr(final_block_start.add_relative(i->get_paddr()));
}
i->last_committed_crc = i->get_crc32c();
+ i->pending_for_transaction = TRANS_ID_NULL;
i->on_initial_write();
i->state = CachedExtent::extent_state_t::CLEAN;
assert(i->is_exist_mutation_pending() ||
i->prior_instance);
i->on_delta_write(final_block_start);
+ i->pending_for_transaction = TRANS_ID_NULL;
i->prior_instance = CachedExtentRef();
i->state = CachedExtent::extent_state_t::DIRTY;
assert(i->version > 0);
root->init(CachedExtent::extent_state_t::CLEAN,
P_ADDR_ROOT,
PLACEMENT_HINT_NULL,
- NULL_GENERATION);
+ NULL_GENERATION,
+ TRANS_ID_NULL);
INFO("init root -- {}", *root);
extents.insert(*root);
}
last_commit,
[this](Transaction& t) {
return on_transaction_destruct(t);
- }
+ },
+ ++next_id
);
SUBDEBUGT(seastore_t, "created name={}, source={}, is_weak={}",
*ret, name, src, is_weak);
ret->init(CachedExtent::extent_state_t::CLEAN_PENDING,
offset,
PLACEMENT_HINT_NULL,
- NULL_GENERATION);
+ NULL_GENERATION,
+ TRANS_ID_NULL);
SUBDEBUG(seastore_cache,
"{} {}~{} is absent, add extent and reading ... -- {}",
T::TYPE, offset, length, *ret);
ret->init(CachedExtent::extent_state_t::CLEAN_PENDING,
offset,
PLACEMENT_HINT_NULL,
- NULL_GENERATION);
+ NULL_GENERATION,
+ TRANS_ID_NULL);
SUBDEBUG(seastore_cache,
"{} {}~{} is absent(placeholder), reading ... -- {}",
T::TYPE, offset, length, *ret);
ret->init(CachedExtent::extent_state_t::INITIAL_WRITE_PENDING,
result.paddr,
hint,
- result.gen);
+ result.gen,
+ t.get_trans_id());
t.add_fresh_extent(ret);
SUBDEBUGT(seastore_cache,
"allocated {} {}B extent at {}, hint={}, gen={} -- {}",
// FIXME: This is specific to the segmented implementation
std::vector<SegmentProvider*> segment_providers_by_device_id;
+ transaction_id_t next_id = 0;
+
/**
* dirty
*
read_set_item_t<T>,
typename read_set_item_t<T>::cmp_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;
+
+ 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;
+ }
+ bool operator()(
+ const transaction_id_t &lhs,
+ const trans_spec_view_t &rhs) const
+ {
+ return lhs < rhs.pending_for_transaction;
+ }
+ bool operator()(
+ const trans_spec_view_t &lhs,
+ const transaction_id_t &rhs) const
+ {
+ return lhs.pending_for_transaction < rhs;
+ }
+ };
+
+ using trans_view_hook_t =
+ boost::intrusive::set_member_hook<
+ boost::intrusive::link_mode<
+ boost::intrusive::auto_unlink>>;
+ trans_view_hook_t trans_view_hook;
+
+ using trans_view_member_options =
+ boost::intrusive::member_hook<
+ trans_spec_view_t,
+ trans_view_hook_t,
+ &trans_spec_view_t::trans_view_hook>;
+ using trans_view_set_t = boost::intrusive::set<
+ trans_spec_view_t,
+ trans_view_member_options,
+ boost::intrusive::constant_time_size<false>,
+ boost::intrusive::compare<cmp_t>>;
+};
+
class ExtentIndex;
-class CachedExtent : public boost::intrusive_ref_counter<
- CachedExtent, boost::thread_unsafe_counter> {
+class CachedExtent
+ : public boost::intrusive_ref_counter<
+ CachedExtent, boost::thread_unsafe_counter>,
+ public trans_spec_view_t {
enum class extent_state_t : uint8_t {
INITIAL_WRITE_PENDING, // In Transaction::write_set and fresh_block_list
MUTATION_PENDING, // In Transaction::write_set and mutated_block_list
void init(extent_state_t _state,
paddr_t paddr,
placement_hint_t hint,
- rewrite_gen_t gen) {
+ rewrite_gen_t gen,
+ transaction_id_t trans_id) {
assert(gen == NULL_GENERATION || is_rewrite_generation(gen));
state = _state;
set_paddr(paddr);
user_hint = hint;
rewrite_generation = gen;
+ pending_for_transaction = trans_id;
}
void set_modify_time(sea_time_point t) {
#include "crimson/common/log.h"
#define LOGT(level_, MSG, t, ...) \
- LOCAL_LOGGER.log(level_, "{} {}: " MSG, (void*)&t, FNAME , ##__VA_ARGS__)
+ LOCAL_LOGGER.log(level_, "{} trans.{} {}: " MSG, (void*)&t, \
+ (t).get_trans_id(), FNAME , ##__VA_ARGS__)
#define SUBLOGT(subname_, level_, MSG, t, ...) \
- LOGGER(subname_).log(level_, "{} {}: " MSG, (void*)&t, FNAME , ##__VA_ARGS__)
+ LOGGER(subname_).log(level_, "{} trans.{} {}: " MSG, (void*)&t, \
+ (t).get_trans_id(), FNAME , ##__VA_ARGS__)
#define TRACET(...) LOGT(seastar::log_level::trace, __VA_ARGS__)
#define SUBTRACET(subname_, ...) SUBLOGT(subname_, seastar::log_level::trace, __VA_ARGS__)
/* using a special xattr key "omap_header" to store omap header */
const std::string OMAP_HEADER_XATTR_KEY = "omap_header";
+using transaction_id_t = uint64_t;
+constexpr transaction_id_t TRANS_ID_NULL = 0;
+
/*
* Note: NULL value is usually the default and max value.
*/
bool weak,
src_t src,
journal_seq_t initiated_after,
- on_destruct_func_t&& f
+ on_destruct_func_t&& f,
+ transaction_id_t trans_id
) : weak(weak),
handle(std::move(handle)),
on_destruct(std::move(f)),
- src(src)
+ src(src),
+ trans_id(trans_id)
{}
void invalidate_clear_write_set() {
return existing_block_stats;
}
+ transaction_id_t get_trans_id() const {
+ return trans_id;
+ }
+
private:
friend class Cache;
friend Ref make_test_transaction();
on_destruct_func_t on_destruct;
const src_t src;
+
+ transaction_id_t trans_id = TRANS_ID_NULL;
};
using TransactionRef = Transaction::Ref;
/// Should only be used with dummy staged-fltree node extent manager
inline TransactionRef make_test_transaction() {
+ static transaction_id_t next_id = 0;
return std::make_unique<Transaction>(
get_dummy_ordering_handle(),
false,
Transaction::src_t::MUTATE,
JOURNAL_SEQ_NULL,
- [](Transaction&) {}
+ [](Transaction&) {},
+ ++next_id
);
}
ext->init(CachedExtent::extent_state_t::EXIST_CLEAN,
existing_paddr,
PLACEMENT_HINT_NULL,
- NULL_GENERATION);
+ NULL_GENERATION,
+ t.get_trans_id());
t.add_fresh_extent(ext);