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 List<ServerName> getUnknownServerNames() {
118    return metrics.getUnknownServerNames();
119  }
120
121  @Override
122  public Map<ServerName, ServerMetrics> getLiveServerMetrics() {
123    return metrics.getLiveServerMetrics();
124  }
125
126  /**
127   * @return the number of region servers in the cluster
128   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
129   *             {@link #getLiveServerMetrics()}.
130   */
131  @Deprecated
132  public int getServersSize() {
133    return metrics.getLiveServerMetrics().size();
134  }
135
136  /**
137   * @return the number of dead region servers in the cluster
138   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
139   *             (<a href="https://issues.apache.org/jira/browse/HBASE-13656">HBASE-13656</a>). Use
140   *             {@link #getDeadServerNames()}.
141   */
142  @Deprecated
143  public int getDeadServers() {
144    return getDeadServersSize();
145  }
146
147  /**
148   * @return the number of dead region servers in the cluster
149   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
150   *             {@link #getDeadServerNames()}.
151   */
152  @Deprecated
153  public int getDeadServersSize() {
154    return metrics.getDeadServerNames().size();
155  }
156
157  /**
158   * @return the number of regions deployed on the cluster
159   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
160   *             {@link #getRegionCount()}.
161   */
162  @Deprecated
163  public int getRegionsCount() {
164    return getRegionCount();
165  }
166
167  /**
168   * @return the number of requests since last report
169   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
170   *             {@link #getRequestCount()} instead.
171   */
172  @Deprecated
173  public int getRequestsCount() {
174    return (int) getRequestCount();
175  }
176
177  @Nullable
178  @Override
179  public ServerName getMasterName() {
180    return metrics.getMasterName();
181  }
182
183  @Override
184  public List<ServerName> getBackupMasterNames() {
185    return metrics.getBackupMasterNames();
186  }
187
188  @Override
189  public List<RegionState> getRegionStatesInTransition() {
190    return metrics.getRegionStatesInTransition();
191  }
192
193  /** Returns the HBase version string as reported by the HMaster */
194  @Override
195  public String getHBaseVersion() {
196    return metrics.getHBaseVersion();
197  }
198
199  private Map<ServerName, ServerLoad> getLiveServerLoads() {
200    return metrics.getLiveServerMetrics().entrySet().stream()
201      .collect(Collectors.toMap(e -> e.getKey(), e -> new ServerLoad(e.getValue())));
202  }
203
204  @Override
205  public boolean equals(Object o) {
206    if (this == o) {
207      return true;
208    }
209    if (!(o instanceof ClusterStatus)) {
210      return false;
211    }
212    ClusterStatus other = (ClusterStatus) o;
213    return Objects.equal(getHBaseVersion(), other.getHBaseVersion())
214      && Objects.equal(getLiveServerLoads(), other.getLiveServerLoads())
215      && getDeadServerNames().containsAll(other.getDeadServerNames())
216      && Arrays.equals(getMasterCoprocessors(), other.getMasterCoprocessors())
217      && Objects.equal(getMaster(), other.getMaster())
218      && getBackupMasters().containsAll(other.getBackupMasters())
219      && Objects.equal(getClusterId(), other.getClusterId())
220      && getMasterInfoPort() == other.getMasterInfoPort();
221  }
222
223  @Override
224  public int hashCode() {
225    return metrics.hashCode();
226  }
227
228  /**
229   * @return the object version number
230   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0
231   */
232  @Deprecated
233  public byte getVersion() {
234    return VERSION;
235  }
236
237  /**
238   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
239   *             {@link #getLiveServerMetrics()} instead.
240   */
241  @Deprecated
242  public Collection<ServerName> getServers() {
243    return metrics.getLiveServerMetrics().keySet();
244  }
245
246  /**
247   * Returns detailed information about the current master {@link ServerName}.
248   * @return current master information if it exists
249   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use {@link #getMasterName}
250   *             instead.
251   */
252  @Deprecated
253  public ServerName getMaster() {
254    return metrics.getMasterName();
255  }
256
257  /**
258   * @return the number of backup masters in the cluster
259   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
260   *             {@link #getBackupMasterNames} instead.
261   */
262  @Deprecated
263  public int getBackupMastersSize() {
264    return metrics.getBackupMasterNames().size();
265  }
266
267  /**
268   * @return the names of backup masters
269   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
270   *             {@link #getBackupMasterNames} instead.
271   */
272  @Deprecated
273  public List<ServerName> getBackupMasters() {
274    return metrics.getBackupMasterNames();
275  }
276
277  /**
278   * n * @return Server's load or null if not found.
279   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
280   *             {@link #getLiveServerMetrics} instead.
281   */
282  @Deprecated
283  public ServerLoad getLoad(final ServerName sn) {
284    ServerMetrics serverMetrics = metrics.getLiveServerMetrics().get(sn);
285    return serverMetrics == null ? null : new ServerLoad(serverMetrics);
286  }
287
288  @Override
289  public String getClusterId() {
290    return metrics.getClusterId();
291  }
292
293  @Override
294  public List<String> getMasterCoprocessorNames() {
295    return metrics.getMasterCoprocessorNames();
296  }
297
298  /**
299   * Get the list of master coprocessor names.
300   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
301   *             {@link #getMasterCoprocessorNames} instead.
302   */
303  @Deprecated
304  public String[] getMasterCoprocessors() {
305    List<String> rval = metrics.getMasterCoprocessorNames();
306    return rval.toArray(new String[rval.size()]);
307  }
308
309  /**
310   * Get the last major compaction time for a given table.
311   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
312   *             {@link #getLastMajorCompactionTimestamp(TableName)} instead.
313   */
314  @Deprecated
315  public long getLastMajorCompactionTsForTable(TableName table) {
316    return metrics.getLastMajorCompactionTimestamp(table);
317  }
318
319  /**
320   * Get the last major compaction time for a given region.
321   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 Use
322   *             {@link #getLastMajorCompactionTimestamp(byte[])} instead.
323   */
324  @Deprecated
325  public long getLastMajorCompactionTsForRegion(final byte[] region) {
326    return metrics.getLastMajorCompactionTimestamp(region);
327  }
328
329  /**
330   * Returns true if the balancer is enabled.
331   * @deprecated As of release 2.0.0, this will be removed in HBase 3.0.0 No flag in 2.0
332   */
333  @Deprecated
334  public boolean isBalancerOn() {
335    return metrics.getBalancerOn() != null && metrics.getBalancerOn();
336  }
337
338  @Override
339  public Boolean getBalancerOn() {
340    return metrics.getBalancerOn();
341  }
342
343  @Override
344  public int getMasterInfoPort() {
345    return metrics.getMasterInfoPort();
346  }
347
348  @Override
349  public List<ServerName> getServersName() {
350    return metrics.getServersName();
351  }
352
353  @Override
354  public Map<TableName, RegionStatesCount> getTableRegionStatesCount() {
355    return metrics.getTableRegionStatesCount();
356  }
357
358  @Override
359  public List<ServerTask> getMasterTasks() {
360    return metrics.getMasterTasks();
361  }
362
363  @Override
364  public String toString() {
365    StringBuilder sb = new StringBuilder(1024);
366    sb.append("Master: " + metrics.getMasterName());
367
368    int backupMastersSize = getBackupMastersSize();
369    sb.append("\nNumber of backup masters: " + backupMastersSize);
370    if (backupMastersSize > 0) {
371      for (ServerName serverName : metrics.getBackupMasterNames()) {
372        sb.append("\n  " + serverName);
373      }
374    }
375
376    int serversSize = getServersSize();
377    int serversNameSize = getServersName().size();
378    sb.append(
379      "\nNumber of live region servers: " + (serversSize > 0 ? serversSize : serversNameSize));
380    if (serversSize > 0) {
381      for (ServerName serverName : metrics.getLiveServerMetrics().keySet()) {
382        sb.append("\n  " + serverName.getServerName());
383      }
384    } else if (serversNameSize > 0) {
385      for (ServerName serverName : getServersName()) {
386        sb.append("\n  " + serverName.getServerName());
387      }
388    }
389
390    int deadServerSize = metrics.getDeadServerNames().size();
391    sb.append("\nNumber of dead region servers: " + deadServerSize);
392    if (deadServerSize > 0) {
393      for (ServerName serverName : metrics.getDeadServerNames()) {
394        sb.append("\n  " + serverName);
395      }
396    }
397
398    sb.append("\nAverage load: " + getAverageLoad());
399    sb.append("\nNumber of requests: " + getRequestCount());
400    sb.append("\nNumber of regions: " + getRegionsCount());
401
402    int ritSize = metrics.getRegionStatesInTransition().size();
403    sb.append("\nNumber of regions in transition: " + ritSize);
404    if (ritSize > 0) {
405      for (RegionState state : metrics.getRegionStatesInTransition()) {
406        sb.append("\n  " + state.toDescriptiveString());
407      }
408    }
409    return sb.toString();
410  }
411}