mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Per XLS-0095, we are taking steps to rename ripple(d) to xrpl(d). This change specifically removes all copyright notices referencing Ripple, XRPLF, and certain affiliated contributors upon mutual agreement, so the notice in the LICENSE.md file applies throughout. Copyright notices referencing external contributions remain as-is. Duplicate verbiage is also removed.
207 lines
4.9 KiB
C++
207 lines
4.9 KiB
C++
#ifndef XRPL_SHAMAP_SHAMAPINNERNODE_H_INCLUDED
|
|
#define XRPL_SHAMAP_SHAMAPINNERNODE_H_INCLUDED
|
|
|
|
#include <xrpl/basics/IntrusivePointer.h>
|
|
#include <xrpl/shamap/SHAMapNodeID.h>
|
|
#include <xrpl/shamap/detail/TaggedPointer.h>
|
|
|
|
#include <atomic>
|
|
#include <cstdint>
|
|
#include <optional>
|
|
#include <string>
|
|
|
|
namespace ripple {
|
|
|
|
class SHAMapInnerNode final : public SHAMapTreeNode,
|
|
public CountedObject<SHAMapInnerNode>
|
|
{
|
|
public:
|
|
/** Each inner node has 16 children (the 'radix tree' part of the map) */
|
|
static inline constexpr unsigned int branchFactor = 16;
|
|
|
|
private:
|
|
/** Opaque type that contains the `hashes` array (array of type
|
|
`SHAMapHash`) and the `children` array (array of type
|
|
`intr_ptr::SharedPtr<SHAMapInnerNode>`).
|
|
*/
|
|
TaggedPointer hashesAndChildren_;
|
|
|
|
std::uint32_t fullBelowGen_ = 0;
|
|
std::uint16_t isBranch_ = 0;
|
|
|
|
/** A bitlock for the children of this node, with one bit per child */
|
|
mutable std::atomic<std::uint16_t> lock_ = 0;
|
|
|
|
/** Convert arrays stored in `hashesAndChildren_` so they can store the
|
|
requested number of children.
|
|
|
|
@param toAllocate allocate space for at least this number of children
|
|
(must be <= branchFactor)
|
|
|
|
@note the arrays may allocate more than the requested value in
|
|
`toAllocate`. This is due to the implementation of TagPointer, which
|
|
only supports allocating arrays of 4 different sizes.
|
|
*/
|
|
void
|
|
resizeChildArrays(std::uint8_t toAllocate);
|
|
|
|
/** Get the child's index inside the `hashes` or `children` array (stored in
|
|
`hashesAndChildren_`.
|
|
|
|
These arrays may or may not be sparse). The optional will be empty is an
|
|
empty branch is requested and the arrays are sparse.
|
|
|
|
@param i index of the requested child
|
|
*/
|
|
std::optional<int>
|
|
getChildIndex(int i) const;
|
|
|
|
/** Call the `f` callback for all 16 (branchFactor) branches - even if
|
|
the branch is empty.
|
|
|
|
@param f a one parameter callback function. The parameter is the
|
|
child's hash.
|
|
*/
|
|
template <class F>
|
|
void
|
|
iterChildren(F&& f) const;
|
|
|
|
/** Call the `f` callback for all non-empty branches.
|
|
|
|
@param f a two parameter callback function. The first parameter is
|
|
the branch number, the second parameter is the index into the array.
|
|
For dense formats these are the same, for sparse they may be
|
|
different.
|
|
*/
|
|
template <class F>
|
|
void
|
|
iterNonEmptyChildIndexes(F&& f) const;
|
|
|
|
public:
|
|
explicit SHAMapInnerNode(
|
|
std::uint32_t cowid,
|
|
std::uint8_t numAllocatedChildren = 2);
|
|
|
|
SHAMapInnerNode(SHAMapInnerNode const&) = delete;
|
|
SHAMapInnerNode&
|
|
operator=(SHAMapInnerNode const&) = delete;
|
|
~SHAMapInnerNode();
|
|
|
|
// Needed to support intrusive weak pointers
|
|
void
|
|
partialDestructor() override;
|
|
|
|
intr_ptr::SharedPtr<SHAMapTreeNode>
|
|
clone(std::uint32_t cowid) const override;
|
|
|
|
SHAMapNodeType
|
|
getType() const override
|
|
{
|
|
return SHAMapNodeType::tnINNER;
|
|
}
|
|
|
|
bool
|
|
isLeaf() const override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
isInner() const override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
isEmpty() const;
|
|
|
|
bool
|
|
isEmptyBranch(int m) const;
|
|
|
|
int
|
|
getBranchCount() const;
|
|
|
|
SHAMapHash const&
|
|
getChildHash(int m) const;
|
|
|
|
void
|
|
setChild(int m, intr_ptr::SharedPtr<SHAMapTreeNode> child);
|
|
|
|
void
|
|
shareChild(int m, intr_ptr::SharedPtr<SHAMapTreeNode> const& child);
|
|
|
|
SHAMapTreeNode*
|
|
getChildPointer(int branch);
|
|
|
|
intr_ptr::SharedPtr<SHAMapTreeNode>
|
|
getChild(int branch);
|
|
|
|
intr_ptr::SharedPtr<SHAMapTreeNode>
|
|
canonicalizeChild(int branch, intr_ptr::SharedPtr<SHAMapTreeNode> node);
|
|
|
|
// sync functions
|
|
bool
|
|
isFullBelow(std::uint32_t generation) const;
|
|
|
|
void
|
|
setFullBelowGen(std::uint32_t gen);
|
|
|
|
void
|
|
updateHash() override;
|
|
|
|
/** Recalculate the hash of all children and this node. */
|
|
void
|
|
updateHashDeep();
|
|
|
|
void
|
|
serializeForWire(Serializer&) const override;
|
|
|
|
void
|
|
serializeWithPrefix(Serializer&) const override;
|
|
|
|
std::string
|
|
getString(SHAMapNodeID const&) const override;
|
|
|
|
void
|
|
invariants(bool is_root = false) const override;
|
|
|
|
static intr_ptr::SharedPtr<SHAMapTreeNode>
|
|
makeFullInner(Slice data, SHAMapHash const& hash, bool hashValid);
|
|
|
|
static intr_ptr::SharedPtr<SHAMapTreeNode>
|
|
makeCompressedInner(Slice data);
|
|
};
|
|
|
|
inline bool
|
|
SHAMapInnerNode::isEmpty() const
|
|
{
|
|
return isBranch_ == 0;
|
|
}
|
|
|
|
inline bool
|
|
SHAMapInnerNode::isEmptyBranch(int m) const
|
|
{
|
|
return (isBranch_ & (1 << m)) == 0;
|
|
}
|
|
|
|
inline int
|
|
SHAMapInnerNode::getBranchCount() const
|
|
{
|
|
return popcnt16(isBranch_);
|
|
}
|
|
|
|
inline bool
|
|
SHAMapInnerNode::isFullBelow(std::uint32_t generation) const
|
|
{
|
|
return fullBelowGen_ == generation;
|
|
}
|
|
|
|
inline void
|
|
SHAMapInnerNode::setFullBelowGen(std::uint32_t gen)
|
|
{
|
|
fullBelowGen_ = gen;
|
|
}
|
|
|
|
} // namespace ripple
|
|
#endif
|