1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 package org.apache.hadoop.hbase.replication.regionserver;
20
21 import static org.junit.Assert.assertArrayEquals;
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertTrue;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.hadoop.hbase.testclassification.SmallTests;
28
29 import org.junit.Test;
30 import org.junit.experimental.categories.Category;
31
32 @Category(SmallTests.class)
33 public class TestReplicationThrottler {
34
35 private static final Log LOG = LogFactory.getLog(TestReplicationThrottler.class);
36
37 /**
38 * unit test for throttling
39 */
40 @Test(timeout=10000)
41 public void testThrottling() {
42 LOG.info("testThrottling");
43
44 // throttle bandwidth is 100 and 10 bytes/cycle respectively
45 ReplicationThrottler throttler1 = new ReplicationThrottler(100);
46 ReplicationThrottler throttler2 = new ReplicationThrottler(10);
47
48 long ticks1 = throttler1.getNextSleepInterval(1000);
49 long ticks2 = throttler2.getNextSleepInterval(1000);
50
51 // 1. the first push size is 1000, though 1000 bytes exceeds 100/10
52 // bandwidthes, but no sleep since it's the first push of current
53 // cycle, amortizing occurs when next push arrives
54 assertEquals(0, ticks1);
55 assertEquals(0, ticks2);
56
57 throttler1.addPushSize(1000);
58 throttler2.addPushSize(1000);
59
60 ticks1 = throttler1.getNextSleepInterval(5);
61 ticks2 = throttler2.getNextSleepInterval(5);
62
63 // 2. when the second push(5) arrives and throttling(5) is called, the
64 // current cyclePushSize is 1000 bytes, this should make throttler1
65 // sleep 1000/100 = 10 cycles = 1s and make throttler2 sleep 1000/10
66 // = 100 cycles = 10s before the second push occurs -- amortize case
67 // after amortizing, both cycleStartTick and cyclePushSize are reset
68 //
69 // Note: in a slow machine, the sleep interval might be less than ideal ticks.
70 // If it is 75% of expected value, its is still acceptable.
71 if (ticks1 != 1000 && ticks1 != 999) {
72 assertTrue(ticks1 >= 750 && ticks1 <=1000);
73 }
74 if (ticks2 != 10000 && ticks2 != 9999) {
75 assertTrue(ticks2 >= 7500 && ticks2 <=10000);
76 }
77
78 throttler1.resetStartTick();
79 throttler2.resetStartTick();
80
81 throttler1.addPushSize(5);
82 throttler2.addPushSize(5);
83
84 ticks1 = throttler1.getNextSleepInterval(45);
85 ticks2 = throttler2.getNextSleepInterval(45);
86
87 // 3. when the third push(45) arrives and throttling(45) is called, the
88 // current cyclePushSize is 5 bytes, 50-byte makes throttler1 no
89 // sleep, but can make throttler2 delay to next cycle
90 // note: in real case, sleep time should cover time elapses during push
91 // operation
92 assertTrue(ticks1 == 0);
93 if (ticks2 != 100 && ticks2 != 99) {
94 assertTrue(ticks1 >= 75 && ticks1 <=100);
95 }
96
97 throttler2.resetStartTick();
98
99 throttler1.addPushSize(45);
100 throttler2.addPushSize(45);
101
102 ticks1 = throttler1.getNextSleepInterval(60);
103 ticks2 = throttler2.getNextSleepInterval(60);
104
105 // 4. when the fourth push(60) arrives and throttling(60) is called, throttler1
106 // delay to next cycle since 45+60 == 105; and throttler2 should firstly sleep
107 // ceiling(45/10)= 5 cycles = 500ms to amortize previous push
108 //
109 // Note: in real case, sleep time should cover time elapses during push operation
110 if (ticks1 != 100 && ticks1 != 99) {
111 assertTrue(ticks1 >= 75 && ticks1 <=100);
112 }
113 if (ticks2 != 500 && ticks2 != 499) {
114 assertTrue(ticks1 >= 375 && ticks1 <=500);
115 }
116 }
117 }