mirror of https://github.com/apache/jclouds.git
Issue 322: switched to Suppliers.memoizeWithExpiration
This commit is contained in:
parent
095ee36537
commit
d476016bd5
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue