Issue 322: switched to Suppliers.memoizeWithExpiration

This commit is contained in:
Adrian Cole 2010-07-26 14:57:37 -07:00
parent 095ee36537
commit d476016bd5
8 changed files with 64 additions and 131 deletions

View File

@ -27,7 +27,6 @@ import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
import org.jclouds.atmosonline.saas.AtmosStorageClient;
import org.jclouds.atmosonline.saas.handlers.AtmosStorageClientErrorRetryHandler;
import org.jclouds.atmosonline.saas.handlers.ParseAtmosStorageErrorFromXmlContent;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.date.DateService;
import org.jclouds.date.TimeStamp;
import org.jclouds.http.HttpErrorHandler;
@ -40,6 +39,7 @@ import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.inject.Provides;
/**
@ -75,7 +75,7 @@ public class AtmosStorageRestClientModule extends RestClientModule<AtmosStorageC
@TimeStamp
Supplier<String> provideTimeStampCache(@Named(Constants.PROPERTY_SESSION_INTERVAL) long seconds,
final DateService dateService) {
return new ExpirableSupplier<String>(new Supplier<String>() {
return Suppliers.memoizeWithExpiration(new Supplier<String>() {
public String get() {
return dateService.rfc822DateFormat();
}

View File

@ -28,7 +28,6 @@ import org.jclouds.aws.config.AWSRestClientModule;
import org.jclouds.aws.s3.S3AsyncClient;
import org.jclouds.aws.s3.S3Client;
import org.jclouds.aws.s3.filters.RequestAuthorizeSignature;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.date.DateService;
import org.jclouds.date.TimeStamp;
import org.jclouds.http.RequiresHttp;
@ -36,6 +35,7 @@ import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.RequestSigner;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.inject.Provides;
import com.google.inject.Scopes;
@ -79,7 +79,7 @@ public class S3RestClientModule extends AWSRestClientModule<S3Client, S3AsyncCli
@Singleton
protected Supplier<String> provideTimeStampCache(@Named(Constants.PROPERTY_SESSION_INTERVAL) long seconds,
final DateService dateService) {
return new ExpirableSupplier<String>(new Supplier<String>() {
return Suppliers.memoizeWithExpiration(new Supplier<String>() {
public String get() {
return dateService.rfc822DateFormat();
}

View File

@ -26,7 +26,6 @@ import javax.inject.Named;
import org.jclouds.azure.storage.handlers.AzureStorageClientErrorRetryHandler;
import org.jclouds.azure.storage.handlers.ParseAzureStorageErrorFromXmlContent;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.date.DateService;
import org.jclouds.date.TimeStamp;
import org.jclouds.http.HttpErrorHandler;
@ -39,6 +38,7 @@ import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.inject.Provides;
/**
@ -67,7 +67,7 @@ public class AzureStorageRestClientModule<S, A> extends RestClientModule<S, A> {
@TimeStamp
protected Supplier<String> provideTimeStampCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
final DateService dateService) {
return new ExpirableSupplier<String>(new Supplier<String>() {
return Suppliers.memoizeWithExpiration(new Supplier<String>() {
public String get() {
return dateService.rfc822DateFormat();
}

View File

@ -31,7 +31,6 @@ import javax.inject.Singleton;
import org.jclouds.chef.handlers.ChefClientErrorRetryHandler;
import org.jclouds.chef.handlers.ChefErrorHandler;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.date.DateService;
import org.jclouds.date.TimeStamp;
import org.jclouds.encryption.EncryptionService;
@ -45,6 +44,7 @@ import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.inject.Provides;
/**
@ -77,7 +77,7 @@ public class BaseChefRestClientModule<S, A> extends RestClientModule<S, A> {
@Provides
@TimeStamp
Supplier<String> provideTimeStampCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds, final DateService dateService) {
return new ExpirableSupplier<String>(new Supplier<String>() {
return Suppliers.memoizeWithExpiration(new Supplier<String>() {
public String get() {
return dateService.iso8601SecondsDateFormat();
}

View File

@ -1,59 +0,0 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* 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.
* ====================================================================
*/
package org.jclouds.concurrent;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import com.google.common.base.Supplier;
/**
* Works in google app engine since it doesn't use threads.
*
* @author Adrian Cole
*/
public class ExpirableSupplier<V> implements Supplier<V> {
private final Supplier<V> supplier;
private final AtomicReference<V> currentValue;
private final AtomicLong trigger;
private final long expirationNanos;
public ExpirableSupplier(Supplier<V> supplier, long duration, TimeUnit unit) {
this.supplier = supplier;
this.expirationNanos = unit.toNanos(duration);
this.currentValue = new AtomicReference<V>(null);
trigger = new AtomicLong(System.nanoTime() + expirationNanos);
}
void updateIfExpired() {
V current = currentValue.get();
if (current == null || trigger.get() - System.nanoTime() <= 0) {
trigger.set(System.nanoTime() + expirationNanos);
// we always want the last one to win. think login session
currentValue.set(supplier.get());
}
}
public V get() {
updateIfExpired();
return currentValue.get();
}
}

View File

@ -25,7 +25,6 @@ import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.date.TimeStamp;
import org.jclouds.gogrid.GoGridAsyncClient;
import org.jclouds.gogrid.GoGridClient;
@ -49,6 +48,7 @@ import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Provides;
@ -61,14 +61,13 @@ import com.google.inject.Provides;
@RequiresHttp
@ConfiguresRestClient
public class GoGridRestClientModule extends RestClientModule<GoGridClient, GoGridAsyncClient> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap
.<Class<?>, Class<?>> builder()//
.put(GridServerClient.class, GridServerAsyncClient.class)//
.put(GridJobClient.class, GridJobAsyncClient.class)//
.put(GridIpClient.class, GridIpAsyncClient.class)//
.put(GridLoadBalancerClient.class, GridLoadBalancerAsyncClient.class)//
.put(GridImageClient.class, GridImageAsyncClient.class)//
.build();
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
.put(GridServerClient.class, GridServerAsyncClient.class)//
.put(GridJobClient.class, GridJobAsyncClient.class)//
.put(GridIpClient.class, GridIpAsyncClient.class)//
.put(GridLoadBalancerClient.class, GridLoadBalancerAsyncClient.class)//
.put(GridImageClient.class, GridImageAsyncClient.class)//
.build();
public GoGridRestClientModule() {
super(GoGridClient.class, GoGridAsyncClient.class, DELEGATE_MAP);
@ -86,7 +85,7 @@ public class GoGridRestClientModule extends RestClientModule<GoGridClient, GoGri
@Provides
@TimeStamp
Supplier<Long> provideTimeStampCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds) {
return new ExpirableSupplier<Long>(new Supplier<Long>() {
return Suppliers.memoizeWithExpiration(new Supplier<Long>() {
public Long get() {
return System.currentTimeMillis() / 1000;
}

View File

@ -28,7 +28,6 @@ import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.concurrent.RetryOnTimeOutExceptionSupplier;
import org.jclouds.date.TimeStamp;
import org.jclouds.http.RequiresHttp;
@ -41,6 +40,7 @@ import org.jclouds.rackspace.RackspaceAuthAsyncClient.AuthenticationResponse;
import org.jclouds.rest.AsyncClientFactory;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.base.Throwables;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.AbstractModule;
@ -79,7 +79,7 @@ public class RackspaceAuthenticationRestModule extends AbstractModule {
@Singleton
Supplier<AuthenticationResponse> provideAuthenticationResponseCache(final AsyncClientFactory factory,
@Named(Constants.PROPERTY_IDENTITY) final String user, @Named(Constants.PROPERTY_CREDENTIAL) final String key) {
return new ExpirableSupplier<AuthenticationResponse>(new RetryOnTimeOutExceptionSupplier<AuthenticationResponse>(
return Suppliers.memoizeWithExpiration(new RetryOnTimeOutExceptionSupplier<AuthenticationResponse>(
new Supplier<AuthenticationResponse>() {
public AuthenticationResponse get() {
try {
@ -99,7 +99,7 @@ public class RackspaceAuthenticationRestModule extends AbstractModule {
@Singleton
@TimeStamp
protected Supplier<Date> provideCacheBusterDate() {
return new ExpirableSupplier<Date>(new Supplier<Date>() {
return Suppliers.memoizeWithExpiration(new Supplier<Date>() {
public Date get() {
return new Date();
}

View File

@ -37,7 +37,6 @@ import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.concurrent.ExpirableSupplier;
import org.jclouds.concurrent.RetryOnTimeOutExceptionSupplier;
import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.RequiresHttp;
@ -73,20 +72,22 @@ import org.jclouds.vcloud.predicates.TaskSuccess;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.inject.Provides;
import com.google.inject.internal.Maps;
/**
* Configures the VCloud authentication service connection, including logging and http transport.
* Configures the VCloud authentication service connection, including logging
* and http transport.
*
* @author Adrian Cole
*/
@RequiresHttp
@ConfiguresRestClient
public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A extends VCloudAsyncClient>
extends RestClientModule<S, A> {
public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A extends VCloudAsyncClient> extends
RestClientModule<S, A> {
public BaseVCloudRestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
super(syncClientType, asyncClientType);
@ -104,7 +105,7 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides
@Singleton
protected Predicate<String> successTester(TaskSuccess success,
@Named(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED) long completed) {
@Named(PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED) long completed) {
return new RetryablePredicate<String>(success, completed);
}
@ -124,8 +125,7 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides
@Named("VDC_TO_ORG")
@Singleton
protected Map<String, String> provideVDCtoORG(@Org Iterable<NamedResource> orgs,
VCloudClient client) {
protected Map<String, String> provideVDCtoORG(@Org Iterable<NamedResource> orgs, VCloudClient client) {
Map<String, String> returnVal = Maps.newLinkedHashMap();
for (NamedResource orgr : orgs) {
for (NamedResource vdc : client.getOrganization(orgr.getId()).getVDCs().values()) {
@ -138,8 +138,7 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides
@Org
@Singleton
protected Iterable<NamedResource> provideOrgs(Supplier<VCloudSession> cache,
@Named(PROPERTY_IDENTITY) String user) {
protected Iterable<NamedResource> provideOrgs(Supplier<VCloudSession> cache, @Named(PROPERTY_IDENTITY) String user) {
VCloudSession discovery = cache.get();
checkState(discovery.getOrgs().size() > 0, "No orgs present for user: " + user);
return discovery.getOrgs().values();
@ -160,47 +159,44 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides
@Singleton
Supplier<VCloudSession> provideVCloudTokenCache(@Named(PROPERTY_SESSION_INTERVAL) long seconds,
final VCloudLoginAsyncClient login) {
return new ExpirableSupplier<VCloudSession>(
new RetryOnTimeOutExceptionSupplier<VCloudSession>(new Supplier<VCloudSession>() {
public VCloudSession get() {
// http://code.google.com/p/google-guice/issues/detail?id=483
// guice doesn't remember when singleton providers throw
// exceptions.
// in this case, if describeRegions fails, it is called
// again for
// each provider method that depends on it. To
// short-circuit this,
// we remember the last exception trusting that guice is
// single-threaded
if (authException != null)
throw authException;
try {
return login.login().get(10, TimeUnit.SECONDS);
} catch (AuthorizationException e) {
BaseVCloudRestClientModule.this.authException = e;
throw e;
} catch (Exception e) {
Throwables.propagate(e);
assert false : e;
return null;
}
final VCloudLoginAsyncClient login) {
return Suppliers.memoizeWithExpiration(new RetryOnTimeOutExceptionSupplier<VCloudSession>(
new Supplier<VCloudSession>() {
public VCloudSession get() {
// http://code.google.com/p/google-guice/issues/detail?id=483
// guice doesn't remember when singleton providers throw
// exceptions.
// in this case, if describeRegions fails, it is called
// again for
// each provider method that depends on it. To
// short-circuit this,
// we remember the last exception trusting that guice is
// single-threaded
if (authException != null)
throw authException;
try {
return login.login().get(10, TimeUnit.SECONDS);
} catch (AuthorizationException e) {
BaseVCloudRestClientModule.this.authException = e;
throw e;
} catch (Exception e) {
Throwables.propagate(e);
assert false : e;
return null;
}
}
}), seconds, TimeUnit.SECONDS);
}), seconds, TimeUnit.SECONDS);
}
@Provides
@Singleton
@org.jclouds.vcloud.endpoints.VCloudLogin
protected URI provideAuthenticationURI(VCloudVersionsAsyncClient versionService,
@Named(PROPERTY_API_VERSION) String version) throws InterruptedException,
ExecutionException, TimeoutException {
SortedMap<String, URI> versions = versionService.getSupportedVersions().get(180,
TimeUnit.SECONDS);
@Named(PROPERTY_API_VERSION) String version) throws InterruptedException, ExecutionException, TimeoutException {
SortedMap<String, URI> versions = versionService.getSupportedVersions().get(180, TimeUnit.SECONDS);
checkState(versions.size() > 0, "No versions present");
checkState(versions.containsKey(version), "version " + version + " not present in: "
+ versions);
checkState(versions.containsKey(version), "version " + version + " not present in: " + versions);
return versions.get(version);
}
@ -239,8 +235,8 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides
@Singleton
protected Organization provideOrganization(VCloudClient discovery) throws ExecutionException,
TimeoutException, InterruptedException {
protected Organization provideOrganization(VCloudClient discovery) throws ExecutionException, TimeoutException,
InterruptedException {
if (authException != null)
throw authException;
try {
@ -270,8 +266,8 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Provides
@Network
@Singleton
protected URI provideDefaultNetwork(VCloudClient client) throws InterruptedException,
ExecutionException, TimeoutException {
protected URI provideDefaultNetwork(VCloudClient client) throws InterruptedException, ExecutionException,
TimeoutException {
if (authException != null)
throw authException;
try {
@ -294,12 +290,9 @@ public abstract class BaseVCloudRestClientModule<S extends VCloudClient, A exten
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
ParseVCloudErrorFromHttpResponse.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
ParseVCloudErrorFromHttpResponse.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
ParseVCloudErrorFromHttpResponse.class);
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseVCloudErrorFromHttpResponse.class);
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseVCloudErrorFromHttpResponse.class);
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseVCloudErrorFromHttpResponse.class);
}
@Provides