You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by te...@apache.org on 2015/06/16 03:29:42 UTC
hbase git commit: HBASE-13888 Fix refill bug from HBASE-13686
(Guanghao Zhang)
Repository: hbase
Updated Branches:
refs/heads/branch-1.1 778b35811 -> 49700460d
HBASE-13888 Fix refill bug from HBASE-13686 (Guanghao Zhang)
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/49700460
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/49700460
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/49700460
Branch: refs/heads/branch-1.1
Commit: 49700460dabf90562b6f9b4f1f5c45df98668c6c
Parents: 778b358
Author: tedyu <yu...@gmail.com>
Authored: Mon Jun 15 18:29:27 2015 -0700
Committer: tedyu <yu...@gmail.com>
Committed: Mon Jun 15 18:29:27 2015 -0700
----------------------------------------------------------------------
.../quotas/AverageIntervalRateLimiter.java | 4 +-
.../hbase/quotas/FixedIntervalRateLimiter.java | 2 +-
.../apache/hadoop/hbase/quotas/RateLimiter.java | 6 +-
.../hadoop/hbase/quotas/TestRateLimiter.java | 117 ++++++++++++++++++-
4 files changed, 122 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hbase/blob/49700460/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/AverageIntervalRateLimiter.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/AverageIntervalRateLimiter.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/AverageIntervalRateLimiter.java
index a0cd71b..1fb721a 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/AverageIntervalRateLimiter.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/AverageIntervalRateLimiter.java
@@ -26,7 +26,7 @@ public class AverageIntervalRateLimiter extends RateLimiter {
private long nextRefillTime = -1L;
@Override
- public long refill(long limit, long available) {
+ public long refill(long limit) {
final long now = EnvironmentEdgeManager.currentTime();
if (nextRefillTime == -1) {
// Till now no resource has been consumed.
@@ -37,7 +37,7 @@ public class AverageIntervalRateLimiter extends RateLimiter {
long delta = (limit * (now - nextRefillTime)) / super.getTimeUnitInMillis();
if (delta > 0) {
this.nextRefillTime = now;
- return Math.min(limit, available + delta);
+ return Math.min(limit, delta);
}
return 0;
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/49700460/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/FixedIntervalRateLimiter.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/FixedIntervalRateLimiter.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/FixedIntervalRateLimiter.java
index 0b05798..475f778 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/FixedIntervalRateLimiter.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/FixedIntervalRateLimiter.java
@@ -24,7 +24,7 @@ public class FixedIntervalRateLimiter extends RateLimiter {
private long nextRefillTime = -1L;
@Override
- public long refill(long limit, long available) {
+ public long refill(long limit) {
final long now = EnvironmentEdgeManager.currentTime();
if (now < nextRefillTime) {
return 0;
http://git-wip-us.apache.org/repos/asf/hbase/blob/49700460/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/RateLimiter.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/RateLimiter.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/RateLimiter.java
index 0d8e51e..e359601 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/RateLimiter.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/RateLimiter.java
@@ -47,9 +47,9 @@ public abstract class RateLimiter {
/**
* Refill the available units w.r.t the elapsed time.
* @param limit Maximum available resource units that can be refilled to.
- * @param available Currently available resource units
+ * @return how many resource units may be refilled ?
*/
- abstract long refill(long limit, long available);
+ abstract long refill(long limit);
/**
* Time in milliseconds to wait for before requesting to consume 'amount' resource.
@@ -142,7 +142,7 @@ public abstract class RateLimiter {
* @return true if there are enough available resources, otherwise false
*/
public synchronized boolean canExecute(final long amount) {
- long refillAmount = refill(limit, avail);
+ long refillAmount = refill(limit);
if (refillAmount == 0 && avail < amount) {
return false;
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/49700460/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestRateLimiter.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestRateLimiter.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestRateLimiter.java
index d2c1507..8073d5f 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestRateLimiter.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestRateLimiter.java
@@ -18,6 +18,7 @@ import static org.junit.Assert.assertTrue;
import java.util.concurrent.TimeUnit;
import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
import org.junit.Test;
import org.junit.experimental.categories.Category;
@@ -162,4 +163,118 @@ public class TestRateLimiter {
}
}
}
-}
\ No newline at end of file
+
+ @Test
+ public void testCanExecuteOfAverageIntervalRateLimiter() throws InterruptedException {
+ RateLimiter limiter = new AverageIntervalRateLimiter();
+ // when set limit is 100 per sec, this AverageIntervalRateLimiter will support at max 200 per sec
+ limiter.set(100, TimeUnit.SECONDS);
+ limiter.setNextRefillTime(EnvironmentEdgeManager.currentTime());
+ assertEquals(50, testCanExecuteByRate(limiter, 50));
+
+ // refill the avail to limit
+ limiter.set(100, TimeUnit.SECONDS);
+ limiter.setNextRefillTime(EnvironmentEdgeManager.currentTime());
+ assertEquals(100, testCanExecuteByRate(limiter, 100));
+
+ // refill the avail to limit
+ limiter.set(100, TimeUnit.SECONDS);
+ limiter.setNextRefillTime(EnvironmentEdgeManager.currentTime());
+ assertEquals(200, testCanExecuteByRate(limiter, 200));
+
+ // refill the avail to limit
+ limiter.set(100, TimeUnit.SECONDS);
+ limiter.setNextRefillTime(EnvironmentEdgeManager.currentTime());
+ assertEquals(200, testCanExecuteByRate(limiter, 500));
+ }
+
+ @Test
+ public void testCanExecuteOfFixedIntervalRateLimiter() throws InterruptedException {
+ RateLimiter limiter = new FixedIntervalRateLimiter();
+ // when set limit is 100 per sec, this FixedIntervalRateLimiter will support at max 100 per sec
+ limiter.set(100, TimeUnit.SECONDS);
+ limiter.setNextRefillTime(EnvironmentEdgeManager.currentTime());
+ assertEquals(50, testCanExecuteByRate(limiter, 50));
+
+ // refill the avail to limit
+ limiter.set(100, TimeUnit.SECONDS);
+ limiter.setNextRefillTime(EnvironmentEdgeManager.currentTime());
+ assertEquals(100, testCanExecuteByRate(limiter, 100));
+
+ // refill the avail to limit
+ limiter.set(100, TimeUnit.SECONDS);
+ limiter.setNextRefillTime(EnvironmentEdgeManager.currentTime());
+ assertEquals(100, testCanExecuteByRate(limiter, 200));
+ }
+
+ public int testCanExecuteByRate(RateLimiter limiter, int rate) {
+ int request = 0;
+ int count = 0;
+ while ((request++) < rate) {
+ limiter.setNextRefillTime(limiter.getNextRefillTime() - limiter.getTimeUnitInMillis() / rate);
+ if (limiter.canExecute()) {
+ count++;
+ limiter.consume();
+ }
+ }
+ return count;
+ }
+
+ @Test
+ public void testRefillOfAverageIntervalRateLimiter() throws InterruptedException {
+ RateLimiter limiter = new AverageIntervalRateLimiter();
+ limiter.set(60, TimeUnit.SECONDS);
+ assertEquals(60, limiter.getAvailable());
+ // first refill, will return the number same with limit
+ assertEquals(60, limiter.refill(limiter.getLimit()));
+
+ limiter.consume(30);
+
+ // after 0.2 sec, refill should return 12
+ limiter.setNextRefillTime(limiter.getNextRefillTime() - 200);
+ assertEquals(12, limiter.refill(limiter.getLimit()));
+
+ // after 0.5 sec, refill should return 30
+ limiter.setNextRefillTime(limiter.getNextRefillTime() - 500);
+ assertEquals(30, limiter.refill(limiter.getLimit()));
+
+ // after 1 sec, refill should return 60
+ limiter.setNextRefillTime(limiter.getNextRefillTime() - 1000);
+ assertEquals(60, limiter.refill(limiter.getLimit()));
+
+ // after more than 1 sec, refill should return at max 60
+ limiter.setNextRefillTime(limiter.getNextRefillTime() - 3000);
+ assertEquals(60, limiter.refill(limiter.getLimit()));
+ limiter.setNextRefillTime(limiter.getNextRefillTime() - 5000);
+ assertEquals(60, limiter.refill(limiter.getLimit()));
+ }
+
+ @Test
+ public void testRefillOfFixedIntervalRateLimiter() throws InterruptedException {
+ RateLimiter limiter = new FixedIntervalRateLimiter();
+ limiter.set(60, TimeUnit.SECONDS);
+ assertEquals(60, limiter.getAvailable());
+ // first refill, will return the number same with limit
+ assertEquals(60, limiter.refill(limiter.getLimit()));
+
+ limiter.consume(30);
+
+ // after 0.2 sec, refill should return 0
+ limiter.setNextRefillTime(limiter.getNextRefillTime() - 200);
+ assertEquals(0, limiter.refill(limiter.getLimit()));
+
+ // after 0.5 sec, refill should return 0
+ limiter.setNextRefillTime(limiter.getNextRefillTime() - 500);
+ assertEquals(0, limiter.refill(limiter.getLimit()));
+
+ // after 1 sec, refill should return 60
+ limiter.setNextRefillTime(limiter.getNextRefillTime() - 1000);
+ assertEquals(60, limiter.refill(limiter.getLimit()));
+
+ // after more than 1 sec, refill should return at max 60
+ limiter.setNextRefillTime(limiter.getNextRefillTime() - 3000);
+ assertEquals(60, limiter.refill(limiter.getLimit()));
+ limiter.setNextRefillTime(limiter.getNextRefillTime() - 5000);
+ assertEquals(60, limiter.refill(limiter.getLimit()));
+ }
+}