Removed use of the C "struct hack" as it is not valid C++. Replaced zero-length members with functions returning a pointer for arrays or a reference for single members.

This commit is contained in:
Stephen Atherton 2019-07-02 00:58:43 -07:00 committed by Alex Miller
parent 817fce080b
commit 71ba490cf8
2 changed files with 66 additions and 40 deletions

View File

@ -69,6 +69,7 @@
// // Retrieves the previously stored boolean
// bool getPrefixSource() const;
//
#pragma pack(push,1)
template <typename T, typename DeltaT = typename T::Delta, typename OffsetT = uint16_t>
struct DeltaTree {
@ -76,36 +77,47 @@ struct DeltaTree {
return std::numeric_limits<OffsetT>::max();
};
#pragma pack(push,1)
struct Node {
OffsetT leftChildOffset;
OffsetT rightChildOffset;
DeltaT delta[0];
inline DeltaT & delta() {
return *(DeltaT *)(this + 1);
};
inline const DeltaT & delta() const {
return *(const DeltaT *)(this + 1);
};
Node * rightChild() const {
//printf("Node(%p): leftOffset=%d rightOffset=%d deltaSize=%d\n", this, (int)leftChildOffset, (int)rightChildOffset, (int)delta->size());
return rightChildOffset == 0 ? nullptr : (Node *)((uint8_t *)delta + rightChildOffset);
//printf("Node(%p): leftOffset=%d rightOffset=%d deltaSize=%d\n", this, (int)leftChildOffset, (int)rightChildOffset, (int)delta().size());
return rightChildOffset == 0 ? nullptr : (Node *)((uint8_t *)&delta() + rightChildOffset);
}
Node * leftChild() const {
//printf("Node(%p): leftOffset=%d rightOffset=%d deltaSize=%d\n", this, (int)leftChildOffset, (int)rightChildOffset, (int)delta->size());
return leftChildOffset == 0 ? nullptr : (Node *)((uint8_t *)delta + leftChildOffset);
//printf("Node(%p): leftOffset=%d rightOffset=%d deltaSize=%d\n", this, (int)leftChildOffset, (int)rightChildOffset, (int)delta().size());
return leftChildOffset == 0 ? nullptr : (Node *)((uint8_t *)&delta() + leftChildOffset);
}
int size() const {
return sizeof(Node) + delta->size();
return sizeof(Node) + delta().size();
}
};
#pragma pack(pop)
#pragma pack(push,1)
struct {
OffsetT nodeBytes; // Total size of all Nodes including the root
uint8_t initialDepth; // Levels in the tree as of the last rebuild
Node root[0];
};
#pragma pack(pop)
inline Node & root() {
return *(Node *)(this + 1);
}
inline const Node & root() const {
return *(const Node *)(this + 1);
}
int size() const {
return sizeof(DeltaTree) + nodeBytes;
}
@ -119,18 +131,18 @@ public:
struct DecodedNode {
DecodedNode(Node *raw, const T *prev, const T *next, Arena &arena)
: raw(raw), parent(nullptr), left(nullptr), right(nullptr), prev(prev), next(next),
item(raw->delta->apply(raw->delta->getPrefixSource() ? *prev : *next, arena))
item(raw->delta().apply(raw->delta().getPrefixSource() ? *prev : *next, arena))
{
//printf("DecodedNode1 raw=%p delta=%s\n", raw, raw->delta->toString().c_str());
//printf("DecodedNode1 raw=%p delta=%s\n", raw, raw->delta().toString().c_str());
}
DecodedNode(Node *raw, DecodedNode *parent, bool left, Arena &arena)
: parent(parent), raw(raw), left(nullptr), right(nullptr),
prev(left ? parent->prev : &parent->item),
next(left ? &parent->item : parent->next),
item(raw->delta->apply(raw->delta->getPrefixSource() ? *prev : *next, arena))
item(raw->delta().apply(raw->delta().getPrefixSource() ? *prev : *next, arena))
{
//printf("DecodedNode2 raw=%p delta=%s\n", raw, raw->delta->toString().c_str());
//printf("DecodedNode2 raw=%p delta=%s\n", raw, raw->delta().toString().c_str());
}
Node *raw;
@ -175,7 +187,7 @@ public:
lower = new(arena) T(arena, *lower);
upper = new(arena) T(arena, *upper);
root = (tree->nodeBytes == 0) ? nullptr : new (arena) DecodedNode(tree->root, lower, upper, arena);
root = (tree->nodeBytes == 0) ? nullptr : new (arena) DecodedNode(&tree->root(), lower, upper, arena);
}
const T *lowerBound() const {
@ -330,7 +342,7 @@ public:
// The boundary leading to the new page acts as the last time we branched right
if(begin != end) {
nodeBytes = build(*root, begin, end, prev, next);
nodeBytes = build(root(), begin, end, prev, next);
}
else {
nodeBytes = 0;
@ -341,7 +353,7 @@ public:
private:
static OffsetT build(Node &root, const T *begin, const T *end, const T *prev, const T *next) {
//printf("build: %s to %s\n", begin->toString().c_str(), (end - 1)->toString().c_str());
//printf("build: root at %p sizeof(Node) %d delta at %p \n", &root, sizeof(Node), root.delta);
//printf("build: root at %p sizeof(Node) %d delta at %p \n", &root, sizeof(Node), &root.delta());
ASSERT(end != begin);
int count = end - begin;
@ -370,12 +382,12 @@ private:
base = next;
}
int deltaSize = item.writeDelta(*root.delta, *base, commonPrefix);
root.delta->setPrefixSource(prefixSourcePrev);
//printf("Serialized %s to %p\n", item.toString().c_str(), root.delta);
int deltaSize = item.writeDelta(root.delta(), *base, commonPrefix);
root.delta().setPrefixSource(prefixSourcePrev);
//printf("Serialized %s to %p\n", item.toString().c_str(), &root.delta());
// Continue writing after the serialized Delta.
uint8_t *wptr = (uint8_t *)root.delta + deltaSize;
uint8_t *wptr = (uint8_t *)&root.delta() + deltaSize;
// Serialize left child
if(count > 1) {
@ -388,7 +400,7 @@ private:
// Serialize right child
if(count > 2) {
root.rightChildOffset = wptr - (uint8_t *)root.delta;
root.rightChildOffset = wptr - (uint8_t *)&root.delta();
wptr += build(*(Node *)wptr, begin + mid + 1, end, &item, next);
}
else {

View File

@ -431,7 +431,14 @@ struct RedwoodRecordRef {
};
uint8_t flags;
byte data[];
inline byte * data() {
return (byte *)(this + 1);
}
inline const byte * data() const {
return (const byte *)(this + 1);
}
void setPrefixSource(bool val) {
if(val) {
@ -447,7 +454,7 @@ struct RedwoodRecordRef {
}
RedwoodRecordRef apply(const RedwoodRecordRef &base, Arena &arena) const {
Reader r(data);
Reader r(data());
int intFieldSuffixLen = flags & INT_FIELD_SUFFIX_BITS;
int prefixLen = r.readVarInt();
@ -501,19 +508,19 @@ struct RedwoodRecordRef {
}
int size() const {
Reader r(data);
Reader r(data());
int intFieldSuffixLen = flags & INT_FIELD_SUFFIX_BITS;
r.readVarInt(); // prefixlen
int valueLen = (flags & HAS_VALUE) ? r.read<uint8_t>() : 0;
int keySuffixLen = (flags & HAS_KEY_SUFFIX) ? r.readVarInt() : 0;
return sizeof(Delta) + r.rptr - data + intFieldSuffixLen + valueLen + keySuffixLen;
return sizeof(Delta) + r.rptr - data() + intFieldSuffixLen + valueLen + keySuffixLen;
}
// Delta can't be determined without the RedwoodRecordRef upon which the Delta is based.
std::string toString() const {
Reader r(data);
Reader r(data());
std::string flagString = " ";
if(flags & PREFIX_SOURCE) flagString += "prefixSource ";
@ -638,7 +645,7 @@ struct RedwoodRecordRef {
commonPrefix = getCommonPrefixLen(base, 0);
}
Writer w(d.data);
Writer w(d.data());
// prefixLen
w.writeVarInt(commonPrefix);
@ -688,7 +695,7 @@ struct RedwoodRecordRef {
w.writeString(value.get());
}
return w.wptr - d.data + sizeof(Delta);
return w.wptr - d.data() + sizeof(Delta);
}
template<typename StringRefT>
@ -737,10 +744,17 @@ struct BTreePage {
uint16_t count;
uint32_t kvBytes;
uint8_t extensionPageCount;
LogicalPageID extensionPages[0];
};
#pragma pack(pop)
inline LogicalPageID * extensionPages() {
return (LogicalPageID *)(this + 1);
}
inline const LogicalPageID * extensionPages() const {
return (const LogicalPageID *)(this + 1);
}
int size() const {
const BinaryTree *t = &tree();
return (uint8_t *)t - (uint8_t *)this + t->size();
@ -751,15 +765,15 @@ struct BTreePage {
}
BinaryTree & tree() {
return *(BinaryTree *)(extensionPages + extensionPageCount);
return *(BinaryTree *)(extensionPages() + extensionPageCount);
}
const BinaryTree & tree() const {
return *(const BinaryTree *)(extensionPages + extensionPageCount);
return *(const BinaryTree *)(extensionPages() + extensionPageCount);
}
static inline int GetHeaderSize(int extensionPages = 0) {
return sizeof(BTreePage) + extensionPages + sizeof(LogicalPageID);
return sizeof(BTreePage) + (extensionPages * sizeof(LogicalPageID));
}
std::string toString(bool write, LogicalPageID id, Version ver, const RedwoodRecordRef *lowerBound, const RedwoodRecordRef *upperBound) const {
@ -1603,7 +1617,7 @@ private:
for(int e = 0, eEnd = extPages.size(); e < eEnd; ++e) {
LogicalPageID eid = m_pager->allocateLogicalPage();
debug_printf("%p: writePages(): Writing extension page op=write id=%u @%" PRId64 " (%d of %lu) referencePageID=%u\n", actor_debug, eid, version, e + 1, extPages.size(), id);
newPage->extensionPages[e] = bigEndian32(eid);
newPage->extensionPages()[e] = bigEndian32(eid);
// If replacing the primary page below (version == 0) then pass the primary page's ID as the reference page ID
m_pager->writePage(eid, extPages[e], version, (version == 0) ? id : invalidLogicalPageID);
++counts.extPageWrites;
@ -1620,8 +1634,8 @@ private:
// Free the old extension pages now that all replacement pages have been written
for(int i = 0; i < originalPage->extensionPageCount; ++i) {
//debug_printf("%p: writePages(): Freeing old extension op=del id=%u @latest\n", actor_debug, bigEndian32(originalPage->extensionPages[i]));
//m_pager->freeLogicalPage(bigEndian32(originalPage->extensionPages[i]), version);
//debug_printf("%p: writePages(): Freeing old extension op=del id=%u @latest\n", actor_debug, bigEndian32(originalPage->extensionPages()[i]));
//m_pager->freeLogicalPage(bigEndian32(originalPage->extensionPages()[i]), version);
}
return primaryLogicalPageIDs;
@ -1684,8 +1698,8 @@ private:
pageGets.push_back(std::move(result));
for(int i = 0; i < pTreePage->extensionPageCount; ++i) {
debug_printf("readPage() Reading extension page op=read id=%u @%" PRId64 " ext=%d/%d\n", bigEndian32(pTreePage->extensionPages[i]), snapshot->getVersion(), i + 1, (int)pTreePage->extensionPageCount);
pageGets.push_back(snapshot->getPhysicalPage(bigEndian32(pTreePage->extensionPages[i])));
debug_printf("readPage() Reading extension page op=read id=%u @%" PRId64 " ext=%d/%d\n", bigEndian32(pTreePage->extensionPages()[i]), snapshot->getVersion(), i + 1, (int)pTreePage->extensionPageCount);
pageGets.push_back(snapshot->getPhysicalPage(bigEndian32(pTreePage->extensionPages()[i])));
}
std::vector<Reference<const IPage>> pages = wait(getAll(pageGets));
@ -3561,12 +3575,12 @@ TEST_CASE("!/redwood/correctness/unit/deltaTree/RedwoodRecordRef") {
while(1) {
if(fwd.get() != items[i]) {
printf("forward iterator i=%d\n %s found\n %s expected\n", i, fwd.get().toString().c_str(), items[i].toString().c_str());
printf("Delta: %s\n", fwd.node->raw->delta->toString().c_str());
printf("Delta: %s\n", fwd.node->raw->delta().toString().c_str());
ASSERT(false);
}
if(rev.get() != items[items.size() - 1 - i]) {
printf("reverse iterator i=%d\n %s found\n %s expected\n", i, rev.get().toString().c_str(), items[items.size() - 1 - i].toString().c_str());
printf("Delta: %s\n", rev.node->raw->delta->toString().c_str());
printf("Delta: %s\n", rev.node->raw->delta().toString().c_str());
ASSERT(false);
}
++i;