mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-04 11:15:56 +00:00
Optimize SHAMapItem and leverage new slab allocator: (#4218)
The `SHAMapItem` class contains a variable-sized buffer that holds the serialized data associated with a particular item inside a `SHAMap`. Prior to this commit, the buffer for the serialized data was allocated separately. Coupled with the fact that most instances of `SHAMapItem` were wrapped around a `std::shared_ptr` meant that an instantiation might result in up to three separate memory allocations. This commit switches away from `std::shared_ptr` for `SHAMapItem` and uses `boost::intrusive_ptr` instead, allowing the reference count for an instance to live inside the instance itself. Coupled with using a slab-based allocator to optimize memory allocation for the most commonly sized buffers, the net result is significant memory savings. In testing, the reduction in memory usage hovers between 400MB and 650MB. Other scenarios might result in larger savings. In performance testing with NFTs, this commit reduces memory size by about 15% sustained over long duration. Commit 2 of 3 in #4218.
This commit is contained in:
@@ -181,7 +181,7 @@ RCLConsensus::Adaptor::share(RCLCxTx const& tx)
|
||||
if (app_.getHashRouter().shouldRelay(tx.id()))
|
||||
{
|
||||
JLOG(j_.debug()) << "Relaying disputed tx " << tx.id();
|
||||
auto const slice = tx.tx_.slice();
|
||||
auto const slice = tx.tx_->slice();
|
||||
protocol::TMTransaction msg;
|
||||
msg.set_rawtransaction(slice.data(), slice.size());
|
||||
msg.set_status(protocol::tsNEW);
|
||||
@@ -325,7 +325,7 @@ RCLConsensus::Adaptor::onClose(
|
||||
tx.first->add(s);
|
||||
initialSet->addItem(
|
||||
SHAMapNodeType::tnTRANSACTION_NM,
|
||||
SHAMapItem(tx.first->getTransactionID(), s.slice()));
|
||||
make_shamapitem(tx.first->getTransactionID(), s.slice()));
|
||||
}
|
||||
|
||||
// Add pseudo-transactions to the set
|
||||
@@ -369,7 +369,8 @@ RCLConsensus::Adaptor::onClose(
|
||||
RCLCensorshipDetector<TxID, LedgerIndex>::TxIDSeqVec proposed;
|
||||
|
||||
initialSet->visitLeaves(
|
||||
[&proposed, seq](std::shared_ptr<SHAMapItem const> const& item) {
|
||||
[&proposed,
|
||||
seq](boost::intrusive_ptr<SHAMapItem const> const& item) {
|
||||
proposed.emplace_back(item->key(), seq);
|
||||
});
|
||||
|
||||
@@ -529,7 +530,7 @@ RCLConsensus::Adaptor::doAccept(
|
||||
std::vector<TxID> accepted;
|
||||
|
||||
result.txns.map_->visitLeaves(
|
||||
[&accepted](std::shared_ptr<SHAMapItem const> const& item) {
|
||||
[&accepted](boost::intrusive_ptr<SHAMapItem const> const& item) {
|
||||
accepted.push_back(item->key());
|
||||
});
|
||||
|
||||
@@ -604,7 +605,7 @@ RCLConsensus::Adaptor::doAccept(
|
||||
<< "Test applying disputed transaction that did"
|
||||
<< " not get in " << dispute.tx().id();
|
||||
|
||||
SerialIter sit(dispute.tx().tx_.slice());
|
||||
SerialIter sit(dispute.tx().tx_->slice());
|
||||
auto txn = std::make_shared<STTx const>(sit);
|
||||
|
||||
// Disputed pseudo-transactions that were not accepted
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
|
||||
@param txn The transaction to wrap
|
||||
*/
|
||||
RCLCxTx(SHAMapItem const& txn) : tx_{txn}
|
||||
RCLCxTx(boost::intrusive_ptr<SHAMapItem const> txn) : tx_(std::move(txn))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -50,11 +50,11 @@ public:
|
||||
ID const&
|
||||
id() const
|
||||
{
|
||||
return tx_.key();
|
||||
return tx_->key();
|
||||
}
|
||||
|
||||
//! The SHAMapItem that represents the transaction.
|
||||
SHAMapItem const tx_;
|
||||
boost::intrusive_ptr<SHAMapItem const> tx_;
|
||||
};
|
||||
|
||||
/** Represents a set of transactions in RCLConsensus.
|
||||
@@ -90,8 +90,7 @@ public:
|
||||
bool
|
||||
insert(Tx const& t)
|
||||
{
|
||||
return map_->addItem(
|
||||
SHAMapNodeType::tnTRANSACTION_NM, SHAMapItem{t.tx_});
|
||||
return map_->addItem(SHAMapNodeType::tnTRANSACTION_NM, t.tx_);
|
||||
}
|
||||
|
||||
/** Remove a transaction from the set.
|
||||
@@ -145,7 +144,7 @@ public:
|
||||
code uses the shared_ptr semantics to know whether the find
|
||||
was successful and properly creates a Tx as needed.
|
||||
*/
|
||||
std::shared_ptr<const SHAMapItem> const&
|
||||
boost::intrusive_ptr<SHAMapItem const> const&
|
||||
find(Tx::ID const& entry) const
|
||||
{
|
||||
return map_->peekItem(entry);
|
||||
|
||||
@@ -119,9 +119,8 @@ public:
|
||||
sles_type::value_type
|
||||
dereference() const override
|
||||
{
|
||||
auto const item = *iter_;
|
||||
SerialIter sit(item.slice());
|
||||
return std::make_shared<SLE const>(sit, item.key());
|
||||
SerialIter sit(iter_->slice());
|
||||
return std::make_shared<SLE const>(sit, iter_->key());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -168,7 +167,7 @@ public:
|
||||
txs_type::value_type
|
||||
dereference() const override
|
||||
{
|
||||
auto const item = *iter_;
|
||||
auto const& item = *iter_;
|
||||
if (metadata_)
|
||||
return deserializeTxPlusMeta(item);
|
||||
return {deserializeTx(item), nullptr};
|
||||
@@ -404,8 +403,8 @@ bool
|
||||
Ledger::addSLE(SLE const& sle)
|
||||
{
|
||||
auto const s = sle.getSerializer();
|
||||
SHAMapItem item(sle.key(), s.slice());
|
||||
return stateMap_->addItem(SHAMapNodeType::tnACCOUNT_STATE, std::move(item));
|
||||
return stateMap_->addItem(
|
||||
SHAMapNodeType::tnACCOUNT_STATE, make_shamapitem(sle.key(), s.slice()));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -565,7 +564,7 @@ Ledger::rawInsert(std::shared_ptr<SLE> const& sle)
|
||||
sle->add(ss);
|
||||
if (!stateMap_->addGiveItem(
|
||||
SHAMapNodeType::tnACCOUNT_STATE,
|
||||
std::make_shared<SHAMapItem const>(sle->key(), ss.slice())))
|
||||
make_shamapitem(sle->key(), ss.slice())))
|
||||
LogicError("Ledger::rawInsert: key already exists");
|
||||
}
|
||||
|
||||
@@ -576,7 +575,7 @@ Ledger::rawReplace(std::shared_ptr<SLE> const& sle)
|
||||
sle->add(ss);
|
||||
if (!stateMap_->updateGiveItem(
|
||||
SHAMapNodeType::tnACCOUNT_STATE,
|
||||
std::make_shared<SHAMapItem const>(sle->key(), ss.slice())))
|
||||
make_shamapitem(sle->key(), ss.slice())))
|
||||
LogicError("Ledger::rawReplace: key not found");
|
||||
}
|
||||
|
||||
@@ -593,8 +592,7 @@ Ledger::rawTxInsert(
|
||||
s.addVL(txn->peekData());
|
||||
s.addVL(metaData->peekData());
|
||||
if (!txMap().addGiveItem(
|
||||
SHAMapNodeType::tnTRANSACTION_MD,
|
||||
std::make_shared<SHAMapItem const>(key, s.slice())))
|
||||
SHAMapNodeType::tnTRANSACTION_MD, make_shamapitem(key, s.slice())))
|
||||
LogicError("duplicate_tx: " + to_string(key));
|
||||
}
|
||||
|
||||
@@ -610,7 +608,7 @@ Ledger::rawTxInsertWithHash(
|
||||
Serializer s(txn->getDataLength() + metaData->getDataLength() + 16);
|
||||
s.addVL(txn->peekData());
|
||||
s.addVL(metaData->peekData());
|
||||
auto item = std::make_shared<SHAMapItem const>(key, s.slice());
|
||||
auto item = make_shamapitem(key, s.slice());
|
||||
auto hash = sha512Half(HashPrefix::txNode, item->slice(), item->key());
|
||||
if (!txMap().addGiveItem(SHAMapNodeType::tnTRANSACTION_MD, std::move(item)))
|
||||
LogicError("duplicate_tx: " + to_string(key));
|
||||
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
void
|
||||
gotSkipList(
|
||||
LedgerInfo const& info,
|
||||
std::shared_ptr<SHAMapItem const> const& data);
|
||||
boost::intrusive_ptr<SHAMapItem const> const& data);
|
||||
|
||||
/**
|
||||
* Process a ledger delta (extracted from a TMReplayDeltaResponse message)
|
||||
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
|
||||
std::shared_ptr<STTx const>
|
||||
fetch(
|
||||
std::shared_ptr<SHAMapItem> const& item,
|
||||
boost::intrusive_ptr<SHAMapItem> const& item,
|
||||
SHAMapNodeType type,
|
||||
std::uint32_t uCommitLedger);
|
||||
|
||||
|
||||
@@ -163,15 +163,15 @@ LedgerReplayMsgHandler::processProofPathResponse(
|
||||
JLOG(journal_.debug()) << "Bad message: Cannot deserialize";
|
||||
return false;
|
||||
}
|
||||
auto item = static_cast<SHAMapLeafNode*>(node.get())->peekItem();
|
||||
if (!item)
|
||||
|
||||
if (auto item = static_cast<SHAMapLeafNode*>(node.get())->peekItem())
|
||||
{
|
||||
JLOG(journal_.debug()) << "Bad message: Cannot get ShaMapItem";
|
||||
return false;
|
||||
replayer_.gotSkipList(info, item);
|
||||
return true;
|
||||
}
|
||||
|
||||
replayer_.gotSkipList(info, item);
|
||||
return true;
|
||||
JLOG(journal_.debug()) << "Bad message: Cannot get ShaMapItem";
|
||||
return false;
|
||||
}
|
||||
|
||||
protocol::TMReplayDeltaResponse
|
||||
@@ -206,9 +206,10 @@ LedgerReplayMsgHandler::processReplayDeltaRequest(
|
||||
reply.set_ledgerheader(nData.getDataPtr(), nData.getLength());
|
||||
// pack transactions
|
||||
auto const& txMap = ledger->txMap();
|
||||
txMap.visitLeaves([&](std::shared_ptr<SHAMapItem const> const& txNode) {
|
||||
reply.add_transaction(txNode->data(), txNode->size());
|
||||
});
|
||||
txMap.visitLeaves(
|
||||
[&](boost::intrusive_ptr<SHAMapItem const> const& txNode) {
|
||||
reply.add_transaction(txNode->data(), txNode->size());
|
||||
});
|
||||
|
||||
JLOG(journal_.debug()) << "getReplayDelta for ledger " << ledgerHash
|
||||
<< " txMap hash " << txMap.getHash().as_uint256();
|
||||
@@ -264,10 +265,9 @@ LedgerReplayMsgHandler::processReplayDeltaResponse(
|
||||
STObject meta(metaSit, sfMetadata);
|
||||
orderedTxns.emplace(meta[sfTransactionIndex], std::move(tx));
|
||||
|
||||
auto item =
|
||||
std::make_shared<SHAMapItem const>(tid, shaMapItemData.slice());
|
||||
if (!item ||
|
||||
!txMap.addGiveItem(SHAMapNodeType::tnTRANSACTION_MD, item))
|
||||
if (!txMap.addGiveItem(
|
||||
SHAMapNodeType::tnTRANSACTION_MD,
|
||||
make_shamapitem(tid, shaMapItemData.slice())))
|
||||
{
|
||||
JLOG(journal_.debug()) << "Bad message: Cannot deserialize";
|
||||
return false;
|
||||
|
||||
@@ -172,7 +172,7 @@ LedgerReplayer::createDeltas(std::shared_ptr<LedgerReplayTask> task)
|
||||
void
|
||||
LedgerReplayer::gotSkipList(
|
||||
LedgerInfo const& info,
|
||||
std::shared_ptr<SHAMapItem const> const& item)
|
||||
boost::intrusive_ptr<SHAMapItem const> const& item)
|
||||
{
|
||||
std::shared_ptr<SkipListAcquire> skipList = {};
|
||||
{
|
||||
|
||||
@@ -137,7 +137,7 @@ SkipListAcquire::pmDowncast()
|
||||
void
|
||||
SkipListAcquire::processData(
|
||||
std::uint32_t ledgerSeq,
|
||||
std::shared_ptr<SHAMapItem const> const& item)
|
||||
boost::intrusive_ptr<SHAMapItem const> const& item)
|
||||
{
|
||||
assert(ledgerSeq != 0 && item);
|
||||
ScopedLockType sl(mtx_);
|
||||
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
void
|
||||
processData(
|
||||
std::uint32_t ledgerSeq,
|
||||
std::shared_ptr<SHAMapItem const> const& item);
|
||||
boost::intrusive_ptr<SHAMapItem const> const& item);
|
||||
|
||||
/**
|
||||
* Add a callback that will be called when the skipList is ready or failed.
|
||||
|
||||
@@ -107,7 +107,7 @@ TransactionMaster::fetch(
|
||||
|
||||
std::shared_ptr<STTx const>
|
||||
TransactionMaster::fetch(
|
||||
std::shared_ptr<SHAMapItem> const& item,
|
||||
boost::intrusive_ptr<SHAMapItem> const& item,
|
||||
SHAMapNodeType type,
|
||||
std::uint32_t uCommitLedger)
|
||||
{
|
||||
|
||||
@@ -172,8 +172,7 @@ public:
|
||||
|
||||
initialPosition->addGiveItem(
|
||||
SHAMapNodeType::tnTRANSACTION_NM,
|
||||
std::make_shared<SHAMapItem>(
|
||||
amendTx.getTransactionID(), s.slice()));
|
||||
make_shamapitem(amendTx.getTransactionID(), s.slice()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -326,7 +326,7 @@ FeeVoteImpl::doVoting(
|
||||
|
||||
if (!initialPosition->addGiveItem(
|
||||
SHAMapNodeType::tnTRANSACTION_NM,
|
||||
std::make_shared<SHAMapItem>(txID, s.slice())))
|
||||
make_shamapitem(txID, s.slice())))
|
||||
{
|
||||
JLOG(journal_.warn()) << "Ledger already had fee change";
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <ripple/app/consensus/RCLValidations.h>
|
||||
#include <ripple/app/ledger/Ledger.h>
|
||||
#include <ripple/app/misc/NegativeUNLVote.h>
|
||||
#include <ripple/shamap/SHAMapItem.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -115,12 +116,11 @@ NegativeUNLVote::addTx(
|
||||
obj.setFieldVL(sfUNLModifyValidator, vp.slice());
|
||||
});
|
||||
|
||||
uint256 txID = negUnlTx.getTransactionID();
|
||||
Serializer s;
|
||||
negUnlTx.add(s);
|
||||
if (!initialSet->addGiveItem(
|
||||
SHAMapNodeType::tnTRANSACTION_NM,
|
||||
std::make_shared<SHAMapItem>(txID, s.slice())))
|
||||
make_shamapitem(negUnlTx.getTransactionID(), s.slice())))
|
||||
{
|
||||
JLOG(j_.warn()) << "N-UNL: ledger seq=" << seq
|
||||
<< ", add ttUNL_MODIFY tx failed";
|
||||
@@ -128,8 +128,8 @@ NegativeUNLVote::addTx(
|
||||
else
|
||||
{
|
||||
JLOG(j_.debug()) << "N-UNL: ledger seq=" << seq
|
||||
<< ", add a ttUNL_MODIFY Tx with txID: " << txID
|
||||
<< ", the validator to "
|
||||
<< ", add a ttUNL_MODIFY Tx with txID: "
|
||||
<< negUnlTx.getTransactionID() << ", the validator to "
|
||||
<< (modify == ToDisable ? "disable: " : "re-enable: ")
|
||||
<< vp;
|
||||
}
|
||||
|
||||
@@ -1643,7 +1643,7 @@ Consensus<Adaptor>::createDisputes(TxSet_t const& o)
|
||||
(inThisSet && result_->txns.find(txId) && !o.find(txId)) ||
|
||||
(!inThisSet && !result_->txns.find(txId) && o.find(txId)));
|
||||
|
||||
Tx_t tx = inThisSet ? *result_->txns.find(txId) : *o.find(txId);
|
||||
Tx_t tx = inThisSet ? result_->txns.find(txId) : o.find(txId);
|
||||
auto txID = tx.id();
|
||||
|
||||
if (result_->disputes.find(txID) != result_->disputes.end())
|
||||
|
||||
@@ -195,7 +195,7 @@ three database entries upon completion.
|
||||
Since downloads execute serially by design, the entries in this table always
|
||||
correspond to the contents of a single file.
|
||||
|
||||
| Bytes | Size | Part |
|
||||
| Bytes | size | Part |
|
||||
|:------:|:----------:|:----:|
|
||||
| 0x... | 2147483647 | 0 |
|
||||
| 0x... | 2147483647 | 1 |
|
||||
|
||||
@@ -22,7 +22,7 @@ uint64 Appnum Application defined constant
|
||||
uint16 KeySize Key size in bytes
|
||||
uint64 Salt A random seed
|
||||
uint64 Pepper The salt hashed
|
||||
uint16 BlockSize Size of a file block in bytes
|
||||
uint16 BlockSize size of a file block in bytes
|
||||
uint16 LoadFactor Target fraction in 65536ths
|
||||
uint8[56] Reserved Zeroes
|
||||
uint8[] Reserved Zero-pad to block size
|
||||
@@ -160,4 +160,3 @@ Iteration 0: RIPEMD160[nudb.dat] = FAE6AE84C15968B0419FDFC014931EA12A396C71
|
||||
Iteration 1: RIPEMD160[nudb.key] = F96BF2722AB2EE009FFAE4A36AAFC4F220E21951
|
||||
Iteration 1: RIPEMD160[nudb.dat] = FAE6AE84C15968B0419FDFC014931EA12A396C71
|
||||
```
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Shard Size Tuning
|
||||
# Shard size Tuning
|
||||
|
||||
The purpose of this document is to compare the sizes of shards containing
|
||||
varying amounts of ledgers.
|
||||
|
||||
@@ -38,7 +38,7 @@ DecodedBlob::DecodedBlob(void const* key, void const* value, int valueBytes)
|
||||
|
||||
m_success = false;
|
||||
m_key = key;
|
||||
// VFALCO NOTE Ledger indexes should have started at 1
|
||||
// VFALCO NOTE Ledger indexes should hav e started at 1
|
||||
m_objectType = hotUNKNOWN;
|
||||
m_objectData = nullptr;
|
||||
m_dataBytes = std::max(0, valueBytes - 9);
|
||||
|
||||
@@ -120,8 +120,8 @@ public:
|
||||
static inline constexpr unsigned int leafDepth = 64;
|
||||
|
||||
using DeltaItem = std::pair<
|
||||
std::shared_ptr<SHAMapItem const>,
|
||||
std::shared_ptr<SHAMapItem const>>;
|
||||
boost::intrusive_ptr<SHAMapItem const>,
|
||||
boost::intrusive_ptr<SHAMapItem const>>;
|
||||
using Delta = std::map<uint256, DeltaItem>;
|
||||
|
||||
SHAMap(SHAMap const&) = delete;
|
||||
@@ -190,23 +190,27 @@ public:
|
||||
delItem(uint256 const& id);
|
||||
|
||||
bool
|
||||
addItem(SHAMapNodeType type, SHAMapItem&& i);
|
||||
addItem(SHAMapNodeType type, boost::intrusive_ptr<SHAMapItem const> item);
|
||||
|
||||
SHAMapHash
|
||||
getHash() const;
|
||||
|
||||
// save a copy if you have a temporary anyway
|
||||
bool
|
||||
updateGiveItem(SHAMapNodeType type, std::shared_ptr<SHAMapItem const>);
|
||||
updateGiveItem(
|
||||
SHAMapNodeType type,
|
||||
boost::intrusive_ptr<SHAMapItem const> item);
|
||||
|
||||
bool
|
||||
addGiveItem(SHAMapNodeType type, std::shared_ptr<SHAMapItem const> item);
|
||||
addGiveItem(
|
||||
SHAMapNodeType type,
|
||||
boost::intrusive_ptr<SHAMapItem const> item);
|
||||
|
||||
// Save a copy if you need to extend the life
|
||||
// of the SHAMapItem beyond this SHAMap
|
||||
std::shared_ptr<SHAMapItem const> const&
|
||||
boost::intrusive_ptr<SHAMapItem const> const&
|
||||
peekItem(uint256 const& id) const;
|
||||
std::shared_ptr<SHAMapItem const> const&
|
||||
boost::intrusive_ptr<SHAMapItem const> const&
|
||||
peekItem(uint256 const& id, SHAMapHash& hash) const;
|
||||
|
||||
// traverse functions
|
||||
@@ -253,8 +257,8 @@ public:
|
||||
*/
|
||||
void
|
||||
visitLeaves(
|
||||
std::function<void(std::shared_ptr<SHAMapItem const> const&)> const&)
|
||||
const;
|
||||
std::function<
|
||||
void(boost::intrusive_ptr<SHAMapItem const> const&)> const&) const;
|
||||
|
||||
// comparison/sync functions
|
||||
|
||||
@@ -361,8 +365,8 @@ private:
|
||||
using SharedPtrNodeStack =
|
||||
std::stack<std::pair<std::shared_ptr<SHAMapTreeNode>, SHAMapNodeID>>;
|
||||
using DeltaRef = std::pair<
|
||||
std::shared_ptr<SHAMapItem const> const&,
|
||||
std::shared_ptr<SHAMapItem const> const&>;
|
||||
boost::intrusive_ptr<SHAMapItem const>,
|
||||
boost::intrusive_ptr<SHAMapItem const>>;
|
||||
|
||||
// tree node cache operations
|
||||
std::shared_ptr<SHAMapTreeNode>
|
||||
@@ -475,7 +479,7 @@ private:
|
||||
descendNoStore(std::shared_ptr<SHAMapInnerNode> const&, int branch) const;
|
||||
|
||||
/** If there is only one leaf below this node, get its contents */
|
||||
std::shared_ptr<SHAMapItem const> const&
|
||||
boost::intrusive_ptr<SHAMapItem const> const&
|
||||
onlyBelow(SHAMapTreeNode*) const;
|
||||
|
||||
bool
|
||||
@@ -490,7 +494,7 @@ private:
|
||||
bool
|
||||
walkBranch(
|
||||
SHAMapTreeNode* node,
|
||||
std::shared_ptr<SHAMapItem const> const& otherMapItem,
|
||||
boost::intrusive_ptr<SHAMapItem const> const& otherMapItem,
|
||||
bool isFirstMap,
|
||||
Delta& differences,
|
||||
int& maxCount) const;
|
||||
|
||||
@@ -36,7 +36,7 @@ class SHAMapAccountStateLeafNode final
|
||||
{
|
||||
public:
|
||||
SHAMapAccountStateLeafNode(
|
||||
std::shared_ptr<SHAMapItem const> item,
|
||||
boost::intrusive_ptr<SHAMapItem const> item,
|
||||
std::uint32_t cowid)
|
||||
: SHAMapLeafNode(std::move(item), cowid)
|
||||
{
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
}
|
||||
|
||||
SHAMapAccountStateLeafNode(
|
||||
std::shared_ptr<SHAMapItem const> item,
|
||||
boost::intrusive_ptr<SHAMapItem const> item,
|
||||
std::uint32_t cowid,
|
||||
SHAMapHash const& hash)
|
||||
: SHAMapLeafNode(std::move(item), cowid, hash)
|
||||
|
||||
@@ -20,26 +20,68 @@
|
||||
#ifndef RIPPLE_SHAMAP_SHAMAPITEM_H_INCLUDED
|
||||
#define RIPPLE_SHAMAP_SHAMAPITEM_H_INCLUDED
|
||||
|
||||
#include <ripple/basics/Buffer.h>
|
||||
#include <ripple/basics/ByteUtilities.h>
|
||||
#include <ripple/basics/CountedObject.h>
|
||||
#include <ripple/basics/SlabAllocator.h>
|
||||
#include <ripple/basics/Slice.h>
|
||||
#include <ripple/basics/base_uint.h>
|
||||
#include <boost/smart_ptr/intrusive_ptr.hpp>
|
||||
#include <cassert>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// an item stored in a SHAMap
|
||||
class SHAMapItem : public CountedObject<SHAMapItem>
|
||||
{
|
||||
// These are used to support boost::intrusive_ptr reference counting
|
||||
// These functions are used internally by boost::intrusive_ptr to handle
|
||||
// lifetime management.
|
||||
friend void
|
||||
intrusive_ptr_add_ref(SHAMapItem const* x);
|
||||
|
||||
friend void
|
||||
intrusive_ptr_release(SHAMapItem const* x);
|
||||
|
||||
// This is the interface for creating new instances of this class.
|
||||
friend boost::intrusive_ptr<SHAMapItem>
|
||||
make_shamapitem(uint256 const& tag, Slice data);
|
||||
|
||||
private:
|
||||
uint256 tag_;
|
||||
Buffer data_;
|
||||
uint256 const tag_;
|
||||
|
||||
// We use std::uint32_t to minimize the size; there's no SHAMapItem whose
|
||||
// size exceeds 4GB and there won't ever be (famous last words?), so this
|
||||
// is safe.
|
||||
std::uint32_t const size_;
|
||||
|
||||
// This is the reference count used to support boost::intrusive_ptr
|
||||
mutable std::atomic<std::uint32_t> refcount_ = 1;
|
||||
|
||||
// Because of the unusual way in which SHAMapItem objects are constructed
|
||||
// the only way to properly create one is to first allocate enough memory
|
||||
// so we limit this constructor to codepaths that do this right and limit
|
||||
// arbitrary construction.
|
||||
SHAMapItem(uint256 const& tag, Slice data)
|
||||
: tag_(tag), size_(static_cast<std::uint32_t>(data.size()))
|
||||
{
|
||||
std::memcpy(
|
||||
reinterpret_cast<std::uint8_t*>(this) + sizeof(*this),
|
||||
data.data(),
|
||||
data.size());
|
||||
}
|
||||
|
||||
public:
|
||||
SHAMapItem() = delete;
|
||||
|
||||
SHAMapItem(uint256 const& tag, Slice data) : tag_(tag), data_(data)
|
||||
{
|
||||
}
|
||||
SHAMapItem(SHAMapItem const& other) = delete;
|
||||
|
||||
SHAMapItem&
|
||||
operator=(SHAMapItem const& other) = delete;
|
||||
|
||||
SHAMapItem(SHAMapItem&& other) = delete;
|
||||
|
||||
SHAMapItem&
|
||||
operator=(SHAMapItem&&) = delete;
|
||||
|
||||
uint256 const&
|
||||
key() const
|
||||
@@ -47,25 +89,101 @@ public:
|
||||
return tag_;
|
||||
}
|
||||
|
||||
Slice
|
||||
slice() const
|
||||
{
|
||||
return static_cast<Slice>(data_);
|
||||
}
|
||||
|
||||
std::size_t
|
||||
size() const
|
||||
{
|
||||
return data_.size();
|
||||
return size_;
|
||||
}
|
||||
|
||||
void const*
|
||||
data() const
|
||||
{
|
||||
return data_.data();
|
||||
return reinterpret_cast<std::uint8_t const*>(this) + sizeof(*this);
|
||||
}
|
||||
|
||||
Slice
|
||||
slice() const
|
||||
{
|
||||
return {data(), size()};
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
// clang-format off
|
||||
// The slab cutoffs and the number of megabytes per allocation are customized
|
||||
// based on the number of objects of each size we expect to need at any point
|
||||
// in time and with an eye to minimize the number of slack bytes in a block.
|
||||
inline SlabAllocatorSet<SHAMapItem> slabber({
|
||||
{ 128, megabytes(std::size_t(60)) },
|
||||
{ 192, megabytes(std::size_t(46)) },
|
||||
{ 272, megabytes(std::size_t(60)) },
|
||||
{ 384, megabytes(std::size_t(56)) },
|
||||
{ 564, megabytes(std::size_t(40)) },
|
||||
{ 772, megabytes(std::size_t(46)) },
|
||||
{ 1052, megabytes(std::size_t(60)) },
|
||||
});
|
||||
// clang-format on
|
||||
|
||||
} // namespace detail
|
||||
|
||||
inline void
|
||||
intrusive_ptr_add_ref(SHAMapItem const* x)
|
||||
{
|
||||
// This can only happen if someone releases the last reference to the
|
||||
// item while we were trying to increment the refcount.
|
||||
if (x->refcount_++ == 0)
|
||||
LogicError("SHAMapItem: the reference count is 0!");
|
||||
}
|
||||
|
||||
inline void
|
||||
intrusive_ptr_release(SHAMapItem const* x)
|
||||
{
|
||||
if (--x->refcount_ == 0)
|
||||
{
|
||||
auto p = reinterpret_cast<std::uint8_t const*>(x);
|
||||
|
||||
// The SHAMapItem constuctor isn't trivial (because the destructor
|
||||
// for CountedObject isn't) so we can't avoid calling it here, but
|
||||
// plan for a future where we might not need to.
|
||||
if constexpr (!std::is_trivially_destructible_v<SHAMapItem>)
|
||||
std::destroy_at(x);
|
||||
|
||||
// If the slabber doens't claim this pointer, it was allocated
|
||||
// manually, so we free it manually.
|
||||
if (!detail::slabber.deallocate(const_cast<std::uint8_t*>(p)))
|
||||
delete[] p;
|
||||
}
|
||||
}
|
||||
|
||||
inline boost::intrusive_ptr<SHAMapItem>
|
||||
make_shamapitem(uint256 const& tag, Slice data)
|
||||
{
|
||||
assert(data.size() <= megabytes<std::size_t>(16));
|
||||
|
||||
std::uint8_t* raw = detail::slabber.allocate(data.size());
|
||||
|
||||
// If we can't grab memory from the slab allocators, we fall back to
|
||||
// the standard library and try to grab a precisely-sized memory block:
|
||||
if (raw == nullptr)
|
||||
raw = new std::uint8_t[sizeof(SHAMapItem) + data.size()];
|
||||
|
||||
// We do not increment the reference count here on purpose: the
|
||||
// constructor of SHAMapItem explicitly sets it to 1. We use the fact
|
||||
// that the refcount can never be zero before incrementing as an
|
||||
// invariant.
|
||||
return {new (raw) SHAMapItem{tag, data}, false};
|
||||
}
|
||||
|
||||
static_assert(alignof(SHAMapItem) != 40);
|
||||
static_assert(alignof(SHAMapItem) == 8 || alignof(SHAMapItem) == 4);
|
||||
|
||||
inline boost::intrusive_ptr<SHAMapItem>
|
||||
make_shamapitem(SHAMapItem const& other)
|
||||
{
|
||||
return make_shamapitem(other.key(), other.slice());
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,11 +32,14 @@ namespace ripple {
|
||||
class SHAMapLeafNode : public SHAMapTreeNode
|
||||
{
|
||||
protected:
|
||||
std::shared_ptr<SHAMapItem const> item_;
|
||||
boost::intrusive_ptr<SHAMapItem const> item_;
|
||||
|
||||
SHAMapLeafNode(std::shared_ptr<SHAMapItem const> item, std::uint32_t cowid);
|
||||
SHAMapLeafNode(
|
||||
std::shared_ptr<SHAMapItem const> item,
|
||||
boost::intrusive_ptr<SHAMapItem const> item,
|
||||
std::uint32_t cowid);
|
||||
|
||||
SHAMapLeafNode(
|
||||
boost::intrusive_ptr<SHAMapItem const> item,
|
||||
std::uint32_t cowid,
|
||||
SHAMapHash const& hash);
|
||||
|
||||
@@ -61,7 +64,7 @@ public:
|
||||
invariants(bool is_root = false) const final override;
|
||||
|
||||
public:
|
||||
std::shared_ptr<SHAMapItem const> const&
|
||||
boost::intrusive_ptr<SHAMapItem const> const&
|
||||
peekItem() const;
|
||||
|
||||
/** Set the item that this node points to and update the node's hash.
|
||||
@@ -71,7 +74,7 @@ public:
|
||||
hash was unchanged); true otherwise.
|
||||
*/
|
||||
bool
|
||||
setItem(std::shared_ptr<SHAMapItem const> i);
|
||||
setItem(boost::intrusive_ptr<SHAMapItem const> i);
|
||||
|
||||
std::string
|
||||
getString(SHAMapNodeID const&) const final override;
|
||||
|
||||
@@ -35,7 +35,7 @@ class SHAMapTxLeafNode final : public SHAMapLeafNode,
|
||||
{
|
||||
public:
|
||||
SHAMapTxLeafNode(
|
||||
std::shared_ptr<SHAMapItem const> item,
|
||||
boost::intrusive_ptr<SHAMapItem const> item,
|
||||
std::uint32_t cowid)
|
||||
: SHAMapLeafNode(std::move(item), cowid)
|
||||
{
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
}
|
||||
|
||||
SHAMapTxLeafNode(
|
||||
std::shared_ptr<SHAMapItem const> item,
|
||||
boost::intrusive_ptr<SHAMapItem const> item,
|
||||
std::uint32_t cowid,
|
||||
SHAMapHash const& hash)
|
||||
: SHAMapLeafNode(std::move(item), cowid, hash)
|
||||
|
||||
@@ -36,7 +36,7 @@ class SHAMapTxPlusMetaLeafNode final
|
||||
{
|
||||
public:
|
||||
SHAMapTxPlusMetaLeafNode(
|
||||
std::shared_ptr<SHAMapItem const> item,
|
||||
boost::intrusive_ptr<SHAMapItem const> item,
|
||||
std::uint32_t cowid)
|
||||
: SHAMapLeafNode(std::move(item), cowid)
|
||||
{
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
}
|
||||
|
||||
SHAMapTxPlusMetaLeafNode(
|
||||
std::shared_ptr<SHAMapItem const> item,
|
||||
boost::intrusive_ptr<SHAMapItem const> item,
|
||||
std::uint32_t cowid,
|
||||
SHAMapHash const& hash)
|
||||
: SHAMapLeafNode(std::move(item), cowid, hash)
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace ripple {
|
||||
[[nodiscard]] std::shared_ptr<SHAMapLeafNode>
|
||||
makeTypedLeaf(
|
||||
SHAMapNodeType type,
|
||||
std::shared_ptr<SHAMapItem const> item,
|
||||
boost::intrusive_ptr<SHAMapItem const> item,
|
||||
std::uint32_t owner)
|
||||
{
|
||||
if (type == SHAMapNodeType::tnTRANSACTION_NM)
|
||||
@@ -512,9 +512,9 @@ SHAMap::firstBelow(
|
||||
|
||||
return belowHelper(node, stack, branch, {init, cmp, incr});
|
||||
}
|
||||
static const std::shared_ptr<SHAMapItem const> no_item;
|
||||
static const boost::intrusive_ptr<SHAMapItem const> no_item;
|
||||
|
||||
std::shared_ptr<SHAMapItem const> const&
|
||||
boost::intrusive_ptr<SHAMapItem const> const&
|
||||
SHAMap::onlyBelow(SHAMapTreeNode* node) const
|
||||
{
|
||||
// If there is only one item below this node, return it
|
||||
@@ -593,7 +593,7 @@ SHAMap::peekNextItem(uint256 const& id, SharedPtrNodeStack& stack) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<SHAMapItem const> const&
|
||||
boost::intrusive_ptr<SHAMapItem const> const&
|
||||
SHAMap::peekItem(uint256 const& id) const
|
||||
{
|
||||
SHAMapLeafNode* leaf = findKey(id);
|
||||
@@ -604,7 +604,7 @@ SHAMap::peekItem(uint256 const& id) const
|
||||
return leaf->peekItem();
|
||||
}
|
||||
|
||||
std::shared_ptr<SHAMapItem const> const&
|
||||
boost::intrusive_ptr<SHAMapItem const> const&
|
||||
SHAMap::peekItem(uint256 const& id, SHAMapHash& hash) const
|
||||
{
|
||||
SHAMapLeafNode* leaf = findKey(id);
|
||||
@@ -776,7 +776,9 @@ SHAMap::delItem(uint256 const& id)
|
||||
}
|
||||
|
||||
bool
|
||||
SHAMap::addGiveItem(SHAMapNodeType type, std::shared_ptr<SHAMapItem const> item)
|
||||
SHAMap::addGiveItem(
|
||||
SHAMapNodeType type,
|
||||
boost::intrusive_ptr<SHAMapItem const> item)
|
||||
{
|
||||
assert(state_ != SHAMapState::Immutable);
|
||||
assert(type != SHAMapNodeType::tnINNER);
|
||||
@@ -813,7 +815,7 @@ SHAMap::addGiveItem(SHAMapNodeType type, std::shared_ptr<SHAMapItem const> item)
|
||||
// this is a leaf node that has to be made an inner node holding two
|
||||
// items
|
||||
auto leaf = std::static_pointer_cast<SHAMapLeafNode>(node);
|
||||
std::shared_ptr<SHAMapItem const> otherItem = leaf->peekItem();
|
||||
auto otherItem = leaf->peekItem();
|
||||
assert(otherItem && (tag != otherItem->key()));
|
||||
|
||||
node = std::make_shared<SHAMapInnerNode>(node->cowid());
|
||||
@@ -844,9 +846,11 @@ SHAMap::addGiveItem(SHAMapNodeType type, std::shared_ptr<SHAMapItem const> item)
|
||||
}
|
||||
|
||||
bool
|
||||
SHAMap::addItem(SHAMapNodeType type, SHAMapItem&& i)
|
||||
SHAMap::addItem(
|
||||
SHAMapNodeType type,
|
||||
boost::intrusive_ptr<SHAMapItem const> item)
|
||||
{
|
||||
return addGiveItem(type, std::make_shared<SHAMapItem const>(std::move(i)));
|
||||
return addGiveItem(type, std::move(item));
|
||||
}
|
||||
|
||||
SHAMapHash
|
||||
@@ -864,7 +868,7 @@ SHAMap::getHash() const
|
||||
bool
|
||||
SHAMap::updateGiveItem(
|
||||
SHAMapNodeType type,
|
||||
std::shared_ptr<SHAMapItem const> item)
|
||||
boost::intrusive_ptr<SHAMapItem const> item)
|
||||
{
|
||||
// can't change the tag but can change the hash
|
||||
uint256 tag = item->key();
|
||||
@@ -889,13 +893,13 @@ SHAMap::updateGiveItem(
|
||||
|
||||
if (node->getType() != type)
|
||||
{
|
||||
JLOG(journal_.fatal()) << "SHAMap::setItem: cross-type change!";
|
||||
JLOG(journal_.fatal()) << "SHAMap::updateGiveItem: cross-type change!";
|
||||
return false;
|
||||
}
|
||||
|
||||
node = unshareNode(std::move(node), nodeID);
|
||||
|
||||
if (node->setItem(std::move(item)))
|
||||
if (node->setItem(item))
|
||||
dirtyUp(stack, tag, node);
|
||||
|
||||
return true;
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace ripple {
|
||||
bool
|
||||
SHAMap::walkBranch(
|
||||
SHAMapTreeNode* node,
|
||||
std::shared_ptr<SHAMapItem const> const& otherMapItem,
|
||||
boost::intrusive_ptr<SHAMapItem const> const& otherMapItem,
|
||||
bool isFirstMap,
|
||||
Delta& differences,
|
||||
int& maxCount) const
|
||||
@@ -71,13 +71,11 @@ SHAMap::walkBranch(
|
||||
{
|
||||
// unmatched
|
||||
if (isFirstMap)
|
||||
differences.insert(std::make_pair(
|
||||
item->key(),
|
||||
DeltaRef(item, std::shared_ptr<SHAMapItem const>())));
|
||||
differences.insert(
|
||||
std::make_pair(item->key(), DeltaRef(item, nullptr)));
|
||||
else
|
||||
differences.insert(std::make_pair(
|
||||
item->key(),
|
||||
DeltaRef(std::shared_ptr<SHAMapItem const>(), item)));
|
||||
differences.insert(
|
||||
std::make_pair(item->key(), DeltaRef(nullptr, item)));
|
||||
|
||||
if (--maxCount <= 0)
|
||||
return false;
|
||||
@@ -110,12 +108,10 @@ SHAMap::walkBranch(
|
||||
// otherMapItem was unmatched, must add
|
||||
if (isFirstMap) // this is first map, so other item is from second
|
||||
differences.insert(std::make_pair(
|
||||
otherMapItem->key(),
|
||||
DeltaRef(std::shared_ptr<SHAMapItem const>(), otherMapItem)));
|
||||
otherMapItem->key(), DeltaRef(nullptr, otherMapItem)));
|
||||
else
|
||||
differences.insert(std::make_pair(
|
||||
otherMapItem->key(),
|
||||
DeltaRef(otherMapItem, std::shared_ptr<SHAMapItem const>())));
|
||||
otherMapItem->key(), DeltaRef(otherMapItem, nullptr)));
|
||||
|
||||
if (--maxCount <= 0)
|
||||
return false;
|
||||
@@ -173,17 +169,13 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const
|
||||
{
|
||||
differences.insert(std::make_pair(
|
||||
ours->peekItem()->key(),
|
||||
DeltaRef(
|
||||
ours->peekItem(),
|
||||
std::shared_ptr<SHAMapItem const>())));
|
||||
DeltaRef(ours->peekItem(), nullptr)));
|
||||
if (--maxCount <= 0)
|
||||
return false;
|
||||
|
||||
differences.insert(std::make_pair(
|
||||
other->peekItem()->key(),
|
||||
DeltaRef(
|
||||
std::shared_ptr<SHAMapItem const>(),
|
||||
other->peekItem())));
|
||||
DeltaRef(nullptr, other->peekItem())));
|
||||
if (--maxCount <= 0)
|
||||
return false;
|
||||
}
|
||||
@@ -216,11 +208,7 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const
|
||||
// We have a branch, the other tree does not
|
||||
SHAMapTreeNode* iNode = descendThrow(ours, i);
|
||||
if (!walkBranch(
|
||||
iNode,
|
||||
std::shared_ptr<SHAMapItem const>(),
|
||||
true,
|
||||
differences,
|
||||
maxCount))
|
||||
iNode, nullptr, true, differences, maxCount))
|
||||
return false;
|
||||
}
|
||||
else if (ours->isEmptyBranch(i))
|
||||
@@ -228,11 +216,7 @@ SHAMap::compare(SHAMap const& otherMap, Delta& differences, int maxCount) const
|
||||
// The other tree has a branch, we do not
|
||||
SHAMapTreeNode* iNode = otherMap.descendThrow(other, i);
|
||||
if (!otherMap.walkBranch(
|
||||
iNode,
|
||||
std::shared_ptr<SHAMapItem const>(),
|
||||
false,
|
||||
differences,
|
||||
maxCount))
|
||||
iNode, nullptr, false, differences, maxCount))
|
||||
return false;
|
||||
}
|
||||
else // The two trees have different non-empty branches
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
namespace ripple {
|
||||
|
||||
SHAMapLeafNode::SHAMapLeafNode(
|
||||
std::shared_ptr<SHAMapItem const> item,
|
||||
boost::intrusive_ptr<SHAMapItem const> item,
|
||||
std::uint32_t cowid)
|
||||
: SHAMapTreeNode(cowid), item_(std::move(item))
|
||||
{
|
||||
@@ -32,7 +32,7 @@ SHAMapLeafNode::SHAMapLeafNode(
|
||||
}
|
||||
|
||||
SHAMapLeafNode::SHAMapLeafNode(
|
||||
std::shared_ptr<SHAMapItem const> item,
|
||||
boost::intrusive_ptr<SHAMapItem const> item,
|
||||
std::uint32_t cowid,
|
||||
SHAMapHash const& hash)
|
||||
: SHAMapTreeNode(cowid, hash), item_(std::move(item))
|
||||
@@ -40,17 +40,17 @@ SHAMapLeafNode::SHAMapLeafNode(
|
||||
assert(item_->size() >= 12);
|
||||
}
|
||||
|
||||
std::shared_ptr<SHAMapItem const> const&
|
||||
boost::intrusive_ptr<SHAMapItem const> const&
|
||||
SHAMapLeafNode::peekItem() const
|
||||
{
|
||||
return item_;
|
||||
}
|
||||
|
||||
bool
|
||||
SHAMapLeafNode::setItem(std::shared_ptr<SHAMapItem const> i)
|
||||
SHAMapLeafNode::setItem(boost::intrusive_ptr<SHAMapItem const> item)
|
||||
{
|
||||
assert(cowid_ != 0);
|
||||
item_ = std::move(i);
|
||||
item_ = std::move(item);
|
||||
|
||||
auto const oldHash = hash_;
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ namespace ripple {
|
||||
|
||||
void
|
||||
SHAMap::visitLeaves(
|
||||
std::function<void(std::shared_ptr<SHAMapItem const> const& item)> const&
|
||||
leafFunction) const
|
||||
std::function<void(boost::intrusive_ptr<SHAMapItem const> const&
|
||||
item)> const& leafFunction) const
|
||||
{
|
||||
visitNodes([&leafFunction](SHAMapTreeNode& node) {
|
||||
if (!node.isInner())
|
||||
|
||||
@@ -42,8 +42,8 @@ SHAMapTreeNode::makeTransaction(
|
||||
SHAMapHash const& hash,
|
||||
bool hashValid)
|
||||
{
|
||||
auto item = std::make_shared<SHAMapItem const>(
|
||||
sha512Half(HashPrefix::transactionID, data), data);
|
||||
auto item =
|
||||
make_shamapitem(sha512Half(HashPrefix::transactionID, data), data);
|
||||
|
||||
if (hashValid)
|
||||
return std::make_shared<SHAMapTxLeafNode>(std::move(item), 0, hash);
|
||||
@@ -71,7 +71,7 @@ SHAMapTreeNode::makeTransactionWithMeta(
|
||||
|
||||
s.chop(tag.bytes);
|
||||
|
||||
auto item = std::make_shared<SHAMapItem const>(tag, s.slice());
|
||||
auto item = make_shamapitem(tag, s.slice());
|
||||
|
||||
if (hashValid)
|
||||
return std::make_shared<SHAMapTxPlusMetaLeafNode>(
|
||||
@@ -103,7 +103,7 @@ SHAMapTreeNode::makeAccountState(
|
||||
if (tag.isZero())
|
||||
Throw<std::runtime_error>("Invalid AS node");
|
||||
|
||||
auto item = std::make_shared<SHAMapItem const>(tag, s.slice());
|
||||
auto item = make_shamapitem(tag, s.slice());
|
||||
|
||||
if (hashValid)
|
||||
return std::make_shared<SHAMapAccountStateLeafNode>(
|
||||
|
||||
@@ -1292,8 +1292,8 @@ struct LedgerReplayer_test : public beast::unit_test::suite
|
||||
|
||||
std::uint8_t payload[55] = {
|
||||
0x6A, 0x09, 0xE6, 0x67, 0xF3, 0xBC, 0xC9, 0x08, 0xB2};
|
||||
auto item = std::make_shared<SHAMapItem>(
|
||||
uint256(12345), Slice(payload, sizeof(payload)));
|
||||
auto item =
|
||||
make_shamapitem(uint256(12345), Slice(payload, sizeof(payload)));
|
||||
skipList->processData(l->seq(), item);
|
||||
|
||||
std::vector<TaskStatus> deltaStatuses;
|
||||
|
||||
@@ -78,7 +78,7 @@ class ByzantineFailureSim_test : public beast::unit_test::suite
|
||||
// All peers see some TX 0
|
||||
for (Peer* peer : network)
|
||||
{
|
||||
peer->submit(Tx(0));
|
||||
peer->submit(Tx{0});
|
||||
// Peers 0,1,2,6 will close the next ledger differently by injecting
|
||||
// a non-consensus approved transaciton
|
||||
if (byzantineNodes.contains(peer))
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace ripple {
|
||||
namespace test {
|
||||
@@ -40,6 +41,11 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_same_v<T, Tx>>>
|
||||
Tx(T const* t) : id_{t->id_}
|
||||
{
|
||||
}
|
||||
|
||||
ID
|
||||
id() const
|
||||
{
|
||||
|
||||
@@ -348,7 +348,7 @@ struct LedgerHistoryHelper
|
||||
assert(seen.emplace(s.back()).second);
|
||||
|
||||
Ledger const& parent = (*this)[s.substr(0, s.size() - 1)];
|
||||
return ledgers.emplace(s, oracle.accept(parent, ++nextTx))
|
||||
return ledgers.emplace(s, oracle.accept(parent, Tx{++nextTx}))
|
||||
.first->second;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -85,13 +85,13 @@ public:
|
||||
beast::Journal mJournal;
|
||||
};
|
||||
|
||||
std::shared_ptr<Item>
|
||||
boost::intrusive_ptr<Item>
|
||||
make_random_item(beast::xor_shift_engine& r)
|
||||
{
|
||||
Serializer s;
|
||||
for (int d = 0; d < 3; ++d)
|
||||
s.add32(ripple::rand_int<std::uint32_t>(r));
|
||||
return std::make_shared<Item>(s.getSHA512Half(), s.slice());
|
||||
return make_shamapitem(s.getSHA512Half(), s.slice());
|
||||
}
|
||||
|
||||
void
|
||||
@@ -99,9 +99,8 @@ public:
|
||||
{
|
||||
while (n--)
|
||||
{
|
||||
std::shared_ptr<SHAMapItem> item(make_random_item(r));
|
||||
auto const result(
|
||||
t.addItem(SHAMapNodeType::tnACCOUNT_STATE, std::move(*item)));
|
||||
auto const result(t.addItem(
|
||||
SHAMapNodeType::tnACCOUNT_STATE, make_random_item(r)));
|
||||
assert(result);
|
||||
(void)result;
|
||||
}
|
||||
|
||||
@@ -34,14 +34,14 @@ class SHAMapSync_test : public beast::unit_test::suite
|
||||
public:
|
||||
beast::xor_shift_engine eng_;
|
||||
|
||||
std::shared_ptr<SHAMapItem>
|
||||
boost::intrusive_ptr<SHAMapItem>
|
||||
makeRandomAS()
|
||||
{
|
||||
Serializer s;
|
||||
|
||||
for (int d = 0; d < 3; ++d)
|
||||
s.add32(rand_int<std::uint32_t>(eng_));
|
||||
return std::make_shared<SHAMapItem>(s.getSHA512Half(), s.slice());
|
||||
return make_shamapitem(s.getSHA512Half(), s.slice());
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -55,10 +55,10 @@ public:
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
std::shared_ptr<SHAMapItem> item = makeRandomAS();
|
||||
auto item = makeRandomAS();
|
||||
items.push_back(item->key());
|
||||
|
||||
if (!map.addItem(SHAMapNodeType::tnACCOUNT_STATE, std::move(*item)))
|
||||
if (!map.addItem(SHAMapNodeType::tnACCOUNT_STATE, item))
|
||||
{
|
||||
log << "Unable to add item to map\n";
|
||||
return false;
|
||||
@@ -97,8 +97,7 @@ public:
|
||||
int items = 10000;
|
||||
for (int i = 0; i < items; ++i)
|
||||
{
|
||||
source.addItem(
|
||||
SHAMapNodeType::tnACCOUNT_STATE, std::move(*makeRandomAS()));
|
||||
source.addItem(SHAMapNodeType::tnACCOUNT_STATE, makeRandomAS());
|
||||
if (i % 100 == 0)
|
||||
source.invariants();
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#include <ripple/beast/unit_test.h>
|
||||
#include <ripple/beast/utility/Journal.h>
|
||||
#include <ripple/shamap/SHAMap.h>
|
||||
#include <algorithm>
|
||||
#include <test/shamap/common.h>
|
||||
#include <test/unit_test/SuiteJournal.h>
|
||||
|
||||
@@ -45,10 +44,7 @@ static_assert(std::is_move_assignable<SHAMap::const_iterator>{}, "");
|
||||
|
||||
static_assert(std::is_nothrow_destructible<SHAMapItem>{}, "");
|
||||
static_assert(!std::is_default_constructible<SHAMapItem>{}, "");
|
||||
static_assert(std::is_copy_constructible<SHAMapItem>{}, "");
|
||||
static_assert(std::is_copy_assignable<SHAMapItem>{}, "");
|
||||
static_assert(std::is_move_constructible<SHAMapItem>{}, "");
|
||||
static_assert(std::is_move_assignable<SHAMapItem>{}, "");
|
||||
static_assert(!std::is_copy_constructible<SHAMapItem>{}, "");
|
||||
|
||||
static_assert(std::is_nothrow_destructible<SHAMapNodeID>{}, "");
|
||||
static_assert(std::is_default_constructible<SHAMapNodeID>{}, "");
|
||||
@@ -155,37 +151,43 @@ public:
|
||||
if (!backed)
|
||||
sMap.setUnbacked();
|
||||
|
||||
SHAMapItem i1(h1, IntToVUC(1)), i2(h2, IntToVUC(2)),
|
||||
i3(h3, IntToVUC(3)), i4(h4, IntToVUC(4)), i5(h5, IntToVUC(5));
|
||||
auto i1 = make_shamapitem(h1, IntToVUC(1));
|
||||
auto i2 = make_shamapitem(h2, IntToVUC(2));
|
||||
auto i3 = make_shamapitem(h3, IntToVUC(3));
|
||||
auto i4 = make_shamapitem(h4, IntToVUC(4));
|
||||
auto i5 = make_shamapitem(h5, IntToVUC(5));
|
||||
|
||||
unexpected(
|
||||
!sMap.addItem(SHAMapNodeType::tnTRANSACTION_NM, SHAMapItem{i2}),
|
||||
!sMap.addItem(
|
||||
SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(*i2)),
|
||||
"no add");
|
||||
sMap.invariants();
|
||||
unexpected(
|
||||
!sMap.addItem(SHAMapNodeType::tnTRANSACTION_NM, SHAMapItem{i1}),
|
||||
!sMap.addItem(
|
||||
SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(*i1)),
|
||||
"no add");
|
||||
sMap.invariants();
|
||||
|
||||
auto i = sMap.begin();
|
||||
auto e = sMap.end();
|
||||
unexpected(i == e || (*i != i1), "bad traverse");
|
||||
unexpected(i == e || (*i != *i1), "bad traverse");
|
||||
++i;
|
||||
unexpected(i == e || (*i != i2), "bad traverse");
|
||||
unexpected(i == e || (*i != *i2), "bad traverse");
|
||||
++i;
|
||||
unexpected(i != e, "bad traverse");
|
||||
sMap.addItem(SHAMapNodeType::tnTRANSACTION_NM, SHAMapItem{i4});
|
||||
sMap.addItem(SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(*i4));
|
||||
sMap.invariants();
|
||||
sMap.delItem(i2.key());
|
||||
sMap.delItem(i2->key());
|
||||
sMap.invariants();
|
||||
sMap.addItem(SHAMapNodeType::tnTRANSACTION_NM, SHAMapItem{i3});
|
||||
sMap.addItem(SHAMapNodeType::tnTRANSACTION_NM, make_shamapitem(*i3));
|
||||
sMap.invariants();
|
||||
i = sMap.begin();
|
||||
e = sMap.end();
|
||||
unexpected(i == e || (*i != i1), "bad traverse");
|
||||
unexpected(i == e || (*i != *i1), "bad traverse");
|
||||
++i;
|
||||
unexpected(i == e || (*i != i3), "bad traverse");
|
||||
unexpected(i == e || (*i != *i3), "bad traverse");
|
||||
++i;
|
||||
unexpected(i == e || (*i != i4), "bad traverse");
|
||||
unexpected(i == e || (*i != *i4), "bad traverse");
|
||||
++i;
|
||||
unexpected(i != e, "bad traverse");
|
||||
|
||||
@@ -265,9 +267,9 @@ public:
|
||||
BEAST_EXPECT(map.getHash() == beast::zero);
|
||||
for (int k = 0; k < keys.size(); ++k)
|
||||
{
|
||||
SHAMapItem item(keys[k], IntToVUC(k));
|
||||
BEAST_EXPECT(map.addItem(
|
||||
SHAMapNodeType::tnTRANSACTION_NM, std::move(item)));
|
||||
SHAMapNodeType::tnTRANSACTION_NM,
|
||||
make_shamapitem(keys[k], IntToVUC(k))));
|
||||
BEAST_EXPECT(map.getHash().as_uint256() == hashes[k]);
|
||||
map.invariants();
|
||||
}
|
||||
@@ -312,7 +314,7 @@ public:
|
||||
{
|
||||
map.addItem(
|
||||
SHAMapNodeType::tnTRANSACTION_NM,
|
||||
SHAMapItem{k, IntToVUC(0)});
|
||||
make_shamapitem(k, IntToVUC(0)));
|
||||
map.invariants();
|
||||
}
|
||||
|
||||
@@ -346,7 +348,7 @@ class SHAMapPathProof_test : public beast::unit_test::suite
|
||||
uint256 k(c);
|
||||
map.addItem(
|
||||
SHAMapNodeType::tnACCOUNT_STATE,
|
||||
SHAMapItem{k, Slice{k.data(), k.size()}});
|
||||
make_shamapitem(k, Slice{k.data(), k.size()}));
|
||||
map.invariants();
|
||||
|
||||
auto root = map.getHash().as_uint256();
|
||||
|
||||
Reference in New Issue
Block a user