-
Notifications
You must be signed in to change notification settings - Fork 615
HDDS-15791. EC reconstructed RECOVERING container while still idle can be deleted by SCM and recreated as new partial OPEN container #10702
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
base: master
Are you sure you want to change the base?
Changes from all commits
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 |
|---|---|---|
|
|
@@ -18,6 +18,7 @@ | |
| package org.apache.hadoop.hdds.scm.storage; | ||
|
|
||
| import static org.apache.hadoop.hdds.scm.storage.ContainerProtocolCalls.putBlockAsync; | ||
| import static org.apache.hadoop.ozone.OzoneConsts.CONTAINER_CREATABLE_KEY; | ||
|
|
||
| import com.google.common.base.Preconditions; | ||
| import java.io.IOException; | ||
|
|
@@ -59,6 +60,7 @@ | |
| public class ECBlockOutputStream extends BlockOutputStream { | ||
|
|
||
| private final DatanodeDetails datanodeDetails; | ||
| private final boolean denyContainerAutoCreate; | ||
| private CompletableFuture<ContainerProtos.ContainerCommandResponseProto> | ||
| currentChunkRspFuture = null; | ||
|
|
||
|
|
@@ -83,11 +85,46 @@ public ECBlockOutputStream( | |
| Token<? extends TokenIdentifier> token, | ||
| ContainerClientMetrics clientMetrics, StreamBufferArgs streamBufferArgs, | ||
| Supplier<ExecutorService> executorServiceSupplier | ||
| ) throws IOException { | ||
| this(blockID, xceiverClientManager, pipeline, bufferPool, config, token, clientMetrics, | ||
| streamBufferArgs, executorServiceSupplier, false); | ||
| } | ||
|
|
||
| @SuppressWarnings("checkstyle:ParameterNumber") | ||
| public ECBlockOutputStream( | ||
| BlockID blockID, | ||
| XceiverClientFactory xceiverClientManager, | ||
| Pipeline pipeline, | ||
| BufferPool bufferPool, | ||
| OzoneClientConfig config, | ||
| Token<? extends TokenIdentifier> token, | ||
| ContainerClientMetrics clientMetrics, StreamBufferArgs streamBufferArgs, | ||
| Supplier<ExecutorService> executorServiceSupplier, | ||
| boolean denyContainerAutoCreate | ||
| ) throws IOException { | ||
| super(blockID, -1, xceiverClientManager, | ||
| pipeline, bufferPool, config, token, clientMetrics, streamBufferArgs, executorServiceSupplier); | ||
| // In EC stream, there will be only one node in pipeline. | ||
| this.datanodeDetails = pipeline.getClosestNode(); | ||
| this.denyContainerAutoCreate = denyContainerAutoCreate; | ||
| if (denyContainerAutoCreate) { | ||
| getContainerBlockData().addMetadata(containerCreatableFalseKv()); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| protected ChunkInfo.Builder decorateChunkInfo(ChunkInfo.Builder builder) { | ||
|
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, this might break the normal EC write as well because
Member
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. Updated to add overloaded API for reconstruction. |
||
| if (!denyContainerAutoCreate) { | ||
| return builder; | ||
| } | ||
| return builder.addMetadata(containerCreatableFalseKv()); | ||
| } | ||
|
|
||
| private static ContainerProtos.KeyValue containerCreatableFalseKv() { | ||
| return ContainerProtos.KeyValue.newBuilder() | ||
| .setKey(CONTAINER_CREATABLE_KEY) | ||
| .setValue(OzoneConsts.CONTAINER_CREATABLE) | ||
| .build(); | ||
| } | ||
|
|
||
| @Override | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,6 +25,7 @@ | |
| import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result.NO_SUCH_ALGORITHM; | ||
| import static org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.Result.UNABLE_TO_FIND_DATA_DIR; | ||
| import static org.apache.hadoop.hdds.scm.protocolPB.ContainerCommandResponseBuilders.getContainerCommandResponse; | ||
| import static org.apache.hadoop.ozone.OzoneConsts.CONTAINER_CREATABLE_KEY; | ||
| import static org.apache.hadoop.ozone.container.common.impl.ContainerData.CHARSET_ENCODING; | ||
|
|
||
| import java.io.File; | ||
|
|
@@ -35,6 +36,7 @@ | |
| import java.security.MessageDigest; | ||
| import java.security.NoSuchAlgorithmException; | ||
| import java.util.Collection; | ||
| import java.util.List; | ||
| import java.util.Objects; | ||
| import java.util.Properties; | ||
| import java.util.UUID; | ||
|
|
@@ -403,4 +405,54 @@ public static long getPendingDeletionBytes(ContainerData containerData) { | |
| " not support."); | ||
| } | ||
| } | ||
|
|
||
| public static ContainerProtos.KeyValue containerCreatableFalseKv() { | ||
| return ContainerProtos.KeyValue.newBuilder() | ||
| .setKey(CONTAINER_CREATABLE_KEY) | ||
| .setValue(OzoneConsts.CONTAINER_CREATABLE) | ||
| .build(); | ||
| } | ||
|
|
||
| /** | ||
| * @return true if the DataNode may auto-create a missing container for this request | ||
| */ | ||
| public static boolean isContainerCreatable(ContainerCommandRequestProto request) { | ||
|
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. This flag is currently only restricted to check
Member
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. Added for PutBlock as well. |
||
| if (request.hasWriteChunk()) { | ||
| ContainerProtos.WriteChunkRequestProto writeChunk = request.getWriteChunk(); | ||
| if (writeChunk.hasChunkData() | ||
| && deniesContainerAutoCreate(writeChunk.getChunkData().getMetadataList())) { | ||
| return false; | ||
| } | ||
| } | ||
| if (request.hasPutBlock()) { | ||
| ContainerProtos.PutBlockRequestProto putBlock = request.getPutBlock(); | ||
| if (putBlock.hasBlockData() | ||
| && deniesContainerAutoCreate(putBlock.getBlockData().getMetadataList())) { | ||
| return false; | ||
| } | ||
| } | ||
| if (request.hasPutSmallFile()) { | ||
| ContainerProtos.PutSmallFileRequestProto putSmallFile = request.getPutSmallFile(); | ||
| if (putSmallFile.hasChunkInfo() | ||
| && deniesContainerAutoCreate(putSmallFile.getChunkInfo().getMetadataList())) { | ||
| return false; | ||
| } | ||
| if (putSmallFile.hasBlock() && putSmallFile.getBlock().hasBlockData() | ||
| && deniesContainerAutoCreate(putSmallFile.getBlock().getBlockData().getMetadataList())) { | ||
| return false; | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| private static boolean deniesContainerAutoCreate( | ||
| List<ContainerProtos.KeyValue> metadataList) { | ||
| for (ContainerProtos.KeyValue kv : metadataList) { | ||
| if (CONTAINER_CREATABLE_KEY.equals(kv.getKey()) | ||
| && OzoneConsts.CONTAINER_CREATABLE.equals(kv.getValue())) { | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
| } | ||
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.
decorateChunkInfomethod will fall into both normal EC write path and reconstruction path. Kindly check this part.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.
Updated this.