-
Notifications
You must be signed in to change notification settings - Fork 9.1k
HDDS-2199 In SCMNodeManager dnsToUuidMap cannot track multiple DNs on the same host #1551
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
Closed
Closed
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
a488e30
Changed SCMNodeManager.getNodeByAddress to returns a list of nodes on…
58026eb
Fixed style issue
7e99565
Make addEntryTodnsToUuidMap synchronized
b7c5d2a
Added findbugs ignore annotation
07df552
Moved HashSet to a Concurrent version and ensured the MockNodeManager…
7fe483a
Fixed further style issues
768ae91
Refactored the the change in sortDatanodes() to make it simpler and r…
dc1e393
Fixed another style issue (unused import) after removing the random l…
4421b5a
Simplify logic used to map Client host string to a DatanodeDetails ob…
5d97878
Remove unused import
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
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 am trying to understand why this big block is not just as simple:
It seems to be a logic to find a datanode which is on the same host as the client. I am not sure if we need this tricky randomization (or choosing the first possible datanodes): if client is null, we don't need sort (handled by the sort method below), if there are multiple datanodes on the same client we can choose the first one as in the topology sort it doesn't matter which one is chosen.
But please fix me if I am wrong.
Uh oh!
There was an error while loading. Please reload this page.
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 am not certain how this sortDatanodes() call is used. Is it on the read path or write path? I was assuming it was on the read path, but write path may be different if all the cluster DNs are passed into the method - then you would always get a match.
A list of DNs (UUIDs) are passed into the method, and then we retrieve a list of DatanodeDetails running on the client machine. The client machine can then be set to one of those DatanodeDetails, but it is not guaranteed that the first in the list will match on of the UUIDs passed into the method.
Eg this is passed in:
DN0, DN5, DN10, DN15
On the client machine is:
DN1, DN6, DN10 and DN16
So only DN10 is a match with one that is passed it. If we just picked the first one (DN1) it would look like there is no DN on the client machine and then when the list and client machine are passed into sortByDistanceCost() at line 355, it would not give the expected result.
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.
Looking at where sortDatanodes() is used, it seems to be from the OM when performing lookup file or lookup key. So that suggests it is only used in the read path, and hence at most 3 DNs should be passed in along with one client address.
The code could be simplified a little, but I think we do need to filter the list of returned nodes down to only the nodes it cares about due to what I said in the comment above.
However, thinking about this some more, I think we can avoid the random selection. In the case where there is only 1 DN per host, the DN matching the client would always be sorted first, so we don't really need to randomize the first node returned if all nodes are on the same host. I will refactor this and see how it looks then.
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.
Not sure If I understand well. I think there are two parameters
The task is to sort the list of datanode UUIDs, with prioritizing the client machine.
First the client hostname is converted to UUID. This is the part which is replaced by this complex block. If it could not been converted it can be null. After that the topology logic sorts the list.
sortByDistanceCost
.IMHO this functionality can be implemented my 4 lines of code, but fix me If I am wrong.
Uh oh!
There was an error while loading. Please reload this page.
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.
When there are multiple DNs on a given host (host1), you pass in the client as host1.
We do a lookup for host1 and we get DN UUIDs (actually DatanodeDetails objects) DN1, DN6, DN10 and DN16 which are on this host.
The pipeline passed in is DN4, DN5 and DN10. Ie only one of these hosts is on the client machine, but the client machine has other nodes not involved in this pipeline.
If it was just the hostname/IP used for later comparison your logic would be fine. However ...
The matched client DatanodeDetails object is passed to sortByDistanceCost() later in the same method, which calls this for each pipeline node:
Where reader is the client Node object we found.
In get distance by cost, the first few lines do this:
Ie, it both parameters are non-null and are the same object returns a distance of zero, otherwise it goes through more logic to calculate a distance.
Going back to the example above - your logic would return DN1 which would not give a zero distance cost in getDistanceByCost() when compared with any of the pipeline nodes.
My more complex logic would return DN10 which would return a zero cost when compared with pipeline node DN10, as they are the same object.
So after a rather long example the summary is that if the cost calculation was based on hostname your logic would be fine, but as it compares the actual node objects I think we need the more complex logic, unfortunately! I have not followed the rest of the logic in getDistanceByCost to see if a cost of zero would fall out in the end, but I suspect it will be some small non-zero value as both nodes will be at the same level.
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.
Reflecting on this issue some more, I think the simplified logic you have suggested is better and the problem is better solved in getDistanceByCost - rather than comparing just the node objects are the same, we should test if they are the same hostname and if so treat that as a zero distance match too.
Unfortunately, as that method takes Node objects rather than DatanodeDetails, this is not trivial to do.
The code path under question here is only relevant for clusters with more than one datanode on the same host, and by definition that is a non-production setup. The only consequence of the change you have suggested over my original code, is that the client may get the wrong 'cost to reach a datanode' sometimes on test clusters - nothing will fail, so the impact of this issue is very low.
Therefore if you are happy, I think we should commit the latest version (which has your simplified logic) and create a followup Jira to look into fixing getDistanceByCost somehow.