use of org.apache.hadoop.hdds.scm.metadata.Replicate in project ozone by apache.
the class ReplicationManager method handleUnderReplicatedContainer.
/**
* If the given container is under replicated, identify a new set of
* datanode(s) to replicate the container using PlacementPolicy
* and send replicate container command to the identified datanode(s).
*
* @param container ContainerInfo
* @param replicaSet An instance of ContainerReplicaCount, containing the
* current replica count and inflight adds and deletes
*/
private void handleUnderReplicatedContainer(final ContainerInfo container, final ContainerReplicaCount replicaSet, final ContainerPlacementStatus placementStatus) {
LOG.debug("Handling under-replicated container: {}", container);
Set<ContainerReplica> replicas = replicaSet.getReplica();
try {
if (replicaSet.isSufficientlyReplicated() && placementStatus.isPolicySatisfied()) {
LOG.info("The container {} with replicas {} is sufficiently " + "replicated and is not mis-replicated", container.getContainerID(), replicaSet);
return;
}
int repDelta = replicaSet.additionalReplicaNeeded();
final ContainerID id = container.containerID();
final List<DatanodeDetails> deletionInFlight = inflightDeletion.getOrDefault(id, Collections.emptyList()).stream().map(action -> action.datanode).collect(Collectors.toList());
final List<DatanodeDetails> replicationInFlight = inflightReplication.getOrDefault(id, Collections.emptyList()).stream().map(action -> action.datanode).collect(Collectors.toList());
final List<DatanodeDetails> source = replicas.stream().filter(r -> r.getState() == State.QUASI_CLOSED || r.getState() == State.CLOSED).filter(r -> getNodeStatus(r.getDatanodeDetails()).isHealthy()).filter(r -> !deletionInFlight.contains(r.getDatanodeDetails())).sorted((r1, r2) -> r2.getSequenceId().compareTo(r1.getSequenceId())).map(ContainerReplica::getDatanodeDetails).collect(Collectors.toList());
if (source.size() > 0) {
final int replicationFactor = container.getReplicationConfig().getRequiredNodes();
// Want to check if the container is mis-replicated after considering
// inflight add and delete.
// Create a new list from source (healthy replicas minus pending delete)
List<DatanodeDetails> targetReplicas = new ArrayList<>(source);
// Then add any pending additions
targetReplicas.addAll(replicationInFlight);
final ContainerPlacementStatus inFlightplacementStatus = containerPlacement.validateContainerPlacement(targetReplicas, replicationFactor);
final int misRepDelta = inFlightplacementStatus.misReplicationCount();
final int replicasNeeded = repDelta < misRepDelta ? misRepDelta : repDelta;
if (replicasNeeded <= 0) {
LOG.debug("Container {} meets replication requirement with " + "inflight replicas", id);
return;
}
// We should ensure that the target datanode has enough space
// for a complete container to be created, but since the container
// size may be changed smaller than origin, we should be defensive.
final long dataSizeRequired = Math.max(container.getUsedBytes(), currentContainerSize);
final List<DatanodeDetails> excludeList = replicas.stream().map(ContainerReplica::getDatanodeDetails).collect(Collectors.toList());
excludeList.addAll(replicationInFlight);
final List<DatanodeDetails> selectedDatanodes = containerPlacement.chooseDatanodes(excludeList, null, replicasNeeded, 0, dataSizeRequired);
if (repDelta > 0) {
LOG.info("Container {} is under replicated. Expected replica count" + " is {}, but found {}.", id, replicationFactor, replicationFactor - repDelta);
}
int newMisRepDelta = misRepDelta;
if (misRepDelta > 0) {
LOG.info("Container: {}. {}", id, placementStatus.misReplicatedReason());
// Check if the new target nodes (original plus newly selected nodes)
// makes the placement policy valid.
targetReplicas.addAll(selectedDatanodes);
newMisRepDelta = containerPlacement.validateContainerPlacement(targetReplicas, replicationFactor).misReplicationCount();
}
if (repDelta > 0 || newMisRepDelta < misRepDelta) {
// improves things.
for (DatanodeDetails datanode : selectedDatanodes) {
sendReplicateCommand(container, datanode, source);
}
} else {
LOG.warn("Container {} is mis-replicated, requiring {} additional " + "replicas. After selecting new nodes, mis-replication has not " + "improved. No additional replicas will be scheduled", id, misRepDelta);
}
} else {
LOG.warn("Cannot replicate container {}, no healthy replica found.", container.containerID());
}
} catch (IOException | IllegalStateException ex) {
LOG.warn("Exception while replicating container {}.", container.getContainerID(), ex);
}
}
use of org.apache.hadoop.hdds.scm.metadata.Replicate in project ozone by apache.
the class ReplicationManager method handleUnstableContainer.
/**
* Handles unstable container.
* A container is inconsistent if any of the replica state doesn't
* match the container state. We have to take appropriate action
* based on state of the replica.
*
* @param container ContainerInfo
* @param replicas Set of ContainerReplicas
*/
private void handleUnstableContainer(final ContainerInfo container, final Set<ContainerReplica> replicas) {
// Find unhealthy replicas
List<ContainerReplica> unhealthyReplicas = replicas.stream().filter(r -> !compareState(container.getState(), r.getState())).collect(Collectors.toList());
Iterator<ContainerReplica> iterator = unhealthyReplicas.iterator();
while (iterator.hasNext()) {
final ContainerReplica replica = iterator.next();
final State state = replica.getState();
if (state == State.OPEN || state == State.CLOSING) {
sendCloseCommand(container, replica.getDatanodeDetails(), false);
iterator.remove();
}
if (state == State.QUASI_CLOSED) {
// Send force close command if the BCSID matches
if (container.getSequenceId() == replica.getSequenceId()) {
sendCloseCommand(container, replica.getDatanodeDetails(), true);
iterator.remove();
}
}
}
// Now we are left with the replicas which are either unhealthy or
// the BCSID doesn't match. These replicas should be deleted.
/*
* If we have unhealthy replicas we go under replicated and then
* replicate the healthy copy.
*
* We also make sure that we delete only one unhealthy replica at a time.
*
* If there are two unhealthy replica:
* - Delete first unhealthy replica
* - Re-replicate the healthy copy
* - Delete second unhealthy replica
* - Re-replicate the healthy copy
*
* Note: Only one action will be executed in a single ReplicationMonitor
* iteration. So to complete all the above actions we need four
* ReplicationMonitor iterations.
*/
unhealthyReplicas.stream().findFirst().ifPresent(replica -> sendDeleteCommand(container, replica.getDatanodeDetails(), false));
}
Aggregations