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.client;
019
020import java.io.IOException;
021
022import org.apache.yetus.audience.InterfaceAudience;
023
024/**
025 * This class is designed to fit into the RetryingCaller class which forms the
026 * central piece of intelligence for the client side retries for most calls.
027 * 
028 * One can extend this class and intercept the RetryingCaller and add additional
029 * logic into the execution of a simple HTable operations like get, delete etc.
030 * 
031 * Concrete implementations of this calls are supposed to the thread safe. The
032 * object is used across threads to identify the fast failing threads.
033 * 
034 * For a concrete use case see {@link PreemptiveFastFailInterceptor}
035 * 
036 * Example use case : 
037 * try {
038 *   interceptor.intercept
039 *   doAction()
040 * } catch (Exception e) {
041 *   interceptor.handleFailure
042 * } finally {
043 *   interceptor.updateFaulireInfo
044 * }
045 * 
046 * The {@link RetryingCallerInterceptor} also acts as a factory
047 * for getting a new {@link RetryingCallerInterceptorContext}.
048 * 
049 */
050
051@InterfaceAudience.Private
052abstract class RetryingCallerInterceptor {
053
054  protected RetryingCallerInterceptor() {
055    // Empty constructor protected for NoOpRetryableCallerInterceptor
056  }
057
058  /**
059   * This returns the context object for the current call.
060   * 
061   * @return context : the context that needs to be used during this call.
062   */
063  public abstract RetryingCallerInterceptorContext createEmptyContext();
064
065  /**
066   * Call this function in case we caught a failure during retries.
067   * 
068   * @param context
069   *          : The context object that we obtained previously.
070   * @param t
071   *          : The exception that we caught in this particular try
072   * @throws IOException
073   */
074  public abstract void handleFailure(RetryingCallerInterceptorContext context,
075      Throwable t) throws IOException;
076
077  /**
078   * Call this function alongside the actual call done on the callable.
079   * 
080   * @param abstractRetryingCallerInterceptorContext
081   * @throws PreemptiveFastFailException
082   */
083  public abstract void intercept(
084      RetryingCallerInterceptorContext abstractRetryingCallerInterceptorContext)
085      throws IOException;
086
087  /**
088   * Call this function to update at the end of the retry. This is not necessary
089   * to happen.
090   * 
091   * @param context
092   */
093  public abstract void updateFailureInfo(
094      RetryingCallerInterceptorContext context);
095
096  @Override
097  public abstract String toString();
098}