View Javadoc

1   /*
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  
20  package org.apache.hadoop.hbase.rest.model;
21  
22  import java.io.IOException;
23  import java.io.Serializable;
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  import javax.xml.bind.annotation.XmlAttribute;
28  import javax.xml.bind.annotation.XmlElement;
29  import javax.xml.bind.annotation.XmlElementWrapper;
30  import javax.xml.bind.annotation.XmlRootElement;
31  
32  import com.google.protobuf.HBaseZeroCopyByteString;
33  import org.apache.hadoop.classification.InterfaceAudience;
34  import org.apache.hadoop.hbase.rest.ProtobufMessageHandler;
35  import org.apache.hadoop.hbase.rest.protobuf.generated.StorageClusterStatusMessage.StorageClusterStatus;
36  import org.apache.hadoop.hbase.util.Bytes;
37  
38  /**
39   * Representation of the status of a storage cluster:
40   * <p>
41   * <ul>
42   * <li>regions: the total number of regions served by the cluster</li>
43   * <li>requests: the total number of requests per second handled by the
44   * cluster in the last reporting interval</li>
45   * <li>averageLoad: the average load of the region servers in the cluster</li>
46   * <li>liveNodes: detailed status of the live region servers</li>
47   * <li>deadNodes: the names of region servers declared dead</li>
48   * </ul>
49   * 
50   * <pre>
51   * &lt;complexType name="StorageClusterStatus"&gt;
52   *   &lt;sequence&gt;
53   *     &lt;element name="liveNode" type="tns:Node"
54   *       maxOccurs="unbounded" minOccurs="0"&gt;
55   *     &lt;/element&gt;
56   *     &lt;element name="deadNode" type="string" maxOccurs="unbounded"
57   *       minOccurs="0"&gt;
58   *     &lt;/element&gt;
59   *   &lt;/sequence&gt;
60   *   &lt;attribute name="regions" type="int"&gt;&lt;/attribute&gt;
61   *   &lt;attribute name="requests" type="int"&gt;&lt;/attribute&gt;
62   *   &lt;attribute name="averageLoad" type="float"&gt;&lt;/attribute&gt;
63   * &lt;/complexType&gt;
64   *
65   * &lt;complexType name="Node"&gt;
66   *   &lt;sequence&gt;
67   *     &lt;element name="region" type="tns:Region" 
68   *       maxOccurs="unbounded" minOccurs="0"&gt;&lt;/element&gt;
69   *   &lt;/sequence&gt;
70   *   &lt;attribute name="name" type="string"&gt;&lt;/attribute&gt;
71   *   &lt;attribute name="startCode" type="int"&gt;&lt;/attribute&gt;
72   *   &lt;attribute name="requests" type="int"&gt;&lt;/attribute&gt;
73   *   &lt;attribute name="heapSizeMB" type="int"&gt;&lt;/attribute&gt;
74   *   &lt;attribute name="maxHeapSizeMB" type="int"&gt;&lt;/attribute&gt;
75   * &lt;/complexType&gt;
76   *
77   * &lt;complexType name="Region"&gt;
78   *   &lt;attribute name="name" type="base64Binary"&gt;&lt;/attribute&gt;
79   *   &lt;attribute name="stores" type="int"&gt;&lt;/attribute&gt;
80   *   &lt;attribute name="storefiles" type="int"&gt;&lt;/attribute&gt;
81   *   &lt;attribute name="storefileSizeMB" type="int"&gt;&lt;/attribute&gt;
82   *   &lt;attribute name="memstoreSizeMB" type="int"&gt;&lt;/attribute&gt;
83   *   &lt;attribute name="storefileIndexSizeMB" type="int"&gt;&lt;/attribute&gt;
84   *   &lt;attribute name="readRequestsCount" type="int"&gt;&lt;/attribute&gt;
85   *   &lt;attribute name="writeRequestsCount" type="int"&gt;&lt;/attribute&gt;
86   *   &lt;attribute name="rootIndexSizeKB" type="int"&gt;&lt;/attribute&gt;
87   *   &lt;attribute name="totalStaticIndexSizeKB" type="int"&gt;&lt;/attribute&gt;
88   *   &lt;attribute name="totalStaticBloomSizeKB" type="int"&gt;&lt;/attribute&gt;
89   *   &lt;attribute name="totalCompactingKVs" type="int"&gt;&lt;/attribute&gt;
90   *   &lt;attribute name="currentCompactedKVs" type="int"&gt;&lt;/attribute&gt;
91   * &lt;/complexType&gt;
92   * </pre>
93   */
94  @XmlRootElement(name="ClusterStatus")
95  @InterfaceAudience.Private
96  public class StorageClusterStatusModel 
97      implements Serializable, ProtobufMessageHandler {
98    private static final long serialVersionUID = 1L;
99  
100   /**
101    * Represents a region server.
102    */
103   public static class Node implements Serializable {
104     private static final long serialVersionUID = 1L;
105 
106     /**
107      * Represents a region hosted on a region server.
108      */
109     public static class Region {
110       private byte[] name;
111       private int stores;
112       private int storefiles;
113       private int storefileSizeMB;
114       private int memstoreSizeMB;
115       private int storefileIndexSizeMB;
116       private long readRequestsCount;
117       private long writeRequestsCount;
118       private int rootIndexSizeKB;
119       private int totalStaticIndexSizeKB;
120       private int totalStaticBloomSizeKB;
121       private long totalCompactingKVs;
122       private long currentCompactedKVs;
123 
124       /**
125        * Default constructor
126        */
127       public Region() {
128       }
129 
130       /**
131        * Constructor
132        * @param name the region name
133        */
134       public Region(byte[] name) {
135         this.name = name;
136       }
137 
138       /**
139        * Constructor
140        * @param name the region name
141        * @param stores the number of stores
142        * @param storefiles the number of store files
143        * @param storefileSizeMB total size of store files, in MB
144        * @param memstoreSizeMB total size of memstore, in MB
145        * @param storefileIndexSizeMB total size of store file indexes, in MB
146        */
147       public Region(byte[] name, int stores, int storefiles,
148           int storefileSizeMB, int memstoreSizeMB, int storefileIndexSizeMB,
149           long readRequestsCount, long writeRequestsCount, int rootIndexSizeKB,
150           int totalStaticIndexSizeKB, int totalStaticBloomSizeKB,
151           long totalCompactingKVs, long currentCompactedKVs) {
152         this.name = name;
153         this.stores = stores;
154         this.storefiles = storefiles;
155         this.storefileSizeMB = storefileSizeMB;
156         this.memstoreSizeMB = memstoreSizeMB;
157         this.storefileIndexSizeMB = storefileIndexSizeMB;
158         this.readRequestsCount = readRequestsCount;
159         this.writeRequestsCount = writeRequestsCount;
160         this.rootIndexSizeKB = rootIndexSizeKB;
161         this.totalStaticIndexSizeKB = totalStaticIndexSizeKB;
162         this.totalStaticBloomSizeKB = totalStaticBloomSizeKB;
163         this.totalCompactingKVs = totalCompactingKVs;
164         this.currentCompactedKVs = currentCompactedKVs;
165       }
166 
167       /**
168        * @return the region name
169        */
170       @XmlAttribute
171       public byte[] getName() {
172         return name;
173       }
174 
175       /**
176        * @return the number of stores
177        */
178       @XmlAttribute
179       public int getStores() {
180         return stores;
181       }
182 
183       /**
184        * @return the number of store files 
185        */
186       @XmlAttribute
187       public int getStorefiles() {
188         return storefiles;
189       }
190 
191       /**
192        * @return the total size of store files, in MB
193        */
194       @XmlAttribute
195       public int getStorefileSizeMB() {
196         return storefileSizeMB;
197       }
198 
199       /**
200        * @return memstore size, in MB
201        */
202       @XmlAttribute
203       public int getMemstoreSizeMB() {
204         return memstoreSizeMB;
205       }
206 
207       /**
208        * @return the total size of store file indexes, in MB
209        */
210       @XmlAttribute
211       public int getStorefileIndexSizeMB() {
212         return storefileIndexSizeMB;
213       }
214 
215       /**
216        * @return the current total read requests made to region
217        */
218       @XmlAttribute
219       public long getReadRequestsCount() {
220         return readRequestsCount;
221       }
222 
223       /**
224        * @return the current total write requests made to region
225        */
226       @XmlAttribute
227       public long getWriteRequestsCount() {
228         return writeRequestsCount;
229       }
230 
231       /**
232        * @return The current total size of root-level indexes for the region, in KB.
233        */
234       @XmlAttribute
235       public int getRootIndexSizeKB() {
236         return rootIndexSizeKB;
237       }
238 
239       /**
240        * @return The total size of static index, in KB
241        */
242       @XmlAttribute
243       public int getTotalStaticIndexSizeKB() {
244         return totalStaticIndexSizeKB;
245       }
246 
247       /**
248        * @return The total size of static bloom, in KB
249        */
250       @XmlAttribute
251       public int getTotalStaticBloomSizeKB() {
252         return totalStaticBloomSizeKB;
253       }
254 
255       /**
256        * @return The total number of compacting key-values 
257        */
258       @XmlAttribute
259       public long getTotalCompactingKVs() {
260         return totalCompactingKVs;
261       }
262 
263       /**
264        * @return The number of current compacted key-values
265        */
266       @XmlAttribute
267       public long getCurrentCompactedKVs() {
268         return currentCompactedKVs;
269       }
270 
271       /**
272        * @param readRequestsCount The current total read requests made to region
273        */
274       public void setReadRequestsCount(long readRequestsCount) {
275         this.readRequestsCount = readRequestsCount;
276       }
277 
278       /**
279        * @param rootIndexSizeKB The current total size of root-level indexes
280        *                        for the region, in KB
281        */
282       public void setRootIndexSizeKB(int rootIndexSizeKB) {
283         this.rootIndexSizeKB = rootIndexSizeKB;
284       }
285 
286       /**
287        * @param writeRequestsCount The current total write requests made to region
288        */
289       public void setWriteRequestsCount(long writeRequestsCount) {
290         this.writeRequestsCount = writeRequestsCount;
291       }
292 
293       /**
294        * @param currentCompactedKVs The completed count of key values
295        *                            in currently running compaction
296        */
297       public void setCurrentCompactedKVs(long currentCompactedKVs) {
298         this.currentCompactedKVs = currentCompactedKVs;
299       }
300 
301       /**
302        * @param totalCompactingKVs The total compacting key values
303        *                           in currently running compaction
304        */
305       public void setTotalCompactingKVs(long totalCompactingKVs) {
306         this.totalCompactingKVs = totalCompactingKVs;
307       }
308 
309       /**
310        * @param totalStaticBloomSizeKB The total size of all Bloom filter blocks,
311        *                               not just loaded into the block cache, in KB.
312        */
313       public void setTotalStaticBloomSizeKB(int totalStaticBloomSizeKB) {
314         this.totalStaticBloomSizeKB = totalStaticBloomSizeKB;
315       }
316 
317       /**
318        * @param totalStaticIndexSizeKB The total size of all index blocks,
319        *                               not just the root level, in KB.
320        */
321       public void setTotalStaticIndexSizeKB(int totalStaticIndexSizeKB) {
322         this.totalStaticIndexSizeKB = totalStaticIndexSizeKB;
323       }
324 
325       /**
326        * @param name the region name
327        */
328       public void setName(byte[] name) {
329         this.name = name;
330       }
331 
332       /**
333        * @param stores the number of stores
334        */
335       public void setStores(int stores) {
336         this.stores = stores;
337       }
338 
339       /**
340        * @param storefiles the number of store files
341        */
342       public void setStorefiles(int storefiles) {
343         this.storefiles = storefiles;
344       }
345 
346       /**
347        * @param storefileSizeMB total size of store files, in MB
348        */
349       public void setStorefileSizeMB(int storefileSizeMB) {
350         this.storefileSizeMB = storefileSizeMB;
351       }
352 
353       /**
354        * @param memstoreSizeMB memstore size, in MB
355        */
356       public void setMemstoreSizeMB(int memstoreSizeMB) {
357         this.memstoreSizeMB = memstoreSizeMB;
358       }
359 
360       /**
361        * @param storefileIndexSizeMB total size of store file indexes, in MB
362        */
363       public void setStorefileIndexSizeMB(int storefileIndexSizeMB) {
364         this.storefileIndexSizeMB = storefileIndexSizeMB;
365       }
366     }
367 
368     private String name;
369     private long startCode;
370     private int requests;
371     private int heapSizeMB;
372     private int maxHeapSizeMB;
373     private List<Region> regions = new ArrayList<Region>();
374 
375     /**
376      * Add a region name to the list
377      * @param name the region name
378      */
379     public void addRegion(byte[] name, int stores, int storefiles,
380         int storefileSizeMB, int memstoreSizeMB, int storefileIndexSizeMB,
381         long readRequestsCount, long writeRequestsCount, int rootIndexSizeKB,
382         int totalStaticIndexSizeKB, int totalStaticBloomSizeKB,
383         long totalCompactingKVs, long currentCompactedKVs) { 
384       regions.add(new Region(name, stores, storefiles, storefileSizeMB,
385         memstoreSizeMB, storefileIndexSizeMB, readRequestsCount,
386         writeRequestsCount, rootIndexSizeKB, totalStaticIndexSizeKB,
387         totalStaticBloomSizeKB, totalCompactingKVs, currentCompactedKVs));
388     }
389 
390     /**
391      * @param index the index
392      * @return the region name
393      */
394     public Region getRegion(int index) {
395       return regions.get(index);
396     }
397 
398     /**
399      * Default constructor
400      */
401     public Node() {}
402 
403     /**
404      * Constructor
405      * @param name the region server name
406      * @param startCode the region server's start code
407      */
408     public Node(String name, long startCode) {
409       this.name = name;
410       this.startCode = startCode;
411     }
412 
413     /**
414      * @return the region server's name
415      */
416     @XmlAttribute
417     public String getName() {
418       return name;
419     }
420 
421     /**
422      * @return the region server's start code
423      */
424     @XmlAttribute
425     public long getStartCode() {
426       return startCode;
427     }
428 
429     /**
430      * @return the current heap size, in MB
431      */
432     @XmlAttribute
433     public int getHeapSizeMB() {
434       return heapSizeMB;
435     }
436 
437     /**
438      * @return the maximum heap size, in MB
439      */
440     @XmlAttribute
441     public int getMaxHeapSizeMB() {
442       return maxHeapSizeMB;
443     }
444 
445     /**
446      * @return the list of regions served by the region server
447      */
448     @XmlElement(name="Region")
449     public List<Region> getRegions() {
450       return regions;
451     }
452 
453     /**
454      * @return the number of requests per second processed by the region server
455      */
456     @XmlAttribute
457     public int getRequests() {
458       return requests;
459     }
460 
461     /**
462      * @param name the region server's hostname
463      */
464     public void setName(String name) {
465       this.name = name;
466     }
467 
468     /**
469      * @param startCode the region server's start code
470      */
471     public void setStartCode(long startCode) {
472       this.startCode = startCode;
473     }
474 
475     /**
476      * @param heapSizeMB the current heap size, in MB
477      */
478     public void setHeapSizeMB(int heapSizeMB) {
479       this.heapSizeMB = heapSizeMB;
480     }
481 
482     /**
483      * @param maxHeapSizeMB the maximum heap size, in MB
484      */
485     public void setMaxHeapSizeMB(int maxHeapSizeMB) {
486       this.maxHeapSizeMB = maxHeapSizeMB;
487     }
488 
489     /**
490      * @param regions a list of regions served by the region server
491      */
492     public void setRegions(List<Region> regions) {
493       this.regions = regions;
494     }
495 
496     /**
497      * @param requests the number of requests per second processed by the
498      * region server
499      */
500     public void setRequests(int requests) {
501       this.requests = requests;
502     }
503   }
504 
505   private List<Node> liveNodes = new ArrayList<Node>();
506   private List<String> deadNodes = new ArrayList<String>();
507   private int regions;
508   private int requests;
509   private double averageLoad;
510 
511   /**
512    * Add a live node to the cluster representation.
513    * @param name the region server name
514    * @param startCode the region server's start code
515    * @param heapSizeMB the current heap size, in MB
516    * @param maxHeapSizeMB the maximum heap size, in MB
517    */
518   public Node addLiveNode(String name, long startCode, int heapSizeMB, int maxHeapSizeMB) {
519     Node node = new Node(name, startCode);
520     node.setHeapSizeMB(heapSizeMB);
521     node.setMaxHeapSizeMB(maxHeapSizeMB);
522     liveNodes.add(node);
523     return node;
524   }
525 
526   /**
527    * @param index the index
528    * @return the region server model
529    */
530   public Node getLiveNode(int index) {
531     return liveNodes.get(index);
532   }
533 
534   /**
535    * Add a dead node to the cluster representation.
536    * @param node the dead region server's name
537    */
538   public void addDeadNode(String node) {
539     deadNodes.add(node);
540   }
541 
542   /**
543    * @param index the index
544    * @return the dead region server's name
545    */
546   public String getDeadNode(int index) {
547     return deadNodes.get(index);
548   }
549 
550   /**
551    * Default constructor
552    */
553   public StorageClusterStatusModel() {
554   }
555 
556   /**
557    * @return the list of live nodes
558    */
559   @XmlElement(name = "Node")
560   @XmlElementWrapper(name = "LiveNodes")
561   public List<Node> getLiveNodes() {
562     return liveNodes;
563   }
564 
565   /**
566    * @return the list of dead nodes
567    */
568   @XmlElement(name = "Node")
569   @XmlElementWrapper(name = "DeadNodes")
570   public List<String> getDeadNodes() {
571     return deadNodes;
572   }
573 
574   /**
575    * @return the total number of regions served by the cluster
576    */
577   @XmlAttribute
578   public int getRegions() {
579     return regions;
580   }
581 
582   /**
583    * @return the total number of requests per second handled by the cluster in
584    * the last reporting interval
585    */
586   @XmlAttribute
587   public int getRequests() {
588     return requests;
589   }
590 
591   /**
592    * @return the average load of the region servers in the cluster
593    */
594   @XmlAttribute
595   public double getAverageLoad() {
596     return averageLoad;
597   }
598 
599   /**
600    * @param nodes the list of live node models
601    */
602   public void setLiveNodes(List<Node> nodes) {
603     this.liveNodes = nodes;
604   }
605 
606   /**
607    * @param nodes the list of dead node names
608    */
609   public void setDeadNodes(List<String> nodes) {
610     this.deadNodes = nodes;
611   }
612 
613   /**
614    * @param regions the total number of regions served by the cluster
615    */
616   public void setRegions(int regions) {
617     this.regions = regions;
618   }
619 
620   /**
621    * @param requests the total number of requests per second handled by the
622    * cluster
623    */
624   public void setRequests(int requests) {
625     this.requests = requests;
626   }
627 
628   /**
629    * @param averageLoad the average load of region servers in the cluster
630    */
631   public void setAverageLoad(double averageLoad) {
632     this.averageLoad = averageLoad;
633   }
634 
635   /*
636    * (non-Javadoc)
637    * @see java.lang.Object#toString()
638    */
639   @Override
640   public String toString() {
641     StringBuilder sb = new StringBuilder();
642     sb.append(String.format("%d live servers, %d dead servers, " + 
643       "%.4f average load%n%n", liveNodes.size(), deadNodes.size(),
644       averageLoad));
645     if (!liveNodes.isEmpty()) {
646       sb.append(liveNodes.size());
647       sb.append(" live servers\n");
648       for (Node node: liveNodes) {
649         sb.append("    ");
650         sb.append(node.name);
651         sb.append(' ');
652         sb.append(node.startCode);
653         sb.append("\n        requests=");
654         sb.append(node.requests);
655         sb.append(", regions=");
656         sb.append(node.regions.size());
657         sb.append("\n        heapSizeMB=");
658         sb.append(node.heapSizeMB);
659         sb.append("\n        maxHeapSizeMB=");
660         sb.append(node.maxHeapSizeMB);
661         sb.append("\n\n");
662         for (Node.Region region: node.regions) {
663           sb.append("        ");
664           sb.append(Bytes.toString(region.name));
665           sb.append("\n            stores=");
666           sb.append(region.stores);
667           sb.append("\n            storefiless=");
668           sb.append(region.storefiles);
669           sb.append("\n            storefileSizeMB=");
670           sb.append(region.storefileSizeMB);
671           sb.append("\n            memstoreSizeMB=");
672           sb.append(region.memstoreSizeMB);
673           sb.append("\n            storefileIndexSizeMB=");
674           sb.append(region.storefileIndexSizeMB);
675           sb.append("\n            readRequestsCount=");
676           sb.append(region.readRequestsCount);
677           sb.append("\n            writeRequestsCount=");
678           sb.append(region.writeRequestsCount);
679           sb.append("\n            rootIndexSizeKB=");
680           sb.append(region.rootIndexSizeKB);
681           sb.append("\n            totalStaticIndexSizeKB=");
682           sb.append(region.totalStaticIndexSizeKB);
683           sb.append("\n            totalStaticBloomSizeKB=");
684           sb.append(region.totalStaticBloomSizeKB);
685           sb.append("\n            totalCompactingKVs=");
686           sb.append(region.totalCompactingKVs);
687           sb.append("\n            currentCompactedKVs=");
688           sb.append(region.currentCompactedKVs);
689           sb.append('\n');
690         }
691         sb.append('\n');
692       }
693     }
694     if (!deadNodes.isEmpty()) {
695       sb.append('\n');
696       sb.append(deadNodes.size());
697       sb.append(" dead servers\n");
698       for (String node: deadNodes) {
699         sb.append("    ");
700         sb.append(node);
701         sb.append('\n');
702       }
703     }
704     return sb.toString();
705   }
706 
707   @Override
708   public byte[] createProtobufOutput() {
709     StorageClusterStatus.Builder builder = StorageClusterStatus.newBuilder();
710     builder.setRegions(regions);
711     builder.setRequests(requests);
712     builder.setAverageLoad(averageLoad);
713     for (Node node: liveNodes) {
714       StorageClusterStatus.Node.Builder nodeBuilder = 
715         StorageClusterStatus.Node.newBuilder();
716       nodeBuilder.setName(node.name);
717       nodeBuilder.setStartCode(node.startCode);
718       nodeBuilder.setRequests(node.requests);
719       nodeBuilder.setHeapSizeMB(node.heapSizeMB);
720       nodeBuilder.setMaxHeapSizeMB(node.maxHeapSizeMB);
721       for (Node.Region region: node.regions) {
722         StorageClusterStatus.Region.Builder regionBuilder =
723           StorageClusterStatus.Region.newBuilder();
724         regionBuilder.setName(HBaseZeroCopyByteString.wrap(region.name));
725         regionBuilder.setStores(region.stores);
726         regionBuilder.setStorefiles(region.storefiles);
727         regionBuilder.setStorefileSizeMB(region.storefileSizeMB);
728         regionBuilder.setMemstoreSizeMB(region.memstoreSizeMB);
729         regionBuilder.setStorefileIndexSizeMB(region.storefileIndexSizeMB);
730         regionBuilder.setReadRequestsCount(region.readRequestsCount);
731         regionBuilder.setWriteRequestsCount(region.writeRequestsCount);
732         regionBuilder.setRootIndexSizeKB(region.rootIndexSizeKB);
733         regionBuilder.setTotalStaticIndexSizeKB(region.totalStaticIndexSizeKB);
734         regionBuilder.setTotalStaticBloomSizeKB(region.totalStaticBloomSizeKB);
735         regionBuilder.setTotalCompactingKVs(region.totalCompactingKVs);
736         regionBuilder.setCurrentCompactedKVs(region.currentCompactedKVs);
737         nodeBuilder.addRegions(regionBuilder);
738       }
739       builder.addLiveNodes(nodeBuilder);
740     }
741     for (String node: deadNodes) {
742       builder.addDeadNodes(node);
743     }
744     return builder.build().toByteArray();
745   }
746 
747   @Override
748   public ProtobufMessageHandler getObjectFromMessage(byte[] message)
749       throws IOException {
750     StorageClusterStatus.Builder builder = StorageClusterStatus.newBuilder();
751     builder.mergeFrom(message);
752     if (builder.hasRegions()) {
753       regions = builder.getRegions();
754     }
755     if (builder.hasRequests()) {
756       requests = builder.getRequests();
757     }
758     if (builder.hasAverageLoad()) {
759       averageLoad = builder.getAverageLoad();
760     }
761     for (StorageClusterStatus.Node node: builder.getLiveNodesList()) {
762       long startCode = node.hasStartCode() ? node.getStartCode() : -1;
763       StorageClusterStatusModel.Node nodeModel = 
764         addLiveNode(node.getName(), startCode, node.getHeapSizeMB(),
765           node.getMaxHeapSizeMB());
766       int requests = node.hasRequests() ? node.getRequests() : 0;
767       nodeModel.setRequests(requests);
768       for (StorageClusterStatus.Region region: node.getRegionsList()) {
769         nodeModel.addRegion(
770           region.getName().toByteArray(),
771           region.getStores(),
772           region.getStorefiles(),
773           region.getStorefileSizeMB(),
774           region.getMemstoreSizeMB(),
775           region.getStorefileIndexSizeMB(),
776           region.getReadRequestsCount(),
777           region.getWriteRequestsCount(),
778           region.getRootIndexSizeKB(),
779           region.getTotalStaticIndexSizeKB(),
780           region.getTotalStaticBloomSizeKB(),
781           region.getTotalCompactingKVs(),
782           region.getCurrentCompactedKVs());
783       }
784     }
785     for (String node: builder.getDeadNodesList()) {
786       addDeadNode(node);
787     }
788     return this;
789   }
790 }