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.util.Bytes;
28  import org.junit.After;
29  import org.junit.AfterClass;
30  import org.junit.Before;
31  import org.junit.BeforeClass;
32  import org.junit.Test;
33  
34  import static org.junit.Assert.assertEquals;
35  import static org.junit.Assert.fail;
36  
37  /**
38   * Test various scanner timeout issues.
39   */
40  public class TestScannerTimeout {
41  
42    private final static HBaseTestingUtility
43        TEST_UTIL = new HBaseTestingUtility();
44  
45    final Log LOG = LogFactory.getLog(getClass());
46    private final static byte[] SOME_BYTES = Bytes.toBytes("f");
47    private final static byte[] TABLE_NAME = Bytes.toBytes("t");
48    private final static int NB_ROWS = 10;
49    private final static int SCANNER_TIMEOUT = 1000;
50    private static HTable table;
51  
52     /**
53     * @throws java.lang.Exception
54     */
55    @BeforeClass
56    public static void setUpBeforeClass() throws Exception {
57      Configuration c = TEST_UTIL.getConfiguration();
58      c.setInt("hbase.regionserver.lease.period", SCANNER_TIMEOUT);
59      TEST_UTIL.startMiniCluster(2);
60      table = TEST_UTIL.createTable(Bytes.toBytes("t"), SOME_BYTES);
61       for (int i = 0; i < NB_ROWS; i++) {
62        Put put = new Put(Bytes.toBytes(i));
63        put.add(SOME_BYTES, SOME_BYTES, SOME_BYTES);
64        table.put(put);
65      }
66    }
67  
68    /**
69     * @throws java.lang.Exception
70     */
71    @AfterClass
72    public static void tearDownAfterClass() throws Exception {
73      TEST_UTIL.shutdownMiniCluster();
74    }
75  
76    /**
77     * @throws java.lang.Exception
78     */
79    @Before
80    public void setUp() throws Exception {
81      TEST_UTIL.ensureSomeRegionServersAvailable(2);
82    }
83  
84    /**
85     * Test that we do get a ScannerTimeoutException
86     * @throws Exception
87     */
88    @Test
89    public void test2481() throws Exception {
90      Scan scan = new Scan();
91      ResultScanner r = table.getScanner(scan);
92      int count = 0;
93      try {
94        Result res = r.next();
95        while (res != null) {
96          count++;
97          if (count == 5) {
98            // Sleep just a bit more to be sure
99            Thread.sleep(SCANNER_TIMEOUT+100);
100         }
101         res = r.next();
102       }
103     } catch (ScannerTimeoutException e) {
104       LOG.info("Got the timeout " + e.getMessage(), e);
105       return;
106     }
107     fail("We should be timing out");
108   }
109 
110   /**
111    * Test that scanner can continue even if the region server it was reading
112    * from failed. Before 2772, it reused the same scanner id.
113    * @throws Exception
114    */
115   @Test
116   public void test2772() throws Exception {
117     int rs = TEST_UTIL.getHBaseCluster().getServerWith(
118         TEST_UTIL.getHBaseCluster().getRegions(
119             TABLE_NAME).get(0).getRegionName());
120     Scan scan = new Scan();
121     // Set a very high timeout, we want to test what happens when a RS
122     // fails but the region is recovered before the lease times out.
123     // Since the RS is already created, this conf is client-side only for
124     // this new table
125     Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
126     conf.setInt(
127         HConstants.HBASE_REGIONSERVER_LEASE_PERIOD_KEY, SCANNER_TIMEOUT*100);
128     HTable higherScanTimeoutTable = new HTable(conf, TABLE_NAME);
129     ResultScanner r = higherScanTimeoutTable.getScanner(scan);
130     // This takes way less than SCANNER_TIMEOUT*100
131     TEST_UTIL.getHBaseCluster().getRegionServer(rs).abort("die!");
132     Result[] results = r.next(NB_ROWS);
133     assertEquals(NB_ROWS, results.length);
134     r.close();
135 
136   }
137 }