HDDS-4731. Fix compatibility issue caused by new enum DatanodeDetails.Port.Name.REPLICATION#1844
HDDS-4731. Fix compatibility issue caused by new enum DatanodeDetails.Port.Name.REPLICATION#1844arp7 merged 14 commits intoapache:masterfrom
Conversation
|
@GlenGeng |
|
We can help to do a upgrade test to verify whether this issue has been solved in the real environment. Please let me know when I can start the verification. |
Thanks @GlenGeng for the offer. Is it repeatable (ie. after the test can you restore prior state), or do we have only one shot? |
|
It is repeatable. Just setup an ozone cluster with your dev branch, and run a testdfsio with old jars upon it. |
Thanks, but I meant your test in real environment. I already added a test to reproduce the bug in CI. |
|
Thanks @adoroszlai. |
|
On second thought it seems necessary to detect at server-side whether client is old (supports only specific port types) or new (can handle unknown ports). Otherwise no new ports for client can be introduced. The current patch should be fine for the REPLICATION port, since it is for datanodes only. |
Yes, I have the same thoughts. Current patch makes the new port internal, which is fine. But even after this patch we can introduce new public ports only after Ozone 2.0 (but I prefer to not break compatibility even between Ozone 1.x client and Ozone 2.x servers.) |
|
@GlenGeng @Xushaohong can you please review, too? |
GlenGeng-awx
left a comment
There was a problem hiding this comment.
LGTM. Thanks for the fix.
| optional GetCommittedBlockLengthRequestProto getCommittedBlockLength = 22; | ||
|
|
||
| optional string encodedToken = 23; | ||
| optional uint32 version = 24; |
There was a problem hiding this comment.
better keep the style consistent. Up to you.
| optional string traceID = 2; | ||
|
|
||
| optional UserInfo userInfo = 3; | ||
| optional uint32 version = 4; |
There was a problem hiding this comment.
Will clientVersion be more straightforward than version in these protos, in case we might add other version into proto message ?
There was a problem hiding this comment.
They are the same.
xiaoyuyao
left a comment
There was a problem hiding this comment.
Thanks @adoroszlai for working on this. The patch looks good to me, especially I like the new forward/backward compatibility testes added. Just one minor suggestion added inline.
| } | ||
|
|
||
| public HddsProtos.DatanodeDetailsProto.Builder toProtoBuilder( | ||
| int clientVersion) { |
There was a problem hiding this comment.
Can we embed the version info inside the PORT Enum without passing clientVersion as parameter?
This way, we can make the the handling of the version specific deserialization easier for future changes.
There was a problem hiding this comment.
Thanks @xiaoyuyao for the review. I'm not sure I understand the proposal. Can you please clarify?
We can embed the minimum version required for handling each port in the enum constants (eg. 0 for existing ports and 1 for the new replication port). But don't we still need the client version to be able to decide whether to include it in the proto message or not?
There was a problem hiding this comment.
Yes. We still need the client version. But that can be a static helper without many interface changes to introduce extra parameter.
There was a problem hiding this comment.
We still need the client version. But that can be a static helper
This conversion must be done on the server-side, and server can have clients of various versions. How would a static helper work?
elek
left a comment
There was a problem hiding this comment.
+1 the concept looks good to me. Let's merge when others have no more concerns.
But I couldn't resist to add some more thoughts about concepts:
Originally we had a pattern where the serialization are added to each of the objects (under different method names).
After a while we introduced the Codec interface to separate the serialization logic from POJOs, but still we call back to the original methods in most of the cases (just because it would be a big refactor to move everything to the codec).
And Codec implementations are used mainly for the persistence.
But long-term I would prefer to use Codec for network serialization, too, to separate the serialization logic and manage in the same way.
At that time, we can introduce VersionedCodec which can use different Codec (depends on the versions).
But this is just a dream, would be great to have more time to improve the code style/class hierarchy....
But even if it's just a dream, I am interested about your opinions ;-)
|
I merged this based on +1s from @xiaoyuyao and @elek. |
|
Thanks @GlenGeng, @elek and @xiaoyuyao for the review, @arp7 for merging it. |
|
It looks like I missed a minor remaining comment from @xiaoyuyao. Let's address in a follow up jira if needed. |
What changes were proposed in this pull request?
versionnumber to client messages. Old client does not send version number, in this case it defaults to 0 at the other side. Client with this change sendsversion = 1.STANDALONE,RATIS,REST) inDatanodeDetailsprotobuf message sent to v0 client, which cannot handle new enum constants.Port.Namevalues. This in itself is not enough as a fix, since old client does not have this logic. But this allows the server to send any new port from now on tov >= 1clients.https://issues.apache.org/jira/browse/HDDS-4731
How was this patch tested?
Added acceptance test which verifies cross-compatibility of key write/read among 0.5.0, 1.0.0, 1.1.0 versions.
Tested closed container replication using
ozone-topologycompose environment to check for regression.https://github.com/adoroszlai/hadoop-ozone/actions/runs/510263073