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