Isolate treap-specific parts
This commit is contained in:
195
ConflictSet.cpp
195
ConflictSet.cpp
@@ -464,13 +464,107 @@ template <class Stepwise> void runSequential(std::span<Stepwise> remaining) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ReferenceImpl {
|
||||||
|
explicit ReferenceImpl(int64_t oldestVersion) : oldestVersion(oldestVersion) {
|
||||||
|
writeVersionMap[""] = oldestVersion;
|
||||||
|
}
|
||||||
|
void check(const ConflictSet::ReadRange *reads, ConflictSet::Result *results,
|
||||||
|
int count) const {
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
if (reads[i].readVersion < oldestVersion) {
|
||||||
|
results[i] = ConflictSet::TooOld;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto begin =
|
||||||
|
std::string((const char *)reads[i].begin.p, reads[i].begin.len);
|
||||||
|
auto end =
|
||||||
|
reads[i].end.len == 0
|
||||||
|
? begin + std::string("\x00", 1)
|
||||||
|
: std::string((const char *)reads[i].end.p, reads[i].end.len);
|
||||||
|
int64_t maxVersion = oldestVersion;
|
||||||
|
for (auto iter = --writeVersionMap.upper_bound(begin),
|
||||||
|
endIter = writeVersionMap.lower_bound(end);
|
||||||
|
iter != endIter; ++iter) {
|
||||||
|
maxVersion = std::max(maxVersion, iter->second);
|
||||||
|
}
|
||||||
|
results[i] = maxVersion > reads[i].readVersion ? ConflictSet::Conflict
|
||||||
|
: ConflictSet::Commit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void addWrites(const ConflictSet::WriteRange *writes, int count) {
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
auto begin =
|
||||||
|
std::string((const char *)writes[i].begin.p, writes[i].begin.len);
|
||||||
|
auto end =
|
||||||
|
writes[i].end.len == 0
|
||||||
|
? begin + std::string("\x00", 1)
|
||||||
|
: std::string((const char *)writes[i].end.p, writes[i].end.len);
|
||||||
|
auto writeVersion = writes[i].writeVersion;
|
||||||
|
auto prevVersion = (--writeVersionMap.upper_bound(end))->second;
|
||||||
|
for (auto iter = writeVersionMap.lower_bound(begin),
|
||||||
|
endIter = writeVersionMap.lower_bound(end);
|
||||||
|
iter != endIter;) {
|
||||||
|
iter = writeVersionMap.erase(iter);
|
||||||
|
}
|
||||||
|
writeVersionMap[begin] = writeVersion;
|
||||||
|
writeVersionMap[end] = prevVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setOldestVersion(int64_t oldestVersion) {
|
||||||
|
this->oldestVersion = oldestVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printLogical(std::string &result) {
|
||||||
|
for (const auto &[k, v] : writeVersionMap) {
|
||||||
|
std::string key;
|
||||||
|
for (uint8_t c : k) {
|
||||||
|
key += "x";
|
||||||
|
key += "0123456789abcdef"[c / 16];
|
||||||
|
key += "0123456789abcdef"[c % 16];
|
||||||
|
}
|
||||||
|
result += key + " -> " + std::to_string(v) + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t oldestVersion;
|
||||||
|
std::map<std::string, int64_t> writeVersionMap;
|
||||||
|
};
|
||||||
|
|
||||||
|
using Key = ConflictSet::Key;
|
||||||
|
|
||||||
|
[[maybe_unused]] Key toKey(Arena &arena, int n) {
|
||||||
|
constexpr int kMaxLength = 8;
|
||||||
|
int i = kMaxLength;
|
||||||
|
uint8_t *itoaBuf = new (arena) uint8_t[kMaxLength];
|
||||||
|
memset(itoaBuf, '0', kMaxLength);
|
||||||
|
do {
|
||||||
|
itoaBuf[--i] = "0123456789abcdef"[n % 16];
|
||||||
|
n /= 16;
|
||||||
|
} while (n);
|
||||||
|
return Key{itoaBuf, kMaxLength};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] Key toKeyAfter(Arena &arena, int n) {
|
||||||
|
constexpr int kMaxLength = 8;
|
||||||
|
int i = kMaxLength;
|
||||||
|
uint8_t *itoaBuf = new (arena) uint8_t[kMaxLength + 1];
|
||||||
|
memset(itoaBuf, '0', kMaxLength);
|
||||||
|
itoaBuf[kMaxLength] = 0;
|
||||||
|
do {
|
||||||
|
itoaBuf[--i] = "0123456789abcdef"[n % 16];
|
||||||
|
n /= 16;
|
||||||
|
} while (n);
|
||||||
|
return Key{itoaBuf, kMaxLength + 1};
|
||||||
|
}
|
||||||
|
|
||||||
// ==================== END UTILITIES IMPL ====================
|
// ==================== END UTILITIES IMPL ====================
|
||||||
|
|
||||||
|
// ==================== BEGIN IMPLEMENTATION ====================
|
||||||
|
|
||||||
#define SHOW_PRIORITY 0
|
#define SHOW_PRIORITY 0
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
|
|
||||||
using Key = ConflictSet::Key;
|
|
||||||
|
|
||||||
static auto operator<=>(const Key &lhs, const Key &rhs) {
|
static auto operator<=>(const Key &lhs, const Key &rhs) {
|
||||||
const int minLen = std::min(lhs.len, rhs.len);
|
const int minLen = std::min(lhs.len, rhs.len);
|
||||||
const int c = memcmp(lhs.p, rhs.p, minLen);
|
const int c = memcmp(lhs.p, rhs.p, minLen);
|
||||||
@@ -738,34 +832,7 @@ void lastLeqMulti(Arena &arena, Node *root, std::span<Key> keys,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[[maybe_unused]] Key toKey(Arena &arena, int n) {
|
|
||||||
constexpr int kMaxLength = 8;
|
|
||||||
int i = kMaxLength;
|
|
||||||
uint8_t *itoaBuf = new (arena) uint8_t[kMaxLength];
|
|
||||||
memset(itoaBuf, '0', kMaxLength);
|
|
||||||
do {
|
|
||||||
itoaBuf[--i] = "0123456789abcdef"[n % 16];
|
|
||||||
n /= 16;
|
|
||||||
} while (n);
|
|
||||||
return Key{itoaBuf, kMaxLength};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[maybe_unused]] Key toKeyAfter(Arena &arena, int n) {
|
|
||||||
constexpr int kMaxLength = 8;
|
|
||||||
int i = kMaxLength;
|
|
||||||
uint8_t *itoaBuf = new (arena) uint8_t[kMaxLength + 1];
|
|
||||||
memset(itoaBuf, '0', kMaxLength);
|
|
||||||
itoaBuf[kMaxLength] = 0;
|
|
||||||
do {
|
|
||||||
itoaBuf[--i] = "0123456789abcdef"[n % 16];
|
|
||||||
n /= 16;
|
|
||||||
} while (n);
|
|
||||||
return Key{itoaBuf, kMaxLength + 1};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recompute maxVersion, and propagate up the tree as necessary
|
// Recompute maxVersion, and propagate up the tree as necessary
|
||||||
// TODO interleave this? Will require careful analysis for correctness, and the
|
|
||||||
// performance gains may not be worth it.
|
|
||||||
void updateMaxVersion(Node *n) {
|
void updateMaxVersion(Node *n) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int64_t maxVersion = std::max(n->pointVersion, n->rangeVersion);
|
int64_t maxVersion = std::max(n->pointVersion, n->rangeVersion);
|
||||||
@@ -847,7 +914,6 @@ void rotate(Node **node, bool dir) {
|
|||||||
return expected;
|
return expected;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class ReferenceImpl>
|
|
||||||
bool checkCorrectness(Node *node, ReferenceImpl &refImpl) {
|
bool checkCorrectness(Node *node, ReferenceImpl &refImpl) {
|
||||||
bool success = true;
|
bool success = true;
|
||||||
// Check bst invariant
|
// Check bst invariant
|
||||||
@@ -1073,6 +1139,8 @@ struct __attribute__((__visibility__("hidden"))) ConflictSet::Impl {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ==================== END IMPLEMENTATION ====================
|
||||||
|
|
||||||
void ConflictSet::check(const ReadRange *reads, Result *results,
|
void ConflictSet::check(const ReadRange *reads, Result *results,
|
||||||
int count) const {
|
int count) const {
|
||||||
return impl->check(reads, results, count);
|
return impl->check(reads, results, count);
|
||||||
@@ -1140,73 +1208,6 @@ namespace std {
|
|||||||
void __throw_length_error(const char *) { __builtin_unreachable(); }
|
void __throw_length_error(const char *) { __builtin_unreachable(); }
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
struct ReferenceImpl {
|
|
||||||
explicit ReferenceImpl(int64_t oldestVersion) : oldestVersion(oldestVersion) {
|
|
||||||
writeVersionMap[""] = oldestVersion;
|
|
||||||
}
|
|
||||||
void check(const ConflictSet::ReadRange *reads, ConflictSet::Result *results,
|
|
||||||
int count) const {
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
if (reads[i].readVersion < oldestVersion) {
|
|
||||||
results[i] = ConflictSet::TooOld;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto begin =
|
|
||||||
std::string((const char *)reads[i].begin.p, reads[i].begin.len);
|
|
||||||
auto end =
|
|
||||||
reads[i].end.len == 0
|
|
||||||
? begin + std::string("\x00", 1)
|
|
||||||
: std::string((const char *)reads[i].end.p, reads[i].end.len);
|
|
||||||
int64_t maxVersion = oldestVersion;
|
|
||||||
for (auto iter = --writeVersionMap.upper_bound(begin),
|
|
||||||
endIter = writeVersionMap.lower_bound(end);
|
|
||||||
iter != endIter; ++iter) {
|
|
||||||
maxVersion = std::max(maxVersion, iter->second);
|
|
||||||
}
|
|
||||||
results[i] = maxVersion > reads[i].readVersion ? ConflictSet::Conflict
|
|
||||||
: ConflictSet::Commit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void addWrites(const ConflictSet::WriteRange *writes, int count) {
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
auto begin =
|
|
||||||
std::string((const char *)writes[i].begin.p, writes[i].begin.len);
|
|
||||||
auto end =
|
|
||||||
writes[i].end.len == 0
|
|
||||||
? begin + std::string("\x00", 1)
|
|
||||||
: std::string((const char *)writes[i].end.p, writes[i].end.len);
|
|
||||||
auto writeVersion = writes[i].writeVersion;
|
|
||||||
auto prevVersion = (--writeVersionMap.upper_bound(end))->second;
|
|
||||||
for (auto iter = writeVersionMap.lower_bound(begin),
|
|
||||||
endIter = writeVersionMap.lower_bound(end);
|
|
||||||
iter != endIter;) {
|
|
||||||
iter = writeVersionMap.erase(iter);
|
|
||||||
}
|
|
||||||
writeVersionMap[begin] = writeVersion;
|
|
||||||
writeVersionMap[end] = prevVersion;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setOldestVersion(int64_t oldestVersion) {
|
|
||||||
this->oldestVersion = oldestVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
void printLogical(std::string &result) {
|
|
||||||
for (const auto &[k, v] : writeVersionMap) {
|
|
||||||
std::string key;
|
|
||||||
for (uint8_t c : k) {
|
|
||||||
key += "x";
|
|
||||||
key += "0123456789abcdef"[c / 16];
|
|
||||||
key += "0123456789abcdef"[c % 16];
|
|
||||||
}
|
|
||||||
result += key + " -> " + std::to_string(v) + "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t oldestVersion;
|
|
||||||
std::map<std::string, int64_t> writeVersionMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef ENABLE_TESTS
|
#ifdef ENABLE_TESTS
|
||||||
int main(void) {
|
int main(void) {
|
||||||
int64_t writeVersion = 0;
|
int64_t writeVersion = 0;
|
||||||
|
Reference in New Issue
Block a user