1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.client;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.apache.hadoop.conf.Configuration;
25  import org.apache.hadoop.hbase.HBaseTestingUtility;
26  import org.apache.hadoop.hbase.HConstants;
27  import org.apache.hadoop.hbase.regionserver.HRegionServer;
28  import org.apache.hadoop.hbase.util.Bytes;
29  import org.junit.After;
30  import org.junit.AfterClass;
31  import org.junit.Before;
32  import org.junit.BeforeClass;
33  import org.junit.Test;
34  
35  import static org.junit.Assert.assertEquals;
36  import static org.junit.Assert.fail;
37  
38  /**
39   * Test various scanner timeout issues.
40   */
41  public class TestScannerTimeout {
42  
43    private final static HBaseTestingUtility
44        TEST_UTIL = new HBaseTestingUtility();
45  
46    final Log LOG = LogFactory.getLog(getClass());
47    private final static byte[] SOME_BYTES = Bytes.toBytes("f");
48    private final static byte[] TABLE_NAME = Bytes.toBytes("t");
49    private final static int NB_ROWS = 10;
50    private final static int SCANNER_TIMEOUT = 1000;
51    private static HTable table;
52  
53     /**
54     * @throws java.lang.Exception
55     */
56    @BeforeClass
57    public static void setUpBeforeClass() throws Exception {
58      Configuration c = TEST_UTIL.getConfiguration();
59      c.setInt("hbase.regionserver.lease.period", SCANNER_TIMEOUT);
60      TEST_UTIL.startMiniCluster(2);
61      table = TEST_UTIL.createTable(Bytes.toBytes("t"), SOME_BYTES);
62       for (int i = 0; i < NB_ROWS; i++) {
63        Put put = new Put(Bytes.toBytes(i));
64        put.add(SOME_BYTES, SOME_BYTES, SOME_BYTES);
65        table.put(put);
66      }
67    }
68  
69    /**
70     * @throws java.lang.Exception
71     */
72    @AfterClass
73    public static void tearDownAfterClass() throws Exception {
74      TEST_UTIL.shutdownMiniCluster();
75    }
76  
77    /**
78     * @throws java.lang.Exception
79     */
80    @Before
81    public void setUp() throws Exception {
82      TEST_UTIL.ensureSomeRegionServersAvailable(2);
83    }
84  
85    /**
86     * Test that we do get a ScannerTimeoutException
87     * @throws Exception
88     */
89    @Test
90    public void test2481() throws Exception {
91      Scan scan = new Scan();
92      ResultScanner r = table.getScanner(scan);
93      int count = 0;
94      try {
95        Result res = r.next();
96        while (res != null) {
97          count++;
98          if (count == 5) {
99            // Sleep just a bit more to be sure
100           Thread.sleep(SCANNER_TIMEOUT+100);
101         }
102         res = r.next();
103       }
104     } catch (ScannerTimeoutException e) {
105       LOG.info("Got the timeout " + e.getMessage(), e);
106       return;
107     }
108     fail("We should be timing out");
109   }
110 
111   /**
112    * Test that scanner can continue even if the region server it was reading
113    * from failed. Before 2772, it reused the same scanner id.
114    * @throws Exception
115    */
116   @Test
117   public void test2772() throws Exception {
118     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLE_NAME);
119     Scan scan = new Scan();
120     // Set a very high timeout, we want to test what happens when a RS
121     // fails but the region is recovered before the lease times out.
122     // Since the RS is already created, this conf is client-side only for
123     // this new table
124     Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
125     conf.setInt(
126         HConstants.HBASE_REGIONSERVER_LEASE_PERIOD_KEY, SCANNER_TIMEOUT*100);
127     HTable higherScanTimeoutTable = new HTable(conf, TABLE_NAME);
128     ResultScanner r = higherScanTimeoutTable.getScanner(scan);
129     // This takes way less than SCANNER_TIMEOUT*100
130     rs.abort("die!");
131     Result[] results = r.next(NB_ROWS);
132     assertEquals(NB_ROWS, results.length);
133     r.close();
134 
135   }
136 }