constexpr segment_id_t NULL_SEG_ID =
std::numeric_limits<segment_id_t>::max() - 1;
/* Used to denote relative paddr_t */
-constexpr segment_id_t REL_SEG_ID =
+constexpr segment_id_t RECORD_REL_SEG_ID =
std::numeric_limits<segment_id_t>::max() - 2;
+constexpr segment_id_t BLOCK_REL_SEG_ID =
+ std::numeric_limits<segment_id_t>::max() - 3;
std::ostream &segment_to_stream(std::ostream &, const segment_id_t &t);
constexpr record_delta_idx_t NULL_DELTA_IDX =
std::numeric_limits<record_delta_idx_t>::max();
-// <segment, offset> offset on disk, see SegmentManager
+/**
+ * paddr_t
+ *
+ * <segment, offset> offset on disk, see SegmentManager
+ *
+ * May be absolute, record_relative, or block_relative.
+ *
+ * Blocks get read independently of the surrounding record,
+ * so paddrs embedded directly within a block need to refer
+ * to other blocks within the same record by a block_relative
+ * addr relative to the block's own offset. By contrast,
+ * deltas to existing blocks need to use record_relative
+ * addrs relative to the first block of the record.
+ *
+ * Fresh extents during a transaction are refered to by
+ * record_relative paddrs.
+ */
struct paddr_t {
segment_id_t segment = NULL_SEG_ID;
segment_off_t offset = NULL_SEG_OFF;
bool is_relative() const {
- return segment == REL_SEG_ID;
+ return segment == RECORD_REL_SEG_ID ||
+ segment == BLOCK_REL_SEG_ID;
+ }
+
+ bool is_record_relative() const {
+ return segment == RECORD_REL_SEG_ID;
+ }
+
+ bool is_block_relative() const {
+ return segment == BLOCK_REL_SEG_ID;
}
paddr_t add_offset(segment_off_t o) const {
paddr_t add_relative(paddr_t o) const {
assert(o.is_relative());
- assert(!is_relative());
return paddr_t{segment, offset + o.offset};
}
+ paddr_t add_block_relative(paddr_t o) const {
+ // special version mainly for documentation purposes
+ assert(o.is_block_relative());
+ return add_relative(o);
+ }
+
+ paddr_t add_record_relative(paddr_t o) const {
+ // special version mainly for documentation purposes
+ assert(o.is_record_relative());
+ return add_relative(o);
+ }
+
+ /**
+ * paddr_t::operator-
+ *
+ * Only defined for record_relative paddr_ts. Yields a
+ * block_relative address.
+ */
paddr_t operator-(paddr_t rhs) const {
- assert(rhs.is_relative() && is_relative());
+ assert(rhs.is_record_relative() && is_record_relative());
return paddr_t{
- REL_SEG_ID,
+ BLOCK_REL_SEG_ID,
offset - rhs.offset
};
}
+ /**
+ * maybe_relative_to
+ *
+ * Helper for the case where an in-memory paddr_t may be
+ * either block_relative or absolute (not record_relative).
+ *
+ * base must be either absolute or record_relative.
+ */
paddr_t maybe_relative_to(paddr_t base) const {
- if (is_relative())
- return base.add_relative(*this);
+ assert(!base.is_block_relative());
+ if (is_block_relative())
+ return base.add_block_relative(*this);
else
return *this;
}
WRITE_CMP_OPERATORS_2(paddr_t, segment, offset)
WRITE_EQ_OPERATORS_2(paddr_t, segment, offset)
constexpr paddr_t P_ADDR_NULL = paddr_t{};
-constexpr paddr_t make_relative_paddr(segment_off_t off) {
- return paddr_t{REL_SEG_ID, off};
+constexpr paddr_t P_ADDR_MIN = paddr_t{0, 0};
+constexpr paddr_t make_record_relative_paddr(segment_off_t off) {
+ return paddr_t{RECORD_REL_SEG_ID, off};
+}
+constexpr paddr_t make_block_relative_paddr(segment_off_t off) {
+ return paddr_t{BLOCK_REL_SEG_ID, off};
}
std::ostream &operator<<(std::ostream &out, const paddr_t &rhs);