Make methods static
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / device / SimpleRatelimiter.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.openflowplugin.impl.device;
9
10 import com.google.common.base.Preconditions;
11 import java.util.concurrent.atomic.AtomicInteger;
12 import org.checkerframework.checker.lock.qual.GuardedBy;
13 import org.checkerframework.checker.lock.qual.Holding;
14
15 abstract class SimpleRatelimiter {
16     private final AtomicInteger counter = new AtomicInteger();
17     private final Object counterLock = new Object();
18     @GuardedBy("counterLock")
19     private int lowWatermark;
20     private volatile int lowWatermarkEffective;
21     private volatile int highWatermark;
22     @GuardedBy("counterLock")
23     private volatile boolean limited;
24
25     SimpleRatelimiter(final int lowWatermark, final int highWatermark) {
26         Preconditions.checkArgument(lowWatermark >= 0);
27         Preconditions.checkArgument(highWatermark >= 0);
28         Preconditions.checkArgument(lowWatermark <= highWatermark);
29
30         this.lowWatermark = lowWatermark;
31         this.highWatermark = highWatermark;
32         lowWatermarkEffective = lowWatermark;
33     }
34
35     protected final boolean isLimited() {
36         return limited;
37     }
38
39     protected abstract void disableFlow();
40
41     protected abstract void enableFlow();
42
43     boolean acquirePermit() {
44         final int cnt = counter.incrementAndGet();
45         if (cnt > highWatermark) {
46             synchronized (counterLock) {
47                 final int recheck = counter.decrementAndGet();
48                 if (recheck >= highWatermark && !limited) {
49                     disableFlow();
50                     limited = true;
51                 }
52             }
53             return false;
54         }
55
56         return true;
57     }
58
59     void releasePermit() {
60         final int cnt = counter.decrementAndGet();
61         if (cnt <= lowWatermarkEffective) {
62             synchronized (counterLock) {
63                 final int recheck = counter.get();
64                 if (recheck <= lowWatermarkEffective && limited) {
65                     enableFlow();
66                     limited = false;
67                     resetLowWaterMark();
68                 }
69             }
70         }
71     }
72
73     @Holding("counterLock")
74     private void resetLowWaterMark() {
75         lowWatermarkEffective = lowWatermark;
76     }
77
78     void adaptLowWaterMarkAndDisableFlow(int temporaryLowWaterMark) {
79         if (temporaryLowWaterMark < highWatermark) {
80             synchronized (counterLock) {
81                 lowWatermarkEffective = temporaryLowWaterMark;
82                 if (!limited) {
83                     disableFlow();
84                     limited = true;
85                 }
86             }
87         }
88     }
89
90     int getOccupiedPermits() {
91         return counter.get();
92     }
93
94     void changeWaterMarks(final int newLowWatermark, final int newHighWatermark) {
95         synchronized (counterLock) {
96             lowWatermark = newLowWatermark;
97             highWatermark = newHighWatermark;
98             resetLowWaterMark();
99         }
100     }
101 }