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