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