@Test
  public void testStoreCloseAndDischargeRunningInParallel() throws Exception {
    byte[] fam = Bytes.toBytes("f");
    byte[] col = Bytes.toBytes("c");
    byte[] val = Bytes.toBytes("val");

    TableName tableName = TableName.valueOf(name.getMethodName());
    TableDescriptor htd = TableDescriptorBuilder.newBuilder(tableName)
      .setColumnFamily(ColumnFamilyDescriptorBuilder.of(fam)).build();
    RegionInfo info = RegionInfoBuilder.newBuilder(tableName).build();
    HRegion region = initHRegion(htd, info);
    RegionServerServices rss = mock(RegionServerServices.class);
    List<HRegion> regions = new ArrayList<>();
    regions.add(region);
    Mockito.doReturn(regions).when(rss).getRegions();

    // Create the cleaner object
    CompactedHFilesDischarger cleaner =
      new CompactedHFilesDischarger(1000, (Stoppable) null, rss, false);
    // Add some data to the region and do some flushes
    int batchSize = 10;
    int fileCount = 10;
    for (int f = 0; f < fileCount; f++) {
      int start = f * batchSize;
      for (int i = start; i < start + batchSize; i++) {
        Put p = new Put(Bytes.toBytes("row" + i));
        p.addColumn(fam, col, val);
        region.put(p);
      }
      // flush them
      region.flush(true);
    }

    HStore store = region.getStore(fam);
    assertEquals(fileCount, store.getStorefilesCount());

    Collection<HStoreFile> storefiles = store.getStorefiles();
    // None of the files should be in compacted state.
    for (HStoreFile file : storefiles) {
      assertFalse(file.isCompactedAway());
    }
    // Do compaction
    region.compact(true);

    // now run the cleaner with a concurrent close
    Thread cleanerThread = new Thread() {
      @Override
      public void run() {
        cleaner.chore();
      }
    };
    cleanerThread.start();
    // wait for cleaner to pause
    synchronized (archived) {
      if (!archived.get()) {
        archived.wait();
      }
    }
    final AtomicReference<Exception> closeException = new AtomicReference<>();
    Thread closeThread = new Thread() {
      @Override
      public void run() {
        // wait for the chore to complete and call close
        try {
          ((HRegion) region).close();
        } catch (IOException e) {
          closeException.set(e);
        }
      }
    };
    closeThread.start();
    // no error should occur after the execution of the test
    closeThread.join();
    cleanerThread.join();

    if (closeException.get() != null) {
      throw closeException.get();
    }
  }
Tests a race condition between archiving of compacted files in CompactedHFilesDischarger chore
and HRegion.close();
hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestCompactionArchiveConcurrentClose.java