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 java.util.LinkedHashMap; 021import java.util.Map; 022import java.util.concurrent.ConcurrentHashMap; 023import org.apache.hadoop.hbase.metrics.Interns; 024import org.apache.hadoop.metrics2.MetricsCollector; 025import org.apache.hadoop.metrics2.MetricsRecordBuilder; 026import org.apache.yetus.audience.InterfaceAudience; 027 028@InterfaceAudience.Private 029public class MetricsStochasticBalancerSourceImpl extends MetricsBalancerSourceImpl 030 implements MetricsStochasticBalancerSource { 031 private static final String TABLE_FUNCTION_SEP = "_"; 032 033 // Most Recently Used(MRU) cache 034 private static final float MRU_LOAD_FACTOR = 0.75f; 035 private int metricsSize = 1000; 036 private int mruCap = calcMruCap(metricsSize); 037 038 private final Map<String, Map<String, Double>> stochasticCosts = 039 new LinkedHashMap<String, Map<String, Double>>(mruCap, MRU_LOAD_FACTOR, true) { 040 private static final long serialVersionUID = 8204713453436906599L; 041 042 @Override 043 protected boolean removeEldestEntry(Map.Entry<String, Map<String, Double>> eldest) { 044 return size() > mruCap; 045 } 046 }; 047 private Map<String, String> costFunctionDescs = new ConcurrentHashMap<>(); 048 049 /** 050 * Calculates the mru cache capacity from the metrics size 051 */ 052 private static int calcMruCap(int metricsSize) { 053 return (int) Math.ceil(metricsSize / MRU_LOAD_FACTOR) + 1; 054 } 055 056 @Override 057 public void updateMetricsSize(int size) { 058 if (size > 0) { 059 metricsSize = size; 060 mruCap = calcMruCap(size); 061 } 062 } 063 064 /** 065 * Reports stochastic load balancer costs to JMX 066 */ 067 @Override 068 public void updateStochasticCost(String tableName, String costFunctionName, String functionDesc, 069 Double cost) { 070 if (tableName == null || costFunctionName == null || cost == null) { 071 return; 072 } 073 if (functionDesc != null) { 074 costFunctionDescs.put(costFunctionName, functionDesc); 075 } 076 077 synchronized (stochasticCosts) { 078 Map<String, Double> costs = stochasticCosts.get(tableName); 079 if (costs == null) { 080 costs = new ConcurrentHashMap<>(); 081 } 082 costs.put(costFunctionName, cost); 083 stochasticCosts.put(tableName, costs); 084 } 085 } 086 087 @Override 088 public void getMetrics(MetricsCollector metricsCollector, boolean all) { 089 MetricsRecordBuilder metricsRecordBuilder = metricsCollector.addRecord(metricsName); 090 091 if (stochasticCosts != null) { 092 synchronized (stochasticCosts) { 093 for (Map.Entry<String, Map<String, Double>> tableEntry : stochasticCosts.entrySet()) { 094 for (Map.Entry<String, Double> costEntry : tableEntry.getValue().entrySet()) { 095 String attrName = tableEntry.getKey() + TABLE_FUNCTION_SEP + costEntry.getKey(); 096 Double cost = costEntry.getValue(); 097 String functionDesc = costFunctionDescs.get(costEntry.getKey()); 098 099 if (functionDesc == null) { 100 functionDesc = costEntry.getKey(); 101 } 102 103 metricsRecordBuilder.addGauge(Interns.info(attrName, functionDesc), cost); 104 } 105 } 106 } 107 } 108 metricsRegistry.snapshot(metricsRecordBuilder, all); 109 } 110}