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.master.assignment;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.fail;
022
023import org.apache.hadoop.hbase.CallQueueTooBigException;
024import org.apache.hadoop.hbase.DoNotRetryIOException;
025import org.apache.hadoop.hbase.HBaseClassTestRule;
026import org.apache.hadoop.hbase.TableName;
027import org.apache.hadoop.hbase.client.RegionInfo;
028import org.apache.hadoop.hbase.client.RetriesExhaustedException;
029import org.apache.hadoop.hbase.testclassification.MasterTests;
030import org.apache.hadoop.hbase.testclassification.MediumTests;
031import org.junit.ClassRule;
032import org.junit.Test;
033import org.junit.experimental.categories.Category;
034import org.slf4j.Logger;
035import org.slf4j.LoggerFactory;
036
037@Category({ MasterTests.class, MediumTests.class })
038public class TestAMServerFailedOpen extends TestAssignmentManagerBase {
039
040  @ClassRule
041  public static final HBaseClassTestRule CLASS_RULE =
042    HBaseClassTestRule.forClass(TestAMServerFailedOpen.class);
043
044  private static final Logger LOG = LoggerFactory.getLogger(TestAMServerFailedOpen.class);
045
046  @Override
047  protected int getAssignMaxAttempts() {
048    // do not need to retry so many times as we will finally fail...
049    return 10;
050  }
051
052  @Test
053  public void testServerNotYetRunning() throws Exception {
054    testRetriesExhaustedFailure(TableName.valueOf(this.name.getMethodName()),
055      new ServerNotYetRunningRsExecutor());
056  }
057
058  private void testRetriesExhaustedFailure(final TableName tableName, final MockRSExecutor executor)
059    throws Exception {
060    RegionInfo hri = createRegionInfo(tableName, 1);
061
062    // collect AM metrics before test
063    collectAssignmentManagerMetrics();
064
065    // Test Assign operation failure
066    rsDispatcher.setMockRsExecutor(executor);
067    try {
068      waitOnFuture(submitProcedure(createAssignProcedure(hri)));
069      fail("unexpected assign completion");
070    } catch (RetriesExhaustedException e) {
071      // expected exception
072      LOG.info("expected exception from assign operation: " + e.getMessage(), e);
073    }
074
075    // Assign the region (without problems)
076    rsDispatcher.setMockRsExecutor(new GoodRsExecutor());
077    waitOnFuture(submitProcedure(createAssignProcedure(hri)));
078  }
079
080  @Test
081  public void testDoNotRetryExceptionOnAssignment() throws Exception {
082    // collect AM metrics before test
083    collectAssignmentManagerMetrics();
084
085    testFailedOpen(TableName.valueOf("testDoNotRetryExceptionOnAssignment"),
086      new FaultyRsExecutor(new DoNotRetryIOException("test do not retry fault")));
087
088    assertEquals(assignSubmittedCount + 1, assignProcMetrics.getSubmittedCounter().getCount());
089    assertEquals(assignFailedCount + 1, assignProcMetrics.getFailedCounter().getCount());
090  }
091
092  private void testFailedOpen(final TableName tableName, final MockRSExecutor executor)
093    throws Exception {
094    final RegionInfo hri = createRegionInfo(tableName, 1);
095
096    // Test Assign operation failure
097    rsDispatcher.setMockRsExecutor(executor);
098    try {
099      waitOnFuture(submitProcedure(createAssignProcedure(hri)));
100      fail("unexpected assign completion");
101    } catch (RetriesExhaustedException e) {
102      // expected exception
103      LOG.info("REGION STATE " + am.getRegionStates().getRegionStateNode(hri));
104      LOG.info("expected exception from assign operation: " + e.getMessage(), e);
105      assertEquals(true, am.getRegionStates().getRegionState(hri).isFailedOpen());
106    }
107  }
108
109  @Test
110  public void testCallQueueTooBigExceptionOnAssignment() throws Exception {
111    // collect AM metrics before test
112    collectAssignmentManagerMetrics();
113
114    testFailedOpen(TableName.valueOf("testCallQueueTooBigExceptionOnAssignment"),
115      new FaultyRsExecutor(new CallQueueTooBigException("test do not retry fault")));
116
117    assertEquals(assignSubmittedCount + 1, assignProcMetrics.getSubmittedCounter().getCount());
118    assertEquals(assignFailedCount + 1, assignProcMetrics.getFailedCounter().getCount());
119  }
120}