Java tutorial
/* * Licensed 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 com.spotify.cassandra.opstools; import org.apache.cassandra.config.CFMetaData; import org.apache.cassandra.config.Config; import org.apache.cassandra.config.DatabaseDescriptor; import org.apache.cassandra.db.Column; import org.apache.cassandra.db.ColumnFamilyType; import org.apache.cassandra.db.OnDiskAtom; import org.apache.cassandra.db.marshal.BytesType; import org.apache.cassandra.db.marshal.UTF8Type; import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.io.sstable.Descriptor; import org.apache.cassandra.io.sstable.SSTableIdentityIterator; import org.apache.cassandra.io.sstable.SSTableReader; import org.apache.cassandra.io.sstable.SSTableScanner; import org.apache.commons.cli.BasicParser; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import java.io.File; import java.io.IOException; import java.io.PrintStream; /** * Counts the number of tombstones in a SSTable */ public class CountTombstones { /** * Counts the number of tombstones, per row, in a given SSTable * * Assumes RandomPartitioner, standard columns and UTF8 encoded row keys * * Does not require a cassandra.yaml file or system tables. * * @param args command lines arguments * * @throws java.io.IOException on failure to open/read/write files or output streams */ public static void main(String[] args) throws IOException, ParseException { String usage = String.format("Usage: %s [-l] <sstable> [<sstable> ...]%n", CountTombstones.class.getName()); final Options options = new Options(); options.addOption("l", "legend", false, "Include column name explanation"); options.addOption("p", "partitioner", true, "The partitioner used by database"); CommandLineParser parser = new BasicParser(); CommandLine cmd = parser.parse(options, args); if (cmd.getArgs().length < 1) { System.err.println("You must supply at least one sstable"); System.err.println(usage); System.exit(1); } // Fake DatabaseDescriptor settings so we don't have to load cassandra.yaml etc Config.setClientMode(true); String partitionerName = String.format("org.apache.cassandra.dht.%s", options.hasOption("p") ? options.getOption("p") : "RandomPartitioner"); try { Class<?> clazz = Class.forName(partitionerName); IPartitioner partitioner = (IPartitioner) clazz.newInstance(); DatabaseDescriptor.setPartitioner(partitioner); } catch (Exception e) { throw new RuntimeException("Can't instantiate partitioner " + partitionerName); } PrintStream out = System.out; for (String arg : cmd.getArgs()) { String ssTableFileName = new File(arg).getAbsolutePath(); Descriptor descriptor = Descriptor.fromFilename(ssTableFileName); run(descriptor, cmd, out); } System.exit(0); } private static void run(Descriptor desc, CommandLine cmd, PrintStream out) throws IOException { // Since we don't have a schema, make one up! CFMetaData cfm = new CFMetaData(desc.ksname, desc.cfname, ColumnFamilyType.Standard, UTF8Type.instance, UTF8Type.instance); SSTableReader reader = SSTableReader.open(desc, cfm); SSTableScanner scanner = reader.getScanner(); long totalTombstones = 0, totalColumns = 0; if (cmd.hasOption("l")) { out.printf(desc.baseFilename() + "\n"); out.printf("rowkey #tombstones (#columns)\n"); } while (scanner.hasNext()) { SSTableIdentityIterator row = (SSTableIdentityIterator) scanner.next(); int tombstonesCount = 0, columnsCount = 0; while (row.hasNext()) { OnDiskAtom column = row.next(); long now = System.currentTimeMillis(); if (column instanceof Column && ((Column) column).isMarkedForDelete(now)) { tombstonesCount++; } columnsCount++; } totalTombstones += tombstonesCount; totalColumns += columnsCount; if (tombstonesCount > 0) { String key; try { key = UTF8Type.instance.getString(row.getKey().key); } catch (RuntimeException e) { key = BytesType.instance.getString(row.getKey().key); } out.printf("%s %d (%d)%n", key, tombstonesCount, columnsCount); } } if (cmd.hasOption("l")) { out.printf("#total_tombstones (#total_columns)\n"); } out.printf("%d (%d)%n", totalTombstones, totalColumns); scanner.close(); } }