Skip to content

Commit fe90816

Browse files
committed
Refactor ApplyView::dirAdd to give access to low-level operations
- Takes a page from #5362, which may turn out to be useful!
1 parent 48cc344 commit fe90816

File tree

2 files changed

+141
-48
lines changed

2 files changed

+141
-48
lines changed

src/xrpld/ledger/ApplyView.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,45 @@ class ApplyView : public ReadView
383383
emptyDirDelete(Keylet const& directory);
384384
};
385385

386+
namespace directory {
387+
/** Helper functions for managing low-level directory operations.
388+
These are not part of the ApplyView interface.
389+
390+
Don't use them unless you really, really know what you're doing.
391+
Instead use dirAdd, dirInsert, etc.
392+
*/
393+
394+
std::uint64_t
395+
createRoot(
396+
ApplyView& view,
397+
Keylet const& directory,
398+
uint256 const& key,
399+
std::function<void(std::shared_ptr<SLE> const&)> const& describe);
400+
401+
auto
402+
findPreviousPage(ApplyView& view, Keylet const& directory, SLE::ref start);
403+
404+
std::uint64_t
405+
insertKey(
406+
ApplyView& view,
407+
SLE::ref node,
408+
std::uint64_t page,
409+
bool preserveOrder,
410+
STVector256& indexes,
411+
uint256 const& key);
412+
413+
std::optional<std::uint64_t>
414+
insertPage(
415+
ApplyView& view,
416+
std::uint64_t page,
417+
SLE::pointer node,
418+
std::uint64_t nextPage,
419+
SLE::ref next,
420+
uint256 const& key,
421+
Keylet const& directory,
422+
std::function<void(std::shared_ptr<SLE> const&)> const& describe);
423+
424+
} // namespace directory
386425
} // namespace ripple
387426

388427
#endif

src/xrpld/ledger/detail/ApplyView.cpp

Lines changed: 102 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -25,87 +25,108 @@
2525

2626
namespace ripple {
2727

28-
std::optional<std::uint64_t>
29-
ApplyView::dirAdd(
30-
bool preserveOrder,
28+
namespace directory {
29+
30+
std::uint64_t
31+
createRoot(
32+
ApplyView& view,
3133
Keylet const& directory,
3234
uint256 const& key,
3335
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
3436
{
35-
auto root = peek(directory);
36-
37-
if (!root)
38-
{
39-
// No root, make it.
40-
root = std::make_shared<SLE>(directory);
41-
root->setFieldH256(sfRootIndex, directory.key);
42-
describe(root);
37+
auto newRoot = std::make_shared<SLE>(directory);
38+
newRoot->setFieldH256(sfRootIndex, directory.key);
39+
describe(newRoot);
4340

44-
STVector256 v;
45-
v.push_back(key);
46-
root->setFieldV256(sfIndexes, v);
41+
STVector256 v;
42+
v.push_back(key);
43+
newRoot->setFieldV256(sfIndexes, v);
4744

48-
insert(root);
49-
return std::uint64_t{0};
50-
}
45+
view.insert(newRoot);
46+
return std::uint64_t{0};
47+
}
5148

52-
std::uint64_t page = root->getFieldU64(sfIndexPrevious);
49+
auto
50+
findPreviousPage(ApplyView& view, Keylet const& directory, SLE::ref start)
51+
{
52+
std::uint64_t page = start->getFieldU64(sfIndexPrevious);
5353

54-
auto node = root;
54+
auto node = start;
5555

5656
if (page)
5757
{
58-
node = peek(keylet::page(directory, page));
58+
node = view.peek(keylet::page(directory, page));
5959
if (!node)
6060
LogicError("Directory chain: root back-pointer broken.");
6161
}
6262

6363
auto indexes = node->getFieldV256(sfIndexes);
64+
return std::make_tuple(page, node, indexes);
65+
}
6466

65-
// If there's space, we use it:
66-
if (indexes.size() < dirNodeMaxEntries)
67+
std::uint64_t
68+
insertKey(
69+
ApplyView& view,
70+
SLE::ref node,
71+
std::uint64_t page,
72+
bool preserveOrder,
73+
STVector256& indexes,
74+
uint256 const& key)
75+
{
76+
if (preserveOrder)
6777
{
68-
if (preserveOrder)
69-
{
70-
if (std::find(indexes.begin(), indexes.end(), key) != indexes.end())
71-
LogicError("dirInsert: double insertion");
78+
if (std::find(indexes.begin(), indexes.end(), key) != indexes.end())
79+
LogicError("dirInsert: double insertion");
7280

73-
indexes.push_back(key);
74-
}
75-
else
76-
{
77-
// We can't be sure if this page is already sorted because
78-
// it may be a legacy page we haven't yet touched. Take
79-
// the time to sort it.
80-
std::sort(indexes.begin(), indexes.end());
81+
indexes.push_back(key);
82+
}
83+
else
84+
{
85+
// We can't be sure if this page is already sorted because
86+
// it may be a legacy page we haven't yet touched. Take
87+
// the time to sort it.
88+
std::sort(indexes.begin(), indexes.end());
8189

82-
auto pos = std::lower_bound(indexes.begin(), indexes.end(), key);
90+
auto pos = std::lower_bound(indexes.begin(), indexes.end(), key);
8391

84-
if (pos != indexes.end() && key == *pos)
85-
LogicError("dirInsert: double insertion");
92+
if (pos != indexes.end() && key == *pos)
93+
LogicError("dirInsert: double insertion");
8694

87-
indexes.insert(pos, key);
88-
}
89-
90-
node->setFieldV256(sfIndexes, indexes);
91-
update(node);
92-
return page;
95+
indexes.insert(pos, key);
9396
}
9497

98+
node->setFieldV256(sfIndexes, indexes);
99+
view.update(node);
100+
return page;
101+
}
102+
103+
std::optional<std::uint64_t>
104+
insertPage(
105+
ApplyView& view,
106+
std::uint64_t page,
107+
SLE::pointer node,
108+
std::uint64_t nextPage,
109+
SLE::ref next,
110+
uint256 const& key,
111+
Keylet const& directory,
112+
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
113+
{
95114
// Check whether we're out of pages.
96115
if (++page >= dirNodeMaxPages)
116+
{
97117
return std::nullopt;
118+
}
98119

99120
// We are about to create a new node; we'll link it to
100121
// the chain first:
101122
node->setFieldU64(sfIndexNext, page);
102-
update(node);
123+
view.update(node);
103124

104-
root->setFieldU64(sfIndexPrevious, page);
105-
update(root);
125+
next->setFieldU64(sfIndexPrevious, page);
126+
view.update(next);
106127

107128
// Insert the new key:
108-
indexes.clear();
129+
STVector256 indexes;
109130
indexes.push_back(key);
110131

111132
node = std::make_shared<SLE>(keylet::page(directory, page));
@@ -116,12 +137,45 @@ ApplyView::dirAdd(
116137
// it's the default.
117138
if (page != 1)
118139
node->setFieldU64(sfIndexPrevious, page - 1);
140+
if (nextPage)
141+
node->setFieldU64(sfIndexNext, nextPage);
119142
describe(node);
120-
insert(node);
143+
view.insert(node);
121144

122145
return page;
123146
}
124147

148+
} // namespace directory
149+
150+
std::optional<std::uint64_t>
151+
ApplyView::dirAdd(
152+
bool preserveOrder,
153+
Keylet const& directory,
154+
uint256 const& key,
155+
std::function<void(std::shared_ptr<SLE> const&)> const& describe)
156+
{
157+
auto root = peek(directory);
158+
159+
if (!root)
160+
{
161+
// No root, make it.
162+
return directory::createRoot(*this, directory, key, describe);
163+
}
164+
165+
auto [page, node, indexes] =
166+
directory::findPreviousPage(*this, directory, root);
167+
168+
// If there's space, we use it:
169+
if (indexes.size() < dirNodeMaxEntries)
170+
{
171+
return directory::insertKey(
172+
*this, node, page, preserveOrder, indexes, key);
173+
}
174+
175+
return directory::insertPage(
176+
*this, page, node, 0, root, key, directory, describe);
177+
}
178+
125179
bool
126180
ApplyView::emptyDirDelete(Keylet const& directory)
127181
{

0 commit comments

Comments
 (0)