/** * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.openflowplugin.impl.device; import com.google.common.base.Preconditions; import java.util.concurrent.atomic.AtomicInteger; import javax.annotation.concurrent.GuardedBy; abstract class SimpleRatelimiter { private final AtomicInteger counter = new AtomicInteger(); private int lowWatermark; private int lowWatermarkEffective; private int highWatermark; @GuardedBy("counter") private volatile boolean limited; SimpleRatelimiter(final int lowWatermark, final int highWatermark) { Preconditions.checkArgument(lowWatermark >= 0); Preconditions.checkArgument(highWatermark >= 0); Preconditions.checkArgument(lowWatermark <= highWatermark); this.lowWatermark = lowWatermark; this.highWatermark = highWatermark; lowWatermarkEffective = lowWatermark; } protected final boolean isLimited() { return limited; } protected abstract void disableFlow(); protected abstract void enableFlow(); boolean acquirePermit() { final int cnt = counter.incrementAndGet(); if (cnt > highWatermark) { synchronized (counter) { final int recheck = counter.decrementAndGet(); if (recheck >= highWatermark && !limited) { disableFlow(); limited = true; } } return false; } return true; } void releasePermit() { final int cnt = counter.decrementAndGet(); if (cnt <= lowWatermarkEffective) { synchronized (counter) { final int recheck = counter.get(); if (recheck <= lowWatermarkEffective && limited) { enableFlow(); limited = false; resetLowWaterMark(); } } } } void resetLowWaterMark() { synchronized (counter) { lowWatermarkEffective = lowWatermark; } } void adaptLowWaterMarkAndDisableFlow(int temporaryLowWaterMark) { if (temporaryLowWaterMark < highWatermark) { synchronized (counter) { lowWatermarkEffective = temporaryLowWaterMark; if (!limited) { disableFlow(); limited = true; } } } } int getOccupiedPermits() { return counter.get(); } void changeWaterMarks(final int newLowWatermark, final int newHighWatermark) { synchronized (counter) { lowWatermark = newLowWatermark; highWatermark = newHighWatermark; resetLowWaterMark(); } } }