001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.master.balancer;
019
020import org.agrona.collections.Int2IntCounterMap;
021import org.apache.hadoop.conf.Configuration;
022import org.apache.yetus.audience.InterfaceAudience;
023
024/**
025 * A cost function for region replicas. We give a very high cost to hosting replicas of the same
026 * region in the same host. We do not prevent the case though, since if numReplicas >
027 * numRegionServers, we still want to keep the replica open.
028 */
029@InterfaceAudience.Private
030class RegionReplicaHostCostFunction extends RegionReplicaGroupingCostFunction {
031
032  private static final String REGION_REPLICA_HOST_COST_KEY =
033    "hbase.master.balancer.stochastic.regionReplicaHostCostKey";
034  private static final float DEFAULT_REGION_REPLICA_HOST_COST_KEY = 100000;
035
036  private Int2IntCounterMap[] colocatedReplicaCountsPerGroup;
037
038  public RegionReplicaHostCostFunction(Configuration conf) {
039    this.setMultiplier(
040      conf.getFloat(REGION_REPLICA_HOST_COST_KEY, DEFAULT_REGION_REPLICA_HOST_COST_KEY));
041  }
042
043  @Override
044  protected void loadCosts() {
045    // max cost is the case where every region replica is hosted together regardless of host
046    maxCost = cluster.numHosts > 1 ? getMaxCost(cluster) : 0;
047    costsPerGroup = new long[cluster.numHosts];
048    // either server based or host based
049    colocatedReplicaCountsPerGroup = cluster.multiServersPerHost
050      ? cluster.colocatedReplicaCountsPerHost
051      : cluster.colocatedReplicaCountsPerServer;
052    for (int i = 0; i < colocatedReplicaCountsPerGroup.length; i++) {
053      costsPerGroup[i] = costPerGroup(colocatedReplicaCountsPerGroup[i]);
054    }
055  }
056
057  @Override
058  protected void regionMoved(int region, int oldServer, int newServer) {
059    if (maxCost <= 0) {
060      return; // no need to compute
061    }
062    if (cluster.multiServersPerHost) {
063      int oldHost = cluster.serverIndexToHostIndex[oldServer];
064      int newHost = cluster.serverIndexToHostIndex[newServer];
065      if (newHost != oldHost) {
066        costsPerGroup[oldHost] = costPerGroup(cluster.colocatedReplicaCountsPerHost[oldHost]);
067        costsPerGroup[newHost] = costPerGroup(cluster.colocatedReplicaCountsPerHost[newHost]);
068      }
069    } else {
070      costsPerGroup[oldServer] = costPerGroup(cluster.colocatedReplicaCountsPerServer[oldServer]);
071      costsPerGroup[newServer] = costPerGroup(cluster.colocatedReplicaCountsPerServer[newServer]);
072    }
073  }
074}