Compare commits
8 Commits
c3190c11ac
...
31ad3e8e1c
Author | SHA1 | Date | |
---|---|---|---|
31ad3e8e1c | |||
e213237698 | |||
a1c61962a1 | |||
a28283748c | |||
cafa540fc8 | |||
b9c642d81d | |||
7abb129f03 | |||
3739ccaaf2 |
@@ -38,6 +38,11 @@ if(NOT APPLE)
|
|||||||
add_compile_options(-g -fno-omit-frame-pointer)
|
add_compile_options(-g -fno-omit-frame-pointer)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# work around lack of musttail for gcc
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
add_compile_options(-O1 -foptimize-sibling-calls)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(full_relro_flags "-pie;LINKER:-z,relro,-z,now,-z,noexecstack")
|
set(full_relro_flags "-pie;LINKER:-z,relro,-z,now,-z,noexecstack")
|
||||||
cmake_push_check_state()
|
cmake_push_check_state()
|
||||||
list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${full_relro_flags})
|
list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${full_relro_flags})
|
||||||
|
464
ConflictSet.cpp
464
ConflictSet.cpp
@@ -203,6 +203,62 @@ enum Type : int8_t {
|
|||||||
|
|
||||||
template <class T> struct BoundedFreeListAllocator;
|
template <class T> struct BoundedFreeListAllocator;
|
||||||
|
|
||||||
|
struct TaggedNodePointer {
|
||||||
|
TaggedNodePointer() = default;
|
||||||
|
operator struct Node *() { return (struct Node *)withoutType(); }
|
||||||
|
operator struct Node0 *() {
|
||||||
|
assert(getType() == Type_Node0);
|
||||||
|
return (struct Node0 *)withoutType();
|
||||||
|
}
|
||||||
|
operator struct Node3 *() {
|
||||||
|
assert(getType() == Type_Node3);
|
||||||
|
return (struct Node3 *)withoutType();
|
||||||
|
}
|
||||||
|
operator struct Node16 *() {
|
||||||
|
assert(getType() == Type_Node16);
|
||||||
|
return (struct Node16 *)withoutType();
|
||||||
|
}
|
||||||
|
operator struct Node48 *() {
|
||||||
|
assert(getType() == Type_Node48);
|
||||||
|
return (struct Node48 *)withoutType();
|
||||||
|
}
|
||||||
|
operator struct Node256 *() {
|
||||||
|
assert(getType() == Type_Node256);
|
||||||
|
return (struct Node256 *)withoutType();
|
||||||
|
}
|
||||||
|
/*implicit*/ TaggedNodePointer(std::nullptr_t) : p(0) {}
|
||||||
|
/*implicit*/ TaggedNodePointer(Node0 *x)
|
||||||
|
: TaggedNodePointer((struct Node *)x, Type_Node0) {}
|
||||||
|
/*implicit*/ TaggedNodePointer(Node3 *x)
|
||||||
|
: TaggedNodePointer((struct Node *)x, Type_Node3) {}
|
||||||
|
/*implicit*/ TaggedNodePointer(Node16 *x)
|
||||||
|
: TaggedNodePointer((struct Node *)x, Type_Node16) {}
|
||||||
|
/*implicit*/ TaggedNodePointer(Node48 *x)
|
||||||
|
: TaggedNodePointer((struct Node *)x, Type_Node48) {}
|
||||||
|
/*implicit*/ TaggedNodePointer(Node256 *x)
|
||||||
|
: TaggedNodePointer((struct Node *)x, Type_Node256) {}
|
||||||
|
|
||||||
|
bool operator!=(std::nullptr_t) { return p != 0; }
|
||||||
|
bool operator==(std::nullptr_t) { return p == 0; }
|
||||||
|
bool operator==(const TaggedNodePointer &) const = default;
|
||||||
|
bool operator==(Node *n) const { return (uintptr_t)n == withoutType(); }
|
||||||
|
Node *operator->() { return (Node *)withoutType(); }
|
||||||
|
Type getType();
|
||||||
|
|
||||||
|
TaggedNodePointer(const TaggedNodePointer &) = default;
|
||||||
|
TaggedNodePointer &operator=(const TaggedNodePointer &) = default;
|
||||||
|
/*implicit*/ TaggedNodePointer(Node *n);
|
||||||
|
|
||||||
|
private:
|
||||||
|
TaggedNodePointer(struct Node *p, Type t) : p((uintptr_t)p) {
|
||||||
|
assert((this->p & 7) == 0);
|
||||||
|
this->p |= t;
|
||||||
|
assume(p != 0);
|
||||||
|
}
|
||||||
|
uintptr_t withoutType() const { return p & ~uintptr_t(7); }
|
||||||
|
uintptr_t p;
|
||||||
|
};
|
||||||
|
|
||||||
struct Node {
|
struct Node {
|
||||||
|
|
||||||
/* begin section that's copied to the next node */
|
/* begin section that's copied to the next node */
|
||||||
@@ -228,6 +284,14 @@ private:
|
|||||||
int32_t partialKeyCapacity;
|
int32_t partialKeyCapacity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TaggedNodePointer::TaggedNodePointer(Node *n)
|
||||||
|
: TaggedNodePointer(n, n->getType()) {}
|
||||||
|
|
||||||
|
Type TaggedNodePointer::getType() {
|
||||||
|
assert(p != 0);
|
||||||
|
return Type(p & uintptr_t(7));
|
||||||
|
}
|
||||||
|
|
||||||
constexpr int kNodeCopyBegin = offsetof(Node, entry);
|
constexpr int kNodeCopyBegin = offsetof(Node, entry);
|
||||||
constexpr int kNodeCopySize =
|
constexpr int kNodeCopySize =
|
||||||
offsetof(Node, parentsIndex) + sizeof(Node::parentsIndex) - kNodeCopyBegin;
|
offsetof(Node, parentsIndex) + sizeof(Node::parentsIndex) - kNodeCopyBegin;
|
||||||
@@ -251,7 +315,7 @@ struct Node3 : Node {
|
|||||||
constexpr static auto kMaxNodes = 3;
|
constexpr static auto kMaxNodes = 3;
|
||||||
constexpr static auto kType = Type_Node3;
|
constexpr static auto kType = Type_Node3;
|
||||||
|
|
||||||
Node *children[kMaxNodes];
|
TaggedNodePointer children[kMaxNodes];
|
||||||
InternalVersionT childMaxVersion[kMaxNodes];
|
InternalVersionT childMaxVersion[kMaxNodes];
|
||||||
// Sorted
|
// Sorted
|
||||||
uint8_t index[kMaxNodes];
|
uint8_t index[kMaxNodes];
|
||||||
@@ -267,7 +331,7 @@ struct Node16 : Node {
|
|||||||
constexpr static auto kType = Type_Node16;
|
constexpr static auto kType = Type_Node16;
|
||||||
constexpr static auto kMaxNodes = 16;
|
constexpr static auto kMaxNodes = 16;
|
||||||
|
|
||||||
Node *children[kMaxNodes];
|
TaggedNodePointer children[kMaxNodes];
|
||||||
InternalVersionT childMaxVersion[kMaxNodes];
|
InternalVersionT childMaxVersion[kMaxNodes];
|
||||||
// Sorted
|
// Sorted
|
||||||
uint8_t index[kMaxNodes];
|
uint8_t index[kMaxNodes];
|
||||||
@@ -288,7 +352,7 @@ struct Node48 : Node {
|
|||||||
constexpr static int kMaxOfMaxTotalPages = kMaxNodes / kMaxOfMaxPageSize;
|
constexpr static int kMaxOfMaxTotalPages = kMaxNodes / kMaxOfMaxPageSize;
|
||||||
|
|
||||||
BitSet bitSet;
|
BitSet bitSet;
|
||||||
Node *children[kMaxNodes];
|
TaggedNodePointer children[kMaxNodes];
|
||||||
InternalVersionT childMaxVersion[kMaxNodes];
|
InternalVersionT childMaxVersion[kMaxNodes];
|
||||||
InternalVersionT maxOfMax[kMaxOfMaxTotalPages];
|
InternalVersionT maxOfMax[kMaxOfMaxTotalPages];
|
||||||
uint8_t reverseIndex[kMaxNodes];
|
uint8_t reverseIndex[kMaxNodes];
|
||||||
@@ -310,7 +374,7 @@ struct Node256 : Node {
|
|||||||
constexpr static int kMaxOfMaxTotalPages = kMaxNodes / kMaxOfMaxPageSize;
|
constexpr static int kMaxOfMaxTotalPages = kMaxNodes / kMaxOfMaxPageSize;
|
||||||
|
|
||||||
BitSet bitSet;
|
BitSet bitSet;
|
||||||
Node *children[kMaxNodes];
|
TaggedNodePointer children[kMaxNodes];
|
||||||
InternalVersionT childMaxVersion[kMaxNodes];
|
InternalVersionT childMaxVersion[kMaxNodes];
|
||||||
InternalVersionT maxOfMax[kMaxOfMaxTotalPages];
|
InternalVersionT maxOfMax[kMaxOfMaxTotalPages];
|
||||||
|
|
||||||
@@ -888,26 +952,26 @@ int getNodeIndexExists(Node16 *self, uint8_t index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Precondition - an entry for index must exist in the node
|
// Precondition - an entry for index must exist in the node
|
||||||
Node *&getChildExists(Node3 *self, uint8_t index) {
|
TaggedNodePointer &getChildExists(Node3 *self, uint8_t index) {
|
||||||
return self->children[getNodeIndexExists(self, index)];
|
return self->children[getNodeIndexExists(self, index)];
|
||||||
}
|
}
|
||||||
// Precondition - an entry for index must exist in the node
|
// Precondition - an entry for index must exist in the node
|
||||||
Node *&getChildExists(Node16 *self, uint8_t index) {
|
TaggedNodePointer &getChildExists(Node16 *self, uint8_t index) {
|
||||||
return self->children[getNodeIndexExists(self, index)];
|
return self->children[getNodeIndexExists(self, index)];
|
||||||
}
|
}
|
||||||
// Precondition - an entry for index must exist in the node
|
// Precondition - an entry for index must exist in the node
|
||||||
Node *&getChildExists(Node48 *self, uint8_t index) {
|
TaggedNodePointer &getChildExists(Node48 *self, uint8_t index) {
|
||||||
assert(self->bitSet.test(index));
|
assert(self->bitSet.test(index));
|
||||||
return self->children[self->index[index]];
|
return self->children[self->index[index]];
|
||||||
}
|
}
|
||||||
// Precondition - an entry for index must exist in the node
|
// Precondition - an entry for index must exist in the node
|
||||||
Node *&getChildExists(Node256 *self, uint8_t index) {
|
TaggedNodePointer &getChildExists(Node256 *self, uint8_t index) {
|
||||||
assert(self->bitSet.test(index));
|
assert(self->bitSet.test(index));
|
||||||
return self->children[index];
|
return self->children[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Precondition - an entry for index must exist in the node
|
// Precondition - an entry for index must exist in the node
|
||||||
Node *&getChildExists(Node *self, uint8_t index) {
|
TaggedNodePointer &getChildExists(Node *self, uint8_t index) {
|
||||||
switch (self->getType()) {
|
switch (self->getType()) {
|
||||||
case Type_Node0: // GCOVR_EXCL_LINE
|
case Type_Node0: // GCOVR_EXCL_LINE
|
||||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||||
@@ -1038,24 +1102,26 @@ void setMaxVersion(Node *n, InternalVersionT newMax) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Node *&getInTree(Node *n, ConflictSet::Impl *);
|
TaggedNodePointer &getInTree(Node *n, ConflictSet::Impl *);
|
||||||
|
|
||||||
Node *getChild(Node0 *, uint8_t) { return nullptr; }
|
TaggedNodePointer getChild(Node0 *, uint8_t) { return nullptr; }
|
||||||
Node *getChild(Node3 *self, uint8_t index) {
|
TaggedNodePointer getChild(Node3 *self, uint8_t index) {
|
||||||
int i = getNodeIndex(self, index);
|
int i = getNodeIndex(self, index);
|
||||||
return i < 0 ? nullptr : self->children[i];
|
return i < 0 ? nullptr : self->children[i];
|
||||||
}
|
}
|
||||||
Node *getChild(Node16 *self, uint8_t index) {
|
TaggedNodePointer getChild(Node16 *self, uint8_t index) {
|
||||||
int i = getNodeIndex(self, index);
|
int i = getNodeIndex(self, index);
|
||||||
return i < 0 ? nullptr : self->children[i];
|
return i < 0 ? nullptr : self->children[i];
|
||||||
}
|
}
|
||||||
Node *getChild(Node48 *self, uint8_t index) {
|
TaggedNodePointer getChild(Node48 *self, uint8_t index) {
|
||||||
int i = self->index[index];
|
int i = self->index[index];
|
||||||
return i < 0 ? nullptr : self->children[i];
|
return i < 0 ? nullptr : self->children[i];
|
||||||
}
|
}
|
||||||
Node *getChild(Node256 *self, uint8_t index) { return self->children[index]; }
|
TaggedNodePointer getChild(Node256 *self, uint8_t index) {
|
||||||
|
return self->children[index];
|
||||||
|
}
|
||||||
|
|
||||||
Node *getChild(Node *self, uint8_t index) {
|
TaggedNodePointer getChild(Node *self, uint8_t index) {
|
||||||
switch (self->getType()) {
|
switch (self->getType()) {
|
||||||
case Type_Node0:
|
case Type_Node0:
|
||||||
return getChild(static_cast<Node0 *>(self), index);
|
return getChild(static_cast<Node0 *>(self), index);
|
||||||
@@ -1073,7 +1139,7 @@ Node *getChild(Node *self, uint8_t index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ChildAndMaxVersion {
|
struct ChildAndMaxVersion {
|
||||||
Node *child;
|
TaggedNodePointer child;
|
||||||
InternalVersionT maxVersion;
|
InternalVersionT maxVersion;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1245,14 +1311,15 @@ Node *getFirstChildExists(Node *self) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void consumePartialKeyFull(Node *&self, std::span<const uint8_t> &key,
|
void consumePartialKeyFull(TaggedNodePointer &self,
|
||||||
|
std::span<const uint8_t> &key,
|
||||||
InternalVersionT writeVersion, WriteContext *tls) {
|
InternalVersionT writeVersion, WriteContext *tls) {
|
||||||
// Handle an existing partial key
|
// Handle an existing partial key
|
||||||
int commonLen = std::min<int>(self->partialKeyLen, key.size());
|
int commonLen = std::min<int>(self->partialKeyLen, key.size());
|
||||||
int partialKeyIndex =
|
int partialKeyIndex =
|
||||||
longestCommonPrefix(self->partialKey(), key.data(), commonLen);
|
longestCommonPrefix(self->partialKey(), key.data(), commonLen);
|
||||||
if (partialKeyIndex < self->partialKeyLen) {
|
if (partialKeyIndex < self->partialKeyLen) {
|
||||||
auto *old = self;
|
Node *old = self;
|
||||||
// Since root cannot have a partial key
|
// Since root cannot have a partial key
|
||||||
assert(old->parent != nullptr);
|
assert(old->parent != nullptr);
|
||||||
InternalVersionT oldMaxVersion = exchangeMaxVersion(old, writeVersion);
|
InternalVersionT oldMaxVersion = exchangeMaxVersion(old, writeVersion);
|
||||||
@@ -1290,7 +1357,7 @@ void consumePartialKeyFull(Node *&self, std::span<const uint8_t> &key,
|
|||||||
// Consume any partial key of `self`, and update `self` and
|
// Consume any partial key of `self`, and update `self` and
|
||||||
// `key` such that `self` is along the search path of `key`
|
// `key` such that `self` is along the search path of `key`
|
||||||
inline __attribute__((always_inline)) void
|
inline __attribute__((always_inline)) void
|
||||||
consumePartialKey(Node *&self, std::span<const uint8_t> &key,
|
consumePartialKey(TaggedNodePointer &self, std::span<const uint8_t> &key,
|
||||||
InternalVersionT writeVersion, WriteContext *tls) {
|
InternalVersionT writeVersion, WriteContext *tls) {
|
||||||
if (self->partialKeyLen > 0) {
|
if (self->partialKeyLen > 0) {
|
||||||
consumePartialKeyFull(self, key, writeVersion, tls);
|
consumePartialKeyFull(self, key, writeVersion, tls);
|
||||||
@@ -1301,8 +1368,10 @@ consumePartialKey(Node *&self, std::span<const uint8_t> &key,
|
|||||||
// such that the search path of the result + key is the same as the search path
|
// such that the search path of the result + key is the same as the search path
|
||||||
// of self + key before the call. Creates a node if necessary. Updates
|
// of self + key before the call. Creates a node if necessary. Updates
|
||||||
// `maxVersion` for result.
|
// `maxVersion` for result.
|
||||||
Node *&getOrCreateChild(Node *&self, std::span<const uint8_t> &key,
|
TaggedNodePointer &getOrCreateChild(TaggedNodePointer &self,
|
||||||
InternalVersionT newMaxVersion, WriteContext *tls) {
|
std::span<const uint8_t> &key,
|
||||||
|
InternalVersionT newMaxVersion,
|
||||||
|
WriteContext *tls) {
|
||||||
|
|
||||||
int index = key.front();
|
int index = key.front();
|
||||||
key = key.subspan(1, key.size() - 1);
|
key = key.subspan(1, key.size() - 1);
|
||||||
@@ -1660,10 +1729,11 @@ void rezero(Node *n, InternalVersionT z) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void mergeWithChild(Node *&self, WriteContext *tls, ConflictSet::Impl *impl,
|
void mergeWithChild(TaggedNodePointer &self, WriteContext *tls,
|
||||||
Node *&dontInvalidate, Node3 *self3) {
|
ConflictSet::Impl *impl, Node *&dontInvalidate,
|
||||||
|
Node3 *self3) {
|
||||||
assert(!self3->entryPresent);
|
assert(!self3->entryPresent);
|
||||||
auto *child = self3->children[0];
|
Node *child = self3->children[0];
|
||||||
int minCapacity = self3->partialKeyLen + 1 + child->partialKeyLen;
|
int minCapacity = self3->partialKeyLen + 1 + child->partialKeyLen;
|
||||||
|
|
||||||
if (minCapacity > child->getCapacity()) {
|
if (minCapacity > child->getCapacity()) {
|
||||||
@@ -1912,7 +1982,8 @@ bool checkPointRead(Node *n, const std::span<const uint8_t> key,
|
|||||||
goto downLeftSpine;
|
goto downLeftSpine;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [child, maxV] = getChildAndMaxVersion(n, remaining[0]);
|
auto [c, maxV] = getChildAndMaxVersion(n, remaining[0]);
|
||||||
|
Node *child = c;
|
||||||
if (child == nullptr) {
|
if (child == nullptr) {
|
||||||
auto c = getChildGeq(n, remaining[0]);
|
auto c = getChildGeq(n, remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
@@ -1982,7 +2053,8 @@ bool checkPrefixRead(Node *n, const std::span<const uint8_t> key,
|
|||||||
return maxVersion(n) <= readVersion;
|
return maxVersion(n) <= readVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [child, maxV] = getChildAndMaxVersion(n, remaining[0]);
|
auto [c, maxV] = getChildAndMaxVersion(n, remaining[0]);
|
||||||
|
Node *child = c;
|
||||||
if (child == nullptr) {
|
if (child == nullptr) {
|
||||||
auto c = getChildGeq(n, remaining[0]);
|
auto c = getChildGeq(n, remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
@@ -2255,7 +2327,7 @@ bool checkMaxBetweenExclusiveImpl(Node *n, int begin, int end,
|
|||||||
if (!mask) {
|
if (!mask) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
auto *child = self->children[std::countr_zero(mask)];
|
Node *child = self->children[std::countr_zero(mask)];
|
||||||
const bool firstRangeOk =
|
const bool firstRangeOk =
|
||||||
!child->entryPresent || child->entry.rangeVersion <= readVersion;
|
!child->entryPresent || child->entry.rangeVersion <= readVersion;
|
||||||
uint32_t compared = 0;
|
uint32_t compared = 0;
|
||||||
@@ -2330,7 +2402,7 @@ bool checkMaxBetweenExclusiveImpl(Node *n, int begin, int end,
|
|||||||
if (!mask) {
|
if (!mask) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
auto *child = self->children[std::countr_zero(mask)];
|
Node *child = self->children[std::countr_zero(mask)];
|
||||||
const bool firstRangeOk =
|
const bool firstRangeOk =
|
||||||
!child->entryPresent || child->entry.rangeVersion <= readVersion;
|
!child->entryPresent || child->entry.rangeVersion <= readVersion;
|
||||||
|
|
||||||
@@ -2375,7 +2447,7 @@ bool checkMaxBetweenExclusiveImpl(Node *n, int begin, int end,
|
|||||||
{
|
{
|
||||||
int c = self->bitSet.firstSetGeq(begin + 1);
|
int c = self->bitSet.firstSetGeq(begin + 1);
|
||||||
if (c >= 0 && c < end) {
|
if (c >= 0 && c < end) {
|
||||||
auto *child = self->children[self->index[c]];
|
Node *child = self->children[self->index[c]];
|
||||||
if (child->entryPresent && child->entry.rangeVersion > readVersion) {
|
if (child->entryPresent && child->entry.rangeVersion > readVersion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2409,7 +2481,7 @@ bool checkMaxBetweenExclusiveImpl(Node *n, int begin, int end,
|
|||||||
{
|
{
|
||||||
int c = self->bitSet.firstSetGeq(begin + 1);
|
int c = self->bitSet.firstSetGeq(begin + 1);
|
||||||
if (c >= 0 && c < end) {
|
if (c >= 0 && c < end) {
|
||||||
auto *child = self->children[c];
|
Node *child = self->children[c];
|
||||||
if (child->entryPresent && child->entry.rangeVersion > readVersion) {
|
if (child->entryPresent && child->entry.rangeVersion > readVersion) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2509,7 +2581,7 @@ bool checkRangeStartsWith(Node *n, std::span<const uint8_t> key, int begin,
|
|||||||
return checkMaxBetweenExclusive(n, begin, end, readVersion, tls);
|
return checkMaxBetweenExclusive(n, begin, end, readVersion, tls);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *child = getChild(n, remaining[0]);
|
Node *child = getChild(n, remaining[0]);
|
||||||
if (child == nullptr) {
|
if (child == nullptr) {
|
||||||
auto c = getChildGeq(n, remaining[0]);
|
auto c = getChildGeq(n, remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
@@ -2581,7 +2653,8 @@ bool checkRangeLeftSide(Node *n, std::span<const uint8_t> key, int prefixLen,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto [child, maxV] = getChildAndMaxVersion(n, remaining[0]);
|
auto [c, maxV] = getChildAndMaxVersion(n, remaining[0]);
|
||||||
|
Node *child = c;
|
||||||
if (child == nullptr) {
|
if (child == nullptr) {
|
||||||
auto c = getChildGeq(n, remaining[0]);
|
auto c = getChildGeq(n, remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
@@ -2675,7 +2748,7 @@ bool checkRangeRightSide(Node *n, std::span<const uint8_t> key, int prefixLen,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *child = getChild(n, remaining[0]);
|
Node *child = getChild(n, remaining[0]);
|
||||||
if (child == nullptr) {
|
if (child == nullptr) {
|
||||||
auto c = getChildGeq(n, remaining[0]);
|
auto c = getChildGeq(n, remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
@@ -2769,7 +2842,8 @@ bool checkRangeRead(Node *n, std::span<const uint8_t> begin,
|
|||||||
if (remaining.size() == 0) {
|
if (remaining.size() == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
auto [child, v] = getChildAndMaxVersion(n, remaining[0]);
|
auto [c, v] = getChildAndMaxVersion(n, remaining[0]);
|
||||||
|
Node *child = c;
|
||||||
if (child == nullptr) {
|
if (child == nullptr) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2835,8 +2909,10 @@ checkMaxBetweenExclusiveImpl<true>(Node *n, int begin, int end,
|
|||||||
// of the result will have `maxVersion` set to `writeVersion` as a
|
// of the result will have `maxVersion` set to `writeVersion` as a
|
||||||
// postcondition. Nodes along the search path may be invalidated. Callers must
|
// postcondition. Nodes along the search path may be invalidated. Callers must
|
||||||
// ensure that the max version of the self argument is updated.
|
// ensure that the max version of the self argument is updated.
|
||||||
[[nodiscard]] Node **insert(Node **self, std::span<const uint8_t> key,
|
[[nodiscard]] TaggedNodePointer *insert(TaggedNodePointer *self,
|
||||||
InternalVersionT writeVersion, WriteContext *tls) {
|
std::span<const uint8_t> key,
|
||||||
|
InternalVersionT writeVersion,
|
||||||
|
WriteContext *tls) {
|
||||||
|
|
||||||
for (; key.size() != 0; ++tls->accum.insert_iterations) {
|
for (; key.size() != 0; ++tls->accum.insert_iterations) {
|
||||||
self = &getOrCreateChild(*self, key, writeVersion, tls);
|
self = &getOrCreateChild(*self, key, writeVersion, tls);
|
||||||
@@ -2864,17 +2940,23 @@ void eraseTree(Node *root, WriteContext *tls) {
|
|||||||
} break;
|
} break;
|
||||||
case Type_Node3: {
|
case Type_Node3: {
|
||||||
auto *n3 = static_cast<Node3 *>(n);
|
auto *n3 = static_cast<Node3 *>(n);
|
||||||
toFree.append(std::span<Node *>(n3->children, n3->numChildren));
|
for (int i = 0; i < n3->numChildren; ++i) {
|
||||||
|
toFree.push_back(n3->children[i]);
|
||||||
|
}
|
||||||
tls->release(n3);
|
tls->release(n3);
|
||||||
} break;
|
} break;
|
||||||
case Type_Node16: {
|
case Type_Node16: {
|
||||||
auto *n16 = static_cast<Node16 *>(n);
|
auto *n16 = static_cast<Node16 *>(n);
|
||||||
toFree.append(std::span<Node *>(n16->children, n16->numChildren));
|
for (int i = 0; i < n16->numChildren; ++i) {
|
||||||
|
toFree.push_back(n16->children[i]);
|
||||||
|
}
|
||||||
tls->release(n16);
|
tls->release(n16);
|
||||||
} break;
|
} break;
|
||||||
case Type_Node48: {
|
case Type_Node48: {
|
||||||
auto *n48 = static_cast<Node48 *>(n);
|
auto *n48 = static_cast<Node48 *>(n);
|
||||||
toFree.append(std::span<Node *>(n48->children, n48->numChildren));
|
for (int i = 0; i < n48->numChildren; ++i) {
|
||||||
|
toFree.push_back(n48->children[i]);
|
||||||
|
}
|
||||||
tls->release(n48);
|
tls->release(n48);
|
||||||
} break;
|
} break;
|
||||||
case Type_Node256: {
|
case Type_Node256: {
|
||||||
@@ -2890,10 +2972,10 @@ void eraseTree(Node *root, WriteContext *tls) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addPointWrite(Node *&root, std::span<const uint8_t> key,
|
void addPointWrite(TaggedNodePointer &root, std::span<const uint8_t> key,
|
||||||
InternalVersionT writeVersion, WriteContext *tls) {
|
InternalVersionT writeVersion, WriteContext *tls) {
|
||||||
++tls->accum.point_writes;
|
++tls->accum.point_writes;
|
||||||
auto *n = *insert(&root, key, writeVersion, tls);
|
auto n = *insert(&root, key, writeVersion, tls);
|
||||||
if (!n->entryPresent) {
|
if (!n->entryPresent) {
|
||||||
++tls->accum.entries_inserted;
|
++tls->accum.entries_inserted;
|
||||||
auto *p = nextLogical(n);
|
auto *p = nextLogical(n);
|
||||||
@@ -3011,7 +3093,7 @@ void fixupMaxVersion(Node *node, WriteContext *tls) {
|
|||||||
setMaxVersion(node, max);
|
setMaxVersion(node, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addWriteRange(Node *&root, std::span<const uint8_t> begin,
|
void addWriteRange(TaggedNodePointer &root, std::span<const uint8_t> begin,
|
||||||
std::span<const uint8_t> end, InternalVersionT writeVersion,
|
std::span<const uint8_t> end, InternalVersionT writeVersion,
|
||||||
WriteContext *tls, ConflictSet::Impl *impl) {
|
WriteContext *tls, ConflictSet::Impl *impl) {
|
||||||
|
|
||||||
@@ -3024,12 +3106,12 @@ void addWriteRange(Node *&root, std::span<const uint8_t> begin,
|
|||||||
++tls->accum.range_writes;
|
++tls->accum.range_writes;
|
||||||
const bool beginIsPrefix = lcp == int(begin.size());
|
const bool beginIsPrefix = lcp == int(begin.size());
|
||||||
|
|
||||||
Node **useAsRoot = insert(&root, begin.subspan(0, lcp), writeVersion, tls);
|
auto useAsRoot = insert(&root, begin.subspan(0, lcp), writeVersion, tls);
|
||||||
|
|
||||||
begin = begin.subspan(lcp, begin.size() - lcp);
|
begin = begin.subspan(lcp, begin.size() - lcp);
|
||||||
end = end.subspan(lcp, end.size() - lcp);
|
end = end.subspan(lcp, end.size() - lcp);
|
||||||
|
|
||||||
auto *beginNode = *insert(useAsRoot, begin, writeVersion, tls);
|
Node *beginNode = *insert(useAsRoot, begin, writeVersion, tls);
|
||||||
addKey(beginNode);
|
addKey(beginNode);
|
||||||
if (!beginNode->entryPresent) {
|
if (!beginNode->entryPresent) {
|
||||||
++tls->accum.entries_inserted;
|
++tls->accum.entries_inserted;
|
||||||
@@ -3040,7 +3122,7 @@ void addWriteRange(Node *&root, std::span<const uint8_t> begin,
|
|||||||
}
|
}
|
||||||
beginNode->entry.pointVersion = writeVersion;
|
beginNode->entry.pointVersion = writeVersion;
|
||||||
|
|
||||||
auto *endNode = *insert(useAsRoot, end, writeVersion, tls);
|
Node *endNode = *insert(useAsRoot, end, writeVersion, tls);
|
||||||
addKey(endNode);
|
addKey(endNode);
|
||||||
if (!endNode->entryPresent) {
|
if (!endNode->entryPresent) {
|
||||||
++tls->accum.entries_inserted;
|
++tls->accum.entries_inserted;
|
||||||
@@ -3060,7 +3142,7 @@ void addWriteRange(Node *&root, std::span<const uint8_t> begin,
|
|||||||
assert(!beginNode->endOfRange);
|
assert(!beginNode->endOfRange);
|
||||||
assert(!endNode->endOfRange);
|
assert(!endNode->endOfRange);
|
||||||
endNode->endOfRange = true;
|
endNode->endOfRange = true;
|
||||||
auto *iter = beginNode;
|
Node *iter = beginNode;
|
||||||
for (iter = nextLogical(iter); !iter->endOfRange;
|
for (iter = nextLogical(iter); !iter->endOfRange;
|
||||||
iter = erase(iter, tls, impl, /*logical*/ true)) {
|
iter = erase(iter, tls, impl, /*logical*/ true)) {
|
||||||
assert(!iter->endOfRange);
|
assert(!iter->endOfRange);
|
||||||
@@ -3080,7 +3162,7 @@ Node *firstGeqPhysical(Node *n, const std::span<const uint8_t> key) {
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *child = getChild(n, remaining[0]);
|
Node *child = getChild(n, remaining[0]);
|
||||||
if (child == nullptr) {
|
if (child == nullptr) {
|
||||||
auto c = getChildGeq(n, remaining[0]);
|
auto c = getChildGeq(n, remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
@@ -3126,34 +3208,288 @@ Node *firstGeqPhysical(Node *n, const std::span<const uint8_t> key) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef __has_attribute
|
||||||
|
#define __has_attribute(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __has_attribute(musttail)
|
||||||
|
#define MUSTTAIL __attribute__((musttail))
|
||||||
|
#else
|
||||||
|
#define MUSTTAIL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __has_attribute(preserve_none)
|
||||||
|
#define PRESERVE_NONE __attribute__((preserve_none))
|
||||||
|
#else
|
||||||
|
#define PRESERVE_NONE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __has_attribute(flatten)
|
||||||
|
#define FLATTEN __attribute__((flatten))
|
||||||
|
#else
|
||||||
|
#define FLATTEN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef PRESERVE_NONE void (*Continuation)(struct CheckJob *,
|
||||||
|
struct CheckContext *);
|
||||||
|
|
||||||
|
// State relevant to an individual query
|
||||||
|
struct CheckJob {
|
||||||
|
void setResult(bool ok) {
|
||||||
|
*result = ok ? ConflictSet::Commit : ConflictSet::Conflict;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(const ConflictSet::ReadRange *read, ConflictSet::Result *result,
|
||||||
|
Node *root, int64_t oldestVersionFullPrecision, ReadContext *tls);
|
||||||
|
|
||||||
|
Node *n;
|
||||||
|
std::span<const uint8_t> begin;
|
||||||
|
InternalVersionT readVersion;
|
||||||
|
ConflictSet::Result *result;
|
||||||
|
Continuation continuation;
|
||||||
|
CheckJob *prev;
|
||||||
|
CheckJob *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
// State relevant to every query
|
||||||
|
struct CheckContext {
|
||||||
|
int count;
|
||||||
|
int64_t oldestVersionFullPrecision;
|
||||||
|
Node *root;
|
||||||
|
const ConflictSet::ReadRange *queries;
|
||||||
|
ConflictSet::Result *results;
|
||||||
|
int64_t started;
|
||||||
|
ReadContext *tls;
|
||||||
|
};
|
||||||
|
|
||||||
|
FLATTEN PRESERVE_NONE void keepGoing(CheckJob *job, CheckContext *context) {
|
||||||
|
job = job->next;
|
||||||
|
MUSTTAIL return job->continuation(job, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
FLATTEN PRESERVE_NONE void complete(CheckJob *job, CheckContext *context) {
|
||||||
|
if (context->started == context->count) {
|
||||||
|
if (job->prev == job) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
job->prev->next = job->next;
|
||||||
|
job->next->prev = job->prev;
|
||||||
|
job = job->prev;
|
||||||
|
} else {
|
||||||
|
int temp = context->started++;
|
||||||
|
job->init(context->queries + temp, context->results + temp, context->root,
|
||||||
|
context->oldestVersionFullPrecision, context->tls);
|
||||||
|
}
|
||||||
|
MUSTTAIL return keepGoing(job, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace check_point_read_state_machine {
|
||||||
|
|
||||||
|
FLATTEN PRESERVE_NONE void begin(CheckJob *, CheckContext *);
|
||||||
|
|
||||||
|
template <class NodeT>
|
||||||
|
FLATTEN PRESERVE_NONE void iter(CheckJob *, CheckContext *);
|
||||||
|
|
||||||
|
FLATTEN PRESERVE_NONE void down_left_spine(CheckJob *, CheckContext *);
|
||||||
|
|
||||||
|
static Continuation iterTable[] = {iter<Node0>, iter<Node3>, iter<Node16>,
|
||||||
|
iter<Node48>, iter<Node256>};
|
||||||
|
|
||||||
|
void begin(CheckJob *job, CheckContext *context) {
|
||||||
|
++context->tls->point_read_accum;
|
||||||
|
#if DEBUG_VERBOSE && !defined(NDEBUG)
|
||||||
|
fprintf(stderr, "Check point read: %s\n", printable(key).c_str());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (job->begin.size() == 0) [[unlikely]] {
|
||||||
|
// We don't erase the root
|
||||||
|
assert(job->n->entryPresent);
|
||||||
|
job->setResult(job->n->entry.pointVersion <= job->readVersion);
|
||||||
|
MUSTTAIL return complete(job, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto taggedChild = getChild(job->n, job->begin[0]);
|
||||||
|
Node *child = taggedChild;
|
||||||
|
if (child == nullptr) [[unlikely]] {
|
||||||
|
auto c = getChildGeq(job->n, job->begin[0]);
|
||||||
|
if (c != nullptr) {
|
||||||
|
job->n = c;
|
||||||
|
job->continuation = down_left_spine;
|
||||||
|
__builtin_prefetch(job->n);
|
||||||
|
MUSTTAIL return keepGoing(job, context);
|
||||||
|
} else {
|
||||||
|
// The root never has a next sibling
|
||||||
|
job->setResult(true);
|
||||||
|
MUSTTAIL return complete(job, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
job->continuation = iterTable[taggedChild.getType()];
|
||||||
|
job->n = child;
|
||||||
|
__builtin_prefetch(child);
|
||||||
|
MUSTTAIL return keepGoing(job, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class NodeT> void iter(CheckJob *job, CheckContext *context) {
|
||||||
|
|
||||||
|
assert(NodeT::kType == job->n->getType());
|
||||||
|
NodeT *n = static_cast<NodeT *>(job->n);
|
||||||
|
job->begin = job->begin.subspan(1, job->begin.size() - 1);
|
||||||
|
|
||||||
|
if (n->partialKeyLen > 0) {
|
||||||
|
int commonLen = std::min<int>(n->partialKeyLen, job->begin.size());
|
||||||
|
int i = longestCommonPrefix(n->partialKey(), job->begin.data(), commonLen);
|
||||||
|
if (i < commonLen) [[unlikely]] {
|
||||||
|
auto c = n->partialKey()[i] <=> job->begin[i];
|
||||||
|
if (c > 0) {
|
||||||
|
job->continuation = down_left_spine;
|
||||||
|
MUSTTAIL return down_left_spine(job, context);
|
||||||
|
} else {
|
||||||
|
job->n = nextSibling(n);
|
||||||
|
if (job->n == nullptr) {
|
||||||
|
job->setResult(true);
|
||||||
|
MUSTTAIL return complete(job, context);
|
||||||
|
}
|
||||||
|
job->continuation = down_left_spine;
|
||||||
|
__builtin_prefetch(job->n);
|
||||||
|
MUSTTAIL return keepGoing(job, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (commonLen == n->partialKeyLen) {
|
||||||
|
// partial key matches
|
||||||
|
job->begin = job->begin.subspan(commonLen, job->begin.size() - commonLen);
|
||||||
|
} else if (n->partialKeyLen > int(job->begin.size())) [[unlikely]] {
|
||||||
|
// n is the first physical node greater than remaining, and there's no
|
||||||
|
// eq node
|
||||||
|
job->continuation = down_left_spine;
|
||||||
|
MUSTTAIL return down_left_spine(job, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
++context->tls->point_read_iterations_accum;
|
||||||
|
|
||||||
|
if (job->begin.size() == 0) [[unlikely]] {
|
||||||
|
if (n->entryPresent) {
|
||||||
|
job->setResult(n->entry.pointVersion <= job->readVersion);
|
||||||
|
MUSTTAIL return complete(job, context);
|
||||||
|
}
|
||||||
|
job->n = getFirstChildExists(n);
|
||||||
|
job->continuation = down_left_spine;
|
||||||
|
__builtin_prefetch(job->n);
|
||||||
|
MUSTTAIL return keepGoing(job, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto taggedChild = getChild(n, job->begin[0]);
|
||||||
|
Node *child = taggedChild;
|
||||||
|
if (child == nullptr) [[unlikely]] {
|
||||||
|
auto c = getChildGeq(n, job->begin[0]);
|
||||||
|
if (c != nullptr) {
|
||||||
|
job->n = c;
|
||||||
|
job->continuation = down_left_spine;
|
||||||
|
__builtin_prefetch(job->n);
|
||||||
|
MUSTTAIL return keepGoing(job, context);
|
||||||
|
} else {
|
||||||
|
job->n = nextSibling(job->n);
|
||||||
|
if (job->n == nullptr) {
|
||||||
|
job->setResult(true);
|
||||||
|
MUSTTAIL return complete(job, context);
|
||||||
|
}
|
||||||
|
job->continuation = down_left_spine;
|
||||||
|
__builtin_prefetch(job->n);
|
||||||
|
MUSTTAIL return keepGoing(job, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
job->continuation = iterTable[taggedChild.getType()];
|
||||||
|
job->n = child;
|
||||||
|
__builtin_prefetch(child);
|
||||||
|
MUSTTAIL return keepGoing(job, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void down_left_spine(CheckJob *job, CheckContext *context) {
|
||||||
|
if (job->n->entryPresent) {
|
||||||
|
job->setResult(job->n->entry.rangeVersion <= job->readVersion);
|
||||||
|
MUSTTAIL return complete(job, context);
|
||||||
|
}
|
||||||
|
job->n = getFirstChildExists(job->n);
|
||||||
|
__builtin_prefetch(job->n);
|
||||||
|
MUSTTAIL return keepGoing(job, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace check_point_read_state_machine
|
||||||
|
|
||||||
|
void CheckJob::init(const ConflictSet::ReadRange *read,
|
||||||
|
ConflictSet::Result *result, Node *root,
|
||||||
|
int64_t oldestVersionFullPrecision, ReadContext *tls) {
|
||||||
|
auto begin = std::span<const uint8_t>(read->begin.p, read->begin.len);
|
||||||
|
auto end = std::span<const uint8_t>(read->end.p, read->end.len);
|
||||||
|
if (read->readVersion < oldestVersionFullPrecision) [[unlikely]] {
|
||||||
|
*result = ConflictSet::TooOld;
|
||||||
|
continuation = complete;
|
||||||
|
} else if (end.size() == 0) {
|
||||||
|
this->begin = begin;
|
||||||
|
this->n = root;
|
||||||
|
this->readVersion = InternalVersionT(read->readVersion);
|
||||||
|
this->result = result;
|
||||||
|
continuation = check_point_read_state_machine::begin;
|
||||||
|
} else {
|
||||||
|
*result = checkRangeRead(root, begin, end,
|
||||||
|
InternalVersionT(read->readVersion), tls)
|
||||||
|
? ConflictSet::Commit
|
||||||
|
: ConflictSet::Conflict;
|
||||||
|
continuation = complete;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||||
|
|
||||||
void check(const ReadRange *reads, Result *result, int count) {
|
void check(const ReadRange *reads, Result *result, int count) {
|
||||||
|
assert(oldestVersionFullPrecision >=
|
||||||
|
newestVersionFullPrecision - kNominalVersionWindow);
|
||||||
|
|
||||||
|
if (count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ReadContext tls;
|
ReadContext tls;
|
||||||
tls.impl = this;
|
tls.impl = this;
|
||||||
int64_t check_byte_accum = 0;
|
int64_t check_byte_accum = 0;
|
||||||
|
constexpr int kConcurrent = 16;
|
||||||
|
CheckJob inProgress[kConcurrent];
|
||||||
|
CheckContext context;
|
||||||
|
context.count = count;
|
||||||
|
context.oldestVersionFullPrecision = oldestVersionFullPrecision;
|
||||||
|
context.root = root;
|
||||||
|
context.queries = reads;
|
||||||
|
context.results = result;
|
||||||
|
context.tls = &tls;
|
||||||
|
int64_t started = std::min(kConcurrent, count);
|
||||||
|
context.started = started;
|
||||||
|
for (int i = 0; i < started; i++) {
|
||||||
|
inProgress[i].init(reads + i, result + i, root,
|
||||||
|
oldestVersionFullPrecision, &tls);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < started - 1; i++) {
|
||||||
|
inProgress[i].next = inProgress + i + 1;
|
||||||
|
}
|
||||||
|
for (int i = 1; i < started; i++) {
|
||||||
|
inProgress[i].prev = inProgress + i - 1;
|
||||||
|
}
|
||||||
|
inProgress[0].prev = inProgress + started - 1;
|
||||||
|
inProgress[started - 1].next = inProgress;
|
||||||
|
|
||||||
|
// Kick off the sequence of tail calls that finally returns once all jobs
|
||||||
|
// are done
|
||||||
|
inProgress->continuation(inProgress, &context);
|
||||||
|
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
assert(reads[i].readVersion >= 0);
|
assert(reads[i].readVersion >= 0);
|
||||||
assert(reads[i].readVersion <= newestVersionFullPrecision);
|
assert(reads[i].readVersion <= newestVersionFullPrecision);
|
||||||
const auto &r = reads[i];
|
const auto &r = reads[i];
|
||||||
check_byte_accum += r.begin.len + r.end.len;
|
check_byte_accum += r.begin.len + r.end.len;
|
||||||
auto begin = std::span<const uint8_t>(r.begin.p, r.begin.len);
|
|
||||||
auto end = std::span<const uint8_t>(r.end.p, r.end.len);
|
|
||||||
assert(oldestVersionFullPrecision >=
|
|
||||||
newestVersionFullPrecision - kNominalVersionWindow);
|
|
||||||
result[i] =
|
|
||||||
reads[i].readVersion < oldestVersionFullPrecision ? TooOld
|
|
||||||
: (end.size() > 0
|
|
||||||
? checkRangeRead(root, begin, end,
|
|
||||||
InternalVersionT(reads[i].readVersion), &tls)
|
|
||||||
: checkPointRead(root, begin,
|
|
||||||
InternalVersionT(reads[i].readVersion), &tls))
|
|
||||||
? Commit
|
|
||||||
: Conflict;
|
|
||||||
tls.commits_accum += result[i] == Commit;
|
tls.commits_accum += result[i] == Commit;
|
||||||
tls.conflicts_accum += result[i] == Conflict;
|
tls.conflicts_accum += result[i] == Conflict;
|
||||||
tls.too_olds_accum += result[i] == TooOld;
|
tls.too_olds_accum += result[i] == TooOld;
|
||||||
}
|
}
|
||||||
|
|
||||||
point_read_total.add(tls.point_read_accum);
|
point_read_total.add(tls.point_read_accum);
|
||||||
prefix_read_total.add(tls.prefix_read_accum);
|
prefix_read_total.add(tls.prefix_read_accum);
|
||||||
range_read_total.add(tls.range_read_accum);
|
range_read_total.add(tls.range_read_accum);
|
||||||
@@ -3375,7 +3711,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
std::span<const uint8_t> removalKey;
|
std::span<const uint8_t> removalKey;
|
||||||
int64_t keyUpdates;
|
int64_t keyUpdates;
|
||||||
|
|
||||||
Node *root;
|
TaggedNodePointer root;
|
||||||
InternalVersionT oldestVersion;
|
InternalVersionT oldestVersion;
|
||||||
int64_t oldestVersionFullPrecision;
|
int64_t oldestVersionFullPrecision;
|
||||||
int64_t oldestExtantVersion;
|
int64_t oldestExtantVersion;
|
||||||
@@ -3456,7 +3792,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Node *&getInTree(Node *n, ConflictSet::Impl *impl) {
|
TaggedNodePointer &getInTree(Node *n, ConflictSet::Impl *impl) {
|
||||||
return n->parent == nullptr ? impl->root
|
return n->parent == nullptr ? impl->root
|
||||||
: getChildExists(n->parent, n->parentsIndex);
|
: getChildExists(n->parent, n->parentsIndex);
|
||||||
}
|
}
|
||||||
@@ -3532,7 +3868,7 @@ Node *firstGeqLogical(Node *n, const std::span<const uint8_t> key) {
|
|||||||
goto downLeftSpine;
|
goto downLeftSpine;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *child = getChild(n, remaining[0]);
|
Node *child = getChild(n, remaining[0]);
|
||||||
if (child == nullptr) {
|
if (child == nullptr) {
|
||||||
auto c = getChildGeq(n, remaining[0]);
|
auto c = getChildGeq(n, remaining[0]);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
|
BIN
corpus/00533f61fd89afb9deb3dc978b368a3b3abf3992
Normal file
BIN
corpus/00533f61fd89afb9deb3dc978b368a3b3abf3992
Normal file
Binary file not shown.
BIN
corpus/00850bfa9ce0f9e64b8688db48dc6562be637d97
Normal file
BIN
corpus/00850bfa9ce0f9e64b8688db48dc6562be637d97
Normal file
Binary file not shown.
BIN
corpus/03119dd29f68a6a8ff8f67a653e7f4ba01c6847a
Normal file
BIN
corpus/03119dd29f68a6a8ff8f67a653e7f4ba01c6847a
Normal file
Binary file not shown.
BIN
corpus/0370da7797ee28434459cf21350d311df2aed581
Normal file
BIN
corpus/0370da7797ee28434459cf21350d311df2aed581
Normal file
Binary file not shown.
BIN
corpus/037f4bcc441003fb4cc2cbfd4d986c201035a744
Normal file
BIN
corpus/037f4bcc441003fb4cc2cbfd4d986c201035a744
Normal file
Binary file not shown.
BIN
corpus/053c56641f68bea3be49d74416d62ca583d6492e
Normal file
BIN
corpus/053c56641f68bea3be49d74416d62ca583d6492e
Normal file
Binary file not shown.
BIN
corpus/05e78ae4ba5007b2ad39b69b19604f8cb90650bd
Normal file
BIN
corpus/05e78ae4ba5007b2ad39b69b19604f8cb90650bd
Normal file
Binary file not shown.
BIN
corpus/07c638816ecc7071961866ba3ed0aa1168f7e998
Normal file
BIN
corpus/07c638816ecc7071961866ba3ed0aa1168f7e998
Normal file
Binary file not shown.
BIN
corpus/090ffb7c1949db26391498d8c7dc3b8f772b90ce
Normal file
BIN
corpus/090ffb7c1949db26391498d8c7dc3b8f772b90ce
Normal file
Binary file not shown.
BIN
corpus/0aa35cd848f2d94178b87dcf68272c8a3f96c42b
Normal file
BIN
corpus/0aa35cd848f2d94178b87dcf68272c8a3f96c42b
Normal file
Binary file not shown.
BIN
corpus/0b323a04077fd639c7e0a51a750eb1259bb6a4b0
Normal file
BIN
corpus/0b323a04077fd639c7e0a51a750eb1259bb6a4b0
Normal file
Binary file not shown.
BIN
corpus/0b445ea9b2e9cd62d4bd681ab94324aea7fe6b98
Normal file
BIN
corpus/0b445ea9b2e9cd62d4bd681ab94324aea7fe6b98
Normal file
Binary file not shown.
BIN
corpus/0b5969da792544a3fd9bb8f9c7fd0a53ad17b938
Normal file
BIN
corpus/0b5969da792544a3fd9bb8f9c7fd0a53ad17b938
Normal file
Binary file not shown.
BIN
corpus/0ed2d396bc5bd9b396942e6ec5569f46bef2476e
Normal file
BIN
corpus/0ed2d396bc5bd9b396942e6ec5569f46bef2476e
Normal file
Binary file not shown.
BIN
corpus/0eea457d59d763abe2b35aa044d839613f0c1eff
Normal file
BIN
corpus/0eea457d59d763abe2b35aa044d839613f0c1eff
Normal file
Binary file not shown.
BIN
corpus/0f8959089fadd2c5542cc9148d86176e800d92d3
Normal file
BIN
corpus/0f8959089fadd2c5542cc9148d86176e800d92d3
Normal file
Binary file not shown.
BIN
corpus/10244abeda5a403187b940e7cedb7a93189f2e67
Normal file
BIN
corpus/10244abeda5a403187b940e7cedb7a93189f2e67
Normal file
Binary file not shown.
BIN
corpus/10c43175be9f940150eb2ec9e709f8d68a9f1a87
Normal file
BIN
corpus/10c43175be9f940150eb2ec9e709f8d68a9f1a87
Normal file
Binary file not shown.
BIN
corpus/10dc6dd48d5819b353f3cabb844e7fefeed0dbce
Normal file
BIN
corpus/10dc6dd48d5819b353f3cabb844e7fefeed0dbce
Normal file
Binary file not shown.
BIN
corpus/1238ace8238748ab0c4bd4e578fa234cb53280ef
Normal file
BIN
corpus/1238ace8238748ab0c4bd4e578fa234cb53280ef
Normal file
Binary file not shown.
BIN
corpus/12a56e9945424996cd08c04ad3261c4bc80aaa17
Normal file
BIN
corpus/12a56e9945424996cd08c04ad3261c4bc80aaa17
Normal file
Binary file not shown.
BIN
corpus/12c1b23a16916c57fec76f5d7b3cbc7d07ad3a01
Normal file
BIN
corpus/12c1b23a16916c57fec76f5d7b3cbc7d07ad3a01
Normal file
Binary file not shown.
BIN
corpus/12e2003fa4ffdbb09ddf81b89d922a6f26d4bbf5
Normal file
BIN
corpus/12e2003fa4ffdbb09ddf81b89d922a6f26d4bbf5
Normal file
Binary file not shown.
BIN
corpus/12f4b3bc769c43a6be2fd9fd0d488439d0dedc9e
Normal file
BIN
corpus/12f4b3bc769c43a6be2fd9fd0d488439d0dedc9e
Normal file
Binary file not shown.
BIN
corpus/138b50160165c26e8ef6281d7ff2139f0ff3fb4f
Normal file
BIN
corpus/138b50160165c26e8ef6281d7ff2139f0ff3fb4f
Normal file
Binary file not shown.
BIN
corpus/13adf2094a36bc035b200dd1c2c2379150e199bd
Normal file
BIN
corpus/13adf2094a36bc035b200dd1c2c2379150e199bd
Normal file
Binary file not shown.
BIN
corpus/142dcdcceda3b86cb8413b5b6b96d214c99221ae
Normal file
BIN
corpus/142dcdcceda3b86cb8413b5b6b96d214c99221ae
Normal file
Binary file not shown.
BIN
corpus/15a3a8596107199f39bfaaf644e4b4ea8504ea2c
Normal file
BIN
corpus/15a3a8596107199f39bfaaf644e4b4ea8504ea2c
Normal file
Binary file not shown.
BIN
corpus/18623ab97d0842e2709ed2870e705c2eacfbb7c8
Normal file
BIN
corpus/18623ab97d0842e2709ed2870e705c2eacfbb7c8
Normal file
Binary file not shown.
BIN
corpus/19212d70d7ccd20b98fad3ba1edebae4aa6236fd
Normal file
BIN
corpus/19212d70d7ccd20b98fad3ba1edebae4aa6236fd
Normal file
Binary file not shown.
BIN
corpus/1ac17c2eaf93409cdc610efe758dfbeed48b0384
Normal file
BIN
corpus/1ac17c2eaf93409cdc610efe758dfbeed48b0384
Normal file
Binary file not shown.
BIN
corpus/1aeef1ad82d916ac77dc877f92262ab928fbd8bf
Normal file
BIN
corpus/1aeef1ad82d916ac77dc877f92262ab928fbd8bf
Normal file
Binary file not shown.
BIN
corpus/1b258ea18042c48ab6c10f10254e5aaeecb04fd5
Normal file
BIN
corpus/1b258ea18042c48ab6c10f10254e5aaeecb04fd5
Normal file
Binary file not shown.
BIN
corpus/1b802ba6b502b722c2f79dc9b268a78531964cba
Normal file
BIN
corpus/1b802ba6b502b722c2f79dc9b268a78531964cba
Normal file
Binary file not shown.
BIN
corpus/1b8daa16f809a7c53ab46c642d7746223c1e89c3
Normal file
BIN
corpus/1b8daa16f809a7c53ab46c642d7746223c1e89c3
Normal file
Binary file not shown.
BIN
corpus/1cf21168dd261282defc4f9550d5073d7325731d
Normal file
BIN
corpus/1cf21168dd261282defc4f9550d5073d7325731d
Normal file
Binary file not shown.
BIN
corpus/1d32cdfb5c5fda145d32ef98c14df05da43edff9
Normal file
BIN
corpus/1d32cdfb5c5fda145d32ef98c14df05da43edff9
Normal file
Binary file not shown.
BIN
corpus/1da019ba42899360b185febee026bff92598fab6
Normal file
BIN
corpus/1da019ba42899360b185febee026bff92598fab6
Normal file
Binary file not shown.
BIN
corpus/1e466f51834d01097b785bcad601630b2f4c4fb3
Normal file
BIN
corpus/1e466f51834d01097b785bcad601630b2f4c4fb3
Normal file
Binary file not shown.
BIN
corpus/1e844736e6767c7c4a05774df051fb2c40ca8d98
Normal file
BIN
corpus/1e844736e6767c7c4a05774df051fb2c40ca8d98
Normal file
Binary file not shown.
BIN
corpus/1ee13de896e906c111ba949e85ed7f48c846df50
Normal file
BIN
corpus/1ee13de896e906c111ba949e85ed7f48c846df50
Normal file
Binary file not shown.
BIN
corpus/2039e0adf8619ec4ce49fca017aa39a8600dc6c9
Normal file
BIN
corpus/2039e0adf8619ec4ce49fca017aa39a8600dc6c9
Normal file
Binary file not shown.
BIN
corpus/20401e8755bab61ef8e9208db78cdbfb59139177
Normal file
BIN
corpus/20401e8755bab61ef8e9208db78cdbfb59139177
Normal file
Binary file not shown.
BIN
corpus/21a3d4a0eb2aa8fd3097a5abef83805e80110944
Normal file
BIN
corpus/21a3d4a0eb2aa8fd3097a5abef83805e80110944
Normal file
Binary file not shown.
BIN
corpus/2250ec7a5578e9511be3649c14dcdd38697015c1
Normal file
BIN
corpus/2250ec7a5578e9511be3649c14dcdd38697015c1
Normal file
Binary file not shown.
BIN
corpus/23a9e57a66b267ea2fe0060b2894afeff525c635
Normal file
BIN
corpus/23a9e57a66b267ea2fe0060b2894afeff525c635
Normal file
Binary file not shown.
BIN
corpus/24089ab0ce8c12a4c5acb10f273ce53b93a65c08
Normal file
BIN
corpus/24089ab0ce8c12a4c5acb10f273ce53b93a65c08
Normal file
Binary file not shown.
BIN
corpus/2537bc610b792602516186a611cff1ada7795a5d
Normal file
BIN
corpus/2537bc610b792602516186a611cff1ada7795a5d
Normal file
Binary file not shown.
BIN
corpus/258d6fbc15128d65e42ce3e561299c6ee3e3484b
Normal file
BIN
corpus/258d6fbc15128d65e42ce3e561299c6ee3e3484b
Normal file
Binary file not shown.
BIN
corpus/259702095aed49b5aaca540dac6d28269a9fd148
Normal file
BIN
corpus/259702095aed49b5aaca540dac6d28269a9fd148
Normal file
Binary file not shown.
BIN
corpus/2a15e4d22a5a2f9e8ec3de15016621df354e6ac7
Normal file
BIN
corpus/2a15e4d22a5a2f9e8ec3de15016621df354e6ac7
Normal file
Binary file not shown.
BIN
corpus/2b4e9e0a74324bccbe722dfe475bf107df42c6f8
Normal file
BIN
corpus/2b4e9e0a74324bccbe722dfe475bf107df42c6f8
Normal file
Binary file not shown.
BIN
corpus/2f6fd9449cd7733833a5119815b7295b09edc9a1
Normal file
BIN
corpus/2f6fd9449cd7733833a5119815b7295b09edc9a1
Normal file
Binary file not shown.
BIN
corpus/316bb5ed63bcc92e6738ec48f795afe56f7ca10f
Normal file
BIN
corpus/316bb5ed63bcc92e6738ec48f795afe56f7ca10f
Normal file
Binary file not shown.
BIN
corpus/330da62b56b866a713befdae197603e59d2a9ed7
Normal file
BIN
corpus/330da62b56b866a713befdae197603e59d2a9ed7
Normal file
Binary file not shown.
BIN
corpus/3377871a18f22528d60d2b51b9f98fabd8966c1b
Normal file
BIN
corpus/3377871a18f22528d60d2b51b9f98fabd8966c1b
Normal file
Binary file not shown.
BIN
corpus/3466899b673dedf91cede941c314db0dab93131f
Normal file
BIN
corpus/3466899b673dedf91cede941c314db0dab93131f
Normal file
Binary file not shown.
BIN
corpus/34d90eccdcc5635b4f36507a9bd864e022bcc998
Normal file
BIN
corpus/34d90eccdcc5635b4f36507a9bd864e022bcc998
Normal file
Binary file not shown.
BIN
corpus/356a70926f5b508e9542b9399fd5d9eea83450a0
Normal file
BIN
corpus/356a70926f5b508e9542b9399fd5d9eea83450a0
Normal file
Binary file not shown.
BIN
corpus/35771141dfa1b3bd0b784ba469d4d319dd3d7800
Normal file
BIN
corpus/35771141dfa1b3bd0b784ba469d4d319dd3d7800
Normal file
Binary file not shown.
BIN
corpus/3585d81febbf44e5ee5454f5ff8143cacccd62d7
Normal file
BIN
corpus/3585d81febbf44e5ee5454f5ff8143cacccd62d7
Normal file
Binary file not shown.
BIN
corpus/368f8a2a3d60c5f73fa3a67d4c592f81bd5bc439
Normal file
BIN
corpus/368f8a2a3d60c5f73fa3a67d4c592f81bd5bc439
Normal file
Binary file not shown.
BIN
corpus/3ba2186d034e9d95397e53107ba600a622c11505
Normal file
BIN
corpus/3ba2186d034e9d95397e53107ba600a622c11505
Normal file
Binary file not shown.
BIN
corpus/3bab37bbf147f1020d3a877d0ac900fb86f69623
Normal file
BIN
corpus/3bab37bbf147f1020d3a877d0ac900fb86f69623
Normal file
Binary file not shown.
BIN
corpus/3c0ca2c59b7e7b64256aaa3351a398f4e1180ca9
Normal file
BIN
corpus/3c0ca2c59b7e7b64256aaa3351a398f4e1180ca9
Normal file
Binary file not shown.
BIN
corpus/3c756216b5cc814af5985cc6ef2f59a275c51954
Normal file
BIN
corpus/3c756216b5cc814af5985cc6ef2f59a275c51954
Normal file
Binary file not shown.
BIN
corpus/3e8092741539dd51b8561acf2c9f15c395d8cc02
Normal file
BIN
corpus/3e8092741539dd51b8561acf2c9f15c395d8cc02
Normal file
Binary file not shown.
BIN
corpus/3ec746d0473c3c756f741658d0825c2bede2173a
Normal file
BIN
corpus/3ec746d0473c3c756f741658d0825c2bede2173a
Normal file
Binary file not shown.
BIN
corpus/40c0cf24dd0e2809281b06b3917910727f9278c3
Normal file
BIN
corpus/40c0cf24dd0e2809281b06b3917910727f9278c3
Normal file
Binary file not shown.
BIN
corpus/41511ef3a9c4d61cd2adbc9f01ed71cbfe6cf37e
Normal file
BIN
corpus/41511ef3a9c4d61cd2adbc9f01ed71cbfe6cf37e
Normal file
Binary file not shown.
BIN
corpus/41b02632b4a15df12d012fc05af2c696aed8b8e5
Normal file
BIN
corpus/41b02632b4a15df12d012fc05af2c696aed8b8e5
Normal file
Binary file not shown.
BIN
corpus/422f18907a48e21c3e337d50cda73ef663e3beed
Normal file
BIN
corpus/422f18907a48e21c3e337d50cda73ef663e3beed
Normal file
Binary file not shown.
BIN
corpus/42a6681fcbebedcfaf7e46b7d45490a049729299
Normal file
BIN
corpus/42a6681fcbebedcfaf7e46b7d45490a049729299
Normal file
Binary file not shown.
BIN
corpus/43fd041f435b52c980fc578073e3ffece8335b8c
Normal file
BIN
corpus/43fd041f435b52c980fc578073e3ffece8335b8c
Normal file
Binary file not shown.
BIN
corpus/4465f40ff741859bcac88cea6f2d8a5aaf56c7a8
Normal file
BIN
corpus/4465f40ff741859bcac88cea6f2d8a5aaf56c7a8
Normal file
Binary file not shown.
BIN
corpus/48373d39e6d45877f67cf4a318211c2da472fb9b
Normal file
BIN
corpus/48373d39e6d45877f67cf4a318211c2da472fb9b
Normal file
Binary file not shown.
BIN
corpus/4844f12d67b5779bae5ecf3103b01430a2155140
Normal file
BIN
corpus/4844f12d67b5779bae5ecf3103b01430a2155140
Normal file
Binary file not shown.
BIN
corpus/48b4269e026a8e9b26c4c9313a275cdbd8c837aa
Normal file
BIN
corpus/48b4269e026a8e9b26c4c9313a275cdbd8c837aa
Normal file
Binary file not shown.
BIN
corpus/4ae1f7137e89d6f9c9079533187a88ec42321092
Normal file
BIN
corpus/4ae1f7137e89d6f9c9079533187a88ec42321092
Normal file
Binary file not shown.
BIN
corpus/4ae57e7e2877620b1785a857f321f3bb0d9ccf11
Normal file
BIN
corpus/4ae57e7e2877620b1785a857f321f3bb0d9ccf11
Normal file
Binary file not shown.
BIN
corpus/4c48ce66e38ecfe8bf57d16aa9ff2b12eb51e71c
Normal file
BIN
corpus/4c48ce66e38ecfe8bf57d16aa9ff2b12eb51e71c
Normal file
Binary file not shown.
BIN
corpus/4d0a44860dbd150cb132f76d02f7bdfc8589767e
Normal file
BIN
corpus/4d0a44860dbd150cb132f76d02f7bdfc8589767e
Normal file
Binary file not shown.
BIN
corpus/4d790e5e6a410e0793dccf93fb0cb6d2ee264882
Normal file
BIN
corpus/4d790e5e6a410e0793dccf93fb0cb6d2ee264882
Normal file
Binary file not shown.
BIN
corpus/4ed655609f4caeffe8a822eedde67840c1fd0ca8
Normal file
BIN
corpus/4ed655609f4caeffe8a822eedde67840c1fd0ca8
Normal file
Binary file not shown.
BIN
corpus/4f66f912bd5ff8a4b8131b4d20f4c8f62a1a4825
Normal file
BIN
corpus/4f66f912bd5ff8a4b8131b4d20f4c8f62a1a4825
Normal file
Binary file not shown.
BIN
corpus/527e824566feda8073a02ede87ff3ec9e621e54f
Normal file
BIN
corpus/527e824566feda8073a02ede87ff3ec9e621e54f
Normal file
Binary file not shown.
BIN
corpus/52b78ae06aff68fdcb36cb00f98b137239127eca
Normal file
BIN
corpus/52b78ae06aff68fdcb36cb00f98b137239127eca
Normal file
Binary file not shown.
BIN
corpus/5344249e358682e6d840aaa93b83d414add79da8
Normal file
BIN
corpus/5344249e358682e6d840aaa93b83d414add79da8
Normal file
Binary file not shown.
BIN
corpus/55a720d6dd90075ee544e7ae50ab89c007d86c06
Normal file
BIN
corpus/55a720d6dd90075ee544e7ae50ab89c007d86c06
Normal file
Binary file not shown.
BIN
corpus/56634af7a28d613c642bb58915e5bb3592fcb2b4
Normal file
BIN
corpus/56634af7a28d613c642bb58915e5bb3592fcb2b4
Normal file
Binary file not shown.
BIN
corpus/5704d358944faf333ebb393767043ee314eba277
Normal file
BIN
corpus/5704d358944faf333ebb393767043ee314eba277
Normal file
Binary file not shown.
BIN
corpus/58151af8e789122f0ba7077e45220c089e2ba80a
Normal file
BIN
corpus/58151af8e789122f0ba7077e45220c089e2ba80a
Normal file
Binary file not shown.
BIN
corpus/587734e5f77eb5f961af9c77f6a84ad023af1b6b
Normal file
BIN
corpus/587734e5f77eb5f961af9c77f6a84ad023af1b6b
Normal file
Binary file not shown.
BIN
corpus/592e4881bab14fef12117905206ab841f2301876
Normal file
BIN
corpus/592e4881bab14fef12117905206ab841f2301876
Normal file
Binary file not shown.
BIN
corpus/5970a48c9760acb1f2fa411a2ef95e8907416707
Normal file
BIN
corpus/5970a48c9760acb1f2fa411a2ef95e8907416707
Normal file
Binary file not shown.
BIN
corpus/59c67c8877c28bffa7e000dc23fd8073b86154a0
Normal file
BIN
corpus/59c67c8877c28bffa7e000dc23fd8073b86154a0
Normal file
Binary file not shown.
BIN
corpus/5ae29d9bc51a9e69599ab4ddd145741f2b21c09d
Normal file
BIN
corpus/5ae29d9bc51a9e69599ab4ddd145741f2b21c09d
Normal file
Binary file not shown.
BIN
corpus/5ae60ef89dde1e9581a18cee62192376e8d68102
Normal file
BIN
corpus/5ae60ef89dde1e9581a18cee62192376e8d68102
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user