@Override public LogEntryProto load(LogRecord key) throws IOException { final File file = getSegmentFile(); // note the loading should not exceed the endIndex: it is possible that // the on-disk log file should be truncated but has not been done yet. readSegmentFile(file, startIndex, endIndex, isOpen, entry -> entryCache.put(ServerProtoUtils.toTermIndex(entry), entry)); loadingTimes.incrementAndGet(); return Objects.requireNonNull(entryCache.get(key.getTermIndex())); } }
@Override public LogEntryProto load(LogRecord key) throws IOException { final File file = getSegmentFile(); // note the loading should not exceed the endIndex: it is possible that // the on-disk log file should be truncated but has not been done yet. readSegmentFile(file, startIndex, endIndex, isOpen, entry -> entryCache.put(ServerProtoUtils.toTermIndex(entry), entry)); loadingTimes.incrementAndGet(); return Objects.requireNonNull(entryCache.get(key.getTermIndex())); } }
/** * Remove records from the given index (inclusive) */ void truncate(long fromIndex) { Preconditions.assertTrue(fromIndex >= startIndex && fromIndex <= endIndex); LogRecord record = records.get(Math.toIntExact(fromIndex - startIndex)); for (long index = endIndex; index >= fromIndex; index--) { LogRecord removed = records.remove(Math.toIntExact(index - startIndex)); entryCache.remove(removed.getTermIndex()); configEntries.remove(removed.getTermIndex()); } totalSize = record.offset; isOpen = false; this.endIndex = fromIndex - 1; }
static void checkLogSegment(LogSegment segment, long start, long end, boolean isOpen, long totalSize, long term) throws Exception { Assert.assertEquals(start, segment.getStartIndex()); Assert.assertEquals(end, segment.getEndIndex()); Assert.assertEquals(isOpen, segment.isOpen()); Assert.assertEquals(totalSize, segment.getTotalSize()); long offset = SegmentedRaftLogFormat.getHeaderLength(); for (long i = start; i <= end; i++) { LogSegment.LogRecord record = segment.getLogRecord(i); LogRecordWithEntry lre = segment.getEntryWithoutLoading(i); Assert.assertEquals(i, lre.getRecord().getTermIndex().getIndex()); Assert.assertEquals(term, lre.getRecord().getTermIndex().getTerm()); Assert.assertEquals(offset, record.getOffset()); LogEntryProto entry = lre.hasEntry() ? lre.getEntry() : segment.loadCache(lre.getRecord()); offset += getEntrySize(entry); } }
@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(); } }
private void checkLogSegment(LogSegment segment, long start, long end, boolean isOpen, long totalSize, long term) throws Exception { Assert.assertEquals(start, segment.getStartIndex()); Assert.assertEquals(end, segment.getEndIndex()); Assert.assertEquals(isOpen, segment.isOpen()); Assert.assertEquals(totalSize, segment.getTotalSize()); long offset = SegmentedRaftLog.HEADER_BYTES.length; for (long i = start; i <= end; i++) { LogSegment.LogRecord record = segment.getLogRecord(i); LogRecordWithEntry lre = segment.getEntryWithoutLoading(i); Assert.assertEquals(i, lre.getRecord().getTermIndex().getIndex()); Assert.assertEquals(term, lre.getRecord().getTermIndex().getTerm()); Assert.assertEquals(offset, record.getOffset()); LogEntryProto entry = lre.hasEntry() ? lre.getEntry() : segment.loadCache(lre.getRecord()); offset += getEntrySize(entry); } }
/** * Acquire LogSegment's monitor so that there is no concurrent loading. */ synchronized LogEntryProto loadCache(LogRecord record) throws RaftLogIOException { LogEntryProto entry = entryCache.get(record.getTermIndex()); if (entry != null) { return entry; } try { entry = cacheLoader.load(record); hasEntryCache = true; return entry; } catch (Exception e) { throw new RaftLogIOException(e); } }
private void testIterator(long startIndex) throws IOException { Iterator<TermIndex> iterator = cache.iterator(startIndex); TermIndex prev = null; while (iterator.hasNext()) { TermIndex termIndex = iterator.next(); Assert.assertEquals(cache.getLogRecord(termIndex.getIndex()).getTermIndex(), termIndex); if (prev != null) { Assert.assertEquals(prev.getIndex() + 1, termIndex.getIndex()); } prev = termIndex; } if (startIndex <= cache.getEndIndex()) { Assert.assertNotNull(prev); Assert.assertEquals(cache.getEndIndex(), prev.getIndex()); } }
@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(); } }
/** * Acquire LogSegment's monitor so that there is no concurrent loading. */ synchronized LogEntryProto loadCache(LogRecord record) throws RaftLogIOException { LogEntryProto entry = entryCache.get(record.getTermIndex()); if (entry != null) { return entry; } try { entry = cacheLoader.load(record); hasEntryCache = true; return entry; } catch (Exception e) { throw new RaftLogIOException(e); } }
/** * Remove records from the given index (inclusive) */ void truncate(long fromIndex) { Preconditions.assertTrue(fromIndex >= startIndex && fromIndex <= endIndex); LogRecord record = records.get(Math.toIntExact(fromIndex - startIndex)); for (long index = endIndex; index >= fromIndex; index--) { LogRecord removed = records.remove(Math.toIntExact(index - startIndex)); entryCache.remove(removed.getTermIndex()); configEntries.remove(removed.getTermIndex()); } totalSize = record.offset; isOpen = false; this.endIndex = fromIndex - 1; }
private void testIterator(long startIndex) throws IOException { Iterator<TermIndex> iterator = cache.iterator(startIndex); TermIndex prev = null; while (iterator.hasNext()) { TermIndex termIndex = iterator.next(); Assert.assertEquals(cache.getLogRecord(termIndex.getIndex()).getTermIndex(), termIndex); if (prev != null) { Assert.assertEquals(prev.getIndex() + 1, termIndex.getIndex()); } prev = termIndex; } if (startIndex <= cache.getEndIndex()) { Assert.assertNotNull(prev); Assert.assertEquals(cache.getEndIndex(), prev.getIndex()); } }
TermIndex getLastTermIndex() { LogRecord last = getLastRecord(); return last == null ? null : last.getTermIndex(); }
@Override public TermIndex getTermIndex(long index) { checkLogState(); try(AutoCloseableLock readLock = readLock()) { LogRecord record = cache.getLogRecord(index); return record != null ? record.getTermIndex() : null; } }
LogRecordWithEntry getEntryWithoutLoading(long index) { LogRecord record = getLogRecord(index); if (record == null) { return null; } return new LogRecordWithEntry(record, entryCache.get(record.getTermIndex())); }
private static void getFromSegment(LogSegment segment, long startIndex, TermIndex[] entries, int offset, int size) { long endIndex = segment.getEndIndex(); endIndex = Math.min(endIndex, startIndex + size - 1); int index = offset; for (long i = startIndex; i <= endIndex; i++) { LogRecord r = segment.getLogRecord(i); entries[index++] = r == null ? null : r.getTermIndex(); } }
TermIndex getLastTermIndex() { LogRecord last = getLastRecord(); return last == null ? null : last.getTermIndex(); }
@Override public TermIndex getTermIndex(long index) { checkLogState(); try(AutoCloseableLock readLock = readLock()) { LogRecord record = cache.getLogRecord(index); return record != null ? record.getTermIndex() : null; } }
LogRecordWithEntry getEntryWithoutLoading(long index) { LogRecord record = getLogRecord(index); if (record == null) { return null; } return new LogRecordWithEntry(record, entryCache.get(record.getTermIndex())); }
private void getFromSegment(LogSegment segment, long startIndex, TermIndex[] entries, int offset, int size) { long endIndex = segment.getEndIndex(); endIndex = Math.min(endIndex, startIndex + size - 1); int index = offset; for (long i = startIndex; i <= endIndex; i++) { LogRecord r = segment.getLogRecord(i); entries[index++] = r == null ? null : r.getTermIndex(); } }