-
Notifications
You must be signed in to change notification settings - Fork 588
HDDS-9638. [hsync] File recovery support in OM #5847
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
Conversation
fffceae to
f474013
Compare
|
There's a compilation error that needs attention. |
jojochuang
left a comment
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'm half way through the review.
| RecoverLeaseResponse recoverLeaseResponse = | ||
| handleError(submitRequest(omRequest)).getRecoverLeaseResponse(); | ||
| return recoverLeaseResponse.getResponse(); | ||
| ArrayList list = new ArrayList(); |
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.
ArrayList has no type parameter
| return recoverLeaseResponse.getResponse(); | ||
| ArrayList list = new ArrayList(); | ||
| list.add(OmKeyInfo.getFromProtobuf(recoverLeaseResponse.getKeyInfo())); | ||
| list.add(OmKeyInfo.getFromProtobuf(recoverLeaseResponse.getOpenKeyInfo())); |
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.
Looks like the second element is not used by callers.
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.
@jojochuang , openKeyInfo is return for client. There is one case, suppose a hsynced file, a new block is allocated to it, then client writes some data to this new block, and crashes before it calls hsync for data on this new block, then the openKeyInfo will have one more block than keyInfo. In this case, If we want to recover the last new block length, then we need the openKeyInfo info. If we only recover the last block that hsynced ever called, then keyInfo is enough. The question is, what's expectation from user? Does recovering the last hsynced block is user's expectation?
| Thread.sleep(1000); | ||
| } | ||
| // The lease should have been recovered. | ||
| assertTrue("File should be closed", fs.recoverLease(file)); |
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.
Does recoverLease() throw except if the file is already closed? If so, it would be a deviation from HDFS.
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.
Yes, the second call of recoverLease will fail if the first has succeeded, since the file is already committed so checks in OM side will fail. Should we keep the same behavior as HDFS? I remember @szetszwo has mentioned a case that if after a Hbase region server fails, two new Hbase region servers start on the server, if the second region server calls recoverLease and gets a successful result, then there could be two region servers started and running on the same server. Not sure if Hbase has other checks to prevent the second region server to start so that the two region servers running altogether will not happen.
| } | ||
|
|
||
| message RecoverLeaseResponse { | ||
| optional bool response = 1; |
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 is potentially incompatible. But given that the feature is disabled by default, I agree this is acceptable.
| return value != null ? value.getCacheValue() : null; | ||
| } | ||
|
|
||
| @NotNull |
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 is moved from OMKeyCommitRequest.
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 can move back. It's move in the first implementation edition where the key commit is called from OMRecoverLeaseRequest. Later I found the key commit in OMRecoverLeaseRequest missed to handle many thing, such as bucket quota check, bucket used bytes update, reallocated but not used block release. All these are already addressed in OMKeyCommitRequestWithFSO. So use OMKeyCommitRequestWithFSO to do the final key commit is a better way than commit in OMRecoverLeaseRequest. That's current edition.
ashishkumar50
left a comment
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.
@ChenSammi Thanks for the patch, Please find few comments inline.
| throws IOException, InterruptedException; | ||
|
|
||
| boolean recoverLease(String pathStr) throws IOException; | ||
| List<OmKeyInfo> recoverFilePrepare(String pathStr) throws IOException; |
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.
Do we need to get list here? I think only openKey info may be required 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.
openKeyInfo has all the allocated blocks. If the file has multiple preallocated blocks, we actually don't know how many blocks are actually used, because each block in openKeyInfo only has the allocated block length, doesn't have the real data length. And keyInfo will have real data length for each block, but keyInfo will not have preallocated by not used yet blocks info.
|
|
||
| message RecoverLeaseResponse { | ||
| optional bool response = 1; | ||
| optional KeyInfo keyInfo = 1; |
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.
keyInfo is required or just openKeyInfo would suffice 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.
Refer to one of above answer to Wei-Chiu's comment.
| if (isHSync) { | ||
| boolean isHSync = commitKeyRequest.hasHsync() && commitKeyRequest.getHsync(); | ||
| boolean isRecovery = commitKeyRequest.hasRecovery() && commitKeyRequest.getRecovery(); | ||
| boolean realCommit = (!isHSync) || (isHSync && isRecovery); |
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.
Can we decouple hsync and recovery. We can just use recovery flag to determine that request is for commit.
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.
The current design is we only recover hsynced file, so that's why check both hsync and recovery flag.
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 see it's changed now.
| parentId); | ||
| OMRequestTestUtils.addDirKeyToDirTable(true, omDirInfo, | ||
| volumeName, bucketName, txnID, omMetaMgr); | ||
| volumeName, bucketName, ++txnID, omMetaMgr); |
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.
Is this change(++txnID) required?
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.
From txn ID point of view, ID should be different for every update operation. Although here in the test, previous same ID doesn't cause any problem since it's not checked in the test. But if later, some new tests start to check the ID, then they will have problems.
| OzoneObj.ResourceType.class))) | ||
| .thenReturn("user"); | ||
| InetSocketAddress address = new InetSocketAddress("localhost", 10000); | ||
| when(ozoneManager.getOmRpcServerAddr()).thenReturn(address); |
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.
Above ACL and address usage seems to be in every new test method, may be we can move to init or other method and use.
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.
Actually not needed, removed them.
| private String doWork(OzoneManager ozoneManager, long transactionLogIndex) | ||
| throws IOException { | ||
|
|
||
| private RecoverLeaseResponse doWork(OzoneManager ozoneManager, |
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 better to have restriction on some time gap between recoverLease and latest hsync call. Or else here recoverLease can be called immediately after hsync call.
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.
Since the patch is quite big now, the support of soft and hard limit is not implemented in this patch. We can file new JIRA to do that.
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.
Yes makes sense.
| "Calls of isFileClosed()"), | ||
| INVOCATION_RECOVER_LEASE("op_recover_lease", | ||
| "Calls of recoverLease()"), | ||
| INVOCATION_COMMIT("op_commit", "Calls of commit()"), |
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 it be called INVOCATION_RECOVER_FILE instead?
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.
Right.
...-manager/src/main/java/org/apache/hadoop/ozone/om/request/key/OMKeyCommitRequestWithFSO.java
Show resolved
Hide resolved
|
@ChenSammi, Thanks for updating patch, overall patch LGTM. |
jojochuang
left a comment
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.
+1 let's merge and proceed.
| // Add to cache. | ||
| omMetadataManager.getOpenKeyTable(getBucketLayout()).addCacheEntry( | ||
| new CacheKey<>(dbOpenFileKey), CacheValue.get(transactionLogIndex, openKeyInfo)); |
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.
nit: we could use the cleaner form instead now that @szetszwo added it in HDDS-7969:
bd900ae#diff-ac3f28f30c26932cfbaf4270f5f0862b973b4e3e5b9b11ae78e725c306736fcdL324-L326
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.e.
| // Add to cache. | |
| omMetadataManager.getOpenKeyTable(getBucketLayout()).addCacheEntry( | |
| new CacheKey<>(dbOpenFileKey), CacheValue.get(transactionLogIndex, openKeyInfo)); | |
| // Add to cache. | |
| omMetadataManager.getOpenKeyTable(getBucketLayout()).addCacheEntry( | |
| dbOpenFileKey, openKeyInfo, transactionLogIndex); |
What changes were proposed in this pull request?
Implement file recovery support in OM.
What is the link to the Apache JIRA
https://issues.apache.org/jira/browse/HDDS-9638
How was this patch tested?
new unit tests and existing tests.