SOLR-7285: ActionThrottle will not pause if getNanoTime first returns 0.

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1668370 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Mark Robert Miller 2015-03-22 13:44:35 +00:00
parent 0a8dfe05dc
commit 8e6f93c6ff
2 changed files with 60 additions and 6 deletions

View File

@ -26,25 +26,45 @@ import org.slf4j.LoggerFactory;
public class ActionThrottle {
private static Logger log = LoggerFactory.getLogger(ActionThrottle.class);
private volatile long lastActionStartedAt;
private volatile long minMsBetweenActions;
private volatile Long lastActionStartedAt;
private volatile Long minMsBetweenActions;
private final String name;
private final NanoTimeSource nanoTimeSource;
public interface NanoTimeSource {
long getTime();
}
private static class DefaultNanoTimeSource implements NanoTimeSource {
@Override
public long getTime() {
return System.nanoTime();
}
}
public ActionThrottle(String name, long minMsBetweenActions) {
this.name = name;
this.minMsBetweenActions = minMsBetweenActions;
this.nanoTimeSource = new DefaultNanoTimeSource();
}
public ActionThrottle(String name, long minMsBetweenActions, NanoTimeSource nanoTimeSource) {
this.name = name;
this.minMsBetweenActions = minMsBetweenActions;
this.nanoTimeSource = nanoTimeSource;
}
public void markAttemptingAction() {
lastActionStartedAt = System.nanoTime();
lastActionStartedAt = nanoTimeSource.getTime();
}
public void minimumWaitBetweenActions() {
if (lastActionStartedAt == 0) {
if (lastActionStartedAt == null) {
return;
}
long diff = System.nanoTime() - lastActionStartedAt;
long diff = nanoTimeSource.getTime() - lastActionStartedAt;
int diffMs = (int) TimeUnit.MILLISECONDS.convert(diff, TimeUnit.NANOSECONDS);
long minNsBetweenActions = TimeUnit.NANOSECONDS.convert(minMsBetweenActions, TimeUnit.MILLISECONDS);
log.info("The last {} attempt started {}ms ago.", name, diffMs);
@ -53,7 +73,7 @@ public class ActionThrottle {
if (diffMs > 0 && diff < minNsBetweenActions) {
sleep = (int) TimeUnit.MILLISECONDS.convert(minNsBetweenActions - diff, TimeUnit.NANOSECONDS);
} else if (diffMs == 0) {
sleep = (int) minMsBetweenActions;
sleep = minMsBetweenActions.intValue();
}
if (sleep > 0) {

View File

@ -17,9 +17,12 @@ package org.apache.solr.cloud;
* limitations under the License.
*/
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.cloud.ActionThrottle.NanoTimeSource;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -27,6 +30,21 @@ import org.slf4j.LoggerFactory;
public class ActionThrottleTest extends SolrTestCaseJ4 {
protected static Logger log = LoggerFactory.getLogger(ActionThrottleTest.class);
static class TestNanoTimeSource implements NanoTimeSource {
private List<Long> returnValues;
private int index = 0;
public TestNanoTimeSource(List<Long> returnValues) {
this.returnValues = returnValues;
}
@Override
public long getTime() {
return returnValues.get(index++);
}
}
@Test
public void testBasics() throws Exception {
@ -59,5 +77,21 @@ public class ActionThrottleTest extends SolrTestCaseJ4 {
assertTrue(elaspsedTime + "ms", elaspsedTime >= 995);
}
@Test
public void testAZeroNanoTimeReturnInWait() throws Exception {
ActionThrottle at = new ActionThrottle("test", 1000, new TestNanoTimeSource(Arrays.asList(new Long[]{0L, 10L})));
long start = System.nanoTime();
at.markAttemptingAction();
at.minimumWaitBetweenActions();
long elaspsedTime = TimeUnit.MILLISECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS);
assertTrue(elaspsedTime + "ms", elaspsedTime >= 995);
}
}