com.pinterest.rocksplicator.Participant.java Source code

Java tutorial

Introduction

Here is the source code for com.pinterest.rocksplicator.Participant.java

Source

/// Copyright 2017 Pinterest Inc.
///
/// 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.

//
// @author bol (bol@pinterest.com)
//

package com.pinterest.rocksplicator;

import java.util.HashMap;
import java.util.Map;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.helix.HelixAdmin;
import org.apache.helix.HelixConstants;
import org.apache.helix.HelixManager;
import org.apache.helix.HelixManagerFactory;
import org.apache.helix.InstanceType;
import org.apache.helix.manager.zk.HelixManagerShutdownHook;
import org.apache.helix.manager.zk.ZKHelixAdmin;
import org.apache.helix.model.HelixConfigScope;
import org.apache.helix.model.Message;
import org.apache.helix.model.builder.HelixConfigScopeBuilder;
import org.apache.helix.participant.HelixCustomCodeRunner;
import org.apache.helix.participant.StateMachineEngine;
import org.apache.helix.participant.statemachine.StateModel;
import org.apache.helix.participant.statemachine.StateModelFactory;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.PatternLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Participant {
    private static final Logger LOG = LoggerFactory.getLogger(Participant.class);
    private static final String zkServer = "zkSvr";
    private static final String cluster = "cluster";
    private static final String domain = "domain";
    private static final String hostAddress = "host";
    private static final String hostPort = "port";
    private static final String stateModel = "stateModelType";
    private static final String configPostUrl = "configPostUrl";

    private HelixManager helixManager;
    private StateModelFactory<StateModel> stateModelFactory;

    private static Options constructCommandLineOptions() {
        Option zkServerOption = OptionBuilder.withLongOpt(zkServer).withDescription("Provide zookeeper addresses")
                .create();
        zkServerOption.setArgs(1);
        zkServerOption.setRequired(true);
        zkServerOption.setArgName("ZookeeperServerAddresses(Required)");

        Option clusterOption = OptionBuilder.withLongOpt(cluster).withDescription("Provide cluster name").create();
        clusterOption.setArgs(1);
        clusterOption.setRequired(true);
        clusterOption.setArgName("Cluster name (Required)");

        Option domainOption = OptionBuilder.withLongOpt(domain).withDescription("Provide instance domain").create();
        domainOption.setArgs(1);
        domainOption.setRequired(true);
        domainOption.setArgName("Instance domain (Required)");

        Option hostOption = OptionBuilder.withLongOpt(hostAddress).withDescription("Provide host name").create();
        hostOption.setArgs(1);
        hostOption.setRequired(true);
        hostOption.setArgName("Host name (Required)");

        Option portOption = OptionBuilder.withLongOpt(hostPort).withDescription("Provide host port").create();
        portOption.setArgs(1);
        portOption.setRequired(true);
        portOption.setArgName("Host port (Required)");

        Option stateModelOption = OptionBuilder.withLongOpt(stateModel).withDescription("StateModel Type").create();
        stateModelOption.setArgs(1);
        stateModelOption.setRequired(true);
        stateModelOption.setArgName("StateModel Type (Required)");

        Option configPostUrlOption = OptionBuilder.withLongOpt(configPostUrl).withDescription("URL to post config")
                .create();
        configPostUrlOption.setArgs(1);
        configPostUrlOption.setRequired(true);
        configPostUrlOption.setArgName("URL to post config (Required)");

        Options options = new Options();
        options.addOption(zkServerOption).addOption(clusterOption).addOption(domainOption).addOption(hostOption)
                .addOption(portOption).addOption(stateModelOption).addOption(configPostUrlOption);
        return options;
    }

    private static CommandLine processCommandLineArgs(String[] cliArgs) throws ParseException {
        CommandLineParser cliParser = new GnuParser();
        Options cliOptions = constructCommandLineOptions();
        return cliParser.parse(cliOptions, cliArgs);
    }

    /**
     * Start a Helix participant.
     * @param args command line parameters
     */
    public static void main(String[] args) throws Exception {
        org.apache.log4j.Logger.getRootLogger().setLevel(Level.WARN);
        BasicConfigurator
                .configure(new ConsoleAppender(new PatternLayout("%d{HH:mm:ss.SSS} [%t] %-5p %30.30c - %m%n")));
        CommandLine cmd = processCommandLineArgs(args);
        final String zkConnectString = cmd.getOptionValue(zkServer);
        final String clusterName = cmd.getOptionValue(cluster);
        final String domainName = cmd.getOptionValue(domain);
        final String host = cmd.getOptionValue(hostAddress);
        final String port = cmd.getOptionValue(hostPort);
        final String stateModelType = cmd.getOptionValue(stateModel);
        final String postUrl = cmd.getOptionValue(configPostUrl);
        final String instanceName = host + "_" + port;

        LOG.error("Starting participant with ZK:" + zkConnectString);
        Participant participant = new Participant(zkConnectString, clusterName, instanceName, stateModelType,
                Integer.parseInt(port), postUrl);

        HelixAdmin helixAdmin = new ZKHelixAdmin(zkConnectString);
        HelixConfigScope scope = new HelixConfigScopeBuilder(HelixConfigScope.ConfigScopeProperty.PARTICIPANT)
                .forCluster(clusterName).forParticipant(instanceName).build();
        Map<String, String> properties = new HashMap<String, String>();
        properties.put("DOMAIN", domainName + ",instance=" + instanceName);
        helixAdmin.setConfig(scope, properties);

        Thread.currentThread().join();
    }

    public Participant(String zkConnectString, String clusterName, String instanceName, String stateModelType,
            int port, String postUrl) throws Exception {
        helixManager = HelixManagerFactory.getZKHelixManager(clusterName, instanceName, InstanceType.PARTICIPANT,
                zkConnectString);

        if (stateModelType.equals("OnlineOffline")) {
            stateModelFactory = new OnlineOfflineStateModelFactory(port, zkConnectString, clusterName);
        } else if (stateModelType.equals("Cache")) {
            stateModelType = "OnlineOffline";
            stateModelFactory = new CacheStateModelFactory();
        } else if (stateModelType.equals("MasterSlave")) {
            stateModelFactory = new MasterSlaveStateModelFactory(instanceName.split("_")[0], port, zkConnectString,
                    clusterName);
        } else {
            LOG.error("Unknown state model: " + stateModelType);
        }
        StateMachineEngine stateMach = helixManager.getStateMachineEngine();
        stateMach.registerStateModelFactory(stateModelType, stateModelFactory);
        helixManager.connect();
        helixManager.getMessagingService()
                .registerMessageHandlerFactory(Message.MessageType.STATE_TRANSITION.name(), stateMach);
        Runtime.getRuntime().addShutdownHook(new HelixManagerShutdownHook(helixManager));

        // Add callback to create rocksplicator shard config
        HelixCustomCodeRunner codeRunner = new HelixCustomCodeRunner(helixManager, zkConnectString)
                .invoke(new ConfigGenerator(clusterName, helixManager, postUrl))
                .on(HelixConstants.ChangeType.EXTERNAL_VIEW, HelixConstants.ChangeType.CONFIG)
                .usingLeaderStandbyModel("ConfigWatcher" + clusterName);

        codeRunner.start();
    }
}