org.apache.accumulo.minicluster.MiniAccumuloRunner.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.accumulo.minicluster.MiniAccumuloRunner.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.minicluster;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Pattern;

import org.apache.accumulo.core.cli.Help;
import org.apache.accumulo.core.util.Pair;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.beust.jcommander.IStringConverter;
import com.beust.jcommander.Parameter;
import com.google.common.io.Files;

/**
 * A runner for starting up a {@link MiniAccumuloCluster} from the command line using an optional configuration properties file. An example property file looks
 * like the following:
 *
 * <pre>
 * rootPassword=secret
 * instanceName=testInstance
 * numTServers=1
 * zooKeeperPort=3191
 * jdwpEnabled=true
 * zooKeeperMemory=128M
 * tserverMemory=256M
 * masterMemory=128M
 * defaultMemory=256M
 * shutdownPort=4446
 * site.instance.secret=HUSH
 * </pre>
 *
 * All items in the properties file above are optional and a default value will be provided in their absence. Any site configuration properties (typically found
 * in the accumulo-site.xml file) should be prefixed with "site." in the properties file.
 *
 * @since 1.6.0
 */
public class MiniAccumuloRunner {
    private static final Logger log = LoggerFactory.getLogger(MiniAccumuloRunner.class);

    private static final String ROOT_PASSWORD_PROP = "rootPassword";
    private static final String SHUTDOWN_PORT_PROP = "shutdownPort";
    private static final String DEFAULT_MEMORY_PROP = "defaultMemory";
    private static final String MASTER_MEMORY_PROP = "masterMemory";
    private static final String TSERVER_MEMORY_PROP = "tserverMemory";
    private static final String ZOO_KEEPER_MEMORY_PROP = "zooKeeperMemory";
    private static final String JDWP_ENABLED_PROP = "jdwpEnabled";
    private static final String ZOO_KEEPER_PORT_PROP = "zooKeeperPort";
    private static final String ZOO_KEEPER_STARTUP_TIME_PROP = "zooKeeperStartupTime";
    private static final String NUM_T_SERVERS_PROP = "numTServers";
    private static final String DIRECTORY_PROP = "directory";
    private static final String INSTANCE_NAME_PROP = "instanceName";
    private static final String EXISTING_ZOO_KEEPERS_PROP = "existingZooKeepers";

    private static void printProperties() {
        System.out.println("#mini Accumulo cluster runner properties.");
        System.out.println("#");
        System.out.println(
                "#uncomment following propeties to use, propeties not set will use default or random value");
        System.out.println();
        System.out.println("#" + INSTANCE_NAME_PROP + "=devTest");
        System.out.println("#" + DIRECTORY_PROP + "=/tmp/mac1");
        System.out.println("#" + ROOT_PASSWORD_PROP + "=secret");
        System.out.println("#" + NUM_T_SERVERS_PROP + "=2");
        System.out.println("#" + ZOO_KEEPER_PORT_PROP + "=40404");
        System.out.println("#" + ZOO_KEEPER_STARTUP_TIME_PROP + "=39000");
        System.out.println("#" + SHUTDOWN_PORT_PROP + "=41414");
        System.out.println("#" + DEFAULT_MEMORY_PROP + "=128M");
        System.out.println("#" + MASTER_MEMORY_PROP + "=128M");
        System.out.println("#" + TSERVER_MEMORY_PROP + "=128M");
        System.out.println("#" + ZOO_KEEPER_MEMORY_PROP + "=128M");
        System.out.println("#" + JDWP_ENABLED_PROP + "=false");
        System.out.println("#" + EXISTING_ZOO_KEEPERS_PROP + "=localhost:2181");

        System.out.println();
        System.out
                .println("# Configuration normally placed in accumulo-site.xml can be added using a site. prefix.");
        System.out.println("# For example the following line will set tserver.compaction.major.concurrent.max");
        System.out.println();
        System.out.println("#site.tserver.compaction.major.concurrent.max=4");

    }

    public static class PropertiesConverter implements IStringConverter<Properties> {
        @Override
        public Properties convert(String fileName) {
            Properties prop = new Properties();
            InputStream is;
            try {
                is = new FileInputStream(fileName);
                try {
                    prop.load(is);
                } finally {
                    is.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return prop;
        }
    }

    private static final String FORMAT_STRING = "  %-21s %s";

    public static class Opts extends Help {
        @Parameter(names = "-p", required = false, description = "properties file name", converter = PropertiesConverter.class)
        Properties prop = new Properties();

        @Parameter(names = { "-c",
                "--printProperties" }, required = false, description = "prints an example propeties file, redirect to file to use")
        boolean printProps = false;
    }

    /**
     * Runs the {@link MiniAccumuloCluster} given a -p argument with a property file. Establishes a shutdown port for asynchronous operation.
     *
     * @param args
     *          An optional -p argument can be specified with the path to a valid properties file.
     */
    public static void main(String[] args) throws IOException, InterruptedException {
        Opts opts = new Opts();
        opts.parseArgs(MiniAccumuloRunner.class.getName(), args);

        if (opts.printProps) {
            printProperties();
            System.exit(0);
        }

        int shutdownPort = 4445;

        final File miniDir;

        if (opts.prop.containsKey(DIRECTORY_PROP))
            miniDir = new File(opts.prop.getProperty(DIRECTORY_PROP));
        else
            miniDir = Files.createTempDir();

        String rootPass = opts.prop.containsKey(ROOT_PASSWORD_PROP) ? opts.prop.getProperty(ROOT_PASSWORD_PROP)
                : "secret";

        MiniAccumuloConfig config = new MiniAccumuloConfig(miniDir, rootPass);

        if (opts.prop.containsKey(INSTANCE_NAME_PROP))
            config.setInstanceName(opts.prop.getProperty(INSTANCE_NAME_PROP));
        if (opts.prop.containsKey(NUM_T_SERVERS_PROP))
            config.setNumTservers(Integer.parseInt(opts.prop.getProperty(NUM_T_SERVERS_PROP)));
        if (opts.prop.containsKey(ZOO_KEEPER_PORT_PROP))
            config.setZooKeeperPort(Integer.parseInt(opts.prop.getProperty(ZOO_KEEPER_PORT_PROP)));
        if (opts.prop.containsKey(ZOO_KEEPER_STARTUP_TIME_PROP))
            config.setZooKeeperStartupTime(Long.parseLong(opts.prop.getProperty(ZOO_KEEPER_STARTUP_TIME_PROP)));
        if (opts.prop.containsKey(EXISTING_ZOO_KEEPERS_PROP))
            config.getImpl().setExistingZooKeepers(opts.prop.getProperty(EXISTING_ZOO_KEEPERS_PROP));
        if (opts.prop.containsKey(JDWP_ENABLED_PROP))
            config.setJDWPEnabled(Boolean.parseBoolean(opts.prop.getProperty(JDWP_ENABLED_PROP)));
        if (opts.prop.containsKey(ZOO_KEEPER_MEMORY_PROP))
            setMemoryOnConfig(config, opts.prop.getProperty(ZOO_KEEPER_MEMORY_PROP), ServerType.ZOOKEEPER);
        if (opts.prop.containsKey(TSERVER_MEMORY_PROP))
            setMemoryOnConfig(config, opts.prop.getProperty(TSERVER_MEMORY_PROP), ServerType.TABLET_SERVER);
        if (opts.prop.containsKey(MASTER_MEMORY_PROP))
            setMemoryOnConfig(config, opts.prop.getProperty(MASTER_MEMORY_PROP), ServerType.MASTER);
        if (opts.prop.containsKey(DEFAULT_MEMORY_PROP))
            setMemoryOnConfig(config, opts.prop.getProperty(DEFAULT_MEMORY_PROP));
        if (opts.prop.containsKey(SHUTDOWN_PORT_PROP))
            shutdownPort = Integer.parseInt(opts.prop.getProperty(SHUTDOWN_PORT_PROP));

        Map<String, String> siteConfig = new HashMap<String, String>();
        for (Map.Entry<Object, Object> entry : opts.prop.entrySet()) {
            String key = (String) entry.getKey();
            if (key.startsWith("site."))
                siteConfig.put(key.replaceFirst("site.", ""), (String) entry.getValue());
        }

        config.setSiteConfig(siteConfig);

        final MiniAccumuloCluster accumulo = new MiniAccumuloCluster(config);

        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                try {
                    accumulo.stop();
                } catch (IOException e) {
                    log.error("IOException attempting to stop Accumulo.", e);
                    return;
                } catch (InterruptedException e) {
                    log.error("InterruptedException attempting to stop Accumulo.", e);
                    return;
                }

                try {
                    FileUtils.deleteDirectory(miniDir);
                } catch (IOException e) {
                    log.error("IOException attempting to clean up miniDir.", e);
                    return;
                }

                System.out.println("\nShut down gracefully on " + new Date());
            }
        });

        accumulo.start();

        printInfo(accumulo, shutdownPort);

        // start a socket on the shutdown port and block- anything connected to this port will activate the shutdown
        try (ServerSocket shutdownServer = new ServerSocket(shutdownPort)) {
            shutdownServer.accept().close();
        }

        System.exit(0);
    }

    private static boolean validateMemoryString(String memoryString) {
        String unitsRegex = "[";
        MemoryUnit[] units = MemoryUnit.values();
        for (int i = 0; i < units.length; i++) {
            unitsRegex += units[i].suffix();
            if (i < units.length - 1)
                unitsRegex += "|";
        }
        unitsRegex += "]";
        Pattern p = Pattern.compile("\\d+" + unitsRegex);
        return p.matcher(memoryString).matches();
    }

    private static void setMemoryOnConfig(MiniAccumuloConfig config, String memoryString) {
        setMemoryOnConfig(config, memoryString, null);
    }

    private static void setMemoryOnConfig(MiniAccumuloConfig config, String memoryString, ServerType serverType) {
        if (!validateMemoryString(memoryString))
            throw new IllegalArgumentException(memoryString + " is not a valid memory string");

        long memSize = Long.parseLong(memoryString.substring(0, memoryString.length() - 1));
        MemoryUnit memUnit = MemoryUnit.fromSuffix(memoryString.substring(memoryString.length() - 1));

        if (serverType != null)
            config.setMemory(serverType, memSize, memUnit);
        else
            config.setDefaultMemory(memSize, memUnit);
    }

    private static void printInfo(MiniAccumuloCluster accumulo, int shutdownPort) {
        System.out.println("Mini Accumulo Cluster\n");
        System.out.println(
                String.format(FORMAT_STRING, "Directory:", accumulo.getConfig().getDir().getAbsoluteFile()));
        System.out.println(String.format(FORMAT_STRING, "Logs:",
                accumulo.getConfig().getImpl().getLogDir().getAbsoluteFile()));
        System.out.println(String.format(FORMAT_STRING, "Instance Name:", accumulo.getConfig().getInstanceName()));
        System.out.println(String.format(FORMAT_STRING, "Root Password:", accumulo.getConfig().getRootPassword()));
        System.out.println(String.format(FORMAT_STRING, "ZooKeeper:", accumulo.getZooKeepers()));

        for (Pair<ServerType, Integer> pair : accumulo.getDebugPorts()) {
            System.out.println(String.format(FORMAT_STRING, pair.getFirst().prettyPrint() + " JDWP Host:",
                    "localhost:" + pair.getSecond()));
        }

        System.out.println(String.format(FORMAT_STRING, "Shutdown Port:", shutdownPort));

        System.out.println();
        System.out.println("  To connect with shell, use the following command : ");
        System.out.println("    accumulo shell -zh " + accumulo.getZooKeepers() + " -zi "
                + accumulo.getConfig().getInstanceName() + " -u root ");

        System.out.println("\n\nSuccessfully started on " + new Date());
    }
}