static LogSegmentList prepareSegments(int numSegments, boolean[] cached, long start, long size) { Assert.assertEquals(numSegments, cached.length); final LogSegmentList segments = new LogSegmentList(TestCacheEviction.class.getSimpleName()); for (int i = 0; i < numSegments; i++) { LogSegment s = LogSegment.newCloseSegment(null, start, start + size - 1); if (cached[i]) { s = Mockito.spy(s); Mockito.when(s.hasCache()).thenReturn(true); } segments.add(s); start += size; } return segments; }
LogSegmentList segments, final int maxCachedSegments) { List<LogSegment> result = new ArrayList<>(); int safeIndex = segments.size() - 1; for (; safeIndex >= 0; safeIndex--) { LogSegment segment = segments.get(safeIndex); LogSegment segment = segments.get(j); if (segment.getEndIndex() > lastAppliedIndex) { break; LogSegment s = segments.get(i); if (s.getStartIndex() > lastAppliedIndex && s.hasCache()) { result.add(s); int j = 0; for (; j <= safeIndex; j++) { LogSegment s = segments.get(j); if (s.getEndIndex() >= minToRead) { break; LogSegment s = segments.get(j); if (Arrays.stream(followerNextIndices).noneMatch(s::containsIndex) && !s.containsIndex(lastAppliedIndex) && s.hasCache()) {
TruncationSegments truncate(long index, LogSegment openSegment, Runnable clearOpenSegment) { try(AutoCloseableLock writeLock = writeLock()) { final int segmentIndex = binarySearch(index); if (segmentIndex == -segments.size() - 1) { if (openSegment != null && openSegment.getEndIndex() >= index) { if (index == openSegment.getStartIndex()) { final SegmentFileInfo deleted = deleteOpenSegment(openSegment, clearOpenSegment); return new TruncationSegments(null, Collections.singletonList(deleted)); } else { list.add(deleteOpenSegment(openSegment, clearOpenSegment));
Assert.assertSame(evicted.get(0), segments.get(0)); Assert.assertSame(evicted.get(1), segments.get(1)); Assert.assertSame(evicted.get(0), segments.get(0)); Assert.assertSame(evicted.get(0), segments.get(0)); Mockito.when(segments.get(0).hasCache()).thenReturn(false); evicted = policy.evict(new long[]{15, 45, 45}, 55, 50, segments, maxCached); Assert.assertEquals(1, evicted.size()); Assert.assertSame(evicted.get(0), segments.get(2)); Mockito.when(segments.get(2).hasCache()).thenReturn(false); evicted = policy.evict(new long[]{15, 45, 45}, 55, 50, segments, maxCached); Assert.assertEquals(1, evicted.size()); Assert.assertSame(evicted.get(0), segments.get(3)); Mockito.when(segments.get(3).hasCache()).thenReturn(false); evicted = policy.evict(new long[]{15, 45, 45}, 55, 50, segments, maxCached); Assert.assertEquals(0, evicted.size());
Assert.assertSame(evicted.get(0), segments.get(0)); Assert.assertSame(evicted.get(1), segments.get(1)); Assert.assertSame(evicted.get(0), segments.get(0)); Assert.assertSame(evicted.get(0), segments.get(2)); Mockito.when(segments.get(2).hasCache()).thenReturn(false); evicted = policy.evict(null, 35, 5, segments, maxCached); Assert.assertEquals(1, evicted.size()); Assert.assertSame(evicted.get(0), segments.get(1)); Mockito.when(segments.get(1).hasCache()).thenReturn(false); evicted = policy.evict(null, 35, 5, segments, maxCached); Assert.assertEquals(0, evicted.size());
/** * @param startIndex inclusive * @param endIndex exclusive */ TermIndex[] getTermIndices(final long startIndex, final long endIndex) { if (startIndex < 0 || startIndex < getStartIndex()) { throw new IndexOutOfBoundsException("startIndex = " + startIndex + ", log cache starts from index " + getStartIndex()); } if (startIndex > endIndex) { throw new IndexOutOfBoundsException("startIndex(" + startIndex + ") > endIndex(" + endIndex + ")"); } final long realEnd = Math.min(getEndIndex() + 1, endIndex); if (startIndex >= realEnd) { return TermIndex.EMPTY_TERMINDEX_ARRAY; } return closedSegments.getTermIndex(startIndex, realEnd, openSegment); }
EntryIterator(long start) { this.nextIndex = start; segmentIndex = closedSegments.binarySearch(nextIndex); if (segmentIndex >= 0) { currentSegment = closedSegments.get(segmentIndex); } else { segmentIndex = -segmentIndex - 1; if (segmentIndex == closedSegments.size()) { currentSegment = openSegment; } else { // the start index is smaller than the first closed segment's start // index. We no longer keep the log entry (because of the snapshot) or // the start index is invalid. Preconditions.assertTrue(segmentIndex == 0); throw new IndexOutOfBoundsException(); } } }
@Override public TermIndex next() { LogRecord record; if (currentSegment == null || (record = currentSegment.getLogRecord(nextIndex)) == null) { throw new NoSuchElementException(); } if (++nextIndex > currentSegment.getEndIndex()) { if (currentSegment != openSegment) { segmentIndex++; currentSegment = segmentIndex == closedSegments.size() ? openSegment : closedSegments.get(segmentIndex); } } return record.getTermIndex(); } }
boolean isEmpty() { return closedSegments.isEmpty() && openSegment == null; }
boolean shouldEvict() { return closedSegments.countCached() > maxCachedSegments; }
long getCachedSegmentNum() { return closedSegments.countCached(); }
/** * finalize the current open segment, and start a new open segment */ void rollOpenSegment(boolean createNewOpen) { Preconditions.assertTrue(openSegment != null && openSegment.numOfEntries() > 0); final long nextIndex = openSegment.getEndIndex() + 1; openSegment.close(); closedSegments.add(openSegment); clearOpenSegment(); if (createNewOpen) { addOpenSegment(nextIndex); } }
RaftLogCache(RaftPeerId selfId, RaftStorage storage, RaftProperties properties) { this.name = selfId + "-" + getClass().getSimpleName(); this.closedSegments = new LogSegmentList(name); this.storage = storage; maxCachedSegments = RaftServerConfigKeys.Log.maxCachedSegmentNum(properties); }
void addSegment(LogSegment segment) { validateAdding(segment); if (segment.isOpen()) { setOpenSegment(segment); } else { closedSegments.add(segment); } }
private void validateAdding(LogSegment segment) { final LogSegment lastClosed = closedSegments.getLast(); if (lastClosed != null) { Preconditions.assertTrue(!lastClosed.isOpen()); Preconditions.assertTrue(lastClosed.getEndIndex() + 1 == segment.getStartIndex()); } }
void clear() { if (openSegment != null) { openSegment.clear(); clearOpenSegment(); } closedSegments.clear(); } }