org.apache.hadoop.hbase.master.AssignmentPlan.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.hbase.master.AssignmentPlan.java

Source

/**
 * Copyright 2012 The Apache Software Foundation
 *
 * 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.hadoop.hbase.master;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.HServerAddress;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.hadoop.io.Writable;

/**
 * AssignmentPlan is a writable object for the region assignment plan.
 * It contains the mapping information between each region and
 * its favored region server list.
 *
 * All the access to this class is thread-safe.
 */
public class AssignmentPlan implements Writable {
    protected static final Log LOG = LogFactory.getLog(AssignmentPlan.class.getName());

    private static final int VERSION = 1;

    /** the map between each region and its favored region server list */
    private Map<HRegionInfo, List<HServerAddress>> assignmentMap;

    /** the map between each region and its lasted favored server list update
     * time stamp
    */
    private Map<HRegionInfo, Long> assignmentUpdateTS;

    public static enum POSITION {
        PRIMARY, SECONDARY, TERTIARY;
    };

    public AssignmentPlan() {
        assignmentMap = new HashMap<HRegionInfo, List<HServerAddress>>();
        assignmentUpdateTS = new HashMap<HRegionInfo, Long>();
    }

    /**
     * Initialize the assignment plan with the existing primary region server map
     * and the existing secondary/tertiary region server map
     *
     * if any regions cannot find the proper secondary / tertiary region server
     * for whatever reason, just do NOT update the assignment plan for this region
     * @param primaryRSMap
     * @param secondaryAndTiteraryRSMap
     */
    public void initialize(Map<HRegionInfo, HServerAddress> primaryRSMap,
            Map<HRegionInfo, Pair<HServerAddress, HServerAddress>> secondaryAndTertiaryRSMap) {
        for (Map.Entry<HRegionInfo, Pair<HServerAddress, HServerAddress>> entry : secondaryAndTertiaryRSMap
                .entrySet()) {
            // Get the region info and their secondary/tertiary region server
            HRegionInfo regionInfo = entry.getKey();
            Pair<HServerAddress, HServerAddress> secondaryAndTertiaryPair = entry.getValue();

            // Get the primary region server
            HServerAddress primaryRS = primaryRSMap.get(regionInfo);
            if (primaryRS == null) {
                LOG.error("No primary region server for region " + regionInfo.getRegionNameAsString());
                continue;
            }

            // Update the assignment plan with the favored nodes
            List<HServerAddress> serverList = new ArrayList<HServerAddress>();
            serverList.add(POSITION.PRIMARY.ordinal(), primaryRS);
            serverList.add(POSITION.SECONDARY.ordinal(), secondaryAndTertiaryPair.getFirst());
            serverList.add(POSITION.TERTIARY.ordinal(), secondaryAndTertiaryPair.getSecond());
            this.updateAssignmentPlan(regionInfo, serverList);
        }
    }

    /**
     * Add an assignment to the plan
     * @param region
     * @param servers
     * @param ts
     */
    public synchronized void updateAssignmentPlan(HRegionInfo region, List<HServerAddress> servers, long ts) {
        if (region == null || servers == null || servers.size() == 0)
            return;
        this.assignmentUpdateTS.put(region, Long.valueOf(ts));
        this.assignmentMap.put(region, servers);
        LOG.info("Update the assignment plan for region " + region.getRegionNameAsString() + " to favored nodes "
                + RegionPlacement.getFavoredNodes(servers) + " at time stamp " + ts);
    }

    /**
     * Add an assignment to the plan
     * @param region
     * @param servers
     */
    public synchronized void updateAssignmentPlan(HRegionInfo region, List<HServerAddress> servers) {
        if (region == null || servers == null || servers.size() == 0)
            return;
        this.assignmentMap.put(region, servers);
        LOG.info("Update the assignment plan for region " + region.getRegionNameAsString() + " ; favored nodes "
                + RegionPlacement.getFavoredNodes(servers));
    }

    /**
     * Remove one assignment from the plan
     * @param region
     */
    public synchronized void removeAssignment(HRegionInfo region) {
        this.assignmentMap.remove(region);
        this.assignmentUpdateTS.remove(region);
    }

    /**
     * @param region
     * @return true if there is an assignment plan for the particular region.
     */
    public synchronized boolean hasAssignment(HRegionInfo region) {
        return assignmentMap.containsKey(region);
    }

    /**
     * @param region
     * @return the list of favored region server for this region based on the plan
     */
    public synchronized List<HServerAddress> getAssignment(HRegionInfo region) {
        return assignmentMap.get(region);
    }

    /**
     * @param region
     * @return the last update time stamp for the region in the plan
     */
    public synchronized long getAssignmentUpdateTS(HRegionInfo region) {
        Long updateTS = assignmentUpdateTS.get(region);
        if (updateTS == null)
            return Long.MIN_VALUE;
        else
            return updateTS.longValue();
    }

    /**
     * @return the mapping between each region to its favored region server list
     */
    public synchronized Map<HRegionInfo, List<HServerAddress>> getAssignmentMap() {
        return this.assignmentMap;
    }

    @Override
    public void write(DataOutput out) throws IOException {
        out.writeInt(VERSION);
        if (this.assignmentMap == null) {
            out.writeInt(0);
        }
        // write the size of the favored assignment map
        out.writeInt(this.assignmentMap.size());
        for (Map.Entry<HRegionInfo, List<HServerAddress>> entry : assignmentMap.entrySet()) {
            // write the region info
            entry.getKey().write(out);
            // write the list of favored server list
            List<HServerAddress> serverList = entry.getValue();
            // write the size of the list
            out.writeInt(serverList.size());
            for (HServerAddress addr : serverList) {
                // write the element of the list
                addr.write(out);
            }
        }
    }

    @Override
    public void readFields(DataInput in) throws IOException {
        int version = in.readInt();
        if (version != VERSION) {
            throw new IOException("The version mismatch for the assignment plan. " + "The expected versioin is "
                    + VERSION + " but the verion from the assigment plan is " + version);
        }
        // read the favoredAssignmentMap size
        int assignmentMapSize = in.readInt();
        for (int i = 0; i < assignmentMapSize; i++) {
            // read each region info
            HRegionInfo region = new HRegionInfo();
            region.readFields(in);
            // read the size of favored server list
            int serverListSize = in.readInt();
            List<HServerAddress> serverList = new ArrayList<HServerAddress>(serverListSize);
            for (int j = 0; j < serverListSize; j++) {
                HServerAddress addr = new HServerAddress();
                addr.readFields(in);
                serverList.add(addr);
            }

            // add the assignment to favoredAssignmentMap
            this.assignmentMap.put(region, serverList);
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null) {
            return false;
        }
        if (getClass() != o.getClass()) {
            return false;
        }
        // To compare the map from objec o is identical to current assignment map.
        Map<HRegionInfo, List<HServerAddress>> comparedMap = ((AssignmentPlan) o).getAssignmentMap();

        // compare the size
        if (comparedMap.size() != this.assignmentMap.size())
            return false;

        // compare each element in the assignment map
        for (Map.Entry<HRegionInfo, List<HServerAddress>> entry : comparedMap.entrySet()) {
            List<HServerAddress> serverList = this.assignmentMap.get(entry.getKey());
            if (serverList == null && entry.getValue() != null) {
                return false;
            } else if (!serverList.equals(entry.getValue())) {
                return false;
            }
        }
        return true;
    }

    public static AssignmentPlan.POSITION getFavoredServerPosition(List<HServerAddress> favoredNodes,
            HServerAddress server) {
        if (favoredNodes == null || server == null || favoredNodes.size() != HConstants.FAVORED_NODES_NUM) {
            return null;
        }
        for (AssignmentPlan.POSITION p : AssignmentPlan.POSITION.values()) {
            if (favoredNodes.get(p.ordinal()).equals(server)) {
                return p;
            }
        }
        return null;
    }
}