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;
021
022import edu.umd.cs.findbugs.annotations.Nullable;
023import java.util.ArrayList;
024import java.util.Arrays;
025import java.util.Collection;
026import java.util.List;
027import java.util.Map;
028import java.util.stream.Collectors;
029
030import org.apache.hadoop.hbase.client.RegionStatesCount;
031import org.apache.hadoop.hbase.master.RegionState;
032import org.apache.yetus.audience.InterfaceAudience;
033
034import org.apache.hbase.thirdparty.com.google.common.base.Objects;
035
036/**
037 * Status information on the HBase cluster.
038 * <p>
039 * <tt>ClusterStatus</tt> provides clients with information such as:
040 * <ul>
041 * <li>The count and names of region servers in the cluster.</li>
042 * <li>The count and names of dead region servers in the cluster.</li>
043 * <li>The name of the active master for the cluster.</li>
044 * <li>The name(s) of the backup master(s) for the cluster, if they exist.</li>
045 * <li>The average cluster load.</li>
046 * <li>The number of regions deployed on the cluster.</li>
047 * <li>The number of requests since last report.</li>
048 * <li>Detailed region server loading and resource usage information,
049 *  per server and per region.</li>
050 * <li>Regions in transition at master</li>
051 * <li>The unique cluster ID</li>
052 * </ul>
053 * <tt>{@link ClusterMetrics.Option}</tt> provides a way to get desired ClusterStatus information.
054 * The following codes will get all the cluster information.
055 * <pre>
056 * {@code
057 * // Original version still works
058 * Admin admin = connection.getAdmin();
059 * ClusterStatus status = admin.getClusterStatus();
060 * // or below, a new version which has the same effects
061 * ClusterStatus status = admin.getClusterStatus(EnumSet.allOf(Option.class));
062 * }
063 * </pre>
064 * If information about live servers is the only wanted.
065 * then codes in the following way:
066 * <pre>
067 * {@code
068 * Admin admin = connection.getAdmin();
069 * ClusterStatus status = admin.getClusterStatus(EnumSet.of(Option.LIVE_SERVERS));
070 * }
071 * </pre>
072 * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
073 *             Use {@link ClusterMetrics} instead.
074 */
075@InterfaceAudience.Public
076@Deprecated
077public class ClusterStatus implements ClusterMetrics {
078
079  // TODO: remove this in 3.0
080  private static final byte VERSION = 2;
081
082  private final ClusterMetrics metrics;
083
084  /**
085   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
086   */
087  @Deprecated
088  public ClusterStatus(final String hbaseVersion, final String clusterid,
089      final Map<ServerName, ServerLoad> servers,
090      final Collection<ServerName> deadServers,
091      final ServerName master,
092      final Collection<ServerName> backupMasters,
093      final List<RegionState> rit,
094      final String[] masterCoprocessors,
095      final Boolean balancerOn,
096      final int masterInfoPort) {
097    // TODO: make this constructor private
098    this(ClusterMetricsBuilder.newBuilder().setHBaseVersion(hbaseVersion)
099      .setDeadServerNames(new ArrayList<>(deadServers))
100      .setLiveServerMetrics(servers.entrySet().stream()
101      .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())))
102      .setBackerMasterNames(new ArrayList<>(backupMasters)).setBalancerOn(balancerOn)
103      .setClusterId(clusterid)
104      .setMasterCoprocessorNames(Arrays.asList(masterCoprocessors))
105      .setMasterName(master)
106      .setMasterInfoPort(masterInfoPort)
107      .setRegionsInTransition(rit)
108      .build());
109  }
110
111  @InterfaceAudience.Private
112  public ClusterStatus(ClusterMetrics metrics) {
113    this.metrics = metrics;
114  }
115
116  /**
117   * @return the names of region servers on the dead list
118   */
119  @Override
120  public List<ServerName> getDeadServerNames() {
121    return metrics.getDeadServerNames();
122  }
123
124  @Override
125  public Map<ServerName, ServerMetrics> getLiveServerMetrics() {
126    return metrics.getLiveServerMetrics();
127  }
128
129  /**
130  * @return the number of region servers in the cluster
131  * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
132  *             Use {@link #getLiveServerMetrics()}.
133  */
134  @Deprecated
135  public int getServersSize() {
136    return metrics.getLiveServerMetrics().size();
137  }
138
139  /**
140   * @return the number of dead region servers in the cluster
141   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
142   *             (<a href="https://issues.apache.org/jira/browse/HBASE-13656">HBASE-13656</a>).
143   *             Use {@link #getDeadServerNames()}.
144   */
145  @Deprecated
146  public int getDeadServers() {
147    return getDeadServersSize();
148  }
149
150  /**
151   * @return the number of dead region servers in the cluster
152   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
153   *             Use {@link #getDeadServerNames()}.
154   */
155  @Deprecated
156  public int getDeadServersSize() {
157    return metrics.getDeadServerNames().size();
158  }
159
160  /**
161   * @return the number of regions deployed on the cluster
162   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
163   *             Use {@link #getRegionCount()}.
164   */
165  @Deprecated
166  public int getRegionsCount() {
167    return getRegionCount();
168  }
169
170  /**
171   * @return the number of requests since last report
172   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
173   *             Use {@link #getRequestCount()} instead.
174   */
175  @Deprecated
176  public int getRequestsCount() {
177    return (int) getRequestCount();
178  }
179
180  @Nullable
181  @Override
182  public ServerName getMasterName() {
183    return metrics.getMasterName();
184  }
185
186  @Override
187  public List<ServerName> getBackupMasterNames() {
188    return metrics.getBackupMasterNames();
189  }
190
191  @Override
192  public List<RegionState> getRegionStatesInTransition() {
193    return metrics.getRegionStatesInTransition();
194  }
195
196  /**
197   * @return the HBase version string as reported by the HMaster
198   */
199  public String getHBaseVersion() {
200    return metrics.getHBaseVersion();
201  }
202
203  private Map<ServerName, ServerLoad> getLiveServerLoads() {
204    return metrics.getLiveServerMetrics().entrySet().stream()
205      .collect(Collectors.toMap(e -> e.getKey(), e -> new ServerLoad(e.getValue())));
206  }
207
208  @Override
209  public boolean equals(Object o) {
210    if (this == o) {
211      return true;
212    }
213    if (!(o instanceof ClusterStatus)) {
214      return false;
215    }
216    ClusterStatus other = (ClusterStatus) o;
217    return Objects.equal(getHBaseVersion(), other.getHBaseVersion()) &&
218      Objects.equal(getLiveServerLoads(), other.getLiveServerLoads()) &&
219      getDeadServerNames().containsAll(other.getDeadServerNames()) &&
220      Arrays.equals(getMasterCoprocessors(), other.getMasterCoprocessors()) &&
221      Objects.equal(getMaster(), other.getMaster()) &&
222      getBackupMasters().containsAll(other.getBackupMasters()) &&
223      Objects.equal(getClusterId(), other.getClusterId()) &&
224      getMasterInfoPort() == other.getMasterInfoPort();
225  }
226
227  @Override
228  public int hashCode() {
229    return metrics.hashCode();
230  }
231
232  /**
233   * @return the object version number
234   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
235   */
236  @Deprecated
237  public byte getVersion() {
238    return VERSION;
239  }
240
241  /**
242   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
243   *             Use {@link #getLiveServerMetrics()} instead.
244   */
245  @Deprecated
246  public Collection<ServerName> getServers() {
247    return metrics.getLiveServerMetrics().keySet();
248  }
249
250  /**
251   * Returns detailed information about the current master {@link ServerName}.
252   * @return current master information if it exists
253   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
254   *             Use {@link #getMasterName} instead.
255   */
256  @Deprecated
257  public ServerName getMaster() {
258    return metrics.getMasterName();
259  }
260
261  /**
262   * @return the number of backup masters in the cluster
263   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
264   *             Use {@link #getBackupMasterNames} instead.
265   */
266  @Deprecated
267  public int getBackupMastersSize() {
268    return metrics.getBackupMasterNames().size();
269  }
270
271  /**
272   * @return the names of backup masters
273   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
274   *             Use {@link #getBackupMasterNames} instead.
275   */
276  @Deprecated
277  public List<ServerName> getBackupMasters() {
278    return metrics.getBackupMasterNames();
279  }
280
281  /**
282   * @param sn
283   * @return Server's load or null if not found.
284   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
285   *             Use {@link #getLiveServerMetrics} instead.
286   */
287  @Deprecated
288  public ServerLoad getLoad(final ServerName sn) {
289    ServerMetrics serverMetrics = metrics.getLiveServerMetrics().get(sn);
290    return serverMetrics == null ? null : new ServerLoad(serverMetrics);
291  }
292
293  public String getClusterId() {
294    return metrics.getClusterId();
295  }
296
297  @Override
298  public List<String> getMasterCoprocessorNames() {
299    return metrics.getMasterCoprocessorNames();
300  }
301
302  /**
303   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
304   *             Use {@link #getMasterCoprocessorNames} instead.
305   */
306  @Deprecated
307  public String[] getMasterCoprocessors() {
308    List<String> rval = metrics.getMasterCoprocessorNames();
309    return rval.toArray(new String[rval.size()]);
310  }
311
312  /**
313   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
314   *             Use {@link #getLastMajorCompactionTimestamp(TableName)} instead.
315   */
316  @Deprecated
317  public long getLastMajorCompactionTsForTable(TableName table) {
318    return metrics.getLastMajorCompactionTimestamp(table);
319  }
320
321  /**
322   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
323   *             Use {@link #getLastMajorCompactionTimestamp(byte[])} instead.
324   */
325  @Deprecated
326  public long getLastMajorCompactionTsForRegion(final byte[] region) {
327    return metrics.getLastMajorCompactionTimestamp(region);
328  }
329
330  /**
331   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
332   *             No flag in 2.0
333   */
334  @Deprecated
335  public boolean isBalancerOn() {
336    return metrics.getBalancerOn() != null && metrics.getBalancerOn();
337  }
338
339  @Override
340  public Boolean getBalancerOn() {
341    return metrics.getBalancerOn();
342  }
343
344  @Override
345  public int getMasterInfoPort() {
346    return metrics.getMasterInfoPort();
347  }
348
349  @Override
350  public List<ServerName> getServersName() {
351    return metrics.getServersName();
352  }
353
354  @Override
355  public Map<TableName, RegionStatesCount> getTableRegionStatesCount() {
356    return metrics.getTableRegionStatesCount();
357  }
358
359  @Override
360  public String toString() {
361    StringBuilder sb = new StringBuilder(1024);
362    sb.append("Master: " + metrics.getMasterName());
363
364    int backupMastersSize = getBackupMastersSize();
365    sb.append("\nNumber of backup masters: " + backupMastersSize);
366    if (backupMastersSize > 0) {
367      for (ServerName serverName: metrics.getBackupMasterNames()) {
368        sb.append("\n  " + serverName);
369      }
370    }
371
372    int serversSize = getServersSize();
373    int serversNameSize = getServersName().size();
374    sb.append("\nNumber of live region servers: "
375        + (serversSize > 0 ? serversSize : serversNameSize));
376    if (serversSize > 0) {
377      for (ServerName serverName : metrics.getLiveServerMetrics().keySet()) {
378        sb.append("\n  " + serverName.getServerName());
379      }
380    } else if (serversNameSize > 0) {
381      for (ServerName serverName : getServersName()) {
382        sb.append("\n  " + serverName.getServerName());
383      }
384    }
385
386    int deadServerSize = metrics.getDeadServerNames().size();
387    sb.append("\nNumber of dead region servers: " + deadServerSize);
388    if (deadServerSize > 0) {
389      for (ServerName serverName : metrics.getDeadServerNames()) {
390        sb.append("\n  " + serverName);
391      }
392    }
393
394    sb.append("\nAverage load: " + getAverageLoad());
395    sb.append("\nNumber of requests: " + getRequestCount());
396    sb.append("\nNumber of regions: " + getRegionsCount());
397
398    int ritSize = metrics.getRegionStatesInTransition().size();
399    sb.append("\nNumber of regions in transition: " + ritSize);
400    if (ritSize > 0) {
401      for (RegionState state: metrics.getRegionStatesInTransition()) {
402        sb.append("\n  " + state.toDescriptiveString());
403      }
404    }
405    return sb.toString();
406  }
407}