20#include <xrpld/ledger/ApplyView.h>
22#include <xrpl/basics/contract.h>
23#include <xrpl/beast/utility/instrumentation.h>
24#include <xrpl/protocol/Protocol.h>
40 root = std::make_shared<SLE>(directory);
41 root->setFieldH256(sfRootIndex, directory.
key);
46 root->setFieldV256(sfIndexes, v);
60 LogicError(
"Directory chain: root back-pointer broken.");
63 auto indexes = node->getFieldV256(sfIndexes);
70 if (
std::find(indexes.begin(), indexes.end(), key) != indexes.end())
73 indexes.push_back(key);
80 std::sort(indexes.begin(), indexes.end());
84 if (pos != indexes.end() && key == *pos)
87 indexes.insert(pos, key);
90 node->setFieldV256(sfIndexes, indexes);
101 node->setFieldU64(sfIndexNext, page);
104 root->setFieldU64(sfIndexPrevious, page);
109 indexes.push_back(key);
111 node = std::make_shared<SLE>(
keylet::page(directory, page));
112 node->setFieldH256(sfRootIndex, directory.
key);
113 node->setFieldV256(sfIndexes, indexes);
118 node->setFieldU64(sfIndexPrevious, page - 1);
128 auto node =
peek(directory);
134 if (directory.
type != ltDIR_NODE ||
135 node->getFieldH256(sfRootIndex) != directory.
key)
137 UNREACHABLE(
"ripple::ApplyView::emptyDirDelete : invalid node type");
142 if (!node->getFieldV256(sfIndexes).empty())
146 auto prevPage = node->getFieldU64(sfIndexPrevious);
147 auto nextPage = node->getFieldU64(sfIndexNext);
149 if (nextPage == rootPage && prevPage != rootPage)
150 LogicError(
"Directory chain: fwd link broken");
152 if (prevPage == rootPage && nextPage != rootPage)
153 LogicError(
"Directory chain: rev link broken");
157 if (nextPage == prevPage && nextPage != rootPage)
162 LogicError(
"Directory chain: fwd link broken.");
164 if (!last->getFieldV256(sfIndexes).empty())
169 node->setFieldU64(sfIndexNext, rootPage);
170 node->setFieldU64(sfIndexPrevious, rootPage);
183 if (nextPage == rootPage && prevPage == rootPage)
204 auto entries = node->getFieldV256(sfIndexes);
206 auto it =
std::find(entries.begin(), entries.end(), key);
208 if (entries.end() == it)
214 node->setFieldV256(sfIndexes, entries);
217 if (!entries.empty())
224 auto prevPage = node->getFieldU64(sfIndexPrevious);
225 auto nextPage = node->getFieldU64(sfIndexNext);
231 if (page == rootPage)
233 if (nextPage == page && prevPage != page)
234 LogicError(
"Directory chain: fwd link broken");
236 if (prevPage == page && nextPage != page)
237 LogicError(
"Directory chain: rev link broken");
242 if (nextPage == prevPage && nextPage != page)
246 LogicError(
"Directory chain: fwd link broken.");
248 if (last->getFieldV256(sfIndexes).empty())
252 node->setFieldU64(sfIndexNext, page);
253 node->setFieldU64(sfIndexPrevious, page);
270 if (nextPage == page && prevPage == page)
277 if (nextPage == page)
278 LogicError(
"Directory chain: fwd link broken");
280 if (prevPage == page)
281 LogicError(
"Directory chain: rev link broken");
289 LogicError(
"Directory chain: fwd link broken.");
291 prev->setFieldU64(sfIndexNext, nextPage);
296 LogicError(
"Directory chain: rev link broken.");
298 next->setFieldU64(sfIndexPrevious, prevPage);
306 if (nextPage != rootPage && next->getFieldU64(sfIndexNext) == rootPage &&
307 next->getFieldV256(sfIndexes).empty())
314 prev->setFieldU64(sfIndexNext, rootPage);
320 LogicError(
"Directory chain: root link broken.");
321 root->setFieldU64(sfIndexPrevious, prevPage);
329 if (!keepRoot && nextPage == rootPage && prevPage == rootPage)
331 if (prev->getFieldV256(sfIndexes).empty())
352 for (
auto const& item : page->getFieldV256(sfIndexes))
355 pi = (*page)[~sfIndexNext];
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.
void push_back(uint256 const &v)
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.