private void ensureCapacity(long writeSize) throws StoreException {
    // all segments are (should be) the same size.
    long segmentCapacity = activeSegment.getCapacityInBytes();
    if (writeSize > segmentCapacity - LogSegment.HEADER_SIZE) {
      metrics.overflowWriteError.inc();
      throw new IllegalArgumentException("Write of size [" + writeSize + "] cannot be serviced because it is greater "
          + "than a single segment's capacity [" + (segmentCapacity - LogSegment.HEADER_SIZE) + "]");
    }
    if (remainingUnallocatedSegments.decrementAndGet() < 0) {
      remainingUnallocatedSegments.incrementAndGet();
      metrics.overflowWriteError.inc();
      throw new IllegalStateException(
          "There is no more capacity left in [" + dataDir + "]. Max capacity is [" + capacityInBytes + "]");
    }
    Pair<LogSegmentName, String> segmentNameAndFilename = getNextSegmentNameAndFilename();
    logger.info("Allocating new segment with name: {}", segmentNameAndFilename.getFirst());
    File newSegmentFile = null;
    try {
      newSegmentFile = allocate(segmentNameAndFilename.getSecond(), segmentCapacity, false);
      LogSegment newSegment =
          new LogSegment(segmentNameAndFilename.getFirst(), newSegmentFile, segmentCapacity, config, metrics, true);
      segmentsByName.put(segmentNameAndFilename.getFirst(), newSegment);
    } catch (StoreException e) {
      try {
        if (newSegmentFile != null) {
          diskSpaceAllocator.free(newSegmentFile, segmentCapacity, storeId, false);
        }
        remainingUnallocatedSegments.incrementAndGet();
        throw e;
      } catch (IOException exception) {
        StoreErrorCodes errorCode = StoreException.resolveErrorCode(exception);
        throw new StoreException(
            e.getMessage() + " And then " + errorCode.toString() + " occurred while freeing the log segment "
                + segmentNameAndFilename.getFirst(), exception, errorCode);
      } finally {
        metrics.overflowWriteError.inc();
      }
    }
  }
Ensures that there is enough capacity for a write of size {@code writeSize} in the log. As a part of ensuring
capacity, this function will also allocate more segments if required.
@param writeSize the size of a subsequent write on the active log segment.
@throws IllegalArgumentException if the {@code writeSize} is greater than a single segment's size
@throws IllegalStateException if there no more capacity in the log.
@throws StoreException if any store exception occurred as a part of ensuring capacity.
ambry-store/src/main/java/com/github/ambry/store/Log.java