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