Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2cb1635
HDDS-4404. Datanode can go OOM when a Recon or SCM Server is very slo…
smengcl Nov 19, 2020
3e53bf8
Checkstyle.
smengcl Nov 19, 2020
024a4f8
Add mock-maker-inline so UT can mock final classes.
smengcl Nov 19, 2020
22846f4
Remove throw exception in addReport.
smengcl Nov 19, 2020
878d271
Fix existing UT TestStateContext#testReportAPIs.
smengcl Nov 19, 2020
5b2bbd3
Remove unused imports.
smengcl Nov 19, 2020
2fcb2b6
Work around mockito bug in UT TestCreatePipelineCommandHandler: cause…
smengcl Nov 20, 2020
c403208
Add UT testContainerNodePipelineReportAPIs.
smengcl Nov 20, 2020
23d25cb
Clean up.
smengcl Nov 20, 2020
50b9a5e
@VisibleForTesting for get container/node/pipeline reports as they ar…
smengcl Nov 23, 2020
6f3ea18
- Renamed `reports` to `incrementalReportsQueue` to better reflect th…
smengcl Nov 24, 2020
9718488
Make containerReports, nodeReport, pipelineReports atomic and final.
smengcl Nov 24, 2020
7988203
Checkstyle.
smengcl Nov 24, 2020
fdc5823
Clean up.
smengcl Nov 24, 2020
3a32e8b
Remove assertion in putBackReports as requestBuilder might include Co…
smengcl Nov 30, 2020
84e8f74
Empty commit to retrigger CI.
smengcl Dec 1, 2020
02298d9
Empty commit to retrigger CI.
smengcl Dec 7, 2020
63a89ab
Retrigger.
smengcl Dec 7, 2020
c64f247
Merge branch 'master' into HDDS-4404-v2
smengcl Dec 8, 2020
34283ca
Allow null as input to StateContext#addReport() as this blocked UT Te…
smengcl Dec 9, 2020
ab37c22
Retrigger CI
smengcl Dec 10, 2020
f0dca47
trigger new CI check
adoroszlai Dec 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,13 @@
import com.google.common.annotations.VisibleForTesting;
import org.apache.hadoop.hdds.conf.ConfigurationSource;
import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.CommandStatus.Status;
import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.CommandStatusReportsProto;
import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerAction;
import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.ContainerReportsProto;
import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.IncrementalContainerReportProto;
import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.NodeReportProto;
import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineAction;
import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.PipelineReportsProto;
import org.apache.hadoop.hdds.protocol.proto.StorageContainerDatanodeProtocolProtos.SCMCommandProto;
import org.apache.hadoop.ozone.container.common.states.DatanodeState;
import org.apache.hadoop.ozone.container.common.states.datanode.InitDatanodeState;
Expand Down Expand Up @@ -72,6 +77,11 @@ public class StateContext {
private final AtomicLong stateExecutionCount;
private final ConfigurationSource conf;
private final Set<InetSocketAddress> endpoints;
// Only keeps the latest Container/Node/PipelineReport
private GeneratedMessage containerReport;
private GeneratedMessage nodeReport;
private GeneratedMessage pipelineReport;
// CommandStatusReport and IncrementalContainerReport queued in the map below
private final Map<InetSocketAddress, List<GeneratedMessage>> reports;
private final Map<InetSocketAddress, Queue<ContainerAction>> containerActions;
private final Map<InetSocketAddress, Queue<PipelineAction>> pipelineActions;
Expand All @@ -80,6 +90,17 @@ public class StateContext {
private boolean shutdownGracefully = false;
private final AtomicLong threadPoolNotAvailableCount;

private static final String containerReportsProtoName =
ContainerReportsProto.getDescriptor().getFullName();
private static final String nodeReportProtoName =
NodeReportProto.getDescriptor().getFullName();
private static final String pipelineReportsProtoName =
PipelineReportsProto.getDescriptor().getFullName();
private static final String commandStatusReportsProtoName =
CommandStatusReportsProto.getDescriptor().getFullName();
private static final String incrementalContainerReportProtoName =
IncrementalContainerReportProto.getDescriptor().getFullName();

/**
* Starting with a 2 sec heartbeat frequency which will be updated to the
* real HB frequency after scm registration. With this method the
Expand All @@ -103,6 +124,12 @@ public StateContext(ConfigurationSource conf,
commandQueue = new LinkedList<>();
cmdStatusMap = new ConcurrentHashMap<>();
reports = new HashMap<>();
// TODO: Even better, is there a way to initialize those as
// empty GeneratedMessage? In protobuf 3 there is Empty.Builder, not in 2?
containerReport = null;
nodeReport = null;
pipelineReport = null;

endpoints = new HashSet<>();
containerActions = new HashMap<>();
pipelineActions = new HashMap<>();
Expand Down Expand Up @@ -190,16 +217,32 @@ void setShutdownGracefully() {
public boolean getShutdownOnError() {
return shutdownOnError;
}

/**
* Adds the report to report queue.
*
* @param report report to be added
*/
public void addReport(GeneratedMessage report) {
if (report != null) {
synchronized (reports) {
for (InetSocketAddress endpoint : endpoints) {
reports.get(endpoint).add(report);
final String reportType = report.getDescriptorForType().getFullName();
for (InetSocketAddress endpoint : endpoints) {
// Check report type
if (reportType.equals(containerReportsProtoName)) {
containerReport = report;
} else if (reportType.equals(nodeReportProtoName)) {
nodeReport = report;
} else if (reportType.equals(pipelineReportsProtoName)) {
pipelineReport = report;
} else if (reportType.equals(commandStatusReportsProtoName) ||
reportType.equals(incrementalContainerReportProtoName)) {
// report type is CommandStatusReports or IncrementalContainerReport
synchronized (reports) {
reports.get(endpoint).add(report);
Comment thread
smengcl marked this conversation as resolved.
Outdated
}
} else {
throw new IllegalArgumentException(
"Unidentified report message type: " + reportType);
}
}
}
Expand Down Expand Up @@ -241,6 +284,15 @@ public List<GeneratedMessage> getAllAvailableReports(
public List<GeneratedMessage> getReports(InetSocketAddress endpoint,
int maxLimit) {
List<GeneratedMessage> reportsToReturn = new LinkedList<>();
if (containerReport != null) {
reportsToReturn.add(containerReport);
}
if (nodeReport != null) {
reportsToReturn.add(nodeReport);
}
if (pipelineReport != null) {
reportsToReturn.add(pipelineReport);
}
synchronized (reports) {
List<GeneratedMessage> reportsForEndpoint = reports.get(endpoint);
if (reportsForEndpoint != null) {
Expand Down Expand Up @@ -583,4 +635,16 @@ public void addEndpoint(InetSocketAddress endpoint) {
this.reports.put(endpoint, new LinkedList<>());
}
}

public GeneratedMessage getContainerReport() {
return containerReport;
}

public GeneratedMessage getNodeReport() {
return nodeReport;
}

public GeneratedMessage getPipelineReport() {
return pipelineReport;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,15 @@ public EndpointStateMachine.EndPointStates call() throws Exception {
if (LOG.isDebugEnabled()) {
LOG.debug("Sending heartbeat message :: {}", request.toString());
}
SCMHeartbeatResponseProto reponse = rpcEndpoint.getEndPoint()
SCMHeartbeatResponseProto response = rpcEndpoint.getEndPoint()
.sendHeartbeat(request);
processResponse(reponse, datanodeDetailsProto);
processResponse(response, datanodeDetailsProto);
rpcEndpoint.setLastSuccessfulHeartbeat(ZonedDateTime.now());
rpcEndpoint.zeroMissedCount();
} catch (IOException ex) {
Preconditions.checkState(requestBuilder != null);
// put back the reports which failed to be sent
putBackReports(requestBuilder);

rpcEndpoint.logIfNeeded(ex);
} finally {
rpcEndpoint.unlock();
Expand All @@ -160,12 +160,9 @@ public EndpointStateMachine.EndPointStates call() throws Exception {
// TODO: Make it generic.
private void putBackReports(SCMHeartbeatRequestProto.Builder requestBuilder) {
List<GeneratedMessage> reports = new LinkedList<>();
if (requestBuilder.hasContainerReport()) {
reports.add(requestBuilder.getContainerReport());
}
if (requestBuilder.hasNodeReport()) {
reports.add(requestBuilder.getNodeReport());
}
// We only put back CommandStatusReports and IncrementalContainerReport
// because those are incremental. Container/Node/PipelineReport are
// accumulative so we can keep only the latest of each.
if (requestBuilder.getCommandStatusReportsCount() != 0) {
reports.addAll(requestBuilder.getCommandStatusReportsList());
}
Expand All @@ -184,15 +181,30 @@ private void addReports(SCMHeartbeatRequestProto.Builder requestBuilder) {
for (GeneratedMessage report :
context.getAllAvailableReports(rpcEndpoint.getAddress())) {
String reportName = report.getDescriptorForType().getFullName();
// Example reportName = hadoop.hdds.NodeReportProto

for (Descriptors.FieldDescriptor descriptor :
SCMHeartbeatRequestProto.getDescriptor().getFields()) {

String heartbeatFieldName = descriptor.getMessageType().getFullName();
// Possible heartbeatFieldName =
// hadoop.hdds.DatanodeDetailsProto
// hadoop.hdds.NodeReportProto
// hadoop.hdds.ContainerReportsProto
// hadoop.hdds.IncrementalContainerReportProto
// hadoop.hdds.CommandStatusReportsProto
// hadoop.hdds.ContainerActionsProto
// hadoop.hdds.PipelineActionsProto
// hadoop.hdds.PipelineReportsProto
if (heartbeatFieldName.equals(reportName)) {
if (descriptor.isRepeated()) {
requestBuilder.addRepeatedField(descriptor, report);
} else {
requestBuilder.setField(descriptor, report);
}
// TODO: We can exit loop early here since we have a match already,
// right? Double check.
break;
Comment thread
avijayanhwx marked this conversation as resolved.
}
}
}
Expand Down