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.LargeTests;
30  import org.apache.hadoop.hbase.catalog.MetaReader;
31  import org.apache.hadoop.hbase.regionserver.HRegionServer;
32  import org.apache.hadoop.hbase.util.Bytes;
33  import org.junit.AfterClass;
34  import org.junit.Before;
35  import org.junit.BeforeClass;
36  import org.junit.Test;
37  import org.junit.experimental.categories.Category;
38  
39  /**
40   * Test various scanner timeout issues.
41   */
42  @Category(LargeTests.class)
43  public class TestScannerTimeout {
44  
45    private final static HBaseTestingUtility
46        TEST_UTIL = new HBaseTestingUtility();
47  
48    final Log LOG = LogFactory.getLog(getClass());
49    private final static byte[] SOME_BYTES = Bytes.toBytes("f");
50    private final static byte[] TABLE_NAME = Bytes.toBytes("t");
51    private final static int NB_ROWS = 10;
52    // Be careful w/ what you set this timer to... it can get in the way of
53    // the mini cluster coming up -- the verification in particular.
54    private final static int THREAD_WAKE_FREQUENCY = 1000;
55    private final static int SCANNER_TIMEOUT = 15000;
56    private final static int SCANNER_CACHING = 5;
57  
58     /**
59     * @throws java.lang.Exception
60     */
61    @BeforeClass
62    public static void setUpBeforeClass() throws Exception {
63      Configuration c = TEST_UTIL.getConfiguration();
64      c.setInt(HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD, SCANNER_TIMEOUT);
65      c.setInt(HConstants.THREAD_WAKE_FREQUENCY, THREAD_WAKE_FREQUENCY);
66      // We need more than one region server for this test
67      TEST_UTIL.startMiniCluster(2);
68      HTable table = TEST_UTIL.createTable(TABLE_NAME, SOME_BYTES);
69       for (int i = 0; i < NB_ROWS; i++) {
70        Put put = new Put(Bytes.toBytes(i));
71        put.add(SOME_BYTES, SOME_BYTES, SOME_BYTES);
72        table.put(put);
73      }
74      table.close();
75    }
76  
77    /**
78     * @throws java.lang.Exception
79     */
80    @AfterClass
81    public static void tearDownAfterClass() throws Exception {
82      TEST_UTIL.shutdownMiniCluster();
83    }
84  
85    /**
86     * @throws java.lang.Exception
87     */
88    @Before
89    public void setUp() throws Exception {
90      TEST_UTIL.ensureSomeNonStoppedRegionServersAvailable(2);
91    }
92  
93    /**
94     * Test that we do get a ScannerTimeoutException
95     * @throws Exception
96     */
97    @Test(timeout=300000)
98    public void test2481() throws Exception {
99      LOG.info("START ************ test2481");
100     Scan scan = new Scan();
101     scan.setCaching(1);
102     HTable table =
103       new HTable(new Configuration(TEST_UTIL.getConfiguration()), TABLE_NAME);
104     ResultScanner r = table.getScanner(scan);
105     int count = 0;
106     try {
107       Result res = r.next();
108       while (res != null) {
109         count++;
110         if (count == 5) {
111           // Sleep just a bit more to be sure
112           Thread.sleep(SCANNER_TIMEOUT + THREAD_WAKE_FREQUENCY + 100);
113         }
114         res = r.next();
115       }
116     } catch (ScannerTimeoutException e) {
117       LOG.info("Got the timeout " + e.getMessage(), e);
118       return;
119     }  finally {
120       table.close();
121     }
122     fail("We should be timing out");
123     LOG.info("END ************ test2481");
124   }
125 
126   /**
127    * Test that scanner can continue even if the region server it was reading
128    * from failed. Before 2772, it reused the same scanner id.
129    * @throws Exception
130    */
131   @Test(timeout=300000)
132   public void test2772() throws Exception {
133     LOG.info("START************ test2772");
134     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLE_NAME);
135     Scan scan = new Scan();
136     // Set a very high timeout, we want to test what happens when a RS
137     // fails but the region is recovered before the lease times out.
138     // Since the RS is already created, this conf is client-side only for
139     // this new table
140     Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
141     conf.setInt(HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD, SCANNER_TIMEOUT * 100);
142     HTable higherScanTimeoutTable = new HTable(conf, TABLE_NAME);
143     ResultScanner r = higherScanTimeoutTable.getScanner(scan);
144     // This takes way less than SCANNER_TIMEOUT*100
145     rs.abort("die!");
146     Result[] results = r.next(NB_ROWS);
147     assertEquals(NB_ROWS, results.length);
148     r.close();
149     higherScanTimeoutTable.close();
150     LOG.info("END ************ test2772");
151 
152   }
153 
154   /**
155    * Test that scanner won't miss any rows if the region server it was reading
156    * from failed. Before 3686, it would skip rows in the scan.
157    * @throws Exception
158    */
159   @Test(timeout=300000)
160   public void test3686a() throws Exception {
161     LOG.info("START ************ TEST3686A---1");
162     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLE_NAME);
163     LOG.info("START ************ TEST3686A---1111");
164 
165     Scan scan = new Scan();
166     scan.setCaching(SCANNER_CACHING);
167     LOG.info("************ TEST3686A");
168     MetaReader.fullScanMetaAndPrint(TEST_UTIL.getHBaseCluster().getMaster().getCatalogTracker());
169     // Set a very high timeout, we want to test what happens when a RS
170     // fails but the region is recovered before the lease times out.
171     // Since the RS is already created, this conf is client-side only for
172     // this new table
173     Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
174     conf.setInt(
175         HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD, SCANNER_TIMEOUT*100);
176     HTable table = new HTable(conf, TABLE_NAME);
177     LOG.info("START ************ TEST3686A---22");
178 
179     ResultScanner r = table.getScanner(scan);
180     LOG.info("START ************ TEST3686A---33");
181 
182     int count = 1;
183     r.next();
184     LOG.info("START ************ TEST3686A---44");
185 
186     // Kill after one call to next(), which got 5 rows.
187     rs.abort("die!");
188     while(r.next() != null) {
189       count ++;
190     }
191     assertEquals(NB_ROWS, count);
192     r.close();
193     table.close();
194     LOG.info("************ END TEST3686A");
195   }
196 
197   /**
198    * Make sure that no rows are lost if the scanner timeout is longer on the
199    * client than the server, and the scan times out on the server but not the
200    * client.
201    * @throws Exception
202    */
203   @Test(timeout=300000)
204   public void test3686b() throws Exception {
205     LOG.info("START ************ test3686b");
206     HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLE_NAME);
207     Scan scan = new Scan();
208     scan.setCaching(SCANNER_CACHING);
209     // Set a very high timeout, we want to test what happens when a RS
210     // fails but the region is recovered before the lease times out.
211     // Since the RS is already created, this conf is client-side only for
212     // this new table
213     Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
214     conf.setInt(HConstants.HBASE_CLIENT_SCANNER_TIMEOUT_PERIOD, SCANNER_TIMEOUT * 100);
215     HTable higherScanTimeoutTable = new HTable(conf, TABLE_NAME);
216     ResultScanner r = higherScanTimeoutTable.getScanner(scan);
217     int count = 1;
218     r.next();
219     // Sleep, allowing the scan to timeout on the server but not on the client.
220     Thread.sleep(SCANNER_TIMEOUT+2000);
221     while(r.next() != null) {
222       count ++;
223     }
224     assertEquals(NB_ROWS, count);
225     r.close();
226     higherScanTimeoutTable.close();
227     LOG.info("END ************ END test3686b");
228 
229   }
230 
231 }
232