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);
138 !nextPage,
"xrpl::directory::insertPage",
"nextPage has default value");
167 auto [page, node, indexes] =
174 *
this, node, page, preserveOrder, indexes, key);
178 *
this, page, node, 0,
root, key, directory, describe);
184 auto node =
peek(directory);
190 if (directory.
type != ltDIR_NODE ||
191 node->getFieldH256(sfRootIndex) != directory.
key)
194 UNREACHABLE(
"xrpl::ApplyView::emptyDirDelete : invalid node type");
200 if (!node->getFieldV256(sfIndexes).empty())
204 auto prevPage = node->getFieldU64(sfIndexPrevious);
205 auto nextPage = node->getFieldU64(sfIndexNext);
207 if (nextPage == rootPage && prevPage != rootPage)
208 LogicError(
"Directory chain: fwd link broken");
210 if (prevPage == rootPage && nextPage != rootPage)
211 LogicError(
"Directory chain: rev link broken");
215 if (nextPage == prevPage && nextPage != rootPage)
221 LogicError(
"Directory chain: fwd link broken.");
225 if (!last->getFieldV256(sfIndexes).empty())
230 node->setFieldU64(sfIndexNext, rootPage);
231 node->setFieldU64(sfIndexPrevious, rootPage);
244 if (nextPage == rootPage && prevPage == rootPage)
265 auto entries = node->getFieldV256(sfIndexes);
267 auto it =
std::find(entries.begin(), entries.end(), key);
269 if (entries.end() == it)
275 node->setFieldV256(sfIndexes, entries);
278 if (!entries.empty())
285 auto prevPage = node->getFieldU64(sfIndexPrevious);
286 auto nextPage = node->getFieldU64(sfIndexNext);
292 if (page == rootPage)
294 if (nextPage == page && prevPage != page)
296 LogicError(
"Directory chain: fwd link broken");
300 if (prevPage == page && nextPage != page)
302 LogicError(
"Directory chain: rev link broken");
309 if (nextPage == prevPage && nextPage != page)
314 LogicError(
"Directory chain: fwd link broken.");
318 if (last->getFieldV256(sfIndexes).empty())
322 node->setFieldU64(sfIndexNext, page);
323 node->setFieldU64(sfIndexPrevious, page);
340 if (nextPage == page && prevPage == page)
347 if (nextPage == page)
348 LogicError(
"Directory chain: fwd link broken");
350 if (prevPage == page)
351 LogicError(
"Directory chain: rev link broken");
359 LogicError(
"Directory chain: fwd link broken.");
361 prev->setFieldU64(sfIndexNext, nextPage);
366 LogicError(
"Directory chain: rev link broken.");
368 next->setFieldU64(sfIndexPrevious, prevPage);
376 if (nextPage != rootPage && next->getFieldU64(sfIndexNext) == rootPage &&
377 next->getFieldV256(sfIndexes).empty())
384 prev->setFieldU64(sfIndexNext, rootPage);
391 LogicError(
"Directory chain: root link broken.");
394 root->setFieldU64(sfIndexPrevious, prevPage);
402 if (!keepRoot && nextPage == rootPage && prevPage == rootPage)
404 if (prev->getFieldV256(sfIndexes).empty())
425 for (
auto const& item : page->getFieldV256(sfIndexes))
428 pi = (*page)[~sfIndexNext];
Writeable view to a ledger, for applying a transaction.
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.
virtual void erase(std::shared_ptr< SLE > const &sle)=0
Remove a peeked SLE.
bool dirDelete(Keylet const &directory, std::function< void(uint256 const &)> const &)
Remove the specified directory, invoking the callback for every node.
virtual void insert(std::shared_ptr< SLE > const &sle)=0
Insert a new state SLE.
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 std::shared_ptr< SLE > peek(Keylet const &k)=0
Prepare to modify the SLE associated with key.
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 insert(std::vector< uint256 >::const_iterator pos, uint256 const &value)
std::vector< uint256 >::iterator begin()
void push_back(uint256 const &v)
std::vector< uint256 >::iterator end()
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)
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.
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.
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
std::size_t constexpr dirNodeMaxEntries
The maximum number of entries per directory page.
Number root(Number f, unsigned d)
std::uint64_t constexpr dirNodeMaxPages
The maximum number of pages allowed in a directory.
A pair of SHAMap key and LedgerEntryType.