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()));
+  }
+}