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