X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=datarouter-node%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Fdmaap%2Fdatarouter%2Fnode%2FRateLimitedOperation.java;fp=datarouter-node%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Fdmaap%2Fdatarouter%2Fnode%2FRateLimitedOperation.java;h=5890e193d3841163b5528e7aaa81c2e6ae759bbd;hb=e4b20cc6f7c31f48ddd0de5bcd054b09a35cd510;hp=0000000000000000000000000000000000000000;hpb=315f5603d8e42969a13d985ca8bb50146e82325a;p=dmaap%2Fdatarouter.git diff --git a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/RateLimitedOperation.java b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/RateLimitedOperation.java new file mode 100644 index 00000000..5890e193 --- /dev/null +++ b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/RateLimitedOperation.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * ============LICENSE_START================================================== + * * org.onap.dmaap + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ + + +package org.onap.dmaap.datarouter.node; + +import java.util.*; + +/** + * Execute an operation no more frequently than a specified interval + */ + +public abstract class RateLimitedOperation implements Runnable { + private boolean marked; // a timer task exists + private boolean executing; // the operation is currently in progress + private boolean remark; // a request was made while the operation was in progress + private Timer timer; + private long last; // when the last operation started + private long mininterval; + /** + * Create a rate limited operation + * @param mininterval The minimum number of milliseconds after the last execution starts before a new execution can begin + * @param timer The timer used to perform deferred executions + */ + public RateLimitedOperation(long mininterval, Timer timer) { + this.timer = timer; + this.mininterval = mininterval; + } + private class deferred extends TimerTask { + public void run() { + execute(); + } + } + private synchronized void unmark() { + marked = false; + } + private void execute() { + unmark(); + request(); + } + /** + * Request that the operation be performed by this thread or at a later time by the timer + */ + public void request() { + if (premark()) { + return; + } + do { + run(); + } while (demark()); + } + private synchronized boolean premark() { + if (executing) { + // currently executing - wait until it finishes + remark = true; + return(true); + } + if (marked) { + // timer currently running - will run when it expires + return(true); + } + long now = System.currentTimeMillis(); + if (last + mininterval > now) { + // too soon - schedule a timer + marked = true; + timer.schedule(new deferred(), last + mininterval - now); + return(true); + } + last = now; + executing = true; + // start execution + return(false); + } + private synchronized boolean demark() { + executing = false; + if (remark) { + remark = false; + return(!premark()); + } + return(false); + } +}