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 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 075 if (functionDesc != null) { 076 costFunctionDescs.put(costFunctionName, functionDesc); 077 } 078 079 synchronized (stochasticCosts) { 080 Map<String, Double> costs = stochasticCosts.get(tableName); 081 if (costs == null) { 082 costs = new ConcurrentHashMap<>(); 083 } 084 085 costs.put(costFunctionName, cost); 086 stochasticCosts.put(tableName, costs); 087 } 088 } 089 090 @Override 091 public void getMetrics(MetricsCollector metricsCollector, boolean all) { 092 MetricsRecordBuilder metricsRecordBuilder = metricsCollector.addRecord(metricsName); 093 094 if (stochasticCosts != null) { 095 synchronized (stochasticCosts) { 096 for (Map.Entry<String, Map<String, Double>> tableEntry : stochasticCosts.entrySet()) { 097 for (Map.Entry<String, Double> costEntry : tableEntry.getValue().entrySet()) { 098 String attrName = tableEntry.getKey() + TABLE_FUNCTION_SEP + costEntry.getKey(); 099 Double cost = costEntry.getValue(); 100 String functionDesc = costFunctionDescs.get(costEntry.getKey()); 101 102 if (functionDesc == null) { 103 functionDesc = costEntry.getKey(); 104 } 105 106 metricsRecordBuilder.addGauge(Interns.info(attrName, functionDesc), cost); 107 } 108 } 109 } 110 } 111 metricsRegistry.snapshot(metricsRecordBuilder, all); 112 } 113}