/*
* StreamCruncher: Copyright (c) 2006-2008, Ashwin Jayaprakash. All Rights Reserved.
* Contact: ashwin {dot} jayaprakash {at} gmail {dot} com
* Web: http://www.StreamCruncher.com
*
* This file is part of StreamCruncher.
*
* StreamCruncher is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* StreamCruncher is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with StreamCruncher. If not, see <http://www.gnu.org/licenses/>.
*/
package streamcruncher.kernel;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import streamcruncher.boot.Registry;
import streamcruncher.innards.InnardsManager;
import streamcruncher.innards.core.InstreamNotificationRendezvous;
import streamcruncher.innards.core.stream.InStream;
/*
* Author: Ashwin Jayaprakash Date: Apr 22, 2006 Time: 3:54:21 PM
*/
public class InstreamRowPollThrottler {
protected final int emptyRunsBeforePause;
protected final long pauseMsecs;
protected final Random random;
protected final InstreamNotificationRendezvous notificationRendezvous;
protected int runsWithoutSuccess;
public InstreamRowPollThrottler(int emptyRunsBeforePause, long pauseMsecs) {
this.emptyRunsBeforePause = emptyRunsBeforePause;
this.pauseMsecs = pauseMsecs;
this.random = new Random();
InnardsManager manager = Registry.getImplFor(InnardsManager.class);
this.notificationRendezvous = manager.getNotificationRendezvous();
}
// -----------------
/**
* Analyse Stream's rate of flow or Trend. Then, reward or penalize.
*
* @param rowsPickedUp
*/
public void afterProcess(int rowsPickedUp) {
if (rowsPickedUp > 0) {
// Speed up slowly.
runsWithoutSuccess = (int) (runsWithoutSuccess * 0.5);
}
else {
// Penalize.
runsWithoutSuccess++;
/*
* For [0 to 9] > 6, is [7, 8, 9] = 30% prob. Reduce penalty only
* 30% of the time.
*/
if (random.nextInt(10) > 6) {
runsWithoutSuccess = (int) (runsWithoutSuccess * 0.7);
}
}
}
/**
* @return {@link InStream} to process. <code>null</code> if nothing in
* particular to process.
*/
public InStream throttle() {
InStream inStreamToProcess = null;
if (runsWithoutSuccess >= emptyRunsBeforePause) {
/*
* "int" is used purposely to get exact multiples of
* emptyRunsBeforePause.
*/
int stepFactor = runsWithoutSuccess / emptyRunsBeforePause;
if (stepFactor > 0) {
inStreamToProcess = notificationRendezvous.awaitNotification(pauseMsecs
* stepFactor, TimeUnit.MILLISECONDS);
}
}
return inStreamToProcess;
}
}