hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/block/BlockManagerImpl.java
@Override
  public AllocatedBlock allocateBlock(final long size,
      ReplicationType type, ReplicationFactor factor, String owner)
      throws IOException {
    LOG.trace("Size;{} , type : {}, factor : {} ", size, type, factor);

    if (size < 0 || size > containerSize) {
      LOG.warn("Invalid block size requested : {}", size);
      throw new SCMException("Unsupported block size: " + size,
          INVALID_BLOCK_SIZE);
    }

    if (!nodeManager.isOutOfChillMode()) {
      LOG.warn("Not out of Chill mode.");
      throw new SCMException("Unable to create block while in chill mode",
          CHILL_MODE_EXCEPTION);
    }

    lock.lock();
    try {
      /*
               Here is the high level logic.

               1. First we check if there are containers in ALLOCATED state,
               that is
                SCM has allocated them in the SCM namespace but the
                corresponding
                container has not been created in the Datanode yet. If we
                have any
                in that state, we will return that to the client, which allows
                client to finish creating those containers. This is a sort of
                 greedy
                 algorithm, our primary purpose is to get as many containers as
                 possible.

                2. If there are no allocated containers -- Then we find a Open
                container that matches that pattern.

                3. If both of them fail, the we will pre-allocate a bunch of
                conatainers in SCM and try again.

               TODO : Support random picking of two containers from the list.
                So we
               can use different kind of policies.
      */

      ContainerInfo containerInfo;

      // Look for ALLOCATED container that matches all other parameters.
      containerInfo =
          containerManager
              .getStateManager()
              .getMatchingContainer(
                  size, owner, type, factor, HddsProtos.LifeCycleState
                      .ALLOCATED);
      if (containerInfo != null) {
        containerManager.updateContainerState(containerInfo.getContainerName(),
            HddsProtos.LifeCycleEvent.CREATE);
        return newBlock(containerInfo, HddsProtos.LifeCycleState.ALLOCATED);
      }

      // Since we found no allocated containers that match our criteria, let us
      // look for OPEN containers that match the criteria.
      containerInfo =
          containerManager
              .getStateManager()
              .getMatchingContainer(size, owner, type, factor, HddsProtos
                  .LifeCycleState.OPEN);
      if (containerInfo != null) {
        return newBlock(containerInfo, HddsProtos.LifeCycleState.OPEN);
      }

      // We found neither ALLOCATED or OPEN Containers. This generally means
      // that most of our containers are full or we have not allocated
      // containers of the type and replication factor. So let us go and
      // allocate some.
      preAllocateContainers(containerProvisionBatchSize, type, factor, owner);

      // Since we just allocated a set of containers this should work
      containerInfo =
          containerManager
              .getStateManager()
              .getMatchingContainer(
                  size, owner, type, factor, HddsProtos.LifeCycleState
                      .ALLOCATED);
      if (containerInfo != null) {
        containerManager.updateContainerState(containerInfo.getContainerName(),
            HddsProtos.LifeCycleEvent.CREATE);
        return newBlock(containerInfo, HddsProtos.LifeCycleState.ALLOCATED);
      }

      // we have tried all strategies we know and but somehow we are not able
      // to get a container for this block. Log that info and return a null.
      LOG.error(
          "Unable to allocate a block for the size: {}, type: {}, " +
              "factor: {}",
          size,
          type,
          factor);
      return null;
    } finally {
      lock.unlock();
    }
  }
/**
   * Allocates a block in a container and returns that info.
   *
   * @param size - Block Size
   * @param type Replication Type
   * @param factor - Replication Factor
   * @return Allocated block
   * @throws IOException on failure.
   */
Allocates a block in a container and returns that info.
Allocates a block in a container and returns that info .
@Override
  public AllocatedBlock allocateBlock(final long size,
      ReplicationType type, ReplicationFactor factor, String owner)
      throws IOException {
    LOG.trace("Size;{} , type : {}, factor : {} ", size, type, factor);
    if (size < 0 || size > containerSize) {
      LOG.warn("Invalid block size requested : {}", size);
      throw new SCMException("Unsupported block size: " + size,
          INVALID_BLOCK_SIZE);
    }
    if (!nodeManager.isOutOfChillMode()) {
      LOG.warn("Not out of Chill mode.");
      throw new SCMException("Unable to create block while in chill mode",
          CHILL_MODE_EXCEPTION);
    }
    lock.lock();
    try {
      /*
               Here is the high level logic.
               1. First we check if there are containers in ALLOCATED state,
               that is
                SCM has allocated them in the SCM namespace but the
                corresponding
                container has not been created in the Datanode yet. If we
                have any
                in that state, we will return that to the client, which allows
                client to finish creating those containers. This is a sort of
                 greedy
                 algorithm, our primary purpose is to get as many containers as
                 possible.
                2. If there are no allocated containers -- Then we find a Open
                container that matches that pattern.
                3. If both of them fail, the we will pre-allocate a bunch of
                conatainers in SCM and try again.
               TODO : Support random picking of two containers from the list.
                So we
               can use different kind of policies.
      */
      ContainerInfo containerInfo;
      containerInfo =
          containerManager
              .getStateManager()
              .getMatchingContainer(
                  size, owner, type, factor, HddsProtos.LifeCycleState
                      .ALLOCATED);
      if (containerInfo != null) {
        containerManager.updateContainerState(containerInfo.getContainerName(),
            HddsProtos.LifeCycleEvent.CREATE);
        return newBlock(containerInfo, HddsProtos.LifeCycleState.ALLOCATED);
      }
      containerInfo =
          containerManager
              .getStateManager()
              .getMatchingContainer(size, owner, type, factor, HddsProtos
                  .LifeCycleState.OPEN);
      if (containerInfo != null) {
        return newBlock(containerInfo, HddsProtos.LifeCycleState.OPEN);
      }
      preAllocateContainers(containerProvisionBatchSize, type, factor, owner);
      containerInfo =
          containerManager
              .getStateManager()
              .getMatchingContainer(
                  size, owner, type, factor, HddsProtos.LifeCycleState
                      .ALLOCATED);
      if (containerInfo != null) {
        containerManager.updateContainerState(containerInfo.getContainerName(),
            HddsProtos.LifeCycleEvent.CREATE);
        return newBlock(containerInfo, HddsProtos.LifeCycleState.ALLOCATED);
      }
      LOG.error(
          "Unable to allocate a block for the size: {}, type: {}, " +
              "factor: {}",
          size,
          type,
          factor);
      return null;
    } finally {
      lock.unlock();
    }
  }
@ Override public AllocatedBlock allocateBlock ( final long size , ReplicationType type , ReplicationFactor factor , String owner ) throws IOException { LOG . trace ( "Size;{} , type : {}, factor : {} " , size , type , factor ) ; if ( size < 0 || size > containerSize ) { LOG . warn ( "Invalid block size requested : {}" , size ) ; throw new SCMException ( "Unsupported block size: " + size , INVALID_BLOCK_SIZE ) ; } if ( ! nodeManager . isOutOfChillMode ( ) ) { LOG . warn ( "Not out of Chill mode." ) ; throw new SCMException ( "Unable to create block while in chill mode" , CHILL_MODE_EXCEPTION ) ; } lock . lock ( ) ; try { /*
               Here is the high level logic.

               1. First we check if there are containers in ALLOCATED state,
               that is
                SCM has allocated them in the SCM namespace but the
                corresponding
                container has not been created in the Datanode yet. If we
                have any
                in that state, we will return that to the client, which allows
                client to finish creating those containers. This is a sort of
                 greedy
                 algorithm, our primary purpose is to get as many containers as
                 possible.

                2. If there are no allocated containers -- Then we find a Open
                container that matches that pattern.

                3. If both of them fail, the we will pre-allocate a bunch of
                conatainers in SCM and try again.

               TODO : Support random picking of two containers from the list.
                So we
               can use different kind of policies.
      */ ContainerInfo containerInfo ; containerInfo = containerManager . getStateManager ( ) . getMatchingContainer ( size , owner , type , factor , HddsProtos . LifeCycleState . ALLOCATED ) ; if ( containerInfo != null ) { containerManager . updateContainerState ( containerInfo . getContainerName ( ) , HddsProtos . LifeCycleEvent . CREATE ) ; return newBlock ( containerInfo , HddsProtos . LifeCycleState . ALLOCATED ) ; } containerInfo = containerManager . getStateManager ( ) . getMatchingContainer ( size , owner , type , factor , HddsProtos . LifeCycleState . OPEN ) ; if ( containerInfo != null ) { return newBlock ( containerInfo , HddsProtos . LifeCycleState . OPEN ) ; } preAllocateContainers ( containerProvisionBatchSize , type , factor , owner ) ; containerInfo = containerManager . getStateManager ( ) . getMatchingContainer ( size , owner , type , factor , HddsProtos . LifeCycleState . ALLOCATED ) ; if ( containerInfo != null ) { containerManager . updateContainerState ( containerInfo . getContainerName ( ) , HddsProtos . LifeCycleEvent . CREATE ) ; return newBlock ( containerInfo , HddsProtos . LifeCycleState . ALLOCATED ) ; } LOG . error ( "Unable to allocate a block for the size: {}, type: {}, " + "factor: {}" , size , type , factor ) ; return null ; } finally { lock . unlock ( ) ; } }
Allocates a block in a container and returns that info.
Allocates a block in a container and returns that info .
// Look for ALLOCATED container that matches all other parameters. // Since we found no allocated containers that match our criteria, let us // look for OPEN containers that match the criteria. // We found neither ALLOCATED or OPEN Containers. This generally means // that most of our containers are full or we have not allocated // containers of the type and replication factor. So let us go and // allocate some. // Since we just allocated a set of containers this should work // we have tried all strategies we know and but somehow we are not able // to get a container for this block. Log that info and return a null.