View Javadoc

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