Files
rippled/include/xrpl/shamap/SHAMapInnerNode.h
Bart 1d42c4f6de refactor: Remove unnecessary copyright notices already covered by LICENSE.md (#5929)
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.
2025-11-04 08:33:42 +00:00

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