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