/**
* 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.db;
import java.io.File;
import java.io.IOException;
import java.util.*;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.config.Config.DiskFailurePolicy;
import org.apache.cassandra.db.Directories.DataDirectory;
import org.apache.cassandra.io.sstable.Component;
import org.apache.cassandra.io.sstable.Descriptor;
import org.apache.cassandra.io.util.FileUtils;
public class DirectoriesTest
{
private static File tempDataDir;
private static String KS = "ks";
private static String[] CFS = new String[] { "cf1", "ks" };
private static Map<String, List<File>> files = new HashMap<String, List<File>>();
@BeforeClass
public static void beforeClass() throws IOException
{
tempDataDir = File.createTempFile("cassandra", "unittest");
tempDataDir.delete(); // hack to create a temp dir
tempDataDir.mkdir();
Directories.overrideDataDirectoriesForTest(tempDataDir.getPath());
// Create two fake data dir for tests, one using CF directories, one that do not.
createTestFiles();
}
@AfterClass
public static void afterClass()
{
Directories.resetDataDirectoriesAfterTest();
FileUtils.deleteRecursive(tempDataDir);
}
private static void createTestFiles() throws IOException
{
for (String cf : CFS)
{
List<File> fs = new ArrayList<File>();
files.put(cf, fs);
File dir = cfDir(cf);
dir.mkdirs();
createFakeSSTable(dir, cf, 1, false, fs);
createFakeSSTable(dir, cf, 2, true, fs);
File backupDir = new File(dir, Directories.BACKUPS_SUBDIR);
backupDir.mkdir();
createFakeSSTable(backupDir, cf, 1, false, fs);
File snapshotDir = new File(dir, Directories.SNAPSHOT_SUBDIR + File.separator + "42");
snapshotDir.mkdirs();
createFakeSSTable(snapshotDir, cf, 1, false, fs);
}
}
private static void createFakeSSTable(File dir, String cf, int gen, boolean temp, List<File> addTo) throws IOException
{
Descriptor desc = new Descriptor(dir, KS, cf, gen, temp);
for (Component c : new Component[]{ Component.DATA, Component.PRIMARY_INDEX, Component.FILTER })
{
File f = new File(desc.filenameFor(c));
f.createNewFile();
addTo.add(f);
}
}
private static File cfDir(String cf)
{
return new File(tempDataDir, KS + File.separator + cf);
}
@Test
public void testStandardDirs()
{
for (String cf : CFS)
{
Directories directories = Directories.create(KS, cf);
Assert.assertEquals(cfDir(cf), directories.getDirectoryForNewSSTables());
Descriptor desc = new Descriptor(cfDir(cf), KS, cf, 1, false);
File snapshotDir = new File(cfDir(cf), File.separator + Directories.SNAPSHOT_SUBDIR + File.separator + "42");
Assert.assertEquals(snapshotDir, directories.getSnapshotDirectory(desc, "42"));
File backupsDir = new File(cfDir(cf), File.separator + Directories.BACKUPS_SUBDIR);
Assert.assertEquals(backupsDir, directories.getBackupsDirectory(desc));
}
}
@Test
public void testSSTableLister()
{
for (String cf : CFS)
{
Directories directories = Directories.create(KS, cf);
Directories.SSTableLister lister;
Set<File> listed;
// List all but no snapshot, backup
lister = directories.sstableLister();
listed = new HashSet<File>(lister.listFiles());
for (File f : files.get(cf))
{
if (f.getPath().contains(Directories.SNAPSHOT_SUBDIR) || f.getPath().contains(Directories.BACKUPS_SUBDIR))
assert !listed.contains(f) : f + " should not be listed";
else
assert listed.contains(f) : f + " is missing";
}
// List all but including backup (but no snapshot)
lister = directories.sstableLister().includeBackups(true);
listed = new HashSet<File>(lister.listFiles());
for (File f : files.get(cf))
{
if (f.getPath().contains(Directories.SNAPSHOT_SUBDIR))
assert !listed.contains(f) : f + " should not be listed";
else
assert listed.contains(f) : f + " is missing";
}
// Skip temporary and compacted
lister = directories.sstableLister().skipTemporary(true);
listed = new HashSet<File>(lister.listFiles());
for (File f : files.get(cf))
{
if (f.getPath().contains(Directories.SNAPSHOT_SUBDIR) || f.getPath().contains(Directories.BACKUPS_SUBDIR))
assert !listed.contains(f) : f + " should not be listed";
else if (f.getName().contains("-tmp-"))
assert !listed.contains(f) : f + " should not be listed";
else
assert listed.contains(f) : f + " is missing";
}
}
}
@Test
public void testDiskFailurePolicy_best_effort() throws IOException
{
DiskFailurePolicy origPolicy = DatabaseDescriptor.getDiskFailurePolicy();
try
{
DatabaseDescriptor.setDiskFailurePolicy(DiskFailurePolicy.best_effort);
for (DataDirectory dd : Directories.dataFileLocations)
{
dd.location.setExecutable(false);
dd.location.setWritable(false);
}
Directories.create(KS, "bad");
for (DataDirectory dd : Directories.dataFileLocations)
{
File file = new File(dd.location, new File(KS, "bad").getPath());
Assert.assertTrue(BlacklistedDirectories.isUnwritable(file));
}
}
finally
{
for (DataDirectory dd : Directories.dataFileLocations)
{
dd.location.setExecutable(true);
dd.location.setWritable(true);
}
DatabaseDescriptor.setDiskFailurePolicy(origPolicy);
}
}
}