This is an automated email from the ASF dual-hosted git repository.
sammichen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 50e57f9af5 HDDS-7137. Add CLI for Getting the failed deleted block txn
(#3691)
50e57f9af5 is described below
commit 50e57f9af5a8835815fd54fb0d39279f40254889
Author: NibiruXu <[email protected]>
AuthorDate: Mon Mar 6 16:33:48 2023 +0800
HDDS-7137. Add CLI for Getting the failed deleted block txn (#3691)
---
.../apache/hadoop/hdds/scm/client/ScmClient.java | 16 +-
.../protocol/StorageContainerLocationProtocol.java | 16 +-
.../org/apache/hadoop/ozone/audit/SCMAction.java | 3 +-
.../DeletedBlocksTransactionInfoWrapper.java | 110 +++++++++
...inerLocationProtocolClientSideTranslatorPB.java | 18 ++
.../src/main/proto/ScmAdminProtocol.proto | 13 +
.../interface-client/src/main/proto/hdds.proto | 7 +
.../hadoop/hdds/scm/block/DeletedBlockLog.java | 12 +-
.../hadoop/hdds/scm/block/DeletedBlockLogImpl.java | 25 +-
...inerLocationProtocolServerSideTranslatorPB.java | 19 ++
.../hdds/scm/server/SCMClientProtocolServer.java | 22 ++
.../hdds/scm/cli/ContainerOperationClient.java | 8 +
.../hadoop/ozone/TestStorageContainerManager.java | 2 +-
.../ozone/shell/TestDeletedBlocksTxnShell.java | 270 +++++++++++++++++++++
.../TestResetDeletedBlockRetryCountShell.java | 169 -------------
...ScmAdmin.java => DeletedBlocksTxnCommands.java} | 39 +--
.../scm/GetFailedDeletedBlocksTxnSubcommand.java | 91 +++++++
.../scm/ResetDeletedBlockRetryCountSubcommand.java | 57 ++++-
.../apache/hadoop/ozone/admin/scm/ScmAdmin.java | 4 +-
19 files changed, 675 insertions(+), 226 deletions(-)
diff --git
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java
index 713d7204c5..916bd7fdfb 100644
---
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java
+++
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/client/ScmClient.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.hdds.scm.client;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.hadoop.hdds.annotation.InterfaceStability;
import org.apache.hadoop.hdds.client.ReplicationConfig;
+import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.DeletedBlocksTransactionInfo;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.StartContainerBalancerResponseProto;
import org.apache.hadoop.hdds.scm.DatanodeAdminError;
import org.apache.hadoop.hdds.scm.container.ContainerReplicaInfo;
@@ -369,7 +370,20 @@ public interface ScmClient extends Closeable {
void transferLeadership(String newLeaderId) throws IOException;
/**
- * Reset the expired deleted block retry count.
+ * Return the failed transactions of the Deleted blocks. A transaction is
+ * considered to be failed if it has been sent more than MAX_RETRY limit
+ * and its count is reset to -1.
+ *
+ * @param count Maximum num of returned transactions, if < 0. return all.
+ * @param startTxId The least transaction id to start with.
+ * @return a list of failed deleted block transactions.
+ * @throws IOException
+ */
+ List<DeletedBlocksTransactionInfo> getFailedDeletedBlockTxn(int count,
+ long startTxId) throws IOException;
+
+ /**
+ * Reset the failed deleted block retry count.
* @param txIDs transactionId list to be reset
* @throws IOException
*/
diff --git
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocol.java
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocol.java
index bd03bc84e8..7690b2eefb 100644
---
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocol.java
+++
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocol.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.hdds.scm.protocol;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.hadoop.hdds.client.ReplicationConfig;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
+import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.DeletedBlocksTransactionInfo;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.StartContainerBalancerResponseProto;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.Type;
import org.apache.hadoop.hdds.scm.DatanodeAdminError;
@@ -317,7 +318,20 @@ public interface StorageContainerLocationProtocol extends
Closeable {
void transferLeadership(String newLeaderId) throws IOException;
/**
- * Reset the expired deleted block retry count.
+ * Return the failed transactions of the Deleted blocks. A transaction is
+ * considered to be failed if it has been sent more than MAX_RETRY limit
+ * and its count is reset to -1.
+ *
+ * @param count Maximum num of returned transactions, if < 0. return all.
+ * @param startTxId The least transaction id to start with.
+ * @return a list of failed deleted block transactions.
+ * @throws IOException
+ */
+ List<DeletedBlocksTransactionInfo> getFailedDeletedBlockTxn(int count,
+ long startTxId) throws IOException;
+
+ /**
+ * Reset the failed deleted block retry count.
*
* @param txIDs transactionId list to be reset
* @return num of successful reset
diff --git
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/SCMAction.java
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/SCMAction.java
index 16e88df281..4e1fe234ff 100644
---
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/SCMAction.java
+++
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/audit/SCMAction.java
@@ -51,7 +51,8 @@ public enum SCMAction implements AuditAction {
ADD_SCM,
GET_REPLICATION_MANAGER_REPORT,
RESET_DELETED_BLOCK_RETRY_COUNT,
- TRANSFER_LEADERSHIP;
+ TRANSFER_LEADERSHIP,
+ GET_FAILED_DELETED_BLOCKS_TRANSACTION;
@Override
public String getAction() {
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/DeletedBlocksTransactionInfoWrapper.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/DeletedBlocksTransactionInfoWrapper.java
new file mode 100644
index 0000000000..64ced8dce4
--- /dev/null
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/container/common/helpers/DeletedBlocksTransactionInfoWrapper.java
@@ -0,0 +1,110 @@
+/*
+ * 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.common.helpers;
+
+import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.DeletedBlocksTransactionInfo;
+import
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.DeletedBlocksTransaction;
+import java.util.List;
+
+/**
+ * The wrapper for {@link DeletedBlocksTransactionInfo}.
+ */
+public class DeletedBlocksTransactionInfoWrapper {
+
+ private final long txID;
+ private final long containerID;
+ private final List<Long> localIdList;
+ private final int count;
+
+ public DeletedBlocksTransactionInfoWrapper(long txID, long containerID,
+ List<Long> localIdList, int count) {
+ this.txID = txID;
+ this.containerID = containerID;
+ this.localIdList = localIdList;
+ this.count = count;
+ }
+
+ public static DeletedBlocksTransactionInfoWrapper fromProtobuf(
+ DeletedBlocksTransactionInfo txn) {
+ if (txn.hasTxID() && txn.hasContainerID() && txn.hasCount()) {
+ return new DeletedBlocksTransactionInfoWrapper(
+ txn.getTxID(),
+ txn.getContainerID(),
+ txn.getLocalIDList(),
+ txn.getCount());
+ }
+ return null;
+ }
+
+ public static DeletedBlocksTransactionInfo toProtobuf(
+ DeletedBlocksTransactionInfoWrapper wrapper) {
+ return DeletedBlocksTransactionInfo.newBuilder()
+ .setTxID(wrapper.txID)
+ .setContainerID(wrapper.containerID)
+ .addAllLocalID(wrapper.localIdList)
+ .setCount(wrapper.count)
+ .build();
+ }
+
+ public static DeletedBlocksTransactionInfo fromTxn(
+ DeletedBlocksTransaction txn) {
+ return DeletedBlocksTransactionInfo.newBuilder()
+ .setTxID(txn.getTxID())
+ .setContainerID(txn.getContainerID())
+ .addAllLocalID(txn.getLocalIDList())
+ .setCount(txn.getCount())
+ .build();
+ }
+
+ public static DeletedBlocksTransaction toTxn(
+ DeletedBlocksTransactionInfo info) {
+ return DeletedBlocksTransaction.newBuilder()
+ .setTxID(info.getTxID())
+ .setContainerID(info.getContainerID())
+ .addAllLocalID(info.getLocalIDList())
+ .setCount(info.getCount())
+ .build();
+ }
+
+
+ public long getTxID() {
+ return txID;
+ }
+
+ public long getContainerID() {
+ return containerID;
+ }
+
+ public List<Long> getLocalIdList() {
+ return localIdList;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ @Override
+ public String toString() {
+ return "DeletedBlocksTransactionInfoWrapper{" +
+ "txID=" + txID +
+ ", containerID=" + containerID +
+ ", localIdList=" + localIdList +
+ ", count=" + count +
+ '}';
+ }
+}
diff --git
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolClientSideTranslatorPB.java
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolClientSideTranslatorPB.java
index 0f7d1c0bb5..c664a42ae6 100644
---
a/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolClientSideTranslatorPB.java
+++
b/hadoop-hdds/framework/src/main/java/org/apache/hadoop/hdds/scm/protocolPB/StorageContainerLocationProtocolClientSideTranslatorPB.java
@@ -25,12 +25,15 @@ import org.apache.hadoop.hdds.client.ECReplicationConfig;
import org.apache.hadoop.hdds.client.ReplicatedReplicationConfig;
import org.apache.hadoop.hdds.client.ReplicationConfig;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
+import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.DeletedBlocksTransactionInfo;
import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.GetScmInfoResponseProto;
import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.TransferLeadershipRequestProto;
import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.UpgradeFinalizationStatus;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.FinalizeScmUpgradeRequestProto;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.FinalizeScmUpgradeResponseProto;
+import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.GetFailedDeletedBlocksTxnRequestProto;
+import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.GetFailedDeletedBlocksTxnResponseProto;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.QueryUpgradeFinalizationProgressRequestProto;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.QueryUpgradeFinalizationProgressResponseProto;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.SafeModeRuleStatusProto;
@@ -713,6 +716,21 @@ public final class
StorageContainerLocationProtocolClientSideTranslatorPB
builder ->
builder.setTransferScmLeadershipRequest(reqBuilder.build()));
}
+ @Override
+ public List<DeletedBlocksTransactionInfo> getFailedDeletedBlockTxn(int count,
+ long startTxId) throws IOException {
+ GetFailedDeletedBlocksTxnRequestProto request =
+ GetFailedDeletedBlocksTxnRequestProto.newBuilder()
+ .setCount(count)
+ .setStartTxId(startTxId)
+ .build();
+ GetFailedDeletedBlocksTxnResponseProto resp = submitRequest(
+ Type.GetFailedDeletedBlocksTransaction,
+ builder -> builder.setGetFailedDeletedBlocksTxnRequest(request)).
+ getGetFailedDeletedBlocksTxnResponse();
+ return resp.getDeletedBlocksTransactionsList();
+ }
+
@Override
public int resetDeletedBlockRetryCount(List<Long> txIDs)
throws IOException {
diff --git a/hadoop-hdds/interface-admin/src/main/proto/ScmAdminProtocol.proto
b/hadoop-hdds/interface-admin/src/main/proto/ScmAdminProtocol.proto
index 2aac8b2f51..d5a3c6f65a 100644
--- a/hadoop-hdds/interface-admin/src/main/proto/ScmAdminProtocol.proto
+++ b/hadoop-hdds/interface-admin/src/main/proto/ScmAdminProtocol.proto
@@ -79,6 +79,7 @@ message ScmContainerLocationRequest {
optional ReplicationManagerReportRequestProto
replicationManagerReportRequest = 40;
optional ResetDeletedBlockRetryCountRequestProto
resetDeletedBlockRetryCountRequest = 41;
optional TransferLeadershipRequestProto transferScmLeadershipRequest = 42;
+ optional GetFailedDeletedBlocksTxnRequestProto
getFailedDeletedBlocksTxnRequest = 43;
}
message ScmContainerLocationResponse {
@@ -129,6 +130,7 @@ message ScmContainerLocationResponse {
optional ReplicationManagerReportResponseProto
getReplicationManagerReportResponse = 40;
optional ResetDeletedBlockRetryCountResponseProto
resetDeletedBlockRetryCountResponse = 41;
optional TransferLeadershipResponseProto transferScmLeadershipResponse = 42;
+ optional GetFailedDeletedBlocksTxnResponseProto
getFailedDeletedBlocksTxnResponse = 43;
enum Status {
OK = 1;
@@ -178,6 +180,7 @@ enum Type {
ResetDeletedBlockRetryCount = 36;
GetClosedContainerCount = 37;
TransferLeadership = 38;
+ GetFailedDeletedBlocksTransaction = 39;
}
/**
@@ -488,6 +491,16 @@ message ReplicationManagerReportResponseProto {
required ReplicationManagerReportProto report = 1;
}
+message GetFailedDeletedBlocksTxnRequestProto {
+ optional string traceID = 1;
+ required int32 count = 2;
+ optional int64 startTxId = 3;
+}
+
+message GetFailedDeletedBlocksTxnResponseProto {
+ repeated DeletedBlocksTransactionInfo deletedBlocksTransactions = 1;
+}
+
message ResetDeletedBlockRetryCountRequestProto {
optional string traceID = 1;
repeated int64 transactionId = 2;
diff --git a/hadoop-hdds/interface-client/src/main/proto/hdds.proto
b/hadoop-hdds/interface-client/src/main/proto/hdds.proto
index 2a07d2dcc5..16ea4887aa 100644
--- a/hadoop-hdds/interface-client/src/main/proto/hdds.proto
+++ b/hadoop-hdds/interface-client/src/main/proto/hdds.proto
@@ -458,4 +458,11 @@ message TransferLeadershipRequestProto {
}
message TransferLeadershipResponseProto {
+}
+
+message DeletedBlocksTransactionInfo {
+ optional int64 txID = 1;
+ optional int64 containerID = 2;
+ repeated int64 localID = 3;
+ optional int32 count = 4;
}
\ No newline at end of file
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLog.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLog.java
index ddd7085e29..ea2013917d 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLog.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLog.java
@@ -51,15 +51,17 @@ public interface DeletedBlockLog extends Closeable {
throws IOException, TimeoutException;
/**
- * Return all failed transactions in the log. A transaction is considered
- * to be failed if it has been sent more than MAX_RETRY limit and its
- * count is reset to -1.
+ * Return the failed transactions in the log. A transaction is
+ * considered to be failed if it has been sent more than MAX_RETRY limit
+ * and its count is reset to -1.
*
+ * @param count Maximum num of returned transactions, if < 0. return all.
+ * @param startTxId The least transaction id to start with.
* @return a list of failed deleted block transactions.
* @throws IOException
*/
- List<DeletedBlocksTransaction> getFailedTransactions()
- throws IOException;
+ List<DeletedBlocksTransaction> getFailedTransactions(int count,
+ long startTxId) throws IOException;
/**
* Increments count for given list of transactions by 1.
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogImpl.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogImpl.java
index 6903d5ed3f..589a9f3f76 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogImpl.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/DeletedBlockLogImpl.java
@@ -92,6 +92,8 @@ public class DeletedBlockLogImpl
private final SequenceIdGenerator sequenceIdGen;
private final ScmBlockDeletingServiceMetrics metrics;
+ private static final int LIST_ALL_FAILED_TRANSACTIONS = -1;
+
@SuppressWarnings("parameternumber")
public DeletedBlockLogImpl(ConfigurationSource conf,
ContainerManager containerManager,
@@ -126,18 +128,27 @@ public class DeletedBlockLogImpl
}
@Override
- public List<DeletedBlocksTransaction> getFailedTransactions()
- throws IOException {
+ public List<DeletedBlocksTransaction> getFailedTransactions(int count,
+ long startTxId) throws IOException {
lock.lock();
try {
final List<DeletedBlocksTransaction> failedTXs = Lists.newArrayList();
try (TableIterator<Long,
? extends Table.KeyValue<Long, DeletedBlocksTransaction>> iter =
deletedBlockLogStateManager.getReadOnlyIterator()) {
- while (iter.hasNext()) {
- DeletedBlocksTransaction delTX = iter.next().getValue();
- if (delTX.getCount() == -1) {
- failedTXs.add(delTX);
+ if (count == LIST_ALL_FAILED_TRANSACTIONS) {
+ while (iter.hasNext()) {
+ DeletedBlocksTransaction delTX = iter.next().getValue();
+ if (delTX.getCount() == -1) {
+ failedTXs.add(delTX);
+ }
+ }
+ } else {
+ while (iter.hasNext() && failedTXs.size() < count) {
+ DeletedBlocksTransaction delTX = iter.next().getValue();
+ if (delTX.getCount() == -1 && delTX.getTxID() >= startTxId) {
+ failedTXs.add(delTX);
+ }
}
}
}
@@ -191,7 +202,7 @@ public class DeletedBlockLogImpl
lock.lock();
try {
if (txIDs == null || txIDs.isEmpty()) {
- txIDs = getFailedTransactions().stream()
+ txIDs = getFailedTransactions(LIST_ALL_FAILED_TRANSACTIONS, 0).stream()
.map(DeletedBlocksTransaction::getTxID)
.collect(Collectors.toList());
}
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocolServerSideTranslatorPB.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocolServerSideTranslatorPB.java
index e550a9bd5d..2dc3c5b04f 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocolServerSideTranslatorPB.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/protocol/StorageContainerLocationProtocolServerSideTranslatorPB.java
@@ -60,6 +60,8 @@ import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolPro
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.GetExistContainerWithPipelinesInBatchRequestProto;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.GetExistContainerWithPipelinesInBatchResponseProto;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.GetContainerCountResponseProto;
+import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.GetFailedDeletedBlocksTxnRequestProto;
+import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.GetFailedDeletedBlocksTxnResponseProto;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.GetPipelineRequestProto;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.GetPipelineResponseProto;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.GetSafeModeRuleStatusesRequestProto;
@@ -657,6 +659,14 @@ public final class
StorageContainerLocationProtocolServerSideTranslatorPB
request.getGetContainerReplicasRequest(),
request.getVersion()))
.build();
+ case GetFailedDeletedBlocksTransaction:
+ return ScmContainerLocationResponse.newBuilder()
+ .setCmdType(request.getCmdType())
+ .setStatus(Status.OK)
+ .setGetFailedDeletedBlocksTxnResponse(getFailedDeletedBlocksTxn(
+ request.getGetFailedDeletedBlocksTxnRequest()
+ ))
+ .build();
case ResetDeletedBlockRetryCount:
return ScmContainerLocationResponse.newBuilder()
.setCmdType(request.getCmdType())
@@ -1176,6 +1186,15 @@ public final class
StorageContainerLocationProtocolServerSideTranslatorPB
.build();
}
+ public GetFailedDeletedBlocksTxnResponseProto getFailedDeletedBlocksTxn(
+ GetFailedDeletedBlocksTxnRequestProto request) throws IOException {
+ long startTxId = request.hasStartTxId() ? request.getStartTxId() : 0;
+ return GetFailedDeletedBlocksTxnResponseProto.newBuilder()
+ .addAllDeletedBlocksTransactions(
+ impl.getFailedDeletedBlockTxn(request.getCount(), startTxId))
+ .build();
+ }
+
public ResetDeletedBlockRetryCountResponseProto
getResetDeletedBlockRetryCount(ResetDeletedBlockRetryCountRequestProto
request) throws IOException {
diff --git
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
index c73b2f0c26..ccd4153698 100644
---
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
+++
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/server/SCMClientProtocolServer.java
@@ -37,6 +37,7 @@ import org.apache.hadoop.hdds.protocol.DatanodeDetails;
import org.apache.hadoop.hdds.protocol.ReconfigureProtocol;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import
org.apache.hadoop.hdds.protocol.proto.ReconfigureProtocolProtos.ReconfigureProtocolService;
+import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.DeletedBlocksTransactionInfo;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.StartContainerBalancerResponseProto;
import org.apache.hadoop.hdds.protocolPB.ReconfigureProtocolPB;
@@ -48,6 +49,7 @@ import org.apache.hadoop.hdds.scm.container.ContainerID;
import org.apache.hadoop.hdds.scm.container.ContainerInfo;
import org.apache.hadoop.hdds.scm.container.ContainerNotFoundException;
import org.apache.hadoop.hdds.scm.container.ContainerReplica;
+import
org.apache.hadoop.hdds.scm.container.common.helpers.DeletedBlocksTransactionInfoWrapper;
import org.apache.hadoop.hdds.scm.container.ReplicationManagerReport;
import org.apache.hadoop.hdds.scm.container.balancer.ContainerBalancer;
import
org.apache.hadoop.hdds.scm.container.balancer.ContainerBalancerConfiguration;
@@ -846,6 +848,26 @@ public class SCMClientProtocolServer implements
}
}
+ public List<DeletedBlocksTransactionInfo> getFailedDeletedBlockTxn(int count,
+ long startTxId) throws IOException {
+ List<DeletedBlocksTransactionInfo> result;
+ try {
+ result = scm.getScmBlockManager().getDeletedBlockLog()
+ .getFailedTransactions(count, startTxId).stream()
+ .map(DeletedBlocksTransactionInfoWrapper::fromTxn)
+ .collect(Collectors.toList());
+ AUDIT.logWriteSuccess(buildAuditMessageForSuccess(
+ SCMAction.GET_FAILED_DELETED_BLOCKS_TRANSACTION, null));
+ return result;
+ } catch (IOException ex) {
+ AUDIT.logReadFailure(
+ buildAuditMessageForFailure(
+ SCMAction.GET_FAILED_DELETED_BLOCKS_TRANSACTION, null, ex)
+ );
+ throw ex;
+ }
+ }
+
@Override
public int resetDeletedBlockRetryCount(List<Long> txIDs) throws IOException {
Map<String, String> auditMap = Maps.newHashMap();
diff --git
a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/ContainerOperationClient.java
b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/ContainerOperationClient.java
index d72ed7bda9..22050f1940 100644
---
a/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/ContainerOperationClient.java
+++
b/hadoop-hdds/tools/src/main/java/org/apache/hadoop/hdds/scm/cli/ContainerOperationClient.java
@@ -26,6 +26,7 @@ import org.apache.hadoop.hdds.conf.OzoneConfiguration;
import
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ContainerDataProto;
import
org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos.ReadContainerResponseProto;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
+import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.DeletedBlocksTransactionInfo;
import
org.apache.hadoop.hdds.protocol.proto.StorageContainerLocationProtocolProtos.StartContainerBalancerResponseProto;
import org.apache.hadoop.hdds.scm.DatanodeAdminError;
import org.apache.hadoop.hdds.scm.ScmConfigKeys;
@@ -469,6 +470,13 @@ public class ContainerOperationClient implements ScmClient
{
storageContainerLocationClient.transferLeadership(newLeaderId);
}
+ @Override
+ public List<DeletedBlocksTransactionInfo> getFailedDeletedBlockTxn(int count,
+ long startTxId) throws IOException {
+ return storageContainerLocationClient.getFailedDeletedBlockTxn(count,
+ startTxId);
+ }
+
@Override
public int resetDeletedBlockRetryCount(List<Long> txIDs) throws IOException {
return storageContainerLocationClient.resetDeletedBlockRetryCount(txIDs);
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestStorageContainerManager.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestStorageContainerManager.java
index 89a17f7b95..33f3e9d363 100644
---
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestStorageContainerManager.java
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/TestStorageContainerManager.java
@@ -357,7 +357,7 @@ public class TestStorageContainerManager {
cluster.getStorageContainerManager().getScmHAManager()
.asSCMHADBTransactionBuffer().flush();
}
- return delLog.getFailedTransactions().size() == 0;
+ return delLog.getFailedTransactions(-1, 0).size() == 0;
} catch (IOException e) {
return false;
}
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestDeletedBlocksTxnShell.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestDeletedBlocksTxnShell.java
new file mode 100644
index 0000000000..e74041ceaf
--- /dev/null
+++
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestDeletedBlocksTxnShell.java
@@ -0,0 +1,270 @@
+/*
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.ozone.shell;
+
+import org.apache.hadoop.hdds.client.RatisReplicationConfig;
+import org.apache.hadoop.hdds.conf.OzoneConfiguration;
+import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
+import
org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReplicaProto.State;
+import org.apache.hadoop.hdds.scm.ScmConfigKeys;
+import org.apache.hadoop.hdds.scm.block.DeletedBlockLog;
+import org.apache.hadoop.hdds.scm.cli.ContainerOperationClient;
+import org.apache.hadoop.hdds.scm.container.ContainerID;
+import org.apache.hadoop.hdds.scm.container.ContainerInfo;
+import org.apache.hadoop.hdds.scm.container.ContainerReplica;
+import org.apache.hadoop.hdds.scm.container.ContainerStateManager;
+import org.apache.hadoop.hdds.scm.pipeline.PipelineID;
+import org.apache.hadoop.hdds.scm.server.StorageContainerManager;
+import org.apache.hadoop.ozone.MiniOzoneCluster;
+import org.apache.hadoop.ozone.MiniOzoneHAClusterImpl;
+import org.apache.hadoop.ozone.admin.scm.GetFailedDeletedBlocksTxnSubcommand;
+import org.apache.hadoop.ozone.admin.scm.ResetDeletedBlockRetryCountSubcommand;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import picocli.CommandLine;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import static
org.apache.hadoop.hdds.protocol.proto.HddsProtos.ReplicationFactor.THREE;
+import static
org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_BLOCK_DELETION_MAX_RETRY;
+
+/**
+ * Test for DeletedBlocksTxnSubcommand Cli.
+ */
+public class TestDeletedBlocksTxnShell {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(TestDeletedBlocksTxnShell.class);
+
+ private final PrintStream originalOut = System.out;
+ private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
+ private MiniOzoneHAClusterImpl cluster = null;
+ private OzoneConfiguration conf;
+ private String clusterId;
+ private String scmId;
+ private String scmServiceId;
+ private File txnFile;
+ private int numOfSCMs = 3;
+
+ private static final String DEFAULT_ENCODING = StandardCharsets.UTF_8.name();
+
+ @TempDir
+ private Path tempDir;
+
+ /**
+ * Create a MiniOzoneHACluster for testing.
+ *
+ * @throws IOException
+ */
+ @BeforeEach
+ public void init() throws Exception {
+ conf = new OzoneConfiguration();
+ clusterId = UUID.randomUUID().toString();
+ scmId = UUID.randomUUID().toString();
+ scmServiceId = "scm-service-test1";
+
+ conf.setBoolean(ScmConfigKeys.OZONE_SCM_HA_ENABLE_KEY, true);
+ conf.setInt(OZONE_SCM_BLOCK_DELETION_MAX_RETRY, 20);
+
+ cluster = (MiniOzoneHAClusterImpl) MiniOzoneCluster.newOMHABuilder(conf)
+ .setClusterId(clusterId)
+ .setScmId(scmId)
+ .setSCMServiceId(scmServiceId)
+ .setNumOfStorageContainerManagers(numOfSCMs)
+ .setNumOfActiveSCMs(numOfSCMs)
+ .setNumOfOzoneManagers(1)
+ .build();
+ cluster.waitForClusterToBeReady();
+
+ txnFile = tempDir.resolve("txn.txt").toFile();
+ LOG.info("txnFile path: {}", txnFile.getAbsolutePath());
+ System.setOut(new PrintStream(outContent, false, DEFAULT_ENCODING));
+ }
+
+ /**
+ * Shutdown MiniDFSCluster.
+ */
+ @AfterEach
+ public void shutdown() {
+ if (cluster != null) {
+ cluster.shutdown();
+ }
+ System.setOut(originalOut);
+ }
+
+ //<containerID, List<blockID>>
+ private Map<Long, List<Long>> generateData(int dataSize) throws Exception {
+ Map<Long, List<Long>> blockMap = new HashMap<>();
+ Random random = new Random(1);
+ int continerIDBase = random.nextInt(100);
+ int localIDBase = random.nextInt(1000);
+ for (int i = 0; i < dataSize; i++) {
+ long containerID = continerIDBase + i;
+ updateContainerMetadata(containerID);
+ List<Long> blocks = new ArrayList<>();
+ for (int j = 0; j < 5; j++) {
+ long localID = localIDBase + j;
+ blocks.add(localID);
+ }
+ blockMap.put(containerID, blocks);
+ }
+ return blockMap;
+ }
+
+ private void updateContainerMetadata(long cid) throws Exception {
+ final ContainerInfo container =
+ new ContainerInfo.Builder()
+ .setContainerID(cid)
+ .setReplicationConfig(RatisReplicationConfig.getInstance(THREE))
+ .setState(HddsProtos.LifeCycleState.CLOSED)
+ .setOwner("TestDeletedBlockLog")
+ .setPipelineID(PipelineID.randomId())
+ .build();
+ final Set<ContainerReplica> replicaSet = cluster.getHddsDatanodes()
+ .subList(0, 3)
+ .stream()
+ .map(dn -> ContainerReplica.newBuilder()
+ .setContainerID(container.containerID())
+ .setContainerState(State.CLOSED)
+ .setDatanodeDetails(dn.getDatanodeDetails())
+ .build())
+ .collect(Collectors.toSet());
+ ContainerStateManager containerStateManager = getSCMLeader().
+ getContainerManager().getContainerStateManager();
+ containerStateManager.addContainer(container.getProtobuf());
+ for (ContainerReplica replica: replicaSet) {
+ containerStateManager.updateContainerReplica(
+ ContainerID.valueOf(cid), replica);
+ }
+ }
+
+ private StorageContainerManager getSCMLeader() {
+ return cluster.getStorageContainerManagersList()
+ .stream().filter(a -> a.getScmContext().isLeaderReady())
+ .collect(Collectors.toList()).get(0);
+ }
+
+ private void flush() throws Exception {
+ // only flush leader here, avoid the follower concurrent flush and write
+ getSCMLeader().getScmHAManager().asSCMHADBTransactionBuffer().flush();
+ }
+
+ @Test
+ public void testDeletedBlocksTxnSubcommand() throws Exception {
+ int maxRetry = conf.getInt(OZONE_SCM_BLOCK_DELETION_MAX_RETRY, 20);
+ int currentValidTxnNum;
+ // add 30 block deletion transactions
+ DeletedBlockLog deletedBlockLog = getSCMLeader().
+ getScmBlockManager().getDeletedBlockLog();
+ deletedBlockLog.addTransactions(generateData(30));
+ flush();
+ currentValidTxnNum = deletedBlockLog.getNumOfValidTransactions();
+ LOG.info("Valid num of txns: {}", currentValidTxnNum);
+ Assertions.assertEquals(30, currentValidTxnNum);
+
+ // let the first 20 txns be failed
+ List<Long> txIds = new ArrayList<>();
+ for (int i = 1; i < 21; i++) {
+ txIds.add((long) i);
+ }
+ // increment retry count than threshold, count will be set to -1
+ for (int i = 0; i < maxRetry + 1; i++) {
+ deletedBlockLog.incrementCount(txIds);
+ }
+ flush();
+ currentValidTxnNum = deletedBlockLog.getNumOfValidTransactions();
+ LOG.info("Valid num of txns: {}", currentValidTxnNum);
+ Assertions.assertEquals(10, currentValidTxnNum);
+
+ ContainerOperationClient scmClient = new ContainerOperationClient(conf);
+ CommandLine cmd;
+ // getFailedDeletedBlocksTxn cmd will print all the failed txns
+ GetFailedDeletedBlocksTxnSubcommand getCommand =
+ new GetFailedDeletedBlocksTxnSubcommand();
+ cmd = new CommandLine(getCommand);
+ cmd.parseArgs("-a");
+ getCommand.execute(scmClient);
+ int matchCount = 0;
+ Pattern p = Pattern.compile("\"txID\" : \\d+", Pattern.MULTILINE);
+ Matcher m = p.matcher(outContent.toString(DEFAULT_ENCODING));
+ while (m.find()) {
+ matchCount += 1;
+ }
+ Assertions.assertEquals(20, matchCount);
+
+ // print the first 10 failed txns info into file
+ cmd.parseArgs("-o", txnFile.getAbsolutePath(), "-c", "10");
+ getCommand.execute(scmClient);
+ Assertions.assertTrue(txnFile.exists());
+
+ ResetDeletedBlockRetryCountSubcommand resetCommand =
+ new ResetDeletedBlockRetryCountSubcommand();
+ cmd = new CommandLine(resetCommand);
+
+ // reset the txns in file
+ cmd.parseArgs("-i", txnFile.getAbsolutePath());
+ resetCommand.execute(scmClient);
+ flush();
+ currentValidTxnNum = deletedBlockLog.getNumOfValidTransactions();
+ LOG.info("Valid num of txns: {}", currentValidTxnNum);
+ Assertions.assertEquals(20, currentValidTxnNum);
+
+ // reset the given txIds list
+ cmd.parseArgs("-l", "11,12,13,14,15");
+ resetCommand.execute(scmClient);
+ flush();
+ currentValidTxnNum = deletedBlockLog.getNumOfValidTransactions();
+ LOG.info("Valid num of txns: {}", currentValidTxnNum);
+ Assertions.assertEquals(25, currentValidTxnNum);
+
+ // reset the non-existing txns and valid txns, should do nothing
+ cmd.parseArgs("-l", "1,2,3,4,5,100,101,102,103,104,105");
+ resetCommand.execute(scmClient);
+ flush();
+ currentValidTxnNum = deletedBlockLog.getNumOfValidTransactions();
+ LOG.info("Valid num of txns: {}", currentValidTxnNum);
+ Assertions.assertEquals(25, currentValidTxnNum);
+
+ // reset all the result expired txIds, all transactions should be available
+ cmd.parseArgs("-a");
+ resetCommand.execute(scmClient);
+ flush();
+ currentValidTxnNum = deletedBlockLog.getNumOfValidTransactions();
+ LOG.info("Valid num of txns: {}", currentValidTxnNum);
+ Assertions.assertEquals(30, currentValidTxnNum);
+ }
+}
diff --git
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestResetDeletedBlockRetryCountShell.java
b/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestResetDeletedBlockRetryCountShell.java
deleted file mode 100644
index 8e90864036..0000000000
---
a/hadoop-ozone/integration-test/src/test/java/org/apache/hadoop/ozone/shell/TestResetDeletedBlockRetryCountShell.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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
- * <p/>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p/>
- * 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.ozone.shell;
-
-import org.apache.hadoop.hdds.conf.OzoneConfiguration;
-import org.apache.hadoop.hdds.scm.ScmConfigKeys;
-import org.apache.hadoop.hdds.scm.block.DeletedBlockLog;
-import org.apache.hadoop.hdds.scm.cli.ContainerOperationClient;
-import org.apache.hadoop.hdds.scm.server.StorageContainerManager;
-import org.apache.hadoop.ozone.MiniOzoneCluster;
-import org.apache.hadoop.ozone.MiniOzoneHAClusterImpl;
-import org.apache.hadoop.ozone.admin.scm.ResetDeletedBlockRetryCountSubcommand;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import picocli.CommandLine;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.UUID;
-import java.util.concurrent.TimeoutException;
-import java.util.stream.Collectors;
-
-import static
org.apache.hadoop.hdds.scm.ScmConfigKeys.OZONE_SCM_BLOCK_DELETION_MAX_RETRY;
-
-/**
- * Test for ResetDeletedBlockRetryCountSubcommand Cli.
- */
-public class TestResetDeletedBlockRetryCountShell {
-
- private static final Logger LOG = LoggerFactory
- .getLogger(TestResetDeletedBlockRetryCountShell.class);
- private MiniOzoneHAClusterImpl cluster = null;
- private OzoneConfiguration conf;
- private String clusterId;
- private String scmId;
- private String scmServiceId;
- private int numOfSCMs = 3;
-
- /**
- * Create a MiniOzoneHACluster for testing.
- *
- * @throws IOException
- */
- @BeforeEach
- public void init() throws Exception {
- conf = new OzoneConfiguration();
- clusterId = UUID.randomUUID().toString();
- scmId = UUID.randomUUID().toString();
- scmServiceId = "scm-service-test1";
-
- conf.setBoolean(ScmConfigKeys.OZONE_SCM_HA_ENABLE_KEY, true);
- conf.setInt(OZONE_SCM_BLOCK_DELETION_MAX_RETRY, 20);
-
- cluster = (MiniOzoneHAClusterImpl) MiniOzoneCluster.newOMHABuilder(conf)
- .setClusterId(clusterId)
- .setScmId(scmId)
- .setSCMServiceId(scmServiceId)
- .setNumOfStorageContainerManagers(numOfSCMs)
- .setNumOfActiveSCMs(numOfSCMs)
- .setNumOfOzoneManagers(1)
- .build();
- cluster.waitForClusterToBeReady();
- }
-
- /**
- * Shutdown MiniDFSCluster.
- */
- @AfterEach
- public void shutdown() {
- if (cluster != null) {
- cluster.shutdown();
- }
- }
-
- //<containerID, List<blockID>>
- private Map<Long, List<Long>> generateData(int dataSize) {
- Map<Long, List<Long>> blockMap = new HashMap<>();
- Random random = new Random(1);
- int continerIDBase = random.nextInt(100);
- int localIDBase = random.nextInt(1000);
- for (int i = 0; i < dataSize; i++) {
- long containerID = continerIDBase + i;
- List<Long> blocks = new ArrayList<>();
- for (int j = 0; j < 5; j++) {
- long localID = localIDBase + j;
- blocks.add(localID);
- }
- blockMap.put(containerID, blocks);
- }
- return blockMap;
- }
-
- private StorageContainerManager getSCMLeader() {
- return cluster.getStorageContainerManagersList()
- .stream().filter(a -> a.getScmContext().isLeaderReady())
- .collect(Collectors.toList()).get(0);
- }
-
- @Test
- public void testResetCmd() throws IOException, TimeoutException {
- int maxRetry = conf.getInt(OZONE_SCM_BLOCK_DELETION_MAX_RETRY, 20);
- // add some block deletion transactions
- DeletedBlockLog deletedBlockLog = getSCMLeader().
- getScmBlockManager().getDeletedBlockLog();
- deletedBlockLog.addTransactions(generateData(30));
- getSCMLeader().getScmHAManager().asSCMHADBTransactionBuffer().flush();
- LOG.info("Valid num of txns: {}", deletedBlockLog.
- getNumOfValidTransactions());
- Assertions.assertEquals(30, deletedBlockLog.getNumOfValidTransactions());
-
- List<Long> txIds = new ArrayList<>();
- for (int i = 1; i < 31; i++) {
- txIds.add((long) i);
- }
- // increment retry count than threshold, count will be set to -1
- for (int i = 0; i < maxRetry + 1; i++) {
- deletedBlockLog.incrementCount(txIds);
- }
- for (StorageContainerManager scm:
- cluster.getStorageContainerManagersList()) {
- scm.getScmHAManager().asSCMHADBTransactionBuffer().flush();
- }
- LOG.info("Valid num of txns: {}", deletedBlockLog.
- getNumOfValidTransactions());
- Assertions.assertEquals(0, deletedBlockLog.getNumOfValidTransactions());
-
- ResetDeletedBlockRetryCountSubcommand subcommand =
- new ResetDeletedBlockRetryCountSubcommand();
- ContainerOperationClient scmClient = new ContainerOperationClient(conf);
- CommandLine c = new CommandLine(subcommand);
- // reset the given txIds list, only these transactions should be available
- c.parseArgs("-l", "1,2,3,4,5");
- subcommand.execute(scmClient);
- getSCMLeader().getScmHAManager().asSCMHADBTransactionBuffer().flush();
- LOG.info("Valid num of txns: {}", deletedBlockLog.
- getNumOfValidTransactions());
- Assertions.assertEquals(5, deletedBlockLog.getNumOfValidTransactions());
-
- // reset all the result expired txIds, all transactions should be available
- c.parseArgs("-a");
- subcommand.execute(scmClient);
- getSCMLeader().getScmHAManager().asSCMHADBTransactionBuffer().flush();
- LOG.info("Valid num of txns: {}", deletedBlockLog.
- getNumOfValidTransactions());
- Assertions.assertEquals(30, deletedBlockLog.getNumOfValidTransactions());
- }
-}
diff --git
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/ScmAdmin.java
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/DeletedBlocksTxnCommands.java
similarity index 59%
copy from
hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/ScmAdmin.java
copy to
hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/DeletedBlocksTxnCommands.java
index 34cf3c7011..3473cd8d03 100644
---
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/ScmAdmin.java
+++
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/DeletedBlocksTxnCommands.java
@@ -19,50 +19,31 @@ package org.apache.hadoop.ozone.admin.scm;
import org.apache.hadoop.hdds.cli.GenericCli;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
-import org.apache.hadoop.hdds.cli.OzoneAdmin;
-import org.apache.hadoop.hdds.cli.SubcommandWithParent;
-import org.kohsuke.MetaInfServices;
import picocli.CommandLine;
-import picocli.CommandLine.Model.CommandSpec;
-import picocli.CommandLine.Spec;
+
+import java.util.concurrent.Callable;
/**
- * Subcommand for admin operations related to SCM.
+ * Subcommand to group container related operations.
*/
@CommandLine.Command(
- name = "scm",
- description = "Ozone Storage Container Manager specific admin operations",
+ name = "deletedBlocksTxn",
+ description = "SCM deleted blocks transaction specific operations",
mixinStandardHelpOptions = true,
versionProvider = HddsVersionProvider.class,
subcommands = {
- GetScmRatisRolesSubcommand.class,
- FinalizeScmUpgradeSubcommand.class,
- FinalizationScmStatusSubcommand.class,
+ GetFailedDeletedBlocksTxnSubcommand.class,
ResetDeletedBlockRetryCountSubcommand.class,
- TransferScmLeaderSubCommand.class
})
-@MetaInfServices(SubcommandWithParent.class)
-public class ScmAdmin extends GenericCli implements SubcommandWithParent {
-
- @CommandLine.ParentCommand
- private OzoneAdmin parent;
+public class DeletedBlocksTxnCommands implements Callable<Void> {
- @Spec
- private CommandSpec spec;
-
- public OzoneAdmin getParent() {
- return parent;
- }
+ @CommandLine.Spec
+ private CommandLine.Model.CommandSpec spec;
@Override
public Void call() throws Exception {
GenericCli.missingSubcommand(spec);
return null;
}
-
- @Override
- public Class<?> getParentType() {
- return OzoneAdmin.class;
- }
-
}
+
diff --git
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/GetFailedDeletedBlocksTxnSubcommand.java
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/GetFailedDeletedBlocksTxnSubcommand.java
new file mode 100644
index 0000000000..cad6c6c1a4
--- /dev/null
+++
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/GetFailedDeletedBlocksTxnSubcommand.java
@@ -0,0 +1,91 @@
+/*
+ * 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.ozone.admin.scm;
+
+import org.apache.hadoop.hdds.cli.HddsVersionProvider;
+import
org.apache.hadoop.hdds.protocol.proto.HddsProtos.DeletedBlocksTransactionInfo;
+import org.apache.hadoop.hdds.scm.cli.ScmSubcommand;
+import org.apache.hadoop.hdds.scm.client.ScmClient;
+import
org.apache.hadoop.hdds.scm.container.common.helpers.DeletedBlocksTransactionInfoWrapper;
+import org.apache.hadoop.hdds.server.JsonUtils;
+import picocli.CommandLine;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * Handler of getting expired deleted blocks from SCM side.
+ */
[email protected](
+ name = "ls",
+ description = "Print the failed DeletedBlocksTransaction(retry count =
-1)",
+ mixinStandardHelpOptions = true,
+ versionProvider = HddsVersionProvider.class)
+public class GetFailedDeletedBlocksTxnSubcommand extends ScmSubcommand {
+
+ @CommandLine.ArgGroup(multiplicity = "1")
+ private TransactionsOption group;
+
+ static class TransactionsOption {
+ @CommandLine.Option(names = {"-a", "--all"},
+ description = "Get all the failed transactions.")
+ private boolean getAll;
+
+ @CommandLine.Option(names = {"-c", "--count"},
+ defaultValue = "20",
+ description = "Get at most the count number of the" +
+ " failed transactions.")
+ private int count;
+ }
+
+ @CommandLine.Option(names = {"-s", "--startTxId"},
+ defaultValue = "0",
+ description = "The least transaction ID to start with, default 0." +
+ " Only work with -c/--count")
+ private long startTxId;
+
+ @CommandLine.Option(names = {"-o", "--out"},
+ description = "Print transactions into file in JSON format.")
+ private String fileName;
+
+ private static final int LIST_ALL_FAILED_TRANSACTIONS = -1;
+
+ @Override
+ public void execute(ScmClient client) throws IOException {
+ List<DeletedBlocksTransactionInfo> response;
+ int count = group.getAll ? LIST_ALL_FAILED_TRANSACTIONS : group.count;
+ response = client.getFailedDeletedBlockTxn(count, startTxId);
+ List<DeletedBlocksTransactionInfoWrapper> txns = response.stream()
+ .map(DeletedBlocksTransactionInfoWrapper::fromProtobuf)
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+
+ String result = JsonUtils.toJsonStringWithDefaultPrettyPrinter(txns);
+ if (fileName != null) {
+ try (FileOutputStream f = new FileOutputStream(fileName)) {
+ f.write(result.getBytes(StandardCharsets.UTF_8));
+ }
+ } else {
+ System.out.println(result);
+ }
+ }
+}
diff --git
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/ResetDeletedBlockRetryCountSubcommand.java
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/ResetDeletedBlockRetryCountSubcommand.java
index 7c91359e48..47a0ec2299 100644
---
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/ResetDeletedBlockRetryCountSubcommand.java
+++
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/ResetDeletedBlockRetryCountSubcommand.java
@@ -16,22 +16,32 @@
*/
package org.apache.hadoop.ozone.admin.scm;
+import com.google.gson.Gson;
+import com.google.gson.JsonIOException;
+import com.google.gson.JsonSyntaxException;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
import org.apache.hadoop.hdds.scm.cli.ScmSubcommand;
import org.apache.hadoop.hdds.scm.client.ScmClient;
+import
org.apache.hadoop.hdds.scm.container.common.helpers.DeletedBlocksTransactionInfoWrapper;
import picocli.CommandLine;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
-
+import java.util.stream.Collectors;
/**
- * Handler of the expired deleted blocks from SCM side.
+ * Handler of resetting expired deleted blocks from SCM side.
*/
@CommandLine.Command(
- name = "resetDeletedBlockRetryCount",
- description = "Reset deleted block transactions whose retry count is -1",
+ name = "reset",
+ description = "Reset the retry count of failed DeletedBlocksTransaction",
mixinStandardHelpOptions = true,
versionProvider = HddsVersionProvider.class)
public class ResetDeletedBlockRetryCountSubcommand extends ScmSubcommand {
@@ -41,25 +51,52 @@ public class ResetDeletedBlockRetryCountSubcommand extends
ScmSubcommand {
static class TransactionsOption {
@CommandLine.Option(names = {"-a", "--all"},
- description = "reset all expired deleted block transaction retry" +
+ description = "Reset all expired deleted block transaction retry" +
" count from -1 to 0.")
private boolean resetAll;
@CommandLine.Option(names = {"-l", "--list"},
split = ",",
- description = "reset the only given deletedBlock transaction ID" +
- " list, e.g 100,101,102.(Separated by ',')")
+ paramLabel = "txID",
+ description = "Reset the only given deletedBlock transaction ID" +
+ " list. Example: 100,101,102.(Separated by ',')")
private List<Long> txList;
- }
- @CommandLine.ParentCommand
- private ScmAdmin parent;
+ @CommandLine.Option(names = {"-i", "--in"},
+ description = "Use file as input, need to be JSON Array format and " +
+ "contains multi \"txID\" key. Example:
[{\"txID\":1},{\"txID\":2}]")
+ private String fileName;
+ }
@Override
public void execute(ScmClient client) throws IOException {
int count;
if (group.resetAll) {
count = client.resetDeletedBlockRetryCount(new ArrayList<>());
+ } else if (group.fileName != null) {
+ Gson gson = new Gson();
+ List<Long> txIDs;
+ try (InputStream in = new FileInputStream(group.fileName);
+ Reader fileReader = new InputStreamReader(in,
+ StandardCharsets.UTF_8)) {
+ DeletedBlocksTransactionInfoWrapper[] txns = gson.fromJson(fileReader,
+ DeletedBlocksTransactionInfoWrapper[].class);
+ txIDs = Arrays.stream(txns)
+ .map(DeletedBlocksTransactionInfoWrapper::getTxID)
+ .sorted()
+ .distinct()
+ .collect(Collectors.toList());
+ System.out.println("Num of loaded txIDs: " + txIDs.size());
+ if (!txIDs.isEmpty()) {
+ System.out.println("The first loaded txID: " + txIDs.get(0));
+ System.out.println("The last loaded txID: " +
+ txIDs.get(txIDs.size() - 1));
+ }
+ } catch (JsonIOException | JsonSyntaxException | IOException ex) {
+ System.out.println("Cannot parse the file " + group.fileName);
+ throw new IOException(ex);
+ }
+ count = client.resetDeletedBlockRetryCount(txIDs);
} else {
if (group.txList == null || group.txList.isEmpty()) {
System.out.println("TransactionId list should not be empty");
diff --git
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/ScmAdmin.java
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/ScmAdmin.java
index 34cf3c7011..a7f96dee84 100644
---
a/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/ScmAdmin.java
+++
b/hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/admin/scm/ScmAdmin.java
@@ -38,8 +38,8 @@ import picocli.CommandLine.Spec;
GetScmRatisRolesSubcommand.class,
FinalizeScmUpgradeSubcommand.class,
FinalizationScmStatusSubcommand.class,
- ResetDeletedBlockRetryCountSubcommand.class,
- TransferScmLeaderSubCommand.class
+ TransferScmLeaderSubCommand.class,
+ DeletedBlocksTxnCommands.class
})
@MetaInfServices(SubcommandWithParent.class)
public class ScmAdmin extends GenericCli implements SubcommandWithParent {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]