From 820390faf1491004edcd9dcc1706faaa647e18da Mon Sep 17 00:00:00 2001 From: Jonathan Ellis Date: Fri, 15 Jan 2010 19:36:11 +0000 Subject: [PATCH] add bin/sstablekeys, listing just the keys from an sstable (actually, from its index file), one per line. patch by Brandon Williams and jbellis for CASSANDRA-679 git-svn-id: https://svn.apache.org/repos/asf/incubator/cassandra/trunk@899781 13f79535-47bb-0310-9956-ffa450edef68 --- bin/sstablekeys | 54 ++++++++++++++ src/java/org/apache/cassandra/io/SSTable.java | 2 +- .../apache/cassandra/tools/SSTableExport.java | 71 ++++++++++++++++--- .../cassandra/tools/SSTableExportTest.java | 38 ++++++++++ 4 files changed, 156 insertions(+), 9 deletions(-) create mode 100644 bin/sstablekeys diff --git a/bin/sstablekeys b/bin/sstablekeys new file mode 100644 index 0000000000..ab4c121c37 --- /dev/null +++ b/bin/sstablekeys @@ -0,0 +1,54 @@ +#!/bin/sh + +# 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. + +if [ "x$CASSANDRA_INCLUDE" = "x" ]; then + for include in /usr/share/cassandra/cassandra.in.sh \ + /usr/local/share/cassandra/cassandra.in.sh \ + /opt/cassandra/cassandra.in.sh \ + ~/.cassandra.in.sh \ + `dirname $0`/cassandra.in.sh; do + if [ -r $include ]; then + . $include + break + fi + done +elif [ -r $CASSANDRA_INCLUDE ]; then + . $CASSANDRA_INCLUDE +fi + + +# Use JAVA_HOME if set, otherwise look for java in PATH +if [ -x $JAVA_HOME/bin/java ]; then + JAVA=$JAVA_HOME/bin/java +else + JAVA=`which java` +fi + +if [ -z $CLASSPATH ]; then + echo "You must set the CLASSPATH var" >&2 + exit 1 +fi +if [ $# -eq "0" ]; then + echo "Usage: `basename $0` " + exit 2 +fi + +$JAVA -cp $CLASSPATH -Dstorage-config=$CASSANDRA_CONF \ + org.apache.cassandra.tools.SSTableExport "$1" -e + +# vi:ai sw=4 ts=4 tw=0 et diff --git a/src/java/org/apache/cassandra/io/SSTable.java b/src/java/org/apache/cassandra/io/SSTable.java index 5130af17c9..18cbc85492 100644 --- a/src/java/org/apache/cassandra/io/SSTable.java +++ b/src/java/org/apache/cassandra/io/SSTable.java @@ -77,7 +77,7 @@ public abstract class SSTable return new File(filename).getName().split("-")[0]; } - protected static String indexFilename(String dataFile) + public static String indexFilename(String dataFile) { String[] parts = dataFile.split("-"); parts[parts.length - 1] = "Index.db"; diff --git a/src/java/org/apache/cassandra/tools/SSTableExport.java b/src/java/org/apache/cassandra/tools/SSTableExport.java index c0f8ea8777..08369c0728 100644 --- a/src/java/org/apache/cassandra/tools/SSTableExport.java +++ b/src/java/org/apache/cassandra/tools/SSTableExport.java @@ -30,8 +30,12 @@ import org.apache.cassandra.db.IColumn; import org.apache.cassandra.db.marshal.AbstractType; import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.io.IteratingRow; +import org.apache.cassandra.io.SSTable; import org.apache.cassandra.io.SSTableReader; import org.apache.cassandra.io.SSTableScanner; +import org.apache.cassandra.io.util.BufferedRandomAccessFile; +import org.apache.cassandra.service.StorageService; + import static org.apache.cassandra.utils.FBUtilities.bytesToHex; import org.apache.commons.cli.*; @@ -44,6 +48,7 @@ public class SSTableExport private static final String OUTFILE_OPTION = "f"; private static final String KEY_OPTION = "k"; + private static final String ENUMERATEKEYS_OPTION = "e"; private static Options options; private static CommandLine cmd; @@ -59,6 +64,11 @@ public class SSTableExport optKey.setArgs(500); optKey.setRequired(false); options.addOption(optKey); + + options = new Options(); + Option optEnumerate = new Option(ENUMERATEKEYS_OPTION, false, "enumerate keys only"); + optOutfile.setRequired(false); + options.addOption(optEnumerate); } private static String quote(String val) @@ -132,6 +142,42 @@ public class SSTableExport return json.toString(); } + + /** + * Enumerate row keys from an SSTableReader and write the result to a PrintStream. + * + * @param ssTableFile the file to export the rows from + * @param outs PrintStream to write the output to + * @throws IOException on failure to read/write input/output + */ + public static void enumeratekeys(String ssTableFile, PrintStream outs) + throws IOException + { + IPartitioner partitioner = StorageService.getPartitioner(); + BufferedRandomAccessFile input = new BufferedRandomAccessFile(SSTable.indexFilename(ssTableFile), "r"); + while (!input.isEOF()) + { + DecoratedKey decoratedKey = partitioner.convertFromDiskFormat(input.readUTF()); + long dataPosition = input.readLong(); + outs.println(decoratedKey.key); + } + + outs.flush(); + } + + /** + * Enumerate row keys from an SSTable and write the result to a file. + * + * @param ssTableFile the SSTable to export the rows from + * @param outFile file to write the output to + * @throws IOException on failure to read/write input/output + */ + public static void enumeratekeys(String ssTableFile, String outFile) + throws IOException + { + PrintStream outs = new PrintStream(outFile); + enumeratekeys(ssTableFile, outs); + } /** * Export specific rows from an SSTable and write the resulting JSON to a PrintStream. @@ -304,22 +350,31 @@ public class SSTableExport System.exit(1); } + String[] keys = cmd.getOptionValues(KEY_OPTION); String ssTableFileName = new File(cmd.getArgs()[0]).getAbsolutePath(); if (outFile != null) { - if ((keys != null) && (keys.length > 0)) - export(ssTableFileName, outFile, keys); - else - export(ssTableFileName, outFile); + if (cmd.hasOption(ENUMERATEKEYS_OPTION)) + enumeratekeys(ssTableFileName, outFile); + else { + if ((keys != null) && (keys.length > 0)) + export(ssTableFileName, outFile, keys); + else + export(ssTableFileName, outFile); + } } else { - if ((keys != null) && (keys.length > 0)) - export(ssTableFileName, System.out, keys); - else - export(ssTableFileName); + if (cmd.hasOption(ENUMERATEKEYS_OPTION)) + enumeratekeys(ssTableFileName, System.out); + else { + if ((keys != null) && (keys.length > 0)) + export(ssTableFileName, System.out, keys); + else + export(ssTableFileName); + } } System.exit(0); } diff --git a/test/unit/org/apache/cassandra/tools/SSTableExportTest.java b/test/unit/org/apache/cassandra/tools/SSTableExportTest.java index 62bfb64b69..206c6104d0 100644 --- a/test/unit/org/apache/cassandra/tools/SSTableExportTest.java +++ b/test/unit/org/apache/cassandra/tools/SSTableExportTest.java @@ -44,6 +44,44 @@ import org.junit.Test; public class SSTableExportTest { + @Test + public void testEnumeratekeys() throws IOException + { + File tempSS = createTemporarySSTable("Keyspace1", "Standard1"); + ColumnFamily cfamily = ColumnFamily.create("Keyspace1", "Standard1"); + IPartitioner partitioner = DatabaseDescriptor.getPartitioner(); + DataOutputBuffer dob = new DataOutputBuffer(); + SSTableWriter writer = new SSTableWriter(tempSS.getPath(), 2, partitioner); + + // Add rowA + cfamily.addColumn(new QueryPath("Standard1", null, "colA".getBytes()), "valA".getBytes(), 1, false); + ColumnFamily.serializer().serializeWithIndexes(cfamily, dob); + writer.append(partitioner.decorateKey("rowA"), dob); + dob.reset(); + cfamily.clear(); + + // Add rowB + cfamily.addColumn(new QueryPath("Standard1", null, "colB".getBytes()), "valB".getBytes(), 1, false); + ColumnFamily.serializer().serializeWithIndexes(cfamily, dob); + writer.append(partitioner.decorateKey("rowB"), dob); + dob.reset(); + cfamily.clear(); + + writer.closeAndOpenReader(0); + + // Enumerate and verify + File temp = File.createTempFile("Standard1", ".txt"); + SSTableExport.enumeratekeys(writer.getFilename(), new PrintStream(temp.getPath())); + + + FileReader file = new FileReader(temp); + char[] buf = new char[(int) temp.length()]; + file.read(buf); + String output = new String(buf); + + assert output.equals("rowA\nrowB\n"); + } + @Test public void testExportSimpleCf() throws IOException {