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