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