This is an automated email from the ASF dual-hosted git repository.
mreutegg pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
The following commit(s) were added to refs/heads/trunk by this push:
new d521fd7c4d OAK-11808: Segment graph may need to be recomputed (#2393)
d521fd7c4d is described below
commit d521fd7c4db66b3617fbd4073693134b850a94ad
Author: Lucas Weitzendorf <[email protected]>
AuthorDate: Mon Aug 11 08:14:10 2025 +0200
OAK-11808: Segment graph may need to be recomputed (#2393)
* OAK-11808: SegmentGraph class
* address review comments
* address further comments
---------
Co-authored-by: Lucas Weitzendorf <[email protected]>
---
.../segment/aws/tool/AwsSegmentStoreMigrator.java | 8 +-
.../oak/segment/aws/tool/SegmentCopyTestBase.java | 9 +-
.../segment/azure/tool/SegmentStoreMigrator.java | 22 +-
.../segment/azure/tool/SegmentCopyTestBase.java | 11 +-
.../remote/AbstractRemoteSegmentArchiveReader.java | 25 +--
.../oak/segment/remote/package-info.java | 2 +-
.../oak/segment/file/tar/GraphLoader.java | 116 ----------
.../oak/segment/file/tar/SegmentGraph.java | 243 +++++++++++++++++++++
.../oak/segment/file/tar/SegmentTarReader.java | 36 +--
.../oak/segment/file/tar/TarConstants.java | 19 --
.../jackrabbit/oak/segment/file/tar/TarFiles.java | 26 +--
.../jackrabbit/oak/segment/file/tar/TarReader.java | 98 ++-------
.../jackrabbit/oak/segment/file/tar/TarWriter.java | 72 +-----
.../spi/persistence/SegmentArchiveReader.java | 17 +-
.../CachingSegmentArchiveReader.java | 11 +-
.../persistence/persistentcache/package-info.java | 2 +-
.../split/UnclosedSegmentArchiveReader.java | 8 +-
.../oak/segment/file/tar/TarFileTest.java | 8 +-
18 files changed, 328 insertions(+), 405 deletions(-)
diff --git
a/oak-segment-aws/src/main/java/org/apache/jackrabbit/oak/segment/aws/tool/AwsSegmentStoreMigrator.java
b/oak-segment-aws/src/main/java/org/apache/jackrabbit/oak/segment/aws/tool/AwsSegmentStoreMigrator.java
index 2bcc900d53..4f37a60d07 100644
---
a/oak-segment-aws/src/main/java/org/apache/jackrabbit/oak/segment/aws/tool/AwsSegmentStoreMigrator.java
+++
b/oak-segment-aws/src/main/java/org/apache/jackrabbit/oak/segment/aws/tool/AwsSegmentStoreMigrator.java
@@ -38,6 +38,7 @@ import org.apache.jackrabbit.oak.commons.Buffer;
import org.apache.jackrabbit.oak.segment.aws.AwsContext;
import org.apache.jackrabbit.oak.segment.aws.AwsPersistence;
import
org.apache.jackrabbit.oak.segment.aws.tool.AwsToolUtils.SegmentStoreType;
+import org.apache.jackrabbit.oak.segment.file.tar.SegmentGraph;
import org.apache.jackrabbit.oak.segment.file.tar.TarPersistence;
import org.apache.jackrabbit.oak.segment.remote.RemoteUtilities;
import org.apache.jackrabbit.oak.segment.spi.RepositoryNotReachableException;
@@ -212,11 +213,8 @@ public class AwsSegmentStoreMigrator implements Closeable
{
}
private void migrateGraph(SegmentArchiveReader reader,
SegmentArchiveWriter writer) throws IOException {
- if (reader.hasGraph()) {
- Buffer graph = reader.getGraph();
- byte[] array = fetchByteArray(graph);
- writer.writeGraph(array);
- }
+ SegmentGraph graph = reader.getGraph();
+ writer.writeGraph(graph.write());
}
private static <T> T runWithRetry(Producer<T> producer, int maxAttempts,
int intervalSec) throws IOException {
diff --git
a/oak-segment-aws/src/test/java/org/apache/jackrabbit/oak/segment/aws/tool/SegmentCopyTestBase.java
b/oak-segment-aws/src/test/java/org/apache/jackrabbit/oak/segment/aws/tool/SegmentCopyTestBase.java
index 4ad310443f..d5b9a65732 100644
---
a/oak-segment-aws/src/test/java/org/apache/jackrabbit/oak/segment/aws/tool/SegmentCopyTestBase.java
+++
b/oak-segment-aws/src/test/java/org/apache/jackrabbit/oak/segment/aws/tool/SegmentCopyTestBase.java
@@ -37,6 +37,7 @@ import org.apache.jackrabbit.oak.segment.aws.AwsContext;
import org.apache.jackrabbit.oak.segment.aws.AwsPersistence;
import
org.apache.jackrabbit.oak.segment.aws.tool.AwsToolUtils.SegmentStoreType;
import org.apache.jackrabbit.oak.segment.file.FileStore;
+import org.apache.jackrabbit.oak.segment.file.tar.SegmentGraph;
import org.apache.jackrabbit.oak.segment.spi.monitor.FileStoreMonitor;
import org.apache.jackrabbit.oak.segment.spi.monitor.FileStoreMonitorAdapter;
import org.apache.jackrabbit.oak.segment.spi.monitor.IOMonitor;
@@ -176,11 +177,9 @@ public abstract class SegmentCopyTestBase {
Buffer destBinRefBuffer = destArchiveReader.getBinaryReferences();
assertEquals(srcBinRefBuffer, destBinRefBuffer);
- assertEquals(srcArchiveReader.hasGraph(),
destArchiveReader.hasGraph());
-
- Buffer srcGraphBuffer = srcArchiveReader.getGraph();
- Buffer destGraphBuffer = destArchiveReader.getGraph();
- assertEquals(srcGraphBuffer, destGraphBuffer);
+ SegmentGraph srcGraph = srcArchiveReader.getGraph();
+ SegmentGraph destGraph = destArchiveReader.getGraph();
+ assertEquals(srcGraph, destGraph);
}
}
diff --git
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentStoreMigrator.java
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentStoreMigrator.java
index 6fabbfe71e..cdd2ac1af7 100644
---
a/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentStoreMigrator.java
+++
b/oak-segment-azure/src/main/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentStoreMigrator.java
@@ -24,6 +24,7 @@ import org.apache.jackrabbit.oak.commons.Buffer;
import org.apache.jackrabbit.oak.segment.azure.AzurePersistence;
import org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils.SegmentStoreType;
import org.apache.jackrabbit.oak.segment.azure.util.Retrier;
+import org.apache.jackrabbit.oak.segment.file.tar.SegmentGraph;
import org.apache.jackrabbit.oak.segment.file.tar.TarPersistence;
import org.apache.jackrabbit.oak.segment.remote.RemoteUtilities;
import org.apache.jackrabbit.oak.segment.spi.monitor.FileStoreMonitorAdapter;
@@ -213,25 +214,14 @@ public class SegmentStoreMigrator implements Closeable {
private void migrateBinaryRef(SegmentArchiveReader reader,
SegmentArchiveWriter writer) throws IOException, ExecutionException,
InterruptedException {
Future<Buffer> future = executor.submit(() ->
RETRIER.execute(reader::getBinaryReferences));
Buffer binaryReferences = future.get();
- if (binaryReferences != null) {
- byte[] array = fetchByteArray(binaryReferences);
- RETRIER.execute(() -> writer.writeBinaryReferences(array));
- }
+ byte[] array = fetchByteArray(binaryReferences);
+ RETRIER.execute(() -> writer.writeBinaryReferences(array));
}
private void migrateGraph(SegmentArchiveReader reader,
SegmentArchiveWriter writer) throws IOException, ExecutionException,
InterruptedException {
- Future<Buffer> future = executor.submit(() -> RETRIER.execute(() -> {
- if (reader.hasGraph()) {
- return reader.getGraph();
- } else {
- return null;
- }
- }));
- Buffer graph = future.get();
- if (graph != null) {
- byte[] array = fetchByteArray(graph);
- RETRIER.execute(() -> writer.writeGraph(array));
- }
+ Future<SegmentGraph> future = executor.submit(() ->
RETRIER.execute(reader::getGraph));
+ SegmentGraph graph = future.get();
+ RETRIER.execute(() -> writer.writeGraph(graph.write()));
}
@Override
diff --git
a/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopyTestBase.java
b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopyTestBase.java
index f259939e53..c7f7f07606 100644
---
a/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopyTestBase.java
+++
b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/azure/tool/SegmentCopyTestBase.java
@@ -54,6 +54,7 @@ import
org.apache.jackrabbit.oak.segment.azure.tool.SegmentCopy;
import org.apache.jackrabbit.oak.segment.azure.tool.ToolUtils.SegmentStoreType;
import
org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions.CompactorType;
import org.apache.jackrabbit.oak.segment.file.FileStore;
+import org.apache.jackrabbit.oak.segment.file.tar.SegmentGraph;
import org.apache.jackrabbit.oak.segment.spi.monitor.FileStoreMonitor;
import org.apache.jackrabbit.oak.segment.spi.monitor.FileStoreMonitorAdapter;
import org.apache.jackrabbit.oak.segment.spi.monitor.IOMonitor;
@@ -195,12 +196,10 @@ public abstract class SegmentCopyTestBase {
Buffer srcBinRefBuffer = srcArchiveReader.getBinaryReferences();
Buffer destBinRefBuffer = destArchiveReader.getBinaryReferences();
assertEquals(srcBinRefBuffer, destBinRefBuffer);
-
- assertEquals(srcArchiveReader.hasGraph(),
destArchiveReader.hasGraph());
-
- Buffer srcGraphBuffer = srcArchiveReader.getGraph();
- Buffer destGraphBuffer = destArchiveReader.getGraph();
- assertEquals(srcGraphBuffer, destGraphBuffer);
+
+ SegmentGraph srcGraph = srcArchiveReader.getGraph();
+ SegmentGraph destGraph = destArchiveReader.getGraph();
+ assertEquals(srcGraph, destGraph);
}
}
diff --git
a/oak-segment-remote/src/main/java/org/apache/jackrabbit/oak/segment/remote/AbstractRemoteSegmentArchiveReader.java
b/oak-segment-remote/src/main/java/org/apache/jackrabbit/oak/segment/remote/AbstractRemoteSegmentArchiveReader.java
index a7f838d758..fe99490e18 100644
---
a/oak-segment-remote/src/main/java/org/apache/jackrabbit/oak/segment/remote/AbstractRemoteSegmentArchiveReader.java
+++
b/oak-segment-remote/src/main/java/org/apache/jackrabbit/oak/segment/remote/AbstractRemoteSegmentArchiveReader.java
@@ -21,9 +21,12 @@ import static
org.apache.jackrabbit.oak.segment.remote.RemoteUtilities.OFF_HEAP;
import org.apache.jackrabbit.oak.commons.Buffer;
import org.apache.jackrabbit.oak.commons.time.Stopwatch;
+import org.apache.jackrabbit.oak.segment.file.tar.SegmentGraph;
import org.apache.jackrabbit.oak.segment.spi.monitor.IOMonitor;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveEntry;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveReader;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
@@ -39,8 +42,6 @@ public abstract class AbstractRemoteSegmentArchiveReader
implements SegmentArchi
protected final Map<UUID, RemoteSegmentArchiveEntry> index = new
LinkedHashMap<>();
- protected Boolean hasGraph;
-
public AbstractRemoteSegmentArchiveReader(IOMonitor ioMonitor) throws
IOException {
this.ioMonitor = ioMonitor;
}
@@ -78,24 +79,16 @@ public abstract class AbstractRemoteSegmentArchiveReader
implements SegmentArchi
}
@Override
- public Buffer getGraph() throws IOException {
- Buffer graph = doReadDataFile(".gph");
- hasGraph = graph != null;
- return graph;
- }
-
- @Override
- public boolean hasGraph() {
- if (hasGraph == null) {
- try {
- getGraph();
- } catch (IOException ignore) { }
+ public @NotNull SegmentGraph getGraph() throws IOException {
+ Buffer buffer = doReadDataFile(".gph");
+ if (buffer != null) {
+ return SegmentGraph.parse(buffer);
}
- return hasGraph != null ? hasGraph : false;
+ return SegmentGraph.compute(this);
}
@Override
- public Buffer getBinaryReferences() throws IOException {
+ public @Nullable Buffer getBinaryReferences() throws IOException {
return doReadDataFile(".brf");
}
diff --git
a/oak-segment-remote/src/main/java/org/apache/jackrabbit/oak/segment/remote/package-info.java
b/oak-segment-remote/src/main/java/org/apache/jackrabbit/oak/segment/remote/package-info.java
index c72df5f1f7..fd64aa03ce 100644
---
a/oak-segment-remote/src/main/java/org/apache/jackrabbit/oak/segment/remote/package-info.java
+++
b/oak-segment-remote/src/main/java/org/apache/jackrabbit/oak/segment/remote/package-info.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
@Internal(since = "1.0.0")
-@Version("1.4.0")
+@Version("2.0.0")
package org.apache.jackrabbit.oak.segment.remote;
import org.apache.jackrabbit.oak.commons.annotations.Internal;
diff --git
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/GraphLoader.java
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/GraphLoader.java
deleted file mode 100644
index 8151920004..0000000000
---
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/GraphLoader.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.jackrabbit.oak.segment.file.tar;
-
-import static
org.apache.jackrabbit.oak.segment.file.tar.TarConstants.GRAPH_MAGIC;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.zip.CRC32;
-
-import org.apache.jackrabbit.oak.commons.Buffer;
-import org.apache.jackrabbit.oak.commons.collections.MapUtils;
-import org.apache.jackrabbit.oak.segment.util.ReaderAtEnd;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public final class GraphLoader {
-
- private static final Logger log =
LoggerFactory.getLogger(GraphLoader.class);
-
- private static final int FOOTER_SIZE = 16;
-
- private GraphLoader() {
- }
-
- /**
- * Loads the optional pre-compiled graph entry from the given tar file.
- *
- * @return the graph or {@code null} if one was not found
- * @throws IOException if the tar file could not be read
- */
- public static Buffer loadGraph(ReaderAtEnd readerAtEnd) throws IOException
{
- Buffer meta = readerAtEnd.readAtEnd(FOOTER_SIZE, FOOTER_SIZE);
-
- int crc32 = meta.getInt();
- int count = meta.getInt();
- int bytes = meta.getInt();
- int magic = meta.getInt();
-
- if (magic != GRAPH_MAGIC) {
- log.warn("Invalid graph magic number");
- return null;
- }
-
- if (count < 0) {
- log.warn("Invalid number of entries");
- return null;
- }
-
- if (bytes < 4 + count * 34) {
- log.warn("Invalid entry size");
- return null;
- }
-
- Buffer graph = readerAtEnd.readAtEnd(bytes, bytes);
-
- byte[] b = new byte[bytes - FOOTER_SIZE];
-
- graph.mark();
- graph.get(b);
- graph.reset();
-
- CRC32 checksum = new CRC32();
- checksum.update(b);
-
- if (crc32 != (int) checksum.getValue()) {
- log.warn("Invalid graph checksum in tar file");
- return null;
- }
-
- return graph;
- }
-
- public static Map<UUID, List<UUID>> parseGraph(Buffer buffer) {
- int nEntries = buffer.getInt(buffer.limit() - 12);
-
- Map<UUID, List<UUID>> graph = MapUtils.newHashMap(nEntries);
-
- for (int i = 0; i < nEntries; i++) {
- long msb = buffer.getLong();
- long lsb = buffer.getLong();
- int nVertices = buffer.getInt();
-
- List<UUID> vertices = new ArrayList<>(nVertices);
-
- for (int j = 0; j < nVertices; j++) {
- long vMsb = buffer.getLong();
- long vLsb = buffer.getLong();
- vertices.add(new UUID(vMsb, vLsb));
- }
-
- graph.put(new UUID(msb, lsb), vertices);
- }
-
- return graph;
- }
-}
diff --git
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/SegmentGraph.java
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/SegmentGraph.java
new file mode 100644
index 0000000000..353eaf52f5
--- /dev/null
+++
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/SegmentGraph.java
@@ -0,0 +1,243 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.jackrabbit.oak.segment.file.tar;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.zip.CRC32;
+
+import org.apache.jackrabbit.oak.commons.Buffer;
+import org.apache.jackrabbit.oak.segment.SegmentId;
+import org.apache.jackrabbit.oak.segment.data.SegmentData;
+import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveEntry;
+import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveReader;
+import org.apache.jackrabbit.oak.segment.util.ReaderAtEnd;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class SegmentGraph {
+
+ private static final Logger log =
LoggerFactory.getLogger(SegmentGraph.class);
+
+ private static final int FOOTER_SIZE = 16;
+
+ /**
+ * Magic byte sequence at the end of the graph block.
+ * <p>
+ * The file is read from the end (the tar file is read from the end: the
+ * last entry is the index, then the graph). File format:
+ * <ul>
+ * <li>0 padding to make the footer end at a 512 byte boundary</li>
+ * <li>The list of UUIDs (segments included the graph; this includes
+ * segments in this tar file, and referenced segments in tar files with a
+ * lower sequence number). 16 bytes each.</li>
+ * <li>The graph data. The index of the source segment UUID (in the above
+ * list, 4 bytes), then the list of referenced segments (the indexes of
+ * those; 4 bytes each). Then the list is terminated by -1.</li>
+ * <li>The last part is the footer, which contains metadata of the graph
+ * (size, checksum, the number of UUIDs).</li>
+ * </ul>
+ */
+ private static final int MAGIC = ('\n' << 24) + ('0' << 16) + ('G' << 8) +
'\n';
+
+ private final @NotNull Map<UUID, Set<UUID>> edgeMap;
+
+ public SegmentGraph() {
+ this.edgeMap = new HashMap<>();
+ }
+
+ private SegmentGraph(@NotNull Map<UUID, Set<UUID>> edgeMap) {
+ this.edgeMap = edgeMap;
+ }
+
+ public void addEdge(@NotNull UUID from, @NotNull UUID to) {
+ edgeMap.computeIfAbsent(from, k -> new HashSet<>()).add(to);
+ }
+
+ public @NotNull Map<UUID, Set<UUID>> getEdges() {
+ return Collections.unmodifiableMap(edgeMap);
+ }
+
+ public @NotNull Set<UUID> getEdges(@NotNull UUID from) {
+ Set<UUID> set = edgeMap.getOrDefault(from, Collections.emptySet());
+ return Collections.unmodifiableSet(set);
+ }
+
+ /**
+ * Loads the optional pre-compiled graph entry from the given tar file.
+ *
+ * @return the graph or {@code null} if one was not found
+ * @throws IOException if the tar file could not be read
+ */
+ public static @Nullable SegmentGraph load(ReaderAtEnd readerAtEnd) throws
IOException {
+ Buffer meta = readerAtEnd.readAtEnd(FOOTER_SIZE, FOOTER_SIZE);
+
+ int crc32 = meta.getInt();
+ int count = meta.getInt();
+ int bytes = meta.getInt();
+ int magic = meta.getInt();
+
+ if (magic != MAGIC) {
+ log.warn("Invalid graph magic number");
+ return null;
+ }
+
+ if (count < 0) {
+ log.warn("Invalid number of entries");
+ return null;
+ }
+
+ if (bytes < 4 + count * 34) {
+ log.warn("Invalid entry size");
+ return null;
+ }
+
+ Buffer buffer = readerAtEnd.readAtEnd(bytes, bytes);
+ byte[] b = new byte[bytes - FOOTER_SIZE];
+
+ buffer.mark();
+ buffer.get(b);
+ buffer.reset();
+
+ CRC32 checksum = new CRC32();
+ checksum.update(b);
+
+ if (crc32 != (int) checksum.getValue()) {
+ log.warn("Invalid graph checksum in tar file");
+ return null;
+ }
+
+ return SegmentGraph.parse(buffer);
+ }
+
+ /**
+ * Computes the graph from a segment archive
+ *
+ * @return the computed segment graph.
+ */
+ public static @NotNull SegmentGraph compute(SegmentArchiveReader
archiveReader) throws IOException {
+ SegmentGraph graph = new SegmentGraph();
+ for (SegmentArchiveEntry entry : archiveReader.listSegments()) {
+ if (!SegmentId.isDataSegmentId(entry.getLsb())) {
+ continue;
+ }
+ UUID from = new UUID(entry.getMsb(), entry.getLsb());
+ Buffer buffer = archiveReader.readSegment(entry.getMsb(),
entry.getLsb());
+ SegmentData data = SegmentData.newSegmentData(buffer);
+ for (int i = 0; i < data.getSegmentReferencesCount(); i++) {
+ UUID to = new UUID(data.getSegmentReferenceMsb(i),
data.getSegmentReferenceLsb(i));
+ graph.addEdge(from, to);
+ }
+ }
+ return graph;
+ }
+
+ public static @NotNull SegmentGraph parse(@NotNull Buffer buffer) {
+ int nEntries = buffer.getInt(buffer.limit() - 12);
+ Map<UUID, Set<UUID>> edgeMap = new HashMap<>(nEntries);
+
+ for (int i = 0; i < nEntries; i++) {
+ long msb = buffer.getLong();
+ long lsb = buffer.getLong();
+ int nVertices = buffer.getInt();
+
+ Set<UUID> vertices = new HashSet<>(nVertices);
+
+ for (int j = 0; j < nVertices; j++) {
+ long vMsb = buffer.getLong();
+ long vLsb = buffer.getLong();
+ vertices.add(new UUID(vMsb, vLsb));
+ }
+
+ edgeMap.put(new UUID(msb, lsb), vertices);
+ }
+
+ return new SegmentGraph(edgeMap);
+ }
+
+ public byte[] write() {
+ int graphSize = size();
+ Buffer buffer = Buffer.allocate(graphSize);
+
+ for (Map.Entry<UUID, Set<UUID>> entry : edgeMap.entrySet()) {
+ UUID from = entry.getKey();
+ buffer.putLong(from.getMostSignificantBits());
+ buffer.putLong(from.getLeastSignificantBits());
+
+ Set<UUID> adj = entry.getValue();
+ buffer.putInt(adj.size());
+ for (UUID to : adj) {
+ buffer.putLong(to.getMostSignificantBits());
+ buffer.putLong(to.getLeastSignificantBits());
+ }
+ }
+
+ CRC32 checksum = new CRC32();
+ checksum.update(buffer.array(), 0, buffer.position());
+
+ buffer.putInt((int) checksum.getValue());
+ buffer.putInt(edgeMap.size());
+ buffer.putInt(graphSize);
+ buffer.putInt(MAGIC);
+
+ return buffer.array();
+ }
+
+ public int size() {
+ // The following information is stored in the footer as meta
information about the entry.
+ // 4 bytes to store a magic number identifying this entry as
containing references to binary values.
+ // 4 bytes to store the CRC32 checksum of the data in this entry.
+ // 4 bytes to store the length of this entry, without including the
optional padding.
+ // 4 bytes to store the number of entries in the graph map.
+ int graphSize = FOOTER_SIZE;
+ // The following information is stored as part of the main content of
+ // this entry, after the optional padding.
+ for (Map.Entry<UUID, Set<UUID>> entry : edgeMap.entrySet()) {
+ // 16 bytes to store the key of the map.
+ graphSize += 16;
+ // 4 bytes for the number of entries in the adjacency list.
+ graphSize += 4;
+ // 16 bytes for every element in the adjacency list.
+ graphSize += 16 * entry.getValue().size();
+ }
+ return graphSize;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (other instanceof SegmentGraph) {
+ return edgeMap.equals(((SegmentGraph) other).edgeMap);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return edgeMap.hashCode();
+ }
+}
diff --git
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/SegmentTarReader.java
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/SegmentTarReader.java
index afc924e49b..3e22e34d51 100644
---
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/SegmentTarReader.java
+++
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/SegmentTarReader.java
@@ -41,6 +41,7 @@ import
org.apache.jackrabbit.oak.segment.spi.monitor.IOMonitor;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveEntry;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveReader;
import org.apache.jackrabbit.oak.segment.util.ReaderAtEnd;
+import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -60,8 +61,6 @@ public class SegmentTarReader implements SegmentArchiveReader
{
private final Index index;
- private volatile Boolean hasGraph;
-
public SegmentTarReader(File file, FileAccess access, Index index,
IOMonitor ioMonitor) {
this.access = access;
this.file = file;
@@ -129,25 +128,18 @@ public class SegmentTarReader implements
SegmentArchiveReader {
}
@Override
- public Buffer getGraph() throws IOException {
+ public @NotNull SegmentGraph getGraph() throws IOException {
int end = access.length() - 2 * BLOCK_SIZE - getIndexEntrySize();
- Buffer graph = GraphLoader.loadGraph((whence, amount) ->
access.read(end - whence, amount));
- hasGraph = graph != null;
- return graph;
- }
-
- @Override
- public boolean hasGraph() {
- if (hasGraph == null) {
- try {
- getGraph();
- } catch (IOException ignore) { }
+ SegmentGraph graph = SegmentGraph.load((whence, amount) ->
access.read(end - whence, amount));
+ if (graph == null) {
+ log.warn("Recomputing missing graph for {}.", name);
+ graph = SegmentGraph.compute(this);
}
- return hasGraph;
+ return graph;
}
@Override
- public Buffer getBinaryReferences() throws IOException {
+ public @NotNull Buffer getBinaryReferences() throws IOException {
try {
int end = access.length() - 2 * BLOCK_SIZE - getIndexEntrySize() -
getGraphEntrySize();
return
BinaryReferencesIndexLoader.loadBinaryReferencesIndex((whence, amount) ->
access.read(end - whence, amount));
@@ -162,7 +154,7 @@ public class SegmentTarReader implements
SegmentArchiveReader {
}
@Override
- public String getName() {
+ public @NotNull String getName() {
return name;
}
@@ -181,20 +173,12 @@ public class SegmentTarReader implements
SegmentArchiveReader {
}
private int getGraphEntrySize() {
- Buffer buffer;
-
try {
- buffer = getGraph();
+ return getEntrySize(getGraph().size());
} catch (IOException e) {
log.warn("Exception while loading pre-compiled tar graph", e);
return 0;
}
-
- if (buffer == null) {
- return 0;
- }
-
- return getEntrySize(buffer.getInt(buffer.limit() - 8));
}
@Override
diff --git
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarConstants.java
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarConstants.java
index 55e4087ce7..e75c56d3bb 100644
---
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarConstants.java
+++
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarConstants.java
@@ -25,25 +25,6 @@ public class TarConstants {
static final String FILE_NAME_FORMAT = "data%05d%s.tar";
- /**
- * Magic byte sequence at the end of the graph block.
- * <p>
- * The file is read from the end (the tar file is read from the end: the
- * last entry is the index, then the graph). File format:
- * <ul>
- * <li>0 padding to make the footer end at a 512 byte boundary</li>
- * <li>The list of UUIDs (segments included the graph; this includes
- * segments in this tar file, and referenced segments in tar files with a
- * lower sequence number). 16 bytes each.</li>
- * <li>The graph data. The index of the source segment UUID (in the above
- * list, 4 bytes), then the list of referenced segments (the indexes of
- * those; 4 bytes each). Then the list is terminated by -1.</li>
- * <li>The last part is the footer, which contains metadata of the graph
- * (size, checksum, the number of UUIDs).</li>
- * </ul>
- */
- public static final int GRAPH_MAGIC = ('\n' << 24) + ('0' << 16) + ('G' <<
8) + '\n';
-
/**
* The tar file block size.
*/
diff --git
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarFiles.java
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarFiles.java
index 111a2e2f28..63936be274 100644
---
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarFiles.java
+++
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarFiles.java
@@ -16,6 +16,7 @@
*/
package org.apache.jackrabbit.oak.segment.file.tar;
+import static java.util.Collections.emptyMap;
import static
org.apache.jackrabbit.oak.commons.conditions.Validate.checkArgument;
import static java.util.Objects.requireNonNull;
@@ -26,6 +27,7 @@ import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -881,29 +883,15 @@ public class TarFiles implements Closeable {
lock.readLock().unlock();
}
- Set<UUID> index = null;
- Map<UUID, List<UUID>> graph = null;
-
for (TarReader reader : iterable(head)) {
if (fileName.equals(reader.getFileName())) {
- index = reader.getUUIDs();
- graph = reader.getGraph();
- break;
- }
- }
-
- Map<UUID, Set<UUID>> result = new HashMap<>();
- if (index != null) {
- for (UUID uuid : index) {
- result.put(uuid, emptySet());
- }
- }
- if (graph != null) {
- for (Entry<UUID, List<UUID>> entry : graph.entrySet()) {
- result.put(entry.getKey(), new HashSet<>(entry.getValue()));
+ Map<UUID, Set<UUID>> result = new HashMap<>();
+ reader.getUUIDs().forEach((uuid -> result.put(uuid,
emptySet())));
+ result.putAll(reader.getGraph().getEdges());
+ return result;
}
}
- return result;
+ return emptyMap();
}
public Map<String, Set<UUID>> getIndices() {
diff --git
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarReader.java
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarReader.java
index c1cd30e4cd..c17a4caa32 100644
---
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarReader.java
+++
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarReader.java
@@ -52,6 +52,7 @@ import
org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveEntry;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveManager;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveReader;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -279,8 +280,6 @@ public class TarReader implements Closeable {
private final Set<UUID> segmentUUIDs;
- private volatile boolean hasGraph;
-
private TarReader(SegmentArchiveManager archiveManager,
SegmentArchiveReader archive) {
this.archiveManager = archiveManager;
this.archive = archive;
@@ -342,24 +341,6 @@ public class TarReader implements Closeable {
return entryList.toArray(new SegmentArchiveEntry[entryList.size()]);
}
- /**
- * Read the references of an entry in this TAR file.
- *
- * @param id The identifier of the entry.
- * @param graph The content of the graph of this TAR file.
- * @return The references of the provided TAR entry.
- */
- @NotNull
- private static List<UUID> getReferences(UUID id, Map<UUID, List<UUID>>
graph) {
- List<UUID> references = graph.get(id);
-
- if (references == null) {
- return Collections.emptyList();
- }
-
- return references;
- }
-
/**
* Collect the references of those BLOBs that are reachable from the
entries
* in this TAR file.
@@ -379,7 +360,6 @@ public class TarReader implements Closeable {
*/
void collectBlobReferences(@NotNull Consumer<String> collector,
Predicate<GCGeneration> skipGeneration) {
BinaryReferencesIndex references = getBinaryReferences();
-
if (references == null) {
return;
}
@@ -426,12 +406,12 @@ public class TarReader implements Closeable {
* @param context An instance of {@link CleanupContext}.
*/
void mark(Set<UUID> references, Set<UUID> reclaimable, CleanupContext
context) throws IOException {
- Map<UUID, List<UUID>> graph = getGraph();
+ SegmentGraph graph = getGraph();
SegmentArchiveEntry[] entries = getEntries();
for (int i = entries.length - 1; i >= 0; i--) {
// A bulk segments is *always* written before any data segment
referencing it.
// Backward iteration ensures we see all references to bulk
segments before
- // we see the bulk segment itself. Therefore we can remove a bulk
reference
+ // we see the bulk segment itself. Therefore, we can remove a bulk
reference
// from the bulkRefs set once we encounter it, which save us some
memory and
// CPU on subsequent look-ups.
SegmentArchiveEntry entry = entries[i];
@@ -440,7 +420,7 @@ public class TarReader implements Closeable {
if (context.shouldReclaim(id, generation, references.remove(id))) {
reclaimable.add(id);
} else {
- for (UUID refId : getReferences(id, graph)) {
+ for (UUID refId : graph.getEdges(id)) {
if (context.shouldFollow(id, refId)) {
references.add(refId);
}
@@ -511,18 +491,12 @@ public class TarReader implements Closeable {
log.debug("None of the entries of {} are referenceable.", name);
return null;
}
- if (afterSize >= beforeSize * 3 / 4 && hasGraph()) {
- // the space savings are not worth it at less than 25%,
- // unless this tar file lacks a pre-compiled segment graph
- // in which case we'll always generate a new tar file with
- // the graph to speed up future garbage collection runs.
+ if (afterSize >= beforeSize * 3 / 4) {
+ // the space savings are not worth it at less than 25%
log.debug("Not enough space savings. ({}/{}). Skipping clean up of
{}",
archive.length() - afterSize, archive.length(), name);
return this;
}
- if (!hasGraph()) {
- log.warn("Recovering {}, which is missing its graph.", name);
- }
int pos = name.length() - "a.tar".length();
char generation = name.charAt(pos);
@@ -548,33 +522,20 @@ public class TarReader implements Closeable {
}
// Reconstruct the graph index for non-cleaned segments.
-
- Map<UUID, List<UUID>> graph = getGraph();
-
- for (Entry<UUID, List<UUID>> e : graph.entrySet()) {
- if (cleaned.contains(e.getKey())) {
- continue;
- }
-
- Set<UUID> vertices = new HashSet<>();
-
- for (UUID vertex : e.getValue()) {
- if (cleaned.contains(vertex)) {
- continue;
+ SegmentGraph graph = getGraph();
+ for (Entry<UUID, Set<UUID>> e : graph.getEdges().entrySet()) {
+ UUID from = e.getKey();
+ if (!cleaned.contains(from)) {
+ for (UUID to : e.getValue()) {
+ if (!cleaned.contains(to)) {
+ writer.addGraphEdge(from, to);
+ }
}
-
- vertices.add(vertex);
- }
-
- for (UUID vertex : vertices) {
- writer.addGraphEdge(e.getKey(), vertex);
}
}
// Reconstruct the binary reference index for non-cleaned segments.
-
BinaryReferencesIndex references = getBinaryReferences();
-
if (references != null) {
references.forEach((gen, full, compacted, id, reference) -> {
if (cleaned.contains(id)) {
@@ -602,22 +563,12 @@ public class TarReader implements Closeable {
}
/**
- * Loads and parses the optional pre-compiled graph entry from the given
tar
- * file.
+ * Loads and parses the pre-compiled graph entry from the tar file if it
exists, computes it otherwise.
*
- * @return The parsed graph, or {@code null} if one was not found.
+ * @return A {@link SegmentGraph} instance
*/
- Map<UUID, List<UUID>> getGraph() throws IOException {
- Buffer buffer = archive.getGraph();
- if (buffer == null) {
- return null;
- } else {
- return GraphLoader.parseGraph(buffer);
- }
- }
-
- private boolean hasGraph() {
- return archive.hasGraph();
+ @NotNull SegmentGraph getGraph() throws IOException {
+ return archive.getGraph();
}
/**
@@ -631,23 +582,20 @@ public class TarReader implements Closeable {
*
* @return An instance of {@link Map}.
*/
- BinaryReferencesIndex getBinaryReferences() {
- BinaryReferencesIndex index = null;
+ @Nullable BinaryReferencesIndex getBinaryReferences() {
try {
-
Buffer binaryReferences = archive.getBinaryReferences();
- if (binaryReferences == null && archive.isRemote()) {
-
+ if (binaryReferences == null) {
// This can happen because segment files and binary references
files are flushed one after another in
// {@link TarWriter#flush}
- log.info("The remote archive directory {} still does not have
file with binary references written.", archive.getName());
+ log.info("The archive directory {} still does not have file
with binary references written.", archive.getName());
return null;
}
- index =
BinaryReferencesIndexLoader.parseBinaryReferencesIndex(binaryReferences);
+ return
BinaryReferencesIndexLoader.parseBinaryReferencesIndex(binaryReferences);
} catch (InvalidBinaryReferencesIndexException | IOException e) {
log.warn("Exception while loading binary reference", e);
+ return null;
}
- return index;
}
/**
diff --git
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarWriter.java
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarWriter.java
index 750b7ec2ee..43516b3379 100644
---
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarWriter.java
+++
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarWriter.java
@@ -23,18 +23,11 @@ import static java.util.Objects.requireNonNull;
import static java.lang.String.format;
import static
org.apache.jackrabbit.oak.segment.file.tar.TarConstants.FILE_NAME_FORMAT;
-import static
org.apache.jackrabbit.oak.segment.file.tar.TarConstants.GRAPH_MAGIC;
import static
org.apache.jackrabbit.oak.segment.file.tar.binaries.BinaryReferencesIndexWriter.newBinaryReferencesIndexWriter;
import java.io.Closeable;
import java.io.IOException;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
import java.util.UUID;
-import java.util.zip.CRC32;
import org.apache.jackrabbit.oak.commons.Buffer;
import org.apache.jackrabbit.oak.commons.conditions.Validate;
@@ -72,7 +65,7 @@ class TarWriter implements Closeable {
/**
* Graph of references between segments.
*/
- private final Map<UUID, Set<UUID>> graph = new HashMap<>();
+ private final SegmentGraph graph = new SegmentGraph();
private final SegmentArchiveManager archiveManager;
@@ -172,7 +165,7 @@ class TarWriter implements Closeable {
}
void addGraphEdge(UUID from, UUID to) {
- graph.computeIfAbsent(from, k -> new HashSet<>()).add(to);
+ graph.addEdge(from, to);
}
/**
@@ -260,66 +253,7 @@ class TarWriter implements Closeable {
}
private void writeGraph() throws IOException {
- int graphSize = 0;
-
- // The following information are stored in the footer as meta-
- // information about the entry.
-
- // 4 bytes to store a magic number identifying this entry as containing
- // references to binary values.
- graphSize += 4;
-
- // 4 bytes to store the CRC32 checksum of the data in this entry.
- graphSize += 4;
-
- // 4 bytes to store the length of this entry, without including the
- // optional padding.
- graphSize += 4;
-
- // 4 bytes to store the number of entries in the graph map.
- graphSize += 4;
-
- // The following information are stored as part of the main content of
- // this entry, after the optional padding.
-
- for (Entry<UUID, Set<UUID>> entry : graph.entrySet()) {
- // 16 bytes to store the key of the map.
- graphSize += 16;
-
- // 4 bytes for the number of entries in the adjacency list.
- graphSize += 4;
-
- // 16 bytes for every element in the adjacency list.
- graphSize += 16 * entry.getValue().size();
- }
-
- Buffer buffer = Buffer.allocate(graphSize);
-
- for (Entry<UUID, Set<UUID>> entry : graph.entrySet()) {
- UUID from = entry.getKey();
-
- buffer.putLong(from.getMostSignificantBits());
- buffer.putLong(from.getLeastSignificantBits());
-
- Set<UUID> adj = entry.getValue();
-
- buffer.putInt(adj.size());
-
- for (UUID to : adj) {
- buffer.putLong(to.getMostSignificantBits());
- buffer.putLong(to.getLeastSignificantBits());
- }
- }
-
- CRC32 checksum = new CRC32();
- checksum.update(buffer.array(), 0, buffer.position());
-
- buffer.putInt((int) checksum.getValue());
- buffer.putInt(graph.size());
- buffer.putInt(graphSize);
- buffer.putInt(GRAPH_MAGIC);
-
- archive.writeGraph(buffer.array());
+ archive.writeGraph(graph.write());
}
synchronized long fileLength() {
diff --git
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/SegmentArchiveReader.java
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/SegmentArchiveReader.java
index 2e99a5970e..3ac897e65b 100644
---
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/SegmentArchiveReader.java
+++
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/SegmentArchiveReader.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.util.List;
import org.apache.jackrabbit.oak.commons.Buffer;
+import org.apache.jackrabbit.oak.segment.file.tar.SegmentGraph;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -61,25 +62,17 @@ public interface SegmentArchiveReader extends Closeable {
/**
* Load the segment graph.
*
- * @return byte buffer representing the graph or null if the graph hasn't
been
- * persisted.
+ * @return segment graph instance
*/
- @Nullable
- Buffer getGraph() throws IOException;
-
- /**
- * Check if the segment graph has been persisted for this archive.
- *
- * @return {@code true} if the graph exists, false otherwise
- */
- boolean hasGraph();
+ @NotNull
+ SegmentGraph getGraph() throws IOException;
/**
* Load binary references.
*
* @return byte buffer representing the binary references structure.
*/
- @NotNull
+ @Nullable
Buffer getBinaryReferences() throws IOException;
/**
diff --git
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/persistentcache/CachingSegmentArchiveReader.java
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/persistentcache/CachingSegmentArchiveReader.java
index 9c682d6b3a..df5aadb3ea 100644
---
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/persistentcache/CachingSegmentArchiveReader.java
+++
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/persistentcache/CachingSegmentArchiveReader.java
@@ -19,6 +19,7 @@
package org.apache.jackrabbit.oak.segment.spi.persistence.persistentcache;
import org.apache.jackrabbit.oak.commons.Buffer;
+import org.apache.jackrabbit.oak.segment.file.tar.SegmentGraph;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveEntry;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveReader;
import org.jetbrains.annotations.NotNull;
@@ -63,18 +64,12 @@ public class CachingSegmentArchiveReader implements
SegmentArchiveReader {
}
@Override
- @Nullable
- public Buffer getGraph() throws IOException {
+ public @NotNull SegmentGraph getGraph() throws IOException {
return delegate.getGraph();
}
@Override
- public boolean hasGraph() {
- return delegate.hasGraph();
- }
-
- @Override
- @NotNull
+ @Nullable
public Buffer getBinaryReferences() throws IOException {
return delegate.getBinaryReferences();
}
diff --git
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/persistentcache/package-info.java
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/persistentcache/package-info.java
index 493125d01b..db4c23c990 100644
---
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/persistentcache/package-info.java
+++
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/persistentcache/package-info.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
@Internal(since = "1.0.0")
-@Version("4.1.0")
+@Version("5.0.0")
package org.apache.jackrabbit.oak.segment.spi.persistence.persistentcache;
import org.apache.jackrabbit.oak.commons.annotations.Internal;
diff --git
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/split/UnclosedSegmentArchiveReader.java
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/split/UnclosedSegmentArchiveReader.java
index 37c74024b6..d6902c757d 100644
---
a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/split/UnclosedSegmentArchiveReader.java
+++
b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/spi/persistence/split/UnclosedSegmentArchiveReader.java
@@ -20,6 +20,7 @@ import java.io.IOException;
import java.util.List;
import org.apache.jackrabbit.oak.commons.Buffer;
+import org.apache.jackrabbit.oak.segment.file.tar.SegmentGraph;
import
org.apache.jackrabbit.oak.segment.file.tar.binaries.BinaryReferencesIndexWriter;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveEntry;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveReader;
@@ -52,15 +53,10 @@ class UnclosedSegmentArchiveReader implements
SegmentArchiveReader {
}
@Override
- public @Nullable Buffer getGraph() throws IOException {
+ public @NotNull SegmentGraph getGraph() throws IOException {
return delegate.getGraph();
}
- @Override
- public boolean hasGraph() {
- return delegate.hasGraph();
- }
-
@Override
public @NotNull Buffer getBinaryReferences() throws IOException {
Buffer buffer = delegate.getBinaryReferences();
diff --git
a/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/TarFileTest.java
b/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/TarFileTest.java
index f2350c35c5..972d462659 100644
---
a/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/TarFileTest.java
+++
b/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/TarFileTest.java
@@ -255,12 +255,10 @@ public class TarFileTest {
Set<UUID> sweep = newSet(new UUID(1, 2), new UUID(2, 3));
try (TarReader reader = TarReader.open("data00000a.tar",
archiveManager)) {
- try (TarReader swept = reader.sweep(sweep, new HashSet<UUID>())) {
+ try (TarReader swept = reader.sweep(sweep, new HashSet<>())) {
assertNotNull(swept);
-
- Map<UUID, List<UUID>> graph = new HashMap<>();
- graph.put(new UUID(2, 1), List.of(new UUID(2, 2)));
-
+ SegmentGraph graph = new SegmentGraph();
+ graph.addEdge(new UUID(2, 1), new UUID(2, 2));
assertEquals(graph, swept.getGraph());
}
}