@@ -79,8 +79,7 @@ public class StoreScanner extends NonReversedNonLazyKeyValueScanner
7979 private int storeOffset = 0 ;
8080
8181 // Used to indicate that the scanner has closed (see HBASE-1107)
82- // Do not need to be volatile because it's always accessed via synchronized methods
83- private boolean closing = false ;
82+ private volatile boolean closing = false ;
8483 private final boolean get ;
8584 private final boolean explicitColumnQuery ;
8685 private final boolean useRowColBloom ;
@@ -157,6 +156,8 @@ public class StoreScanner extends NonReversedNonLazyKeyValueScanner
157156 final List <KeyValueScanner > currentScanners = new ArrayList <>();
158157 // flush update lock
159158 private final ReentrantLock flushLock = new ReentrantLock ();
159+ // lock for closing.
160+ private final ReentrantLock closeLock = new ReentrantLock ();
160161
161162 protected final long readPt ;
162163 private boolean topChanged = false ;
@@ -473,31 +474,38 @@ public void close() {
473474 }
474475
475476 private void close (boolean withDelayedScannersClose ) {
476- if (this .closing ) {
477- return ;
478- }
479- if (withDelayedScannersClose ) {
480- this .closing = true ;
481- }
482- // For mob compaction, we do not have a store.
483- if (this .store != null ) {
484- this .store .deleteChangedReaderObserver (this );
485- }
486- if (withDelayedScannersClose ) {
487- clearAndClose (scannersForDelayedClose );
488- clearAndClose (memStoreScannersAfterFlush );
489- clearAndClose (flushedstoreFileScanners );
490- if (this .heap != null ) {
491- this .heap .close ();
492- this .currentScanners .clear ();
493- this .heap = null ; // CLOSED!
477+ closeLock .lock ();
478+ // If the closeLock is acquired then any subsequent updateReaders()
479+ // call is ignored.
480+ try {
481+ if (this .closing ) {
482+ return ;
494483 }
495- } else {
496- if (this .heap != null ) {
497- this .scannersForDelayedClose .add (this .heap );
498- this .currentScanners .clear ();
499- this .heap = null ;
484+ if (withDelayedScannersClose ) {
485+ this .closing = true ;
486+ }
487+ // For mob compaction, we do not have a store.
488+ if (this .store != null ) {
489+ this .store .deleteChangedReaderObserver (this );
500490 }
491+ if (withDelayedScannersClose ) {
492+ clearAndClose (scannersForDelayedClose );
493+ clearAndClose (memStoreScannersAfterFlush );
494+ clearAndClose (flushedstoreFileScanners );
495+ if (this .heap != null ) {
496+ this .heap .close ();
497+ this .currentScanners .clear ();
498+ this .heap = null ; // CLOSED!
499+ }
500+ } else {
501+ if (this .heap != null ) {
502+ this .scannersForDelayedClose .add (this .heap );
503+ this .currentScanners .clear ();
504+ this .heap = null ;
505+ }
506+ }
507+ } finally {
508+ closeLock .unlock ();
501509 }
502510 }
503511
@@ -877,8 +885,25 @@ public void updateReaders(List<HStoreFile> sfs, List<KeyValueScanner> memStoreSc
877885 if (CollectionUtils .isEmpty (sfs ) && CollectionUtils .isEmpty (memStoreScanners )) {
878886 return ;
879887 }
888+ boolean updateReaders = false ;
880889 flushLock .lock ();
881890 try {
891+ if (!closeLock .tryLock ()) {
892+ // The reason for doing this is that when the current store scanner does not retrieve
893+ // any new cells, then the scanner is considered to be done. The heap of this scanner
894+ // is not closed till the shipped() call is completed. Hence in that case if at all
895+ // the partial close (close (false)) has been called before updateReaders(), there is no
896+ // need for the updateReaders() to happen.
897+ LOG .debug ("StoreScanner already has the close lock. There is no need to updateReaders" );
898+ // no lock acquired.
899+ return ;
900+ }
901+ // lock acquired
902+ updateReaders = true ;
903+ if (this .closing ) {
904+ LOG .debug ("StoreScanner already closing. There is no need to updateReaders" );
905+ return ;
906+ }
882907 flushed = true ;
883908 final boolean isCompaction = false ;
884909 boolean usePread = get || scanUsePread ;
@@ -897,6 +922,9 @@ public void updateReaders(List<HStoreFile> sfs, List<KeyValueScanner> memStoreSc
897922 }
898923 } finally {
899924 flushLock .unlock ();
925+ if (updateReaders ) {
926+ closeLock .unlock ();
927+ }
900928 }
901929 // Let the next() call handle re-creating and seeking
902930 }
0 commit comments