1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.ipc;
19
20 import java.util.Collection;
21 import java.util.Iterator;
22 import java.util.concurrent.BlockingQueue;
23 import java.util.concurrent.LinkedBlockingDeque;
24 import java.util.concurrent.LinkedBlockingQueue;
25 import java.util.concurrent.TimeUnit;
26 import java.util.concurrent.atomic.AtomicBoolean;
27 import java.util.concurrent.atomic.AtomicLong;
28
29 import org.apache.hadoop.hbase.classification.InterfaceAudience;
30 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 @InterfaceAudience.Private
46 public class AdaptiveLifoCoDelCallQueue implements BlockingQueue<CallRunner> {
47
48
49 private LinkedBlockingDeque<CallRunner> queue;
50
51
52 private int maxCapacity;
53
54
55 private AtomicLong numGeneralCallsDropped;
56 private AtomicLong numLifoModeSwitches;
57
58
59 private volatile int codelTargetDelay;
60 private volatile int codelInterval;
61
62
63
64 private volatile double lifoThreshold;
65
66
67 private volatile long minDelay;
68
69
70 private volatile long intervalTime = EnvironmentEdgeManager.currentTime();
71
72
73 private AtomicBoolean resetDelay = new AtomicBoolean(true);
74
75
76 private AtomicBoolean isOverloaded = new AtomicBoolean(false);
77
78 public AdaptiveLifoCoDelCallQueue(int capacity, int targetDelay, int interval,
79 double lifoThreshold, AtomicLong numGeneralCallsDropped, AtomicLong numLifoModeSwitches) {
80 this.maxCapacity = capacity;
81 this.queue = new LinkedBlockingDeque<>(capacity);
82 this.codelTargetDelay = targetDelay;
83 this.codelInterval = interval;
84 this.lifoThreshold = lifoThreshold;
85 this.numGeneralCallsDropped = numGeneralCallsDropped;
86 this.numLifoModeSwitches = numLifoModeSwitches;
87 }
88
89
90
91
92
93
94
95
96 public void updateTunables(int newCodelTargetDelay, int newCodelInterval,
97 double newLifoThreshold) {
98 this.codelTargetDelay = newCodelTargetDelay;
99 this.codelInterval = newCodelInterval;
100 this.lifoThreshold = newLifoThreshold;
101 }
102
103
104
105
106
107
108
109
110 @Override
111 public CallRunner take() throws InterruptedException {
112 CallRunner cr;
113 while(true) {
114 if (((double) queue.size() / this.maxCapacity) > lifoThreshold) {
115 numLifoModeSwitches.incrementAndGet();
116 cr = queue.takeLast();
117 } else {
118 cr = queue.takeFirst();
119 }
120 if (needToDrop(cr)) {
121 numGeneralCallsDropped.incrementAndGet();
122 cr.drop();
123 } else {
124 return cr;
125 }
126 }
127 }
128
129 @Override
130 public CallRunner poll() {
131 CallRunner cr;
132 boolean switched = false;
133 while(true) {
134 if (((double) queue.size() / this.maxCapacity) > lifoThreshold) {
135
136 if (!switched) {
137 switched = true;
138 numLifoModeSwitches.incrementAndGet();
139 }
140 cr = queue.pollLast();
141 } else {
142 switched = false;
143 cr = queue.pollFirst();
144 }
145 if (cr == null) {
146 return cr;
147 }
148 if (needToDrop(cr)) {
149 numGeneralCallsDropped.incrementAndGet();
150 cr.drop();
151 } else {
152 return cr;
153 }
154 }
155 }
156
157
158
159
160
161
162 private boolean needToDrop(CallRunner callRunner) {
163 long now = EnvironmentEdgeManager.currentTime();
164 long callDelay = now - callRunner.getCall().timestamp;
165
166 long localMinDelay = this.minDelay;
167
168
169
170 if (now > intervalTime &&
171 !resetDelay.get() &&
172 !resetDelay.getAndSet(true)) {
173 intervalTime = now + codelInterval;
174
175 isOverloaded.set(localMinDelay > codelTargetDelay);
176 }
177
178
179
180 if (resetDelay.get() && resetDelay.getAndSet(false)) {
181 minDelay = callDelay;
182
183 return false;
184 } else if (callDelay < localMinDelay) {
185 minDelay = callDelay;
186 }
187
188 return isOverloaded.get() && callDelay > 2 * codelTargetDelay;
189 }
190
191
192 @Override
193 public boolean offer(CallRunner callRunner) {
194 return queue.offer(callRunner);
195 }
196
197 @Override
198 public int size() {
199 return queue.size();
200 }
201
202 @Override
203 public String toString() {
204 return queue.toString();
205 }
206
207
208
209
210 @Override
211 public CallRunner poll(long timeout, TimeUnit unit) throws InterruptedException {
212 throw new UnsupportedOperationException("This class doesn't support anything,"
213 + " but take() and offer() methods");
214 }
215
216
217 @Override
218 public CallRunner peek() {
219 throw new UnsupportedOperationException("This class doesn't support anything,"
220 + " but take() and offer() methods");
221 }
222
223 @Override
224 public boolean remove(Object o) {
225 throw new UnsupportedOperationException("This class doesn't support anything,"
226 + " but take() and offer() methods");
227 }
228
229 @Override
230 public boolean contains(Object o) {
231 throw new UnsupportedOperationException("This class doesn't support anything,"
232 + " but take() and offer() methods");
233 }
234
235 @Override
236 public Object[] toArray() {
237 throw new UnsupportedOperationException("This class doesn't support anything,"
238 + " but take() and offer() methods");
239 }
240
241 @Override
242 public <T> T[] toArray(T[] a) {
243 throw new UnsupportedOperationException("This class doesn't support anything,"
244 + " but take() and offer() methods");
245 }
246
247 @Override
248 public void clear() {
249 throw new UnsupportedOperationException("This class doesn't support anything,"
250 + " but take() and offer() methods");
251 }
252
253 @Override
254 public int drainTo(Collection<? super CallRunner> c) {
255 throw new UnsupportedOperationException("This class doesn't support anything,"
256 + " but take() and offer() methods");
257 }
258
259 @Override
260 public int drainTo(Collection<? super CallRunner> c, int maxElements) {
261 throw new UnsupportedOperationException("This class doesn't support anything,"
262 + " but take() and offer() methods");
263 }
264
265 @Override
266 public Iterator<CallRunner> iterator() {
267 throw new UnsupportedOperationException("This class doesn't support anything,"
268 + " but take() and offer() methods");
269 }
270
271 @Override
272 public boolean add(CallRunner callRunner) {
273 throw new UnsupportedOperationException("This class doesn't support anything,"
274 + " but take() and offer() methods");
275 }
276
277 @Override
278 public CallRunner remove() {
279 throw new UnsupportedOperationException("This class doesn't support anything,"
280 + " but take() and offer() methods");
281 }
282
283 @Override
284 public CallRunner element() {
285 throw new UnsupportedOperationException("This class doesn't support anything,"
286 + " but take() and offer() methods");
287 }
288
289 @Override
290 public boolean addAll(Collection<? extends CallRunner> c) {
291 throw new UnsupportedOperationException("This class doesn't support anything,"
292 + " but take() and offer() methods");
293 }
294
295 @Override
296 public boolean isEmpty() {
297 throw new UnsupportedOperationException("This class doesn't support anything,"
298 + " but take() and offer() methods");
299 }
300
301 @Override
302 public boolean containsAll(Collection<?> c) {
303 throw new UnsupportedOperationException("This class doesn't support anything,"
304 + " but take() and offer() methods");
305 }
306
307 @Override
308 public boolean removeAll(Collection<?> c) {
309 throw new UnsupportedOperationException("This class doesn't support anything,"
310 + " but take() and offer() methods");
311 }
312
313 @Override
314 public boolean retainAll(Collection<?> c) {
315 throw new UnsupportedOperationException("This class doesn't support anything,"
316 + " but take() and offer() methods");
317 }
318
319 @Override
320 public int remainingCapacity() {
321 throw new UnsupportedOperationException("This class doesn't support anything,"
322 + " but take() and offer() methods");
323 }
324
325 @Override
326 public void put(CallRunner callRunner) throws InterruptedException {
327 throw new UnsupportedOperationException("This class doesn't support anything,"
328 + " but take() and offer() methods");
329 }
330
331 @Override
332 public boolean offer(CallRunner callRunner, long timeout, TimeUnit unit)
333 throws InterruptedException {
334 throw new UnsupportedOperationException("This class doesn't support anything,"
335 + " but take() and offer() methods");
336 }
337 }