public ScanBatch read() throws IOException, TabletClosedException { ScanDataSource dataSource = null; Batch results = null; try { try { scannerSemaphore.acquire(); } catch (InterruptedException e) { sawException = true; } // sawException may have occurred within close, so we cannot assume that an interrupted // exception was its cause if (sawException) throw new IllegalStateException("Tried to use scanner after exception occurred."); if (scanClosed) throw new IllegalStateException("Tried to use scanner after it was closed."); if (options.isIsolated()) { if (isolatedDataSource == null) isolatedDataSource = new ScanDataSource(tablet, options); dataSource = isolatedDataSource; } else { dataSource = new ScanDataSource(tablet, options); } SortedKeyValueIterator<Key, Value> iter; if (options.isIsolated()) { if (isolatedIter == null) isolatedIter = new SourceSwitchingIterator(dataSource, true); else isolatedDataSource.reattachFileManager(); iter = isolatedIter; } else { iter = new SourceSwitchingIterator(dataSource, false); } results = tablet.nextBatch( iter, range, options.getNum(), options.getColumnSet(), options.getBatchTimeOut()); if (results.getResults() == null) { range = null; return new ScanBatch(new ArrayList<KVEntry>(), false); } else if (results.getContinueKey() == null) { return new ScanBatch(results.getResults(), false); } else { range = new Range( results.getContinueKey(), !results.isSkipContinueKey(), range.getEndKey(), range.isEndKeyInclusive()); return new ScanBatch(results.getResults(), true); } } catch (IterationInterruptedException iie) { sawException = true; if (tablet.isClosed()) throw new TabletClosedException(iie); else throw iie; } catch (IOException ioe) { if (tablet.shutdownInProgress()) { log.debug("IOException while shutdown in progress ", ioe); throw new TabletClosedException( ioe); // assume IOException was caused by execution of HDFS shutdown hook } sawException = true; dataSource.close(true); throw ioe; } catch (RuntimeException re) { sawException = true; throw re; } finally { // code in finally block because always want // to return mapfiles, even when exception is thrown if (null != dataSource && !options.isIsolated()) { dataSource.close(false); } else if (null != dataSource) { dataSource.detachFileManager(); } if (results != null && results.getResults() != null) tablet.updateQueryStats(results.getResults().size(), results.getNumBytes()); scannerSemaphore.release(); } }