blob: 8686685b0bedd7bf9bc8519be46684dec4488b88 [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.accumulo.manager.upgrade;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import org.apache.accumulo.core.conf.AccumuloConfiguration;
import org.apache.accumulo.core.conf.ConfigurationCopy;
import org.apache.accumulo.core.conf.Property;
import org.apache.accumulo.core.spi.fs.RandomVolumeChooser;
import org.apache.accumulo.server.fs.VolumeManager;
import org.apache.accumulo.server.fs.VolumeManagerImpl;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "paths not set by user input")
public class RootFilesUpgradeTest {
@Rule
public TemporaryFolder tempFolder =
new TemporaryFolder(new File(System.getProperty("user.dir") + "/target"));
static void rename(VolumeManager fs, Path src, Path dst) throws IOException {
if (!fs.rename(src, dst)) {
throw new IOException("Rename " + src + " to " + dst + " returned false ");
}
}
private class TestWrapper {
File rootTabletDir;
Set<Path> oldDatafiles;
String compactName;
Path tmpDatafile;
Path newDatafile;
VolumeManager vm;
AccumuloConfiguration conf;
public void prepareReplacement(VolumeManager fs, Path location, Set<Path> oldDatafiles,
String compactName) throws IOException {
for (Path path : oldDatafiles) {
rename(fs, path, new Path(location + "/delete+" + compactName + "+" + path.getName()));
}
}
public void renameReplacement(VolumeManager fs, Path tmpDatafile, Path newDatafile)
throws IOException {
if (fs.exists(newDatafile)) {
throw new IllegalStateException("Target map file already exist " + newDatafile);
}
rename(fs, tmpDatafile, newDatafile);
}
public void finishReplacement(AccumuloConfiguration acuTableConf, VolumeManager fs,
Path location, Set<Path> oldDatafiles, String compactName) throws IOException {
// start deleting files, if we do not finish they will be cleaned
// up later
for (Path path : oldDatafiles) {
Path deleteFile = new Path(location + "/delete+" + compactName + "+" + path.getName());
if (acuTableConf.getBoolean(Property.GC_TRASH_IGNORE) || !fs.moveToTrash(deleteFile))
fs.deleteRecursively(deleteFile);
}
}
TestWrapper(VolumeManager vm, AccumuloConfiguration conf, String compactName,
String... inputFiles) throws IOException {
this.vm = vm;
this.conf = conf;
rootTabletDir = new File(tempFolder.newFolder(), "accumulo/tables/+r/root_tablet");
assertTrue(rootTabletDir.mkdirs() || rootTabletDir.isDirectory());
oldDatafiles = new HashSet<>();
for (String filename : inputFiles) {
File file = new File(rootTabletDir, filename);
assertTrue(file.createNewFile());
oldDatafiles.add(new Path(file.toURI()));
}
this.compactName = compactName;
File tmpFile = new File(rootTabletDir, compactName + "_tmp");
assertTrue(tmpFile.createNewFile());
tmpDatafile = new Path(tmpFile.toURI());
newDatafile = new Path(new File(rootTabletDir, compactName).toURI());
}
void prepareReplacement() throws IOException {
prepareReplacement(vm, new Path(rootTabletDir.toURI()), oldDatafiles, compactName);
}
void renameReplacement() throws IOException {
renameReplacement(vm, tmpDatafile, newDatafile);
}
public void finishReplacement() throws IOException {
finishReplacement(conf, vm, new Path(rootTabletDir.toURI()), oldDatafiles, compactName);
}
public Collection<String> cleanupReplacement(String... expectedFiles) throws IOException {
Collection<String> ret =
Upgrader9to10.cleanupRootTabletFiles(vm, rootTabletDir.toString()).keySet();
HashSet<String> expected = new HashSet<>();
for (String efile : expectedFiles)
expected.add(new File(rootTabletDir, efile).toURI().toString());
assertEquals(expected, new HashSet<>(ret));
return ret;
}
public void assertFiles(String... files) {
HashSet<String> actual = new HashSet<>();
File[] children = rootTabletDir.listFiles();
if (children != null) {
for (File file : children) {
actual.add(file.getName());
}
}
HashSet<String> expected = new HashSet<>();
expected.addAll(Arrays.asList(files));
assertEquals(expected, actual);
}
}
@Test
public void testFileReplacement() throws IOException {
ConfigurationCopy conf = new ConfigurationCopy();
conf.set(Property.INSTANCE_VOLUMES, "file:///");
conf.set(Property.GENERAL_VOLUME_CHOOSER, RandomVolumeChooser.class.getName());
try (var vm = VolumeManagerImpl.get(conf, new Configuration())) {
TestWrapper wrapper = new TestWrapper(vm, conf, "A00004.rf", "A00002.rf", "F00003.rf");
wrapper.prepareReplacement();
wrapper.renameReplacement();
wrapper.finishReplacement();
wrapper.assertFiles("A00004.rf");
wrapper = new TestWrapper(vm, conf, "A00004.rf", "A00002.rf", "F00003.rf");
wrapper.prepareReplacement();
wrapper.cleanupReplacement("A00002.rf", "F00003.rf");
wrapper.assertFiles("A00002.rf", "F00003.rf");
wrapper = new TestWrapper(vm, conf, "A00004.rf", "A00002.rf", "F00003.rf");
wrapper.prepareReplacement();
wrapper.renameReplacement();
wrapper.cleanupReplacement("A00004.rf");
wrapper.assertFiles("A00004.rf");
wrapper = new TestWrapper(vm, conf, "A00004.rf", "A00002.rf", "F00003.rf");
wrapper.prepareReplacement();
wrapper.renameReplacement();
wrapper.finishReplacement();
wrapper.cleanupReplacement("A00004.rf");
wrapper.assertFiles("A00004.rf");
}
}
}