org.apache.accumulo.shell.commands.GetSplitsCommand.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.accumulo.shell.commands.GetSplitsCommand.java

Source

/*
 * 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.accumulo.shell.commands;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Iterator;
import java.util.Map.Entry;

import org.apache.accumulo.core.client.AccumuloException;
import org.apache.accumulo.core.client.AccumuloSecurityException;
import org.apache.accumulo.core.client.Scanner;
import org.apache.accumulo.core.client.TableNotFoundException;
import org.apache.accumulo.core.data.Key;
import org.apache.accumulo.core.data.Range;
import org.apache.accumulo.core.data.Value;
import org.apache.accumulo.core.data.impl.KeyExtent;
import org.apache.accumulo.core.metadata.MetadataTable;
import org.apache.accumulo.core.metadata.RootTable;
import org.apache.accumulo.core.metadata.schema.MetadataSchema.TabletsSection;
import org.apache.accumulo.core.security.Authorizations;
import org.apache.accumulo.core.util.TextUtil;
import org.apache.accumulo.core.util.format.DefaultFormatter;
import org.apache.accumulo.shell.Shell;
import org.apache.accumulo.shell.Shell.Command;
import org.apache.accumulo.shell.Shell.PrintFile;
import org.apache.accumulo.shell.Shell.PrintLine;
import org.apache.accumulo.shell.Shell.PrintShell;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.hadoop.io.Text;

public class GetSplitsCommand extends Command {

    private Option outputFileOpt, maxSplitsOpt, base64Opt, verboseOpt;

    @Override
    public int execute(final String fullCommand, final CommandLine cl, final Shell shellState)
            throws IOException, AccumuloException, AccumuloSecurityException, TableNotFoundException {
        final String tableName = OptUtil.getTableOpt(cl, shellState);

        final String outputFile = cl.getOptionValue(outputFileOpt.getOpt());
        final String m = cl.getOptionValue(maxSplitsOpt.getOpt());
        final int maxSplits = m == null ? 0 : Integer.parseInt(m);
        final boolean encode = cl.hasOption(base64Opt.getOpt());
        final boolean verbose = cl.hasOption(verboseOpt.getOpt());

        final PrintLine p = outputFile == null ? new PrintShell(shellState.getReader()) : new PrintFile(outputFile);

        try {
            if (!verbose) {
                for (Text row : maxSplits > 0
                        ? shellState.getConnector().tableOperations().listSplits(tableName, maxSplits)
                        : shellState.getConnector().tableOperations().listSplits(tableName)) {
                    p.print(encode(encode, row));
                }
            } else {
                String systemTableToCheck = MetadataTable.NAME.equals(tableName) ? RootTable.NAME
                        : MetadataTable.NAME;
                final Scanner scanner = shellState.getConnector().createScanner(systemTableToCheck,
                        Authorizations.EMPTY);
                TabletsSection.TabletColumnFamily.PREV_ROW_COLUMN.fetch(scanner);
                final Text start = new Text(
                        shellState.getConnector().tableOperations().tableIdMap().get(tableName));
                final Text end = new Text(start);
                end.append(new byte[] { '<' }, 0, 1);
                scanner.setRange(new Range(start, end));
                for (Iterator<Entry<Key, Value>> iterator = scanner.iterator(); iterator.hasNext();) {
                    final Entry<Key, Value> next = iterator.next();
                    if (TabletsSection.TabletColumnFamily.PREV_ROW_COLUMN.hasColumns(next.getKey())) {
                        KeyExtent extent = new KeyExtent(next.getKey().getRow(), next.getValue());
                        final String pr = encode(encode, extent.getPrevEndRow());
                        final String er = encode(encode, extent.getEndRow());
                        final String line = String.format("%-26s (%s, %s%s", obscuredTabletName(extent),
                                pr == null ? "-inf" : pr, er == null ? "+inf" : er,
                                er == null ? ") Default Tablet " : "]");
                        p.print(line);
                    }
                }
            }

        } finally {
            p.close();
        }

        return 0;
    }

    private static String encode(final boolean encode, final Text text) {
        if (text == null) {
            return null;
        }
        final int length = text.getLength();
        return encode ? Base64.getEncoder().encodeToString(TextUtil.getBytes(text))
                : DefaultFormatter.appendText(new StringBuilder(), text, length).toString();
    }

    private static String obscuredTabletName(final KeyExtent extent) {
        MessageDigest digester;
        try {
            digester = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        if (extent.getEndRow() != null && extent.getEndRow().getLength() > 0) {
            digester.update(extent.getEndRow().getBytes(), 0, extent.getEndRow().getLength());
        }
        return Base64.getEncoder().encodeToString(digester.digest());
    }

    @Override
    public String description() {
        return "retrieves the current split points for tablets in the current table";
    }

    @Override
    public int numArgs() {
        return 0;
    }

    @Override
    public Options getOptions() {
        final Options opts = new Options();

        outputFileOpt = new Option("o", "output", true, "local file to write the splits to");
        outputFileOpt.setArgName("file");

        maxSplitsOpt = new Option("m", "max", true, "maximum number of splits to return (evenly spaced)");
        maxSplitsOpt.setArgName("num");

        base64Opt = new Option("b64", "base64encoded", false, "encode the split points");

        verboseOpt = new Option("v", "verbose", false, "print out the tablet information with start/end rows");

        opts.addOption(outputFileOpt);
        opts.addOption(maxSplitsOpt);
        opts.addOption(base64Opt);
        opts.addOption(verboseOpt);
        opts.addOption(OptUtil.tableOpt("table to get splits for"));

        return opts;
    }
}