@Override
    public void onPartitionBecomeBootstrapFromOffline(@Nonnull String partitionName) {
      logger.info("Bootstrap Controller's state change listener invoked for partition `{}`, "
              + "state change `Offline -> Bootstrap`", partitionName);

      ReplicaId replica = storeManager.getReplica(partitionName);
      PartitionStateChangeListener listenerToInvoke = null;

      if (null == replica) {
        if (isFileCopyFeatureEnabled()) {
          // "New partition -> FC"
          // This is a new partition placement and FileCopy bootstrap protocol is enabled.
          listenerToInvoke = fileCopyManagerListener;

          replicationProtocolTransitionType = EnumSet.of(
              ReplicationProtocolTransitionType.NEW_PARTITION_TO_FILE_BASED_HYDRATION);
          logStateChange("New partition -> FC", partitionName);
        } else {
          // "New partition -> R"
          // This is a new partition placement and FileCopy bootstrap protocol is disabled.
          listenerToInvoke = storageManagerListener;

          replicationProtocolTransitionType = EnumSet.of(
              ReplicationProtocolTransitionType.NEW_PARTITION_TO_BLOB_BASED_HYDRATION);
          logStateChange("New partition -> R", partitionName);
        }
      } else {
        if (isFileCopyFeatureEnabled()) {
          if (isFileExists(replica.getPartitionId(), storeConfig.storeBootstrapInProgressFile)) {
            // R.Incomplete -> FC
            // Last attempt with blob based bootstrap protocol had failed for this partition.
            // FileCopy bootstrap protocol is enabled but we will still continue with blob based bootstrap protocol.
            listenerToInvoke = storageManagerListener;

            replicationProtocolTransitionType = EnumSet.of(
                ReplicationProtocolTransitionType.BLOB_BASED_HYDRATION_INCOMPLETE_TO_FILE_BASED_HYDRATION);
            logStateChange("R.Incomplete -> FC", partitionName);
          } else if (isAnyLogSegmentExists(replica.getPartitionId())) {
            if (isFileExists(replica.getPartitionId(), storeConfig.storeFileCopyInProgressFileName)) {
              // FC.Incomplete -> FC
              // Last attempt with FileCopy bootstrap protocol had failed for this partition.
              // We will resume the boostrap with FileCopy bootstrap protocol.
              listenerToInvoke = fileCopyManagerListener;

              replicationProtocolTransitionType = EnumSet.of(
                  ReplicationProtocolTransitionType.FILE_BASED_HYDRATION_INCOMPLETE_TO_FILE_BASED_HYDRATION);
              logStateChange("FC.Incomplete -> FC", partitionName);
            } else {
              // R.complete -> FC or FC.complete -> FC
              // Last attempt either with blob based or file based bootstrap protocol had succeeded for this partition.
              // We'll continue with blob based bootstrap protocol for this partition to catch up with its peers.
              // as part of Bootstrap->Standby state transition.
              listenerToInvoke = storageManagerListener;

              replicationProtocolTransitionType = EnumSet.of(
                  ReplicationProtocolTransitionType.BLOB_BASED_HYDRATION_COMPLETE_TO_FILE_BASED_HYDRATION,
                  ReplicationProtocolTransitionType.FILE_BASED_HYDRATION_COMPLETE_TO_FILE_BASED_HYDRATION);
              logStateChange("R.complete -> FC or FC.complete -> FC", partitionName);
            }
          }
        } else {
          if (isFileExists(replica.getPartitionId(), storeConfig.storeBootstrapInProgressFile)) {
            // R.Incomplete -> R
            // Last attempt with blob based bootstrap protocol had failed for this partition.
            // FileCopy bootstrap protocol is disabled and we will continue with blob based bootstrap protocol.
            listenerToInvoke = storageManagerListener;

            replicationProtocolTransitionType = EnumSet.of(
                ReplicationProtocolTransitionType.BLOB_BASED_HYDRATION_INCOMPLETE_TO_BLOB_BASED_HYDRATION);
            logStateChange("R.Incomplete -> R", partitionName);
          } else if (isAnyLogSegmentExists(replica.getPartitionId())) {
            if (isFileExists(replica.getPartitionId(), storeConfig.storeFileCopyInProgressFileName)) {
              // FC.Incomplete -> R
              // Last attempt with FileCopy bootstrap protocol had failed for this partition.
              // First we delete FileCopy data and then continue with blob based bootstrap protocol.
              try {
                deleteFileCopyData(replica.getPartitionId());
              } catch (IOException | StoreException e) {
                String message = "Failed `deleteFileCopyData` step for " + partitionName;
                logger.error(message);
                throw new StateTransitionException(message, BootstrapControllerFailure);
              }
              listenerToInvoke = storageManagerListener;

              replicationProtocolTransitionType = EnumSet.of(
                  ReplicationProtocolTransitionType.FILE_BASED_HYDRATION_INCOMPLETE_TO_BLOB_BASED_HYDRATION);
              logStateChange("FC.Incomplete -> R", partitionName);
            } else {
              // R.complete -> R or FC.complete -> R
              // Last attempt either with blob based or file based bootstrap protocol had succeeded for this partition.
              // We'll continue with blob based bootstrap protocol for this partition to catch up with its peers.
              // as part of Bootstrap->Standby state transition.
              listenerToInvoke = storageManagerListener;

              replicationProtocolTransitionType = EnumSet.of(
                  ReplicationProtocolTransitionType.BLOB_BASED_HYDRATION_COMPLETE_TO_BLOB_BASED_HYDRATION,
                  ReplicationProtocolTransitionType.FILE_BASED_HYDRATION_COMPLETE_TO_BLOB_BASED_HYDRATION);
              logStateChange("R.complete -> R or FC.complete -> R", partitionName);
            }
          }
        }
      }

      assert listenerToInvoke != null;
      listenerToInvoke.onPartitionBecomeBootstrapFromOffline(partitionName);
      if (listenerToInvoke == fileCopyManagerListener) {
        try {
          primaryClusterParticipant.getReplicaSyncUpManager().waitForFileCopyCompleted(partitionName);
        } catch (InterruptedException e) {
          String message = "Failed `waitForFileCopyCompleted` step for " + partitionName;
          logger.error(message);
          throw new StateTransitionException(message, BootstrapControllerFailure);
        } catch (Exception e) {
          logger.error(e.getMessage());
          throw new StateTransitionException(e.getMessage(), BootstrapControllerFailure);
        }
      }
    }
TODO: Add context
@param partitionName of the partition.
ambry-store/src/main/java/com/github/ambry/store/BootstrapController.java