HBASE-19709 Ensure that we don't set a poolSize of 0

In some situations, Runtime.getRuntime().getAvailableProcessors()
may return 0 which would result in calculatePoolSize returning 0
which will trigger an exception. Guard against this case.

Signed-off-by: Reid Chan <reidddchan@outlook.com>
Signed-off-by: Chia-Ping Tsai <chia7712@gmail.com>
Signed-off-by: Ted Yu <yuzhihong@gmail.com>
This commit is contained in:
Josh Elser 2018-01-04 18:11:59 -05:00
parent ce80e8e38f
commit 443b27b707
2 changed files with 27 additions and 2 deletions

View File

@ -119,7 +119,7 @@ public abstract class CleanerChore<T extends FileCleanerDelegate> extends Schedu
* @param poolSize size from configuration * @param poolSize size from configuration
* @return size of pool after calculation * @return size of pool after calculation
*/ */
private int calculatePoolSize(String poolSize) { int calculatePoolSize(String poolSize) {
if (poolSize.matches("[1-9][0-9]*")) { if (poolSize.matches("[1-9][0-9]*")) {
// If poolSize is an integer, return it directly, // If poolSize is an integer, return it directly,
// but upmost to the number of available processors. // but upmost to the number of available processors.
@ -130,7 +130,13 @@ public abstract class CleanerChore<T extends FileCleanerDelegate> extends Schedu
return size; return size;
} else if (poolSize.matches("0.[0-9]+|1.0")) { } else if (poolSize.matches("0.[0-9]+|1.0")) {
// if poolSize is a double, return poolSize * availableProcessors; // if poolSize is a double, return poolSize * availableProcessors;
return (int) (AVAIL_PROCESSORS * Double.valueOf(poolSize)); // Ensure that we always return at least one.
int computedThreads = (int) (AVAIL_PROCESSORS * Double.valueOf(poolSize));
if (computedThreads < 1) {
LOG.debug("Computed {} threads for CleanerChore, using 1 instead", computedThreads);
return 1;
}
return computedThreads;
} else { } else {
LOG.error("Unrecognized value: " + poolSize + " for " + CHORE_POOL_SIZE + LOG.error("Unrecognized value: " + poolSize + " for " + CHORE_POOL_SIZE +
", use default config: " + DEFAULT_CHORE_POOL_SIZE + " instead."); ", use default config: " + DEFAULT_CHORE_POOL_SIZE + " instead.");

View File

@ -388,6 +388,25 @@ public class TestCleanerChore {
t.join(); t.join();
} }
@Test
public void testMinimumNumberOfThreads() throws Exception {
Stoppable stop = new StoppableImplementation();
Configuration conf = UTIL.getConfiguration();
Path testDir = UTIL.getDataTestDir();
FileSystem fs = UTIL.getTestFileSystem();
String confKey = "hbase.test.cleaner.delegates";
conf.set(confKey, AlwaysDelete.class.getName());
conf.set(CleanerChore.CHORE_POOL_SIZE, "2");
AllValidPaths chore = new AllValidPaths("test-file-cleaner", stop, conf, fs, testDir, confKey);
int numProcs = Runtime.getRuntime().availableProcessors();
// Sanity
assertEquals(numProcs, chore.calculatePoolSize(Integer.toString(numProcs)));
// The implementation does not allow us to set more threads than we have processors
assertEquals(numProcs, chore.calculatePoolSize(Integer.toString(numProcs + 2)));
// Force us into the branch that is multiplying 0.0 against the number of processors
assertEquals(1, chore.calculatePoolSize("0.0"));
}
private void createFiles(FileSystem fs, Path parentDir, int numOfFiles) throws IOException { private void createFiles(FileSystem fs, Path parentDir, int numOfFiles) throws IOException {
Random random = new Random(); Random random = new Random();
for (int i = 0; i < numOfFiles; i++) { for (int i = 0; i < numOfFiles; i++) {