Package org.apache.helix.spectator

Source Code of org.apache.helix.spectator.RoutingTableProvider$RoutingTable

package org.apache.helix.spectator;

/*
* 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.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.helix.ConfigChangeListener;
import org.apache.helix.ExternalViewChangeListener;
import org.apache.helix.HelixDataAccessor;
import org.apache.helix.NotificationContext;
import org.apache.helix.PropertyKey.Builder;
import org.apache.helix.model.ExternalView;
import org.apache.helix.model.InstanceConfig;
import org.apache.log4j.Logger;


public class RoutingTableProvider implements ExternalViewChangeListener, ConfigChangeListener
{
  private static final Logger logger = Logger.getLogger(RoutingTableProvider.class);
  private final AtomicReference<RoutingTable> _routingTableRef;

  public RoutingTableProvider()
  {
    _routingTableRef = new AtomicReference<RoutingTableProvider.RoutingTable>(new RoutingTable());

  }

  /**
   * returns the instances for {resource,partition} pair that are in a specific
   * {state}
   *
   * @param resourceName
   *          -
   * @param partitionName
   * @param state
   * @return empty list if there is no instance in a given state
   */
  public List<InstanceConfig> getInstances(String resourceName, String partitionName, String state)
  {
    List<InstanceConfig> instanceList = null;
    RoutingTable _routingTable = _routingTableRef.get();
    ResourceInfo resourceInfo = _routingTable.get(resourceName);
    if (resourceInfo != null)
    {
      PartitionInfo keyInfo = resourceInfo.get(partitionName);
      if (keyInfo != null)
      {
        instanceList = keyInfo.get(state);
      }
    }
    if (instanceList == null)
    {
      instanceList = Collections.emptyList();
    }
    return instanceList;
  }

  /**
   * returns all instances for {resource} that are in a specific {state}
   *
   * @param resource
   * @param state
   * @return empty list if there is no instance in a given state
   */
  public Set<InstanceConfig> getInstances(String resource, String state)
  {
    Set<InstanceConfig> instanceSet = null;
    RoutingTable routingTable = _routingTableRef.get();
    ResourceInfo resourceInfo = routingTable.get(resource);
    if (resourceInfo != null)
    {
      instanceSet = resourceInfo.getInstances(state);
    }
    if (instanceSet == null)
    {
      instanceSet = Collections.emptySet();
    }
    return instanceSet;
  }

  @Override
  public void onExternalViewChange(List<ExternalView> externalViewList,
      NotificationContext changeContext)
  {
    // session has expired clean up the routing table
    if (changeContext.getType() == NotificationContext.Type.FINALIZE)
    {
      logger.info("Resetting the routing table. ");
      RoutingTable newRoutingTable = new RoutingTable();
      _routingTableRef.set(newRoutingTable);
      return;
    }
    refresh(externalViewList, changeContext);
  }

  @Override
  public void onConfigChange(List<InstanceConfig> configs,
                             NotificationContext changeContext)
  {
    // session has expired clean up the routing table
    if (changeContext.getType() == NotificationContext.Type.FINALIZE)
    {
      logger.info("Resetting the routing table. ");
      RoutingTable newRoutingTable = new RoutingTable();
      _routingTableRef.set(newRoutingTable);
      return;
    }
   
    HelixDataAccessor accessor = changeContext.getManager().getHelixDataAccessor();
    Builder keyBuilder = accessor.keyBuilder();
    List<ExternalView> externalViewList = accessor.getChildValues(keyBuilder.externalViews());
    refresh(externalViewList, changeContext);   
  }
 
  private void refresh(List<ExternalView> externalViewList, NotificationContext changeContext)
  {
    HelixDataAccessor accessor = changeContext.getManager().getHelixDataAccessor();
    Builder keyBuilder = accessor.keyBuilder();
   
    List<InstanceConfig> configList = accessor.getChildValues(keyBuilder.instanceConfigs());
    Map<String, InstanceConfig> instanceConfigMap = new HashMap<String, InstanceConfig>();
    for (InstanceConfig config : configList)
    {
      instanceConfigMap.put(config.getId(), config);
    }
    RoutingTable newRoutingTable = new RoutingTable();
    if (externalViewList != null)
    {
      for (ExternalView extView : externalViewList)
      {
        String resourceName = extView.getId();
        for (String partitionName : extView.getPartitionSet())
        {
          Map<String, String> stateMap = extView.getStateMap(partitionName);
          for (String instanceName : stateMap.keySet())
          {
            String currentState = stateMap.get(instanceName);
            if (instanceConfigMap.containsKey(instanceName))
            {
              InstanceConfig instanceConfig = instanceConfigMap.get(instanceName);
              newRoutingTable.addEntry(resourceName, partitionName, currentState, instanceConfig);
            } else
            {
              logger.error("Invalid instance name." + instanceName
                  + " .Not found in /cluster/configs/. instanceName: ");
            }

          }
        }
      }
    }
    _routingTableRef.set(newRoutingTable);
  }

  class RoutingTable
  {
    private final HashMap<String, ResourceInfo> resourceInfoMap;

    public RoutingTable()
    {
      resourceInfoMap = new HashMap<String, RoutingTableProvider.ResourceInfo>();
    }

    public void addEntry(String resourceName, String partitionName, String state,
        InstanceConfig config)
    {
      if (!resourceInfoMap.containsKey(resourceName))
      {
        resourceInfoMap.put(resourceName, new ResourceInfo());
      }
      ResourceInfo resourceInfo = resourceInfoMap.get(resourceName);
      resourceInfo.addEntry(partitionName, state, config);

    }

    ResourceInfo get(String resourceName)
    {
      return resourceInfoMap.get(resourceName);
    }

  }

  class ResourceInfo
  {
    // store PartitionInfo for each partition
    HashMap<String, PartitionInfo> partitionInfoMap;
    // stores the Set of Instances in a given state
    HashMap<String, Set<InstanceConfig>> stateInfoMap;

    public ResourceInfo()
    {
      partitionInfoMap = new HashMap<String, RoutingTableProvider.PartitionInfo>();
      stateInfoMap = new HashMap<String, Set<InstanceConfig>>();
    }

    public void addEntry(String stateUnitKey, String state, InstanceConfig config)
    {
      // add
      if (!stateInfoMap.containsKey(state))
      {
        Comparator<InstanceConfig> comparator = new Comparator<InstanceConfig>() {

          @Override
          public int compare(InstanceConfig o1, InstanceConfig o2)
          {
            if (o1 == o2)
            {
              return 0;
            }
            if (o1 == null)
            {
              return -1;
            }
            if (o2 == null)
            {
              return 1;
            }

            int compareTo = o1.getHostName().compareTo(o2.getHostName());
            if (compareTo == 0)
            {
              return o1.getPort().compareTo(o2.getPort());
            } else
            {
              return compareTo;
            }

          }
        };
        stateInfoMap.put(state, new TreeSet<InstanceConfig>(comparator));
      }
      Set<InstanceConfig> set = stateInfoMap.get(state);
      set.add(config);

      if (!partitionInfoMap.containsKey(stateUnitKey))
      {
        partitionInfoMap.put(stateUnitKey, new PartitionInfo());
      }
      PartitionInfo stateUnitKeyInfo = partitionInfoMap.get(stateUnitKey);
      stateUnitKeyInfo.addEntry(state, config);

    }

    public Set<InstanceConfig> getInstances(String state)
    {
      Set<InstanceConfig> instanceSet = stateInfoMap.get(state);
      return instanceSet;
    }

    PartitionInfo get(String stateUnitKey)
    {
      return partitionInfoMap.get(stateUnitKey);
    }
  }

  class PartitionInfo
  {
    HashMap<String, List<InstanceConfig>> stateInfoMap;

    public PartitionInfo()
    {
      stateInfoMap = new HashMap<String, List<InstanceConfig>>();
    }

    public void addEntry(String state, InstanceConfig config)
    {
      if (!stateInfoMap.containsKey(state))
      {
        stateInfoMap.put(state, new ArrayList<InstanceConfig>());
      }
      List<InstanceConfig> list = stateInfoMap.get(state);
      list.add(config);
    }

    List<InstanceConfig> get(String state)
    {
      return stateInfoMap.get(state);
    }
  }
}
TOP

Related Classes of org.apache.helix.spectator.RoutingTableProvider$RoutingTable

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.