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