Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,11 @@ subprojects {
maxHeapSize = '2048m'
jvmArgs '-Xshare:off'
include '**/*Test.class'
/*
* Past ~4 forks the per-fork JVM startup cost (inflated by -Xshare:off above) outweighs the
* gain, since only a handful of classes take more than a second. Override with -PtestForks=N.
*/
maxParallelForks = (project.findProperty('testForks') ?: Math.max(1, Math.min(4, Runtime.runtime.availableProcessors().intdiv(2)))) as int
}

if (rootProject.coverageEnabled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@

public class PropertiesConfigurationUtil {

/**
* How long the reloading detector waits before it will stat the file again. This matches the
* default used by FileHandlerReloadingDetector.
*/
private static final long DEFAULT_RELOADING_REFRESH_DELAY_MILLIS = 5000;

/** How often the periodic trigger asks the reloading controller to check for changes. */
private static final long DEFAULT_RELOAD_TRIGGER_PERIOD = 1;
private static final TimeUnit DEFAULT_RELOAD_TRIGGER_PERIOD_UNIT = TimeUnit.SECONDS;

public static FileBasedConfigurationBuilder<PropertiesConfiguration> createBuilder() {
return new Configurations().propertiesBuilder(getDefaultParameters());
}
Expand Down Expand Up @@ -66,15 +76,23 @@ public static ReloadingFileBasedConfigurationBuilder<PropertiesConfiguration> cr
}

public static ReloadingFileBasedConfigurationBuilder<PropertiesConfiguration> createReloadingBuilder(File file, boolean commaDelimited) {
PropertiesBuilderParameters params = getDefaultParameters().setFile(file);
return createReloadingBuilder(file, commaDelimited, DEFAULT_RELOADING_REFRESH_DELAY_MILLIS);
}

public static ReloadingFileBasedConfigurationBuilder<PropertiesConfiguration> createReloadingBuilder(File file, boolean commaDelimited, long reloadingRefreshDelayMillis) {
PropertiesBuilderParameters params = getDefaultParameters().setFile(file).setReloadingRefreshDelay(reloadingRefreshDelayMillis);
if (commaDelimited) {
params.setListDelimiterHandler(new DefaultListDelimiterHandler(','));
}
return new ReloadingFileBasedConfigurationBuilder<PropertiesConfiguration>(PropertiesConfiguration.class).configure(params);
}

public static PeriodicReloadingTrigger createReloadTrigger(ReloadingFileBasedConfigurationBuilder<PropertiesConfiguration> builder) {
return new PeriodicReloadingTrigger(builder.getReloadingController(), null, 1, TimeUnit.SECONDS);
return createReloadTrigger(builder, DEFAULT_RELOAD_TRIGGER_PERIOD, DEFAULT_RELOAD_TRIGGER_PERIOD_UNIT);
}

public static PeriodicReloadingTrigger createReloadTrigger(ReloadingFileBasedConfigurationBuilder<PropertiesConfiguration> builder, long period, TimeUnit unit) {
return new PeriodicReloadingTrigger(builder.getReloadingController(), null, period, unit);
}

public static void saveTo(PropertiesConfiguration config, File file) throws ConfigurationException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,12 @@ protected ServerSocket getServerSocket() {
return serverSocket;
}

protected int getServerModeSocketCount() {
synchronized (serverModeSockets) {
return serverModeSockets.size();
}
}

private String getLocalAddress() {
return TcpUtil.getFixedHost(replacer.replaceValues(connectorProperties.getLocalAddress(), getChannelId(), getChannel().getName()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -895,15 +895,19 @@ private void createServerSocket() throws IOException {
throw e;
} else {
try {
Thread.sleep(1000);
Thread.sleep(getBindRetryInterval());
} catch (InterruptedException e2) {
Thread.currentThread().interrupt();
}
}
}
}
}


protected long getBindRetryInterval() {
return 1000L;
}

protected ServerSocket getServerSocket() {
return serverSocket;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.io.InputStream;
import java.util.Iterator;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.builder.FileBasedConfigurationBuilder;
Expand All @@ -29,6 +30,16 @@

public class PropertiesConfigurationUtilTest {

/*
* The production reload path is deliberately slow: a one second trigger period on top of the
* five second refresh delay that FileHandlerReloadingDetector defaults to. Driving both down to
* milliseconds keeps the reload behavior under test while removing seven seconds of sleeping.
*/
private static final long RELOAD_REFRESH_DELAY_MILLIS = 10;
private static final long RELOAD_TRIGGER_PERIOD_MILLIS = 10;
private static final long RELOAD_TIMEOUT_MILLIS = 10000;
private static final long QUIET_PERIOD_MILLIS = 200;

@Test
public void testCreateBuilder1() throws Exception {
FileBasedConfigurationBuilder<PropertiesConfiguration> builder = PropertiesConfigurationUtil.createBuilder();
Expand Down Expand Up @@ -110,31 +121,49 @@ public void testCreateReloadingBuilder1() throws Exception {
File file = new File(UUID.randomUUID().toString());
file.createNewFile();

ReloadingFileBasedConfigurationBuilder<PropertiesConfiguration> builder = PropertiesConfigurationUtil.createReloadingBuilder(file);
ReloadingFileBasedConfigurationBuilder<PropertiesConfiguration> builder = PropertiesConfigurationUtil.createReloadingBuilder(file, false, RELOAD_REFRESH_DELAY_MILLIS);

PropertiesConfiguration config = builder.getConfiguration();
assertTrue(config.getListDelimiterHandler() == DisabledListDelimiterHandler.INSTANCE);
assertFalse(config.getKeys().hasNext());

PeriodicReloadingTrigger trigger = PropertiesConfigurationUtil.createReloadTrigger(builder);
PeriodicReloadingTrigger trigger = PropertiesConfigurationUtil.createReloadTrigger(builder, RELOAD_TRIGGER_PERIOD_MILLIS, TimeUnit.MILLISECONDS);
trigger.start();

Thread.sleep(2000);
config = builder.getConfiguration();
assertFalse(config.getKeys().hasNext());
try {
// The file is still empty, so many trigger cycles must not invent any content.
Thread.sleep(QUIET_PERIOD_MILLIS);
assertFalse(builder.getConfiguration().getKeys().hasNext());

FileUtils.writeStringToFile(file, getTestFile(), "UTF-8");
PropertiesConfiguration config2 = PropertiesConfigurationUtil.create(file);
verifyTestProperties(config2);
FileUtils.writeStringToFile(file, getTestFile(), "UTF-8");
PropertiesConfiguration config2 = PropertiesConfigurationUtil.create(file);
verifyTestProperties(config2);

Thread.sleep(5000);
config = builder.getConfiguration();
verifyTestProperties(config);
verifyTestProperties(awaitReloadedConfiguration(builder));
} finally {
trigger.shutdown();
file.delete();
}
}

trigger.shutdown();
file.delete();
/**
* Polls the builder until the trigger has picked up the changed file. The reload normally lands
* within a few trigger periods; the timeout only exists so a genuine failure reports as a failed
* assertion instead of hanging.
*/
private static PropertiesConfiguration awaitReloadedConfiguration(ReloadingFileBasedConfigurationBuilder<PropertiesConfiguration> builder) throws Exception {
long deadline = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(RELOAD_TIMEOUT_MILLIS);
PropertiesConfiguration config = builder.getConfiguration();

while (!config.getKeys().hasNext() && System.nanoTime() < deadline) {
Thread.sleep(RELOAD_TRIGGER_PERIOD_MILLIS);
config = builder.getConfiguration();
}

assertTrue("Configuration was not reloaded after the file changed", config.getKeys().hasNext());
return config;
}

@Test
public void testCreateReloadingBuilderCommaDelimited() throws Exception {
File file = new File(UUID.randomUUID().toString());
Expand Down
Loading
Loading