diff --git a/src/java/com/samskivert/util/Throttle.java b/src/java/com/samskivert/util/Throttle.java index a73c35ae..c5530d8a 100644 --- a/src/java/com/samskivert/util/Throttle.java +++ b/src/java/com/samskivert/util/Throttle.java @@ -21,15 +21,13 @@ package com.samskivert.util; /** - * A throttle is used to prevent code from attempting a particular - * operation too often. Often it is desirable to retry an operation under - * failure conditions, but simplistic approaches to retrying operations - * can lead to large numbers of spurious attempts to do something that - * will obviously fail. The throttle class provides a mechanism for - * limiting such attempts by measuring whether or not an activity has been - * performed N times in the last M seconds. The user of the class decides - * the appropriate throttle parameters and then simply calls through to - * throttle to determine whether or not to go ahead with the operation. + * A throttle is used to prevent code from attempting a particular operation too often. Often it is + * desirable to retry an operation under failure conditions, but simplistic approaches to retrying + * operations can lead to large numbers of spurious attempts to do something that will obviously + * fail. The throttle class provides a mechanism for limiting such attempts by measuring whether or + * not an activity has been performed N times in the last M seconds. The user of the class decides + * the appropriate throttle parameters and then simply calls through to throttle to determine + * whether or not to go ahead with the operation. * *

For example: * @@ -50,17 +48,14 @@ package com.samskivert.util; public class Throttle { /** - * Constructs a new throttle instance that will allow the specified - * number of operations to proceed within the specified period (the - * period is measured in milliseconds). + * Constructs a new throttle instance that will allow the specified number of operations to + * proceed within the specified period (the period is measured in milliseconds). * - *

As operations and period define a ratio, use the smallest value - * possible for operations as an array is created to - * track the time at which each operation was performed (e.g. use 6 - * ops per 10 seconds rather than 60 ops per 100 seconds if - * possible). However, note that you may not always want to reduce the - * ratio as much as possible if you wish to allow bursts of operations - * up to some large value. + *

As operations and period define a ratio, use the smallest value possible for + * operations as an array is created to track the time at which each operation was + * performed (e.g. use 6 ops per 10 seconds rather than 60 ops per 100 seconds if + * possible). However, note that you may not always want to reduce the ratio as much as + * possible if you wish to allow bursts of operations up to some large value. */ public Throttle (int operations, long period) { @@ -69,13 +64,11 @@ public class Throttle } /** - * Registers an attempt at an operation and returns true if the - * operation should be performed or false if it should be throttled - * (meaning N operations have already been performed in the last M - * seconds). + * Registers an attempt at an operation and returns true if the operation should be performed + * or false if it should be throttled (meaning N operations have already been performed in the + * last M seconds). * - * @return true if the throttle is activated, false if the operation - * can proceed. + * @return true if the throttle is activated, false if the operation can proceed. */ public boolean throttleOp () { @@ -83,21 +76,16 @@ public class Throttle } /** - * Registers an attempt at an operation and returns true if the - * operation should be performed or false if it should be throttled - * (meaning N operations have already been performed in the last M - * seconds). For systems that don't wish to use {@link - * System#currentTimeMillis} (opting in favor for some custom timing - * mechanism that is more accurate that {@link - * System#currentTimeMillis}) or those that already have the time, - * they can avoid an unnecessary call to {@link - * System#currentTimeMillis} by using this version of the method. + * Registers an attempt at an operation and returns true if the operation should be performed + * or false if it should be throttled (meaning N operations have already been performed in the + * last M seconds). For systems that don't wish to use {@link System#currentTimeMillis} (opting + * in favor for some custom timing mechanism that is more accurate that {@link + * System#currentTimeMillis}) or those that already have the time, they can avoid an + * unnecessary call to {@link System#currentTimeMillis} by using this version of the method. * - * @param timeStamp the timestamp at which this operation is being - * attempted. + * @param timeStamp the timestamp at which this operation is being attempted. * - * @return true if the throttle is activated, false if the operation - * can proceed. + * @return true if the throttle is activated, false if the operation can proceed. */ public boolean throttleOp (long timeStamp) { @@ -110,36 +98,42 @@ public class Throttle } /** - * Check to see if we would throttle an operation occuring at the specified - * timestamp. Typically used in conjunction with {@link #noteOp}. + * Check to see if we would throttle an operation occuring at the specified timestamp. + * Typically used in conjunction with {@link #noteOp}. */ public boolean wouldThrottle (long timeStamp) { - // if the oldest operation was performed less than _period ago, we - // need to throttle + // if the oldest operation was performed less than _period ago, we need to throttle long elapsed = timeStamp - _ops[_lastOp]; - // if negative time elapsed, we must be running on windows. - // Let's just cope by not throttling. + // if negative time elapsed, we must be running on windows; let's just cope by not + // throttling return (elapsed >= 0 && elapsed < _period); } /** - * Note that an operation occurred at the specified timestamp. This - * method should be used with {@link #wouldThrottle} to note an operation - * that has already been cleared to occur. Typically this is used if - * there is another limiting factor besides the throttle that determines - * whether the operation can occur. You are responsible for calling this - * method in a safe and timely manner after using wouldThrottle. + * Note that an operation occurred at the specified timestamp. This method should be used with + * {@link #wouldThrottle} to note an operation that has already been cleared to + * occur. Typically this is used if there is another limiting factor besides the throttle that + * determines whether the operation can occur. You are responsible for calling this method in a + * safe and timely manner after using wouldThrottle. */ public void noteOp (long timeStamp) { - // overwrite the oldest operation with the current time - // and move the oldest operation pointer to the second oldest - // operation (which is now the oldest as we overwrote the oldest) + // overwrite the oldest operation with the current time and move the oldest operation + // pointer to the second oldest operation (which is now the oldest as we overwrote the + // oldest) _ops[_lastOp] = timeStamp; _lastOp = (_lastOp + 1) % _ops.length; } + /** + * Returns the timestamp of the most recently recorded operation. + */ + public long getLatestOperation () + { + return _ops[(_lastOp + _ops.length - 1) % _ops.length]; + } + /** * Used for testing. */ @@ -148,12 +142,10 @@ public class Throttle // set up a throttle for 5 ops per 10 seconds Throttle throttle = new Throttle(5, 10000); - // try doing one operation per second and we should hit the - // throttle on the sixth operation and then kick in again on the - // eleventh, only to stop again on the fifteenth + // try doing one operation per second and we should hit the throttle on the sixth operation + // and then kick in again on the eleventh, only to stop again on the fifteenth for (int i = 0; i < 20; i++) { - System.out.println((i+1) + ". Throttle: " + - throttle.throttleOp()); + System.out.println((i+1) + ". Throttle: " + throttle.throttleOp()); // pause for a sec try { Thread.sleep(1000L); } catch (InterruptedException ie) {}