CompletableFuture<Void> compact(@NonNull DirectSegmentAccess segment, TimeoutTimer timer) {
        SegmentProperties info = segment.getInfo();
        long startOffset = getCompactionStartOffset(info);
        int maxLength = (int) Math.min(this.connector.getMaxCompactionSize(), this.indexReader.getLastIndexedOffset(info) - startOffset);
        if (startOffset < 0 || maxLength < 0) {
            // The Segment's Compaction offset must be a value between 0 and the current LastIndexedOffset.
            return Futures.failedFuture(new DataCorruptionException(String.format(
                    "Segment[%s] (%s) has CompactionStartOffset=%s and CompactionLength=%s.",
                    segment.getSegmentId(), info.getName(), startOffset, maxLength)));
        } else if (maxLength == 0) {
            // Nothing to do.
            log.debug("TableCompactor[{}]: Up to date.", segment.getSegmentId());
            return CompletableFuture.completedFuture(null);
        }

        // Read the Table Entries beginning at the specified offset, without exceeding the given maximum length.
        return readCandidates(segment, startOffset, maxLength, timer)
                .thenComposeAsync(candidates -> this.indexReader
                                .locateBuckets(segment, candidates.candidates.keySet(), timer)
                                .thenComposeAsync(buckets -> excludeObsolete(segment, candidates, buckets, timer), this.executor)
                                .thenComposeAsync(v -> copyCandidates(segment, candidates, timer), this.executor),
                        this.executor);
    }
CompletableFuture < Void > compact ( @ NonNull DirectSegmentAccess segment , TimeoutTimer timer ) { SegmentProperties info = segment . getInfo ( ) ; long startOffset = getCompactionStartOffset ( info ) ; int maxLength = ( int ) Math . min ( this . connector . getMaxCompactionSize ( ) , this . indexReader . getLastIndexedOffset ( info ) - startOffset ) ; if ( startOffset < 0 || maxLength < 0 ) { return Futures . failedFuture ( new DataCorruptionException ( String . format ( "Segment[%s] (%s) has CompactionStartOffset=%s and CompactionLength=%s." , segment . getSegmentId ( ) , info . getName ( ) , startOffset , maxLength ) ) ) ; } else if ( maxLength == 0 ) { log . debug ( "TableCompactor[{}]: Up to date." , segment . getSegmentId ( ) ) ; return CompletableFuture . completedFuture ( null ) ; } return readCandidates ( segment , startOffset , maxLength , timer ) . thenComposeAsync ( candidates -> this . indexReader . locateBuckets ( segment , candidates . candidates . keySet ( ) , timer ) . thenComposeAsync ( buckets -> excludeObsolete ( segment , candidates , buckets , timer ) , this . executor ) . thenComposeAsync ( v -> copyCandidates ( segment , candidates , timer ) , this . executor ) , this . executor ) ; }
Performs a compaction of a Table Segment. Refer to this class' Javadoc for a description of the compaction process.

@param segment A {@link DirectSegmentAccess} providing access to the Table Segment to compact.
@param timer   Timer for the operation.
@return A CompletableFuture that, when completed, indicate the compaction completed. When this future completes,
some of the Segment's Table Attributes may change to reflect the modifications to the Segment and/or compaction progress.
Notable exceptions:
<ul>
<li>{@link BadAttributeUpdateException} If the {@link TableAttributes#COMPACTION_OFFSET} changed while this method
was executing. In this case, no change will be performed and it can be resolved with a retry.</li>
</ul>