-
Notifications
You must be signed in to change notification settings - Fork 624
HDDS-13305. Create wrapper object for container checksums #8789
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
Changes from 13 commits
8f59ac0
3323de2
902997d
1299510
f0e922f
0253d2d
ed449d4
c9425f4
242f2e4
cffc5c2
620efb0
42d61cf
5fd256e
f4ef042
df89c7f
d5cf9d9
bb8bb9f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one or more | ||
| * contributor license agreements. See the NOTICE file distributed with | ||
| * this work for additional information regarding copyright ownership. | ||
| * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
| * (the "License"); you may not use this file except in compliance with | ||
| * the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| package org.apache.hadoop.hdds.scm.container; | ||
|
|
||
| import java.util.Objects; | ||
| import net.jcip.annotations.Immutable; | ||
|
|
||
| /** | ||
| * Wrapper for container checksums (data, metadata, etc.). | ||
| * Provides equality, hash, and hex string rendering. | ||
| */ | ||
| @Immutable | ||
| public final class ContainerChecksums { | ||
|
|
||
| private static final ContainerChecksums UNKNOWN = | ||
| new ContainerChecksums(-1L, -1L); | ||
|
|
||
| // Checksum of the data within the wrapper. | ||
| private final long dataChecksum; | ||
| private static final long UNSET_DATA_CHECKSUM = -1; | ||
|
|
||
| // Checksum of the metadata within the wrapper. | ||
| private final long metadataChecksum; | ||
| private static final long UNSET_METADATA_CHECKSUM = -1; | ||
|
|
||
| private ContainerChecksums(long dataChecksum, long metadataChecksum) { | ||
| this.dataChecksum = dataChecksum; | ||
| this.metadataChecksum = metadataChecksum; | ||
| } | ||
|
|
||
| public static ContainerChecksums unknown() { | ||
| return UNKNOWN; | ||
| } | ||
|
|
||
| public static ContainerChecksums of(long dataChecksum, long metadataChecksum) { | ||
| return new ContainerChecksums(dataChecksum, metadataChecksum); | ||
| } | ||
|
|
||
| public long getDataChecksum() { | ||
| // UNSET_DATA_CHECKSUM is an internal placeholder, it should not be used outside this class. | ||
| if (needsDataChecksum()) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: move comment to |
||
| return 0; | ||
| } | ||
| return dataChecksum; | ||
| } | ||
|
|
||
| public boolean needsDataChecksum() { | ||
| return dataChecksum == UNSET_DATA_CHECKSUM; | ||
| } | ||
|
|
||
| public long getMetadataChecksum() { | ||
| // UNSET_DATA_CHECKSUM is an internal placeholder, it should not be used outside this class. | ||
| if (needsMetadataChecksum()) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: this should mention |
||
| return 0; | ||
| } | ||
| return metadataChecksum; | ||
| } | ||
|
|
||
| public boolean needsMetadataChecksum() { | ||
| return metadataChecksum == UNSET_METADATA_CHECKSUM; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean equals(Object obj) { | ||
| if (this == obj) { | ||
| return true; | ||
| } | ||
| if (!(obj instanceof ContainerChecksums)) { | ||
| return false; | ||
| } | ||
| ContainerChecksums that = (ContainerChecksums) obj; | ||
| return getDataChecksum() == that.getDataChecksum() && | ||
| getMetadataChecksum() == that.getMetadataChecksum(); | ||
| } | ||
|
|
||
| @Override | ||
| public int hashCode() { | ||
| return Objects.hash(dataChecksum, metadataChecksum); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Do we want to consider these unequal? Then Otherwise, if we want to consider these to be equal, and all other code passes 0 for unknown value, can we avoid using -1 internally? That would also make
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that we should consider this unequality.
|
||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return "data=" + Long.toHexString(getDataChecksum()) + | ||
| ", metadata=" + Long.toHexString(getMetadataChecksum()); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| /* | ||
| * Licensed to the Apache Software Foundation (ASF) under one or more | ||
| * contributor license agreements. See the NOTICE file distributed with | ||
| * this work for additional information regarding copyright ownership. | ||
| * The ASF licenses this file to You under the Apache License, Version 2.0 | ||
| * (the "License"); you may not use this file except in compliance with | ||
| * the License. You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| package org.apache.hadoop.hdds.scm.container; | ||
|
|
||
| import static org.assertj.core.api.Assertions.assertThat; | ||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
| import static org.junit.jupiter.api.Assertions.assertNotEquals; | ||
|
|
||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| class TestContainerChecksums { | ||
| @Test | ||
| void testEqualsAndHashCode() { | ||
| ContainerChecksums c1 = ContainerChecksums.of(123L, 0L); | ||
| ContainerChecksums c2 = ContainerChecksums.of(123L, 0L); | ||
| ContainerChecksums c3 = ContainerChecksums.of(456L, 0L); | ||
| ContainerChecksums c4 = ContainerChecksums.of(123L, 789L); | ||
| ContainerChecksums c5 = ContainerChecksums.of(123L, 789L); | ||
| ContainerChecksums c6 = ContainerChecksums.of(123L, 790L); | ||
|
|
||
| assertEquals(c1, c2); | ||
| assertEquals(c1.hashCode(), c2.hashCode()); | ||
| assertNotEquals(c1, c3); | ||
| assertNotEquals(c1, c4); | ||
| assertEquals(c4, c5); | ||
| assertNotEquals(c4, c6); | ||
| } | ||
|
|
||
| @Test | ||
| void testToString() { | ||
| ContainerChecksums c1 = ContainerChecksums.of(0x1234ABCDL, 0L); | ||
| assertThat(c1.toString()).contains("data=1234abcd", "metadata=0"); | ||
|
|
||
| ContainerChecksums c2 = ContainerChecksums.of(0x1234ABCDL, 0xDEADBEEFL); | ||
| assertThat(c2.toString()).contains("data=1234abcd").contains("metadata=deadbeef"); | ||
|
|
||
| ContainerChecksums c3 = ContainerChecksums.unknown(); | ||
| assertThat(c3.toString()).contains("data=0").contains("metadata=0"); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -362,7 +362,7 @@ private void updateContainerReplica(final DatanodeDetails datanodeDetails, | |
| .setReplicaIndex(replicaProto.getReplicaIndex()) | ||
| .setBytesUsed(replicaProto.getUsed()) | ||
| .setEmpty(replicaProto.getIsEmpty()) | ||
| .setDataChecksum(replicaProto.getDataChecksum()) | ||
| .setChecksums(ContainerChecksums.of(replicaProto.getDataChecksum(), 0L)) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please replace all calls like this with Rationale:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @adoroszlai
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently we only have data checksum, so we should not force all callers to pass
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for pointing it out! |
||
| .build(); | ||
|
|
||
| if (replica.getState().equals(State.DELETED)) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,7 +45,7 @@ public final class ContainerReplica implements Comparable<ContainerReplica> { | |
| private final long keyCount; | ||
| private final long bytesUsed; | ||
| private final boolean isEmpty; | ||
| private final long dataChecksum; | ||
| private final ContainerChecksums checksums; | ||
|
|
||
| private ContainerReplica(ContainerReplicaBuilder b) { | ||
| this.containerID = Objects.requireNonNull(b.containerID, "containerID == null"); | ||
|
|
@@ -57,7 +57,7 @@ private ContainerReplica(ContainerReplicaBuilder b) { | |
| this.replicaIndex = b.replicaIndex; | ||
| this.isEmpty = b.isEmpty; | ||
| this.sequenceId = b.sequenceId; | ||
| this.dataChecksum = b.dataChecksum; | ||
| this.checksums = Objects.requireNonNull(b.checksums, "checksums == null"); | ||
| } | ||
|
|
||
| public ContainerID getContainerID() { | ||
|
|
@@ -122,8 +122,12 @@ public boolean isEmpty() { | |
| return isEmpty; | ||
| } | ||
|
|
||
| public ContainerChecksums getChecksums() { | ||
| return checksums; | ||
| } | ||
|
|
||
| public long getDataChecksum() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can just use
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| return dataChecksum; | ||
| return checksums.getDataChecksum(); | ||
| } | ||
|
|
||
| @Override | ||
|
|
@@ -180,7 +184,8 @@ public ContainerReplicaBuilder toBuilder() { | |
| .setOriginNodeId(originDatanodeId) | ||
| .setReplicaIndex(replicaIndex) | ||
| .setSequenceId(sequenceId) | ||
| .setEmpty(isEmpty); | ||
| .setEmpty(isEmpty) | ||
| .setChecksums(checksums); | ||
| } | ||
|
|
||
| @Override | ||
|
|
@@ -194,7 +199,7 @@ public String toString() { | |
| + ", keyCount=" + keyCount | ||
| + ", bytesUsed=" + bytesUsed | ||
| + ", " + (isEmpty ? "empty" : "non-empty") | ||
| + ", dataChecksum=" + dataChecksum | ||
| + ", checksums=" + checksums | ||
| + '}'; | ||
| } | ||
|
|
||
|
|
@@ -212,7 +217,7 @@ public static class ContainerReplicaBuilder { | |
| private long keyCount; | ||
| private int replicaIndex; | ||
| private boolean isEmpty; | ||
| private long dataChecksum; | ||
| private ContainerChecksums checksums; | ||
|
|
||
| /** | ||
| * Set Container Id. | ||
|
|
@@ -287,8 +292,8 @@ public ContainerReplicaBuilder setEmpty(boolean empty) { | |
| return this; | ||
| } | ||
|
|
||
| public ContainerReplicaBuilder setDataChecksum(long dataChecksum) { | ||
| this.dataChecksum = dataChecksum; | ||
| public ContainerReplicaBuilder setChecksums(ContainerChecksums checksums) { | ||
| this.checksums = checksums; | ||
| return this; | ||
| } | ||
|
|
||
|
|
@@ -298,6 +303,9 @@ public ContainerReplicaBuilder setDataChecksum(long dataChecksum) { | |
| * @return ContainerReplicaBuilder | ||
| */ | ||
| public ContainerReplica build() { | ||
| if (this.checksums == null) { | ||
| this.checksums = ContainerChecksums.unknown(); | ||
| } | ||
| return new ContainerReplica(this); | ||
| } | ||
| } | ||
|
|
||
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: use
UNSET_DATA_CHECKSUMandUNSET_METADATA_CHECKSUM