@Test
  public void testOnConfigurationChange() throws Exception {
    // constants
    final int ORIGINAL_THROTTLE_POINT = 512 * 1024;
    final int ORIGINAL_QUEUE_INIT_SIZE = 512;
    final int UPDATE_THROTTLE_POINT = 1024;// small enough to change large/small check
    final int UPDATE_QUEUE_INIT_SIZE = 1024;
    final int LARGE_FILE_NUM = 5;
    final int SMALL_FILE_NUM = 20;
    final int LARGE_THREAD_NUM = 2;
    final int SMALL_THREAD_NUM = 4;
    final long THREAD_TIMEOUT_MSEC = 30 * 1000L;
    final long THREAD_CHECK_INTERVAL_MSEC = 500L;

    Configuration conf = UTIL.getConfiguration();
    // no cleaner policies = delete all files
    conf.setStrings(HFileCleaner.MASTER_HFILE_CLEANER_PLUGINS, "");
    conf.setInt(HFileCleaner.HFILE_DELETE_THROTTLE_THRESHOLD, ORIGINAL_THROTTLE_POINT);
    conf.setInt(HFileCleaner.LARGE_HFILE_QUEUE_INIT_SIZE, ORIGINAL_QUEUE_INIT_SIZE);
    conf.setInt(HFileCleaner.SMALL_HFILE_QUEUE_INIT_SIZE, ORIGINAL_QUEUE_INIT_SIZE);
    Server server = new DummyServer();
    Path archivedHfileDir =
      new Path(UTIL.getDataTestDirOnTestFS(), HConstants.HFILE_ARCHIVE_DIRECTORY);

    // setup the cleaner
    FileSystem fs = UTIL.getDFSCluster().getFileSystem();
    final HFileCleaner cleaner = new HFileCleaner(1000, server, conf, fs, archivedHfileDir, POOL);
    Assert.assertEquals(ORIGINAL_THROTTLE_POINT, cleaner.getThrottlePoint());
    Assert.assertEquals(ORIGINAL_QUEUE_INIT_SIZE, cleaner.getLargeQueueInitSize());
    Assert.assertEquals(ORIGINAL_QUEUE_INIT_SIZE, cleaner.getSmallQueueInitSize());
    Assert.assertEquals(HFileCleaner.DEFAULT_HFILE_DELETE_THREAD_TIMEOUT_MSEC,
      cleaner.getCleanerThreadTimeoutMsec());
    Assert.assertEquals(HFileCleaner.DEFAULT_HFILE_DELETE_THREAD_CHECK_INTERVAL_MSEC,
      cleaner.getCleanerThreadCheckIntervalMsec());

    // clean up archive directory and create files for testing
    fs.delete(archivedHfileDir, true);
    fs.mkdirs(archivedHfileDir);
    createFilesForTesting(LARGE_FILE_NUM, SMALL_FILE_NUM, fs, archivedHfileDir);

    // call cleaner, run as daemon to test the interrupt-at-middle case
    Thread t = new Thread() {
      @Override
      public void run() {
        cleaner.chore();
      }
    };
    t.setDaemon(true);
    t.start();
    // wait until file clean started
    while (cleaner.getNumOfDeletedSmallFiles() == 0) {
      Thread.yield();
    }

    // trigger configuration change
    Configuration newConf = new Configuration(conf);
    newConf.setInt(HFileCleaner.HFILE_DELETE_THROTTLE_THRESHOLD, UPDATE_THROTTLE_POINT);
    newConf.setInt(HFileCleaner.LARGE_HFILE_QUEUE_INIT_SIZE, UPDATE_QUEUE_INIT_SIZE);
    newConf.setInt(HFileCleaner.SMALL_HFILE_QUEUE_INIT_SIZE, UPDATE_QUEUE_INIT_SIZE);
    newConf.setInt(HFileCleaner.LARGE_HFILE_DELETE_THREAD_NUMBER, LARGE_THREAD_NUM);
    newConf.setInt(HFileCleaner.SMALL_HFILE_DELETE_THREAD_NUMBER, SMALL_THREAD_NUM);
    newConf.setLong(HFileCleaner.HFILE_DELETE_THREAD_TIMEOUT_MSEC, THREAD_TIMEOUT_MSEC);
    newConf.setLong(HFileCleaner.HFILE_DELETE_THREAD_CHECK_INTERVAL_MSEC,
      THREAD_CHECK_INTERVAL_MSEC);

    LOG.debug("File deleted from large queue: " + cleaner.getNumOfDeletedLargeFiles()
      + "; from small queue: " + cleaner.getNumOfDeletedSmallFiles());
    cleaner.onConfigurationChange(newConf);

    // check values after change
    Assert.assertEquals(UPDATE_THROTTLE_POINT, cleaner.getThrottlePoint());
    Assert.assertEquals(UPDATE_QUEUE_INIT_SIZE, cleaner.getLargeQueueInitSize());
    Assert.assertEquals(UPDATE_QUEUE_INIT_SIZE, cleaner.getSmallQueueInitSize());
    Assert.assertEquals(LARGE_THREAD_NUM + SMALL_THREAD_NUM, cleaner.getCleanerThreads().size());
    Assert.assertEquals(THREAD_TIMEOUT_MSEC, cleaner.getCleanerThreadTimeoutMsec());
    Assert.assertEquals(THREAD_CHECK_INTERVAL_MSEC, cleaner.getCleanerThreadCheckIntervalMsec());

    // make sure no cost when onConfigurationChange called with no change
    List<Thread> oldThreads = cleaner.getCleanerThreads();
    cleaner.onConfigurationChange(newConf);
    List<Thread> newThreads = cleaner.getCleanerThreads();
    Assert.assertArrayEquals(oldThreads.toArray(), newThreads.toArray());

    // wait until clean done and check
    t.join();
    LOG.debug("File deleted from large queue: " + cleaner.getNumOfDeletedLargeFiles()
      + "; from small queue: " + cleaner.getNumOfDeletedSmallFiles());
    Assert.assertTrue(
      "Should delete more than " + LARGE_FILE_NUM + " files from large queue but actually "
        + cleaner.getNumOfDeletedLargeFiles(),
      cleaner.getNumOfDeletedLargeFiles() > LARGE_FILE_NUM);
    Assert.assertTrue(
      "Should delete less than " + SMALL_FILE_NUM + " files from small queue but actually "
        + cleaner.getNumOfDeletedSmallFiles(),
      cleaner.getNumOfDeletedSmallFiles() < SMALL_FILE_NUM);
  }
@param file to check
@return loggable information about the file
hbase-server/src/test/java/org/apache/hadoop/hbase/master/cleaner/TestHFileCleaner.java