mirror of https://github.com/apache/jclouds.git
removed copy/paste code relating to expiration after write
This commit is contained in:
parent
17fce87661
commit
07240f3e77
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rest.suppliers;
|
package org.jclouds.rest.suppliers;
|
||||||
|
|
||||||
import static org.jclouds.util.Suppliers2.memoizeWithExpirationOnAbsoluteInterval;
|
import static org.jclouds.util.Suppliers2.memoizeWithExpirationAfterWrite;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
@ -54,7 +54,7 @@ public class MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<T> imp
|
||||||
|
|
||||||
public MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier(
|
public MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier(
|
||||||
AtomicReference<AuthorizationException> authException, long seconds, Supplier<T> delegate) {
|
AtomicReference<AuthorizationException> authException, long seconds, Supplier<T> delegate) {
|
||||||
this.delegate = memoizeWithExpirationOnAbsoluteInterval(new RetryOnTimeOutExceptionSupplier<T>(
|
this.delegate = memoizeWithExpirationAfterWrite(new RetryOnTimeOutExceptionSupplier<T>(
|
||||||
new SetAndThrowAuthorizationExceptionSupplier<T>(delegate, authException)), seconds, TimeUnit.SECONDS);
|
new SetAndThrowAuthorizationExceptionSupplier<T>(delegate, authException)), seconds, TimeUnit.SECONDS);
|
||||||
this.seconds = seconds;
|
this.seconds = seconds;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,12 +26,14 @@ import java.io.Serializable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Suppliers;
|
import com.google.common.base.Suppliers;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import com.google.common.collect.ForwardingObject;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.io.OutputSupplier;
|
import com.google.common.io.OutputSupplier;
|
||||||
|
|
||||||
|
@ -57,7 +59,7 @@ public class Suppliers2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <X> Function<X, Supplier<X>> ofInstanceFunction() {
|
public static <X> Function<X, Supplier<X>> ofInstanceFunction() {
|
||||||
return new Function<X, Supplier<X>>(){
|
return new Function<X, Supplier<X>>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Supplier<X> apply(X arg0) {
|
public Supplier<X> apply(X arg0) {
|
||||||
|
@ -65,7 +67,7 @@ public class Suppliers2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString() {
|
||||||
return "Suppliers.ofInstance()";
|
return "Suppliers.ofInstance()";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -85,70 +87,43 @@ public class Suppliers2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See Supplier.memoizeWithExpiration.
|
* same as {@link Supplier.memoizeWithExpiration} except that the expiration ticker starts after
|
||||||
|
* write vs after call to {@code get}.
|
||||||
*
|
*
|
||||||
* Difference between this impl and v11.0 is that we fix
|
* @see Supplier.memoizeWithExpiration
|
||||||
* http://code.google.com/p/guava-libraries/issues/detail?id=857.
|
|
||||||
*/
|
*/
|
||||||
public static <T> Supplier<T> memoizeWithExpirationOnAbsoluteInterval(Supplier<T> delegate, long duration,
|
public static <T> Supplier<T> memoizeWithExpirationAfterWrite(Supplier<T> delegate, long duration, TimeUnit unit) {
|
||||||
TimeUnit unit) {
|
return new ExpireAfterWriteSupplier<T>(delegate, duration, unit);
|
||||||
return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
static class ExpireAfterWriteSupplier<T> extends ForwardingObject implements Supplier<T>, Serializable {
|
||||||
static class ExpiringMemoizingSupplier<T> implements Supplier<T>, Serializable {
|
private final Supplier<T> delegate;
|
||||||
final Supplier<T> delegate;
|
private final long duration;
|
||||||
final long durationNanos;
|
private final TimeUnit unit;
|
||||||
transient volatile T value;
|
private final LoadingCache<Object, T> cache;
|
||||||
// The special value 0 means "not yet initialized".
|
|
||||||
transient volatile long expirationNanos;
|
|
||||||
|
|
||||||
ExpiringMemoizingSupplier(Supplier<T> delegate, long duration, TimeUnit unit) {
|
public ExpireAfterWriteSupplier(Supplier<T> delegate, long duration, TimeUnit unit) {
|
||||||
this.delegate = Preconditions.checkNotNull(delegate);
|
this.delegate = delegate;
|
||||||
this.durationNanos = unit.toNanos(duration);
|
this.duration = duration;
|
||||||
Preconditions.checkArgument(duration > 0);
|
this.unit = unit;
|
||||||
|
cache = CacheBuilder.newBuilder().expireAfterWrite(duration, unit).build(CacheLoader.from(delegate));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Supplier<T> delegate() {
|
||||||
|
return delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T get() {
|
public T get() {
|
||||||
// Another variant of Double Checked Locking.
|
return cache.getUnchecked("FOO");
|
||||||
//
|
|
||||||
// We use two volatile reads. We could reduce this to one by
|
|
||||||
// putting our fields into a holder class, but (at least on x86)
|
|
||||||
// the extra memory consumption and indirection are more
|
|
||||||
// expensive than the extra volatile reads.
|
|
||||||
long nanos = expirationNanos;
|
|
||||||
long now = System.nanoTime();
|
|
||||||
if (nanos == 0 || now - nanos >= 0) {
|
|
||||||
synchronized (this) {
|
|
||||||
if (nanos == expirationNanos) { // recheck for lost race
|
|
||||||
|
|
||||||
// Set value to null prior to retrieving new val, so old and new are not held in
|
|
||||||
// memory simultaneously
|
|
||||||
value = null;
|
|
||||||
|
|
||||||
T t = delegate.get();
|
|
||||||
value = t;
|
|
||||||
|
|
||||||
// Update now so that, if call was expensive, we keep value for the full duration
|
|
||||||
now = System.nanoTime();
|
|
||||||
|
|
||||||
nanos = now + durationNanos;
|
|
||||||
// In the very unlikely event that nanos is 0, set it to 1;
|
|
||||||
// no one will notice 1 ns of tardiness.
|
|
||||||
expirationNanos = (nanos == 0) ? 1 : nanos;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final long serialVersionUID = 0;
|
private static final long serialVersionUID = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hashCode(delegate, durationNanos);
|
return Objects.hashCode(delegate, duration, unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -159,13 +134,14 @@ public class Suppliers2 {
|
||||||
return false;
|
return false;
|
||||||
if (getClass() != obj.getClass())
|
if (getClass() != obj.getClass())
|
||||||
return false;
|
return false;
|
||||||
ExpiringMemoizingSupplier<?> that = ExpiringMemoizingSupplier.class.cast(obj);
|
ExpireAfterWriteSupplier<?> that = ExpireAfterWriteSupplier.class.cast(obj);
|
||||||
return Objects.equal(delegate, that.delegate) && Objects.equal(durationNanos, that.durationNanos);
|
return Objects.equal(delegate, that.delegate) && Objects.equal(duration, that.duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return Objects.toStringHelper(this).add("delegate", delegate).add("durationNanos", durationNanos).toString();
|
return Objects.toStringHelper(this).add("delegate", delegate).add("duration", duration).add("unit", unit)
|
||||||
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class Suppliers2Test {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Supplier<Integer> memoizedSupplier = Suppliers2.memoizeWithExpirationOnAbsoluteInterval(
|
Supplier<Integer> memoizedSupplier = Suppliers2.memoizeWithExpirationAfterWrite(
|
||||||
slowSupplier, EXPIRATION_TIME, TimeUnit.MILLISECONDS);
|
slowSupplier, EXPIRATION_TIME, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
assertEquals(memoizedSupplier.get(), (Integer)10);
|
assertEquals(memoizedSupplier.get(), (Integer)10);
|
||||||
|
@ -100,7 +100,7 @@ public class Suppliers2Test {
|
||||||
public void testMemoizeWithExpiration() throws InterruptedException {
|
public void testMemoizeWithExpiration() throws InterruptedException {
|
||||||
CountingSupplier countingSupplier = new CountingSupplier();
|
CountingSupplier countingSupplier = new CountingSupplier();
|
||||||
|
|
||||||
Supplier<Integer> memoizedSupplier = Suppliers2.memoizeWithExpirationOnAbsoluteInterval(
|
Supplier<Integer> memoizedSupplier = Suppliers2.memoizeWithExpirationAfterWrite(
|
||||||
countingSupplier, 75, TimeUnit.MILLISECONDS);
|
countingSupplier, 75, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
checkExpiration(countingSupplier, memoizedSupplier);
|
checkExpiration(countingSupplier, memoizedSupplier);
|
||||||
|
@ -111,7 +111,7 @@ public class Suppliers2Test {
|
||||||
throws InterruptedException {
|
throws InterruptedException {
|
||||||
CountingSupplier countingSupplier = new CountingSupplier();
|
CountingSupplier countingSupplier = new CountingSupplier();
|
||||||
|
|
||||||
Supplier<Integer> memoizedSupplier = Suppliers2.memoizeWithExpirationOnAbsoluteInterval(
|
Supplier<Integer> memoizedSupplier = Suppliers2.memoizeWithExpirationAfterWrite(
|
||||||
countingSupplier, 75, TimeUnit.MILLISECONDS);
|
countingSupplier, 75, TimeUnit.MILLISECONDS);
|
||||||
// Calls to the original memoized supplier shouldn't affect its copy.
|
// Calls to the original memoized supplier shouldn't affect its copy.
|
||||||
memoizedSupplier.get();
|
memoizedSupplier.get();
|
||||||
|
@ -120,7 +120,7 @@ public class Suppliers2Test {
|
||||||
memoizedSupplier.get();
|
memoizedSupplier.get();
|
||||||
|
|
||||||
CountingSupplier countingCopy = (CountingSupplier)
|
CountingSupplier countingCopy = (CountingSupplier)
|
||||||
((Suppliers2.ExpiringMemoizingSupplier<Integer>) copy).delegate;
|
((Suppliers2.ExpireAfterWriteSupplier<Integer>) copy).delegate();
|
||||||
checkExpiration(countingCopy, copy);
|
checkExpiration(countingCopy, copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ public class Suppliers2Test {
|
||||||
Function<Supplier<Boolean>, Supplier<Boolean>> memoizer =
|
Function<Supplier<Boolean>, Supplier<Boolean>> memoizer =
|
||||||
new Function<Supplier<Boolean>, Supplier<Boolean>>() {
|
new Function<Supplier<Boolean>, Supplier<Boolean>>() {
|
||||||
@Override public Supplier<Boolean> apply(Supplier<Boolean> supplier) {
|
@Override public Supplier<Boolean> apply(Supplier<Boolean> supplier) {
|
||||||
return Suppliers2.memoizeWithExpirationOnAbsoluteInterval(
|
return Suppliers2.memoizeWithExpirationAfterWrite(
|
||||||
supplier, Long.MAX_VALUE, TimeUnit.NANOSECONDS);
|
supplier, Long.MAX_VALUE, TimeUnit.NANOSECONDS);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue