Package org.apache.helix.examples

Source Code of org.apache.helix.examples.Quickstart

package org.apache.helix.examples;

/*
* 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.
*/

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

import org.I0Itec.zkclient.IDefaultNameSpace;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.ZkServer;
import org.apache.helix.HelixAdmin;
import org.apache.helix.HelixManager;
import org.apache.helix.HelixManagerFactory;
import org.apache.helix.InstanceType;
import org.apache.helix.controller.HelixControllerMain;
import org.apache.helix.manager.zk.ZKHelixAdmin;
import org.apache.helix.manager.zk.ZNRecordSerializer;
import org.apache.helix.model.ExternalView;
import org.apache.helix.model.InstanceConfig;
import org.apache.helix.model.StateModelDefinition;
import org.apache.helix.participant.StateMachineEngine;

public class Quickstart
{

  private static String ZK_ADDRESS = "localhost:2199";
  private static String CLUSTER_NAME = "HELIX_QUICKSTART";
  private static int NUM_NODES = 2;
  private static final String RESOURCE_NAME = "MyResource";
  private static final int NUM_PARTITIONS = 6;
  private static final int NUM_REPLICAS = 2;

  private static final String STATE_MODEL_NAME = "MyStateModel";

  // states
  private static final String SLAVE = "SLAVE";
  private static final String OFFLINE = "OFFLINE";
  private static final String MASTER = "MASTER";
  private static final String DROPPED = "DROPPED";

  private static List<InstanceConfig> INSTANCE_CONFIG_LIST;
  private static List<MyProcess> PROCESS_LIST;
  private static HelixAdmin admin;
  static
  {
    INSTANCE_CONFIG_LIST = new ArrayList<InstanceConfig>();
    PROCESS_LIST = new ArrayList<Quickstart.MyProcess>();
    for (int i = 0; i < NUM_NODES; i++)
    {
      int port = 12000 + i;
      InstanceConfig instanceConfig = new InstanceConfig("localhost_" + port);
      instanceConfig.setHostName("localhost");
      instanceConfig.setPort("" + port);
      instanceConfig.setInstanceEnabled(true);
      INSTANCE_CONFIG_LIST.add(instanceConfig);
    }

  }

  public static void setup()
  {
    admin = new ZKHelixAdmin(ZK_ADDRESS);
    // create cluster
    echo("Creating cluster: " + CLUSTER_NAME);
    admin.addCluster(CLUSTER_NAME, true);

    // Add nodes to the cluster
    echo("Adding " + NUM_NODES + " participants to the cluster");
    for (int i = 0; i < NUM_NODES; i++)
    {
      admin.addInstance(CLUSTER_NAME, INSTANCE_CONFIG_LIST.get(i));
      echo("\t Added participant: "
          + INSTANCE_CONFIG_LIST.get(i).getInstanceName());
    }

    // Add a state model
    StateModelDefinition myStateModel = defineStateModel();
    echo("Configuring StateModel: " + "MyStateModel  with 1 Master and 1 Slave");
    admin.addStateModelDef(CLUSTER_NAME, STATE_MODEL_NAME, myStateModel);

    // Add a resource with 6 partitions and 2 replicas
    echo("Adding a resource MyResource: " + "with 6 partitions and 2 replicas");
    admin.addResource(CLUSTER_NAME, RESOURCE_NAME, NUM_PARTITIONS,
        STATE_MODEL_NAME, "AUTO");
    // this will set up the ideal state, it calculates the preference list for
    // each partition similar to consistent hashing
    admin.rebalance(CLUSTER_NAME, RESOURCE_NAME, NUM_REPLICAS);
  }

  private static StateModelDefinition defineStateModel()
  {
    StateModelDefinition.Builder builder = new StateModelDefinition.Builder(
        STATE_MODEL_NAME);
    // Add states and their rank to indicate priority. Lower the rank higher the
    // priority
    builder.addState(MASTER, 1);
    builder.addState(SLAVE, 2);
    builder.addState(OFFLINE);
    builder.addState(DROPPED);
    // Set the initial state when the node starts
    builder.initialState(OFFLINE);

    // Add transitions between the states.
    builder.addTransition(OFFLINE, SLAVE);
    builder.addTransition(SLAVE, OFFLINE);
    builder.addTransition(SLAVE, MASTER);
    builder.addTransition(MASTER, SLAVE);
    builder.addTransition(OFFLINE, DROPPED);

    // set constraints on states.
    // static constraint
    builder.upperBound(MASTER, 1);
    // dynamic constraint, R means it should be derived based on the replication
    // factor.
    builder.dynamicUpperBound(SLAVE, "R");

    StateModelDefinition statemodelDefinition = builder.build();
    return statemodelDefinition;
  }

  public static void startController()
  {
    // start controller
    echo("Starting Helix Controller");
    HelixControllerMain.startHelixController(ZK_ADDRESS, CLUSTER_NAME,
        "localhost_9100", HelixControllerMain.STANDALONE);
  }

  public static void startNodes() throws Exception
  {
    echo("Starting Participants");
    for (int i = 0; i < NUM_NODES; i++)
    {
      MyProcess process = new MyProcess(INSTANCE_CONFIG_LIST.get(i).getId());
      PROCESS_LIST.add(process);
      process.start();
      echo("\t Started Participant: " + INSTANCE_CONFIG_LIST.get(i).getId());
    }
  }

  public static void startZookeeper()
  {
    echo("STARTING Zookeeper at " + ZK_ADDRESS);
    IDefaultNameSpace defaultNameSpace = new IDefaultNameSpace()
    {
      @Override
      public void createDefaultNameSpace(ZkClient zkClient)
      {
      }
    };
    new File("/tmp/helix-quickstart").mkdirs();
    // start zookeeper
    ZkServer server = new ZkServer("/tmp/helix-quickstart/dataDir",
        "/tmp/helix-quickstart/logDir", defaultNameSpace, 2199);
    server.start();
  }

  public static void echo(Object obj)
  {
    System.out.println(obj);
  }

  public static void main(String[] args) throws Exception
  {
    startZookeeper();
    setup();
    startNodes();
    startController();
    Thread.sleep(5000);
    printState("After starting 2 nodes");
    addNode();
    Thread.sleep(5000);
    printState("After adding a third node");
    stopNode();
    Thread.sleep(5000);
    printState("After the 3rd node stops/crashes");
    Thread.currentThread().join();
    System.exit(0);
  }

  private static void addNode() throws Exception
  {

    NUM_NODES = NUM_NODES + 1;
    int port = 12000 + NUM_NODES - 1;
    InstanceConfig instanceConfig = new InstanceConfig("localhost_" + port);
    instanceConfig.setHostName("localhost");
    instanceConfig.setPort("" + port);
    instanceConfig.setInstanceEnabled(true);
    echo("ADDING NEW NODE :" + instanceConfig.getInstanceName()+ ". Partitions will move from old nodes to the new node.");
    admin.addInstance(CLUSTER_NAME, instanceConfig);
    INSTANCE_CONFIG_LIST.add(instanceConfig);
    MyProcess process = new MyProcess(instanceConfig.getInstanceName());
    PROCESS_LIST.add(process);
    admin.rebalance(CLUSTER_NAME, RESOURCE_NAME, 3);
    process.start();
  }

  private static void stopNode()
  {
    int nodeId = NUM_NODES - 1;
    echo("STOPPING " + INSTANCE_CONFIG_LIST.get(nodeId).getInstanceName()+". Mastership will be transferred to the remaining nodes");
    PROCESS_LIST.get(nodeId).stop();
  }

  private static void printState(String msg)
  {
    System.out.println("CLUSTER STATE: "+ msg);
    ExternalView resourceExternalView = admin.getResourceExternalView(
        CLUSTER_NAME, RESOURCE_NAME);
    TreeSet<String> sortedSet = new TreeSet<String>(
        resourceExternalView.getPartitionSet());
    StringBuilder sb = new StringBuilder("\t\t");
    for (int i = 0; i < NUM_NODES; i++)
    {
      sb.append(INSTANCE_CONFIG_LIST.get(i).getInstanceName()).append("\t");
    }
    System.out.println(sb);
    for (String partitionName : sortedSet)
    {
      sb.delete(0, sb.length() - 1);
      sb.append(partitionName).append("\t");
      for (int i = 0; i < NUM_NODES; i++)
      {
        Map<String, String> stateMap = resourceExternalView
            .getStateMap(partitionName);
        if (stateMap != null
            && stateMap.containsKey(INSTANCE_CONFIG_LIST.get(i)
                .getInstanceName()))
        {
          sb.append(
              stateMap.get(INSTANCE_CONFIG_LIST.get(i).getInstanceName())
                  .charAt(0)).append("\t\t");
        } else
        {
          sb.append("-").append("\t\t");
        }
      }
      System.out.println(sb);
    }
    System.out.println("###################################################################");
  }

  static final class MyProcess
  {
    private final String instanceName;
    private HelixManager manager;

    public MyProcess(String instanceName)
    {
      this.instanceName = instanceName;
    }

    public void start() throws Exception
    {
      manager = HelixManagerFactory.getZKHelixManager(CLUSTER_NAME,
          instanceName, InstanceType.PARTICIPANT, ZK_ADDRESS);

      MasterSlaveStateModelFactory stateModelFactory = new MasterSlaveStateModelFactory(
          instanceName);

      StateMachineEngine stateMach = manager.getStateMachineEngine();
      stateMach.registerStateModelFactory(STATE_MODEL_NAME, stateModelFactory);
      manager.connect();
    }

    public void stop()
    {
      manager.disconnect();
    }
  }

}
TOP

Related Classes of org.apache.helix.examples.Quickstart

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.