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,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.hadoop.hbase.client;
020
021import java.io.IOException;
022import java.util.Date;
023import java.util.List;
024
025import org.apache.yetus.audience.InterfaceAudience;
026
027/**
028 * Exception thrown by HTable methods when an attempt to do something (like
029 * commit changes) fails after a bunch of retries.
030 */
031@InterfaceAudience.Public
032public class RetriesExhaustedException extends IOException {
033  private static final long serialVersionUID = 1876775844L;
034
035  public RetriesExhaustedException(final String msg) {
036    super(msg);
037  }
038
039  public RetriesExhaustedException(final String msg, final IOException e) {
040    super(msg, e);
041  }
042
043  /**
044   * Datastructure that allows adding more info around Throwable incident.
045   */
046  @InterfaceAudience.Private
047  public static class ThrowableWithExtraContext {
048    private final Throwable t;
049    private final long when;
050    private final String extras;
051
052    public ThrowableWithExtraContext(final Throwable t, final long when,
053        final String extras) {
054      this.t = t;
055      this.when = when;
056      this.extras = extras;
057    }
058
059    @Override
060    public String toString() {
061      return new Date(this.when).toString() + ", " + extras + ", " + t.toString();
062    }
063  }
064
065  /**
066   * Create a new RetriesExhaustedException from the list of prior failures.
067   * @param callableVitals Details from the Callable we were using
068   * when we got this exception.
069   * @param numTries The number of tries we made
070   * @param exceptions List of exceptions that failed before giving up
071   */
072  public RetriesExhaustedException(final String callableVitals, int numTries,
073      List<Throwable> exceptions) {
074    super(getMessage(callableVitals, numTries, exceptions));
075  }
076
077  /**
078   * Create a new RetriesExhaustedException from the list of prior failures.
079   * @param numRetries How many times we have retried, one less than total attempts
080   * @param exceptions List of exceptions that failed before giving up
081   */
082  @InterfaceAudience.Private
083  public RetriesExhaustedException(final int numRetries,
084                                   final List<ThrowableWithExtraContext> exceptions) {
085    super(getMessage(numRetries, exceptions),
086      exceptions.isEmpty()? null: exceptions.get(exceptions.size() - 1).t);
087  }
088
089  private static String getMessage(String callableVitals, int numTries,
090      List<Throwable> exceptions) {
091    StringBuilder buffer = new StringBuilder("Failed contacting ");
092    buffer.append(callableVitals);
093    buffer.append(" after ");
094    buffer.append(numTries);
095    buffer.append(" attempts.\nExceptions:\n");
096    for (Throwable t : exceptions) {
097      buffer.append(t.toString());
098      buffer.append("\n");
099    }
100    return buffer.toString();
101  }
102
103  private static String getMessage(final int numRetries,
104      final List<ThrowableWithExtraContext> exceptions) {
105    StringBuilder buffer = new StringBuilder("Failed after attempts=");
106    buffer.append(numRetries + 1);
107    buffer.append(", exceptions:\n");
108    for (ThrowableWithExtraContext t : exceptions) {
109      buffer.append(t.toString());
110      buffer.append("\n");
111    }
112    return buffer.toString();
113  }
114}