Refactor and improve the SHAMap code:

This commit combines a number of cleanups, targeting both the
code structure and the code logic. Large changes include:

 - Using more strongly-typed classes for SHAMap nodes, instead of relying
   on runtime-time detection of class types. This change saves 16 bytes
   of memory per node.
 - Improving the interface of SHAMap::addGiveItem and SHAMap::addItem to
   avoid the need for passing two bool arguments.
 - Documenting the "copy-on-write" semantics that SHAMap uses to
   efficiently track changes in individual nodes.
 - Removing unused code and simplifying several APIs.
 - Improving function naming.
This commit is contained in:
Nik Bougalis
2020-11-13 23:30:43 -08:00
parent 5def79e93c
commit 1bb294afbc
49 changed files with 1641 additions and 1378 deletions

View File

@@ -72,8 +72,8 @@ public:
res->updateSkipList();
{
res->stateMap().flushDirty(hotACCOUNT_NODE, res->info().seq);
res->txMap().flushDirty(hotTRANSACTION_NODE, res->info().seq);
res->stateMap().flushDirty(hotACCOUNT_NODE);
res->txMap().flushDirty(hotTRANSACTION_NODE);
}
res->unshare();

View File

@@ -283,15 +283,14 @@ class DatabaseShard_test : public TestBase
}
// Store the state map
auto visitAcc = [&](SHAMapAbstractNode& node) {
auto visitAcc = [&](SHAMapTreeNode const& node) {
Serializer s;
node.serializeWithPrefix(s);
db.store(
node.getType() == SHAMapAbstractNode::TNType::tnINNER
? hotUNKNOWN
: hotACCOUNT_NODE,
node.getType() == SHAMapNodeType::tnINNER ? hotUNKNOWN
: hotACCOUNT_NODE,
std::move(s.modData()),
node.getNodeHash().as_uint256(),
node.getHash().as_uint256(),
ledger.info().seq);
return true;
};
@@ -311,15 +310,14 @@ class DatabaseShard_test : public TestBase
}
// Store the transaction map
auto visitTx = [&](SHAMapAbstractNode& node) {
auto visitTx = [&](SHAMapTreeNode& node) {
Serializer s;
node.serializeWithPrefix(s);
db.store(
node.getType() == SHAMapAbstractNode::TNType::tnINNER
? hotUNKNOWN
: hotTRANSACTION_NODE,
node.getType() == SHAMapNodeType::tnINNER ? hotUNKNOWN
: hotTRANSACTION_NODE,
std::move(s.modData()),
node.getNodeHash().as_uint256(),
node.getHash().as_uint256(),
ledger.info().seq);
return true;
};
@@ -357,20 +355,19 @@ class DatabaseShard_test : public TestBase
LedgerFill{*fetched, LedgerFill::full | LedgerFill::binary}));
// walk shamap and validate each node
auto fcompAcc = [&](SHAMapAbstractNode& node) -> bool {
auto fcompAcc = [&](SHAMapTreeNode& node) -> bool {
Serializer s;
node.serializeWithPrefix(s);
auto nSrc{NodeObject::createObject(
node.getType() == SHAMapAbstractNode::TNType::tnINNER
? hotUNKNOWN
: hotACCOUNT_NODE,
node.getType() == SHAMapNodeType::tnINNER ? hotUNKNOWN
: hotACCOUNT_NODE,
std::move(s.modData()),
node.getNodeHash().as_uint256())};
node.getHash().as_uint256())};
if (!BEAST_EXPECT(nSrc))
return false;
auto nDst = db.fetchNodeObject(
node.getNodeHash().as_uint256(), ledger.info().seq);
node.getHash().as_uint256(), ledger.info().seq);
if (!BEAST_EXPECT(nDst))
return false;
@@ -381,20 +378,19 @@ class DatabaseShard_test : public TestBase
if (ledger.stateMap().getHash().isNonZero())
ledger.stateMap().snapShot(false)->visitNodes(fcompAcc);
auto fcompTx = [&](SHAMapAbstractNode& node) -> bool {
auto fcompTx = [&](SHAMapTreeNode& node) -> bool {
Serializer s;
node.serializeWithPrefix(s);
auto nSrc{NodeObject::createObject(
node.getType() == SHAMapAbstractNode::TNType::tnINNER
? hotUNKNOWN
: hotTRANSACTION_NODE,
node.getType() == SHAMapNodeType::tnINNER ? hotUNKNOWN
: hotTRANSACTION_NODE,
std::move(s.modData()),
node.getNodeHash().as_uint256())};
node.getHash().as_uint256())};
if (!BEAST_EXPECT(nSrc))
return false;
auto nDst = db.fetchNodeObject(
node.getNodeHash().as_uint256(), ledger.info().seq);
node.getHash().as_uint256(), ledger.info().seq);
if (!BEAST_EXPECT(nDst))
return false;

View File

@@ -65,7 +65,7 @@ public:
SHAMapHash const& nodeHash,
std::uint32_t ledgerSeq,
Blob&& nodeData,
SHAMapTreeNode::TNType type) const override
SHAMapNodeType type) const override
{
}
@@ -100,7 +100,8 @@ public:
while (n--)
{
std::shared_ptr<SHAMapItem> item(make_random_item(r));
auto const result(t.addItem(std::move(*item), false, false));
auto const result(
t.addItem(SHAMapNodeType::tnACCOUNT_STATE, std::move(*item)));
assert(result);
(void)result;
}

View File

@@ -59,7 +59,7 @@ public:
std::shared_ptr<SHAMapItem> item = makeRandomAS();
items.push_back(item->key());
if (!map.addItem(std::move(*item), false, false))
if (!map.addItem(SHAMapNodeType::tnACCOUNT_STATE, std::move(*item)))
{
log << "Unable to add item to map\n";
return false;
@@ -98,7 +98,8 @@ public:
int items = 10000;
for (int i = 0; i < items; ++i)
{
source.addItem(std::move(*makeRandomAS()), false, false);
source.addItem(
SHAMapNodeType::tnACCOUNT_STATE, std::move(*makeRandomAS()));
if (i % 100 == 0)
source.invariants();
}

View File

@@ -64,12 +64,12 @@ static_assert(std::is_copy_assignable<SHAMapHash>{}, "");
static_assert(std::is_move_constructible<SHAMapHash>{}, "");
static_assert(std::is_move_assignable<SHAMapHash>{}, "");
static_assert(!std::is_nothrow_destructible<SHAMapAbstractNode>{}, "");
static_assert(!std::is_default_constructible<SHAMapAbstractNode>{}, "");
static_assert(!std::is_copy_constructible<SHAMapAbstractNode>{}, "");
static_assert(!std::is_copy_assignable<SHAMapAbstractNode>{}, "");
static_assert(!std::is_move_constructible<SHAMapAbstractNode>{}, "");
static_assert(!std::is_move_assignable<SHAMapAbstractNode>{}, "");
static_assert(std::is_nothrow_destructible<SHAMapTreeNode>{}, "");
static_assert(!std::is_default_constructible<SHAMapTreeNode>{}, "");
static_assert(!std::is_copy_constructible<SHAMapTreeNode>{}, "");
static_assert(!std::is_copy_assignable<SHAMapTreeNode>{}, "");
static_assert(!std::is_move_constructible<SHAMapTreeNode>{}, "");
static_assert(!std::is_move_assignable<SHAMapTreeNode>{}, "");
static_assert(std::is_nothrow_destructible<SHAMapInnerNode>{}, "");
static_assert(!std::is_default_constructible<SHAMapInnerNode>{}, "");
@@ -78,12 +78,12 @@ static_assert(!std::is_copy_assignable<SHAMapInnerNode>{}, "");
static_assert(!std::is_move_constructible<SHAMapInnerNode>{}, "");
static_assert(!std::is_move_assignable<SHAMapInnerNode>{}, "");
static_assert(std::is_nothrow_destructible<SHAMapTreeNode>{}, "");
static_assert(!std::is_default_constructible<SHAMapTreeNode>{}, "");
static_assert(!std::is_copy_constructible<SHAMapTreeNode>{}, "");
static_assert(!std::is_copy_assignable<SHAMapTreeNode>{}, "");
static_assert(!std::is_move_constructible<SHAMapTreeNode>{}, "");
static_assert(!std::is_move_assignable<SHAMapTreeNode>{}, "");
static_assert(std::is_nothrow_destructible<SHAMapLeafNode>{}, "");
static_assert(!std::is_default_constructible<SHAMapLeafNode>{}, "");
static_assert(!std::is_copy_constructible<SHAMapLeafNode>{}, "");
static_assert(!std::is_copy_assignable<SHAMapLeafNode>{}, "");
static_assert(!std::is_move_constructible<SHAMapLeafNode>{}, "");
static_assert(!std::is_move_assignable<SHAMapLeafNode>{}, "");
#endif
inline bool
@@ -161,9 +161,13 @@ public:
SHAMapItem i1(h1, IntToVUC(1)), i2(h2, IntToVUC(2)),
i3(h3, IntToVUC(3)), i4(h4, IntToVUC(4)), i5(h5, IntToVUC(5));
unexpected(!sMap.addItem(SHAMapItem{i2}, true, false), "no add");
unexpected(
!sMap.addItem(SHAMapNodeType::tnTRANSACTION_NM, SHAMapItem{i2}),
"no add");
sMap.invariants();
unexpected(!sMap.addItem(SHAMapItem{i1}, true, false), "no add");
unexpected(
!sMap.addItem(SHAMapNodeType::tnTRANSACTION_NM, SHAMapItem{i1}),
"no add");
sMap.invariants();
auto i = sMap.begin();
@@ -173,11 +177,11 @@ public:
unexpected(i == e || (*i != i2), "bad traverse");
++i;
unexpected(i != e, "bad traverse");
sMap.addItem(SHAMapItem{i4}, true, false);
sMap.addItem(SHAMapNodeType::tnTRANSACTION_NM, SHAMapItem{i4});
sMap.invariants();
sMap.delItem(i2.key());
sMap.invariants();
sMap.addItem(SHAMapItem{i3}, true, false);
sMap.addItem(SHAMapNodeType::tnTRANSACTION_NM, SHAMapItem{i3});
sMap.invariants();
i = sMap.begin();
e = sMap.end();
@@ -282,7 +286,8 @@ public:
for (int k = 0; k < keys.size(); ++k)
{
SHAMapItem item(keys[k], IntToVUC(k));
BEAST_EXPECT(map.addItem(std::move(item), true, false));
BEAST_EXPECT(map.addItem(
SHAMapNodeType::tnTRANSACTION_NM, std::move(item)));
BEAST_EXPECT(map.getHash().as_uint256() == hashes[k]);
map.invariants();
}
@@ -333,7 +338,9 @@ public:
map.setUnbacked();
for (auto const& k : keys)
{
map.addItem(SHAMapItem{k, IntToVUC(0)}, true, false);
map.addItem(
SHAMapNodeType::tnTRANSACTION_NM,
SHAMapItem{k, IntToVUC(0)});
map.invariants();
}