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 static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.fail;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.HBaseTestingUtility;
29  import org.apache.hadoop.hbase.HConstants;
30  import org.apache.hadoop.hbase.regionserver.HRegionServer;
31  import org.apache.hadoop.hbase.util.Bytes;
32  import org.junit.AfterClass;
33  import org.junit.Before;
34  import org.junit.BeforeClass;
35  import org.junit.Test;
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    // Be careful w/ what you set this timer too... it can get in the way of
50    // the mini cluster coming up -- the verification in particular.
51    private final static int SCANNER_TIMEOUT = 10000;
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      HTable table = TEST_UTIL.createTable(TABLE_NAME, 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      HTable table =
93        new HTable(new Configuration(TEST_UTIL.getConfiguration()), TABLE_NAME);
94      ResultScanner r = table.getScanner(scan);
95      int count = 0;
96      try {
97        Result res = r.next();
98        while (res != null) {
99          count++;
100         if (count == 5) {
101           // Sleep just a bit more to be sure
102           Thread.sleep(SCANNER_TIMEOUT+100);
103         }
104         res = r.next();
105       }
106     } catch (ScannerTimeoutException e) {
107       LOG.info("Got the timeout " + e.getMessage(), e);
108       return;
109     }
110     fail("We should be timing out");
111   }
112 
113   /**
114    * Test that scanner can continue even if the region server it was reading
115    * from failed. Before 2772, it reused the same scanner id.
116    * @throws Exception
117    */
118   @Test
119   public void test2772() throws Exception {
120     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLE_NAME);
121     Scan scan = new Scan();
122     // Set a very high timeout, we want to test what happens when a RS
123     // fails but the region is recovered before the lease times out.
124     // Since the RS is already created, this conf is client-side only for
125     // this new table
126     Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
127     conf.setInt(
128         HConstants.HBASE_REGIONSERVER_LEASE_PERIOD_KEY, SCANNER_TIMEOUT*100);
129     HTable higherScanTimeoutTable = new HTable(conf, TABLE_NAME);
130     ResultScanner r = higherScanTimeoutTable.getScanner(scan);
131     // This takes way less than SCANNER_TIMEOUT*100
132     rs.abort("die!");
133     Result[] results = r.next(NB_ROWS);
134     assertEquals(NB_ROWS, results.length);
135     r.close();
136   }
137 }