mutation_partition: add row_marker class

Row marker can be in one of three states: missing, live (possibly
expiring) or dead. Since it basically behaves like a normal cell, except
it doesn't have any value, row_marker class provides an interface
similar to atomic_cell.

Signed-off-by: Paweł Dziepak <pdziepak@cloudius-systems.com>
This commit is contained in:
Paweł Dziepak
2015-07-30 10:15:11 +02:00
parent f5fff734ed
commit ed21fd1ef8
2 changed files with 99 additions and 0 deletions

View File

@@ -353,6 +353,17 @@ operator<<(std::ostream& os, const row& r) {
return fprint(os, "{row: %s}", ::join(", ", r));
}
std::ostream&
operator<<(std::ostream& os, const row_marker& rm) {
if (rm.is_missing()) {
return fprint(os, "{missing row_marker}");
} else if (rm._ttl == row_marker::dead) {
return fprint(os, "{dead row_marker %s %s}", rm._timestamp, rm._expiry.time_since_epoch().count());
} else {
return fprint(os, "{row_marker %s %s %s}", rm._timestamp, rm._ttl.count(),
rm._ttl != row_marker::no_ttl ? rm._expiry.time_since_epoch().count() : 0);
}
}
std::ostream&
operator<<(std::ostream& os, const deletable_row& dr) {
@@ -376,6 +387,9 @@ operator<<(std::ostream& os, const mutation_partition& mp) {
::join(", ", mp._rows));
}
constexpr gc_clock::duration row_marker::no_ttl;
constexpr gc_clock::duration row_marker::dead;
static bool
rows_equal(const schema& s, const row& r1, const row& r2) {
return std::equal(r1.begin(), r1.end(), r2.begin(), r2.end(),

View File

@@ -99,6 +99,91 @@ public:
std::ostream& operator<<(std::ostream& os, const row::value_type& rv);
std::ostream& operator<<(std::ostream& os, const row& r);
class row_marker {
static constexpr gc_clock::duration no_ttl { 0 };
static constexpr gc_clock::duration dead { -1 };
api::timestamp_type _timestamp = api::missing_timestamp;
gc_clock::duration _ttl = no_ttl;
gc_clock::time_point _expiry;
public:
row_marker() = default;
row_marker(api::timestamp_type created_at) : _timestamp(created_at) { }
row_marker(api::timestamp_type created_at, gc_clock::duration ttl, gc_clock::time_point expiry)
: _timestamp(created_at), _ttl(ttl), _expiry(expiry)
{ }
row_marker(tombstone deleted_at)
: _timestamp(deleted_at.timestamp), _ttl(dead), _expiry(deleted_at.deletion_time)
{ }
bool is_missing() const {
return _timestamp == api::missing_timestamp;
}
bool is_live(tombstone t, gc_clock::time_point now) const {
if (is_missing() || _ttl == dead) {
return false;
}
if (_ttl != no_ttl && _expiry < now) {
return false;
}
return _timestamp > t.timestamp;
}
// Can be called only when !is_missing().
bool is_dead(gc_clock::time_point now) const {
if (_ttl == dead) {
return true;
}
return _ttl != no_ttl && _expiry < now;
}
// Can be called only when is_live().
bool is_expiring() const {
return _ttl != no_ttl;
}
// Can be called only when is_expiring().
gc_clock::duration ttl() const {
return _ttl;
}
// Can be called only when is_expiring().
gc_clock::time_point expiry() const {
return _expiry;
}
// Can be called only when is_dead().
gc_clock::time_point deletion_time() const {
return _ttl == dead ? _expiry : _expiry - _ttl;
}
api::timestamp_type timestamp() const {
return _timestamp;
}
void apply(const row_marker& rm) {
if (_timestamp <= rm._timestamp) {
*this = rm;
}
}
bool compact_and_expire(tombstone tomb, gc_clock::time_point now) {
if (is_missing()) {
return false;
}
if (_timestamp <= tomb.timestamp) {
_timestamp = api::missing_timestamp;
return false;
}
if (_ttl != no_ttl && _expiry < now) {
_expiry -= _ttl;
_ttl = dead;
return false;
}
return true;
}
bool operator==(const row_marker& other) const {
if (_timestamp != other._timestamp || _ttl != other._ttl) {
return false;
}
return _ttl == no_ttl || _expiry == other._expiry;
}
bool operator!=(const row_marker& other) const {
return !(*this == other);
}
friend std::ostream& operator<<(std::ostream& os, const row_marker& rm);
};
class deletable_row final {
tombstone _deleted_at;
api::timestamp_type _created_at = api::missing_timestamp;