public void allocate(File destinationFile, long sizeInBytes, String storeId, boolean isSwapSegment) throws IOException {
    long startTime = System.currentTimeMillis();
    try {
      if (enablePooling && poolState != PoolState.INITIALIZED) {
        logger.info("Allocating segment of size {} to {} before pool is fully initialized", sizeInBytes,
            destinationFile.getAbsolutePath());
        metrics.diskSpaceAllocatorAllocBeforeInitCount.inc();
      } else {
        logger.info("Allocating segment of size {} to {}", sizeInBytes, destinationFile.getAbsolutePath());
      }
      if (destinationFile.exists()) {
        throw new IOException("Destination file already exists: " + destinationFile.getAbsolutePath());
      }
      File reserveFile = null;
      if (poolState != PoolState.NOT_INVENTORIED) {
        if (isSwapSegment) {
          // attempt to get segment from swap reserve directory
          reserveFile = swapReserveFiles.remove(sizeInBytes);
        } else {
          // attempt to get segment from corresponding store reserve directory
          if (storeReserveFiles.containsKey(storeId)) {
            reserveFile = storeReserveFiles.get(storeId).remove(sizeInBytes);
          }
        }
      }
      if (reserveFile == null) {
        if (enablePooling) {
          logger.info("Segment of size {} not found in {}; attempting to create a new preallocated file; poolState: {}",
              sizeInBytes, isSwapSegment ? SWAP_DIR_NAME + " directory" : STORE_DIR_PREFIX + storeId + " directory",
              poolState);
          metrics.diskSpaceAllocatorSegmentNotFoundCount.inc();
        }
        Utils.preAllocateFileIfNeeded(destinationFile, sizeInBytes);
      } else {
        logger.info("Moving segment with size {} from {} to {}", sizeInBytes,
            isSwapSegment ? SWAP_DIR_NAME + " directory" : STORE_DIR_PREFIX + storeId + " directory",
            destinationFile.getAbsolutePath());
        try {
          Files.move(reserveFile.toPath(), destinationFile.toPath());
        } catch (Exception e) {
          // return the segment (if exists) to corresponding store reserve dir or swap reserve dir which it belongs to
          if (reserveFile.exists()) {
            if (isSwapSegment) {
              swapReserveFiles.add(sizeInBytes, reserveFile);
            } else {
              storeReserveFiles.get(storeId).add(sizeInBytes, reserveFile);
            }
          } else {
            logger.warn("Reserve file {} doesn't exist when adding it back to in-mem file map",
                reserveFile.getAbsolutePath());
          }
          throw e;
        }
      }
    } finally {
      long elapsedTime = System.currentTimeMillis() - startTime;
      logger.debug("allocating new segment took {} ms for {}", elapsedTime, "store[" + storeId + "]");
      metrics.diskSpaceAllocatorAllocTimeMs.update(elapsedTime);
    }
  }
Allocate a file, that is, take a file matching the requested size from the reserve directory and move it to the
provided file path
@param destinationFile the file path to move the allocated file to.
@param sizeInBytes the size in bytes of the requested file.
@param storeId the id of store that requests segment from pool.
@param isSwapSegment {@code true} if the segment is used for swap purpose in compaction. {@code false} otherwise.
@throws IOException if the file could not be moved to the destination.
ambry-store/src/main/java/com/github/ambry/store/DiskSpaceAllocator.java