@@ -211,7 +211,7 @@ public MemStoreSnapshot snapshot() {
211211 stopCompaction ();
212212 // region level lock ensures pushing active to pipeline is done in isolation
213213 // no concurrent update operations trying to flush the active segment
214- pushActiveToPipeline (getActive ());
214+ pushActiveToPipeline (getActive (), true );
215215 resetTimeOfOldestEdit ();
216216 snapshotId = EnvironmentEdgeManager .currentTime ();
217217 // in both cases whatever is pushed to snapshot is cleared from the pipeline
@@ -419,33 +419,61 @@ protected List<KeyValueScanner> createList(int capacity) {
419419 }
420420
421421 /**
422- * Check whether anything need to be done based on the current active set size.
423- * The method is invoked upon every addition to the active set.
424- * For CompactingMemStore, flush the active set to the read-only memory if it's
425- * size is above threshold
422+ * Check whether anything need to be done based on the current active set size. The method is
423+ * invoked upon every addition to the active set. For CompactingMemStore, flush the active set to
424+ * the read-only memory if it's size is above threshold
426425 * @param currActive intended segment to update
427426 * @param cellToAdd cell to be added to the segment
428427 * @param memstoreSizing object to accumulate changed size
429- * @return true if the cell can be added to the
428+ * @return true if the cell can be added to the currActive
430429 */
431- private boolean checkAndAddToActiveSize (MutableSegment currActive , Cell cellToAdd ,
430+ protected boolean checkAndAddToActiveSize (MutableSegment currActive , Cell cellToAdd ,
432431 MemStoreSizing memstoreSizing ) {
433- if (shouldFlushInMemory (currActive , cellToAdd , memstoreSizing )) {
434- if (currActive .setInMemoryFlushed ()) {
435- flushInMemory (currActive );
436- if (setInMemoryCompactionFlag ()) {
437- // The thread is dispatched to do in-memory compaction in the background
438- InMemoryCompactionRunnable runnable = new InMemoryCompactionRunnable ();
439- if (LOG .isTraceEnabled ()) {
440- LOG .trace ("Dispatching the MemStore in-memory flush for store " + store
441- .getColumnFamilyName ());
442- }
443- getPool ().execute (runnable );
432+ long cellSize = MutableSegment .getCellLength (cellToAdd );
433+ boolean successAdd = false ;
434+ while (true ) {
435+ long segmentDataSize = currActive .getDataSize ();
436+ if (!inWalReplay && segmentDataSize > inmemoryFlushSize ) {
437+ // when replaying edits from WAL there is no need in in-memory flush regardless the size
438+ // otherwise size below flush threshold try to update atomically
439+ break ;
440+ }
441+ if (currActive .compareAndSetDataSize (segmentDataSize , segmentDataSize + cellSize )) {
442+ if (memstoreSizing != null ) {
443+ memstoreSizing .incMemStoreSize (cellSize , 0 , 0 , 0 );
444444 }
445+ successAdd = true ;
446+ break ;
447+ }
448+ }
449+
450+ if (!inWalReplay && currActive .getDataSize () > inmemoryFlushSize ) {
451+ // size above flush threshold so we flush in memory
452+ this .tryFlushInMemoryAndCompactingAsync (currActive );
453+ }
454+ return successAdd ;
455+ }
456+
457+ /**
458+ * Try to flush the currActive in memory and submit the background
459+ * {@link InMemoryCompactionRunnable} to
460+ * {@link RegionServicesForStores#getInMemoryCompactionPool()}. Just one thread can do the actual
461+ * flushing in memory.
462+ * @param currActive current Active Segment to be flush in memory.
463+ */
464+ private void tryFlushInMemoryAndCompactingAsync (MutableSegment currActive ) {
465+ if (currActive .setInMemoryFlushed ()) {
466+ flushInMemory (currActive );
467+ if (setInMemoryCompactionFlag ()) {
468+ // The thread is dispatched to do in-memory compaction in the background
469+ InMemoryCompactionRunnable runnable = new InMemoryCompactionRunnable ();
470+ if (LOG .isTraceEnabled ()) {
471+ LOG .trace (
472+ "Dispatching the MemStore in-memory flush for store " + store .getColumnFamilyName ());
473+ }
474+ getPool ().execute (runnable );
445475 }
446- return false ;
447476 }
448- return true ;
449477 }
450478
451479 // externally visible only for tests
@@ -504,27 +532,6 @@ private ThreadPoolExecutor getPool() {
504532 return getRegionServices ().getInMemoryCompactionPool ();
505533 }
506534
507- @ VisibleForTesting
508- protected boolean shouldFlushInMemory (MutableSegment currActive , Cell cellToAdd ,
509- MemStoreSizing memstoreSizing ) {
510- long cellSize = MutableSegment .getCellLength (cellToAdd );
511- long segmentDataSize = currActive .getDataSize ();
512- while (segmentDataSize + cellSize < inmemoryFlushSize || inWalReplay ) {
513- // when replaying edits from WAL there is no need in in-memory flush regardless the size
514- // otherwise size below flush threshold try to update atomically
515- if (currActive .compareAndSetDataSize (segmentDataSize , segmentDataSize + cellSize )) {
516- if (memstoreSizing != null ) {
517- memstoreSizing .incMemStoreSize (cellSize , 0 , 0 , 0 );
518- }
519- // enough space for cell - no need to flush
520- return false ;
521- }
522- segmentDataSize = currActive .getDataSize ();
523- }
524- // size above flush threshold
525- return true ;
526- }
527-
528535 /**
529536 * The request to cancel the compaction asynchronous task (caused by in-memory flush)
530537 * The compaction may still happen if the request was sent too late
@@ -536,10 +543,6 @@ private void stopCompaction() {
536543 }
537544 }
538545
539- protected void pushActiveToPipeline (MutableSegment currActive ) {
540- pushActiveToPipeline (currActive , true );
541- }
542-
543546 /**
544547 * NOTE: When {@link CompactingMemStore#flushInMemory(MutableSegment)} calls this method, due to
545548 * concurrent writes and because we first add cell size to currActive.getDataSize and then
0 commit comments