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}