View Javadoc

1   /**
2    *
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *     http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   */
19  package org.apache.hadoop.hbase.client;
20  
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.fail;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.hadoop.conf.Configuration;
27  import org.apache.hadoop.hbase.HBaseTestingUtility;
28  import org.apache.hadoop.hbase.HConstants;
29  import org.apache.hadoop.hbase.testclassification.LargeTests;
30  import org.apache.hadoop.hbase.MetaTableAccessor;
31  import org.apache.hadoop.hbase.TableName;
32  import org.apache.hadoop.hbase.regionserver.HRegionServer;
33  import org.apache.hadoop.hbase.util.Bytes;
34  import org.junit.AfterClass;
35  import org.junit.Before;
36  import org.junit.BeforeClass;
37  import org.junit.Test;
38  import org.junit.experimental.categories.Category;
39  
40  /**
41   * Test various scanner timeout issues.
42   */
43  @Category(LargeTests.class)
44  public class TestScannerTimeout {
45  
46    private final static HBaseTestingUtility
47        TEST_UTIL = new HBaseTestingUtility();
48  
49    private static final Log LOG = LogFactory.getLog(TestScannerTimeout.class);
50    private final static byte[] SOME_BYTES = Bytes.toBytes("f");
51    private final static TableName TABLE_NAME = TableName.valueOf("t");
52    private final static int NB_ROWS = 10;
53    // Be careful w/ what you set this timer to... it can get in the way of
54    // the mini cluster coming up -- the verification in particular.
55    private final static int THREAD_WAKE_FREQUENCY = 1000;
56    private final static int SCANNER_TIMEOUT = 15000;
57    private final static int SCANNER_CACHING = 5;
58  
59     /**
60     * @throws java.lang.Exception
61     */
62    @BeforeClass
63    public static void setUpBeforeClass() throws Exception {
64      Configuration c = TEST_UTIL.getConfiguration();
65      c.setInt(HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD, SCANNER_TIMEOUT);
66      c.setInt(HConstants.THREAD_WAKE_FREQUENCY, THREAD_WAKE_FREQUENCY);
67      // Put meta on master to avoid meta server shutdown handling
68      c.set("hbase.balancer.tablesOnMaster", "hbase:meta");
69      // We need more than one region server for this test
70      TEST_UTIL.startMiniCluster(2);
71      Table table = TEST_UTIL.createTable(TABLE_NAME, SOME_BYTES);
72       for (int i = 0; i < NB_ROWS; i++) {
73        Put put = new Put(Bytes.toBytes(i));
74        put.add(SOME_BYTES, SOME_BYTES, SOME_BYTES);
75        table.put(put);
76      }
77      table.close();
78    }
79  
80    /**
81     * @throws java.lang.Exception
82     */
83    @AfterClass
84    public static void tearDownAfterClass() throws Exception {
85      TEST_UTIL.shutdownMiniCluster();
86    }
87  
88    /**
89     * @throws java.lang.Exception
90     */
91    @Before
92    public void setUp() throws Exception {
93      TEST_UTIL.ensureSomeNonStoppedRegionServersAvailable(2);
94    }
95  
96    /**
97     * Test that we do get a ScannerTimeoutException
98     * @throws Exception
99     */
100   @Test(timeout=300000)
101   public void test2481() throws Exception {
102     LOG.info("START ************ test2481");
103     Scan scan = new Scan();
104     scan.setCaching(1);
105     Table table =
106       new HTable(new Configuration(TEST_UTIL.getConfiguration()), TABLE_NAME);
107     ResultScanner r = table.getScanner(scan);
108     int count = 0;
109     try {
110       Result res = r.next();
111       while (res != null) {
112         count++;
113         if (count == 5) {
114           // Sleep just a bit more to be sure
115           Thread.sleep(SCANNER_TIMEOUT + THREAD_WAKE_FREQUENCY + 100);
116         }
117         res = r.next();
118       }
119     } catch (ScannerTimeoutException e) {
120       LOG.info("Got the timeout " + e.getMessage(), e);
121       return;
122     }  finally {
123       table.close();
124     }
125     fail("We should be timing out");
126     LOG.info("END ************ test2481");
127   }
128 
129   /**
130    * Test that scanner can continue even if the region server it was reading
131    * from failed. Before 2772, it reused the same scanner id.
132    * @throws Exception
133    */
134   @Test(timeout=300000)
135   public void test2772() throws Exception {
136     LOG.info("START************ test2772");
137     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLE_NAME);
138     Scan scan = new Scan();
139     // Set a very high timeout, we want to test what happens when a RS
140     // fails but the region is recovered before the lease times out.
141     // Since the RS is already created, this conf is client-side only for
142     // this new table
143     Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
144     conf.setInt(HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD, SCANNER_TIMEOUT * 100);
145     Table higherScanTimeoutTable = new HTable(conf, TABLE_NAME);
146     ResultScanner r = higherScanTimeoutTable.getScanner(scan);
147     // This takes way less than SCANNER_TIMEOUT*100
148     rs.abort("die!");
149     Result[] results = r.next(NB_ROWS);
150     assertEquals(NB_ROWS, results.length);
151     r.close();
152     higherScanTimeoutTable.close();
153     LOG.info("END ************ test2772");
154 
155   }
156 
157   /**
158    * Test that scanner won't miss any rows if the region server it was reading
159    * from failed. Before 3686, it would skip rows in the scan.
160    * @throws Exception
161    */
162   @Test(timeout=300000)
163   public void test3686a() throws Exception {
164     LOG.info("START ************ TEST3686A---1");
165     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLE_NAME);
166     LOG.info("START ************ TEST3686A---1111");
167 
168     Scan scan = new Scan();
169     scan.setCaching(SCANNER_CACHING);
170     LOG.info("************ TEST3686A");
171     MetaTableAccessor.fullScanMetaAndPrint(TEST_UTIL.getHBaseAdmin().getConnection());
172     // Set a very high timeout, we want to test what happens when a RS
173     // fails but the region is recovered before the lease times out.
174     // Since the RS is already created, this conf is client-side only for
175     // this new table
176     Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
177     conf.setInt(
178         HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD, SCANNER_TIMEOUT*100);
179     Table table = new HTable(conf, TABLE_NAME);
180     LOG.info("START ************ TEST3686A---22");
181 
182     ResultScanner r = table.getScanner(scan);
183     LOG.info("START ************ TEST3686A---33");
184 
185     int count = 1;
186     r.next();
187     LOG.info("START ************ TEST3686A---44");
188 
189     // Kill after one call to next(), which got 5 rows.
190     rs.abort("die!");
191     while(r.next() != null) {
192       count ++;
193     }
194     assertEquals(NB_ROWS, count);
195     r.close();
196     table.close();
197     LOG.info("************ END TEST3686A");
198   }
199 
200   /**
201    * Make sure that no rows are lost if the scanner timeout is longer on the
202    * client than the server, and the scan times out on the server but not the
203    * client.
204    * @throws Exception
205    */
206   @Test(timeout=300000)
207   public void test3686b() throws Exception {
208     LOG.info("START ************ test3686b");
209     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLE_NAME);
210     Scan scan = new Scan();
211     scan.setCaching(SCANNER_CACHING);
212     // Set a very high timeout, we want to test what happens when a RS
213     // fails but the region is recovered before the lease times out.
214     // Since the RS is already created, this conf is client-side only for
215     // this new table
216     Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
217     conf.setInt(HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD, SCANNER_TIMEOUT * 100);
218     Table higherScanTimeoutTable = new HTable(conf, TABLE_NAME);
219     ResultScanner r = higherScanTimeoutTable.getScanner(scan);
220     int count = 1;
221     r.next();
222     // Sleep, allowing the scan to timeout on the server but not on the client.
223     Thread.sleep(SCANNER_TIMEOUT+2000);
224     while(r.next() != null) {
225       count ++;
226     }
227     assertEquals(NB_ROWS, count);
228     r.close();
229     higherScanTimeoutTable.close();
230     LOG.info("END ************ END test3686b");
231 
232   }
233 
234 }
235