View Javadoc

1   /**
2    * Copyright 2007 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  package org.apache.hadoop.hbase;
21  
22  import java.io.DataInput;
23  import java.io.DataOutput;
24  import java.io.IOException;
25  import java.util.ArrayList;
26  import java.util.Collection;
27  import java.util.Collections;
28  
29  import org.apache.hadoop.hbase.util.Bytes;
30  import org.apache.hadoop.hbase.util.Strings;
31  import org.apache.hadoop.io.Writable;
32  import org.apache.hadoop.io.WritableComparable;
33  
34  /**
35   * This class encapsulates metrics for determining the load on a HRegionServer
36   */
37  public class HServerLoad implements WritableComparable<HServerLoad> {
38    /** number of regions */
39      // could just use regionLoad.size() but master.RegionManager likes to play
40      // around with this value while passing HServerLoad objects around during
41      // balancer calculations
42    private int numberOfRegions;
43    /** number of requests since last report */
44    private int numberOfRequests;
45    /** the amount of used heap, in MB */
46    private int usedHeapMB;
47    /** the maximum allowable size of the heap, in MB */
48    private int maxHeapMB;
49    /** per-region load metrics */
50    private ArrayList<RegionLoad> regionLoad = new ArrayList<RegionLoad>();
51  
52    /**
53     * Encapsulates per-region loading metrics.
54     */
55    public static class RegionLoad implements Writable {
56      /** the region name */
57      private byte[] name;
58      /** the number of stores for the region */
59      private int stores;
60      /** the number of storefiles for the region */
61      private int storefiles;
62      /** the current total size of the store files for the region, in MB */
63      private int storefileSizeMB;
64      /** the current size of the memstore for the region, in MB */
65      private int memstoreSizeMB;
66      /** the current total size of storefile indexes for the region, in MB */
67      private int storefileIndexSizeMB;
68  
69      /**
70       * Constructor, for Writable
71       */
72      public RegionLoad() {
73          super();
74      }
75  
76      /**
77       * @param name
78       * @param stores
79       * @param storefiles
80       * @param storefileSizeMB
81       * @param memstoreSizeMB
82       * @param storefileIndexSizeMB
83       */
84      public RegionLoad(final byte[] name, final int stores,
85          final int storefiles, final int storefileSizeMB,
86          final int memstoreSizeMB, final int storefileIndexSizeMB) {
87        this.name = name;
88        this.stores = stores;
89        this.storefiles = storefiles;
90        this.storefileSizeMB = storefileSizeMB;
91        this.memstoreSizeMB = memstoreSizeMB;
92        this.storefileIndexSizeMB = storefileIndexSizeMB;
93      }
94  
95      // Getters
96  
97      /**
98       * @return the region name
99       */
100     public byte[] getName() {
101       return name;
102     }
103 
104     /**
105      * @return the region name as a string
106      */
107     public String getNameAsString() {
108       return Bytes.toString(name);
109     }
110 
111     /**
112      * @return the number of stores
113      */
114     public int getStores() {
115       return stores;
116     }
117 
118     /**
119      * @return the number of storefiles
120      */
121     public int getStorefiles() {
122       return storefiles;
123     }
124 
125     /**
126      * @return the total size of the storefiles, in MB
127      */
128     public int getStorefileSizeMB() {
129       return storefileSizeMB;
130     }
131 
132     /**
133      * @return the memstore size, in MB
134      */
135     public int getMemStoreSizeMB() {
136       return memstoreSizeMB;
137     }
138 
139     /**
140      * @return the approximate size of storefile indexes on the heap, in MB
141      */
142     public int getStorefileIndexSizeMB() {
143       return storefileIndexSizeMB;
144     }
145 
146     // Setters
147 
148     /**
149      * @param name the region name
150      */
151     public void setName(byte[] name) {
152       this.name = name;
153     }
154 
155     /**
156      * @param stores the number of stores
157      */
158     public void setStores(int stores) {
159       this.stores = stores;
160     }
161 
162     /**
163      * @param storefiles the number of storefiles
164      */
165     public void setStorefiles(int storefiles) {
166       this.storefiles = storefiles;
167     }
168 
169     /**
170      * @param memstoreSizeMB the memstore size, in MB
171      */
172     public void setMemStoreSizeMB(int memstoreSizeMB) {
173       this.memstoreSizeMB = memstoreSizeMB;
174     }
175 
176     /**
177      * @param storefileIndexSizeMB the approximate size of storefile indexes
178      *  on the heap, in MB
179      */
180     public void setStorefileIndexSizeMB(int storefileIndexSizeMB) {
181       this.storefileIndexSizeMB = storefileIndexSizeMB;
182     }
183 
184     // Writable
185     public void readFields(DataInput in) throws IOException {
186       int namelen = in.readInt();
187       this.name = new byte[namelen];
188       in.readFully(this.name);
189       this.stores = in.readInt();
190       this.storefiles = in.readInt();
191       this.storefileSizeMB = in.readInt();
192       this.memstoreSizeMB = in.readInt();
193       this.storefileIndexSizeMB = in.readInt();
194     }
195 
196     public void write(DataOutput out) throws IOException {
197       out.writeInt(name.length);
198       out.write(name);
199       out.writeInt(stores);
200       out.writeInt(storefiles);
201       out.writeInt(storefileSizeMB);
202       out.writeInt(memstoreSizeMB);
203       out.writeInt(storefileIndexSizeMB);
204     }
205 
206     /**
207      * @see java.lang.Object#toString()
208      */
209     @Override
210     public String toString() {
211       StringBuilder sb = Strings.appendKeyValue(new StringBuilder(), "stores",
212         Integer.valueOf(this.stores));
213       sb = Strings.appendKeyValue(sb, "storefiles",
214         Integer.valueOf(this.storefiles));
215       sb = Strings.appendKeyValue(sb, "storefileSizeMB",
216           Integer.valueOf(this.storefileSizeMB));
217       sb = Strings.appendKeyValue(sb, "memstoreSizeMB",
218         Integer.valueOf(this.memstoreSizeMB));
219       sb = Strings.appendKeyValue(sb, "storefileIndexSizeMB",
220         Integer.valueOf(this.storefileIndexSizeMB));
221       return sb.toString();
222     }
223   }
224 
225   /*
226    * TODO: Other metrics that might be considered when the master is actually
227    * doing load balancing instead of merely trying to decide where to assign
228    * a region:
229    * <ul>
230    *   <li># of CPUs, heap size (to determine the "class" of machine). For
231    *       now, we consider them to be homogeneous.</li>
232    *   <li>#requests per region (Map<{String|HRegionInfo}, Integer>)</li>
233    *   <li>#compactions and/or #splits (churn)</li>
234    *   <li>server death rate (maybe there is something wrong with this server)</li>
235    * </ul>
236    */
237 
238   /** default constructor (used by Writable) */
239   public HServerLoad() {
240     super();
241   }
242 
243   /**
244    * Constructor
245    * @param numberOfRequests
246    * @param usedHeapMB
247    * @param maxHeapMB
248    */
249   public HServerLoad(final int numberOfRequests, final int usedHeapMB,
250       final int maxHeapMB) {
251     this.numberOfRequests = numberOfRequests;
252     this.usedHeapMB = usedHeapMB;
253     this.maxHeapMB = maxHeapMB;
254   }
255 
256   /**
257    * Constructor
258    * @param hsl the template HServerLoad
259    */
260   public HServerLoad(final HServerLoad hsl) {
261     this(hsl.numberOfRequests, hsl.usedHeapMB, hsl.maxHeapMB);
262     this.regionLoad.addAll(hsl.regionLoad);
263   }
264 
265   /**
266    * Originally, this method factored in the effect of requests going to the
267    * server as well. However, this does not interact very well with the current
268    * region rebalancing code, which only factors number of regions. For the
269    * interim, until we can figure out how to make rebalancing use all the info
270    * available, we're just going to make load purely the number of regions.
271    *
272    * @return load factor for this server
273    */
274   public int getLoad() {
275     // int load = numberOfRequests == 0 ? 1 : numberOfRequests;
276     // load *= numberOfRegions == 0 ? 1 : numberOfRegions;
277     // return load;
278     return numberOfRegions;
279   }
280 
281   /**
282    * @see java.lang.Object#toString()
283    */
284   @Override
285   public String toString() {
286     return toString(1);
287   }
288 
289   /**
290    * Returns toString() with the number of requests divided by the message
291    * interval in seconds
292    * @param msgInterval
293    * @return The load as a String
294    */
295   public String toString(int msgInterval) {
296     StringBuilder sb = new StringBuilder();
297     sb = Strings.appendKeyValue(sb, "requests",
298       Integer.valueOf(numberOfRequests/msgInterval));
299     sb = Strings.appendKeyValue(sb, "regions",
300       Integer.valueOf(numberOfRegions));
301     sb = Strings.appendKeyValue(sb, "usedHeap",
302       Integer.valueOf(this.usedHeapMB));
303     sb = Strings.appendKeyValue(sb, "maxHeap", Integer.valueOf(maxHeapMB));
304     return sb.toString();
305   }
306 
307   /**
308    * @see java.lang.Object#equals(java.lang.Object)
309    */
310   @Override
311   public boolean equals(Object o) {
312     if (this == o) {
313       return true;
314     }
315     if (o == null) {
316       return false;
317     }
318     if (getClass() != o.getClass()) {
319       return false;
320     }
321     return compareTo((HServerLoad)o) == 0;
322   }
323 
324   /**
325    * @see java.lang.Object#hashCode()
326    */
327   @Override
328   public int hashCode() {
329     int result = Integer.valueOf(numberOfRequests).hashCode();
330     result ^= Integer.valueOf(numberOfRegions).hashCode();
331     return result;
332   }
333 
334   // Getters
335 
336   /**
337    * @return the numberOfRegions
338    */
339   public int getNumberOfRegions() {
340     return numberOfRegions;
341   }
342 
343   /**
344    * @return the numberOfRequests
345    */
346   public int getNumberOfRequests() {
347     return numberOfRequests;
348   }
349 
350   /**
351    * @return the amount of heap in use, in MB
352    */
353   public int getUsedHeapMB() {
354     return usedHeapMB;
355   }
356 
357   /**
358    * @return the maximum allowable heap size, in MB
359    */
360   public int getMaxHeapMB() {
361     return maxHeapMB;
362   }
363 
364   /**
365    * @return region load metrics
366    */
367   public Collection<RegionLoad> getRegionsLoad() {
368     return Collections.unmodifiableCollection(regionLoad);
369   }
370 
371   /**
372    * @return Count of storefiles on this regionserver
373    */
374   public int getStorefiles() {
375     int count = 0;
376     for (RegionLoad info: regionLoad)
377     	count += info.getStorefiles();
378     return count;
379   }
380 
381   /**
382    * @return Total size of store files in MB
383    */
384   public int getStorefileSizeInMB() {
385     int count = 0;
386     for (RegionLoad info: regionLoad)
387       count += info.getStorefileSizeMB();
388     return count;
389   }
390 
391   /**
392    * @return Size of memstores in MB
393    */
394   public int getMemStoreSizeInMB() {
395     int count = 0;
396     for (RegionLoad info: regionLoad)
397     	count += info.getMemStoreSizeMB();
398     return count;
399   }
400 
401   /**
402    * @return Size of store file indexes in MB
403    */
404   public int getStorefileIndexSizeInMB() {
405     int count = 0;
406     for (RegionLoad info: regionLoad)
407     	count += info.getStorefileIndexSizeMB();
408     return count;
409   }
410 
411   // Setters
412 
413   /**
414    * @param numberOfRegions the number of regions
415    */
416   public void setNumberOfRegions(int numberOfRegions) {
417     this.numberOfRegions = numberOfRegions;
418   }
419 
420   /**
421    * @param numberOfRequests the number of requests to set
422    */
423   public void setNumberOfRequests(int numberOfRequests) {
424     this.numberOfRequests = numberOfRequests;
425   }
426 
427   /**
428    * @param usedHeapMB the amount of heap in use, in MB
429    */
430   public void setUsedHeapMB(int usedHeapMB) {
431     this.usedHeapMB = usedHeapMB;
432   }
433 
434   /**
435    * @param maxHeapMB the maximum allowable heap size, in MB
436    */
437   public void setMaxHeapMB(int maxHeapMB) {
438     this.maxHeapMB = maxHeapMB;
439   }
440 
441   /**
442    * @param load Instance of HServerLoad
443    */
444   public void addRegionInfo(final HServerLoad.RegionLoad load) {
445     this.numberOfRegions++;
446     this.regionLoad.add(load);
447   }
448 
449   /**
450    * @param name
451    * @param stores
452    * @param storefiles
453    * @param memstoreSizeMB
454    * @param storefileIndexSizeMB
455    * @deprecated Use {@link #addRegionInfo(RegionLoad)}
456    */
457   @Deprecated
458   public void addRegionInfo(final byte[] name, final int stores,
459       final int storefiles, final int storefileSizeMB,
460       final int memstoreSizeMB, final int storefileIndexSizeMB) {
461     this.regionLoad.add(new HServerLoad.RegionLoad(name, stores, storefiles,
462       storefileSizeMB, memstoreSizeMB, storefileIndexSizeMB));
463   }
464 
465   // Writable
466 
467   public void readFields(DataInput in) throws IOException {
468     numberOfRequests = in.readInt();
469     usedHeapMB = in.readInt();
470     maxHeapMB = in.readInt();
471     numberOfRegions = in.readInt();
472     for (int i = 0; i < numberOfRegions; i++) {
473       RegionLoad rl = new RegionLoad();
474       rl.readFields(in);
475       regionLoad.add(rl);
476     }
477   }
478 
479   public void write(DataOutput out) throws IOException {
480     out.writeInt(numberOfRequests);
481     out.writeInt(usedHeapMB);
482     out.writeInt(maxHeapMB);
483     out.writeInt(numberOfRegions);
484     for (int i = 0; i < numberOfRegions; i++)
485       regionLoad.get(i).write(out);
486   }
487 
488   // Comparable
489 
490   public int compareTo(HServerLoad o) {
491     return this.getLoad() - o.getLoad();
492   }
493 }