blob: 13705f9b34b99eb683f1fdb7f41be7159cff9451 [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.cassandra.tools;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.apache.cassandra.db.ColumnFamilyStore;
import org.apache.cassandra.db.Directories;
import org.apache.cassandra.db.Keyspace;
import org.apache.cassandra.distributed.shared.WithProperties;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.StartupException;
import org.apache.cassandra.io.sstable.LegacySSTableTest;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.tools.ToolRunner.ToolResult;
import org.assertj.core.api.Assertions;
import static org.apache.cassandra.config.CassandraRelevantProperties.TEST_UTIL_ALLOW_TOOL_REINIT_FOR_TEST;
import static org.junit.Assert.assertEquals;
/*
* SStableUpdater should be run with the server shutdown, but we need to set up a certain env to be able to
* load/swap/drop sstable files under the test's feet. Hence why we need a separate file vs StandaloneUpgraderTest.
*
* Caution: heavy hacking ahead.
*/
public class StandaloneUpgraderOnSStablesTest
{
static WithProperties properties;
String legacyId = LegacySSTableTest.legacyVersions[LegacySSTableTest.legacyVersions.length - 1];
@BeforeClass
public static void defineSchema() throws ConfigurationException
{
LegacySSTableTest.defineSchema();
properties = new WithProperties().set(TEST_UTIL_ALLOW_TOOL_REINIT_FOR_TEST, true);
}
@AfterClass
public static void clearClassEnv()
{
properties.close();
}
@Test
public void testUpgradeKeepFiles() throws Throwable
{
LegacySSTableTest.truncateLegacyTables(legacyId);
LegacySSTableTest.loadLegacyTables(legacyId);
List<String> origFiles = getSStableFiles("legacy_tables", "legacy_" + legacyId + "_simple");
ToolResult tool = ToolRunner.invokeClass(StandaloneUpgrader.class,
"-k",
"legacy_tables",
"legacy_" + legacyId + "_simple");
checkUpgradeToolOutput(tool, origFiles);
tool.assertOnCleanExit();
List<String> newFiles = getSStableFiles("legacy_tables", "legacy_" + legacyId + "_simple");
origFiles.removeAll(newFiles);
assertEquals(0, origFiles.size()); // check previous version files are kept
// need to make sure the new sstables are live, so that they get truncated later
Keyspace.open("legacy_tables").getColumnFamilyStore("legacy_" + legacyId + "_simple").loadNewSSTables();
}
@Test
public void testUpgradeSnapshot() throws Throwable
{
LegacySSTableTest.truncateLegacyTables(legacyId);
LegacySSTableTest.loadLegacyTables(legacyId);
StorageService.instance.takeSnapshot("testsnapshot",
Collections.emptyMap(),
"legacy_tables.legacy_" + legacyId + "_simple");
ToolResult tool = ToolRunner.invokeClass(StandaloneUpgrader.class,
"-k",
"legacy_tables",
"legacy_" + legacyId + "_simple",
"wrongsnapshot");
Assertions.assertThat(tool.getStdout()).contains("Found 0 sstables that need upgrading.");
ColumnFamilyStore cfs = ColumnFamilyStore.getIfExists("legacy_tables", "legacy_" + legacyId + "_simple");
List<String> names = cfs.getDirectories()
.sstableLister(Directories.OnTxnErr.IGNORE)
.snapshots("testsnapshot").list().keySet().stream()
.map(descriptor -> descriptor.baseFile().toString())
.collect(Collectors.toList());
tool = ToolRunner.invokeClass(StandaloneUpgrader.class,
"legacy_tables",
"legacy_" + legacyId + "_simple",
"testsnapshot");
checkUpgradeToolOutput(tool, names);
tool.assertOnCleanExit();
}
@Test
public void testUpgrade() throws Throwable
{
LegacySSTableTest.truncateLegacyTables(legacyId);
LegacySSTableTest.loadLegacyTables(legacyId);
List<String> origFiles = getSStableFiles("legacy_tables", "legacy_" + legacyId + "_simple");
ToolResult tool = ToolRunner.invokeClass(StandaloneUpgrader.class,
"legacy_tables",
"legacy_" + legacyId + "_simple");
checkUpgradeToolOutput(tool, origFiles);
tool.assertOnCleanExit();
List<String> newFiles = getSStableFiles("legacy_tables", "legacy_" + legacyId + "_simple");
int origSize = origFiles.size();
origFiles.removeAll(newFiles);
assertEquals(origSize, origFiles.size()); // check previous version files are gone
// need to make sure the new sstables are live, so that they get truncated later
Keyspace.open("legacy_tables").getColumnFamilyStore("legacy_" + legacyId + "_simple").loadNewSSTables();
}
private static void checkUpgradeToolOutput(ToolResult tool, List<String> names)
{
Assertions.assertThat(tool.getStdout()).contains("Found " + names.size() + " sstables that need upgrading.");
for (String name : names)
{
Assertions.assertThat(tool.getStdout()).matches("(?s).*Upgrading.*" + Pattern.quote(name) + ".*");
Assertions.assertThat(tool.getStdout()).matches("(?s).*Upgrade of.*" + Pattern.quote(name) + ".*complete.*");
}
}
private List<String> getSStableFiles(String ks, String table) throws StartupException
{
ColumnFamilyStore cfs = Keyspace.open(ks).getColumnFamilyStore(table);
org.apache.cassandra.Util.flush(cfs);
ColumnFamilyStore.scrubDataDirectories(cfs.metadata());
return cfs.getDirectories()
.sstableLister(Directories.OnTxnErr.IGNORE).list().keySet().stream()
.map(descriptor -> descriptor.baseFile().toString())
.collect(Collectors.toList());
}
}