HDFS-12795. Ozone: SCM: Support for Container LifeCycleState PENDING_CLOSE and LifeCycleEvent FULL_CONTAINER. Contributed by Nandakumar.

This commit is contained in:
Anu Engineer 2017-12-18 18:48:12 -08:00 committed by Owen O'Malley
parent 26e270b908
commit 966853894f
4 changed files with 75 additions and 20 deletions

View File

@ -104,19 +104,21 @@ enum LifeCycleState {
ALLOCATED = 1;
CREATING = 2; // Used for container allocated/created by different client.
OPEN =3; // Mostly an update to SCM via HB or client call.
CLOSED = 4; // !!State after this has not been used yet.
DELETING = 5;
DELETED = 6; // object is deleted.
PENDING_CLOSE = 4;
CLOSED = 5; // !!State after this has not been used yet.
DELETING = 6;
DELETED = 7; // object is deleted.
}
enum LifeCycleEvent {
BEGIN_CREATE = 1; // A request to client to create this object
COMPLETE_CREATE = 2;
CLOSE = 3; // !!Event after this has not been used yet.
UPDATE = 4;
TIMEOUT = 5; // creation has timed out from SCM's View.
DELETE = 6;
CLEANUP = 7;
FULL_CONTAINER = 3;
CLOSE = 4; // !!Event after this has not been used yet.
UPDATE = 5;
TIMEOUT = 6; // creation has timed out from SCM's View.
DELETE = 7;
CLEANUP = 8;
}
message SCMContainerInfo {

View File

@ -56,6 +56,7 @@ import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static org.apache.hadoop.ozone.OzoneConsts.CONTAINER_DB;
import static org.apache.hadoop.ozone.scm.exceptions.SCMException.ResultCodes.FAILED_TO_CHANGE_CONTAINER_STATE;
/**
* Mapping class contains the mapping from a name to a pipeline mapping. This
@ -296,8 +297,8 @@ public class ContainerMapping implements Mapping {
.parseFrom(containerBytes));
Preconditions.checkNotNull(containerInfo);
if (event == OzoneProtos.LifeCycleEvent.BEGIN_CREATE) {
switch (event) {
case BEGIN_CREATE:
// Acquire lease on container
Lease<ContainerInfo> containerLease =
containerLeaseManager.acquire(containerInfo);
@ -307,10 +308,30 @@ public class ContainerMapping implements Mapping {
OzoneProtos.LifeCycleEvent.TIMEOUT);
return null;
});
} else if (event == OzoneProtos.LifeCycleEvent.COMPLETE_CREATE) {
break;
case COMPLETE_CREATE:
// Release the lease on container
containerLeaseManager.release(containerInfo);
break;
case TIMEOUT:
break;
case CLEANUP:
break;
case FULL_CONTAINER:
break;
case CLOSE:
break;
case UPDATE:
break;
case DELETE:
break;
default:
throw new SCMException("Unsupported container LifeCycleEvent.",
FAILED_TO_CHANGE_CONTAINER_STATE);
}
// If the below updateContainerState call fails, we should revert the
// changes made in switch case.
// Like releasing the lease in case of BEGIN_CREATE.
ContainerInfo updatedContainer = containerStateManager
.updateContainerState(containerInfo, event);
containerStore.put(dbKey, updatedContainer.getProtobuf().toByteArray());
@ -383,16 +404,13 @@ public class ContainerMapping implements Mapping {
// Close container implementation can decide on how to maintain
// list of containers to be closed, this is the place where we
// have to add the containers to that list.
ContainerInfo updatedContainer =
containerStateManager.updateContainerState(
ContainerInfo.fromProtobuf(newContainerInfo),
OzoneProtos.LifeCycleEvent.CLOSE);
if (updatedContainer.getState() !=
OzoneProtos.LifeCycleState.CLOSED) {
OzoneProtos.LifeCycleState state = updateContainerState(
ContainerInfo.fromProtobuf(newContainerInfo).getContainerName(),
OzoneProtos.LifeCycleEvent.FULL_CONTAINER);
if (state != OzoneProtos.LifeCycleState.PENDING_CLOSE) {
LOG.error("Failed to close container {}, reason : Not able to " +
"update container state, current container state: {}." +
"in state {}", containerInfo.getContainerName(),
updatedContainer.getState());
"in state {}", containerInfo.getContainerName(), state);
}
}
} else {

View File

@ -251,11 +251,14 @@ public class ContainerStateManager implements Closeable {
// DELETING----------------->[DELETED]
// (CLEANUP)
// SCM Open/Close State Machine
// States: OPEN------------------>PENDING_CLOSE---------->[CLOSE]
// States: OPEN------------------>PENDING_CLOSE---------->[CLOSED]
// Events: (FULL_CONTAINER) (CLOSE)
// Delete State Machine
// States: OPEN------------------>DELETING------------------>[DELETED]
// Events: (DELETE) (CLEANUP)
// Should we allow DELETING of OPEN containers? we can always have
// OPEN--------->PENDING_CLOSE----->CLOSE---->DELETING---->[DELETED]
private void initializeStateMachine() {
stateMachine.addTransition(LifeCycleState.ALLOCATED,
LifeCycleState.CREATING,
@ -266,6 +269,10 @@ public class ContainerStateManager implements Closeable {
LifeCycleEvent.COMPLETE_CREATE);
stateMachine.addTransition(LifeCycleState.OPEN,
LifeCycleState.PENDING_CLOSE,
LifeCycleEvent.FULL_CONTAINER);
stateMachine.addTransition(LifeCycleState.PENDING_CLOSE,
LifeCycleState.CLOSED,
LifeCycleEvent.CLOSE);

View File

@ -264,6 +264,34 @@ public class TestContainerMapping {
ContainerInfo updatedContainer = mapping.getContainer(containerName);
Assert.assertEquals(500000000L, updatedContainer.getNumberOfKeys());
Assert.assertEquals(5368705120L, updatedContainer.getUsedBytes());
List<ContainerInfo> pendingCloseContainers = mapping.getStateManager()
.getMatchingContainers(
OzoneProtos.Owner.OZONE,
xceiverClientManager.getType(),
xceiverClientManager.getFactor(),
OzoneProtos.LifeCycleState.PENDING_CLOSE);
Assert.assertTrue(pendingCloseContainers.stream().map(
container -> container.getContainerName()).collect(
Collectors.toList()).contains(containerName));
}
@Test
public void testCloseContainer() throws IOException {
String containerName = UUID.randomUUID().toString();
createContainer(containerName);
mapping.updateContainerState(containerName,
OzoneProtos.LifeCycleEvent.FULL_CONTAINER);
List<ContainerInfo> pendingCloseContainers = mapping.getStateManager()
.getMatchingContainers(
OzoneProtos.Owner.OZONE,
xceiverClientManager.getType(),
xceiverClientManager.getFactor(),
OzoneProtos.LifeCycleState.PENDING_CLOSE);
Assert.assertTrue(pendingCloseContainers.stream().map(
container -> container.getContainerName()).collect(
Collectors.toList()).contains(containerName));
mapping.updateContainerState(containerName,
OzoneProtos.LifeCycleEvent.CLOSE);
List<ContainerInfo> closeContainers = mapping.getStateManager()
.getMatchingContainers(
OzoneProtos.Owner.OZONE,