diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java index 9c966cd..7c6bde3 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/HRegion.java @@ -5630,26 +5630,39 @@ public class HRegion implements HeapSize, PropagatingConfigurationObserver, Regi List scanners = new ArrayList(scan.getFamilyMap().size()); List joinedScanners = new ArrayList(scan.getFamilyMap().size()); - if (additionalScanners != null) { + // Store all already instantiated scanners for exception handling + List instantiatedScanners = new ArrayList(); + // handle additionalScanners + if (additionalScanners != null && !additionalScanners.isEmpty()) { scanners.addAll(additionalScanners); + instantiatedScanners.addAll(additionalScanners); } - for (Map.Entry> entry : scan.getFamilyMap().entrySet()) { - Store store = stores.get(entry.getKey()); - KeyValueScanner scanner; - try { - scanner = store.getScanner(scan, entry.getValue(), this.readPt); - } catch (FileNotFoundException e) { - throw handleFileNotFound(e); + try { + for (Map.Entry> entry : scan.getFamilyMap().entrySet()) { + Store store = stores.get(entry.getKey()); + KeyValueScanner scanner; + try { + scanner = store.getScanner(scan, entry.getValue(), this.readPt); + } catch (FileNotFoundException e) { + throw handleFileNotFound(e); + } + instantiatedScanners.add(scanner); + if (this.filter == null || !scan.doLoadColumnFamiliesOnDemand() + || this.filter.isFamilyEssential(entry.getKey())) { + scanners.add(scanner); + } else { + joinedScanners.add(scanner); + } } - if (this.filter == null || !scan.doLoadColumnFamiliesOnDemand() - || this.filter.isFamilyEssential(entry.getKey())) { - scanners.add(scanner); - } else { - joinedScanners.add(scanner); + initializeKVHeap(scanners, joinedScanners, region); + } catch (IOException e) { + // close all already instantiated scanners before throwing the exception + for (KeyValueScanner scanner : instantiatedScanners) { + scanner.close(); } + throw e; } - initializeKVHeap(scanners, joinedScanners, region); } protected void initializeKVHeap(List scanners, diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/StoreScanner.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/StoreScanner.java index 7ebae94..40add33 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/StoreScanner.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/StoreScanner.java @@ -200,8 +200,6 @@ public class StoreScanner extends NonReversedNonLazyKeyValueScanner ScanType.USER_SCAN, Long.MAX_VALUE, HConstants.LATEST_TIMESTAMP, oldestUnexpiredTS, now, store.getCoprocessorHost()); - this.store.addChangedReaderObserver(this); - // Pass columns to try to filter out unnecessary StoreFiles. List scanners = getScannersNoCompaction(); @@ -220,6 +218,9 @@ public class StoreScanner extends NonReversedNonLazyKeyValueScanner addCurrentScanners(scanners); // Combine all seeked scanners with a heap resetKVHeap(scanners, store.getComparator()); + + // add observer at last to avoid memory leak when exception occurs during initialization + this.store.addChangedReaderObserver(this); } /**