-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve directory insertion & deletion (RIPD-1353, RIPD-1488) #2165
Conversation
} | ||
|
||
// Check whether we're out of pages. | ||
if (++page == dirNodeMaxPages) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be ++page > dirNodeMaxPages
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, since pages are zero-based. But I guess making it >= dirNodeMaxPages
is a good idea anyways. There's no directory with that many pages, but using >=
will do the right thing if there were..
src/ripple/protocol/Protocol.h
Outdated
@@ -59,4 +62,4 @@ using TxSeq = std::uint32_t; | |||
|
|||
} // ripple | |||
|
|||
#endif | |||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing CR
Finally!
|
The non-unity builds are failing:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
//------------------------------------------------------------------------------ | ||
/* | ||
This file is part of rippled: https://github.com/ripple/rippled | ||
Copyright (c) 2012, 2013 Ripple Labs Inc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider updating the date ?
src/ripple/ledger/ApplyView.h
Outdated
|
||
@param directory the base of the directory | ||
@param key the entry to insert | ||
@param strictOrder keep entries in order of insertion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was slightly confused by the name of this parameter - "strict" could mean a number of things. Maybe "preserveOrder" is closer to the intent? Just a suggestion - I'm ok with name as is, since the doc here is clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is actually giving me heartburn. I dislike functions that take a bool
and implement two different kinds of behavior based on that. Very error prone.
I seriously considered having two functions. Something like this:
boost::optional<std::uint64_t>
ApplyView::dirInsertSorted (
Keylet const& directory,
uint256 const& key,
std::function<void (std::shared_ptr<SLE> const&)> describe)
{
// dirInsert is a private function:
return dirInsert (directory, key, describe,
[](STVector256& indexes, uint256 const& key)
{
// We can't be sure if this page is already sorted because
// it may be a legacy page we haven't yet touched. Take
// the time to sort it.
std::sort (indexes.begin(), indexes.end());
auto pos = std::lower_bound(indexes.begin(), indexes.end(), key);
if (pos != indexes.end() && key == *pos)
LogicError ("dirInsert: double insertion");
indexes.insert (pos, key);
});
}
boost::optional<std::uint64_t>
ApplyView::dirInsertUnsorted (
Keylet const& directory,
uint256 const& key,
std::function<void (std::shared_ptr<SLE> const&)> describe)
{
// dirInsert is a private function:
return dirInsert (directory, key, describe,
[](STVector256& indexes, uint256 const& key)
{
if (std::find(indexes.begin(), indexes.end(), key) != indexes.end())
LogicError ("dirInsert: double insertion");
indexes.push_back(key);
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this. Perhaps a better name for dirInsertUnsorted
would be dirAppend
?
Codecov Report
@@ Coverage Diff @@
## develop #2165 +/- ##
===========================================
- Coverage 69.48% 69.42% -0.07%
===========================================
Files 685 686 +1
Lines 50520 50644 +124
===========================================
+ Hits 35105 35159 +54
- Misses 15415 15485 +70
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some nits
Keylet const& directory, | ||
uint256 const& key, | ||
bool strictOrder, | ||
std::function<void (std::shared_ptr<SLE> const&)> describe) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
describe
should be passed by const&
Keylet const& directory, | ||
Keylet const& key, | ||
bool strictOrder, | ||
std::function<void (std::shared_ptr<SLE> const&)> describe) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
describe
should be passed by const&
src/ripple/protocol/STVector256.h
Outdated
std::vector<uint256>::iterator | ||
insert(std::vector<uint256>::const_iterator pos, uint256&& value) | ||
{ | ||
return mValue.insert(pos, value); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uint256
is not move friendly, so I don't think we need this function. However, if we do want to keep it, we should still std::move(value)
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather keep it, for when in case we make base_uint
move-friendly.
This commit introduces the "SortedDirectories" amendment, which addresses two distinct issues: First, it corrects a technical flaw that could, in some edge cases, prevent an empty intermediate page from being deleted. Second, it sorts directory entries within a page (other than order book page entries, which remain strictly FIFO). This makes insert operations deterministic, instead of pseudo-random and reliant on temporal ordering. Lastly, it removes the ability to perform a "soft delete" where the page number of the item to delete need not be known if the item is in the first 20 pages, and enforces a maximum limit to the number of pages that a directory can span.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unit tests are failing. I took a look at the first one, and it looks like a problem in the unit test, rather than this code, but those need to be resolved. You might consider asking the people who originally wrote the now failing tests to resolve the failures.
Keylet const& dir, | ||
uint256 const& uLedgerIndex, | ||
bool strictOrder, | ||
std::function<void (SLE::ref)> fDescriber, | ||
beast::Journal j) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should consider splitting dirAdd
into dirAppend
and dirInsert
as well. I don't like that the high-level interface still has the bool parameter, while the lower level one is actually cleaner. I'd have less objection if it were the other way around (i.e. a high level function then sets the correct flags to a lower level function).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two dirAdd
functions:
- The existing legacy, free function, which this PR deprecates and which will be removed after the amendment activates. I had to insert the
bool
parameter to it, temporarily, but the function is going away. - The new low-level
dirAdd
function (which isprivate
to the class) and accepts a lambda for the insertion strategy. Users only invokeApplyView::dirInsert
orApplyView::dirAppend
.
src/ripple/ledger/impl/ApplyView.cpp
Outdated
LogicError ("dirInsert: double insertion"); | ||
|
||
v.insert (pos, k); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the low level, private dirAdd should just have a bool (or better, an enum, but bool is fine), and we should just embed this code into the main low-level function. There isn't a need for dirAdd
to be as generic as it is. We really only need the two options. And inlining the code makes is easier to understand dirAdd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more quick note on this: If you want to keep the std::function<void(STVector256&, uint256 const&)> const& add
parameter on dirAdd
, consider making it a template instead of a std::function
. Rational: using std::function
incurs a virtual function call, and may require allocation (though since our lambdas don't have captures, unlikely in our cases). Since it's private, and only called from the cpp
, we can easily declare it in the header and define it in the cpp.
👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
In 0.80.0-b4 |
This commit introduces the
SortedDirectories
amendment, which addresses two distinct issues:First, it corrects a technical flaw that could, in some edge cases, prevent an empty intermediate page from being deleted.
Second, it sorts directory entries within a page (other than order book page entries, which remain strictly FIFO). This makes insert operations deterministic, instead of pseudo-random and reliant on temporal ordering.
Lastly, it removes the ability to perform a "soft delete" where the page number of the item to delete need not be known if the item is in the first 20 pages, and enforces a maximum limit to the number of pages that a directory can span.