/** * Copyright 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; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.TreeSet; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos; import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.Coprocessor; import org.apache.hadoop.hbase.RegionLoad; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Strings; /** * This class is used for exporting current state of load on a RegionServer. */ @InterfaceAudience.Public @InterfaceStability.Evolving public class ServerLoad { private int stores = 0; private int storefiles = 0; private int storeUncompressedSizeMB = 0; private int storefileSizeMB = 0; private int memstoreSizeMB = 0; private int storefileIndexSizeMB = 0; private int readRequestsCount = 0; private int writeRequestsCount = 0; private int rootIndexSizeKB = 0; private int totalStaticIndexSizeKB = 0; private int totalStaticBloomSizeKB = 0; private long totalCompactingKVs = 0; private long currentCompactedKVs = 0; public ServerLoad(HBaseProtos.ServerLoad serverLoad) { this.serverLoad = serverLoad; for (HBaseProtos.RegionLoad rl: serverLoad.getRegionLoadsList()) { stores += rl.getStores(); storefiles += rl.getStorefiles(); storeUncompressedSizeMB += rl.getStoreUncompressedSizeMB(); storefileSizeMB += rl.getStorefileSizeMB(); memstoreSizeMB += rl.getMemstoreSizeMB(); storefileIndexSizeMB += rl.getStorefileIndexSizeMB(); readRequestsCount += rl.getReadRequestsCount(); writeRequestsCount += rl.getWriteRequestsCount(); rootIndexSizeKB += rl.getRootIndexSizeKB(); totalStaticIndexSizeKB += rl.getTotalStaticIndexSizeKB(); totalStaticBloomSizeKB += rl.getTotalStaticBloomSizeKB(); totalCompactingKVs += rl.getTotalCompactingKVs(); currentCompactedKVs += rl.getCurrentCompactedKVs(); } } // NOTE: Function name cannot start with "get" because then an OpenDataException is thrown because // HBaseProtos.ServerLoad cannot be converted to an open data type(see HBASE-5967). /* @return the underlying ServerLoad protobuf object */ public HBaseProtos.ServerLoad obtainServerLoadPB() { return serverLoad; } protected HBaseProtos.ServerLoad serverLoad; /* @return number of requests since last report. */ public int getNumberOfRequests() { return serverLoad.getNumberOfRequests(); } public boolean hasNumberOfRequests() { return serverLoad.hasNumberOfRequests(); } /* @return total Number of requests from the start of the region server. */ public int getTotalNumberOfRequests() { return serverLoad.getTotalNumberOfRequests(); } public boolean hasTotalNumberOfRequests() { return serverLoad.hasTotalNumberOfRequests(); } /* @return the amount of used heap, in MB. */ public int getUsedHeapMB() { return serverLoad.getUsedHeapMB(); } public boolean hasUsedHeapMB() { return serverLoad.hasUsedHeapMB(); } /* @return the maximum allowable size of the heap, in MB. */ public int getMaxHeapMB() { return serverLoad.getMaxHeapMB(); } public boolean hasMaxHeapMB() { return serverLoad.hasMaxHeapMB(); } public int getStores() { return stores; } public int getStorefiles() { return storefiles; } public int getStoreUncompressedSizeMB() { return storeUncompressedSizeMB; } public int getStorefileSizeInMB() { return storefileSizeMB; } public int getMemstoreSizeInMB() { return memstoreSizeMB; } public int getStorefileIndexSizeInMB() { return storefileIndexSizeMB; } public int getReadRequestsCount() { return readRequestsCount; } public int getWriteRequestsCount() { return writeRequestsCount; } public int getRootIndexSizeKB() { return rootIndexSizeKB; } public int getTotalStaticIndexSizeKB() { return totalStaticIndexSizeKB; } public int getTotalStaticBloomSizeKB() { return totalStaticBloomSizeKB; } public long getTotalCompactingKVs() { return totalCompactingKVs; } public long getCurrentCompactedKVs() { return currentCompactedKVs; } /** * @return the number of regions */ public int getNumberOfRegions() { return serverLoad.getRegionLoadsCount(); } public int getInfoServerPort() { return serverLoad.getInfoServerPort(); } /** * Originally, this method factored in the effect of requests going to the * server as well. However, this does not interact very well with the current * region rebalancing code, which only factors number of regions. For the * interim, until we can figure out how to make rebalancing use all the info * available, we're just going to make load purely the number of regions. * * @return load factor for this server */ public int getLoad() { // See above comment // int load = numberOfRequests == 0 ? 1 : numberOfRequests; // load *= numberOfRegions == 0 ? 1 : numberOfRegions; // return load; return getNumberOfRegions(); } /** * @return region load metrics */ public Map<byte[], RegionLoad> getRegionsLoad() { Map<byte[], RegionLoad> regionLoads = new TreeMap<byte[], RegionLoad>(Bytes.BYTES_COMPARATOR); for (HBaseProtos.RegionLoad rl : serverLoad.getRegionLoadsList()) { RegionLoad regionLoad = new RegionLoad(rl); regionLoads.put(regionLoad.getName(), regionLoad); } return regionLoads; } /** * Return the RegionServer-level coprocessors * @return string array of loaded RegionServer-level coprocessors */ public String[] getRegionServerCoprocessors() { List<Coprocessor> list = obtainServerLoadPB().getCoprocessorsList(); String [] ret = new String[list.size()]; int i = 0; for (Coprocessor elem : list) { ret[i++] = elem.getName(); } return ret; } /** * Return the RegionServer-level and Region-level coprocessors * @return string array of loaded RegionServer-level and * Region-level coprocessors */ public String[] getAllCoprocessors() { // Need a set to remove duplicates, but since generated Coprocessor class // is not Comparable, make it a Set<String> instead of Set<Coprocessor> TreeSet<String> coprocessSet = new TreeSet<String>(); for (Coprocessor coprocessor : obtainServerLoadPB().getCoprocessorsList()) { coprocessSet.add(coprocessor.getName()); } for (HBaseProtos.RegionLoad rl : obtainServerLoadPB().getRegionLoadsList()) { for (Coprocessor coprocessor : rl.getCoprocessorsList()) { coprocessSet.add(coprocessor.getName()); } } return coprocessSet.toArray(new String[0]); } /** * @deprecated Use getAllCoprocessors instead */ public String[] getCoprocessors() { return getAllCoprocessors(); } /** * @return number of requests per second received since the last report */ public double getRequestsPerSecond() { return getNumberOfRequests(); } /** * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder sb = Strings.appendKeyValue(new StringBuilder(), "requestsPerSecond", Double.valueOf(getRequestsPerSecond())); Strings.appendKeyValue(sb, "numberOfOnlineRegions", Integer.valueOf(getNumberOfRegions())); sb = Strings.appendKeyValue(sb, "usedHeapMB", Integer.valueOf(this.getUsedHeapMB())); sb = Strings.appendKeyValue(sb, "maxHeapMB", Integer.valueOf(getMaxHeapMB())); sb = Strings.appendKeyValue(sb, "numberOfStores", Integer.valueOf(this.stores)); sb = Strings.appendKeyValue(sb, "numberOfStorefiles", Integer.valueOf(this.storefiles)); sb = Strings.appendKeyValue(sb, "storefileUncompressedSizeMB", Integer.valueOf(this.storeUncompressedSizeMB)); sb = Strings.appendKeyValue(sb, "storefileSizeMB", Integer.valueOf(this.storefileSizeMB)); if (this.storeUncompressedSizeMB != 0) { sb = Strings.appendKeyValue( sb, "compressionRatio", String.format("%.4f", (float) this.storefileSizeMB / (float) this.storeUncompressedSizeMB)); } sb = Strings.appendKeyValue(sb, "memstoreSizeMB", Integer.valueOf(this.memstoreSizeMB)); sb = Strings.appendKeyValue(sb, "storefileIndexSizeMB", Integer.valueOf(this.storefileIndexSizeMB)); sb = Strings.appendKeyValue(sb, "readRequestsCount", Long.valueOf(this.readRequestsCount)); sb = Strings.appendKeyValue(sb, "writeRequestsCount", Long.valueOf(this.writeRequestsCount)); sb = Strings.appendKeyValue(sb, "rootIndexSizeKB", Integer.valueOf(this.rootIndexSizeKB)); sb = Strings.appendKeyValue(sb, "totalStaticIndexSizeKB", Integer.valueOf(this.totalStaticIndexSizeKB)); sb = Strings.appendKeyValue(sb, "totalStaticBloomSizeKB", Integer.valueOf(this.totalStaticBloomSizeKB)); sb = Strings.appendKeyValue(sb, "totalCompactingKVs", Long.valueOf(this.totalCompactingKVs)); sb = Strings.appendKeyValue(sb, "currentCompactedKVs", Long.valueOf(this.currentCompactedKVs)); float compactionProgressPct = Float.NaN; if (this.totalCompactingKVs > 0) { compactionProgressPct = Float.valueOf((float) this.currentCompactedKVs / this.totalCompactingKVs); } sb = Strings.appendKeyValue(sb, "compactionProgressPct", compactionProgressPct); String[] coprocessorStrings = getAllCoprocessors(); if (coprocessorStrings != null) { sb = Strings.appendKeyValue(sb, "coprocessors", Arrays.toString(coprocessorStrings)); } return sb.toString(); } public static final ServerLoad EMPTY_SERVERLOAD = new ServerLoad(HBaseProtos.ServerLoad.newBuilder().build()); }