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