@Test
  public void testExceededClientDeadline() throws Exception {
    Table table = CONN.getTable(TABLE_NAME);

    // put some rows so that our scanner doesn't complete on the first rpc.
    // this would prematurely close the scanner before the timeout handling has a chance to
    for (int i = 0; i < 10; i++) {
      table.put(new Put(Bytes.toBytes(i)).addColumn(new byte[] { '0' }, new byte[] { '0' },
        new byte[] { '0' }));
    }

    try {
      ResultScanner scanner = table.getScanner(new Scan().setCaching(1).setMaxResultSize(1));
      scanner.next();
    } catch (RetriesExhaustedException e) {
      assertTrue(e.getCause() instanceof CallTimeoutException);
    } finally {
      // ensure the scan has finished on the server side
      RSRpcServicesWithScanTimeout.lock.tryLock(60, TimeUnit.SECONDS);
      // there should be 0 running scanners, meaning the scanner was properly closed on the server
      assertEquals(0, RSRpcServicesWithScanTimeout.scannerCount);
      // we should have caught the expected exception
      assertTrue(RSRpcServicesWithScanTimeout.caughtTimeoutException);
      // we should have incremented the callTimedOut metric
      METRICS_ASSERT.assertCounterGt("exceptions.callTimedOut", 0, TEST_UTIL.getHBaseCluster()
        .getRegionServer(0).getRpcServer().getMetrics().getMetricsSource());
    }
  }
If a client's timeout would be exceeded before scan results are ready, there is no point
returning results to the client. Worse, for openScanner calls, the client cannot close the
timed out scanner so this leaks scanners on the server. This test verifies that we properly
track and cleanup scanners when a client timeout is exceeded. This should be more rare when
heartbeats are enabled, since we try to return before timeout there. But it's still possible if
queueing eats up most of the timeout or the inner workings of the scan were slowed down enough
to still exceed the timeout despite the calculated heartbeat deadline.
hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestScannerTimeoutHandling.java