1#include <xrpl/basics/contract.h>
2#include <xrpl/beast/utility/instrumentation.h>
3#include <xrpl/ledger/ApplyView.h>
4#include <xrpl/protocol/Protocol.h>
21 newRoot->setFieldH256(sfRootIndex, directory.
key);
26 newRoot->setFieldV256(sfIndexes, v);
44 LogicError(
"Directory chain: root back-pointer broken.");
49 auto indexes = node->getFieldV256(sfIndexes);
78 if (pos != indexes.
end() && key == *pos)
84 node->setFieldV256(sfIndexes, indexes);
119 node->setFieldU64(sfIndexNext, page);
122 next->setFieldU64(sfIndexPrevious, page);
130 node->setFieldH256(sfRootIndex, directory.
key);
131 node->setFieldV256(sfIndexes, indexes);
136 node->setFieldU64(sfIndexPrevious, page - 1);
139 "ripple::directory::insertPage",
140 "nextPage has default value");
169 auto [page, node, indexes] =
176 *
this, node, page, preserveOrder, indexes, key);
180 *
this, page, node, 0,
root, key, directory, describe);
186 auto node =
peek(directory);
192 if (directory.
type != ltDIR_NODE ||
193 node->getFieldH256(sfRootIndex) != directory.
key)
196 UNREACHABLE(
"ripple::ApplyView::emptyDirDelete : invalid node type");
202 if (!node->getFieldV256(sfIndexes).empty())
206 auto prevPage = node->getFieldU64(sfIndexPrevious);
207 auto nextPage = node->getFieldU64(sfIndexNext);
209 if (nextPage == rootPage && prevPage != rootPage)
210 LogicError(
"Directory chain: fwd link broken");
212 if (prevPage == rootPage && nextPage != rootPage)
213 LogicError(
"Directory chain: rev link broken");
217 if (nextPage == prevPage && nextPage != rootPage)
223 LogicError(
"Directory chain: fwd link broken.");
227 if (!last->getFieldV256(sfIndexes).empty())
232 node->setFieldU64(sfIndexNext, rootPage);
233 node->setFieldU64(sfIndexPrevious, rootPage);
246 if (nextPage == rootPage && prevPage == rootPage)
267 auto entries = node->getFieldV256(sfIndexes);
269 auto it =
std::find(entries.begin(), entries.end(), key);
271 if (entries.end() == it)
277 node->setFieldV256(sfIndexes, entries);
280 if (!entries.empty())
287 auto prevPage = node->getFieldU64(sfIndexPrevious);
288 auto nextPage = node->getFieldU64(sfIndexNext);
294 if (page == rootPage)
296 if (nextPage == page && prevPage != page)
298 LogicError(
"Directory chain: fwd link broken");
302 if (prevPage == page && nextPage != page)
304 LogicError(
"Directory chain: rev link broken");
311 if (nextPage == prevPage && nextPage != page)
316 LogicError(
"Directory chain: fwd link broken.");
320 if (last->getFieldV256(sfIndexes).empty())
324 node->setFieldU64(sfIndexNext, page);
325 node->setFieldU64(sfIndexPrevious, page);
342 if (nextPage == page && prevPage == page)
349 if (nextPage == page)
350 LogicError(
"Directory chain: fwd link broken");
352 if (prevPage == page)
353 LogicError(
"Directory chain: rev link broken");
361 LogicError(
"Directory chain: fwd link broken.");
363 prev->setFieldU64(sfIndexNext, nextPage);
368 LogicError(
"Directory chain: rev link broken.");
370 next->setFieldU64(sfIndexPrevious, prevPage);
378 if (nextPage != rootPage && next->getFieldU64(sfIndexNext) == rootPage &&
379 next->getFieldV256(sfIndexes).empty())
386 prev->setFieldU64(sfIndexNext, rootPage);
393 LogicError(
"Directory chain: root link broken.");
396 root->setFieldU64(sfIndexPrevious, prevPage);
404 if (!keepRoot && nextPage == rootPage && prevPage == rootPage)
406 if (prev->getFieldV256(sfIndexes).empty())
427 for (
auto const& item : page->getFieldV256(sfIndexes))
430 pi = (*page)[~sfIndexNext];
Writeable view to a ledger, for applying a transaction.
bool dirDelete(Keylet const &directory, std::function< void(uint256 const &)> const &)
Remove the specified directory, invoking the callback for every node.
virtual void update(std::shared_ptr< SLE > const &sle)=0
Indicate changes to a peeked SLE.
bool dirRemove(Keylet const &directory, std::uint64_t page, uint256 const &key, bool keepRoot)
Remove an entry from a directory.
bool emptyDirDelete(Keylet const &directory)
Remove the specified directory, if it is empty.
std::optional< std::uint64_t > dirAdd(bool preserveOrder, Keylet const &directory, uint256 const &key, std::function< void(std::shared_ptr< SLE > const &)> const &describe)
Add an entry to a directory using the specified insert strategy.
virtual void insert(std::shared_ptr< SLE > const &sle)=0
Insert a new state SLE.
virtual std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
virtual void erase(std::shared_ptr< SLE > const &sle)=0
Remove a peeked SLE.
virtual Rules const & rules() const =0
Returns the tx processing rules.
bool enabled(uint256 const &feature) const
Returns true if a feature is enabled.
std::vector< uint256 >::iterator begin()
void push_back(uint256 const &v)
std::vector< uint256 >::iterator insert(std::vector< uint256 >::const_iterator pos, uint256 const &value)
std::vector< uint256 >::iterator end()
std::uint64_t createRoot(ApplyView &view, Keylet const &directory, uint256 const &key, std::function< void(std::shared_ptr< SLE > const &)> const &describe)
Helper functions for managing low-level directory operations.
auto findPreviousPage(ApplyView &view, Keylet const &directory, SLE::ref start)
std::uint64_t insertKey(ApplyView &view, SLE::ref node, std::uint64_t page, bool preserveOrder, STVector256 &indexes, uint256 const &key)
std::optional< std::uint64_t > insertPage(ApplyView &view, std::uint64_t page, SLE::pointer node, std::uint64_t nextPage, SLE::ref next, uint256 const &key, Keylet const &directory, std::function< void(std::shared_ptr< SLE > const &)> const &describe)
Keylet page(uint256 const &root, std::uint64_t index=0) noexcept
A page in a directory.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
std::uint64_t constexpr dirNodeMaxPages
The maximum number of pages allowed in a directory.
std::size_t constexpr dirNodeMaxEntries
The maximum number of entries per directory page.
Number root(Number f, unsigned d)
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
A pair of SHAMap key and LedgerEntryType.