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    @InterfaceAudience.Private
61    public ServerLoad(ClusterStatusProtos.ServerLoad serverLoad) {
62      this.serverLoad = serverLoad;
63      for (ClusterStatusProtos.RegionLoad rl: serverLoad.getRegionLoadsList()) {
64        stores += rl.getStores();
65        storefiles += rl.getStorefiles();
66        storeUncompressedSizeMB += rl.getStoreUncompressedSizeMB();
67        storefileSizeMB += rl.getStorefileSizeMB();
68        memstoreSizeMB += rl.getMemstoreSizeMB();
69        storefileIndexSizeMB += rl.getStorefileIndexSizeMB();
70        readRequestsCount += rl.getReadRequestsCount();
71        filteredReadRequestsCount += rl.getFilteredReadRequestsCount();
72        writeRequestsCount += rl.getWriteRequestsCount();
73        rootIndexSizeKB += rl.getRootIndexSizeKB();
74        totalStaticIndexSizeKB += rl.getTotalStaticIndexSizeKB();
75        totalStaticBloomSizeKB += rl.getTotalStaticBloomSizeKB();
76        totalCompactingKVs += rl.getTotalCompactingKVs();
77        currentCompactedKVs += rl.getCurrentCompactedKVs();
78      }
79
80    }
81
82    // NOTE: Function name cannot start with "get" because then an OpenDataException is thrown because
83    // HBaseProtos.ServerLoad cannot be converted to an open data type(see HBASE-5967).
84    /* @return the underlying ServerLoad protobuf object */
85    @InterfaceAudience.Private
86    public ClusterStatusProtos.ServerLoad obtainServerLoadPB() {
87      return serverLoad;
88    }
89  
90    protected ClusterStatusProtos.ServerLoad serverLoad;
91
92    /* @return number of requests  since last report. */
93    public long getNumberOfRequests() {
94      return serverLoad.getNumberOfRequests();
95    }
96    public boolean hasNumberOfRequests() {
97      return serverLoad.hasNumberOfRequests();
98    }
99
100   /* @return total Number of requests from the start of the region server. */
101   public long getTotalNumberOfRequests() {
102     return serverLoad.getTotalNumberOfRequests();
103   }
104   public boolean hasTotalNumberOfRequests() {
105     return serverLoad.hasTotalNumberOfRequests();
106   }
107
108   /* @return the amount of used heap, in MB. */
109   public int getUsedHeapMB() {
110     return serverLoad.getUsedHeapMB();
111   }
112   public boolean hasUsedHeapMB() {
113     return serverLoad.hasUsedHeapMB();
114   }
115
116   /* @return the maximum allowable size of the heap, in MB. */
117   public int getMaxHeapMB() {
118     return serverLoad.getMaxHeapMB();
119   }
120   public boolean hasMaxHeapMB() {
121     return serverLoad.hasMaxHeapMB();
122   }
123
124   public int getStores() {
125     return stores;
126   }
127
128   public int getStorefiles() {
129     return storefiles;
130   }
131
132   public int getStoreUncompressedSizeMB() {
133     return storeUncompressedSizeMB;
134   }
135
136   public int getStorefileSizeInMB() {
137     return storefileSizeMB;
138   }
139
140   public int getMemstoreSizeInMB() {
141     return memstoreSizeMB;
142   }
143
144   public int getStorefileIndexSizeInMB() {
145     return storefileIndexSizeMB;
146   }
147
148   public long getReadRequestsCount() {
149     return readRequestsCount;
150   }
151
152   public long getFilteredReadRequestsCount() {
153     return filteredReadRequestsCount;
154   }
155
156   public long getWriteRequestsCount() {
157     return writeRequestsCount;
158   }
159
160   public int getRootIndexSizeKB() {
161     return rootIndexSizeKB;
162   }
163
164   public int getTotalStaticIndexSizeKB() {
165     return totalStaticIndexSizeKB;
166   }
167
168   public int getTotalStaticBloomSizeKB() {
169     return totalStaticBloomSizeKB;
170   }
171
172   public long getTotalCompactingKVs() {
173     return totalCompactingKVs;
174   }
175
176   public long getCurrentCompactedKVs() {
177     return currentCompactedKVs;
178   }
179
180   /**
181    * @return the number of regions
182    */
183   public int getNumberOfRegions() {
184     return serverLoad.getRegionLoadsCount();
185   }
186
187   public int getInfoServerPort() {
188     return serverLoad.getInfoServerPort();
189   }
190
191   /**
192    * Call directly from client such as hbase shell
193    * @return the list of ReplicationLoadSource
194    */
195   public List<ReplicationLoadSource> getReplicationLoadSourceList() {
196     return ProtobufUtil.toReplicationLoadSourceList(serverLoad.getReplLoadSourceList());
197   }
198
199   /**
200    * Call directly from client such as hbase shell
201    * @return ReplicationLoadSink
202    */
203   public ReplicationLoadSink getReplicationLoadSink() {
204     if (serverLoad.hasReplLoadSink()) {
205       return ProtobufUtil.toReplicationLoadSink(serverLoad.getReplLoadSink());
206     } else {
207       return null;
208     }
209   }
210
211   /**
212    * Originally, this method factored in the effect of requests going to the
213    * server as well. However, this does not interact very well with the current
214    * region rebalancing code, which only factors number of regions. For the
215    * interim, until we can figure out how to make rebalancing use all the info
216    * available, we're just going to make load purely the number of regions.
217    *
218    * @return load factor for this server
219    */
220   public int getLoad() {
221     // See above comment
222     // int load = numberOfRequests == 0 ? 1 : numberOfRequests;
223     // load *= numberOfRegions == 0 ? 1 : numberOfRegions;
224     // return load;
225     return getNumberOfRegions();
226   }
227
228   /**
229    * @return region load metrics
230    */
231   public Map<byte[], RegionLoad> getRegionsLoad() {
232     Map<byte[], RegionLoad> regionLoads =
233       new TreeMap<byte[], RegionLoad>(Bytes.BYTES_COMPARATOR);
234     for (ClusterStatusProtos.RegionLoad rl : serverLoad.getRegionLoadsList()) {
235       RegionLoad regionLoad = new RegionLoad(rl);
236       regionLoads.put(regionLoad.getName(), regionLoad);
237     }
238     return regionLoads;
239   }
240
241   /**
242    * Return the RegionServer-level coprocessors
243    * @return string array of loaded RegionServer-level coprocessors
244    */
245   public String[] getRegionServerCoprocessors() {
246     List<Coprocessor> list = obtainServerLoadPB().getCoprocessorsList();
247     String [] ret = new String[list.size()];
248     int i = 0;
249     for (Coprocessor elem : list) {
250       ret[i++] = elem.getName();
251     }
252
253     return ret;
254   }
255
256   /**
257    * Return the RegionServer-level and Region-level coprocessors
258    * @return string array of loaded RegionServer-level and
259    *         Region-level coprocessors
260    */
261   public String[] getRsCoprocessors() {
262     // Need a set to remove duplicates, but since generated Coprocessor class
263     // is not Comparable, make it a Set<String> instead of Set<Coprocessor>
264     TreeSet<String> coprocessSet = new TreeSet<String>();
265     for (Coprocessor coprocessor : obtainServerLoadPB().getCoprocessorsList()) {
266       coprocessSet.add(coprocessor.getName());
267     }
268     return coprocessSet.toArray(new String[coprocessSet.size()]);
269   }
270
271   /**
272    * @return number of requests per second received since the last report
273    */
274   public double getRequestsPerSecond() {
275     return getNumberOfRequests();
276   }
277
278   /**
279    * @see java.lang.Object#toString()
280    */
281   @Override
282   public String toString() {
283      StringBuilder sb =
284         Strings.appendKeyValue(new StringBuilder(), "requestsPerSecond",
285           Double.valueOf(getRequestsPerSecond()));
286     Strings.appendKeyValue(sb, "numberOfOnlineRegions", Integer.valueOf(getNumberOfRegions()));
287     sb = Strings.appendKeyValue(sb, "usedHeapMB", Integer.valueOf(this.getUsedHeapMB()));
288     sb = Strings.appendKeyValue(sb, "maxHeapMB", Integer.valueOf(getMaxHeapMB()));
289     sb = Strings.appendKeyValue(sb, "numberOfStores", Integer.valueOf(this.stores));
290     sb = Strings.appendKeyValue(sb, "numberOfStorefiles", Integer.valueOf(this.storefiles));
291     sb =
292         Strings.appendKeyValue(sb, "storefileUncompressedSizeMB",
293           Integer.valueOf(this.storeUncompressedSizeMB));
294     sb = Strings.appendKeyValue(sb, "storefileSizeMB", Integer.valueOf(this.storefileSizeMB));
295     if (this.storeUncompressedSizeMB != 0) {
296       sb =
297           Strings.appendKeyValue(
298             sb,
299             "compressionRatio",
300             String.format("%.4f", (float) this.storefileSizeMB
301                 / (float) this.storeUncompressedSizeMB));
302     }
303     sb = Strings.appendKeyValue(sb, "memstoreSizeMB", Integer.valueOf(this.memstoreSizeMB));
304     sb =
305         Strings.appendKeyValue(sb, "storefileIndexSizeMB",
306           Integer.valueOf(this.storefileIndexSizeMB));
307     sb = Strings.appendKeyValue(sb, "readRequestsCount", Long.valueOf(this.readRequestsCount));
308     sb = Strings.appendKeyValue(sb, "filteredReadRequestsCount",
309       Long.valueOf(this.filteredReadRequestsCount));
310     sb = Strings.appendKeyValue(sb, "writeRequestsCount", Long.valueOf(this.writeRequestsCount));
311     sb = Strings.appendKeyValue(sb, "rootIndexSizeKB", Integer.valueOf(this.rootIndexSizeKB));
312     sb =
313         Strings.appendKeyValue(sb, "totalStaticIndexSizeKB",
314           Integer.valueOf(this.totalStaticIndexSizeKB));
315     sb =
316         Strings.appendKeyValue(sb, "totalStaticBloomSizeKB",
317           Integer.valueOf(this.totalStaticBloomSizeKB));
318     sb = Strings.appendKeyValue(sb, "totalCompactingKVs", Long.valueOf(this.totalCompactingKVs));
319     sb = Strings.appendKeyValue(sb, "currentCompactedKVs", Long.valueOf(this.currentCompactedKVs));
320     float compactionProgressPct = Float.NaN;
321     if (this.totalCompactingKVs > 0) {
322       compactionProgressPct =
323           Float.valueOf((float) this.currentCompactedKVs / this.totalCompactingKVs);
324     }
325     sb = Strings.appendKeyValue(sb, "compactionProgressPct", compactionProgressPct);
326
327     String[] coprocessorStrings = getRsCoprocessors();
328     if (coprocessorStrings != null) {
329       sb = Strings.appendKeyValue(sb, "coprocessors", Arrays.toString(coprocessorStrings));
330     }
331     return sb.toString();
332   }
333
334   public static final ServerLoad EMPTY_SERVERLOAD =
335     new ServerLoad(ClusterStatusProtos.ServerLoad.newBuilder().build());
336 }