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