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