View Javadoc

1   /**
2    * Copyright The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package org.apache.hadoop.hbase;
22  
23  import java.util.Arrays;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.TreeMap;
27  import java.util.TreeSet;
28  
29  import org.apache.hadoop.hbase.classification.InterfaceAudience;
30  import org.apache.hadoop.hbase.classification.InterfaceStability;
31  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
32  import org.apache.hadoop.hbase.protobuf.generated.ClusterStatusProtos;
33  import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.Coprocessor;
34  import org.apache.hadoop.hbase.replication.ReplicationLoadSink;
35  import org.apache.hadoop.hbase.replication.ReplicationLoadSource;
36  import org.apache.hadoop.hbase.util.Bytes;
37  import org.apache.hadoop.hbase.util.Strings;
38  
39  /**
40   * This class is used for exporting current state of load on a RegionServer.
41   */
42  @InterfaceAudience.Public
43  @InterfaceStability.Evolving
44  public class ServerLoad {
45    private int stores = 0;
46    private int storefiles = 0;
47    private int storeUncompressedSizeMB = 0;
48    private int storefileSizeMB = 0;
49    private int memstoreSizeMB = 0;
50    private int storefileIndexSizeMB = 0;
51    private long readRequestsCount = 0;
52    private long filteredReadRequestsCount = 0;
53    private long writeRequestsCount = 0;
54    private int rootIndexSizeKB = 0;
55    private int totalStaticIndexSizeKB = 0;
56    private int totalStaticBloomSizeKB = 0;
57    private long totalCompactingKVs = 0;
58    private long currentCompactedKVs = 0;
59  
60    public ServerLoad(ClusterStatusProtos.ServerLoad serverLoad) {
61      this.serverLoad = serverLoad;
62      for (ClusterStatusProtos.RegionLoad rl: serverLoad.getRegionLoadsList()) {
63        stores += rl.getStores();
64        storefiles += rl.getStorefiles();
65        storeUncompressedSizeMB += rl.getStoreUncompressedSizeMB();
66        storefileSizeMB += rl.getStorefileSizeMB();
67        memstoreSizeMB += rl.getMemstoreSizeMB();
68        storefileIndexSizeMB += rl.getStorefileIndexSizeMB();
69        readRequestsCount += rl.getReadRequestsCount();
70        filteredReadRequestsCount += rl.getFilteredReadRequestsCount();
71        writeRequestsCount += rl.getWriteRequestsCount();
72        rootIndexSizeKB += rl.getRootIndexSizeKB();
73        totalStaticIndexSizeKB += rl.getTotalStaticIndexSizeKB();
74        totalStaticBloomSizeKB += rl.getTotalStaticBloomSizeKB();
75        totalCompactingKVs += rl.getTotalCompactingKVs();
76        currentCompactedKVs += rl.getCurrentCompactedKVs();
77      }
78  
79    }
80  
81    // NOTE: Function name cannot start with "get" because then an OpenDataException is thrown because
82    // HBaseProtos.ServerLoad cannot be converted to an open data type(see HBASE-5967).
83    /* @return the underlying ServerLoad protobuf object */
84    public ClusterStatusProtos.ServerLoad obtainServerLoadPB() {
85      return serverLoad;
86    }
87  
88    protected ClusterStatusProtos.ServerLoad serverLoad;
89  
90    /* @return number of requests  since last report. */
91    public long getNumberOfRequests() {
92      return serverLoad.getNumberOfRequests();
93    }
94    public boolean hasNumberOfRequests() {
95      return serverLoad.hasNumberOfRequests();
96    }
97  
98    /* @return total Number of requests from the start of the region server. */
99    public long getTotalNumberOfRequests() {
100     return serverLoad.getTotalNumberOfRequests();
101   }
102   public boolean hasTotalNumberOfRequests() {
103     return serverLoad.hasTotalNumberOfRequests();
104   }
105 
106   /* @return the amount of used heap, in MB. */
107   public int getUsedHeapMB() {
108     return serverLoad.getUsedHeapMB();
109   }
110   public boolean hasUsedHeapMB() {
111     return serverLoad.hasUsedHeapMB();
112   }
113 
114   /* @return the maximum allowable size of the heap, in MB. */
115   public int getMaxHeapMB() {
116     return serverLoad.getMaxHeapMB();
117   }
118   public boolean hasMaxHeapMB() {
119     return serverLoad.hasMaxHeapMB();
120   }
121 
122   public int getStores() {
123     return stores;
124   }
125 
126   public int getStorefiles() {
127     return storefiles;
128   }
129 
130   public int getStoreUncompressedSizeMB() {
131     return storeUncompressedSizeMB;
132   }
133 
134   public int getStorefileSizeInMB() {
135     return storefileSizeMB;
136   }
137 
138   public int getMemstoreSizeInMB() {
139     return memstoreSizeMB;
140   }
141 
142   public int getStorefileIndexSizeInMB() {
143     return storefileIndexSizeMB;
144   }
145 
146   public long getReadRequestsCount() {
147     return readRequestsCount;
148   }
149 
150   public long getFilteredReadRequestsCount() {
151     return filteredReadRequestsCount;
152   }
153 
154   public long getWriteRequestsCount() {
155     return writeRequestsCount;
156   }
157 
158   public int getRootIndexSizeKB() {
159     return rootIndexSizeKB;
160   }
161 
162   public int getTotalStaticIndexSizeKB() {
163     return totalStaticIndexSizeKB;
164   }
165 
166   public int getTotalStaticBloomSizeKB() {
167     return totalStaticBloomSizeKB;
168   }
169 
170   public long getTotalCompactingKVs() {
171     return totalCompactingKVs;
172   }
173 
174   public long getCurrentCompactedKVs() {
175     return currentCompactedKVs;
176   }
177 
178   /**
179    * @return the number of regions
180    */
181   public int getNumberOfRegions() {
182     return serverLoad.getRegionLoadsCount();
183   }
184 
185   public int getInfoServerPort() {
186     return serverLoad.getInfoServerPort();
187   }
188 
189   /**
190    * Call directly from client such as hbase shell
191    * @return the list of ReplicationLoadSource
192    */
193   public List<ReplicationLoadSource> getReplicationLoadSourceList() {
194     return ProtobufUtil.toReplicationLoadSourceList(serverLoad.getReplLoadSourceList());
195   }
196 
197   /**
198    * Call directly from client such as hbase shell
199    * @return ReplicationLoadSink
200    */
201   public ReplicationLoadSink getReplicationLoadSink() {
202     if (serverLoad.hasReplLoadSink()) {
203       return ProtobufUtil.toReplicationLoadSink(serverLoad.getReplLoadSink());
204     } else {
205       return null;
206     }
207   }
208 
209   /**
210    * Originally, this method factored in the effect of requests going to the
211    * server as well. However, this does not interact very well with the current
212    * region rebalancing code, which only factors number of regions. For the
213    * interim, until we can figure out how to make rebalancing use all the info
214    * available, we're just going to make load purely the number of regions.
215    *
216    * @return load factor for this server
217    */
218   public int getLoad() {
219     // See above comment
220     // int load = numberOfRequests == 0 ? 1 : numberOfRequests;
221     // load *= numberOfRegions == 0 ? 1 : numberOfRegions;
222     // return load;
223     return getNumberOfRegions();
224   }
225 
226   /**
227    * @return region load metrics
228    */
229   public Map<byte[], RegionLoad> getRegionsLoad() {
230     Map<byte[], RegionLoad> regionLoads =
231       new TreeMap<byte[], RegionLoad>(Bytes.BYTES_COMPARATOR);
232     for (ClusterStatusProtos.RegionLoad rl : serverLoad.getRegionLoadsList()) {
233       RegionLoad regionLoad = new RegionLoad(rl);
234       regionLoads.put(regionLoad.getName(), regionLoad);
235     }
236     return regionLoads;
237   }
238 
239   /**
240    * Return the RegionServer-level coprocessors
241    * @return string array of loaded RegionServer-level coprocessors
242    */
243   public String[] getRegionServerCoprocessors() {
244     List<Coprocessor> list = obtainServerLoadPB().getCoprocessorsList();
245     String [] ret = new String[list.size()];
246     int i = 0;
247     for (Coprocessor elem : list) {
248       ret[i++] = elem.getName();
249     }
250 
251     return ret;
252   }
253 
254   /**
255    * Return the RegionServer-level and Region-level coprocessors
256    * @return string array of loaded RegionServer-level and
257    *         Region-level coprocessors
258    */
259   public String[] getRsCoprocessors() {
260     // Need a set to remove duplicates, but since generated Coprocessor class
261     // is not Comparable, make it a Set<String> instead of Set<Coprocessor>
262     TreeSet<String> coprocessSet = new TreeSet<String>();
263     for (Coprocessor coprocessor : obtainServerLoadPB().getCoprocessorsList()) {
264       coprocessSet.add(coprocessor.getName());
265     }
266     return coprocessSet.toArray(new String[coprocessSet.size()]);
267   }
268 
269   /**
270    * @return number of requests per second received since the last report
271    */
272   public double getRequestsPerSecond() {
273     return getNumberOfRequests();
274   }
275 
276   /**
277    * @see java.lang.Object#toString()
278    */
279   @Override
280   public String toString() {
281      StringBuilder sb =
282         Strings.appendKeyValue(new StringBuilder(), "requestsPerSecond",
283           Double.valueOf(getRequestsPerSecond()));
284     Strings.appendKeyValue(sb, "numberOfOnlineRegions", Integer.valueOf(getNumberOfRegions()));
285     sb = Strings.appendKeyValue(sb, "usedHeapMB", Integer.valueOf(this.getUsedHeapMB()));
286     sb = Strings.appendKeyValue(sb, "maxHeapMB", Integer.valueOf(getMaxHeapMB()));
287     sb = Strings.appendKeyValue(sb, "numberOfStores", Integer.valueOf(this.stores));
288     sb = Strings.appendKeyValue(sb, "numberOfStorefiles", Integer.valueOf(this.storefiles));
289     sb =
290         Strings.appendKeyValue(sb, "storefileUncompressedSizeMB",
291           Integer.valueOf(this.storeUncompressedSizeMB));
292     sb = Strings.appendKeyValue(sb, "storefileSizeMB", Integer.valueOf(this.storefileSizeMB));
293     if (this.storeUncompressedSizeMB != 0) {
294       sb =
295           Strings.appendKeyValue(
296             sb,
297             "compressionRatio",
298             String.format("%.4f", (float) this.storefileSizeMB
299                 / (float) this.storeUncompressedSizeMB));
300     }
301     sb = Strings.appendKeyValue(sb, "memstoreSizeMB", Integer.valueOf(this.memstoreSizeMB));
302     sb =
303         Strings.appendKeyValue(sb, "storefileIndexSizeMB",
304           Integer.valueOf(this.storefileIndexSizeMB));
305     sb = Strings.appendKeyValue(sb, "readRequestsCount", Long.valueOf(this.readRequestsCount));
306     sb = Strings.appendKeyValue(sb, "filteredReadRequestsCount",
307       Long.valueOf(this.filteredReadRequestsCount));
308     sb = Strings.appendKeyValue(sb, "writeRequestsCount", Long.valueOf(this.writeRequestsCount));
309     sb = Strings.appendKeyValue(sb, "rootIndexSizeKB", Integer.valueOf(this.rootIndexSizeKB));
310     sb =
311         Strings.appendKeyValue(sb, "totalStaticIndexSizeKB",
312           Integer.valueOf(this.totalStaticIndexSizeKB));
313     sb =
314         Strings.appendKeyValue(sb, "totalStaticBloomSizeKB",
315           Integer.valueOf(this.totalStaticBloomSizeKB));
316     sb = Strings.appendKeyValue(sb, "totalCompactingKVs", Long.valueOf(this.totalCompactingKVs));
317     sb = Strings.appendKeyValue(sb, "currentCompactedKVs", Long.valueOf(this.currentCompactedKVs));
318     float compactionProgressPct = Float.NaN;
319     if (this.totalCompactingKVs > 0) {
320       compactionProgressPct =
321           Float.valueOf((float) this.currentCompactedKVs / this.totalCompactingKVs);
322     }
323     sb = Strings.appendKeyValue(sb, "compactionProgressPct", compactionProgressPct);
324 
325     String[] coprocessorStrings = getRsCoprocessors();
326     if (coprocessorStrings != null) {
327       sb = Strings.appendKeyValue(sb, "coprocessors", Arrays.toString(coprocessorStrings));
328     }
329     return sb.toString();
330   }
331 
332   public static final ServerLoad EMPTY_SERVERLOAD =
333     new ServerLoad(ClusterStatusProtos.ServerLoad.newBuilder().build());
334 }