using Base = BtreeCursor<laddr_t, lba::lba_map_val_t>;
using Base::BtreeCursor;
bool is_indirect() const {
- assert(!is_end());
- return val->pladdr.is_laddr();
+ return !is_end() && val->pladdr.is_laddr();
}
laddr_t get_laddr() const {
return key;
using Base = BtreeCursor<paddr_t, backref::backref_map_val_t>;
using Base::BtreeCursor;
paddr_t get_paddr() const {
+ assert(key.is_absolute());
return key;
}
laddr_t get_laddr() const {
ctx,
leaf.node,
leaf.node->modifications,
- get_key(),
- std::make_optional(get_val()),
+ is_end() ? min_max_t<node_key_t>::max : get_key(),
+ is_end() ? std::nullopt : std::make_optional(get_val()),
leaf.pos);
}
cursors,
[FNAME, this, c, laddr, length, &btree, &ret](auto& cursor)
{
+ assert(!cursor->is_end());
if (!cursor->is_indirect()) {
ret.emplace_back(LBAMapping::create_direct(std::move(cursor)));
TRACET("{}~0x{:x} got {}",
}
return fut.si_then([FNAME, laddr, &btree, c, this,
search_containing](LBACursorRef cursor) {
+ assert(!cursor->is_end());
if (!cursor->is_indirect()) {
TRACET("{} got direct cursor {}",
c.trans, laddr, *cursor);
c,
iter
).si_then([ret, c, laddr=cursor.key](auto iter) {
- if (iter.is_end()) {
- return update_mapping_ret_bare_t{
- L_ADDR_NULL, std::move(ret), nullptr};
- } else {
- return update_mapping_ret_bare_t{
- laddr, std::move(ret), iter.get_cursor(c)};
- }
+ return update_mapping_ret_bare_t{
+ laddr, std::move(ret), iter.get_cursor(c)};
});
} else {
return btree.update(
pladdr_t addr;
extent_len_t length = 0;
LBAMapping mapping; // the mapping pointing to the updated lba entry if
- // refcount is non-zero; the next lba entry otherwise;
- // null mapping if the mapping is the last one and
- // is removed
+ // refcount is non-zero; the next lba entry or the
+ // end mapping otherwise.
bool need_to_remove_extent() const {
return refcount == 0 && addr.is_paddr() && !addr.get_paddr().is_zero();
}
std::ostream &operator<<(std::ostream &out, const LBAMapping &rhs)
{
+ if (rhs.is_end()) {
+ return out << "LBAMapping(END)";
+ }
out << "LBAMapping(" << rhs.get_key()
<< "~0x" << std::hex << rhs.get_length();
if (rhs.is_complete()) {
{
assert(!is_linked_direct() || !direct_cursor->is_indirect());
assert(!indirect_cursor || indirect_cursor->is_indirect());
+ // if the mapping is indirect, it mustn't be at the end
+ if (is_indirect() && is_linked_direct()) {
+ assert((bool)direct_cursor->val
+ && direct_cursor->key != L_ADDR_NULL);
+ }
}
public:
return (bool)direct_cursor;
}
+ bool is_end() const {
+ bool end = !is_indirect() && !direct_cursor->val;
+ // if the mapping is at the end, it can't be indirect and
+ // the physical cursor must be L_ADDR_NULL
+ assert(end
+ ? (!indirect_cursor && direct_cursor->key == L_ADDR_NULL)
+ : true);
+ return end;
+ }
+
bool is_indirect() const {
assert(!is_null());
return (bool)indirect_cursor;
bool is_data_stable() const;
bool is_clone() const {
assert(is_linked_direct());
+ assert(!direct_cursor->is_end());
return direct_cursor->get_refcount() > 1;
}
bool is_zero_reserved() const {
extent_len_t get_length() const {
assert(!is_null());
if (is_indirect()) {
+ assert(!indirect_cursor->is_end());
return indirect_cursor->get_length();
}
+ assert(!direct_cursor->is_end());
return direct_cursor->get_length();
}
paddr_t get_val() const {
assert(is_linked_direct());
+ assert(!direct_cursor->is_end());
return direct_cursor->get_paddr();
}
checksum_t get_checksum() const {
assert(is_linked_direct());
+ assert(!direct_cursor->is_end());
return direct_cursor->get_checksum();
}
laddr_t get_key() const {
assert(!is_null());
if (is_indirect()) {
+ assert(!indirect_cursor->is_end());
return indirect_cursor->get_laddr();
}
+ assert(!direct_cursor->is_end());
return direct_cursor->get_laddr();
}
// An lba pin may be indirect, see comments in lba/btree_lba_manager.h
laddr_t get_intermediate_key() const {
assert(is_indirect());
+ assert(!indirect_cursor->is_end());
return indirect_cursor->get_intermediate_key();
}
laddr_t get_intermediate_base() const {
}
extent_len_t get_intermediate_length() const {
assert(is_linked_direct());
+ assert(!direct_cursor->is_end());
return direct_cursor->get_length();
}
// The start offset of the indirect cursor related to direct cursor