/** * Given a list of segments this reader owns, (which contain their positions) returns the one * that should be read from next. This is done in way to minimize blocking and ensure fairness. * * This is done by calling {@link EventSegmentReader#isSegmentReady()} on each segment. * This method will prefer to return streams where that method is true. This method should * reflect that the next call to {@link EventSegmentReader#read()} will not block (either * because it has data or will throw {@link EndOfSegmentException} * * @param <T> The type of the SegmentInputStream that is being selected from. * @param segments The logs to get the next reader for. * @return A segment that this reader should read from next. */ @VisibleForTesting public <T extends EventSegmentReader> T nextSegment(List<T> segments) { if (segments.isEmpty()) { return null; } for (int i = 0; i < segments.size(); i++) { T inputStream = segments.get(MathHelpers.abs(counter.incrementAndGet()) % segments.size()); if (inputStream.isSegmentReady()) { log.trace("Selecting segment: " + inputStream.getSegmentId()); return inputStream; } else { inputStream.fillBuffer(); } } return segments.get(MathHelpers.abs(counter.incrementAndGet()) % segments.size()); } }