Repository: cassandra Updated Branches: refs/heads/trunk 0ae5def83 -> d13a996e4
Shorten SSTable path patch by yukim; reviewed by Josh McKenzie for CASSANDRA-6962 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/d13a996e Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/d13a996e Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/d13a996e Branch: refs/heads/trunk Commit: d13a996e45a3294a7c16102bf9d3da881ae2c732 Parents: 0ae5def Author: Yuki Morishita <[email protected]> Authored: Mon Jul 7 10:53:01 2014 -0500 Committer: Yuki Morishita <[email protected]> Committed: Mon Jul 7 10:53:01 2014 -0500 ---------------------------------------------------------------------- CHANGES.txt | 1 + NEWS.txt | 7 ++ .../org/apache/cassandra/db/Directories.java | 64 +++++++--- .../db/compaction/CompactionManager.java | 2 +- .../db/compaction/CompactionManagerMBean.java | 3 +- .../apache/cassandra/io/sstable/Descriptor.java | 102 ++++++++++++---- .../apache/cassandra/io/sstable/SSTable.java | 9 +- .../apache/cassandra/db/DirectoriesTest.java | 2 +- .../db/compaction/CompactionsTest.java | 2 +- .../cassandra/io/sstable/DescriptorTest.java | 120 +++++++++++++++++++ .../cassandra/io/sstable/SSTableUtils.java | 8 +- 11 files changed, 265 insertions(+), 55 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/d13a996e/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index e80ab9f..5cbf4bb 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -9,6 +9,7 @@ * Make incremental repair default (CASSANDRA-7250) * Enable code coverage thru JaCoCo (CASSANDRA-7226) * Switch external naming of 'column families' to 'tables' (CASSANDRA-4369) + * Shorten SSTable path (CASSANDRA-6962) 2.1.1 http://git-wip-us.apache.org/repos/asf/cassandra/blob/d13a996e/NEWS.txt ---------------------------------------------------------------------- diff --git a/NEWS.txt b/NEWS.txt index 232cdf7..b51faec 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -16,6 +16,13 @@ using the provided 'sstableupgrade' tool. 3.0 === +New features +------------ + - SSTable file name is changed. Now you don't have Keyspace/CF name + in file name. Also, secondary index has its own directory under parent's + directory. + + Upgrading --------- - CQL2 has been removed entirely in this release (previously deprecated http://git-wip-us.apache.org/repos/asf/cassandra/blob/d13a996e/src/java/org/apache/cassandra/db/Directories.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/Directories.java b/src/java/org/apache/cassandra/db/Directories.java index 4319481..d62ebeb 100644 --- a/src/java/org/apache/cassandra/db/Directories.java +++ b/src/java/org/apache/cassandra/db/Directories.java @@ -191,7 +191,15 @@ public class Directories String cfId = ByteBufferUtil.bytesToHex(ByteBufferUtil.bytes(metadata.cfId)); int idx = metadata.cfName.indexOf(SECONDARY_INDEX_NAME_SEPARATOR); // secondary indicies go in the same directory as the base cf - String directoryName = idx > 0 ? metadata.cfName.substring(0, idx) + "-" + cfId : metadata.cfName + "-" + cfId; + String directoryName; + if (idx >= 0) + { + directoryName = metadata.cfName.substring(0, idx) + "-" + cfId + File.separator + metadata.cfName.substring(idx); + } + else + { + directoryName = metadata.cfName + "-" + cfId; + } this.dataPaths = new File[dataDirectories.length]; // If upgraded from version less than 2.1, use existing directories @@ -318,7 +326,19 @@ public class Directories public static File getSnapshotDirectory(Descriptor desc, String snapshotName) { - return getOrCreate(desc.directory, SNAPSHOT_SUBDIR, snapshotName); + return getSnapshotDirectory(desc.directory, snapshotName); + } + + public static File getSnapshotDirectory(File location, String snapshotName) + { + if (location.getName().startsWith(SECONDARY_INDEX_NAME_SEPARATOR)) + { + return getOrCreate(location.getParentFile(), SNAPSHOT_SUBDIR, snapshotName, location.getName()); + } + else + { + return getOrCreate(location, SNAPSHOT_SUBDIR, snapshotName); + } } public File getSnapshotManifestFile(String snapshotName) @@ -328,7 +348,19 @@ public class Directories public static File getBackupsDirectory(Descriptor desc) { - return getOrCreate(desc.directory, BACKUPS_SUBDIR); + return getBackupsDirectory(desc.directory); + } + + public static File getBackupsDirectory(File location) + { + if (location.getName().startsWith(SECONDARY_INDEX_NAME_SEPARATOR)) + { + return getOrCreate(location.getParentFile(), BACKUPS_SUBDIR, location.getName()); + } + else + { + return getOrCreate(location, BACKUPS_SUBDIR); + } } public SSTableLister sstableLister() @@ -439,7 +471,7 @@ public class Directories if (snapshotName != null) { - new File(location, join(SNAPSHOT_SUBDIR, snapshotName)).listFiles(getFilter()); + getSnapshotDirectory(location, snapshotName).listFiles(getFilter()); continue; } @@ -447,28 +479,29 @@ public class Directories location.listFiles(getFilter()); if (includeBackups) - new File(location, BACKUPS_SUBDIR).listFiles(getFilter()); + getBackupsDirectory(location).listFiles(getFilter()); } filtered = true; } private FileFilter getFilter() { - // Note: the prefix needs to include cfname + separator to distinguish between a cfs and it's secondary indexes - final String sstablePrefix = getSSTablePrefix(); return new FileFilter() { // This function always return false since accepts adds to the components map public boolean accept(File file) { - // we are only interested in the SSTable files that belong to the specific ColumnFamily - if (file.isDirectory() || !file.getName().startsWith(sstablePrefix)) + if (file.isDirectory()) return false; Pair<Descriptor, Component> pair = SSTable.tryComponentFromFilename(file.getParentFile(), file.getName()); if (pair == null) return false; + // we are only interested in the SSTable files that belong to the specific ColumnFamily + if (!pair.left.ksname.equals(metadata.ksName) || !pair.left.cfname.equals(metadata.cfName)) + return false; + if (skipTemporary && pair.left.type.isTemporary) return false; @@ -569,11 +602,6 @@ public class Directories return result; } - private String getSSTablePrefix() - { - return metadata.ksName + Component.separator + metadata.cfName + Component.separator; - } - public long getTrueAllocatedSizeIn(File input) { if (!input.isDirectory()) @@ -662,7 +690,6 @@ public class Directories private final AtomicLong size = new AtomicLong(0); private final Set<String> visited = newHashSet(); //count each file only once private final Set<String> alive; - private final String prefix = getSSTablePrefix(); public TrueFilesSizeVisitor() { @@ -675,8 +702,11 @@ public class Directories private boolean isAcceptable(Path file) { - String fileName = file.toFile().getName(); - return fileName.startsWith(prefix) + String fileName = file.toFile().getName(); + Pair<Descriptor, Component> pair = SSTable.tryComponentFromFilename(file.getParent().toFile(), fileName); + return pair != null + && pair.left.ksname.equals(metadata.ksName) + && pair.left.cfname.equals(metadata.cfName) && !visited.contains(fileName) && !alive.contains(fileName); } http://git-wip-us.apache.org/repos/asf/cassandra/blob/d13a996e/src/java/org/apache/cassandra/db/compaction/CompactionManager.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/compaction/CompactionManager.java b/src/java/org/apache/cassandra/db/compaction/CompactionManager.java index 0f38e53..d571814 100644 --- a/src/java/org/apache/cassandra/db/compaction/CompactionManager.java +++ b/src/java/org/apache/cassandra/db/compaction/CompactionManager.java @@ -479,7 +479,7 @@ public class CompactionManager implements CompactionManagerMBean } // group by keyspace/columnfamily ColumnFamilyStore cfs = Keyspace.open(desc.ksname).getColumnFamilyStore(desc.cfname); - descriptors.put(cfs, cfs.directories.find(filename.trim())); + descriptors.put(cfs, cfs.directories.find(new File(filename.trim()).getName())); } List<Future<?>> futures = new ArrayList<>(); http://git-wip-us.apache.org/repos/asf/cassandra/blob/d13a996e/src/java/org/apache/cassandra/db/compaction/CompactionManagerMBean.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/compaction/CompactionManagerMBean.java b/src/java/org/apache/cassandra/db/compaction/CompactionManagerMBean.java index acf1e52..6900b9f 100644 --- a/src/java/org/apache/cassandra/db/compaction/CompactionManagerMBean.java +++ b/src/java/org/apache/cassandra/db/compaction/CompactionManagerMBean.java @@ -66,7 +66,8 @@ public interface CompactionManagerMBean * If you do so, user defined compaction is performed several times to the groups of files * in the same keyspace/columnfamily. * - * @param dataFiles a comma separated list of sstable filename to compact + * @param dataFiles a comma separated list of sstable file to compact. + * must contain keyspace and columnfamily name in path(for 2.1+) or file name itself. */ public void forceUserDefinedCompaction(String dataFiles); http://git-wip-us.apache.org/repos/asf/cassandra/blob/d13a996e/src/java/org/apache/cassandra/io/sstable/Descriptor.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/io/sstable/Descriptor.java b/src/java/org/apache/cassandra/io/sstable/Descriptor.java index 4415db4..db5b60c 100644 --- a/src/java/org/apache/cassandra/io/sstable/Descriptor.java +++ b/src/java/org/apache/cassandra/io/sstable/Descriptor.java @@ -18,10 +18,13 @@ package org.apache.cassandra.io.sstable; import java.io.File; +import java.util.ArrayDeque; +import java.util.Deque; import java.util.StringTokenizer; import com.google.common.base.Objects; +import org.apache.cassandra.db.Directories; import org.apache.cassandra.io.sstable.metadata.IMetadataSerializer; import org.apache.cassandra.io.sstable.metadata.LegacyMetadataSerializer; import org.apache.cassandra.io.sstable.metadata.MetadataSerializer; @@ -60,6 +63,7 @@ public class Descriptor // jb (2.0.1): switch from crc32 to adler32 for compression checksums // checksum the compressed data // ka (2.1.0): new Statistics.db file format + // new file name format // index summaries can be downsampled and the sampling level is persisted // switch uncompressed checksums to adler32 // tracks presense of legacy (local and remote) counter shards @@ -75,6 +79,7 @@ public class Descriptor public final boolean hasAllAdlerChecksums; public final boolean hasRepairedAt; public final boolean tracksLegacyCounterShards; + public final boolean newFileName; public Version(String version) { @@ -86,6 +91,7 @@ public class Descriptor hasAllAdlerChecksums = version.compareTo("ka") >= 0; hasRepairedAt = version.compareTo("ka") >= 0; tracksLegacyCounterShards = version.compareTo("ka") >= 0; + newFileName = version.compareTo("ka") >= 0; } /** @@ -188,8 +194,11 @@ public class Descriptor private void appendFileName(StringBuilder buff) { - buff.append(ksname).append(separator); - buff.append(cfname).append(separator); + if (!version.newFileName) + { + buff.append(ksname).append(separator); + buff.append(cfname).append(separator); + } if (type.isTemporary) buff.append(type.marker).append(separator); buff.append(version).append(separator); @@ -230,13 +239,20 @@ public class Descriptor return fromFilename(file.getParentFile(), file.getName(), skipComponent).left; } - public static Pair<Descriptor,String> fromFilename(File directory, String name) + public static Pair<Descriptor, String> fromFilename(File directory, String name) { return fromFilename(directory, name, false); } /** - * Filename of the form "<ksname>-<cfname>-[tmp-][<version>-]<gen>-<component>" + * Filename of the form is vary by version: + * + * <ul> + * <li><ksname>-<cfname>-(tmp-)?<version>-<gen>-<component> for cassandra 2.0 and before</li> + * <li>(<tmp marker>-)?<version>-<gen>-<component> for cassandra 2.1 and later</li> + * </ul> + * + * If this is for SSTable of secondary index, directory should ends with index name for 2.1+. * * @param directory The directory of the SSTable files * @param name The name of the SSTable file @@ -244,43 +260,79 @@ public class Descriptor * * @return A Descriptor for the SSTable, and the Component remainder. */ - public static Pair<Descriptor,String> fromFilename(File directory, String name, boolean skipComponent) + public static Pair<Descriptor, String> fromFilename(File directory, String name, boolean skipComponent) { + File parentDirectory = directory != null ? directory : new File("."); + // tokenize the filename StringTokenizer st = new StringTokenizer(name, String.valueOf(separator)); String nexttok; - // all filenames must start with keyspace and column family - String ksname = st.nextToken(); - String cfname = st.nextToken(); + // read tokens backwards to determine version + Deque<String> tokenStack = new ArrayDeque<>(); + while (st.hasMoreTokens()) + { + tokenStack.push(st.nextToken()); + } + + // component suffix + String component = skipComponent ? null : tokenStack.pop(); + + // generation + int generation = Integer.parseInt(tokenStack.pop()); + + // version + nexttok = tokenStack.pop(); + if (!Version.validate(nexttok)) + throw new UnsupportedOperationException("SSTable " + name + " is too old to open. Upgrade to 2.0 first, and run upgradesstables"); + Version version = new Version(nexttok); // optional temporary marker - nexttok = st.nextToken(); Type type = Type.FINAL; - if (nexttok.equals(Type.TEMP.marker)) + nexttok = tokenStack.peek(); + if (Type.TEMP.marker.equals(nexttok)) { type = Type.TEMP; - nexttok = st.nextToken(); + tokenStack.pop(); } - else if (nexttok.equals(Type.TEMPLINK.marker)) + else if (Type.TEMPLINK.marker.equals(nexttok)) { type = Type.TEMPLINK; - nexttok = st.nextToken(); + tokenStack.pop(); } - if (!Version.validate(nexttok)) - throw new UnsupportedOperationException("SSTable " + name + " is too old to open. Upgrade to 2.0 first, and run upgradesstables"); - Version version = new Version(nexttok); - - nexttok = st.nextToken(); - int generation = Integer.parseInt(nexttok); + // ks/cf names + String ksname, cfname; + if (version.newFileName) + { + // for 2.1+ read ks and cf names from directory + File cfDirectory = parentDirectory; + // check if this is secondary index + String indexName = ""; + if (cfDirectory.getName().startsWith(Directories.SECONDARY_INDEX_NAME_SEPARATOR)) + { + indexName = cfDirectory.getName(); + cfDirectory = cfDirectory.getParentFile(); + } + if (cfDirectory.getName().equals(Directories.BACKUPS_SUBDIR)) + { + cfDirectory = cfDirectory.getParentFile(); + } + else if (cfDirectory.getParentFile().getName().equals(Directories.SNAPSHOT_SUBDIR)) + { + cfDirectory = cfDirectory.getParentFile().getParentFile(); + } + cfname = cfDirectory.getName().split("-")[0] + indexName; + ksname = cfDirectory.getParentFile().getName(); + } + else + { + cfname = tokenStack.pop(); + ksname = tokenStack.pop(); + } + assert tokenStack.isEmpty() : "Invalid file name " + name + " in " + directory; - // component suffix - String component = null; - if (!skipComponent) - component = st.nextToken(); - directory = directory != null ? directory : new File("."); - return Pair.create(new Descriptor(version, directory, ksname, cfname, generation, type), component); + return Pair.create(new Descriptor(version, parentDirectory, ksname, cfname, generation, type), component); } /** http://git-wip-us.apache.org/repos/asf/cassandra/blob/d13a996e/src/java/org/apache/cassandra/io/sstable/SSTable.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/io/sstable/SSTable.java b/src/java/org/apache/cassandra/io/sstable/SSTable.java index 6eff369..dee024a 100644 --- a/src/java/org/apache/cassandra/io/sstable/SSTable.java +++ b/src/java/org/apache/cassandra/io/sstable/SSTable.java @@ -150,18 +150,17 @@ public abstract class SSTable } /** - * @return A Descriptor,Component pair. If component is of unknown type, returns CUSTOM component. + * @return Descriptor and Component pair. null if given file is not acceptable as SSTable component. + * If component is of unknown type, returns CUSTOM component. */ - public static Pair<Descriptor,Component> tryComponentFromFilename(File dir, String name) + public static Pair<Descriptor, Component> tryComponentFromFilename(File dir, String name) { try { return Component.fromFilename(dir, name); } - catch (NoSuchElementException e) + catch (Throwable e) { - // A NoSuchElementException is thrown if the name does not match the Descriptor format - // This is the less impacting change (all calls to this method test for null return) return null; } } http://git-wip-us.apache.org/repos/asf/cassandra/blob/d13a996e/test/unit/org/apache/cassandra/db/DirectoriesTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/db/DirectoriesTest.java b/test/unit/org/apache/cassandra/db/DirectoriesTest.java index 9e6b26b..3e29a89 100644 --- a/test/unit/org/apache/cassandra/db/DirectoriesTest.java +++ b/test/unit/org/apache/cassandra/db/DirectoriesTest.java @@ -173,7 +173,7 @@ public class DirectoriesTest { 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-")) + else if (f.getName().contains("tmp-")) assert !listed.contains(f) : f + " should not be listed"; else assert listed.contains(f) : f + " is missing"; http://git-wip-us.apache.org/repos/asf/cassandra/blob/d13a996e/test/unit/org/apache/cassandra/db/compaction/CompactionsTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/db/compaction/CompactionsTest.java b/test/unit/org/apache/cassandra/db/compaction/CompactionsTest.java index e790005..e784051 100644 --- a/test/unit/org/apache/cassandra/db/compaction/CompactionsTest.java +++ b/test/unit/org/apache/cassandra/db/compaction/CompactionsTest.java @@ -367,7 +367,7 @@ public class CompactionsTest SSTableReader sstable = sstables.iterator().next(); int prevGeneration = sstable.descriptor.generation; - String file = new File(sstable.descriptor.filenameFor(Component.DATA)).getName(); + String file = new File(sstable.descriptor.filenameFor(Component.DATA)).getAbsolutePath(); // submit user defined compaction on flushed sstable CompactionManager.instance.forceUserDefinedCompaction(file); // wait until user defined compaction finishes http://git-wip-us.apache.org/repos/asf/cassandra/blob/d13a996e/test/unit/org/apache/cassandra/io/sstable/DescriptorTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/io/sstable/DescriptorTest.java b/test/unit/org/apache/cassandra/io/sstable/DescriptorTest.java new file mode 100644 index 0000000..71145f7 --- /dev/null +++ b/test/unit/org/apache/cassandra/io/sstable/DescriptorTest.java @@ -0,0 +1,120 @@ +/* + * 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.io.sstable; + +import java.io.File; +import java.io.IOException; +import java.util.UUID; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Test; + +import org.apache.cassandra.db.Directories; +import org.apache.cassandra.utils.ByteBufferUtil; +import org.apache.cassandra.utils.Pair; + +import static org.junit.Assert.*; + +public class DescriptorTest +{ + private final String ksname = "ks"; + private final String cfname = "cf"; + private final String cfId = ByteBufferUtil.bytesToHex(ByteBufferUtil.bytes(UUID.randomUUID())); + private final File tempDataDir; + + public DescriptorTest() throws IOException + { + // create CF directories, one without CFID and one with it + tempDataDir = File.createTempFile("DescriptorTest", null).getParentFile(); + } + + @Test + public void testFromFilename() throws Exception + { + File cfIdDir = new File(tempDataDir.getAbsolutePath() + File.separator + ksname + File.separator + cfname + '-' + cfId); + testFromFilenameFor(cfIdDir); + } + + @Test + public void testFromFilenameInBackup() throws Exception + { + File backupDir = new File(StringUtils.join(new String[]{tempDataDir.getAbsolutePath(), ksname, cfname + '-' + cfId, Directories.BACKUPS_SUBDIR}, File.separator)); + testFromFilenameFor(backupDir); + } + + @Test + public void testFromFilenameInSnapshot() throws Exception + { + File snapshotDir = new File(StringUtils.join(new String[]{tempDataDir.getAbsolutePath(), ksname, cfname + '-' + cfId, Directories.SNAPSHOT_SUBDIR, "snapshot_name"}, File.separator)); + testFromFilenameFor(snapshotDir); + } + + @Test + public void testFromFilenameInLegacyDirectory() throws Exception + { + File cfDir = new File(tempDataDir.getAbsolutePath() + File.separator + ksname + File.separator + cfname); + testFromFilenameFor(cfDir); + } + + private void testFromFilenameFor(File dir) + { + // normal + checkFromFilename(new Descriptor(dir, ksname, cfname, 1, Descriptor.Type.FINAL), false); + // skip component (for streaming lock file) + checkFromFilename(new Descriptor(dir, ksname, cfname, 2, Descriptor.Type.FINAL), true); + // tmp + checkFromFilename(new Descriptor(dir, ksname, cfname, 3, Descriptor.Type.TEMP), false); + // secondary index + String idxName = "myidx"; + File idxDir = new File(dir.getAbsolutePath() + File.separator + Directories.SECONDARY_INDEX_NAME_SEPARATOR + idxName); + checkFromFilename(new Descriptor(idxDir, ksname, cfname + Directories.SECONDARY_INDEX_NAME_SEPARATOR + idxName, 4, Descriptor.Type.FINAL), false); + // secondary index tmp + checkFromFilename(new Descriptor(idxDir, ksname, cfname + Directories.SECONDARY_INDEX_NAME_SEPARATOR + idxName, 5, Descriptor.Type.TEMP), false); + + // legacy version + checkFromFilename(new Descriptor("ja", dir, ksname, cfname, 1, Descriptor.Type.FINAL), false); + // legacy tmp + checkFromFilename(new Descriptor("ja", dir, ksname, cfname, 2, Descriptor.Type.TEMP), false); + // legacy secondary index + checkFromFilename(new Descriptor("ja", dir, ksname, cfname + Directories.SECONDARY_INDEX_NAME_SEPARATOR + idxName, 3, Descriptor.Type.FINAL), false); + } + + private void checkFromFilename(Descriptor original, boolean skipComponent) + { + File file = new File(skipComponent ? original.baseFilename() : original.filenameFor(Component.DATA)); + + Pair<Descriptor, String> pair = Descriptor.fromFilename(file.getParentFile(), file.getName(), skipComponent); + Descriptor desc = pair.left; + + assertEquals(original.directory, desc.directory); + assertEquals(original.ksname, desc.ksname); + assertEquals(original.cfname, desc.cfname); + assertEquals(original.version, desc.version); + assertEquals(original.generation, desc.generation); + assertEquals(original.type, desc.type); + + if (skipComponent) + { + assertNull(pair.right); + } + else + { + assertEquals(Component.DATA.name(), pair.right); + } + } +} http://git-wip-us.apache.org/repos/asf/cassandra/blob/d13a996e/test/unit/org/apache/cassandra/io/sstable/SSTableUtils.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/io/sstable/SSTableUtils.java b/test/unit/org/apache/cassandra/io/sstable/SSTableUtils.java index 32d07ac..157f89b 100644 --- a/test/unit/org/apache/cassandra/io/sstable/SSTableUtils.java +++ b/test/unit/org/apache/cassandra/io/sstable/SSTableUtils.java @@ -69,10 +69,10 @@ public class SSTableUtils if(!tempdir.delete() || !tempdir.mkdir()) throw new IOException("Temporary directory creation failed."); tempdir.deleteOnExit(); - File keyspaceDir = new File(tempdir, keyspaceName); - keyspaceDir.mkdir(); - keyspaceDir.deleteOnExit(); - File datafile = new File(new Descriptor(keyspaceDir, keyspaceName, cfname, generation, Descriptor.Type.FINAL).filenameFor("Data.db")); + File cfDir = new File(tempdir, keyspaceName + File.separator + cfname); + cfDir.mkdirs(); + cfDir.deleteOnExit(); + File datafile = new File(new Descriptor(cfDir, keyspaceName, cfname, generation, Descriptor.Type.FINAL).filenameFor("Data.db")); if (!datafile.createNewFile()) throw new IOException("unable to create file " + datafile); datafile.deleteOnExit();
