diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java index 4896df93982..c32b391edaa 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java @@ -779,7 +779,7 @@ public interface Admin extends Abortable, Closeable { /** * Ask for a scan of the catalog table * - * @return the number of entries cleaned + * @return the number of entries cleaned. Returns -1 if previous run is in progress. * @throws IOException if a remote or network exception occurs */ int runCatalogScan() throws IOException; diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/CatalogJanitor.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/CatalogJanitor.java index 549c38f5b83..911248c6f9b 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/CatalogJanitor.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/CatalogJanitor.java @@ -238,7 +238,9 @@ public class CatalogJanitor extends ScheduledChore { int scan() throws IOException { try { if (!alreadyRunning.compareAndSet(false, true)) { - return 0; + LOG.debug("CatalogJanitor already running"); + // -1 indicates previous scan is in progress + return -1; } Triple, Map> scanTriple = getMergedRegionsAndSplitParents(); diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java index 94166203caf..397d5a80f08 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java @@ -26,6 +26,7 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.SortedMap; @@ -1068,6 +1069,37 @@ public class TestCatalogJanitor { janitor.cancel(true); } + @Test + public void testAlreadyRunningStatus() throws Exception { + int numberOfThreads = 2; + final List gcValues = new ArrayList<>(); + Thread[] threads = new Thread[numberOfThreads]; + HBaseTestingUtility hBaseTestingUtility = new HBaseTestingUtility(); + hBaseTestingUtility.getConfiguration().setInt("hbase.client.retries.number", 5); + Server server = new MockServer(hBaseTestingUtility); + MasterServices services = new MockMasterServices(server); + final CatalogJanitor catalogJanitor = new CatalogJanitor(server, services); + for (int i = 0; i < numberOfThreads; i++) { + threads[i] = new Thread(new Runnable() { + @Override + public void run() { + try { + gcValues.add(catalogJanitor.scan()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }); + } + for (int i = 0; i < numberOfThreads; i++) { + threads[i].start(); + } + for (int i = 0; i < numberOfThreads; i++) { + threads[i].join(); + } + assertTrue("One janitor.scan() call should have returned -1", gcValues.contains(-1)); + } + private FileStatus[] addMockStoreFiles(int count, MasterServices services, Path storedir) throws IOException { // get the existing store files