blob: 55295d40af319c361f99958f8970ee6f33743960 [file] [log] [blame]
/*
* 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 com.google.common.base.Charsets.UTF_8;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import static org.apache.jackrabbit.oak.segment.file.tar.GCGeneration.newGCGeneration;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.internal.util.collections.Sets.newSet;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
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.SegmentArchiveEntry;
import org.apache.jackrabbit.oak.segment.spi.persistence.SegmentArchiveManager;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class TarFileTest {
protected static GCGeneration generation(int full) {
return newGCGeneration(full, 0, false);
}
@Rule
public TemporaryFolder folder = new TemporaryFolder(new File("target"));
protected SegmentArchiveManager archiveManager;
@Before
public void setUp() throws IOException {
archiveManager = new SegmentTarManager(folder.newFolder(), new FileStoreMonitorAdapter(), new IOMonitorAdapter(), false);
}
protected long getWriteAndReadExpectedSize() {
return 5120;
}
@Test
public void testWriteAndRead() throws IOException {
UUID id = UUID.randomUUID();
long msb = id.getMostSignificantBits();
long lsb = id.getLeastSignificantBits() & (-1 >>> 4); // OAK-1672
byte[] data = "Hello, World!".getBytes(UTF_8);
try (TarWriter writer = new TarWriter(archiveManager, "data00000a.tar")) {
writer.writeEntry(msb, lsb, data, 0, data.length, generation(0));
assertEquals(ByteBuffer.wrap(data), writer.readEntry(msb, lsb));
}
try (TarReader reader = TarReader.open("data00000a.tar", archiveManager)) {
assertEquals(getWriteAndReadExpectedSize(), reader.size());
assertEquals(ByteBuffer.wrap(data), reader.readEntry(msb, lsb));
}
}
@Test
public void testGCGeneration() throws Exception {
UUID id = UUID.randomUUID();
long msb = id.getMostSignificantBits();
long lsb = id.getLeastSignificantBits();
String data = "test";
byte[] buffer = data.getBytes(UTF_8);
try (TarWriter writer = new TarWriter(archiveManager, "data00000a.tar")) {
writer.writeEntry(msb, lsb, buffer, 0, buffer.length, newGCGeneration(1, 2, false));
}
try (TarReader reader = TarReader.open("data00000a.tar", archiveManager)) {
SegmentArchiveEntry[] entries = reader.getEntries();
assertEquals(newGCGeneration(1, 2, false), newGCGeneration(entries[0]));
}
}
@Test
public void testGCGenerationIsCompactedFlagNotErased() throws Exception {
UUID id = UUID.randomUUID();
long msb = id.getMostSignificantBits();
long lsb = id.getLeastSignificantBits();
String data = "test";
byte[] buffer = data.getBytes(UTF_8);
try (TarWriter writer = new TarWriter(archiveManager, "data00000a.tar")) {
writer.writeEntry(msb, lsb, buffer, 0, buffer.length, newGCGeneration(1, 2, true));
}
try (TarReader reader = TarReader.open("data00000a.tar", archiveManager)) {
SegmentArchiveEntry[] entries = reader.getEntries();
assertEquals(newGCGeneration(1, 2, true), newGCGeneration(entries[0]));
}
}
@Test
public void testWriteAndReadBinaryReferences() throws Exception {
try (TarWriter writer = new TarWriter(archiveManager, "data00000a.tar")) {
writer.writeEntry(0x00, 0x00, new byte[] {0x01, 0x02, 0x3}, 0, 3, generation(0));
writer.addBinaryReference(generation(1), new UUID(1, 0), "r0");
writer.addBinaryReference(generation(1), new UUID(1, 1), "r1");
writer.addBinaryReference(generation(1), new UUID(1, 2), "r2");
writer.addBinaryReference(generation(1), new UUID(1, 3), "r3");
writer.addBinaryReference(generation(2), new UUID(2, 0), "r4");
writer.addBinaryReference(generation(2), new UUID(2, 1), "r5");
writer.addBinaryReference(generation(2), new UUID(2, 2), "r6");
writer.addBinaryReference(generation(3), new UUID(3, 0), "r7");
writer.addBinaryReference(generation(3), new UUID(3, 1), "r8");
}
Map<UUID, Set<String>> one = newHashMap();
one.put(new UUID(1, 0), newSet("r0"));
one.put(new UUID(1, 1), newSet("r1"));
one.put(new UUID(1, 2), newSet("r2"));
one.put(new UUID(1, 3), newSet("r3"));
Map<UUID, Set<String>> two = newHashMap();
two.put(new UUID(2, 0), newSet("r4"));
two.put(new UUID(2, 1), newSet("r5"));
two.put(new UUID(2, 2), newSet("r6"));
Map<UUID, Set<String>> three = newHashMap();
three.put(new UUID(3, 0), newSet("r7"));
three.put(new UUID(3, 1), newSet("r8"));
Map<GCGeneration, Map<UUID, Set<String>>> expected = newHashMap();
expected.put(generation(1), one);
expected.put(generation(2), two);
expected.put(generation(3), three);
try (TarReader reader = TarReader.open("data00000a.tar", archiveManager)) {
Map<GCGeneration, Map<UUID, Set<String>>> actual = new HashMap<>();
reader.getBinaryReferences().forEach((generation, full, compacted, id, reference) -> {
actual
.computeIfAbsent(newGCGeneration(generation, full, compacted), x -> new HashMap<>())
.computeIfAbsent(id, x -> new HashSet<>())
.add(reference);
});
assertEquals(expected, actual);
}
}
@Test
public void binaryReferencesIndexShouldBeTrimmedDownOnSweep() throws Exception {
try (TarWriter writer = new TarWriter(archiveManager, "data00000a.tar")) {
writer.writeEntry(1, 1, new byte[] {1}, 0, 1, generation(1));
writer.writeEntry(1, 2, new byte[] {1}, 0, 1, generation(1));
writer.writeEntry(2, 1, new byte[] {1}, 0, 1, generation(2));
writer.writeEntry(2, 2, new byte[] {1}, 0, 1, generation(2));
writer.addBinaryReference(generation(1), new UUID(1, 1), "a");
writer.addBinaryReference(generation(1), new UUID(1, 2), "b");
writer.addBinaryReference(generation(2), new UUID(2, 1), "c");
writer.addBinaryReference(generation(2), new UUID(2, 2), "d");
}
Set<UUID> sweep = newSet(new UUID(1, 1), new UUID(2, 2));
try (TarReader reader = TarReader.open("data00000a.tar", archiveManager)) {
try (TarReader swept = reader.sweep(sweep, new HashSet<>())) {
assertNotNull(swept);
Map<UUID, Set<String>> one = newHashMap();
one.put(new UUID(1, 2), newSet("b"));
Map<UUID, Set<String>> two = newHashMap();
two.put(new UUID(2, 1), newSet("c"));
Map<GCGeneration, Map<UUID, Set<String>>> references = newHashMap();
references.put(generation(1), one);
references.put(generation(2), two);
Map<GCGeneration, Map<UUID, Set<String>>> actual = new HashMap<>();
swept.getBinaryReferences().forEach((generation, full, compacted, uuid, reference) -> {
actual
.computeIfAbsent(newGCGeneration(generation, full, compacted), x -> new HashMap<>())
.computeIfAbsent(uuid, x -> new HashSet<>())
.add(reference);
});
assertEquals(references, actual);
}
}
}
@Test
public void binaryReferencesIndexShouldContainCompleteGCGeneration() throws Exception {
try (TarWriter writer = new TarWriter(archiveManager, "data00000a.tar")) {
writer.writeEntry(0x00, 0x00, new byte[] {0x01, 0x02, 0x3}, 0, 3, generation(0));
writer.addBinaryReference(newGCGeneration(1, 2, false), new UUID(1, 2), "r1");
writer.addBinaryReference(newGCGeneration(3, 4, true), new UUID(3, 4), "r2");
}
try (TarReader reader = TarReader.open("data00000a.tar", archiveManager)) {
Set<GCGeneration> expected = new HashSet<>();
expected.add(newGCGeneration(1, 2, false));
expected.add(newGCGeneration(3, 4, true));
Set<GCGeneration> actual = new HashSet<>();
reader.getBinaryReferences().forEach((generation, full, compacted, segment, reference) -> {
actual.add(newGCGeneration(generation, full, compacted));
});
assertEquals(expected, actual);
}
}
@Test
public void graphShouldBeTrimmedDownOnSweep() throws Exception {
try (TarWriter writer = new TarWriter(archiveManager, "data00000a.tar")) {
writer.writeEntry(1, 1, new byte[] {1}, 0, 1, generation(1));
writer.writeEntry(1, 2, new byte[] {1}, 0, 1, generation(1));
writer.writeEntry(1, 3, new byte[] {1}, 0, 1, generation(1));
writer.writeEntry(2, 1, new byte[] {1}, 0, 1, generation(2));
writer.writeEntry(2, 2, new byte[] {1}, 0, 1, generation(2));
writer.writeEntry(2, 3, new byte[] {1}, 0, 1, generation(2));
writer.addGraphEdge(new UUID(1, 1), new UUID(1, 2));
writer.addGraphEdge(new UUID(1, 2), new UUID(1, 3));
writer.addGraphEdge(new UUID(2, 1), new UUID(2, 2));
writer.addGraphEdge(new UUID(2, 2), new UUID(2, 3));
}
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>())) {
assertNotNull(swept);
Map<UUID, List<UUID>> graph = newHashMap();
graph.put(new UUID(2, 1), newArrayList(new UUID(2, 2)));
assertEquals(graph, swept.getGraph());
}
}
}
}