Bump versions 9.0.4-SNAPSHOT
[controller.git] / atomix-storage / src / main / java / io / atomix / storage / journal / SegmentedJournalReader.java
index e5a9094f3697c47c70532a6faabfb6881af7c579..4021518ef5273eba5486b36b5f0142f9bf040f07 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright 2017-present Open Networking Foundation
+ * Copyright 2017-2022 Open Networking Foundation and others.  All rights reserved.
+ * Copyright (c) 2024 PANTHEON.tech, s.r.o. and others.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,139 +18,49 @@ package io.atomix.storage.journal;
 
 import static java.util.Objects.requireNonNull;
 
-import java.util.NoSuchElementException;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.controller.raft.journal.EntryReader;
+import org.opendaylight.controller.raft.journal.FromByteBufMapper;
 
 /**
- * A {@link JournalReader} traversing all entries.
+ * A {@link JournalReader} backed by a {@link EntryReader}.
  */
-sealed class SegmentedJournalReader<E> implements JournalReader<E> permits CommitsSegmentJournalReader {
-  final SegmentedJournal<E> journal;
-  private JournalSegment<E> currentSegment;
-  private Indexed<E> previousEntry;
-  private JournalSegmentReader<E> currentReader;
-
-  SegmentedJournalReader(SegmentedJournal<E> journal, JournalSegment<E> segment) {
-    this.journal = requireNonNull(journal);
-    currentSegment = requireNonNull(segment);
-    currentReader = segment.createReader();
-  }
-
-  @Override
-  public final long getFirstIndex() {
-    return journal.getFirstSegment().index();
-  }
-
-  @Override
-  public final long getCurrentIndex() {
-    long currentIndex = currentReader.getCurrentIndex();
-    if (currentIndex != 0) {
-      return currentIndex;
+@NonNullByDefault
+final class SegmentedJournalReader<E> implements JournalReader<E> {
+    private final FromByteBufMapper<E> mapper;
+    private final EntryReader reader;
+
+    SegmentedJournalReader(final EntryReader reader, final FromByteBufMapper<E> mapper) {
+        this.reader = requireNonNull(reader);
+        this.mapper = requireNonNull(mapper);
     }
-    if (previousEntry != null) {
-      return previousEntry.index();
-    }
-    return 0;
-  }
-
-  @Override
-  public final Indexed<E> getCurrentEntry() {
-    // If previousEntry was the last in the previous segment, we may have moved currentReader to the next segment.
-    // That segment may be empty, though, in which case we need to report the previousEntry.
-    final Indexed<E> currentEntry;
-    return (currentEntry = currentReader.getCurrentEntry()) != null ? currentEntry : previousEntry;
-  }
 
-  @Override
-  public final long getNextIndex() {
-    return currentReader.getNextIndex();
-  }
-
-  @Override
-  public final void reset() {
-    previousEntry = null;
-    currentReader.close();
-
-    currentSegment = journal.getFirstSegment();
-    currentReader = currentSegment.createReader();
-  }
-
-  @Override
-  public final void reset(long index) {
-    // If the current segment is not open, it has been replaced. Reset the segments.
-    if (!currentSegment.isOpen()) {
-      reset();
+    @Override
+    public long getNextIndex() {
+        return reader.nextIndex();
     }
 
-    if (index < currentReader.getNextIndex()) {
-      rewind(index);
-    } else if (index > currentReader.getNextIndex()) {
-      forward(index);
-    } else {
-      currentReader.reset(index);
+    @Override
+    public void reset() {
+        reader.reset();
     }
-  }
-
-  /**
-   * Rewinds the journal to the given index.
-   */
-  private void rewind(long index) {
-    if (currentSegment.index() >= index) {
-      JournalSegment<E> segment = journal.getSegment(index - 1);
-      if (segment != null) {
-        currentReader.close();
 
-        currentSegment = segment;
-        currentReader = currentSegment.createReader();
-      }
+    @Override
+    public void reset(final long index) {
+        reader.reset(index);
     }
 
-    currentReader.reset(index);
-    previousEntry = currentReader.getCurrentEntry();
-  }
-
-  /**
-   * Fast forwards the journal to the given index.
-   */
-  private void forward(long index) {
-    while (getNextIndex() < index && hasNext()) {
-      next();
-    }
-  }
-
-  @Override
-  public boolean hasNext() {
-    return currentReader.hasNext() || moveToNextSegment() && currentReader.hasNext();
-  }
-
-  @Override
-  public final Indexed<E> next() {
-    if (currentReader.hasNext()) {
-      previousEntry = currentReader.getCurrentEntry();
-      return currentReader.next();
+    @Override
+    public <T> @Nullable T tryNext(final EntryMapper<E, T> entryMapper) {
+        return reader.tryNext((index, buf) -> {
+            final var size = buf.readableBytes();
+            return requireNonNull(entryMapper.mapEntry(index, mapper.bytesToObject(index, buf), size));
+        });
     }
-    if (moveToNextSegment()) {
-      return currentReader.next();
-    }
-    throw new NoSuchElementException();
-  }
-
-  @Override
-  public final void close() {
-    currentReader.close();
-    journal.closeReader(this);
-  }
 
-  private boolean moveToNextSegment() {
-    final var nextSegment = journal.getNextSegment(currentSegment.index());
-    if (nextSegment == null || nextSegment.index() != getNextIndex()) {
-      return false;
+    @Override
+    public void close() {
+        reader.close();
     }
-
-    previousEntry = currentReader.getCurrentEntry();
-    currentReader.close();
-
-    currentSegment = nextSegment;
-    currentReader = currentSegment.createReader();
-    return true;
-  }
 }