diff --git a/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/split/SplitPersistenceTest.java b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/split/SplitPersistenceTest.java index deb68e4a46..1337d71dc9 100644 --- a/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/split/SplitPersistenceTest.java +++ b/oak-segment-azure/src/test/java/org/apache/jackrabbit/oak/segment/split/SplitPersistenceTest.java @@ -26,6 +26,13 @@ import org.apache.jackrabbit.oak.segment.file.FileStore; import org.apache.jackrabbit.oak.segment.file.FileStoreBuilder; import org.apache.jackrabbit.oak.segment.file.InvalidFileStoreVersionException; import org.apache.jackrabbit.oak.segment.file.tar.TarPersistence; +import org.apache.jackrabbit.oak.segment.file.tar.binaries.BinaryReferencesIndex; +import org.apache.jackrabbit.oak.segment.file.tar.binaries.BinaryReferencesIndexLoader; +import org.apache.jackrabbit.oak.segment.file.tar.binaries.InvalidBinaryReferencesIndexException; +import org.apache.jackrabbit.oak.segment.spi.monitor.FileStoreMonitorAdapter; +import org.apache.jackrabbit.oak.segment.spi.monitor.IOMonitorAdapter; +import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveManager; +import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveReader; import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentNodeStorePersistence; import org.apache.jackrabbit.oak.spi.commit.CommitInfo; import org.apache.jackrabbit.oak.spi.commit.EmptyHook; @@ -41,6 +48,7 @@ import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.security.InvalidKeyException; +import java.util.UUID; import static org.junit.Assert.assertEquals; @@ -60,6 +68,8 @@ public class SplitPersistenceTest { private FileStore splitFileStore; + private SegmentNodeStorePersistence splitPersistence; + @Before public void setup() throws IOException, InvalidFileStoreVersionException, CommitFailedException, URISyntaxException, InvalidKeyException, StorageException { SegmentNodeStorePersistence sharedPersistence = new AzurePersistence(azurite.getContainer("oak-test").getDirectoryReference("oak")); @@ -76,7 +86,7 @@ public class SplitPersistenceTest { baseFileStore.flush(); SegmentNodeStorePersistence localPersistence = new TarPersistence(folder.newFolder()); - SegmentNodeStorePersistence splitPersistence = new SplitPersistence(sharedPersistence, localPersistence); + splitPersistence = new SplitPersistence(sharedPersistence, localPersistence); splitFileStore = FileStoreBuilder .fileStoreBuilder(folder.newFolder()) @@ -87,8 +97,13 @@ public class SplitPersistenceTest { @After public void tearDown() { - splitFileStore.close(); - baseFileStore.close(); + if (splitFileStore != null) { + splitFileStore.close(); + } + + if (baseFileStore != null) { + baseFileStore.close(); + } } @Test @@ -113,4 +128,17 @@ public class SplitPersistenceTest { assertEquals("v1", base.getRoot().getChildNode("foo").getChildNode("bar").getString("version")); } + + @Test + public void testBinaryReferencesAreNotNull() throws IOException, InvalidBinaryReferencesIndexException { + splitFileStore.close(); + splitFileStore = null; + + SegmentArchiveManager manager = splitPersistence.createArchiveManager(true, new IOMonitorAdapter(), new FileStoreMonitorAdapter()); + for (String archive : manager.listArchives()) { + SegmentArchiveReader reader = manager.open(archive); + BinaryReferencesIndexLoader.parseBinaryReferencesIndex(reader.getBinaryReferences()); + reader.close(); + } + } } diff --git a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/SplitSegmentArchiveManager.java b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/SplitSegmentArchiveManager.java index 16ef503ffb..e4ea631d43 100644 --- a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/SplitSegmentArchiveManager.java +++ b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/SplitSegmentArchiveManager.java @@ -63,8 +63,8 @@ public class SplitSegmentArchiveManager implements SegmentArchiveManager { @Override public @Nullable SegmentArchiveReader open(@NotNull String archiveName) throws IOException { - SegmentArchiveReader reader = null; if (roArchiveList.contains(archiveName)) { + SegmentArchiveReader reader = null; try { reader = roArchiveManager.open(archiveName); } catch (IOException e) { @@ -73,10 +73,10 @@ public class SplitSegmentArchiveManager implements SegmentArchiveManager { if (reader == null) { reader = roArchiveManager.forceOpen(archiveName); } + return new UnclosedSegmentArchiveReader(reader); } else { - reader = rwArchiveManager.open(archiveName); + return rwArchiveManager.open(archiveName); } - return reader; } @Override @@ -135,4 +135,5 @@ public class SplitSegmentArchiveManager implements SegmentArchiveManager { rwArchiveManager.recoverEntries(archiveName, entries); } } + } diff --git a/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/UnclosedSegmentArchiveReader.java b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/UnclosedSegmentArchiveReader.java new file mode 100644 index 0000000000..9f54ff8255 --- /dev/null +++ b/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/split/UnclosedSegmentArchiveReader.java @@ -0,0 +1,93 @@ +/* + * 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.split; + +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; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.List; + +class UnclosedSegmentArchiveReader implements SegmentArchiveReader { + + private final SegmentArchiveReader delegate; + + private static final ByteBuffer EMPTY_BINARY_REF = ByteBuffer.wrap(BinaryReferencesIndexWriter.newBinaryReferencesIndexWriter().write()).asReadOnlyBuffer(); + + UnclosedSegmentArchiveReader(SegmentArchiveReader delegate) { + this.delegate = delegate; + } + + @Override + public @Nullable ByteBuffer readSegment(long msb, long lsb) throws IOException { + return delegate.readSegment(msb, lsb); + } + + @Override + public boolean containsSegment(long msb, long lsb) { + return delegate.containsSegment(msb, lsb); + } + + @Override + public List listSegments() { + return delegate.listSegments(); + } + + @Override + public @Nullable ByteBuffer getGraph() throws IOException { + return delegate.getGraph(); + } + + @Override + public boolean hasGraph() { + return delegate.hasGraph(); + } + + @Override + public @NotNull ByteBuffer getBinaryReferences() throws IOException { + ByteBuffer buffer = delegate.getBinaryReferences(); + if (buffer == null) { + return EMPTY_BINARY_REF; + } else { + return buffer; + } + } + + @Override + public long length() { + return delegate.length(); + } + + @Override + public @NotNull String getName() { + return delegate.getName(); + } + + @Override + public void close() throws IOException { + delegate.close(); + } + + @Override + public int getEntrySize(int size) { + return delegate.getEntrySize(size); + } +}