Merge pull request #1174 from jclouds/simplify-futures

use standard guava Futures and ListenableFuture
This commit is contained in:
Adrian Cole 2013-01-13 11:42:38 -08:00
commit 00cc1ce67d
121 changed files with 1304 additions and 2317 deletions

View File

@ -19,12 +19,12 @@
package org.jclouds.atmos.blobstore;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.transform;
import static org.jclouds.atmos.options.PutOptions.Builder.publicRead;
import java.net.URI;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
@ -56,7 +56,6 @@ import org.jclouds.blobstore.options.PutOptions;
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
import org.jclouds.blobstore.util.BlobUtils;
import org.jclouds.collect.Memoized;
import org.jclouds.concurrent.Futures;
import org.jclouds.crypto.Crypto;
import org.jclouds.domain.Location;
import org.jclouds.http.options.GetOptions;
@ -66,6 +65,7 @@ import com.google.common.base.Supplier;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -86,14 +86,14 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
@Inject
AtmosAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, Supplier<Location> defaultLocation,
@Memoized Supplier<Set<? extends Location>> locations, AtmosAsyncClient async, AtmosClient sync,
ObjectToBlob object2Blob, ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object,
BlobStoreListOptionsToListOptions container2ContainerListOptions,
DirectoryEntryListToResourceMetadataList container2ResourceList, Crypto crypto,
BlobToHttpGetOptions blob2ObjectGetOptions, Provider<FetchBlobMetadata> fetchBlobMetadataProvider,
LoadingCache<String, Boolean> isPublic) {
super(context, blobUtils, service, defaultLocation, locations);
super(context, blobUtils, userExecutor, defaultLocation, locations);
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
this.sync = checkNotNull(sync, "sync");
this.async = checkNotNull(async, "async");
@ -113,12 +113,12 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
*/
@Override
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
return Futures.compose(async.headFile(container + "/" + key), new Function<AtmosObject, BlobMetadata>() {
return transform(async.headFile(container + "/" + key), new Function<AtmosObject, BlobMetadata>() {
@Override
public BlobMetadata apply(AtmosObject from) {
return object2BlobMd.apply(from);
}
}, service);
}, userExecutor);
}
/**
@ -128,13 +128,11 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
*/
@Override
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container) {
return Futures.compose(async.createDirectory(container), new Function<URI, Boolean>() {
return transform(async.createDirectory(container), new Function<URI, Boolean>() {
public Boolean apply(URI from) {
return true;
}
}, service);
}, userExecutor);
}
/**
@ -142,13 +140,11 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
*/
@Override
public ListenableFuture<Void> createDirectory(String container, String directory) {
return Futures.compose(async.createDirectory(container + "/" + directory), new Function<URI, Void>() {
return transform(async.createDirectory(container + "/" + directory), new Function<URI, Void>() {
public Void apply(URI from) {
return null;// no etag
}
}, service);
}, userExecutor);
}
/**
@ -204,7 +200,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
public ListenableFuture<Blob> getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions options) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(options);
ListenableFuture<AtmosObject> returnVal = async.readFile(container + "/" + key, httpOptions);
return Futures.compose(returnVal, object2Blob, service);
return transform(returnVal, object2Blob, userExecutor);
}
/**
@ -212,7 +208,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
*/
@Override
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
return Futures.compose(async.listDirectories(), container2ResourceList, service);
return transform(async.listDirectories(), container2ResourceList, userExecutor);
}
/**
@ -224,10 +220,10 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
container = AtmosUtils.adjustContainerIfDirOptionPresent(container, options);
ListOptions nativeOptions = container2ContainerListOptions.apply(options);
ListenableFuture<BoundedSet<? extends DirectoryEntry>> returnVal = async.listDirectory(container, nativeOptions);
ListenableFuture<PageSet<? extends StorageMetadata>> list = Futures.compose(returnVal, container2ResourceList,
service);
return (ListenableFuture<PageSet<? extends StorageMetadata>>) (options.isDetailed() ? Futures.compose(list,
fetchBlobMetadataProvider.get().setContainerName(container), service) : list);
ListenableFuture<PageSet<? extends StorageMetadata>> list = transform(returnVal, container2ResourceList,
userExecutor);
return (ListenableFuture<PageSet<? extends StorageMetadata>>) (options.isDetailed() ? transform(list,
fetchBlobMetadataProvider.get().setContainerName(container)) : list);
}
/**
@ -244,7 +240,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
} catch (CacheLoader.InvalidCacheLoadException e) {
// nulls not permitted
}
return Futures.makeListenable(service.submit(new Callable<String>() {
return userExecutor.submit(new Callable<String>() {
@Override
public String call() throws Exception {
@ -255,7 +251,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
public String toString() {
return "putBlob(" + container + "," + blob.getMetadata().getName() + ")";
}
}), service);
});
}
@ -277,13 +273,13 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
public ListenableFuture<Boolean> createContainerInLocation(Location location, String container,
CreateContainerOptions options) {
if (options.isPublicRead())
return Futures.compose(async.createDirectory(container, publicRead()), new Function<URI, Boolean>() {
return transform(async.createDirectory(container, publicRead()), new Function<URI, Boolean>() {
public Boolean apply(URI from) {
return true;
}
}, service);
}, userExecutor);
return createContainerInLocation(location, container);
}

View File

@ -26,11 +26,9 @@ import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.annotation.Resource;
import javax.inject.Named;
@ -45,12 +43,12 @@ import org.jclouds.blobstore.internal.BlobRuntimeException;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
import org.jclouds.blobstore.strategy.ListBlobsInContainer;
import org.jclouds.concurrent.Futures;
import org.jclouds.logging.Logger;
import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
/**
@ -65,7 +63,7 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
protected final ObjectMD5 objectMD5;
protected final ListBlobsInContainer getAllBlobMetadata;
private final AtmosAsyncClient client;
private final ExecutorService userExecutor;
private final ListeningExecutorService userExecutor;
/**
* maximum duration of an blob Request
*/
@ -74,7 +72,7 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
protected Long maxTime;
@Inject
FindMD5InUserMetadata(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, ObjectMD5 objectMD5,
FindMD5InUserMetadata(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, ObjectMD5 objectMD5,
ListBlobsInContainer getAllBlobMetadata, AtmosAsyncClient client) {
this.objectMD5 = objectMD5;
this.getAllBlobMetadata = getAllBlobMetadata;
@ -86,10 +84,9 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
public boolean execute(final String containerName, Object value, ListContainerOptions options) {
final byte[] toSearch = objectMD5.apply(value);
final BlockingQueue<Boolean> queue = new SynchronousQueue<Boolean>();
Map<String, Future<?>> responses = Maps.newHashMap();
Map<String, ListenableFuture<?>> responses = Maps.newHashMap();
for (BlobMetadata md : getAllBlobMetadata.execute(containerName, options)) {
final ListenableFuture<AtmosObject> future = Futures.makeListenable(
client.headFile(containerName + "/" + md.getName()), userExecutor);
final ListenableFuture<AtmosObject> future = client.headFile(containerName + "/" + md.getName());
future.addListener(new Runnable() {
public void run() {
try {

View File

@ -24,7 +24,6 @@ import static com.google.common.util.concurrent.Futures.immediateFuture;
import java.net.URI;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
@ -47,12 +46,13 @@ import org.jclouds.blobstore.LocalAsyncBlobStore;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions;
import org.jclouds.concurrent.Futures;
import org.jclouds.http.options.GetOptions;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* Implementation of {@link AtmosAsyncClient} which keeps all data in a local Map object.
@ -68,13 +68,13 @@ public class StubAtmosAsyncClient implements AtmosAsyncClient {
private final BlobMetadataToObject blob2ObjectInfo;
private final ListOptionsToBlobStoreListOptions container2ContainerListOptions;
private final ResourceMetadataListToDirectoryEntryList resource2ObjectList;
private final ExecutorService service;
private final ListeningExecutorService userExecutor;
@Inject
private StubAtmosAsyncClient(LocalAsyncBlobStore blobStore, AtmosObject.Factory objectProvider,
HttpGetOptionsListToGetOptions httpGetOptionsConverter, ObjectToBlob object2Blob, BlobToObject blob2Object,
BlobMetadataToObject blob2ObjectInfo, ListOptionsToBlobStoreListOptions container2ContainerListOptions,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
ResourceMetadataListToDirectoryEntryList resource2ContainerList) {
this.blobStore = blobStore;
this.objectProvider = objectProvider;
@ -85,7 +85,7 @@ public class StubAtmosAsyncClient implements AtmosAsyncClient {
this.container2ContainerListOptions = checkNotNull(container2ContainerListOptions,
"container2ContainerListOptions");
this.resource2ObjectList = checkNotNull(resource2ContainerList, "resource2ContainerList");
this.service = service;
this.userExecutor = userExecutor;
}
@Override
@ -99,7 +99,7 @@ public class StubAtmosAsyncClient implements AtmosAsyncClient {
container = directoryName;
path = null;
}
return Futures.compose(blobStore.createContainerInLocation(null, container), new Function<Boolean, URI>() {
return Futures.transform(blobStore.createContainerInLocation(null, container), new Function<Boolean, URI>() {
public URI apply(Boolean from) {
if (path != null) {
@ -109,7 +109,7 @@ public class StubAtmosAsyncClient implements AtmosAsyncClient {
return URI.create("http://stub/containers/" + container);
}
}, service);
}, userExecutor);
}
@Override
@ -124,27 +124,27 @@ public class StubAtmosAsyncClient implements AtmosAsyncClient {
object.getContentMetadata().setName(path + "/" + file);
}
Blob blob = object2Blob.apply(object);
return Futures.compose(blobStore.putBlob(container, blob), new Function<String, URI>() {
return Futures.transform(blobStore.putBlob(container, blob), new Function<String, URI>() {
public URI apply(String from) {
return URI.create(uri);
}
}, service);
}, userExecutor);
}
@Override
public ListenableFuture<Void> deletePath(String path) {
if (path.indexOf('/') == path.length() - 1) {
// chop off the trailing slash
return Futures.compose(blobStore.deleteContainerIfEmpty(path.substring(0, path.length() - 1)),
return Futures.transform(blobStore.deleteContainerIfEmpty(path.substring(0, path.length() - 1)),
new Function<Boolean, Void>() {
public Void apply(Boolean from) {
return null;
}
}, service);
}, userExecutor);
} else {
String container = path.substring(0, path.indexOf('/'));
path = path.substring(path.indexOf('/') + 1);
@ -164,11 +164,11 @@ public class StubAtmosAsyncClient implements AtmosAsyncClient {
else {
String container = path.substring(0, path.indexOf('/'));
path = path.substring(path.indexOf('/') + 1);
return Futures.compose(blobStore.blobMetadata(container, path), new Function<BlobMetadata, UserMetadata>() {
return Futures.transform(blobStore.blobMetadata(container, path), new Function<BlobMetadata, UserMetadata>() {
public UserMetadata apply(BlobMetadata from) {
return blob2ObjectInfo.apply(from).getUserMetadata();
}
}, service);
}, userExecutor);
}
}
@ -177,7 +177,7 @@ public class StubAtmosAsyncClient implements AtmosAsyncClient {
String container = path.substring(0, path.indexOf('/'));
path = path.substring(path.indexOf('/') + 1);
try {
return Futures.compose(blobStore.getBlob(container, path), blob2Object, service);
return Futures.transform(blobStore.getBlob(container, path), blob2Object, userExecutor);
} catch (Exception e) {
return immediateFailedFuture(Throwables.getRootCause(e));
}
@ -187,7 +187,7 @@ public class StubAtmosAsyncClient implements AtmosAsyncClient {
public ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectories(ListOptions... optionsList) {
// org.jclouds.blobstore.options.ListOptions options = container2ContainerListOptions
// .apply(optionsList);
return Futures.compose(blobStore.list(), resource2ObjectList, service);
return Futures.transform(blobStore.list(), resource2ObjectList, userExecutor);
}
@Override
@ -201,7 +201,7 @@ public class StubAtmosAsyncClient implements AtmosAsyncClient {
if (!path.equals(""))
options.inDirectory(path);
}
return Futures.compose(blobStore.list(container, options), resource2ObjectList, service);
return Futures.transform(blobStore.list(container, options), resource2ObjectList, userExecutor);
}
@Override
@ -232,7 +232,7 @@ public class StubAtmosAsyncClient implements AtmosAsyncClient {
String container = path.substring(0, path.indexOf('/'));
String blobName = path.substring(path.indexOf('/') + 1);
org.jclouds.blobstore.options.GetOptions getOptions = httpGetOptionsConverter.apply(options);
return Futures.compose(blobStore.getBlob(container, blobName, getOptions), blob2Object, service);
return Futures.transform(blobStore.getBlob(container, blobName, getOptions), blob2Object, userExecutor);
}
@Override

View File

@ -18,8 +18,9 @@
*/
package org.jclouds.cloudfiles.blobstore;
import static com.google.common.util.concurrent.Futures.transform;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
@ -36,7 +37,6 @@ import org.jclouds.cloudfiles.CloudFilesAsyncClient;
import org.jclouds.cloudfiles.CloudFilesClient;
import org.jclouds.cloudfiles.blobstore.functions.EnableCDNAndCache;
import org.jclouds.collect.Memoized;
import org.jclouds.concurrent.Futures;
import org.jclouds.domain.Location;
import org.jclouds.openstack.swift.blobstore.SwiftAsyncBlobStore;
import org.jclouds.openstack.swift.blobstore.functions.BlobStoreListContainerOptionsToListContainerOptions;
@ -45,11 +45,12 @@ import org.jclouds.openstack.swift.blobstore.functions.ContainerToResourceList;
import org.jclouds.openstack.swift.blobstore.functions.ContainerToResourceMetadata;
import org.jclouds.openstack.swift.blobstore.functions.ObjectToBlob;
import org.jclouds.openstack.swift.blobstore.functions.ObjectToBlobMetadata;
import org.jclouds.openstack.swift.blobstore.strategy.internal.AsyncMultipartUploadStrategy;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.util.concurrent.ListenableFuture;
import org.jclouds.openstack.swift.blobstore.strategy.internal.AsyncMultipartUploadStrategy;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
*
@ -61,7 +62,7 @@ public class CloudFilesAsyncBlobStore extends SwiftAsyncBlobStore {
@Inject
protected CloudFilesAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, Supplier<Location> defaultLocation,
@Memoized Supplier<Set<? extends Location>> locations, CloudFilesClient sync, CloudFilesAsyncClient async,
ContainerToResourceMetadata container2ResourceMd,
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,
@ -69,7 +70,7 @@ public class CloudFilesAsyncBlobStore extends SwiftAsyncBlobStore {
ObjectToBlobMetadata object2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions,
Provider<FetchBlobMetadata> fetchBlobMetadataProvider, EnableCDNAndCache enableCDNAndCache,
Provider<AsyncMultipartUploadStrategy> multipartUploadStrategy) {
super(context, blobUtils, service, defaultLocation, locations, sync, async, container2ResourceMd,
super(context, blobUtils, userExecutor, defaultLocation, locations, sync, async, container2ResourceMd,
container2ContainerListOptions, container2ResourceList, object2Blob, blob2Object, object2BlobMd,
blob2ObjectGetOptions, fetchBlobMetadataProvider, multipartUploadStrategy);
this.enableCDNAndCache = enableCDNAndCache;
@ -81,7 +82,7 @@ public class CloudFilesAsyncBlobStore extends SwiftAsyncBlobStore {
ListenableFuture<Boolean> returnVal = createContainerInLocation(location, container);
if (options.isPublicRead())
return Futures.compose(createContainerInLocation(location, container), new Function<Boolean, Boolean>() {
return transform(createContainerInLocation(location, container), new Function<Boolean, Boolean>() {
@Override
public Boolean apply(Boolean input) {
@ -91,7 +92,7 @@ public class CloudFilesAsyncBlobStore extends SwiftAsyncBlobStore {
return false;
}
}, service);
}, userExecutor);
return returnVal;
}
}

View File

@ -24,7 +24,6 @@ import static com.google.common.base.Preconditions.checkState;
import java.util.NoSuchElementException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
@ -41,12 +40,12 @@ import org.jclouds.compute.domain.ImageTemplate;
import org.jclouds.compute.domain.ImageTemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.concurrent.Futures;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.PredicateWithResult;
import org.jclouds.predicates.Retryables;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* CloudServers implementation of {@link ImageExtension}
@ -62,7 +61,7 @@ public class CloudServersImageExtension implements ImageExtension {
protected Logger logger = Logger.NULL;
private final CloudServersClient client;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
private final PredicateWithResult<Integer, Image> imageAvailablePredicate;
@com.google.inject.Inject(optional = true)
@Named("IMAGE_MAX_WAIT")
@ -73,11 +72,11 @@ public class CloudServersImageExtension implements ImageExtension {
@Inject
public CloudServersImageExtension(CloudServersClient client,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
PredicateWithResult<Integer, Image> imageAvailablePredicate) {
this.client = checkNotNull(client);
this.executor = userThreads;
this.imageAvailablePredicate = imageAvailablePredicate;
this.client = checkNotNull(client, "client");
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
this.imageAvailablePredicate = checkNotNull(imageAvailablePredicate, "imageAvailablePredicate");
}
@Override
@ -96,14 +95,14 @@ public class CloudServersImageExtension implements ImageExtension {
CloneImageTemplate cloneTemplate = (CloneImageTemplate) template;
final org.jclouds.cloudservers.domain.Image image = client.createImageFromServer(cloneTemplate.getName(),
Integer.parseInt(cloneTemplate.getSourceNodeId()));
return Futures.makeListenable(executor.submit(new Callable<Image>() {
return userExecutor.submit(new Callable<Image>() {
@Override
public Image call() throws Exception {
return Retryables.retryGettingResultOrFailing(imageAvailablePredicate, image.getId(), maxWait, waitPeriod,
TimeUnit.SECONDS, "Image was not created within the time limit, Giving up! [Limit: " + maxWait
+ " secs.]");
}
}), executor);
});
}

View File

@ -22,9 +22,6 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -66,6 +63,8 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.UncheckedExecutionException;
/**
@ -89,7 +88,7 @@ public class CloudSigmaComputeServiceAdapter implements
private final Predicate<DriveInfo> driveNotClaimed;
private final String defaultVncPassword;
private final LoadingCache<String, DriveInfo> cache;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
@ -98,13 +97,13 @@ public class CloudSigmaComputeServiceAdapter implements
@Inject
public CloudSigmaComputeServiceAdapter(CloudSigmaClient client, Predicate<DriveInfo> driveNotClaimed,
@Named(CloudSigmaConstants.PROPERTY_VNC_PASSWORD) String defaultVncPassword,
LoadingCache<String, DriveInfo> cache, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
LoadingCache<String, DriveInfo> cache, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.client = checkNotNull(client, "client");
this.driveNotClaimed = checkNotNull(driveNotClaimed, "driveNotClaimed");
this.defaultVncPassword = checkNotNull(defaultVncPassword, "defaultVncPassword");
checkArgument(defaultVncPassword.length() <= 8, "vnc passwords should be less that 8 characters!");
this.cache = checkNotNull(cache, "cache");
this.executor = checkNotNull(executor, "executor");
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
}
@Override
@ -171,10 +170,10 @@ public class CloudSigmaComputeServiceAdapter implements
@Override
public Iterable<DriveInfo> listImages() {
return FluentIterable.from(transformParallel(client.listStandardDrives(),
new Function<String, Future<? extends DriveInfo>>() {
new Function<String, ListenableFuture<? extends DriveInfo>>() {
@Override
public Future<DriveInfo> apply(String input) {
public ListenableFuture<DriveInfo> apply(String input) {
try {
return Futures.immediateFuture(cache.getUnchecked(input));
} catch (CacheLoader.InvalidCacheLoadException e) {
@ -189,7 +188,7 @@ public class CloudSigmaComputeServiceAdapter implements
public String toString() {
return "seedDriveCache()";
}
}, executor, null, logger, "drives")).filter(PREINSTALLED_DISK);
}, userExecutor, null, logger, "drives")).filter(PREINSTALLED_DISK);
}
@SuppressWarnings("unchecked")

View File

@ -35,7 +35,6 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Named;
@ -96,6 +95,7 @@ import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
/**
@ -124,7 +124,7 @@ public class EC2ComputeService extends BaseComputeService {
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client client,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, EC2Client client,
ConcurrentMap<RegionAndName, KeyPair> credentialsMap,
@Named("SECURITY") LoadingCache<RegionAndName, String> securityGroupMap,
Optional<ImageExtension> imageExtension, GroupNamingConvention.Factory namingConvention,
@ -133,7 +133,7 @@ public class EC2ComputeService extends BaseComputeService {
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, executor, imageExtension);
persistNodeCredentials, timeouts, userExecutor, imageExtension);
this.client = client;
this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap;

View File

@ -24,7 +24,6 @@ import static com.google.common.base.Preconditions.checkState;
import java.util.NoSuchElementException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
@ -39,7 +38,6 @@ import org.jclouds.compute.domain.ImageTemplate;
import org.jclouds.compute.domain.ImageTemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.concurrent.Futures;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.domain.Reservation;
import org.jclouds.ec2.domain.RunningInstance;
@ -50,6 +48,7 @@ import org.jclouds.predicates.Retryables;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* EC2 implementation of {@link ImageExtension} please note that {@link #createImage(ImageTemplate)}
@ -64,7 +63,7 @@ public class EC2ImageExtension implements ImageExtension {
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final EC2Client ec2Client;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
private final PredicateWithResult<String, Image> imageReadyPredicate;
@com.google.inject.Inject(optional = true)
@Named("IMAGE_MAX_WAIT")
@ -74,10 +73,10 @@ public class EC2ImageExtension implements ImageExtension {
private long waitPeriod = 1;
@Inject
public EC2ImageExtension(EC2Client ec2Client, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
public EC2ImageExtension(EC2Client ec2Client, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
PredicateWithResult<String, Image> imageReadyPredicate) {
this.ec2Client = checkNotNull(ec2Client);
this.executor = checkNotNull(userThreads);
this.userExecutor = checkNotNull(userExecutor);
this.imageReadyPredicate = imageReadyPredicate;
}
@ -105,14 +104,14 @@ public class EC2ImageExtension implements ImageExtension {
final String imageId = ec2Client.getAMIServices().createImageInRegion(region, cloneTemplate.getName(),
instanceId, CreateImageOptions.NONE);
return Futures.makeListenable(executor.submit(new Callable<Image>() {
return userExecutor.submit(new Callable<Image>() {
@Override
public Image call() throws Exception {
return Retryables.retryGettingResultOrFailing(imageReadyPredicate, region + "/" + imageId, maxWait,
waitPeriod, TimeUnit.SECONDS, "Image was not created within the time limit, Giving up! [Limit: "
+ maxWait + " secs.]");
}
}), executor);
});
}
@Override

View File

@ -23,8 +23,6 @@ import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -38,6 +36,8 @@ import org.jclouds.ec2.options.DescribeImagesOptions;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
*
@ -51,13 +51,12 @@ public class DescribeImagesParallel implements
protected Logger logger = Logger.NULL;
protected final EC2AsyncClient async;
final ExecutorService executor;
final ListeningExecutorService userExecutor;
@Inject
public DescribeImagesParallel(EC2AsyncClient async, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
super();
public DescribeImagesParallel(EC2AsyncClient async, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.async = async;
this.executor = executor;
this.userExecutor = userExecutor;
}
@Override
@ -65,15 +64,11 @@ public class DescribeImagesParallel implements
Iterable<Entry<String, DescribeImagesOptions>> queries) {
return concat(transformParallel(
queries,
new Function<Entry<String, DescribeImagesOptions>, Future<? extends Set<? extends org.jclouds.ec2.domain.Image>>>() {
@Override
public Future<Set<? extends org.jclouds.ec2.domain.Image>> apply(
new Function<Entry<String, DescribeImagesOptions>, ListenableFuture<? extends Set<? extends org.jclouds.ec2.domain.Image>>>() {
public ListenableFuture<Set<? extends org.jclouds.ec2.domain.Image>> apply(
Entry<String, DescribeImagesOptions> from) {
return async.getAMIServices().describeImagesInRegion(from.getKey(), from.getValue());
}
}, executor, null, logger, "amis"));
}, userExecutor, null, logger, "amis"));
}
}

View File

@ -30,7 +30,6 @@ import static org.jclouds.ec2.compute.util.EC2ComputeUtils.getZoneFromLocationOr
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Resource;
@ -65,6 +64,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListenableFuture;
/**
* creates futures that correlate to
@ -129,7 +129,7 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
};
@Override
public Map<?, Future<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
public Map<?, ListenableFuture<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
Template mutableTemplate = template.clone();

View File

@ -27,8 +27,6 @@ import static com.google.common.collect.Iterables.transform;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Named;
@ -50,6 +48,8 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
/**
@ -70,16 +70,16 @@ public class EC2ListNodesStrategy implements ListNodesStrategy {
protected final EC2AsyncClient client;
protected final Supplier<Set<String>> regions;
protected final Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata;
protected final ExecutorService executor;
protected final ListeningExecutorService userExecutor;
@Inject
protected EC2ListNodesStrategy(EC2AsyncClient client, @Region Supplier<Set<String>> regions,
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.client = checkNotNull(client, "client");
this.regions = checkNotNull(regions, "regions");
this.runningInstanceToNodeMetadata = checkNotNull(runningInstanceToNodeMetadata, "runningInstanceToNodeMetadata");
this.executor = checkNotNull(executor, "executor");
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
}
@Override
@ -97,21 +97,14 @@ public class EC2ListNodesStrategy implements ListNodesStrategy {
protected Iterable<? extends RunningInstance> pollRunningInstances() {
Iterable<? extends Set<? extends Reservation<? extends RunningInstance>>> reservations = transformParallel(
regions.get(), new Function<String, Future<? extends Set<? extends Reservation<? extends RunningInstance>>>>() {
regions.get(), new Function<String, ListenableFuture<? extends Set<? extends Reservation<? extends RunningInstance>>>>() {
@Override
public Future<Set<? extends Reservation<? extends RunningInstance>>> apply(String from) {
// see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7126754
return castToSpecificTypedFuture(client.getInstanceServices().describeInstancesInRegion(from));
public ListenableFuture<? extends Set<? extends Reservation<? extends RunningInstance>>> apply(String from) {
return client.getInstanceServices().describeInstancesInRegion(from);
}
}, executor, maxTime, logger, "reservations");
}, userExecutor, maxTime, logger, "reservations");
return concat(concat(reservations));
}
@SuppressWarnings("unchecked")
private static <T> Future<T> castToSpecificTypedFuture(Future<? extends T> input) {
return (Future<T>) input;
}
}

View File

@ -25,8 +25,6 @@ import static org.jclouds.concurrent.FutureIterables.transformParallel;
import static org.jclouds.elasticstack.util.Servers.small;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -67,6 +65,8 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.UncheckedExecutionException;
/**
@ -82,7 +82,7 @@ public class ElasticStackComputeServiceAdapter implements
private final Map<String, WellKnownImage> preinstalledImages;
private final LoadingCache<String, DriveInfo> cache;
private final String defaultVncPassword;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
@ -92,14 +92,14 @@ public class ElasticStackComputeServiceAdapter implements
public ElasticStackComputeServiceAdapter(ElasticStackClient client, Predicate<DriveInfo> driveNotClaimed,
Map<String, WellKnownImage> preinstalledImages, LoadingCache<String, DriveInfo> cache,
@Named(ElasticStackConstants.PROPERTY_VNC_PASSWORD) String defaultVncPassword,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.client = checkNotNull(client, "client");
this.driveNotClaimed = checkNotNull(driveNotClaimed, "driveNotClaimed");
this.preinstalledImages = checkNotNull(preinstalledImages, "preinstalledImages");
this.cache = checkNotNull(cache, "cache");
this.defaultVncPassword = checkNotNull(defaultVncPassword, "defaultVncPassword");
checkArgument(defaultVncPassword.length() <= 8, "vnc passwords should be less that 8 characters!");
this.executor = checkNotNull(executor, "executor");
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
}
@Override
@ -164,10 +164,10 @@ public class ElasticStackComputeServiceAdapter implements
@Override
public Iterable<DriveInfo> listImages() {
return FluentIterable.from(transformParallel(preinstalledImages.keySet(),
new Function<String, Future<? extends DriveInfo>>() {
new Function<String, ListenableFuture<? extends DriveInfo>>() {
@Override
public Future<? extends DriveInfo> apply(String input) {
public ListenableFuture<? extends DriveInfo> apply(String input) {
try {
return Futures.immediateFuture(cache.getUnchecked(input));
} catch (CacheLoader.InvalidCacheLoadException e) {
@ -183,7 +183,7 @@ public class ElasticStackComputeServiceAdapter implements
return "seedDriveCache()";
}
}, executor, null, logger, "drives")).filter(notNull());
}, userExecutor, null, logger, "drives")).filter(notNull());
}
@SuppressWarnings("unchecked")

View File

@ -25,7 +25,6 @@ import static org.jclouds.openstack.nova.v2_0.predicates.KeyPairPredicates.nameM
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject;
@ -77,6 +76,7 @@ import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -104,7 +104,7 @@ public class NovaComputeService extends BaseComputeService {
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, NovaApi novaApi,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, NovaApi novaApi,
LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupMap,
LoadingCache<ZoneAndName, KeyPair> keyPairCache,
Function<Set<? extends NodeMetadata>, Multimap<String, String>> orphanedGroupsByZoneId,
@ -113,7 +113,7 @@ public class NovaComputeService extends BaseComputeService {
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, executor, imageExtension);
persistNodeCredentials, timeouts, userExecutor, imageExtension);
this.novaApi = checkNotNull(novaApi, "novaApi");
this.securityGroupMap = checkNotNull(securityGroupMap, "securityGroupMap");
this.keyPairCache = checkNotNull(keyPairCache, "keyPairCache");

View File

@ -24,7 +24,6 @@ import static com.google.common.base.Preconditions.checkState;
import java.util.NoSuchElementException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
@ -39,7 +38,6 @@ import org.jclouds.compute.domain.ImageTemplate;
import org.jclouds.compute.domain.ImageTemplateBuilder;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.concurrent.Futures;
import org.jclouds.logging.Logger;
import org.jclouds.openstack.nova.v2_0.NovaApi;
import org.jclouds.openstack.nova.v2_0.domain.Server;
@ -48,6 +46,7 @@ import org.jclouds.predicates.PredicateWithResult;
import org.jclouds.predicates.Retryables;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* Nova implementation of {@link ImageExtension}
@ -63,7 +62,7 @@ public class NovaImageExtension implements ImageExtension {
protected Logger logger = Logger.NULL;
private final NovaApi novaApi;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@com.google.inject.Inject(optional = true)
@Named("IMAGE_MAX_WAIT")
private long maxWait = 3600;
@ -74,10 +73,10 @@ public class NovaImageExtension implements ImageExtension {
@Inject
public NovaImageExtension(NovaApi novaApi,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
PredicateWithResult<ZoneAndId, Image> imageReadyPredicate) {
this.novaApi = checkNotNull(novaApi);
this.executor = userThreads;
this.userExecutor = userExecutor;
this.imageReadyPredicate = imageReadyPredicate;
}
@ -105,14 +104,14 @@ public class NovaImageExtension implements ImageExtension {
logger.info(">> Registered new Image %s, waiting for it to become available.", newImageId);
return Futures.makeListenable(executor.submit(new Callable<Image>() {
return userExecutor.submit(new Callable<Image>() {
@Override
public Image call() throws Exception {
return Retryables.retryGettingResultOrFailing(imageReadyPredicate, targetImageZoneAndId, maxWait,
waitPeriod, TimeUnit.SECONDS, "Image was not created within the time limit, Giving up! [Limit: "
+ maxWait + " secs.]");
}
}), executor);
});
}
@Override

View File

@ -26,8 +26,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject;
@ -43,7 +41,6 @@ import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
import org.jclouds.concurrent.Futures;
import org.jclouds.openstack.nova.v2_0.NovaApi;
import org.jclouds.openstack.nova.v2_0.compute.functions.AllocateAndAddFloatingIpToNode;
import org.jclouds.openstack.nova.v2_0.compute.options.NovaTemplateOptions;
@ -56,6 +53,9 @@ import com.google.common.base.Throwables;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Multimap;
import com.google.common.primitives.Ints;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
*
@ -76,11 +76,11 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
ListNodesStrategy listNodesStrategy,
GroupNamingConvention.Factory namingConvention,
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
AllocateAndAddFloatingIpToNode createAndAddFloatingIpToNode,
LoadingCache<ZoneAndName, SecurityGroupInZone> securityGroupCache,
LoadingCache<ZoneAndName, KeyPair> keyPairCache, NovaApi novaApi) {
super(addNodeWithTagStrategy, listNodesStrategy, namingConvention, executor,
super(addNodeWithTagStrategy, listNodesStrategy, namingConvention, userExecutor,
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
this.securityGroupCache = checkNotNull(securityGroupCache, "securityGroupCache");
this.keyPairCache = checkNotNull(keyPairCache, "keyPairCache");
@ -90,7 +90,7 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
}
@Override
public Map<?, Future<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
public Map<?, ListenableFuture<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
Template mutableTemplate = template.clone();
@ -149,14 +149,14 @@ public class ApplyNovaTemplateOptionsCreateNodesWithGroupEncodedIntoNameThenAddT
}
@Override
protected Future<AtomicReference<NodeMetadata>> createNodeInGroupWithNameAndTemplate(String group,
protected ListenableFuture<AtomicReference<NodeMetadata>> createNodeInGroupWithNameAndTemplate(String group,
final String name, Template template) {
Future<AtomicReference<NodeMetadata>> future = super.createNodeInGroupWithNameAndTemplate(group, name, template);
ListenableFuture<AtomicReference<NodeMetadata>> future = super.createNodeInGroupWithNameAndTemplate(group, name, template);
NovaTemplateOptions templateOptions = NovaTemplateOptions.class.cast(template.getOptions());
if (templateOptions.shouldAutoAssignFloatingIp()) {
return Futures.compose(future, createAndAddFloatingIpToNode, executor);
return Futures.transform(future, createAndAddFloatingIpToNode, userExecutor);
} else {
return future;
}

View File

@ -21,26 +21,20 @@ package org.jclouds.rackspace.cloudloadbalancers.loadbalancer.strategy;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.loadbalancer.domain.LoadBalancerMetadata;
import org.jclouds.loadbalancer.reference.LoadBalancerConstants;
import org.jclouds.loadbalancer.strategy.ListLoadBalancersStrategy;
import org.jclouds.location.Zone;
import org.jclouds.logging.Logger;
import org.jclouds.rackspace.cloudloadbalancers.CloudLoadBalancersApi;
import org.jclouds.rackspace.cloudloadbalancers.domain.LoadBalancer;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Sets;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
/**
*
@ -48,38 +42,25 @@ import com.google.common.collect.Sets;
*/
@Singleton
public class CloudLoadBalancersListLoadBalancersStrategy implements ListLoadBalancersStrategy {
@Resource
@Named(LoadBalancerConstants.LOADBALANCER_LOGGER)
protected Logger logger = Logger.NULL;
private final CloudLoadBalancersApi aclient;
private final Function<LoadBalancer, LoadBalancerMetadata> converter;
private final ExecutorService executor; // leaving this here for possible future parallelization
private final Supplier<Set<String>> zones;
@Inject
protected CloudLoadBalancersListLoadBalancersStrategy(CloudLoadBalancersApi aclient,
Function<LoadBalancer, LoadBalancerMetadata> converter,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, @Zone Supplier<Set<String>> zones) {
Function<LoadBalancer, LoadBalancerMetadata> converter, @Zone Supplier<Set<String>> zones) {
this.aclient = checkNotNull(aclient, "aclient");
this.zones = checkNotNull(zones, "zones");
this.converter = checkNotNull(converter, "converter");
this.executor = checkNotNull(executor, "executor");
}
@Override
public Iterable<? extends LoadBalancerMetadata> listLoadBalancers() {
Set<LoadBalancerMetadata> loadBalancerMetadatas = Sets.newHashSet();
for (String zone: zones.get()) {
FluentIterable<LoadBalancerMetadata> lbm =
aclient.getLoadBalancerApiForZone(zone).list().concat().transform(converter);
for (LoadBalancerMetadata loadBalancerMetadata: lbm) {
loadBalancerMetadatas.add(loadBalancerMetadata);
}
}
return loadBalancerMetadatas;
Builder<LoadBalancerMetadata> loadBalancers = ImmutableSet.<LoadBalancerMetadata> builder();
for (String zone : zones.get()) { // TODO: parallel
loadBalancers.addAll(aclient.getLoadBalancerApiForZone(zone).list().concat().transform(converter));
}
return loadBalancers.build();
}
}

View File

@ -19,6 +19,9 @@
package org.jclouds.s3;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.jclouds.http.options.GetOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.s3.domain.AccessControlList;

View File

@ -19,9 +19,9 @@
package org.jclouds.s3.blobstore;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.transform;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
@ -42,7 +42,6 @@ import org.jclouds.blobstore.options.PutOptions;
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
import org.jclouds.blobstore.util.BlobUtils;
import org.jclouds.collect.Memoized;
import org.jclouds.concurrent.Futures;
import org.jclouds.domain.Location;
import org.jclouds.http.options.GetOptions;
import org.jclouds.s3.S3AsyncClient;
@ -69,6 +68,7 @@ import com.google.common.base.Supplier;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
*
@ -91,14 +91,14 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
@Inject
protected S3AsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, Supplier<Location> defaultLocation,
@Memoized Supplier<Set<? extends Location>> locations, S3AsyncClient async, S3Client sync,
Function<Set<BucketMetadata>, PageSet<? extends StorageMetadata>> convertBucketsToStorageMetadata,
ContainerToBucketListOptions container2BucketListOptions, BucketToResourceList bucket2ResourceList,
ObjectToBlob object2Blob, BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object,
ObjectToBlobMetadata object2BlobMd, Provider<FetchBlobMetadata> fetchBlobMetadataProvider,
LoadingCache<String, AccessControlList> bucketAcls) {
super(context, blobUtils, service, defaultLocation, locations);
super(context, blobUtils, userExecutor, defaultLocation, locations);
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
this.async = checkNotNull(async, "async");
this.sync = checkNotNull(sync, "sync");
@ -117,12 +117,12 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
*/
@Override
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
return Futures.compose(async.listOwnedBuckets(),
return transform(async.listOwnedBuckets(),
new Function<Set<BucketMetadata>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(Set<BucketMetadata> from) {
return convertBucketsToStorageMetadata.apply(from);
}
}, service);
}, userExecutor);
}
/**
@ -156,14 +156,14 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
* bucket name
*/
@Override
// TODO get rid of compose, as it serializes async results when the executor is single-threaded.
// TODO get rid of transform, as it serializes async results when the executor is single-threaded.
public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container, ListContainerOptions options) {
ListBucketOptions httpOptions = container2BucketListOptions.apply(options);
ListenableFuture<ListBucketResponse> returnVal = async.listBucket(container, httpOptions);
ListenableFuture<PageSet<? extends StorageMetadata>> list = Futures.compose(returnVal, bucket2ResourceList,
service);
return (options.isDetailed()) ? Futures.compose(list,
fetchBlobMetadataProvider.get().setContainerName(container), service) : list;
ListenableFuture<PageSet<? extends StorageMetadata>> list = transform(returnVal, bucket2ResourceList,
userExecutor);
return (options.isDetailed()) ? transform(list,
fetchBlobMetadataProvider.get().setContainerName(container), userExecutor) : list;
}
/**
@ -196,14 +196,14 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
*/
@Override
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
return Futures.compose(async.headObject(container, key), new Function<ObjectMetadata, BlobMetadata>() {
return transform(async.headObject(container, key), new Function<ObjectMetadata, BlobMetadata>() {
@Override
public BlobMetadata apply(ObjectMetadata from) {
return object2BlobMd.apply(from);
}
}, service);
}, userExecutor);
}
/**
@ -217,7 +217,7 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
@Override
public ListenableFuture<Blob> getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions options) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(options);
return Futures.compose(async.getObject(container, key, httpOptions), object2Blob, service);
return transform(async.getObject(container, key, httpOptions), object2Blob, userExecutor);
}
/**

View File

@ -22,8 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -39,6 +37,8 @@ import org.jclouds.logging.Logger;
import org.jclouds.s3.domain.BucketMetadata;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
@Singleton
public class BucketsToStorageMetadata implements
@ -47,11 +47,11 @@ public class BucketsToStorageMetadata implements
@Resource
protected Logger logger = Logger.NULL;
private final ExecutorService userExecutor;
private final ListeningExecutorService userExecutor;
private final BucketToResourceMetadata bucket2ResourceMd;
@Inject
public BucketsToStorageMetadata(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, BucketToResourceMetadata bucket2ResourceMd) {
public BucketsToStorageMetadata(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, BucketToResourceMetadata bucket2ResourceMd) {
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
this.bucket2ResourceMd = checkNotNull(bucket2ResourceMd, "bucket2ResourceMd");
}
@ -62,9 +62,9 @@ public class BucketsToStorageMetadata implements
// parallel as listing buckets is slow when looking up regions
Iterable<? extends StorageMetadata> buckets = FutureIterables
.<BucketMetadata, StorageMetadata> transformParallel(input,
new Function<BucketMetadata, Future<? extends StorageMetadata>>() {
new Function<BucketMetadata, ListenableFuture<? extends StorageMetadata>>() {
@Override
public Future<? extends StorageMetadata> apply(final BucketMetadata from) {
public ListenableFuture<? extends StorageMetadata> apply(final BucketMetadata from) {
return userExecutor.submit(new Callable<StorageMetadata>() {
@Override

View File

@ -24,12 +24,11 @@ import static org.jclouds.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCK
import java.net.URI;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.handlers.ParseAWSErrorFromXmlContent;
import org.jclouds.aws.util.AWSUtils;
@ -40,6 +39,9 @@ import org.jclouds.http.HttpResponse;
import org.jclouds.rest.ResourceNotFoundException;
import org.jclouds.s3.S3ApiMetadata;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
/**
* @author Adrian Cole
*

View File

@ -23,6 +23,7 @@ import static org.jclouds.http.Uris.uriBuilder;
import static org.jclouds.util.SaxUtils.currentOrNull;
import java.util.regex.Pattern;
import javax.inject.Inject;
import org.jclouds.date.DateService;

View File

@ -36,7 +36,6 @@ import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReleasePayloadAndReturn;
import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.options.GetOptions;
import com.google.common.reflect.Invokable;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.s3.S3Fallbacks.TrueOn404OrNotFoundFalseOnIllegalState;
@ -71,6 +70,7 @@ import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.reflect.Invokable;
import com.google.inject.Module;
/**

View File

@ -43,13 +43,13 @@ import java.util.concurrent.TimeoutException;
import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
import org.jclouds.http.HttpResponseException;
import org.jclouds.s3.domain.AccessControlList;
import org.jclouds.s3.domain.CannedAccessPolicy;
import org.jclouds.s3.domain.ObjectMetadata;
import org.jclouds.s3.domain.S3Object;
import org.jclouds.s3.domain.AccessControlList.CanonicalUserGrantee;
import org.jclouds.s3.domain.AccessControlList.EmailAddressGrantee;
import org.jclouds.s3.domain.AccessControlList.GroupGranteeURI;
import org.jclouds.s3.domain.AccessControlList.Permission;
import org.jclouds.s3.domain.CannedAccessPolicy;
import org.jclouds.s3.domain.ObjectMetadata;
import org.jclouds.s3.domain.S3Object;
import org.jclouds.s3.options.PutObjectOptions;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;

View File

@ -21,13 +21,13 @@ package org.jclouds.s3.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static com.google.common.util.concurrent.Futures.transform;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
@ -44,7 +44,6 @@ import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.util.BlobStoreUtils;
import org.jclouds.concurrent.Futures;
import org.jclouds.date.DateService;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
@ -78,6 +77,7 @@ import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* Implementation of {@link S3AsyncBlobStore} which keeps all data in a local Map object.
@ -99,17 +99,17 @@ public class StubS3AsyncClient implements S3AsyncClient {
private final ResourceToBucketList resource2BucketList;
private final ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs;
private final ConcurrentMap<String, Location> containerToLocation;
private final ExecutorService service;
private final ListeningExecutorService userExecutor;
@Inject
private StubS3AsyncClient(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
private StubS3AsyncClient(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
LocalAsyncBlobStore blobStore, ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
ConcurrentMap<String, Location> containerToLocation, DateService dateService,
S3Object.Factory objectProvider, Blob.Factory blobProvider,
HttpGetOptionsListToGetOptions httpGetOptionsConverter, ObjectToBlob object2Blob, BlobToObject blob2Object,
BlobToObjectMetadata blob2ObjectMetadata, BucketToContainerListOptions bucket2ContainerListOptions,
ResourceToBucketList resource2BucketList) {
this.service = service;
this.userExecutor = userExecutor;
this.containerToBlobs = containerToBlobs;
this.containerToLocation = containerToLocation;
this.blobStore = blobStore;
@ -146,7 +146,7 @@ public class StubS3AsyncClient implements S3AsyncClient {
public ListenableFuture<ListBucketResponse> listBucket(final String name, ListBucketOptions... optionsList) {
ListContainerOptions options = bucket2ContainerListOptions.apply(optionsList);
return Futures.compose(blobStore.list(name, options), resource2BucketList, service);
return transform(blobStore.list(name, options), resource2BucketList, userExecutor);
}
public ListenableFuture<ObjectMetadata> copyObject(final String sourceBucket, final String sourceObject,
@ -274,16 +274,15 @@ public class StubS3AsyncClient implements S3AsyncClient {
public ListenableFuture<S3Object> getObject(final String bucketName, final String key, final GetOptions... options) {
org.jclouds.blobstore.options.GetOptions getOptions = httpGetOptionsConverter.apply(options);
return Futures.compose(blobStore.getBlob(bucketName, key, getOptions), blob2Object, service);
return transform(blobStore.getBlob(bucketName, key, getOptions), blob2Object, userExecutor);
}
public ListenableFuture<ObjectMetadata> headObject(String bucketName, String key) {
return Futures.compose(blobStore.blobMetadata(bucketName, key), new Function<BlobMetadata, ObjectMetadata>() {
@Override
return transform(blobStore.blobMetadata(bucketName, key), new Function<BlobMetadata, ObjectMetadata>() {
public ObjectMetadata apply(BlobMetadata from) {
return blob2ObjectMetadata.apply(from);
}
}, service);
}, userExecutor);
}
public ListenableFuture<? extends Set<BucketMetadata>> listOwnedBuckets() {

View File

@ -19,10 +19,10 @@
package org.jclouds.openstack.swift.blobstore;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.transform;
import static org.jclouds.blobstore.util.BlobStoreUtils.createParentIfNeededAsync;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
@ -44,7 +44,6 @@ import org.jclouds.blobstore.options.PutOptions;
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
import org.jclouds.blobstore.util.BlobUtils;
import org.jclouds.collect.Memoized;
import org.jclouds.concurrent.Futures;
import org.jclouds.domain.Location;
import org.jclouds.http.options.GetOptions;
import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
@ -65,6 +64,7 @@ import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
*
@ -86,7 +86,7 @@ public class SwiftAsyncBlobStore extends BaseAsyncBlobStore {
@Inject
protected SwiftAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, Supplier<Location> defaultLocation,
@Memoized Supplier<Set<? extends Location>> locations, CommonSwiftClient sync,
CommonSwiftAsyncClient async, ContainerToResourceMetadata container2ResourceMd,
BlobStoreListContainerOptionsToListContainerOptions container2ContainerListOptions,
@ -94,7 +94,7 @@ public class SwiftAsyncBlobStore extends BaseAsyncBlobStore {
ObjectToBlobMetadata object2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions,
Provider<FetchBlobMetadata> fetchBlobMetadataProvider,
Provider<AsyncMultipartUploadStrategy> multipartUploadStrategy) {
super(context, blobUtils, service, defaultLocation, locations);
super(context, blobUtils, userExecutor, defaultLocation, locations);
this.sync = sync;
this.async = async;
this.container2ResourceMd = container2ResourceMd;
@ -113,13 +113,13 @@ public class SwiftAsyncBlobStore extends BaseAsyncBlobStore {
*/
@Override
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
return Futures.compose(async.listContainers(),
return transform(async.listContainers(),
new Function<Set<ContainerMetadata>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(
Set<ContainerMetadata> from) {
return new PageSetImpl<StorageMetadata>(Iterables.transform(from, container2ResourceMd), null);
}
}, service);
}, userExecutor);
}
/**
@ -152,10 +152,10 @@ public class SwiftAsyncBlobStore extends BaseAsyncBlobStore {
org.jclouds.openstack.swift.options.ListContainerOptions httpOptions = container2ContainerListOptions
.apply(options);
ListenableFuture<PageSet<ObjectInfo>> returnVal = async.listObjects(container, httpOptions);
ListenableFuture<PageSet<? extends StorageMetadata>> list = Futures.compose(returnVal, container2ResourceList,
service);
return options.isDetailed() ? Futures.compose(list, fetchBlobMetadataProvider.get().setContainerName(container),
service) : list;
ListenableFuture<PageSet<? extends StorageMetadata>> list = transform(returnVal, container2ResourceList,
userExecutor);
return options.isDetailed() ? transform(list, fetchBlobMetadataProvider.get().setContainerName(container),
userExecutor) : list;
}
/**
@ -181,7 +181,7 @@ public class SwiftAsyncBlobStore extends BaseAsyncBlobStore {
*/
@Override
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
return Futures.compose(async.getObjectInfo(container, key),
return transform(async.getObjectInfo(container, key),
new Function<MutableObjectInfoWithMetadata, BlobMetadata>() {
@Override
@ -189,7 +189,7 @@ public class SwiftAsyncBlobStore extends BaseAsyncBlobStore {
return object2BlobMd.apply(from);
}
}, service);
}, userExecutor);
}
/**
@ -204,7 +204,7 @@ public class SwiftAsyncBlobStore extends BaseAsyncBlobStore {
public ListenableFuture<Blob> getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions options) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(options);
ListenableFuture<SwiftObject> returnVal = async.getObject(container, key, httpOptions);
return Futures.compose(returnVal, object2Blob, service);
return transform(returnVal, object2Blob, userExecutor);
}
/**

View File

@ -1,27 +1,7 @@
package org.jclouds.openstack.swift.blobstore.strategy.internal;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Inject;
import org.jclouds.Constants;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.internal.BlobRuntimeException;
import org.jclouds.blobstore.options.PutOptions;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.concurrent.Futures;
import org.jclouds.io.Payload;
import org.jclouds.io.PayloadSlicer;
import org.jclouds.logging.Logger;
import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
import org.jclouds.openstack.swift.CommonSwiftClient;
import org.jclouds.openstack.swift.SwiftApiMetadata;
import org.jclouds.openstack.swift.blobstore.SwiftAsyncBlobStore;
import org.jclouds.openstack.swift.blobstore.functions.BlobToObject;
import org.jclouds.util.Throwables2;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource;
import javax.inject.Named;
import java.util.Map;
import java.util.Queue;
import java.util.SortedMap;
@ -33,11 +13,32 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.internal.BlobRuntimeException;
import org.jclouds.blobstore.options.PutOptions;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.io.Payload;
import org.jclouds.io.PayloadSlicer;
import org.jclouds.logging.Logger;
import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
import org.jclouds.openstack.swift.CommonSwiftClient;
import org.jclouds.openstack.swift.SwiftApiMetadata;
import org.jclouds.openstack.swift.blobstore.SwiftAsyncBlobStore;
import org.jclouds.openstack.swift.blobstore.functions.BlobToObject;
import org.jclouds.util.Throwables2;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
public class ParallelMultipartUploadStrategy implements AsyncMultipartUploadStrategy {
@Resource
@ -74,17 +75,17 @@ public class ParallelMultipartUploadStrategy implements AsyncMultipartUploadStra
@Named(Constants.PROPERTY_REQUEST_TIMEOUT)
protected Long maxTime;
private final ExecutorService ioWorkerExecutor;
private final ListeningExecutorService ioExecutor;
protected final SwiftAsyncBlobStore ablobstore;
protected final PayloadSlicer slicer;
@Inject
public ParallelMultipartUploadStrategy(SwiftAsyncBlobStore ablobstore, PayloadSlicer slicer,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioWorkerExecutor) {
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor) {
this.ablobstore = checkNotNull(ablobstore, "ablobstore");
this.slicer = checkNotNull(slicer, "slicer");
this.ioWorkerExecutor = checkNotNull(ioWorkerExecutor, "ioWorkerExecutor");
this.ioExecutor = checkNotNull(ioExecutor, "ioExecutor");
}
@ -136,14 +137,13 @@ public class ParallelMultipartUploadStrategy implements AsyncMultipartUploadStra
latch.countDown();
}
}
}, ioWorkerExecutor);
}, ioExecutor);
futureParts.put(part, futureETag);
}
@Override
public ListenableFuture<String> execute(final String container, final Blob blob, final PutOptions options, final BlobToObject blob2Object) {
return Futures.makeListenable(
ioWorkerExecutor.submit(new Callable<String>() {
return ioExecutor.submit(new Callable<String>() {
@Override
public String call() throws Exception {
String key = blob.getMetadata().getName();
@ -235,7 +235,7 @@ public class ParallelMultipartUploadStrategy implements AsyncMultipartUploadStra
futureETag.get(maxTime, TimeUnit.SECONDS) : futureETag.get();
}
}
}), ioWorkerExecutor);
});
}
class Part {

View File

@ -20,13 +20,13 @@ package org.jclouds.openstack.swift.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static com.google.common.util.concurrent.Futures.transform;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
@ -39,7 +39,6 @@ import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.concurrent.Futures;
import org.jclouds.http.options.GetOptions;
import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
import org.jclouds.openstack.swift.SwiftAsyncClient;
@ -60,6 +59,7 @@ import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* Implementation of {@link SwiftAsyncClient} which keeps all data in a local Map object.
@ -76,16 +76,16 @@ public class StubSwiftAsyncClient implements CommonSwiftAsyncClient {
private final ResourceToObjectInfo blob2ObjectInfo;
private final ListContainerOptionsToBlobStoreListContainerOptions container2ContainerListOptions;
private final ResourceToObjectList resource2ObjectList;
private final ExecutorService service;
private final ListeningExecutorService userExecutor;
@Inject
private StubSwiftAsyncClient(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
private StubSwiftAsyncClient(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
LocalAsyncBlobStore blobStore,
SwiftObject.Factory objectProvider, HttpGetOptionsListToGetOptions httpGetOptionsConverter,
ObjectToBlob object2Blob, BlobToObject blob2Object, ResourceToObjectInfo blob2ObjectInfo,
ListContainerOptionsToBlobStoreListContainerOptions container2ContainerListOptions,
ResourceToObjectList resource2ContainerList) {
this.service = service;
this.userExecutor = userExecutor;
this.blobStore = blobStore;
this.objectProvider = objectProvider;
this.httpGetOptionsConverter = httpGetOptionsConverter;
@ -127,11 +127,11 @@ public class StubSwiftAsyncClient implements CommonSwiftAsyncClient {
public ListenableFuture<SwiftObject> getObject(String container, String key, GetOptions... options) {
org.jclouds.blobstore.options.GetOptions getOptions = httpGetOptionsConverter.apply(options);
return Futures.compose(blobStore.getBlob(container, key, getOptions), blob2Object, service);
return transform(blobStore.getBlob(container, key, getOptions), blob2Object, userExecutor);
}
public ListenableFuture<MutableObjectInfoWithMetadata> getObjectInfo(String container, String key) {
return Futures.compose(blobStore.blobMetadata(container, key),
return transform(blobStore.blobMetadata(container, key),
new Function<BlobMetadata, MutableObjectInfoWithMetadata>() {
@Override
@ -140,7 +140,7 @@ public class StubSwiftAsyncClient implements CommonSwiftAsyncClient {
return blob2ObjectInfo.apply(from);
}
}, service);
}, userExecutor);
}
public ListenableFuture<? extends Set<ContainerMetadata>> listContainers(
@ -181,7 +181,7 @@ public class StubSwiftAsyncClient implements CommonSwiftAsyncClient {
public ListenableFuture<PageSet<ObjectInfo>> listObjects(String container,
org.jclouds.openstack.swift.options.ListContainerOptions... optionsList) {
ListContainerOptions options = container2ContainerListOptions.apply(optionsList);
return Futures.compose(blobStore.list(container, options), resource2ObjectList, service);
return transform(blobStore.list(container, options), resource2ObjectList, userExecutor);
}
public ListenableFuture<Boolean> copyObject(String sourceContainer, String sourceObject, String destinationContainer, String destinationObject) {

View File

@ -21,9 +21,6 @@ package org.jclouds.vcloud.functions;
import static com.google.common.collect.Iterables.filter;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -39,6 +36,8 @@ import org.jclouds.vcloud.domain.ReferenceType;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -49,27 +48,25 @@ public class CatalogItemsInCatalog implements Function<Catalog, Iterable<Catalog
public Logger logger = Logger.NULL;
private final VCloudAsyncClient aclient;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
CatalogItemsInCatalog(VCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
CatalogItemsInCatalog(VCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.aclient = aclient;
this.executor = executor;
this.userExecutor = userExecutor;
}
@Override
public Iterable<CatalogItem> apply(Catalog from) {
return transformParallel(filter(from.values(), new Predicate<ReferenceType>() {
@Override
public boolean apply(ReferenceType input) {
return input.getType().equals(VCloudMediaType.CATALOGITEM_XML);
}
}), new Function<ReferenceType, Future<? extends CatalogItem>>() {
@Override
public Future<CatalogItem> apply(ReferenceType from) {
}), new Function<ReferenceType, ListenableFuture<? extends CatalogItem>>() {
public ListenableFuture<CatalogItem> apply(ReferenceType from) {
return aclient.getCatalogClient().getCatalogItem(from.getHref());
}
}, executor, null, logger, "catalogItems in " + from.getHref());
}, userExecutor, null, logger, "catalogItems in " + from.getHref());
}
}

View File

@ -20,9 +20,6 @@ package org.jclouds.vcloud.functions;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -36,6 +33,8 @@ import org.jclouds.vcloud.domain.Org;
import org.jclouds.vcloud.domain.ReferenceType;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -46,21 +45,20 @@ public class CatalogsInOrg implements Function<Org, Iterable<Catalog>> {
public Logger logger = Logger.NULL;
private final VCloudAsyncClient aclient;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
CatalogsInOrg(VCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
CatalogsInOrg(VCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.aclient = aclient;
this.executor = executor;
this.userExecutor = userExecutor;
}
@Override
public Iterable<Catalog> apply(final Org org) {
return transformParallel(org.getCatalogs().values(), new Function<ReferenceType, Future<? extends Catalog>>() {
@Override
public Future<Catalog> apply(ReferenceType from) {
return transformParallel(org.getCatalogs().values(), new Function<ReferenceType, ListenableFuture<? extends Catalog>>() {
public ListenableFuture<Catalog> apply(ReferenceType from) {
return aclient.getCatalogClient().getCatalog(from.getHref());
}
}, executor, null, logger, "catalogs in " + org.getName());
}, userExecutor, null, logger, "catalogs in " + org.getName());
}
}

View File

@ -20,9 +20,6 @@ package org.jclouds.vcloud.functions;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -36,6 +33,8 @@ import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.domain.network.OrgNetwork;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -46,22 +45,21 @@ public class NetworksInOrg implements Function<Org, Iterable<OrgNetwork>> {
public Logger logger = Logger.NULL;
private final VCloudAsyncClient aclient;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
NetworksInOrg(VCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
NetworksInOrg(VCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.aclient = aclient;
this.executor = executor;
this.userExecutor = userExecutor;
}
@Override
public Iterable<OrgNetwork> apply(final Org org) {
return transformParallel(org.getNetworks().values(), new Function<ReferenceType, Future<? extends OrgNetwork>>() {
@Override
public Future<? extends OrgNetwork> apply(ReferenceType from) {
return transformParallel(org.getNetworks().values(), new Function<ReferenceType, ListenableFuture<? extends OrgNetwork>>() {
public ListenableFuture<? extends OrgNetwork> apply(ReferenceType from) {
return aclient.getNetworkClient().getNetwork(from.getHref());
}
}, executor, null, logger, "OrgNetworks in org " + org.getName());
}, userExecutor, null, logger, "OrgNetworks in org " + org.getName());
}
}

View File

@ -21,8 +21,6 @@ package org.jclouds.vcloud.functions;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.net.URI;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -39,6 +37,8 @@ import org.jclouds.vcloud.domain.Org;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -48,12 +48,12 @@ public class OrgsForLocations implements Function<Iterable<Location>, Iterable<O
@Resource
public Logger logger = Logger.NULL;
private final VCloudAsyncClient aclient;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
OrgsForLocations(VCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
OrgsForLocations(VCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.aclient = aclient;
this.executor = executor;
this.userExecutor = userExecutor;
}
/**
@ -63,22 +63,19 @@ public class OrgsForLocations implements Function<Iterable<Location>, Iterable<O
@Override
public Iterable<Org> apply(Iterable<Location> from) {
FluentIterable<URI> uris = FluentIterable.from(from).filter(new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getScope() == LocationScope.ZONE;
}
}).transform(new Function<Location, URI>() {
@Override
public URI apply(Location from) {
return URI.create(from.getParent().getId());
}
});
return transformParallel(uris, new Function<URI, Future<? extends Org>>() {
@Override
public Future<Org> apply(URI from) {
return transformParallel(uris, new Function<URI, ListenableFuture<? extends Org>>() {
public ListenableFuture<Org> apply(URI from) {
return aclient.getOrgClient().getOrg(from);
}
}, executor, null, logger, "organizations for uris");
}, userExecutor, null, logger, "organizations for uris");
}
}

View File

@ -20,9 +20,6 @@ package org.jclouds.vcloud.functions;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -36,6 +33,8 @@ import org.jclouds.vcloud.domain.Org;
import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -45,24 +44,21 @@ public class OrgsForNames implements Function<Iterable<String>, Iterable<Org>> {
@Resource
public Logger logger = Logger.NULL;
private final VCloudAsyncClient aclient;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
OrgsForNames(VCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
OrgsForNames(VCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.aclient = aclient;
this.executor = executor;
this.userExecutor = userExecutor;
}
@Override
public Iterable<Org> apply(Iterable<String> from) {
return Iterables.filter(transformParallel(from, new Function<String, Future<? extends Org>>() {
@Override
public Future<Org> apply(String from) {
return Iterables.filter(transformParallel(from, new Function<String, ListenableFuture<? extends Org>>() {
public ListenableFuture<Org> apply(String from) {
return aclient.getOrgClient().findOrgNamed(from);
}
}, executor, null, logger, "organizations for names"), Predicates.notNull());
}, userExecutor, null, logger, "organizations for names"), Predicates.notNull());
}
}

View File

@ -22,9 +22,6 @@ import static com.google.common.collect.Iterables.filter;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -40,6 +37,8 @@ import org.jclouds.vcloud.domain.VAppTemplate;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -50,32 +49,26 @@ public class VAppTemplatesForCatalogItems implements Function<Iterable<CatalogIt
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
private Logger logger = Logger.NULL;
private final VCloudAsyncClient aclient;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
VAppTemplatesForCatalogItems(VCloudAsyncClient aclient, @Named(PROPERTY_USER_THREADS) ExecutorService executor) {
VAppTemplatesForCatalogItems(VCloudAsyncClient aclient, @Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.aclient = aclient;
this.executor = executor;
this.userExecutor = userExecutor;
}
@Override
public Iterable<VAppTemplate> apply(Iterable<CatalogItem> from) {
return filter(transformParallel(filter(from, new Predicate<CatalogItem>() {
@Override
public boolean apply(CatalogItem input) {
return input.getEntity().getType().equals(VCloudMediaType.VAPPTEMPLATE_XML);
}
}), new Function<CatalogItem, Future<? extends VAppTemplate>>() {
@Override
public Future<VAppTemplate> apply(CatalogItem from) {
}), new Function<CatalogItem, ListenableFuture<? extends VAppTemplate>>() {
public ListenableFuture<VAppTemplate> apply(CatalogItem from) {
return aclient.getVAppTemplateClient().getVAppTemplate(from.getEntity().getHref());
}
}, executor, null, logger, "vappTemplates in"), Predicates.notNull());
}, userExecutor, null, logger, "vappTemplates in"), Predicates.notNull());
}
}

View File

@ -20,9 +20,6 @@ package org.jclouds.vcloud.functions;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -36,6 +33,8 @@ import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.domain.VDC;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -46,23 +45,21 @@ public class VDCsInOrg implements Function<Org, Iterable<VDC>> {
public Logger logger = Logger.NULL;
private final VCloudAsyncClient aclient;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
VDCsInOrg(VCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
VDCsInOrg(VCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.aclient = aclient;
this.executor = executor;
this.userExecutor = userExecutor;
}
@Override
public Iterable<VDC> apply(final Org org) {
return transformParallel(org.getVDCs().values(), new Function<ReferenceType, Future<? extends VDC>>() {
@Override
public Future<? extends VDC> apply(ReferenceType from) {
return transformParallel(org.getVDCs().values(), new Function<ReferenceType, ListenableFuture<? extends VDC>>() {
public ListenableFuture<? extends VDC> apply(ReferenceType from) {
return aclient.getVDCClient().getVDC(from.getHref());
}
}, executor, null, logger, "vdcs in org " + org.getName());
}, userExecutor, null, logger, "vdcs in org " + org.getName());
}
}

View File

@ -26,8 +26,6 @@ import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -42,6 +40,8 @@ import org.jclouds.vcloud.domain.VAppTemplate;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -55,41 +55,34 @@ public class VAppTemplatesSupplier implements Supplier<Set<VAppTemplate>> {
private final Supplier<Map<String, Org>> orgMap;
private final Function<Org, Iterable<VAppTemplate>> imagesInOrg;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
VAppTemplatesSupplier(Supplier<Map<String, Org>> orgMap,
Function<Org, Iterable<VAppTemplate>> imagesInOrg,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.orgMap = checkNotNull(orgMap, "orgMap");
this.imagesInOrg = checkNotNull(imagesInOrg, "imagesInOrg");
this.executor = checkNotNull(executor, "executor");
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
}
@Override
public Set<VAppTemplate> get() {
Iterable<Org> orgs = checkNotNull(orgMap.get().values(), "orgs");
Iterable<? extends Iterable<VAppTemplate>> images = transformParallel(orgs,
new Function<Org, Future<? extends Iterable<VAppTemplate>>>() {
@Override
public Future<Iterable<VAppTemplate>> apply(final Org from) {
new Function<Org, ListenableFuture<? extends Iterable<VAppTemplate>>>() {
public ListenableFuture<Iterable<VAppTemplate>> apply(final Org from) {
checkNotNull(from, "org");
return executor.submit(new Callable<Iterable<VAppTemplate>>() {
@Override
return userExecutor.submit(new Callable<Iterable<VAppTemplate>>() {
public Iterable<VAppTemplate> call() throws Exception {
return imagesInOrg.apply(from);
}
@Override
public String toString() {
return "imagesInOrg(" + from.getHref() + ")";
}
});
}
}, executor, null, logger, "images in " + orgs);
}, userExecutor, null, logger, "images in " + orgs);
return newLinkedHashSet(concat(images));
}
}

View File

@ -36,7 +36,6 @@ import java.io.IOException;
import java.util.Date;
import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -80,6 +79,7 @@ import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* Implementation of {@link BaseAsyncBlobStore} which uses a pluggable
@ -103,13 +103,13 @@ public class LocalAsyncBlobStore extends BaseAsyncBlobStore {
@Inject
protected LocalAsyncBlobStore(BlobStoreContext context,
BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
Supplier<Location> defaultLocation,
@Memoized Supplier<Set<? extends Location>> locations,
ContentMetadataCodec contentMetadataCodec,
IfDirectoryReturnNameStrategy ifDirectoryReturnName,
Factory blobFactory, LocalStorageStrategy storageStrategy) {
super(context, blobUtils, service, defaultLocation, locations);
super(context, blobUtils, userExecutor, defaultLocation, locations);
this.blobFactory = blobFactory;
this.contentMetadataCodec = contentMetadataCodec;
this.ifDirectoryReturnName = ifDirectoryReturnName;

View File

@ -24,7 +24,6 @@ import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursi
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
@ -48,6 +47,7 @@ import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
*
@ -57,17 +57,17 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
protected final BlobStoreContext context;
protected final BlobUtils blobUtils;
protected final ExecutorService service;
protected final ListeningExecutorService userExecutor;
protected final Supplier<Location> defaultLocation;
protected final Supplier<Set<? extends Location>> locations;
@Inject
protected BaseAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Supplier<Location> defaultLocation,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, Supplier<Location> defaultLocation,
@Memoized Supplier<Set<? extends Location>> locations) {
this.context = checkNotNull(context, "context");
this.blobUtils = checkNotNull(blobUtils, "blobUtils");
this.service = checkNotNull(service, "service");
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
this.defaultLocation = checkNotNull(defaultLocation, "defaultLocation");
this.locations = checkNotNull(locations, "locations");
}
@ -117,7 +117,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
*/
@Override
public ListenableFuture<Long> countBlobs(final String containerName, final ListContainerOptions options) {
return org.jclouds.concurrent.Futures.makeListenable(service.submit(new Callable<Long>() {
return userExecutor.submit(new Callable<Long>() {
public Long call() throws Exception {
return blobUtils.countBlobs(containerName, options);
}
@ -126,7 +126,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
public String toString() {
return "countBlobs(" + containerName + ")";
}
}), service);
});
}
/**
@ -149,7 +149,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
*/
@Override
public ListenableFuture<Void> clearContainer(final String containerName, final ListContainerOptions options) {
return org.jclouds.concurrent.Futures.makeListenable(service.submit(new Callable<Void>() {
return userExecutor.submit(new Callable<Void>() {
public Void call() throws Exception {
blobUtils.clearContainer(containerName, options);
@ -160,7 +160,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
public String toString() {
return "clearContainer(" + containerName + ")";
}
}), service);
});
}
/**
@ -171,7 +171,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
*/
@Override
public ListenableFuture<Void> deleteDirectory(final String containerName, final String directory) {
return org.jclouds.concurrent.Futures.makeListenable(service.submit(new Callable<Void>() {
return userExecutor.submit(new Callable<Void>() {
public Void call() throws Exception {
blobUtils.deleteDirectory(containerName, directory);
@ -182,7 +182,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
public String toString() {
return "deleteDirectory(" + containerName + "," + directory + ")";
}
}), service);
});
}
/**
@ -194,7 +194,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
* virtual path
*/
public ListenableFuture<Boolean> directoryExists(final String containerName, final String directory) {
return org.jclouds.concurrent.Futures.makeListenable(service.submit(new Callable<Boolean>() {
return userExecutor.submit(new Callable<Boolean>() {
public Boolean call() throws Exception {
return blobUtils.directoryExists(containerName, directory);
@ -204,7 +204,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
public String toString() {
return "directoryExists(" + containerName + "," + directory + ")";
}
}), service);
});
}
/**
@ -217,9 +217,8 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
*/
public ListenableFuture<Void> createDirectory(final String containerName, final String directory) {
return blobUtils.directoryExists(containerName, directory) ? Futures.immediateFuture((Void) null)
: org.jclouds.concurrent.Futures.makeListenable(service.submit(new Callable<Void>() {
: userExecutor.submit(new Callable<Void>() {
public Void call() throws Exception {
blobUtils.createDirectory(containerName, directory);
return null;
@ -229,7 +228,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
public String toString() {
return "createDirectory(" + containerName + "," + directory + ")";
}
}), service);
});
}
/**
@ -254,7 +253,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
*/
@Override
public ListenableFuture<Void> deleteContainer(final String container) {
return org.jclouds.concurrent.Futures.makeListenable(service.submit(new Callable<Void>() {
return userExecutor.submit(new Callable<Void>() {
public Void call() throws Exception {
deletePathAndEnsureGone(container);
@ -265,7 +264,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
public String toString() {
return "deleteContainer(" + container + ")";
}
}), service);
});
}
protected void deletePathAndEnsureGone(String path) {

View File

@ -24,10 +24,8 @@ import static org.jclouds.concurrent.FutureIterables.awaitCompletion;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.annotation.Resource;
import javax.inject.Named;
@ -46,6 +44,8 @@ import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.logging.Logger;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
/**
@ -60,7 +60,7 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
protected Logger logger = Logger.NULL;
protected final BackoffLimitedRetryHandler retryHandler;
private final ExecutorService userExecutor;
private final ListeningExecutorService userExecutor;
protected final AsyncBlobStore connection;
/** Maximum duration in milliseconds of a request. */
@ -69,10 +69,8 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
protected Long maxTime = Long.MAX_VALUE;
@Inject
DeleteAllKeysInList(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
AsyncBlobStore connection,
BackoffLimitedRetryHandler retryHandler) {
DeleteAllKeysInList(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
AsyncBlobStore connection, BackoffLimitedRetryHandler retryHandler) {
this.userExecutor = userExecutor;
this.connection = connection;
this.retryHandler = retryHandler;
@ -95,7 +93,7 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
for (int numErrors = 0; numErrors < maxErrors; ) {
// fetch partial directory listing
PageSet<? extends StorageMetadata> listing;
Future<PageSet<? extends StorageMetadata>> listFuture =
ListenableFuture<PageSet<? extends StorageMetadata>> listFuture =
connection.list(containerName, options);
try {
listing = listFuture.get(maxTime, TimeUnit.MILLISECONDS);
@ -141,7 +139,7 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
}
// remove blobs and now-empty subdirectories
Map<StorageMetadata, Future<?>> responses = Maps.newHashMap();
Map<StorageMetadata, ListenableFuture<?>> responses = Maps.newHashMap();
for (StorageMetadata md : listing) {
String fullPath = parentIsFolder(options, md) ? options.getDir() + "/"
+ md.getName() : md.getName();
@ -174,7 +172,7 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
retryHandler.imposeBackoffExponentialDelay(numErrors, message);
continue;
} finally {
for (Future<?> future : responses.values()) {
for (ListenableFuture<?> future : responses.values()) {
future.cancel(true);
}
}

View File

@ -21,9 +21,6 @@ package org.jclouds.blobstore.strategy.internal;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Named;
@ -43,6 +40,8 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
/**
@ -55,7 +54,7 @@ public class FetchBlobMetadata implements Function<PageSet<? extends StorageMeta
protected final BackoffLimitedRetryHandler retryHandler;
protected final AsyncBlobStore ablobstore;
protected final ExecutorService userExecutor;
protected final ListeningExecutorService userExecutor;
@Resource
@Named(BlobStoreConstants.BLOBSTORE_LOGGER)
protected Logger logger = Logger.NULL;
@ -69,7 +68,7 @@ public class FetchBlobMetadata implements Function<PageSet<? extends StorageMeta
protected Long maxTime;
@Inject
FetchBlobMetadata(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, AsyncBlobStore ablobstore,
FetchBlobMetadata(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, AsyncBlobStore ablobstore,
BackoffLimitedRetryHandler retryHandler) {
this.userExecutor = userExecutor;
this.ablobstore = ablobstore;
@ -91,10 +90,10 @@ public class FetchBlobMetadata implements Function<PageSet<? extends StorageMeta
return input.getType() == StorageType.BLOB;
}
}), new Function<StorageMetadata, Future<? extends BlobMetadata>>() {
}), new Function<StorageMetadata, ListenableFuture<? extends BlobMetadata>>() {
@Override
public Future<BlobMetadata> apply(StorageMetadata from) {
public ListenableFuture<BlobMetadata> apply(StorageMetadata from) {
return ablobstore.blobMetadata(container, from.getName());
}

View File

@ -20,9 +20,6 @@ package org.jclouds.blobstore.strategy.internal;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
@ -39,6 +36,8 @@ import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
/**
@ -53,7 +52,7 @@ public class GetAllBlobsInListAndRetryOnFailure implements GetBlobsInListStrateg
protected final ListBlobsInContainer getAllBlobMetadata;
protected final BackoffLimitedRetryHandler retryHandler;
protected final AsyncBlobStore ablobstore;
protected final ExecutorService userExecutor;
protected final ListeningExecutorService userExecutor;
@Resource
@Named(BlobStoreConstants.BLOBSTORE_LOGGER)
protected Logger logger = Logger.NULL;
@ -65,7 +64,7 @@ public class GetAllBlobsInListAndRetryOnFailure implements GetBlobsInListStrateg
protected Long maxTime;
@Inject
GetAllBlobsInListAndRetryOnFailure(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
GetAllBlobsInListAndRetryOnFailure(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
ListBlobsInContainer getAllBlobMetadata, AsyncBlobStore ablobstore, BackoffLimitedRetryHandler retryHandler) {
this.userExecutor = userExecutor;
this.ablobstore = ablobstore;
@ -75,10 +74,10 @@ public class GetAllBlobsInListAndRetryOnFailure implements GetBlobsInListStrateg
public Iterable<Blob> execute(final String container, ListContainerOptions options) {
Iterable<? extends BlobMetadata> list = getAllBlobMetadata.execute(container, options);
return transformParallel(list, new Function<BlobMetadata, Future<? extends Blob>>() {
return transformParallel(list, new Function<BlobMetadata, ListenableFuture<? extends Blob>>() {
@Override
public Future<Blob> apply(BlobMetadata from) {
public ListenableFuture<Blob> apply(BlobMetadata from) {
return ablobstore.getBlob(container, from.getName());
}

View File

@ -23,8 +23,6 @@ import static org.jclouds.concurrent.FutureIterables.awaitCompletion;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import javax.annotation.Resource;
@ -41,6 +39,8 @@ import org.jclouds.logging.Logger;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
/**
@ -68,7 +68,7 @@ public class MarkersDeleteDirectoryStrategy implements DeleteDirectoryStrategy {
private final AsyncBlobStore ablobstore;
private final BlobStore blobstore;
private final ExecutorService userExecutor;
private final ListeningExecutorService userExecutor;
@Resource
@Named(BlobStoreConstants.BLOBSTORE_LOGGER)
protected Logger logger = Logger.NULL;
@ -81,7 +81,7 @@ public class MarkersDeleteDirectoryStrategy implements DeleteDirectoryStrategy {
@Inject
MarkersDeleteDirectoryStrategy(
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
AsyncBlobStore ablobstore, BlobStore blobstore) {
this.userExecutor = userExecutor;
this.ablobstore = ablobstore;
@ -94,7 +94,7 @@ public class MarkersDeleteDirectoryStrategy implements DeleteDirectoryStrategy {
for (String suffix : BlobStoreConstants.DIRECTORY_SUFFIXES) {
names.add(directory + suffix);
}
Map<String, Future<?>> responses = Maps.newHashMap();
Map<String, ListenableFuture<?>> responses = Maps.newHashMap();
for (String name : names) {
responses.put(name, ablobstore.removeBlob(containerName, name));
}

View File

@ -22,8 +22,6 @@ import static com.google.common.base.Throwables.propagate;
import static org.jclouds.concurrent.FutureIterables.awaitCompletion;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import javax.annotation.Resource;
@ -39,6 +37,8 @@ import org.jclouds.blobstore.strategy.PutBlobsStrategy;
import org.jclouds.logging.Logger;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
/**
@ -49,7 +49,7 @@ import com.google.inject.Inject;
public class PutBlobsStrategyImpl implements PutBlobsStrategy {
private final AsyncBlobStore ablobstore;
private final ExecutorService userExecutor;
private final ListeningExecutorService userExecutor;
@Resource
@Named(BlobStoreConstants.BLOBSTORE_LOGGER)
protected Logger logger = Logger.NULL;
@ -61,7 +61,7 @@ public class PutBlobsStrategyImpl implements PutBlobsStrategy {
protected Long maxTime;
@Inject
PutBlobsStrategyImpl(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
PutBlobsStrategyImpl(@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
AsyncBlobStore ablobstore) {
this.userExecutor = userExecutor;
this.ablobstore = ablobstore;
@ -69,7 +69,7 @@ public class PutBlobsStrategyImpl implements PutBlobsStrategy {
@Override
public void execute(String containerName, Iterable<? extends Blob> blobs) {
Map<Blob, Future<?>> responses = Maps.newLinkedHashMap();
Map<Blob, ListenableFuture<?>> responses = Maps.newLinkedHashMap();
for (Blob blob : blobs) {
responses.put(blob, ablobstore.putBlob(containerName, blob));
}

View File

@ -43,7 +43,6 @@ import java.util.Date;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.GZIPInputStream;
@ -58,7 +57,6 @@ import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.concurrent.Futures;
import org.jclouds.crypto.Crypto;
import org.jclouds.encryption.internal.JCECrypto;
import org.jclouds.http.BaseJettyTest;
@ -84,6 +82,8 @@ import com.google.common.collect.Maps;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import com.google.common.io.InputSupplier;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
/**
* @author Adrian Cole
@ -139,7 +139,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
final AtomicInteger blobCount = new AtomicInteger();
final String container = getContainerName();
try {
Map<Integer, Future<?>> responses = Maps.newHashMap();
Map<Integer, ListenableFuture<?>> responses = Maps.newHashMap();
for (int i = 0; i < 10; i++) {
responses.put(i, this.exec.submit(new Callable<Void>() {
@ -179,10 +179,10 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
final String name = "constitution.txt";
uploadConstitution(container, name, expectedContentDisposition);
Map<Integer, Future<?>> responses = Maps.newHashMap();
Map<Integer, ListenableFuture<?>> responses = Maps.newHashMap();
for (int i = 0; i < 10; i++) {
responses.put(i, Futures.compose(view.getAsyncBlobStore().getBlob(container, name),
responses.put(i, Futures.transform(view.getAsyncBlobStore().getBlob(container, name),
new Function<Blob, Void>() {
@Override

View File

@ -32,7 +32,6 @@ import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@ -63,6 +62,8 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.google.common.reflect.TypeToken;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.inject.Module;
public class BaseBlobStoreIntegrationTest extends BaseViewLiveTest<BlobStoreContext> {
@ -106,7 +107,7 @@ public class BaseBlobStoreIntegrationTest extends BaseViewLiveTest<BlobStoreCont
return ImmutableSet.<Module> of(getLoggingModule(), createHttpModule());
}
protected ExecutorService exec;
protected ListeningExecutorService exec;
/**
* we are doing this at a class level, as the context.getBlobStore() object is going to be shared
@ -116,7 +117,7 @@ public class BaseBlobStoreIntegrationTest extends BaseViewLiveTest<BlobStoreCont
*/
@BeforeClass(groups = { "integration", "live" }, dependsOnMethods = "setupContext")
public void setUpResourcesOnThisThread(ITestContext testContext) throws Exception {
exec = Executors.newCachedThreadPool();
exec = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
}

View File

@ -23,7 +23,6 @@ import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_T
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject;
@ -62,6 +61,7 @@ import org.jclouds.trmk.vcloud_0_8.compute.strategy.CleanupOrphanKeys;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -85,13 +85,13 @@ public class TerremarkVCloudComputeService extends BaseComputeService {
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, CleanupOrphanKeys cleanupOrphanKeys,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, CleanupOrphanKeys cleanupOrphanKeys,
Optional<ImageExtension> imageExtension) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
resumeNodeStrategy, suspendNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
persistNodeCredentials, timeouts, executor, imageExtension);
persistNodeCredentials, timeouts, userExecutor, imageExtension);
this.cleanupOrphanKeys = cleanupOrphanKeys;
}

View File

@ -21,8 +21,6 @@ package org.jclouds.trmk.vcloud_0_8.compute.strategy;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.inject.Inject;
import javax.inject.Named;
@ -41,6 +39,8 @@ import org.jclouds.domain.LocationScope;
import org.jclouds.trmk.vcloud_0_8.compute.options.TerremarkVCloudTemplateOptions;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* creates futures that correlate to
@ -58,15 +58,15 @@ public class TerremarkEncodeTagIntoNameRunNodesAndAddToSetStrategy extends Creat
ListNodesStrategy listNodesStrategy,
GroupNamingConvention.Factory namingConvention,
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
CreateNewKeyPairUnlessUserSpecifiedOtherwise createNewKeyPairUnlessUserSpecifiedOtherwise) {
super(addNodeWithTagStrategy, listNodesStrategy, namingConvention, executor,
super(addNodeWithTagStrategy, listNodesStrategy, namingConvention, userExecutor,
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
this.createNewKeyPairUnlessUserSpecifiedOtherwise = createNewKeyPairUnlessUserSpecifiedOtherwise;
}
@Override
public Map<?, Future<Void>> execute(String tag, int count, Template template, Set<NodeMetadata> goodNodes,
public Map<?, ListenableFuture<Void>> execute(String tag, int count, Template template, Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
assert template.getLocation().getParent().getScope() == LocationScope.REGION : "template location should have a parent of org, which should be mapped to region: "
+ template.getLocation();

View File

@ -26,8 +26,6 @@ import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -42,6 +40,8 @@ import org.jclouds.trmk.vcloud_0_8.domain.Org;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -55,27 +55,27 @@ public class VCloudHardwareSupplier implements Supplier<Set<? extends Hardware>>
private final Supplier<Map<String, ? extends Org>> orgMap;
private final Function<Org, Iterable<? extends Hardware>> sizesInOrg;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
VCloudHardwareSupplier(Supplier<Map<String, ? extends Org>> orgMap,
Function<Org, Iterable<? extends Hardware>> sizesInOrg,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.orgMap = checkNotNull(orgMap, "orgMap");
this.sizesInOrg = checkNotNull(sizesInOrg, "sizesInOrg");
this.executor = checkNotNull(executor, "executor");
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
}
@Override
public Set<? extends Hardware> get() {
Iterable<? extends Org> orgs = checkNotNull(orgMap.get().values(), "orgs");
Iterable<? extends Iterable<? extends Hardware>> sizes = transformParallel(orgs,
new Function<Org, Future<? extends Iterable<? extends Hardware>>>() {
new Function<Org, ListenableFuture<? extends Iterable<? extends Hardware>>>() {
@Override
public Future<Iterable<? extends Hardware>> apply(final Org from) {
public ListenableFuture<Iterable<? extends Hardware>> apply(final Org from) {
checkNotNull(from, "org");
return executor.submit(new Callable<Iterable<? extends Hardware>>() {
return userExecutor.submit(new Callable<Iterable<? extends Hardware>>() {
@Override
public Iterable<? extends Hardware> call() throws Exception {
@ -89,7 +89,7 @@ public class VCloudHardwareSupplier implements Supplier<Set<? extends Hardware>>
});
}
}, executor, null, logger, "sizes in " + orgs);
}, userExecutor, null, logger, "sizes in " + orgs);
return newLinkedHashSet(concat(sizes));
}
}

View File

@ -26,8 +26,6 @@ import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -42,6 +40,8 @@ import org.jclouds.trmk.vcloud_0_8.domain.Org;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -55,27 +55,27 @@ public class VCloudImageSupplier implements Supplier<Set<? extends Image>> {
private final Supplier<Map<String, ? extends Org>> orgMap;
private final Function<Org, Iterable<? extends Image>> imagesInOrg;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
VCloudImageSupplier(Supplier<Map<String, ? extends Org>> orgMap,
Function<Org, Iterable<? extends Image>> imagesInOrg,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.orgMap = checkNotNull(orgMap, "orgMap");
this.imagesInOrg = checkNotNull(imagesInOrg, "imagesInOrg");
this.executor = checkNotNull(executor, "executor");
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
}
@Override
public Set<? extends Image> get() {
Iterable<? extends Org> orgs = checkNotNull(orgMap.get().values(), "orgs");
Iterable<? extends Iterable<? extends Image>> images = transformParallel(orgs,
new Function<Org, Future<? extends Iterable<? extends Image>>>() {
new Function<Org, ListenableFuture<? extends Iterable<? extends Image>>>() {
@Override
public Future<Iterable<? extends Image>> apply(final Org from) {
public ListenableFuture<Iterable<? extends Image>> apply(final Org from) {
checkNotNull(from, "org");
return executor.submit(new Callable<Iterable<? extends Image>>() {
return userExecutor.submit(new Callable<Iterable<? extends Image>>() {
@Override
public Iterable<? extends Image> call() throws Exception {
@ -89,7 +89,7 @@ public class VCloudImageSupplier implements Supplier<Set<? extends Image>> {
});
}
}, executor, null, logger, "images in " + orgs);
}, userExecutor, null, logger, "images in " + orgs);
return newLinkedHashSet(concat(images));
}
}

View File

@ -21,9 +21,6 @@ package org.jclouds.trmk.vcloud_0_8.functions;
import static com.google.common.collect.Iterables.filter;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -39,6 +36,8 @@ import org.jclouds.trmk.vcloud_0_8.domain.ReferenceType;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -49,35 +48,26 @@ public class AllCatalogItemsInCatalog implements Function<Catalog, Iterable<? ex
public Logger logger = Logger.NULL;
private final TerremarkVCloudAsyncClient aclient;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
AllCatalogItemsInCatalog(TerremarkVCloudAsyncClient aclient,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.aclient = aclient;
this.executor = executor;
this.userExecutor = userExecutor;
}
@Override
public Iterable<? extends CatalogItem> apply(Catalog from) {
Iterable<? extends CatalogItem> catalogItems = transformParallel(filter(from.values(), new Predicate<ReferenceType>() {
@Override
return transformParallel(filter(from.values(), new Predicate<ReferenceType>() {
public boolean apply(ReferenceType input) {
return input.getType().equals(TerremarkVCloudMediaType.CATALOGITEM_XML);
}
}), new Function<ReferenceType, Future<? extends CatalogItem>>() {
@SuppressWarnings("unchecked")
@Override
public Future<CatalogItem> apply(ReferenceType from) {
return (Future<CatalogItem>) aclient.getCatalogItem(from.getHref());
}), new Function<ReferenceType, ListenableFuture<? extends CatalogItem>>() {
public ListenableFuture<? extends CatalogItem> apply(ReferenceType from) {
return aclient.getCatalogItem(from.getHref());
}
}, executor, null, logger, "catalogItems in " + from.getHref());
return catalogItems;
}, userExecutor, null, logger, "catalogItems in " + from.getHref());
}
}

View File

@ -20,9 +20,6 @@ package org.jclouds.trmk.vcloud_0_8.functions;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -36,6 +33,8 @@ import org.jclouds.trmk.vcloud_0_8.domain.Org;
import org.jclouds.trmk.vcloud_0_8.domain.ReferenceType;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -46,25 +45,21 @@ public class AllCatalogsInOrg implements Function<Org, Iterable<? extends Catalo
public Logger logger = Logger.NULL;
private final TerremarkVCloudAsyncClient aclient;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
AllCatalogsInOrg(TerremarkVCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
AllCatalogsInOrg(TerremarkVCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.aclient = aclient;
this.executor = executor;
this.userExecutor = userExecutor;
}
@Override
public Iterable<? extends Catalog> apply(final Org org) {
Iterable<? extends Catalog> catalogs = transformParallel(org.getCatalogs().values(),
new Function<ReferenceType, Future<? extends Catalog>>() {
@SuppressWarnings("unchecked")
@Override
public Future<Catalog> apply(ReferenceType from) {
return (Future<Catalog>) aclient.getCatalog(from.getHref());
return transformParallel(org.getCatalogs().values(),
new Function<ReferenceType, ListenableFuture<? extends Catalog>>() {
public ListenableFuture<? extends Catalog> apply(ReferenceType from) {
return aclient.getCatalog(from.getHref());
}
}, executor, null, logger, "catalogs in " + org.getName());
return catalogs;
}, userExecutor, null, logger, "catalogs in " + org.getName());
}
}

View File

@ -20,9 +20,6 @@ package org.jclouds.trmk.vcloud_0_8.functions;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -35,6 +32,8 @@ import org.jclouds.trmk.vcloud_0_8.domain.Org;
import org.jclouds.trmk.vcloud_0_8.domain.ReferenceType;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -45,26 +44,22 @@ public class AllVDCsInOrg implements Function<Org, Iterable<? extends org.jcloud
public Logger logger = Logger.NULL;
private final TerremarkVCloudAsyncClient aclient;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
AllVDCsInOrg(TerremarkVCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
AllVDCsInOrg(TerremarkVCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.aclient = aclient;
this.executor = executor;
this.userExecutor = userExecutor;
}
@Override
public Iterable<? extends org.jclouds.trmk.vcloud_0_8.domain.VDC> apply(final Org org) {
Iterable<? extends org.jclouds.trmk.vcloud_0_8.domain.VDC> catalogItems = transformParallel(org.getVDCs().values(),
new Function<ReferenceType, Future<? extends org.jclouds.trmk.vcloud_0_8.domain.VDC>>() {
@Override
public Future<? extends org.jclouds.trmk.vcloud_0_8.domain.VDC> apply(ReferenceType from) {
return transformParallel(org.getVDCs().values(),
new Function<ReferenceType, ListenableFuture<? extends org.jclouds.trmk.vcloud_0_8.domain.VDC>>() {
public ListenableFuture<? extends org.jclouds.trmk.vcloud_0_8.domain.VDC> apply(ReferenceType from) {
return aclient.getVDC(from.getHref());
}
}, executor, null, logger, "vdcs in org " + org.getName());
return catalogItems;
}, userExecutor, null, logger, "vdcs in org " + org.getName());
}
}

View File

@ -23,8 +23,6 @@ import static com.google.common.collect.Iterables.transform;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.net.URI;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -41,6 +39,8 @@ import org.jclouds.trmk.vcloud_0_8.domain.Org;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -50,12 +50,12 @@ public class OrgsForLocations implements Function<Iterable<? extends Location>,
@Resource
public Logger logger = Logger.NULL;
private final TerremarkVCloudAsyncClient aclient;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
OrgsForLocations(TerremarkVCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
OrgsForLocations(TerremarkVCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.aclient = aclient;
this.executor = executor;
this.userExecutor = userExecutor;
}
/**
@ -64,28 +64,18 @@ public class OrgsForLocations implements Function<Iterable<? extends Location>,
*/
@Override
public Iterable<? extends Org> apply(Iterable<? extends Location> from) {
return transformParallel(Sets.newLinkedHashSet(transform(filter(from, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getScope() == LocationScope.ZONE;
}
}), new Function<Location, URI>() {
@Override
public URI apply(Location from) {
return URI.create(from.getParent().getId());
}
})), new Function<URI, Future<? extends Org>>() {
@Override
public Future<? extends Org> apply(URI from) {
})), new Function<URI, ListenableFuture<? extends Org>>() {
public ListenableFuture<? extends Org> apply(URI from) {
return aclient.getOrg(from);
}
}, executor, null, logger, "organizations for uris");
}, userExecutor, null, logger, "organizations for uris");
}
}

View File

@ -20,9 +20,6 @@ package org.jclouds.trmk.vcloud_0_8.functions;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -34,6 +31,8 @@ import org.jclouds.trmk.vcloud_0_8.TerremarkVCloudAsyncClient;
import org.jclouds.trmk.vcloud_0_8.domain.Org;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -43,23 +42,21 @@ public class OrgsForNames implements Function<Iterable<String>, Iterable<? exten
@Resource
public Logger logger = Logger.NULL;
private final TerremarkVCloudAsyncClient aclient;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
OrgsForNames(TerremarkVCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
OrgsForNames(TerremarkVCloudAsyncClient aclient, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.aclient = aclient;
this.executor = executor;
this.userExecutor = userExecutor;
}
@Override
public Iterable<? extends Org> apply(Iterable<String> from) {
return transformParallel(from, new Function<String, Future<? extends Org>>() {
@Override
public Future<? extends Org> apply(String from) {
return transformParallel(from, new Function<String, ListenableFuture<? extends Org>>() {
public ListenableFuture<? extends Org> apply(String from) {
return aclient.findOrgNamed(from);
}
}, executor, null, logger, "organizations for names");
}, userExecutor, null, logger, "organizations for names");
}
}

View File

@ -21,9 +21,6 @@ package org.jclouds.trmk.vcloud_0_8.functions;
import static com.google.common.collect.Iterables.filter;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -39,6 +36,8 @@ import org.jclouds.trmk.vcloud_0_8.domain.VAppTemplate;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -50,31 +49,26 @@ public class VAppTemplatesForCatalogItems implements
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
public Logger logger = Logger.NULL;
private final TerremarkVCloudAsyncClient aclient;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
VAppTemplatesForCatalogItems(TerremarkVCloudAsyncClient aclient,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.aclient = aclient;
this.executor = executor;
this.userExecutor = userExecutor;
}
@Override
public Iterable<? extends VAppTemplate> apply(Iterable<? extends CatalogItem> from) {
return transformParallel(filter(from, new Predicate<CatalogItem>() {
@Override
public boolean apply(CatalogItem input) {
return input.getEntity().getType().equals(TerremarkVCloudMediaType.VAPPTEMPLATE_XML);
}
}), new Function<CatalogItem, Future<? extends VAppTemplate>>() {
@Override
public Future<? extends VAppTemplate> apply(CatalogItem from) {
}), new Function<CatalogItem, ListenableFuture<? extends VAppTemplate>>() {
public ListenableFuture<? extends VAppTemplate> apply(CatalogItem from) {
return aclient.getVAppTemplate(from.getEntity().getHref());
}
}, executor, null, logger, "vappTemplates in");
}, userExecutor, null, logger, "vappTemplates in");
}
}

View File

@ -22,9 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.filter;
import static org.jclouds.concurrent.FutureIterables.transformParallel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -40,6 +37,8 @@ import org.jclouds.trmk.vcloud_0_8.domain.VAppTemplate;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* @author Adrian Cole
@ -51,31 +50,26 @@ public class VAppTemplatesForResourceEntities implements
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
public Logger logger = Logger.NULL;
private final TerremarkVCloudAsyncClient aclient;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
VAppTemplatesForResourceEntities(TerremarkVCloudAsyncClient aclient,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.aclient = aclient;
this.executor = executor;
this.userExecutor = userExecutor;
}
@Override
public Iterable<? extends VAppTemplate> apply(Iterable<? extends ReferenceType> from) {
return transformParallel(filter(checkNotNull(from, "named resources"), new Predicate<ReferenceType>() {
@Override
public boolean apply(ReferenceType input) {
return input.getType().equals(TerremarkVCloudMediaType.VAPPTEMPLATE_XML);
}
}), new Function<ReferenceType, Future<? extends VAppTemplate>>() {
@Override
public Future<? extends VAppTemplate> apply(ReferenceType from) {
}), new Function<ReferenceType, ListenableFuture<? extends VAppTemplate>>() {
public ListenableFuture<? extends VAppTemplate> apply(ReferenceType from) {
return aclient.getVAppTemplate(from.getHref());
}
}, executor, null, logger, "vappTemplates in");
}, userExecutor, null, logger, "vappTemplates in");
}
}

View File

@ -23,7 +23,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@ -36,6 +35,7 @@ import org.jclouds.compute.events.StatementOnNodeFailure;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.scriptbuilder.InitScript;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
@ -44,6 +44,7 @@ import com.google.common.base.Predicates;
import com.google.common.eventbus.EventBus;
import com.google.common.primitives.Ints;
import com.google.common.util.concurrent.AbstractFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.name.Named;
@ -63,7 +64,7 @@ public class BlockUntilInitScriptStatusIsZeroThenReturnOutput extends AbstractFu
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final ExecutorService userThreads;
private final ListeningExecutorService userExecutor;
private final EventBus eventBus;
private final SudoAwareInitManager commandRunner;
@ -75,19 +76,19 @@ public class BlockUntilInitScriptStatusIsZeroThenReturnOutput extends AbstractFu
@Inject
public BlockUntilInitScriptStatusIsZeroThenReturnOutput(
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads, EventBus eventBus,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, EventBus eventBus,
ComputeServiceConstants.InitStatusProperties properties, @Assisted SudoAwareInitManager commandRunner) {
this(userThreads, eventBus, Predicates.<String> alwaysTrue(), commandRunner);
this(userExecutor, eventBus, Predicates.<String> alwaysTrue(), commandRunner);
// this is mutable only until we can determine how to decouple "this" from here
notRunningAnymore = new LoopUntilTrueOrThrowCancellationException(new ExitStatusOfCommandGreaterThanZero(
commandRunner), properties.initStatusMaxPeriod, properties.initStatusInitialPeriod, this);
}
@VisibleForTesting
public BlockUntilInitScriptStatusIsZeroThenReturnOutput(ExecutorService userThreads, EventBus eventBus,
public BlockUntilInitScriptStatusIsZeroThenReturnOutput(ListeningExecutorService userExecutor, EventBus eventBus,
Predicate<String> notRunningAnymore, SudoAwareInitManager commandRunner) {
this.commandRunner = checkNotNull(commandRunner, "commandRunner");
this.userThreads = checkNotNull(userThreads, "userThreads");
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
this.eventBus = checkNotNull(eventBus, "eventBus");
this.notRunningAnymore = checkNotNull(notRunningAnymore, "notRunningAnymore");
}
@ -136,7 +137,7 @@ public class BlockUntilInitScriptStatusIsZeroThenReturnOutput extends AbstractFu
* place
*/
public BlockUntilInitScriptStatusIsZeroThenReturnOutput init() {
userThreads.submit(this);
userExecutor.submit(this);
return this;
}

View File

@ -24,7 +24,6 @@ import static com.google.common.base.Predicates.notNull;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Maps.newLinkedHashMap;
import static com.google.common.collect.Sets.filter;
import static com.google.common.collect.Sets.newLinkedHashSet;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
@ -40,10 +39,8 @@ import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Resource;
@ -65,10 +62,10 @@ import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.extensions.ImageExtension;
import org.jclouds.compute.options.RunScriptOptions;
import org.jclouds.compute.options.TemplateOptions;
@ -107,6 +104,7 @@ import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.Atomics;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
*
@ -143,7 +141,7 @@ public class BaseComputeService implements ComputeService {
private final InitAdminAccess initAdminAccess;
private final PersistNodeCredentials persistNodeCredentials;
private final RunScriptOnNode.Factory runScriptOnNodeFactory;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
private final Optional<ImageExtension> imageExtension;
@Inject
@ -161,7 +159,7 @@ public class BaseComputeService implements ComputeService {
@Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, InitAdminAccess initAdminAccess,
RunScriptOnNode.Factory runScriptOnNodeFactory, PersistNodeCredentials persistNodeCredentials,
Timeouts timeouts, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
Timeouts timeouts, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
Optional<ImageExtension> imageExtension) {
this.context = checkNotNull(context, "context");
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
@ -186,8 +184,8 @@ public class BaseComputeService implements ComputeService {
this.initAdminAccess = checkNotNull(initAdminAccess, "initAdminAccess");
this.runScriptOnNodeFactory = checkNotNull(runScriptOnNodeFactory, "runScriptOnNodeFactory");
this.persistNodeCredentials = checkNotNull(persistNodeCredentials, "persistNodeCredentials");
this.executor = checkNotNull(executor, "executor");
this.imageExtension = imageExtension;
this.userExecutor = checkNotNull(userExecutor, "userExecutor");
this.imageExtension = checkNotNull(imageExtension, "imageExtension");
}
/**
@ -213,11 +211,11 @@ public class BaseComputeService implements ComputeService {
if (template.getOptions().getRunScript() != null)
initAdminAccess.visit(template.getOptions().getRunScript());
Map<?, Future<Void>> responses = runNodesAndAddToSetStrategy.execute(group, count, template, goodNodes, badNodes,
Map<?, ListenableFuture<Void>> responses = runNodesAndAddToSetStrategy.execute(group, count, template, goodNodes, badNodes,
customizationResponses);
Map<?, Exception> executionExceptions;
try {
executionExceptions = awaitCompletion(responses, executor, null, logger, "createNodesInGroup(" + group + ")");
executionExceptions = awaitCompletion(responses, userExecutor, null, logger, "createNodesInGroup(" + group + ")");
} catch (TimeoutException te) {
throw propagate(te);
}
@ -257,29 +255,24 @@ public class BaseComputeService implements ComputeService {
@Override
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> destroying nodes matching(%s)", filter);
Set<NodeMetadata> set = newLinkedHashSet(filter(transformParallel(nodesMatchingFilterAndNotTerminated(filter),
new Function<NodeMetadata, Future<? extends NodeMetadata>>() {
Set<NodeMetadata> set = ImmutableSet.copyOf(transformParallel(nodesMatchingFilterAndNotTerminated(filter),
new Function<NodeMetadata, ListenableFuture<? extends NodeMetadata>>() {
// TODO make an async interface instead of re-wrapping
@Override
public Future<NodeMetadata> apply(final NodeMetadata from) {
return executor.submit(new Callable<NodeMetadata>() {
@Nullable
@Override
public ListenableFuture<NodeMetadata> apply(final NodeMetadata from) {
return userExecutor.submit(new Callable<NodeMetadata>() {
public NodeMetadata call() throws Exception {
doDestroyNode(from.getId());
return from;
}
@Override
public String toString() {
return "destroyNode(" + from.getId() + ")";
}
});
}
}, executor, null, logger, "destroyNodesMatching(" + filter + ")"), notNull()));
}, userExecutor, null, logger, "destroyNodesMatching(" + filter + ")"));
logger.debug("<< destroyed(%d)", set.size());
cleanUpIncidentalResourcesOfDeadNodes(set);
@ -432,15 +425,15 @@ public class BaseComputeService implements ComputeService {
public void rebootNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> rebooting nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<? extends Void>>() {
new Function<NodeMetadata, ListenableFuture<? extends Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
public ListenableFuture<Void> apply(NodeMetadata from) {
rebootNode(from.getId());
return immediateFuture(null);
}
}, executor, null, logger, "rebootNodesMatching(" + filter + ")");
}, userExecutor, null, logger, "rebootNodesMatching(" + filter + ")");
logger.debug("<< rebooted");
}
@ -463,15 +456,15 @@ public class BaseComputeService implements ComputeService {
public void resumeNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> resuming nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<? extends Void>>() {
new Function<NodeMetadata, ListenableFuture<? extends Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
public ListenableFuture<Void> apply(NodeMetadata from) {
resumeNode(from.getId());
return immediateFuture(null);
}
}, executor, null, logger, "resumeNodesMatching(" + filter + ")");
}, userExecutor, null, logger, "resumeNodesMatching(" + filter + ")");
logger.debug("<< resumed");
}
@ -494,15 +487,15 @@ public class BaseComputeService implements ComputeService {
public void suspendNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> suspending nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<? extends Void>>() {
new Function<NodeMetadata, ListenableFuture<? extends Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
public ListenableFuture<Void> apply(NodeMetadata from) {
suspendNode(from.getId());
return immediateFuture(null);
}
}, executor, null, logger, "suspendNodesMatching(" + filter + ")");
}, userExecutor, null, logger, "suspendNodesMatching(" + filter + ")");
logger.debug("<< suspended");
}
@ -543,7 +536,7 @@ public class BaseComputeService implements ComputeService {
Map<NodeMetadata, ExecResponse> goodNodes = newLinkedHashMap();
Map<NodeMetadata, Exception> badNodes = newLinkedHashMap();
Map<NodeMetadata, Future<ExecResponse>> responses = newLinkedHashMap();
Map<NodeMetadata, ListenableFuture<ExecResponse>> responses = newLinkedHashMap();
Map<?, Exception> exceptions = ImmutableMap.<Object, Exception> of();
initAdminAccess.visit(runScript);
@ -552,11 +545,11 @@ public class BaseComputeService implements ComputeService {
nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), runScript, options, badNodes);
if (Iterables.size(scriptRunners) > 0) {
for (RunScriptOnNode runner : scriptRunners) {
responses.put(runner.getNode(), executor.submit(new RunScriptOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap(
responses.put(runner.getNode(), userExecutor.submit(new RunScriptOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap(
runner, goodNodes, badNodes)));
}
try {
exceptions = awaitCompletion(responses, executor, null, logger, "runScriptOnNodesMatching(" + filter + ")");
exceptions = awaitCompletion(responses, userExecutor, null, logger, "runScriptOnNodesMatching(" + filter + ")");
} catch (TimeoutException te) {
throw propagate(te);
}
@ -638,22 +631,18 @@ public class BaseComputeService implements ComputeService {
final NodeMetadata node1 = updateNodeWithCredentialsIfPresent(node, options);
ListenableFuture<ExecResponse> response = runScriptOnNodeFactory.submit(node1, runScript, options);
response.addListener(new Runnable() {
@Override
public void run() {
persistNodeCredentials.ifAdminAccess(runScript).apply(node1);
}
}, executor);
}, userExecutor);
return response;
}
private Iterable<? extends RunScriptOnNode> transformNodesIntoInitializedScriptRunners(
private Iterable<RunScriptOnNode> transformNodesIntoInitializedScriptRunners(
Iterable<? extends NodeMetadata> nodes, Statement script, RunScriptOptions options,
Map<NodeMetadata, Exception> badNodes) {
return filter(
transformParallel(nodes, new TransformNodesIntoInitializedScriptRunners(script, options, badNodes),
executor, null, logger, "initialize script runners"), notNull());
return filter(transformParallel(nodes, new TransformNodesIntoInitializedScriptRunners(script, options, badNodes),
userExecutor, null, logger, "initialize script runners"), notNull());
}
private Set<? extends NodeMetadata> detailsOnAllNodes() {
@ -690,7 +679,7 @@ public class BaseComputeService implements ComputeService {
}
private final class TransformNodesIntoInitializedScriptRunners implements
Function<NodeMetadata, Future<? extends RunScriptOnNode>> {
Function<NodeMetadata, ListenableFuture<? extends RunScriptOnNode>> {
private final Map<NodeMetadata, Exception> badNodes;
private final Statement script;
private final RunScriptOptions options;
@ -703,9 +692,9 @@ public class BaseComputeService implements ComputeService {
}
@Override
public Future<RunScriptOnNode> apply(NodeMetadata node) {
public ListenableFuture<RunScriptOnNode> apply(NodeMetadata node) {
node = updateNodeWithCredentialsIfPresent(node, options);
return executor.submit(initScriptRunnerFactory.create(node, script, options, badNodes));
return userExecutor.submit(initScriptRunnerFactory.create(node, script, options, badNodes));
}
}

View File

@ -19,7 +19,6 @@
package org.jclouds.compute.internal;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import javax.inject.Named;
import javax.inject.Singleton;
@ -40,6 +39,7 @@ import org.jclouds.xml.XMLParser;
import com.google.common.base.Function;
import com.google.common.eventbus.EventBus;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
import com.google.inject.Injector;
@ -55,11 +55,11 @@ public class UtilsImpl extends org.jclouds.rest.internal.UtilsImpl implements Ut
@Inject
UtilsImpl(Injector injector, Json json, XMLParser xml, HttpClient simpleClient, HttpAsyncClient simpleAsyncClient,
Crypto encryption, DateService date, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads, EventBus eventBus,
Crypto encryption, DateService date, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor, EventBus eventBus,
Map<String, Credentials> credentialStore, LoggerFactory loggerFactory,
Function<NodeMetadata, SshClient> sshForNode) {
super(injector, json, xml, simpleClient, simpleAsyncClient, encryption, date, userThreads, ioThreads, eventBus,
super(injector, json, xml, simpleClient, simpleAsyncClient, encryption, date, userExecutor, ioExecutor, eventBus,
credentialStore, loggerFactory);
this.sshForNode = sshForNode;
}

View File

@ -20,7 +20,6 @@ package org.jclouds.compute.strategy;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
import org.jclouds.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.NodeMetadata;
@ -28,6 +27,7 @@ import org.jclouds.compute.domain.Template;
import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.ImplementedBy;
/**
@ -37,6 +37,6 @@ import com.google.inject.ImplementedBy;
@ImplementedBy(CreateNodesWithGroupEncodedIntoNameThenAddToSet.class)
public interface CreateNodesInGroupThenAddToSet {
Map<?, Future<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
Map<?, ListenableFuture<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses);
}

View File

@ -24,13 +24,10 @@ import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Maps.newLinkedHashMap;
import static com.google.common.collect.Sets.newLinkedHashSet;
import static org.jclouds.compute.util.ComputeServiceUtils.formatStatus;
import static org.jclouds.concurrent.Futures.compose;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Resource;
@ -42,6 +39,7 @@ import org.jclouds.Constants;
import org.jclouds.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.ComputeMetadata;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.functions.GroupNamingConvention;
import org.jclouds.compute.reference.ComputeServiceConstants;
@ -53,6 +51,9 @@ import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* creates futures that correlate to
@ -95,7 +96,7 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet implements CreateNo
protected final CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy;
protected final ListNodesStrategy listNodesStrategy;
protected final GroupNamingConvention.Factory namingConvention;
protected final ExecutorService executor;
protected final ListeningExecutorService userExecutor;
protected final CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory;
@Inject
@ -103,12 +104,12 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet implements CreateNo
CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy,
ListNodesStrategy listNodesStrategy,
GroupNamingConvention.Factory namingConvention,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor,
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory) {
this.addNodeWithGroupStrategy = addNodeWithGroupStrategy;
this.listNodesStrategy = listNodesStrategy;
this.namingConvention = namingConvention;
this.executor = executor;
this.userExecutor = userExecutor;
this.customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory = customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory;
}
@ -117,13 +118,13 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet implements CreateNo
* simultaneously runs the nodes and applies options to them.
*/
@Override
public Map<?, Future<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
public Map<?, ListenableFuture<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
Map<String, Future<Void>> responses = newLinkedHashMap();
Map<String, ListenableFuture<Void>> responses = newLinkedHashMap();
for (String name : getNextNames(group, template, count)) {
responses.put(name, compose(createNodeInGroupWithNameAndTemplate(group, name, template),
responses.put(name, Futures.transform(createNodeInGroupWithNameAndTemplate(group, name, template),
customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory.create(template.getOptions(), goodNodes,
badNodes, customizationResponses), executor));
badNodes, customizationResponses), userExecutor));
}
return responses;
}
@ -141,10 +142,10 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet implements CreateNo
*
* <pre>
* &#064;Override
* protected Future&lt;AtomicReference&lt;NodeMetadata&gt;&gt; createNodeInGroupWithNameAndTemplate(String group, String name,
* protected ListenableFuture&lt;AtomicReference&lt;NodeMetadata&gt;&gt; createNodeInGroupWithNameAndTemplate(String group, String name,
* Template template) {
*
* Future&lt;AtomicReference&lt;NodeMetadata&gt;&gt; future = super.addNodeIntoGroupWithNameAndTemplate(group, name, template);
* ListenableFuture&lt;AtomicReference&lt;NodeMetadata&gt;&gt; future = super.addNodeIntoGroupWithNameAndTemplate(group, name, template);
* return Futures.compose(future, new Function&lt;AtomicReference&lt;NodeMetadata&gt;, AtomicReference&lt;NodeMetadata&gt;&gt;() {
*
* &#064;Override
@ -164,9 +165,9 @@ public class CreateNodesWithGroupEncodedIntoNameThenAddToSet implements CreateNo
* @param template user-specified template
* @return node that is created, yet not necessarily in {@link Status#RUNNING}
*/
protected Future<AtomicReference<NodeMetadata>> createNodeInGroupWithNameAndTemplate(String group, String name,
protected ListenableFuture<AtomicReference<NodeMetadata>> createNodeInGroupWithNameAndTemplate(String group, String name,
Template template) {
return executor.submit(new AddNode(name, group, template));
return userExecutor.submit(new AddNode(name, group, template));
}
/**

View File

@ -21,10 +21,9 @@ package org.jclouds.compute.stub.config;
import static org.jclouds.compute.util.ComputeServiceUtils.formatStatus;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
@ -37,11 +36,11 @@ import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.ImageBuilder;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.predicates.ImagePredicates;
import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
@ -51,9 +50,10 @@ import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
*
@ -63,7 +63,7 @@ import com.google.common.collect.ImmutableList.Builder;
public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAdapter {
private final Supplier<Location> location;
private final ConcurrentMap<String, NodeMetadata> nodes;
private final ExecutorService ioThreads;
private final ListeningExecutorService ioExecutor;
private final Provider<Integer> idProvider;
private final String publicIpPrefix;
private final String privateIpPrefix;
@ -73,12 +73,12 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
@Inject
public StubComputeServiceAdapter(ConcurrentMap<String, NodeMetadata> nodes,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads, Supplier<Location> location,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor, Supplier<Location> location,
@Named("NODE_ID") Provider<Integer> idProvider, @Named("PUBLIC_IP_PREFIX") String publicIpPrefix,
@Named("PRIVATE_IP_PREFIX") String privateIpPrefix, @Named("PASSWORD_PREFIX") String passwordPrefix,
JustProvider locationSupplier, Map<OsFamily, Map<String, String>> osToVersionMap) {
this.nodes = nodes;
this.ioThreads=ioThreads;
this.ioExecutor = ioExecutor;
this.location = location;
this.idProvider = idProvider;
this.publicIpPrefix = publicIpPrefix;
@ -96,7 +96,7 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
if (millis == 0l)
setStateOnNode(status, node);
else
ioThreads.execute(new Runnable() {
ioExecutor.execute(new Runnable() {
@Override
public void run() {
@ -187,7 +187,7 @@ public class StubComputeServiceAdapter implements JCloudsNativeComputeServiceAda
return;
setStateOnNodeAfterDelay(Status.PENDING, node, 0);
setStateOnNodeAfterDelay(Status.TERMINATED, node, 50);
ioThreads.execute(new Runnable() {
ioExecutor.execute(new Runnable() {
@Override
public void run() {

View File

@ -22,8 +22,6 @@ import static com.google.common.collect.Maps.newLinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject;
@ -37,6 +35,8 @@ import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
*
@ -45,22 +45,22 @@ import com.google.common.collect.Multimap;
@Singleton
public class ComputeUtils {
private final CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory;
private final ExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
public ComputeUtils(
CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory = customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory;
this.executor = executor;
this.userExecutor = userExecutor;
}
public Map<?, Future<Void>> customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(TemplateOptions options,
public Map<?, ListenableFuture<Void>> customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(TemplateOptions options,
Iterable<NodeMetadata> runningNodes, Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes,
Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
Map<NodeMetadata, Future<Void>> responses = newLinkedHashMap();
Map<NodeMetadata, ListenableFuture<Void>> responses = newLinkedHashMap();
for (NodeMetadata node : runningNodes) {
responses.put(node, executor.submit(customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory.create(
responses.put(node, userExecutor.submit(customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory.create(
options, new AtomicReference<NodeMetadata>(node), goodNodes, badNodes, customizationResponses)));
}
return responses;

View File

@ -18,7 +18,6 @@
*/
package org.jclouds.compute.util;
import static java.lang.String.format;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Predicates.or;
@ -27,12 +26,12 @@ import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.size;
import static com.google.common.util.concurrent.Atomics.newReference;
import static com.google.common.util.concurrent.MoreExecutors.listeningDecorator;
import static java.lang.String.format;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
import java.util.NoSuchElementException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@ -66,16 +65,16 @@ public class ConcurrentOpenSocketFinder implements OpenSocketFinder {
private final SocketOpen socketTester;
private final Predicate<AtomicReference<NodeMetadata>> nodeRunning;
private final ListeningExecutorService executor;
private final ListeningExecutorService userExecutor;
@Inject
@VisibleForTesting
ConcurrentOpenSocketFinder(SocketOpen socketTester,
@Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
@Named(PROPERTY_USER_THREADS) ExecutorService userThreads) {
@Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
this.socketTester = checkNotNull(socketTester, "socketTester");
this.nodeRunning = checkNotNull(nodeRunning, "nodeRunning");
this.executor = listeningDecorator(checkNotNull(userThreads, "userThreads"));
this.userExecutor = listeningDecorator(checkNotNull(userExecutor, "userExecutor"));
}
@Override
@ -123,7 +122,7 @@ public class ConcurrentOpenSocketFinder implements OpenSocketFinder {
Builder<ListenableFuture<?>> futures = ImmutableList.builder();
for (final HostAndPort socket : input) {
futures.add(executor.submit(new Runnable() {
futures.add(userExecutor.submit(new Runnable() {
@Override
public void run() {

View File

@ -27,7 +27,6 @@ import static org.testng.Assert.fail;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicBoolean;
import org.jclouds.compute.callables.BlockUntilInitScriptStatusIsZeroThenReturnOutput.ExitStatusOfCommandGreaterThanZero;
@ -42,6 +41,7 @@ import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.eventbus.EventBus;
import com.google.common.util.concurrent.AbstractFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
/**
@ -139,7 +139,7 @@ public class BlockUntilInitScriptStatusIsZeroThenReturnOutputTest {
EventBus eventBus = new EventBus();
public void testExitStatusZeroReturnsExecResponse() throws InterruptedException, ExecutionException {
ExecutorService userThreads = MoreExecutors.sameThreadExecutor();
ListeningExecutorService userExecutor = MoreExecutors.sameThreadExecutor();
Predicate<String> notRunningAnymore = Predicates.alwaysTrue();
SudoAwareInitManager commandRunner = createMockBuilder(SudoAwareInitManager.class).addMockedMethod("runAction")
.addMockedMethod("getStatement").addMockedMethod("getNode").addMockedMethod("toString")
@ -155,7 +155,7 @@ public class BlockUntilInitScriptStatusIsZeroThenReturnOutputTest {
replay(commandRunner, initScript);
BlockUntilInitScriptStatusIsZeroThenReturnOutput future = new BlockUntilInitScriptStatusIsZeroThenReturnOutput(
userThreads, eventBus, notRunningAnymore, commandRunner);
userExecutor, eventBus, notRunningAnymore, commandRunner);
future.run();
@ -167,7 +167,7 @@ public class BlockUntilInitScriptStatusIsZeroThenReturnOutputTest {
public void testFirstExitStatusOneButSecondExitStatusZeroReturnsExecResponse() throws InterruptedException,
ExecutionException {
ExecutorService userThreads = MoreExecutors.sameThreadExecutor();
ListeningExecutorService userExecutor = MoreExecutors.sameThreadExecutor();
Predicate<String> notRunningAnymore = Predicates.alwaysTrue();
SudoAwareInitManager commandRunner = createMockBuilder(SudoAwareInitManager.class).addMockedMethod("runAction")
@ -190,7 +190,7 @@ public class BlockUntilInitScriptStatusIsZeroThenReturnOutputTest {
replay(commandRunner, initScript);
BlockUntilInitScriptStatusIsZeroThenReturnOutput future = new BlockUntilInitScriptStatusIsZeroThenReturnOutput(
userThreads, eventBus, notRunningAnymore, commandRunner);
userExecutor, eventBus, notRunningAnymore, commandRunner);
future.run();
@ -201,7 +201,7 @@ public class BlockUntilInitScriptStatusIsZeroThenReturnOutputTest {
}
public void testCancelInterruptStopsCommand() throws InterruptedException, ExecutionException {
ExecutorService userThreads = MoreExecutors.sameThreadExecutor();
ListeningExecutorService userExecutor = MoreExecutors.sameThreadExecutor();
Predicate<String> notRunningAnymore = Predicates.alwaysTrue();
SudoAwareInitManager commandRunner = createMockBuilder(SudoAwareInitManager.class).addMockedMethod(
"refreshAndRunAction").addMockedMethod("runAction").addMockedMethod("getStatement").addMockedMethod(
@ -229,7 +229,7 @@ public class BlockUntilInitScriptStatusIsZeroThenReturnOutputTest {
replay(commandRunner, initScript);
BlockUntilInitScriptStatusIsZeroThenReturnOutput future = new BlockUntilInitScriptStatusIsZeroThenReturnOutput(
userThreads, eventBus, notRunningAnymore, commandRunner);
userExecutor, eventBus, notRunningAnymore, commandRunner);
future.cancel(true);
@ -246,7 +246,7 @@ public class BlockUntilInitScriptStatusIsZeroThenReturnOutputTest {
public void testCancelDontInterruptLeavesCommandRunningAndReturnsLastStatus() throws InterruptedException,
ExecutionException {
ExecutorService userThreads = MoreExecutors.sameThreadExecutor();
ListeningExecutorService userExecutor = MoreExecutors.sameThreadExecutor();
Predicate<String> notRunningAnymore = Predicates.alwaysTrue();
SudoAwareInitManager commandRunner = createMockBuilder(SudoAwareInitManager.class).addMockedMethod("runAction")
.addMockedMethod("getStatement").addMockedMethod("getNode").addMockedMethod("toString")
@ -262,7 +262,7 @@ public class BlockUntilInitScriptStatusIsZeroThenReturnOutputTest {
replay(commandRunner, initScript);
BlockUntilInitScriptStatusIsZeroThenReturnOutput future = new BlockUntilInitScriptStatusIsZeroThenReturnOutput(
userThreads, eventBus, notRunningAnymore, commandRunner);
userExecutor, eventBus, notRunningAnymore, commandRunner);
future.cancel(false);

View File

@ -423,7 +423,7 @@ public abstract class BaseComputeServiceLiveTest extends BaseComputeServiceConte
final long timeoutMs = 20 * 60 * 1000;
List<String> groups = Lists.newArrayList();
List<ListenableFuture<NodeMetadata>> futures = Lists.newArrayList();
ListeningExecutorService executor = MoreExecutors.listeningDecorator(context.utils().userExecutor());
ListeningExecutorService userExecutor = MoreExecutors.listeningDecorator(context.utils().userExecutor());
try {
for (int i = 0; i < 2; i++) {
@ -431,7 +431,7 @@ public abstract class BaseComputeServiceLiveTest extends BaseComputeServiceConte
final String group = "twin" + groupNum;
groups.add(group);
ListenableFuture<NodeMetadata> future = executor.submit(new Callable<NodeMetadata>() {
ListenableFuture<NodeMetadata> future = userExecutor.submit(new Callable<NodeMetadata>() {
public NodeMetadata call() throws Exception {
NodeMetadata node = getOnlyElement(client.createNodesInGroup(group, 1, inboundPorts(22, 8080)
.blockOnPort(22, 300 + groupNum)));

View File

@ -30,7 +30,6 @@ import static org.testng.Assert.fail;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@ -47,6 +46,8 @@ import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.net.HostAndPort;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
@Test(singleThreaded = true)
public class ConcurrentOpenSocketFinderTest {
@ -67,24 +68,24 @@ public class ConcurrentOpenSocketFinderTest {
private final Predicate<AtomicReference<NodeMetadata>> nodeRunning = alwaysTrue();
private final Predicate<AtomicReference<NodeMetadata>> nodeNotRunning = alwaysFalse();
private ExecutorService threadPool;
private ListeningExecutorService userExecutor;
@BeforeClass
public void setUp() {
threadPool = Executors.newCachedThreadPool();
userExecutor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
}
@AfterClass(alwaysRun = true)
public void tearDown() {
if (threadPool != null)
threadPool.shutdownNow();
if (userExecutor != null)
userExecutor.shutdownNow();
}
@Test
public void testRespectsTimeout() throws Exception {
final long timeoutMs = 1000;
OpenSocketFinder finder = new ConcurrentOpenSocketFinder(socketAlwaysClosed, nodeRunning, threadPool);
OpenSocketFinder finder = new ConcurrentOpenSocketFinder(socketAlwaysClosed, nodeRunning, userExecutor);
Stopwatch stopwatch = new Stopwatch();
stopwatch.start();
@ -109,7 +110,7 @@ public class ConcurrentOpenSocketFinderTest {
}
};
OpenSocketFinder finder = new ConcurrentOpenSocketFinder(secondSocketOpen, nodeRunning, threadPool);
OpenSocketFinder finder = new ConcurrentOpenSocketFinder(secondSocketOpen, nodeRunning, userExecutor);
HostAndPort result = finder.findOpenSocketOnNode(node, 22, 2000, MILLISECONDS);
assertEquals(result, HostAndPort.fromParts("1.2.3.5", 22));
@ -122,7 +123,7 @@ public class ConcurrentOpenSocketFinderTest {
HostAndPort.fromParts("1.2.3.4", 22), new SlowCallable<Boolean>(true, 1500),
HostAndPort.fromParts("1.2.3.5", 22), new SlowCallable<Boolean>(true, 1000)));
OpenSocketFinder finder = new ConcurrentOpenSocketFinder(socketTester, nodeRunning, threadPool);
OpenSocketFinder finder = new ConcurrentOpenSocketFinder(socketTester, nodeRunning, userExecutor);
HostAndPort result = finder.findOpenSocketOnNode(node, 22, 2000, MILLISECONDS);
assertEquals(result, HostAndPort.fromParts("1.2.3.5", 22));
@ -131,7 +132,7 @@ public class ConcurrentOpenSocketFinderTest {
@Test
public void testAbortsWhenNodeNotRunning() throws Exception {
OpenSocketFinder finder = new ConcurrentOpenSocketFinder(socketAlwaysClosed, nodeNotRunning, threadPool) {
OpenSocketFinder finder = new ConcurrentOpenSocketFinder(socketAlwaysClosed, nodeNotRunning, userExecutor) {
@Override
protected <T> Predicate<T> retryPredicate(final Predicate<T> findOrBreak, long period, long timeoutValue,
TimeUnit timeUnits) {

View File

@ -27,16 +27,14 @@ import static org.jclouds.util.Throwables2.containsThrowable;
import static org.jclouds.util.Throwables2.propagateAuthorizationOrOriginalException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Resource;
import javax.inject.Named;
import org.jclouds.Constants;
@ -47,6 +45,8 @@ import org.jclouds.rest.AuthorizationException;
import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
/**
@ -69,21 +69,21 @@ public class FutureIterables {
private static BackoffLimitedRetryHandler retryHandler = BackoffLimitedRetryHandler.INSTANCE;
public static <F, T> Iterable<T> transformParallel(final Iterable<F> fromIterable,
final Function<? super F, Future<? extends T>> function, ExecutorService exec, @Nullable Long maxTime, Logger logger,
final Function<? super F, ListenableFuture<? extends T>> function, ListeningExecutorService exec, @Nullable Long maxTime, Logger logger,
String logPrefix) {
return transformParallel(fromIterable, function, exec, maxTime, logger, logPrefix, retryHandler, maxRetries);
}
@SuppressWarnings("unchecked")
public static <F, T> Iterable<T> transformParallel(Iterable<F> fromIterable,
Function<? super F, Future<? extends T>> function, ExecutorService exec, @Nullable Long maxTime, Logger logger,
Function<? super F, ListenableFuture<? extends T>> function, ListeningExecutorService exec, @Nullable Long maxTime, Logger logger,
String logPrefix, BackoffLimitedRetryHandler retryHandler, int maxRetries) {
Map<F, Exception> exceptions = newHashMap();
Map<F, Future<? extends T>> responses = newHashMap();
Map<F, ListenableFuture<? extends T>> responses = newHashMap();
for (int i = 0; i < maxRetries; i++) {
for (F from : fromIterable) {
Future<? extends T> to = function.apply(from);
ListenableFuture<? extends T> to = function.apply(from);
responses.put(from, to);
}
try {
@ -107,9 +107,10 @@ public class FutureIterables {
return unwrap(responses.values());
}
public static <T> Map<T, Exception> awaitCompletion(Map<T, ? extends Future<?>> responses, ExecutorService exec,
@Nullable Long maxTime, final Logger logger, final String logPrefix) throws TimeoutException {
final ConcurrentMap<T, Exception> errorMap = newConcurrentMap();
public static <F> Map<F, Exception> awaitCompletion(Map<F, ? extends ListenableFuture<?>> responses,
ListeningExecutorService exec, @Nullable Long maxTime, final Logger logger, final String logPrefix)
throws TimeoutException {
final ConcurrentMap<F, Exception> errorMap = newConcurrentMap();
if (responses.size() == 0)
return errorMap;
final int total = responses.size();
@ -117,8 +118,8 @@ public class FutureIterables {
final AtomicInteger complete = new AtomicInteger(0);
final AtomicInteger errors = new AtomicInteger(0);
final long start = System.currentTimeMillis();
for (final java.util.Map.Entry<T, ? extends Future<?>> future : responses.entrySet()) {
Futures.makeListenable(future.getValue(), exec).addListener(new Runnable() {
for (final Entry<F, ? extends ListenableFuture<?>> future : responses.entrySet()) {
future.getValue().addListener(new Runnable() {
@Override
public void run() {
@ -168,10 +169,10 @@ public class FutureIterables {
return errorMap;
}
private static <T> Iterable<T> unwrap(Iterable<Future<? extends T>> values) {
return transform(values, new Function<Future<? extends T>, T>() {
private static <T> Iterable<T> unwrap(Iterable<ListenableFuture<? extends T>> values) {
return transform(values, new Function<ListenableFuture<? extends T>, T>() {
@Override
public T apply(Future<? extends T> from) {
public T apply(ListenableFuture<? extends T> from) {
try {
return from.get();
} catch (InterruptedException e) {

View File

@ -1,282 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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 static com.google.common.base.Preconditions.checkNotNull;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import com.google.common.annotations.Beta;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.collect.ForwardingObject;
import com.google.common.util.concurrent.ExecutionList;
import com.google.common.util.concurrent.ForwardingFuture;
import com.google.common.util.concurrent.ListenableFuture;
/**
* functions related to or replacing those in {@link com.google.common.util.concurrent.Futures}
*
* @author Adrian Cole
*/
@Beta
public class Futures {
@VisibleForTesting
static class CallGetAndRunExecutionList<T> implements Runnable {
private final Future<T> delegate;
private final ExecutionList executionList;
CallGetAndRunExecutionList(Future<T> delegate, ExecutionList executionList) {
this.delegate = checkNotNull(delegate, "delegate");
this.executionList = checkNotNull(executionList, "executionList");
}
@Override
public void run() {
try {
delegate.get();
} catch (InterruptedException e) {
// This thread was interrupted. This should never happen, so we
// throw an IllegalStateException.
Thread.currentThread().interrupt();
// TODO we cannot inspect the executionList at the moment to make a reasonable
// toString()
throw new IllegalStateException(String.format(
"interrupted calling get() on [%s], so could not run listeners", delegate), e);
} catch (Throwable e) {
// ExecutionException / CancellationException / RuntimeException
// The task is done, run the listeners.
}
executionList.execute();
}
@Override
public String toString() {
return "[delegate=" + delegate + ", executionList=" + executionList + "]";
}
}
// Adapted from Guava
//
// * to allow us to enforce supply of an adapterExecutor
// note that this is done so that we can operate in Google AppEngine which
// restricts thread creation
// * to allow us to print debug info about what the delegate was doing
private static class FutureListener<T> {
private final ExecutorService adapterExecutor;
// The execution list to hold our listeners.
private final ExecutionList executionList = new ExecutionList();
// This allows us to only start up a thread waiting on the delegate future
// when the first listener is added.
private final AtomicBoolean hasListeners = new AtomicBoolean(false);
// The delegate future.
private final Future<T> delegate;
private static <T> FutureListener<T> create(Future<T> delegate, ExecutorService adapterExecutor) {
return new FutureListener<T>(delegate, adapterExecutor);
}
private FutureListener(Future<T> delegate, ExecutorService adapterExecutor) {
this.delegate = checkNotNull(delegate, "delegate");
this.adapterExecutor = checkNotNull(adapterExecutor, "adapterExecutor");
}
private void addListener(Runnable listener, Executor exec) {
executionList.add(listener, exec);
// When a listener is first added, we run a task that will wait for
// the delegate to finish, and when it is done will run the listeners.
if (hasListeners.compareAndSet(false, true)) {
if (delegate.isDone()) {
// If the delegate is already done, run the execution list
// immediately on the current thread.
executionList.execute();
return;
}
adapterExecutor.execute(new CallGetAndRunExecutionList<T>(delegate, executionList));
}
}
private Future<T> getFuture() {
return delegate;
}
}
private static class ListenableFutureAdapter<T> extends ForwardingFuture<T> implements ListenableFuture<T> {
private final FutureListener<T> futureListener;
private static <T> ListenableFutureAdapter<T> create(Future<T> future, ExecutorService executor) {
return new ListenableFutureAdapter<T>(future, executor);
}
private ListenableFutureAdapter(Future<T> future, ExecutorService executor) {
this.futureListener = FutureListener.create(future, executor);
}
@Override
protected Future<T> delegate() {
return futureListener.getFuture();
}
@Override
public void addListener(Runnable listener, Executor exec) {
futureListener.addListener(listener, exec);
}
}
private static class LazyListenableFutureFunctionAdapter<I, O> extends ForwardingObject implements
ListenableFuture<O> {
private final FutureListener<I> futureListener;
private final Function<? super I, ? extends O> function;
private static <I, O> LazyListenableFutureFunctionAdapter<I, O> create(Future<I> future,
Function<? super I, ? extends O> function, ExecutorService executor) {
return new LazyListenableFutureFunctionAdapter<I, O>(future, function, executor);
}
private static <I, O> LazyListenableFutureFunctionAdapter<I, O> create(FutureListener<I> futureListener,
Function<? super I, ? extends O> function) {
return new LazyListenableFutureFunctionAdapter<I, O>(futureListener, function);
}
private LazyListenableFutureFunctionAdapter(Future<I> future, Function<? super I, ? extends O> function,
ExecutorService executor) {
this(FutureListener.create(future, executor), function);
}
private LazyListenableFutureFunctionAdapter(FutureListener<I> futureListener,
Function<? super I, ? extends O> function) {
this.futureListener = checkNotNull(futureListener, "futureListener");
this.function = checkNotNull(function, "function");
}
/*
* Concurrency detail:
*
* <p>To preserve the idempotency of calls to this.get(*) calls to the function are only
* applied once. A lock is required to prevent multiple applications of the function. The
* calls to future.get(*) are performed outside the lock, as is required to prevent calls to
* get(long, TimeUnit) to persist beyond their timeout.
*
* <p>Calls to future.get(*) on every call to this.get(*) also provide the cancellation
* behavior for this.
*
* <p>(Consider: in thread A, call get(), in thread B call get(long, TimeUnit). Thread B may
* have to wait for Thread A to finish, which would be unacceptable.)
*
* <p>Note that each call to Future<O>.get(*) results in a call to Future<I>.get(*), but the
* function is only applied once, so Future<I>.get(*) is assumed to be idempotent.
*/
private final Object lock = new Object();
private boolean set = false;
private O value = null;
@Override
public O get() throws InterruptedException, ExecutionException {
return apply(futureListener.getFuture().get());
}
@Override
public O get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return apply(futureListener.getFuture().get(timeout, unit));
}
private O apply(I raw) {
synchronized (lock) {
if (!set) {
value = function.apply(raw);
set = true;
}
return value;
}
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return futureListener.getFuture().cancel(mayInterruptIfRunning);
}
@Override
public boolean isCancelled() {
return futureListener.getFuture().isCancelled();
}
@Override
public boolean isDone() {
return futureListener.getFuture().isDone();
}
@Override
public void addListener(Runnable listener, Executor exec) {
futureListener.addListener(listener, exec);
}
@Override
protected Object delegate() {
return futureListener.getFuture();
}
}
/**
* Just like {@code Futures#compose} except that we check the type of the executorService before
* creating the Future. If we are single threaded, invoke the function lazy as opposed to
* chaining, so that we don't invoke get() early.
*/
public static <I, O> ListenableFuture<O> compose(Future<I> future, final Function<? super I, ? extends O> function,
ExecutorService executorService) {
if (future instanceof Futures.ListenableFutureAdapter<?>) {
Futures.ListenableFutureAdapter<I> lf = (ListenableFutureAdapter<I>) future;
if (lf.futureListener.adapterExecutor.getClass().isAnnotationPresent(SingleThreaded.class))
return Futures.LazyListenableFutureFunctionAdapter.create(
((org.jclouds.concurrent.Futures.ListenableFutureAdapter<I>) future).futureListener, function);
else
return com.google.common.util.concurrent.Futures.transform(lf, function, executorService);
} else if (executorService.getClass().isAnnotationPresent(SingleThreaded.class)) {
return Futures.LazyListenableFutureFunctionAdapter.create(future, function, executorService);
} else {
return com.google.common.util.concurrent.Futures.transform(Futures.makeListenable(future, executorService),
function, executorService);
}
}
/**
* Just like {@code Futures#makeListenable} except that we pass in an executorService.
* <p/>
* Temporary hack until http://code.google.com/p/guava-libraries/issues/detail?id=317 is fixed.
*/
public static <T> ListenableFuture<T> makeListenable(Future<T> future, ExecutorService executorService) {
if (future instanceof ListenableFuture<?>) {
return (ListenableFuture<T>) future;
}
return ListenableFutureAdapter.create(future, executorService);
}
}

View File

@ -1,130 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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.config;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
class DescribedFuture<T> implements Future<T> {
protected final Future<T> delegate;
private final String description;
private StackTraceElement[] submissionTrace;
DescribedFuture(Future<T> delegate, String description, StackTraceElement[] submissionTrace) {
this.delegate = delegate;
this.description = description;
this.submissionTrace = submissionTrace;
}
@Override
public boolean cancel(boolean arg0) {
return delegate.cancel(arg0);
}
@Override
public T get() throws InterruptedException, ExecutionException {
try {
return delegate.get();
} catch (ExecutionException e) {
throw ensureCauseHasSubmissionTrace(e);
} catch (InterruptedException e) {
throw ensureCauseHasSubmissionTrace(e);
}
}
@Override
public T get(long arg0, TimeUnit arg1) throws InterruptedException, ExecutionException, TimeoutException {
try {
return delegate.get(arg0, arg1);
} catch (ExecutionException e) {
throw ensureCauseHasSubmissionTrace(e);
} catch (InterruptedException e) {
throw ensureCauseHasSubmissionTrace(e);
} catch (TimeoutException e) {
throw ensureCauseHasSubmissionTrace(e);
}
}
/** This method does the work to ensure _if_ a submission stack trace was provided,
* it is included in the exception. most errors are thrown from the frame of the
* Future.get call, with a cause that took place in the executor's thread.
* We extend the stack trace of that cause with the submission stack trace.
* (An alternative would be to put the stack trace as a root cause,
* at the bottom of the stack, or appended to all traces, or inserted
* after the second cause, etc ... but since we can't change the "Caused by:"
* method in Throwable the compromise made here seems best.)
*/
private <ET extends Exception> ET ensureCauseHasSubmissionTrace(ET e) {
if (submissionTrace==null) return e;
if (e.getCause()==null) {
ExecutionException ee = new ExecutionException("task submitted from the following trace", null);
e.initCause(ee);
return e;
}
Throwable cause = e.getCause();
StackTraceElement[] causeTrace = cause.getStackTrace();
boolean causeIncludesSubmissionTrace = submissionTrace.length >= causeTrace.length;
for (int i=0; causeIncludesSubmissionTrace && i<submissionTrace.length; i++) {
if (!causeTrace[causeTrace.length-1-i].equals(submissionTrace[submissionTrace.length-1-i])) {
causeIncludesSubmissionTrace = false;
}
}
if (!causeIncludesSubmissionTrace) {
cause.setStackTrace(merge(causeTrace, submissionTrace));
}
return e;
}
private StackTraceElement[] merge(StackTraceElement[] t1, StackTraceElement[] t2) {
StackTraceElement[] t12 = new StackTraceElement[t1.length + t2.length];
System.arraycopy(t1, 0, t12, 0, t1.length);
System.arraycopy(t2, 0, t12, t1.length, t2.length);
return t12;
}
@Override
public boolean isCancelled() {
return delegate.isCancelled();
}
@Override
public boolean isDone() {
return delegate.isDone();
}
@Override
public boolean equals(Object obj) {
return delegate.equals(obj);
}
@Override
public int hashCode() {
return delegate.hashCode();
}
@Override
public String toString() {
return description;
}
}

View File

@ -1,124 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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.config;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.concurrent.config.ExecutorServiceModule.getStackTraceHere;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class DescribingExecutorService implements ExecutorService {
protected final ExecutorService delegate;
public DescribingExecutorService(ExecutorService delegate) {
this.delegate = checkNotNull(delegate, "delegate");
}
@Override
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
return delegate.awaitTermination(timeout, unit);
}
@Override
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
return delegate.invokeAll(tasks);
}
@Override
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
throws InterruptedException {
return delegate.invokeAll(tasks, timeout, unit);
}
@Override
public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
return delegate.invokeAny(tasks);
}
@Override
public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return delegate.invokeAny(tasks, timeout, unit);
}
@Override
public boolean isShutdown() {
return delegate.isShutdown();
}
@Override
public boolean isTerminated() {
return delegate.isTerminated();
}
@Override
public void shutdown() {
delegate.shutdown();
}
@Override
public List<Runnable> shutdownNow() {
return delegate.shutdownNow();
}
@Override
public <T> Future<T> submit(Callable<T> task) {
return new DescribedFuture<T>(delegate.submit(task), task.toString(), getStackTraceHere());
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Future<?> submit(Runnable task) {
return new DescribedFuture(delegate.submit(task), task.toString(), getStackTraceHere());
}
@Override
public <T> Future<T> submit(Runnable task, T result) { // NO_UCD
return new DescribedFuture<T>(delegate.submit(task, result), task.toString(), getStackTraceHere());
}
@Override
public void execute(Runnable arg0) {
delegate.execute(arg0);
}
@Override
public boolean equals(Object obj) {
return delegate.equals(obj);
}
@Override
public int hashCode() {
return delegate.hashCode();
}
@Override
public String toString() {
return delegate.toString();
}
}

View File

@ -18,6 +18,7 @@
*/
package org.jclouds.concurrent.config;
import static com.google.common.util.concurrent.MoreExecutors.listeningDecorator;
import static org.jclouds.Constants.PROPERTY_IO_WORKER_THREADS;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import static org.jclouds.concurrent.DynamicExecutors.newScalingThreadPool;
@ -30,19 +31,19 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.lifecycle.Closer;
import org.jclouds.logging.Logger;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
/**
* Configures {@link ExecutorService}.
* Configures {@link ListeningExecutorService}.
*
* Note that this uses threads.
*
@ -60,9 +61,9 @@ public class ExecutorServiceModule extends AbstractModule {
@Resource
private Logger logger = Logger.NULL;
private final ExecutorService service;
private final ListeningExecutorService service;
private ShutdownExecutorOnClose(ExecutorService service) {
private ShutdownExecutorOnClose(ListeningExecutorService service) {
this.service = service;
}
@ -74,26 +75,23 @@ public class ExecutorServiceModule extends AbstractModule {
}
}
final ExecutorService userExecutorFromConstructor;
final ExecutorService ioExecutorFromConstructor;
@Inject
public ExecutorServiceModule(@Named(PROPERTY_USER_THREADS) ExecutorService userThreads,
@Named(PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads) {
this.userExecutorFromConstructor = addToStringOnSubmit(userThreads);
this.ioExecutorFromConstructor = addToStringOnSubmit(ioThreads);
}
private ExecutorService addToStringOnSubmit(ExecutorService executor) {
if (executor != null) {
return new DescribingExecutorService(executor);
}
return executor;
}
final ListeningExecutorService userExecutorFromConstructor;
final ListeningExecutorService ioExecutorFromConstructor;
public ExecutorServiceModule() {
this(null, null);
this.userExecutorFromConstructor = null;
this.ioExecutorFromConstructor = null;
}
public ExecutorServiceModule(@Named(PROPERTY_USER_THREADS) ExecutorService userExecutor,
@Named(PROPERTY_IO_WORKER_THREADS) ExecutorService ioExecutor) {
this(listeningDecorator(userExecutor), listeningDecorator(ioExecutor));
}
public ExecutorServiceModule(@Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
@Named(PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor) {
this.userExecutorFromConstructor = WithSubmissionTrace.wrap(userExecutor);
this.ioExecutorFromConstructor = WithSubmissionTrace.wrap(ioExecutor);
}
@Override
@ -103,50 +101,55 @@ public class ExecutorServiceModule extends AbstractModule {
@Provides
@Singleton
@Named(PROPERTY_USER_THREADS)
ExecutorService provideExecutorService(@Named(PROPERTY_USER_THREADS) int count, Closer closer) { // NO_UCD
ListeningExecutorService provideListeningUserExecutorService(@Named(PROPERTY_USER_THREADS) int count, Closer closer) { // NO_UCD
if (userExecutorFromConstructor != null)
return userExecutorFromConstructor;
return shutdownOnClose(addToStringOnSubmit(newThreadPoolNamed("user thread %d", count)), closer);
return shutdownOnClose(WithSubmissionTrace.wrap(newThreadPoolNamed("user thread %d", count)), closer);
}
@Provides
@Singleton
@Named(PROPERTY_IO_WORKER_THREADS)
ExecutorService provideIOExecutor(@Named(PROPERTY_IO_WORKER_THREADS) int count, Closer closer) { // NO_UCD
ListeningExecutorService provideListeningIOExecutorService(@Named(PROPERTY_IO_WORKER_THREADS) int count,
Closer closer) { // NO_UCD
if (ioExecutorFromConstructor != null)
return ioExecutorFromConstructor;
return shutdownOnClose(addToStringOnSubmit(newThreadPoolNamed("i/o thread %d", count)), closer);
return shutdownOnClose(WithSubmissionTrace.wrap(newThreadPoolNamed("i/o thread %d", count)), closer);
}
static <T extends ExecutorService> T shutdownOnClose(final T service, Closer closer) {
@Provides
@Singleton
@Named(PROPERTY_USER_THREADS)
ExecutorService provideUserExecutorService(@Named(PROPERTY_USER_THREADS) ListeningExecutorService in) { // NO_UCD
return in;
}
@Provides
@Singleton
@Named(PROPERTY_IO_WORKER_THREADS)
ExecutorService provideIOExecutorService(@Named(PROPERTY_IO_WORKER_THREADS) ListeningExecutorService in) { // NO_UCD
return in;
}
static <T extends ListeningExecutorService> T shutdownOnClose(final T service, Closer closer) {
closer.addToClose(new ShutdownExecutorOnClose(service));
return service;
}
private ExecutorService newCachedThreadPoolNamed(String name) {
return Executors.newCachedThreadPool(namedThreadFactory(name));
private ListeningExecutorService newCachedThreadPoolNamed(String name) {
return listeningDecorator(Executors.newCachedThreadPool(namedThreadFactory(name)));
}
private ExecutorService newThreadPoolNamed(String name, int maxCount) {
private ListeningExecutorService newThreadPoolNamed(String name, int maxCount) {
return maxCount == 0 ? newCachedThreadPoolNamed(name) : newScalingThreadPoolNamed(name, maxCount);
}
private ExecutorService newScalingThreadPoolNamed(String name, int maxCount) {
return newScalingThreadPool(1, maxCount, 60L * 1000, namedThreadFactory(name));
private ListeningExecutorService newScalingThreadPoolNamed(String name, int maxCount) {
return listeningDecorator(newScalingThreadPool(1, maxCount, 60L * 1000, namedThreadFactory(name)));
}
private ThreadFactory namedThreadFactory(String name) {
return new ThreadFactoryBuilder().setNameFormat(name).setThreadFactory(Executors.defaultThreadFactory()).build();
}
/** returns the stack trace at the caller */
static StackTraceElement[] getStackTraceHere() {
// remove the first two items in the stack trace (because the first one refers to the call to
// Thread.getStackTrace, and the second one is us)
StackTraceElement[] fullSubmissionTrace = Thread.currentThread().getStackTrace();
StackTraceElement[] cleanedSubmissionTrace = new StackTraceElement[fullSubmissionTrace.length - 2];
System.arraycopy(fullSubmissionTrace, 2, cleanedSubmissionTrace, 0, cleanedSubmissionTrace.length);
return cleanedSubmissionTrace;
}
}

View File

@ -1,22 +1,21 @@
package org.jclouds.concurrent.config;
import static com.google.common.util.concurrent.MoreExecutors.listeningDecorator;
import static java.util.concurrent.Executors.defaultThreadFactory;
import static java.util.concurrent.Executors.newScheduledThreadPool;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.jclouds.Constants.PROPERTY_SCHEDULER_THREADS;
import static org.jclouds.concurrent.config.ExecutorServiceModule.getStackTraceHere;
import static org.jclouds.concurrent.config.ExecutorServiceModule.shutdownOnClose;
import java.util.concurrent.Callable;
import java.util.concurrent.Delayed;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.lifecycle.Closer;
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
@ -32,76 +31,28 @@ import com.google.inject.Provides;
*
*/
public class ScheduledExecutorServiceModule extends AbstractModule {
private static class DescribingScheduledExecutorService extends DescribingExecutorService implements
ScheduledExecutorService {
private DescribingScheduledExecutorService(ScheduledExecutorService delegate) {
super(delegate);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
return new DescribedScheduledFuture(((ScheduledExecutorService) delegate).schedule(command, delay, unit),
command.toString(), getStackTraceHere());
}
@Override
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
return new DescribedScheduledFuture<V>(((ScheduledExecutorService) delegate).schedule(callable, delay, unit),
callable.toString(), getStackTraceHere());
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
return new DescribedScheduledFuture(((ScheduledExecutorService) delegate).scheduleAtFixedRate(command,
initialDelay, period, unit), command.toString(), getStackTraceHere());
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
return new DescribedScheduledFuture(((ScheduledExecutorService) delegate).scheduleWithFixedDelay(command,
initialDelay, delay, unit), command.toString(), getStackTraceHere());
}
}
private static class DescribedScheduledFuture<T> extends DescribedFuture<T> implements ScheduledFuture<T> {
private DescribedScheduledFuture(ScheduledFuture<T> delegate, String description,
StackTraceElement[] submissionTrace) {
super(delegate, description, submissionTrace);
}
@Override
public long getDelay(TimeUnit unit) {
return ((ScheduledFuture<T>) delegate).getDelay(unit);
}
@Override
public int compareTo(Delayed o) {
return ((ScheduledFuture<T>) delegate).compareTo(o);
}
}
private static ScheduledExecutorService addToStringOnSchedule(ScheduledExecutorService executor) {
return (executor != null) ? new DescribingScheduledExecutorService(executor) : executor;
@Provides
@Singleton
@Named(PROPERTY_SCHEDULER_THREADS)
ListeningScheduledExecutorService provideListeningScheduledExecutorService(
@Named(PROPERTY_SCHEDULER_THREADS) int count, Closer closer) {
return shutdownOnClose(WithSubmissionTrace.wrap(newScheduledThreadPoolNamed("scheduler thread %d", count)),
closer);
}
@Provides
@Singleton
@Named(PROPERTY_SCHEDULER_THREADS)
ScheduledExecutorService provideScheduledExecutor(@Named(PROPERTY_SCHEDULER_THREADS) int count, Closer closer) {
return shutdownOnClose(addToStringOnSchedule(newScheduledThreadPoolNamed("scheduler thread %d", count)), closer);
ScheduledExecutorService provideScheduledExecutor(
@Named(PROPERTY_SCHEDULER_THREADS) ListeningScheduledExecutorService in) {
return in;
}
private static ScheduledExecutorService newScheduledThreadPoolNamed(String name, int maxCount) {
ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat(name)
.setThreadFactory(Executors.defaultThreadFactory()).build();
return maxCount == 0 ? Executors.newSingleThreadScheduledExecutor(factory) : Executors.newScheduledThreadPool(
maxCount, factory);
private static ListeningScheduledExecutorService newScheduledThreadPoolNamed(String name, int maxCount) {
ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat(name).setThreadFactory(defaultThreadFactory())
.build();
return listeningDecorator(maxCount == 0 ? newSingleThreadScheduledExecutor(factory) : newScheduledThreadPool(
maxCount, factory));
}
@Override

View File

@ -0,0 +1,255 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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.config;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.toArray;
import static com.google.common.collect.ObjectArrays.concat;
import java.util.Arrays;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ForwardingFuture;
import com.google.common.util.concurrent.ForwardingListenableFuture;
import com.google.common.util.concurrent.ForwardingListeningExecutorService;
/**
*
* @author Adrian Cole
*/
public class WithSubmissionTrace {
private WithSubmissionTrace() {
}
public static ListeningExecutorService wrap(com.google.common.util.concurrent.ListeningExecutorService delegate) {
return new ListeningExecutorService(delegate);
}
private static class ListeningExecutorService extends ForwardingListeningExecutorService {
private final com.google.common.util.concurrent.ListeningExecutorService delegate;
private ListeningExecutorService(com.google.common.util.concurrent.ListeningExecutorService delegate) {
this.delegate = checkNotNull(delegate, "delegate");
}
@Override
protected com.google.common.util.concurrent.ListeningExecutorService delegate() {
return delegate;
}
@Override
public <T> com.google.common.util.concurrent.ListenableFuture<T> submit(Callable<T> task) {
return new ListenableFuture<T>(delegate().submit(task));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public com.google.common.util.concurrent.ListenableFuture<?> submit(Runnable task) {
return new ListenableFuture(delegate().submit(task));
}
@Override
public <T> com.google.common.util.concurrent.ListenableFuture<T> submit(Runnable task, T result) {
return new ListenableFuture<T>(delegate().submit(task, result));
}
}
private static class ListenableFuture<T> extends ForwardingListenableFuture<T> {
private final com.google.common.util.concurrent.ListenableFuture<T> delegate;
private final StackTraceElement[] submissionTrace;
ListenableFuture(com.google.common.util.concurrent.ListenableFuture<T> delegate) {
this.delegate = checkNotNull(delegate, "delegate");
this.submissionTrace = getStackTraceHere();
}
@Override
protected com.google.common.util.concurrent.ListenableFuture<T> delegate() {
return delegate;
}
@Override
public T get() throws InterruptedException, ExecutionException {
try {
return delegate().get();
} catch (ExecutionException e) {
throw addSubmissionTrace(submissionTrace, e);
}
}
@Override
public T get(long arg0, TimeUnit arg1) throws InterruptedException, ExecutionException, TimeoutException {
try {
return delegate().get(arg0, arg1);
} catch (ExecutionException e) {
throw addSubmissionTrace(submissionTrace, e);
}
}
}
private final static Set<String> stackTracesToTrim = ImmutableSet.of(WithSubmissionTrace.class.getName(),
ListeningExecutorService.class.getName(), ListenableFuture.class.getName(),
ListeningScheduledExecutorService.class.getName(), ScheduledFuture.class.getName());
/** returns the stack trace at the caller */
private static StackTraceElement[] getStackTraceHere() {
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
return filterTrace(trace);
}
private static StackTraceElement[] filterTrace(StackTraceElement[] trace) {
return toArray(filter(Arrays.asList(trace), new Predicate<StackTraceElement>() {
public boolean apply(StackTraceElement input) {
String className = input.getClassName();
return !stackTracesToTrim.contains(className);
}
}), StackTraceElement.class);
}
private static ExecutionException addSubmissionTrace(StackTraceElement[] submissionTrace, ExecutionException e) {
if (e.getCause() == null) {
return filterTrace(e);
}
Throwable cause = e.getCause();
StackTraceElement[] combined = filterTrace(concat(cause.getStackTrace(), submissionTrace, StackTraceElement.class));
cause.setStackTrace(combined);
return filterTrace(e);
}
private static ExecutionException filterTrace(ExecutionException e) {
StackTraceElement[] withoutHere = filterTrace(e.getStackTrace());
e.setStackTrace(withoutHere);
return e;
}
public static ListeningScheduledExecutorService wrap(
com.google.common.util.concurrent.ListeningScheduledExecutorService delegate) {
return new ListeningScheduledExecutorService(delegate);
}
private static class ListeningScheduledExecutorService extends ListeningExecutorService implements
com.google.common.util.concurrent.ListeningScheduledExecutorService {
private ListeningScheduledExecutorService(
com.google.common.util.concurrent.ListeningScheduledExecutorService delegate) {
super(delegate);
}
@Override
protected com.google.common.util.concurrent.ListeningScheduledExecutorService delegate() {
return com.google.common.util.concurrent.ListeningScheduledExecutorService.class.cast(super.delegate());
}
@Override
public <T> ListenableFuture<T> submit(Callable<T> task) {
return new ListenableFuture<T>(delegate().submit(task));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public ListenableFuture<?> submit(Runnable task) {
return new ListenableFuture(delegate().submit(task));
}
@Override
public <T> ListenableFuture<T> submit(Runnable task, T result) {
return new ListenableFuture<T>(delegate().submit(task, result));
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
return new ScheduledFuture(delegate().schedule(command, delay, unit));
}
@Override
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
return new ScheduledFuture<V>(delegate().schedule(callable, delay, unit));
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
return new ScheduledFuture(delegate().scheduleAtFixedRate(command, initialDelay, period, unit));
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
return new ScheduledFuture(delegate().scheduleWithFixedDelay(command, initialDelay, delay, unit));
}
}
private static class ScheduledFuture<T> extends ForwardingFuture<T> implements
java.util.concurrent.ScheduledFuture<T> {
private final java.util.concurrent.ScheduledFuture<T> delegate;
private final StackTraceElement[] submissionTrace;
private ScheduledFuture(java.util.concurrent.ScheduledFuture<T> delegate) {
this.delegate = checkNotNull(delegate, "delegate");
this.submissionTrace = getStackTraceHere();
}
@Override
protected java.util.concurrent.ScheduledFuture<T> delegate() {
return delegate;
}
@Override
public long getDelay(TimeUnit arg0) {
return delegate().getDelay(arg0);
}
@Override
public int compareTo(Delayed arg0) {
return delegate().compareTo(arg0);
}
@Override
public T get() throws InterruptedException, ExecutionException {
try {
return delegate().get();
} catch (ExecutionException e) {
throw addSubmissionTrace(submissionTrace, e);
}
}
@Override
public T get(long arg0, TimeUnit arg1) throws InterruptedException, ExecutionException, TimeoutException {
try {
return delegate().get(arg0, arg1);
} catch (ExecutionException e) {
throw addSubmissionTrace(submissionTrace, e);
}
}
}
}

View File

@ -22,8 +22,6 @@ package org.jclouds.events.config;
import static com.google.inject.Scopes.SINGLETON;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import java.util.concurrent.ExecutorService;
import javax.inject.Named;
import javax.inject.Singleton;
@ -33,6 +31,7 @@ import org.jclouds.events.handlers.DeadEventLoggingHandler;
import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
@ -56,9 +55,9 @@ public class EventBusModule extends AbstractModule {
*/
@Provides
@Singleton
AsyncEventBus provideAsyncEventBus(@Named(PROPERTY_USER_THREADS) ExecutorService executor,
AsyncEventBus provideAsyncEventBus(@Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
DeadEventLoggingHandler deadEventsHandler) {// NO_UCD
AsyncEventBus asyncBus = new AsyncEventBus("jclouds-async-event-bus", executor);
AsyncEventBus asyncBus = new AsyncEventBus("jclouds-async-event-bus", userExecutor);
asyncBus.register(deadEventsHandler);
return asyncBus;
}

View File

@ -20,6 +20,8 @@ package org.jclouds.http;
import java.util.concurrent.Future;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Capable of invoking http commands.
*
@ -35,5 +37,5 @@ public interface HttpCommandExecutorService {
* that generates requests
* @return {@link Future} containing the response from the {@code endpoint}
*/
Future<HttpResponse> submit(HttpCommand command);
ListenableFuture<HttpResponse> submit(HttpCommand command);
}

View File

@ -27,8 +27,6 @@ import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -50,6 +48,8 @@ import org.jclouds.logging.Logger;
import org.jclouds.util.Throwables2;
import com.google.common.io.NullOutputStream;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
*
@ -62,7 +62,7 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
private final DelegatingRetryHandler retryHandler;
private final IOExceptionRetryHandler ioRetryHandler;
private final DelegatingErrorHandler errorHandler;
private final ExecutorService ioWorkerExecutor;
private final ListeningExecutorService ioExecutor;
@Resource
protected Logger logger = Logger.NULL;
@ -74,7 +74,7 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
@Inject
protected BaseHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioWorkerExecutor,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire) {
this.utils = checkNotNull(utils, "utils");
@ -82,7 +82,7 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
this.retryHandler = checkNotNull(retryHandler, "retryHandler");
this.ioRetryHandler = checkNotNull(ioRetryHandler, "ioRetryHandler");
this.errorHandler = checkNotNull(errorHandler, "errorHandler");
this.ioWorkerExecutor = checkNotNull(ioWorkerExecutor, "ioWorkerExecutor");
this.ioExecutor = checkNotNull(ioExecutor, "ioExecutor");
this.wire = checkNotNull(wire, "wire");
}
@ -124,12 +124,12 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
}
@Override
public Future<HttpResponse> submit(HttpCommand command) {
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
HttpRequest request = command.getCurrentRequest();
checkRequestHasContentLengthOrChunkedEncoding(request,
"if the request has a payload, it must be set to chunked encoding or specify a content length: "
+ request);
return ioWorkerExecutor.submit(new HttpResponseCallable(command));
return ioExecutor.submit(new HttpResponseCallable(command));
}
public class HttpResponseCallable implements Callable<HttpResponse> {

View File

@ -44,7 +44,6 @@ import java.net.SocketAddress;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import javax.inject.Named;
import javax.inject.Singleton;
@ -69,6 +68,7 @@ import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.common.io.CountingOutputStream;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
/**
@ -90,12 +90,12 @@ public class JavaUrlHttpCommandExecutorService extends BaseHttpCommandExecutorSe
@Inject
public JavaUrlHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioWorkerExecutor,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier,
@Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider) throws SecurityException,
NoSuchFieldException {
super(utils, contentMetadataCodec, ioWorkerExecutor, retryHandler, ioRetryHandler, errorHandler, wire);
super(utils, contentMetadataCodec, ioExecutor, retryHandler, ioRetryHandler, errorHandler, wire);
if (utils.getMaxConnections() > 0)
System.setProperty("http.maxConnections", String.valueOf(checkNotNull(utils, "utils").getMaxConnections()));
this.untrustedSSLContextProvider = checkNotNull(untrustedSSLContextProvider, "untrustedSSLContextProvider");

View File

@ -20,17 +20,17 @@ package org.jclouds.lifecycle;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import org.jclouds.logging.Logger;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Atomics;
import org.jclouds.logging.Logger;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* // TODO: Adrian: Document this!
@ -41,14 +41,14 @@ public abstract class BaseLifeCycle implements Runnable, LifeCycle {
@Resource
protected Logger logger = Logger.NULL;
protected final ExecutorService executorService;
protected final ListeningExecutorService userExecutor;
protected final List<LifeCycle> dependencies;
protected final Object statusLock;
protected volatile Status status;
protected AtomicReference<Exception> exception = Atomics.newReference();
public BaseLifeCycle(ExecutorService executor, LifeCycle... dependencies) {
this.executorService = executor;
public BaseLifeCycle(ListeningExecutorService userExecutor, LifeCycle... dependencies) {
this.userExecutor = userExecutor;
this.dependencies = Lists.newArrayList();
this.dependencies.addAll(Arrays.asList(dependencies));
this.statusLock = new Object();
@ -118,7 +118,7 @@ public abstract class BaseLifeCycle implements Runnable, LifeCycle {
this.status = Status.ACTIVE;
}
executorService.execute(this);
userExecutor.execute(this);
}
protected void exceptionIfDependenciesNotActive() {

View File

@ -23,23 +23,25 @@ import static com.google.common.collect.Sets.newHashSet;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static com.google.inject.matcher.Matchers.any;
import static java.util.Arrays.asList;
import static org.jclouds.Constants.PROPERTY_IO_WORKER_THREADS;
import static org.jclouds.Constants.PROPERTY_SCHEDULER_THREADS;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.lifecycle.Closer;
import com.google.common.util.concurrent.ExecutionList;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Stage;
@ -70,14 +72,14 @@ public class LifeCycleModule extends AbstractModule {
Closeable executorCloser = new Closeable() {
@Inject
@Named(Constants.PROPERTY_USER_THREADS)
ExecutorService userExecutor;
@Named(PROPERTY_USER_THREADS)
ListeningExecutorService userExecutor;
@Inject
@Named(Constants.PROPERTY_IO_WORKER_THREADS)
ExecutorService ioExecutor;
@Named(PROPERTY_IO_WORKER_THREADS)
ListeningExecutorService ioExecutor;
// ScheduledExecutor is defined in an optional module
@Inject(optional = true)
@Named(Constants.PROPERTY_SCHEDULER_THREADS)
@Named(PROPERTY_SCHEDULER_THREADS)
ScheduledExecutorService scheduledExecutor;
public void close() throws IOException {

View File

@ -19,7 +19,6 @@
package org.jclouds.rest;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import org.jclouds.crypto.Crypto;
import org.jclouds.date.DateService;
@ -31,6 +30,7 @@ import org.jclouds.xml.XMLParser;
import com.google.common.annotations.Beta;
import com.google.common.eventbus.EventBus;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.ImplementedBy;
import com.google.inject.Injector;
@ -103,19 +103,19 @@ public interface Utils {
*/
DateService date();
ExecutorService getUserExecutor();
ListeningExecutorService getUserExecutor();
/**
* #see #getUserExecutor
*/
ExecutorService userExecutor();
ListeningExecutorService userExecutor();
ExecutorService getIoExecutor();
ListeningExecutorService getIoExecutor();
/**
* #see #getIoExecutor
*/
ExecutorService ioExecutor();
ListeningExecutorService ioExecutor();
@Beta
EventBus getEventBus();

View File

@ -23,9 +23,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.util.concurrent.Futures.transform;
import static com.google.common.util.concurrent.Futures.withFallback;
import static org.jclouds.concurrent.Futures.makeListenable;
import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -52,6 +49,7 @@ import com.google.common.reflect.Invokable;
import com.google.common.reflect.TypeToken;
import com.google.common.util.concurrent.FutureFallback;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Injector;
import com.google.inject.TypeLiteral;
@ -66,7 +64,7 @@ public class InvokeHttpMethod<S, A> implements Function<Invocation, Result> {
private final RestAnnotationProcessor<A> annotationProcessor;
private final HttpCommandExecutorService http;
private final TransformerForRequest<A> transformerForRequest;
private final ExecutorService userThreads;
private final ListeningExecutorService userExecutor;
private final BlockOnFuture.Factory blocker;
@SuppressWarnings("unchecked")
@ -74,13 +72,13 @@ public class InvokeHttpMethod<S, A> implements Function<Invocation, Result> {
private InvokeHttpMethod(Injector injector, TypeLiteral<A> enclosingType,
Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncInvokables, RestAnnotationProcessor<A> annotationProcessor,
HttpCommandExecutorService http, TransformerForRequest<A> transformerForRequest,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads, BlockOnFuture.Factory blocker) {
@Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, BlockOnFuture.Factory blocker) {
this.injector = injector;
this.enclosingType = (TypeToken<A>) TypeToken.of(enclosingType.getType());
this.sync2AsyncInvokables = sync2AsyncInvokables;
this.annotationProcessor = annotationProcessor;
this.http = http;
this.userThreads = userThreads;
this.userExecutor = userExecutor;
this.blocker = blocker;
this.transformerForRequest = transformerForRequest;
}
@ -125,8 +123,7 @@ public class InvokeHttpMethod<S, A> implements Function<Invocation, Result> {
logger.trace("<< response from %s is parsed by %s", name, transformer.getClass().getSimpleName());
logger.debug(">> invoking %s", name);
ListenableFuture<?> result = transform(makeListenable(http.submit(new HttpCommand(request)), userThreads),
transformer);
ListenableFuture<?> result = transform(http.submit(new HttpCommand(request)), transformer, userExecutor);
FutureFallback<?> fallback = fallbacks.getUnchecked(invocation.getInvokable());
if (fallback instanceof InvocationContext) {

View File

@ -19,7 +19,6 @@
package org.jclouds.rest.internal;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
@ -37,6 +36,7 @@ import org.jclouds.xml.XMLParser;
import com.google.common.annotations.Beta;
import com.google.common.eventbus.EventBus;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Injector;
import com.google.inject.Singleton;
@ -51,8 +51,8 @@ public class UtilsImpl implements Utils {
private final HttpAsyncClient simpleAsyncClient;
private final Crypto encryption;
private final DateService date;
private final ExecutorService userExecutor;
private final ExecutorService ioExecutor;
private final ListeningExecutorService userExecutor;
private final ListeningExecutorService ioExecutor;
private final EventBus eventBus;
private final Map<String, Credentials> credentialStore;
private final LoggerFactory loggerFactory;
@ -61,8 +61,8 @@ public class UtilsImpl implements Utils {
@Inject
protected UtilsImpl(Injector injector, Json json, XMLParser xml, HttpClient simpleClient, HttpAsyncClient simpleAsyncClient,
Crypto encryption, DateService date, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads, EventBus eventBus,
Crypto encryption, DateService date, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor, EventBus eventBus,
Map<String, Credentials> credentialStore, LoggerFactory loggerFactory) {
this.injector = injector;
this.json = json;
@ -70,8 +70,8 @@ public class UtilsImpl implements Utils {
this.simpleAsyncClient = simpleAsyncClient;
this.encryption = encryption;
this.date = date;
this.userExecutor = userThreads;
this.ioExecutor = ioThreads;
this.userExecutor = userExecutor;
this.ioExecutor = ioExecutor;
this.eventBus = eventBus;
this.credentialStore = credentialStore;
this.loggerFactory = loggerFactory;
@ -119,22 +119,22 @@ public class UtilsImpl implements Utils {
}
@Override
public ExecutorService getIoExecutor() {
public ListeningExecutorService getIoExecutor() {
return ioExecutor;
}
@Override
public ExecutorService getUserExecutor() {
public ListeningExecutorService getUserExecutor() {
return userExecutor;
}
@Override
public ExecutorService ioExecutor() {
public ListeningExecutorService ioExecutor() {
return ioExecutor;
}
@Override
public ExecutorService userExecutor() {
public ListeningExecutorService userExecutor() {
return userExecutor;
}

View File

@ -1,257 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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 com.google.common.util.concurrent;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Maps.newHashMap;
import static java.util.concurrent.Executors.newCachedThreadPool;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
/**
* In google appengine, we can get a future without using an executorservice, using its async http
* fetch command. However, we still may need to do some conversions, or add listeners. In
* googleappengine, we cannot employ a *real* executorservice, but we can employ a same thread
* executor. This test identifies efficiencies that can be made by strengthening guava's handling of
* same thread execution.
*
* <p/>
*
* We simulate an i/o future by running a callable that simply sleeps. How this is created isn't
* important.
*
* <ol>
* <li>{@code IO_DURATION} is the time that the source future spends doing work</li>
* <li>{@code LISTENER_DURATION} is the time that the attached listener or function</li>
* </ol>
*
* The execution time of a transformd task within a composite should not be more than {@code
* IO_DURATION} + {@code LISTENER_DURATION} + overhead when a threadpool is used. This is because
* the listener should be invoked as soon as the result is available.
* <p/>
* The execution time of a transformd task within a composite should not be more than {@code
* IO_DURATION} + {@code LISTENER_DURATION} * {@code COUNT} + overhead when caller thread is used
* for handling the listeners.
* <p/>
* This test shows that Futures.transform eagerly issues a get() on the source future. code iterating
* over futures and assigning listeners will take the same amount of time as calling get() on each
* one, if using a within thread executor. This exposes an inefficiency which can make some use
* cases in google appengine impossible to achieve within the cutoff limits.
*
* @author Adrian Cole
*/
@Test(groups = "performance", enabled = false, singleThreaded = true, testName = "FuturesTransformPerformanceTest")
public class FuturesTransformPerformanceTest {
private static final int FUDGE = 5;
private static final int COUNT = 100;
private static final int IO_DURATION = 50;
private static final int LISTENER_DURATION = 100;
ExecutorService ioFunctionExecutor = newCachedThreadPool();
/**
* When we use threadpools for both the chain and invoking listener, user experience is
* consistent.
*/
@Test(enabled = false)
public void whenCachedThreadPoolIsUsedForChainAndListenerMaxDurationIsSumOfCallableAndListener()
throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION + LISTENER_DURATION;
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT * 4 + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = userthreads;
ExecutorService listenerExecutor = userthreads;
checkThresholdsUsingFuturesTransform(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
/**
* When we use threadpools for the chain, but same thread for invoking listener, user experience
* is still consistent.
*/
@Test(enabled = false)
public void whenCachedThreadPoolIsUsedForChainButSameThreadForListenerMaxDurationIsSumOfCallableAndListener()
throws InterruptedException, ExecutionException {
long expectedMax = IO_DURATION + LISTENER_DURATION;
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = userthreads;
ExecutorService listenerExecutor = MoreExecutors.sameThreadExecutor();
checkThresholdsUsingFuturesTransform(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
/**
* When using same thread for the chain, the futures are being called (get()) eagerly, resulting
* in the max duration being the sum of all i/o plus the cost of executing the listeners. In this
* case, listeners are executed in a different thread pool.
*
*/
@Test(enabled = false)
public void whenSameThreadIsUsedForChainButCachedThreadPoolForListenerMaxDurationIsSumOfAllIOAndOneListener()
throws InterruptedException, ExecutionException {
long expectedMax = (IO_DURATION * COUNT) + LISTENER_DURATION;
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = MoreExecutors.sameThreadExecutor();
ExecutorService listenerExecutor = userthreads;
checkThresholdsUsingFuturesTransform(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
/**
* This case can be optimized for sure. The side effect of the eager get() is that all i/o must
* complete before *any* listeners are run. In this case, if you are inside google appengine and
* using same thread executors, worst experience is sum of all io duration plus the sum of all
* listener duration. An efficient implementation would call get() on the i/o future lazily. Such
* an impl would have a max duration of I/O + Listener * count.
*/
@Test(enabled = false)
public void whenSameThreadIsUsedForChainAndListenerMaxDurationIsSumOfAllIOAndAllListeners()
throws InterruptedException, ExecutionException {
long expectedMax = (IO_DURATION * COUNT) + (LISTENER_DURATION * COUNT);
long expectedMin = IO_DURATION + LISTENER_DURATION;
long expectedOverhead = COUNT + FUDGE;
ExecutorService userthreads = newCachedThreadPool();
try {
ExecutorService chainExecutor = MoreExecutors.sameThreadExecutor();
ExecutorService listenerExecutor = MoreExecutors.sameThreadExecutor();
checkThresholdsUsingFuturesTransform(expectedMin, expectedMax, expectedOverhead, chainExecutor, listenerExecutor);
} finally {
userthreads.shutdownNow();
}
}
private void checkThresholdsUsingFuturesTransform(long expectedMin, long expectedMax, long expectedOverhead,
ExecutorService chainExecutor, final ExecutorService listenerExecutor) {
long start = System.currentTimeMillis();
Map<String, Future<Long>> responses = newHashMap();
for (int i = 0; i < COUNT; i++)
responses.put(i + "", Futures.transform(JdkFutureAdapters.listenInPoolThread(simultateIO(), chainExecutor),
new Function<Long, Long>() {
@Override
public Long apply(Long from) {
try {
Thread.sleep(LISTENER_DURATION);
} catch (InterruptedException e) {
propagate(e);
}
return System.currentTimeMillis();
}
}, listenerExecutor));
checkTimeThresholds(expectedMin, expectedMax, expectedOverhead, start, responses);
}
private Future<Long> simultateIO() {
return ioFunctionExecutor.submit(new Callable<Long>() {
@Override
public Long call() throws Exception {
Thread.sleep(IO_DURATION);
return System.currentTimeMillis();
}
});
}
private static long getMaxIn(Map<String, Future<Long>> responses) {
Iterable<Long> collection = Iterables.transform(responses.values(), new Function<Future<Long>, Long>() {
@Override
public Long apply(Future<Long> from) {
try {
return from.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
return null;
}
});
long time = Collections.max(Sets.newHashSet(collection));
return time;
}
private static long getMinIn(Map<String, Future<Long>> responses) {
Iterable<Long> collection = Iterables.transform(responses.values(), new Function<Future<Long>, Long>() {
@Override
public Long apply(Future<Long> from) {
try {
return from.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
return null;
}
});
long time = Collections.min(Sets.newHashSet(collection));
return time;
}
private static void checkTimeThresholds(long expectedMin, long expectedMax, long expectedOverhead, long start,
Map<String, Future<Long>> responses) {
long time = getMaxIn(responses) - start;
assert time >= expectedMax && time < expectedMax + expectedOverhead : String.format("expectedMax %d, max %d",
expectedMax, time);
time = getMinIn(responses) - start;
assert time >= expectedMin && time < expectedMin + expectedOverhead : String.format("expectedMin %d, min %d",
expectedMin, time);
time = getMaxIn(responses) - start;
assert time >= expectedMax && time < expectedMax + expectedOverhead : String.format("expectedMax %d, max %d",
expectedMax, time);
}
}

View File

@ -26,9 +26,7 @@ import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
@ -38,6 +36,9 @@ import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
/**
* Tests behavior of FutureIterables
@ -51,15 +52,12 @@ public class FutureIterablesTest {
final AtomicInteger counter = new AtomicInteger();
try {
transformParallel(ImmutableSet.of("hello", "goodbye"), new Function<String, Future<? extends String>>() {
@Override
public Future<String> apply(String input) {
transformParallel(ImmutableSet.of("hello", "goodbye"), new Function<String, ListenableFuture<? extends String>>() {
public ListenableFuture<String> apply(String input) {
counter.incrementAndGet();
return immediateFailedFuture(new AuthorizationException());
}
}, sameThreadExecutor(), null, Logger.CONSOLE, "");
}, sameThreadExecutor(), null, Logger.NULL, "");
fail("Expected AuthorizationException");
} catch (AuthorizationException e) {
assertEquals(counter.get(), 2);
@ -71,14 +69,11 @@ public class FutureIterablesTest {
final AtomicInteger counter = new AtomicInteger();
try {
transformParallel(ImmutableSet.of("hello", "goodbye"), new Function<String, Future<? extends String>>() {
@Override
public Future<String> apply(String input) {
transformParallel(ImmutableSet.of("hello", "goodbye"), new Function<String, ListenableFuture<? extends String>>() {
public ListenableFuture<String> apply(String input) {
counter.incrementAndGet();
return immediateFailedFuture(new RuntimeException());
}
}, sameThreadExecutor(), null, Logger.CONSOLE, "");
fail("Expected TransformParallelException");
} catch (TransformParallelException e) {
@ -90,10 +85,10 @@ public class FutureIterablesTest {
public void testAwaitCompletionTimeout() throws Exception {
final long timeoutMs = 1000;
ExecutorService executorService = Executors.newSingleThreadExecutor();
Map<Void, Future<?>> responses = newHashMap();
ListeningExecutorService userExecutor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
Map<Void, ListenableFuture<?>> responses = newHashMap();
try {
responses.put(null, executorService.submit(new Runnable() {
responses.put(null, userExecutor.submit(new Runnable() {
@Override
public void run() {
try {
@ -103,8 +98,7 @@ public class FutureIterablesTest {
}
}
}));
Map<Void, Exception> errors = FutureIterables.awaitCompletion(responses, executorService, timeoutMs,
Logger.CONSOLE,
Map<Void, Exception> errors = FutureIterables.awaitCompletion(responses, userExecutor, timeoutMs, Logger.NULL,
/* prefix= */"");
if (!errors.isEmpty()) {
throw errors.values().iterator().next();
@ -113,7 +107,7 @@ public class FutureIterablesTest {
} catch (TimeoutException te) {
// expected
} finally {
executorService.shutdownNow();
userExecutor.shutdownNow();
}
}
}

View File

@ -1,94 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you 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 static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.jclouds.concurrent.Futures.CallGetAndRunExecutionList;
import org.testng.annotations.Test;
import com.google.common.util.concurrent.ExecutionList;
/**
* Tests behavior of Futures
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class FuturesTest {
ExecutorService executorService = sameThreadExecutor();
@Test
public void testCallGetAndRunRunnableRunsListOnRuntimeException() throws InterruptedException, ExecutionException {
Runnable runnable = createMock(Runnable.class);
@SuppressWarnings("unchecked")
Future<String> future = createMock(Future.class);
runnable.run();
expect(future.get()).andThrow(new RuntimeException());
replay(runnable);
replay(future);
ExecutionList executionList = new ExecutionList();
executionList.add(runnable, executorService);
CallGetAndRunExecutionList<String> caller = new CallGetAndRunExecutionList<String>(future, executionList);
caller.run();
verify(runnable);
verify(future);
}
@Test
public void testCallGetAndRunRunnableInterruptsAndThrowsIllegalStateExceptionOnInterruptedException()
throws InterruptedException, ExecutionException {
Runnable runnable = createMock(Runnable.class);
@SuppressWarnings("unchecked")
Future<String> future = createMock(Future.class);
expect(future.get()).andThrow(new InterruptedException());
replay(runnable);
replay(future);
ExecutionList executionList = new ExecutionList();
executionList.add(runnable, executorService);
CallGetAndRunExecutionList<String> caller = new CallGetAndRunExecutionList<String>(future, executionList);
try {
caller.run();
fail("Expected IllegalStateException");
} catch (IllegalStateException e) {
assertEquals(e.getMessage(), "interrupted calling get() on [EasyMock for interface java.util.concurrent.Future], so could not run listeners");
}
verify(runnable);
verify(future);
}
}

View File

@ -18,29 +18,31 @@
*/
package org.jclouds.concurrent.config;
import static com.google.common.base.Throwables.getStackTraceAsString;
import static com.google.inject.name.Names.named;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.fail;
import static org.jclouds.Constants.PROPERTY_IO_WORKER_THREADS;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.jclouds.Constants;
import org.jclouds.lifecycle.Closer;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.name.Names;
/**
*
@ -49,12 +51,35 @@ import com.google.inject.name.Names;
@Test
public class ExecutorServiceModuleTest {
private Injector injector;
@BeforeMethod
private void setupExecutorModule() {
ExecutorServiceModule module = new ExecutorServiceModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(named(PROPERTY_IO_WORKER_THREADS)).to(1);
bindConstant().annotatedWith(named(PROPERTY_USER_THREADS)).to(1);
super.configure();
}
};
injector = Guice.createInjector(module);
assertNull(module.userExecutorFromConstructor);
assertNull(module.ioExecutorFromConstructor);
}
@AfterMethod
private void close() throws IOException {
injector.getInstance(Closer.class).close();
}
@Test
public void testShutdownOnClose() throws IOException {
Injector i = Guice.createInjector();
Closer closer = i.getInstance(Closer.class);
ExecutorService executor = createMock(ExecutorService.class);
ListeningExecutorService executor = createMock(ListeningExecutorService.class);
ExecutorServiceModule.shutdownOnClose(executor, closer);
expect(executor.shutdownNow()).andReturn(ImmutableList.<Runnable> of()).atLeastOnce();
@ -68,192 +93,64 @@ public class ExecutorServiceModuleTest {
@Test
public void testShutdownOnCloseThroughModule() throws IOException {
ExecutorServiceModule module = new ExecutorServiceModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
super.configure();
}
};
ListeningExecutorService user = injector.getInstance(Key.get(ListeningExecutorService.class,
named(PROPERTY_USER_THREADS)));
ListeningExecutorService io = injector.getInstance(Key.get(ListeningExecutorService.class,
named(PROPERTY_IO_WORKER_THREADS)));
Injector i = Guice.createInjector(module);
assertEquals(module.userExecutorFromConstructor, null);
assertEquals(module.ioExecutorFromConstructor, null);
assertFalse(user.isShutdown());
assertFalse(io.isShutdown());
Closer closer = i.getInstance(Closer.class);
ExecutorService user = i
.getInstance(Key.get(ExecutorService.class, Names.named(Constants.PROPERTY_USER_THREADS)));
ExecutorService io = i.getInstance(Key.get(ExecutorService.class, Names
.named(Constants.PROPERTY_IO_WORKER_THREADS)));
assert !user.isShutdown();
assert !io.isShutdown();
closer.close();
assert user.isShutdown();
assert io.isShutdown();
injector.getInstance(Closer.class).close();
assertTrue(user.isShutdown());
assertTrue(io.isShutdown());
}
@Test
public void testDescribedFutureToString() throws Exception {
public void testExceptionInSubmitRunnableIncludesSubmissionTrace() throws Exception {
ListeningExecutorService user = injector.getInstance(Key.get(ListeningExecutorService.class,
named(PROPERTY_USER_THREADS)));
ListeningExecutorService io = injector.getInstance(Key.get(ListeningExecutorService.class,
named(PROPERTY_IO_WORKER_THREADS)));
ExecutorServiceModule module = new ExecutorServiceModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
super.configure();
}
};
Injector i = Guice.createInjector(module);
Closer closer = i.getInstance(Closer.class);
ExecutorService user = i
.getInstance(Key.get(ExecutorService.class, Names.named(Constants.PROPERTY_USER_THREADS)));
ExecutorService io = i.getInstance(Key.get(ExecutorService.class, Names
.named(Constants.PROPERTY_IO_WORKER_THREADS)));
ConfigurableRunner t1 = new ConfigurableRunner();
t1.result = "okay";
Future<Object> euc = performSubmissionInSeparateMethod1(user, t1);
assert euc.toString().indexOf("ConfigurableRunner") >= 0;
assert euc.get().equals("okay");
Future<Object> eic = performSubmissionInSeparateMethod1(io, t1);
assert eic.toString().indexOf("ConfigurableRunner") >= 0;
assert eic.get().equals("okay");
closer.close();
}
/*
* The decoration makes sure that the stack trace looks like the following.
* Note the last three included trace elements: this details where the task was submitted _from_
* (technically it is a different stack frame, since it is across threads; but logically it is the same)
*
java.util.concurrent.ExecutionException: java.lang.IllegalStateException: foo
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
at java.util.concurrent.FutureTask.get(FutureTask.java:83)
at org.jclouds.concurrent.config.ExecutorServiceModule$DescribedFuture.get(ExecutorServiceModule.java:232)
at org.jclouds.concurrent.config.ExecutorServiceModuleTest.checkFutureGetFailsWith(ExecutorServiceModuleTest.java:186)
at org.jclouds.concurrent.config.ExecutorServiceModuleTest.testDescribedFutureExceptionIncludesSubmissionTrace(ExecutorServiceModuleTest.java:171)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:691)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:883)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1208)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:753)
at org.testng.TestRunner.run(TestRunner.java:613)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:335)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:330)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:292)
at org.testng.SuiteRunner.run(SuiteRunner.java:241)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1169)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1094)
at org.testng.TestNG.run(TestNG.java:1006)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:107)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:199)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:170)
Caused by: java.lang.IllegalStateException: foo
at org.jclouds.concurrent.config.ExecutorServiceModuleTest$ConfigurableRunner.call(ExecutorServiceModuleTest.java:206)
at org.jclouds.concurrent.config.ExecutorServiceModuleTest$ConfigurableRunner.run(ExecutorServiceModuleTest.java:203)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:637)
at org.jclouds.concurrent.config.ExecutorServiceModule$DescribingExecutorService.submit(ExecutorServiceModule.java:188)
at org.jclouds.concurrent.config.ExecutorServiceModuleTest.performSubmissionInSeparateMethod2(ExecutorServiceModuleTest.java:181)
at org.jclouds.concurrent.config.ExecutorServiceModuleTest.testDescribedFutureExceptionIncludesSubmissionTrace(ExecutorServiceModuleTest.java:170)
... 24 more
*
*/
@Test
public void testDescribedFutureExceptionIncludesSubmissionTrace() throws Exception {
ExecutorServiceModule module = new ExecutorServiceModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_USER_THREADS)).to(1);
super.configure();
}
};
Injector i = Guice.createInjector(module);
Closer closer = i.getInstance(Closer.class);
ExecutorService user = i
.getInstance(Key.get(ExecutorService.class, Names.named(Constants.PROPERTY_USER_THREADS)));
ExecutorService io = i.getInstance(Key.get(ExecutorService.class, Names
.named(Constants.PROPERTY_IO_WORKER_THREADS)));
ConfigurableRunner t1 = new ConfigurableRunner();
t1.failMessage = "foo";
t1.result = "shouldn't happen";
Future<Object> euc = performSubmissionInSeparateMethod1(user, t1);
checkFutureGetFailsWith(euc, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod1");
Future<Object> eur = performSubmissionInSeparateMethod2(user, t1);
checkFutureGetFailsWith(eur, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod2");
Future<Object> eic = performSubmissionInSeparateMethod1(io, t1);
checkFutureGetFailsWith(eic, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod1");
Future<Object> eir = performSubmissionInSeparateMethod2(io, t1);
checkFutureGetFailsWith(eir, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performSubmissionInSeparateMethod2");
closer.close();
}
static Future<Object> performSubmissionInSeparateMethod1(ExecutorService user, ConfigurableRunner t1) {
return user.submit((Callable<Object>)t1);
}
static Future<Object> performSubmissionInSeparateMethod2(ExecutorService io, ConfigurableRunner t1) {
return io.submit((Runnable)t1, (Object)"shouldn't happen");
}
static void checkFutureGetFailsWith(Future<?> task, String ...requiredPhrases) throws Exception {
for (ListeningExecutorService exec : ImmutableList.of(user, io)) {
String submission = null;
try {
task.get();
fail("task should have failed");
// this is sensitive to formatting as we are looking for the stack traces to match. if you wrap the below
// line again, you'll need to change incrementInitialElement to 3 line numbers instead of 2.
submission = getStackTraceAsString(incrementInitialElement(new RuntimeException(), 2)).replaceFirst(".*\n",
"");
exec.submit(runnableThrowsRTE()).get();
} catch (ExecutionException e) {
String trace = Throwables.getStackTraceAsString(e);
for (String requiredPhrase : requiredPhrases) {
assert trace.indexOf(requiredPhrase) >= 0 : "stack trace should have contained '"+requiredPhrase+"'";
assertTraceHasSubmission(getStackTraceAsString(e), submission);
assertTraceHasSubmission(getStackTraceAsString(e.getCause()), submission);
}
}
}
static class ConfigurableRunner implements Runnable, Callable<Object> {
Object result;
String failMessage;
static void assertTraceHasSubmission(String trace, String expected) {
assertTrue(trace.indexOf(WithSubmissionTrace.class.getName()) == -1, trace);
assertTrue(trace.indexOf(expected) != -1, trace + " " + expected);
}
static <E extends Exception> E incrementInitialElement(E ex, int lines) {
StackTraceElement[] trace = ex.getStackTrace();
StackTraceElement initialElement = trace[0];
trace[0] = new StackTraceElement(initialElement.getClassName(), initialElement.getMethodName(),
initialElement.getFileName(), initialElement.getLineNumber() + lines);
ex.setStackTrace(trace);
return ex;
}
static Runnable runnableThrowsRTE() {
return new Runnable() {
@Override
public void run() {
call();
}
public Object call() {
if (failMessage!=null) throw new IllegalStateException(failMessage);
return result;
throw new RuntimeException();
}
};
}
}

View File

@ -17,46 +17,66 @@
* under the License.
*/
package org.jclouds.concurrent.config;
import static com.google.common.base.Throwables.getStackTraceAsString;
import static com.google.inject.name.Names.named;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.jclouds.concurrent.config.ExecutorServiceModuleTest.checkFutureGetFailsWith;
import static org.jclouds.Constants.PROPERTY_SCHEDULER_THREADS;
import static org.jclouds.concurrent.config.ExecutorServiceModuleTest.assertTraceHasSubmission;
import static org.jclouds.concurrent.config.ExecutorServiceModuleTest.incrementInitialElement;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.easymock.EasyMock;
import org.jclouds.Constants;
import org.jclouds.concurrent.config.ExecutorServiceModuleTest.ConfigurableRunner;
import org.jclouds.lifecycle.Closer;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.name.Names;
/**
* Unit tests for the {@link ScheduledExecutorServiceModule} class.
*
* @author Ignasi Barrera
*
* @see ExecutorServiceModuleTest
* @author Adrian Cole
*/
@Test(groups = "unit")
@Test
public class ScheduledExecutorServiceModuleTest {
@Test(groups = "unit")
private Injector injector;
@BeforeMethod
private void setupExecutorModule() {
ScheduledExecutorServiceModule module = new ScheduledExecutorServiceModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(named(PROPERTY_SCHEDULER_THREADS)).to(1);
super.configure();
}
};
injector = Guice.createInjector(module);
}
@AfterMethod
private void close() throws IOException {
injector.getInstance(Closer.class).close();
}
@Test
public void testShutdownOnClose() throws IOException {
Injector i = Guice.createInjector();
Closer closer = i.getInstance(Closer.class);
ScheduledExecutorService executor = EasyMock.createMock(ScheduledExecutorService.class);
ListeningScheduledExecutorService executor = createMock(ListeningScheduledExecutorService.class);
ExecutorServiceModule.shutdownOnClose(executor, closer);
expect(executor.shutdownNow()).andReturn(ImmutableList.<Runnable> of()).atLeastOnce();
@ -67,106 +87,61 @@ public class ScheduledExecutorServiceModuleTest {
verify(executor);
}
@Test(groups = "unit")
@Test
public void testShutdownOnCloseThroughModule() throws IOException {
ScheduledExecutorServiceModule module = new ScheduledExecutorServiceModule() {
ListeningScheduledExecutorService sched = injector.getInstance(Key.get(ListeningScheduledExecutorService.class,
named(PROPERTY_SCHEDULER_THREADS)));
assertFalse(sched.isShutdown());
injector.getInstance(Closer.class).close();
assertTrue(sched.isShutdown());
}
@Test
public void testExceptionInSubmitRunnableIncludesSubmissionTrace() throws Exception {
ListeningScheduledExecutorService sched = injector.getInstance(Key.get(ListeningScheduledExecutorService.class,
named(PROPERTY_SCHEDULER_THREADS)));
String submission = null;
try {
// this is sensitive to formatting as we are looking for the stack traces to match. if you wrap the below
// line again, you'll need to change incrementInitialElement to 3 line numbers instead of 2.
submission = getStackTraceAsString(incrementInitialElement(new RuntimeException(), 2))
.replaceFirst(".*\n", "");
sched.submit(runnableThrowsRTE()).get();
} catch (ExecutionException e) {
assertTraceHasSubmission(getStackTraceAsString(e), submission);
assertTraceHasSubmission(getStackTraceAsString(e.getCause()), submission);
}
}
@Test
public void testExceptionInScheduleWithFixedDelayRunnableIncludesSubmissionTrace() throws Exception {
ListeningScheduledExecutorService sched = injector.getInstance(Key.get(ListeningScheduledExecutorService.class,
named(PROPERTY_SCHEDULER_THREADS)));
String submission = null;
try {
// this is sensitive to formatting as we are looking for the stack traces to match. if you wrap the below
// line again, you'll need to change incrementInitialElement to 3 line numbers instead of 2.
submission = getStackTraceAsString(incrementInitialElement(new RuntimeException(), 2))
.replaceFirst(".*\n", "");
sched.scheduleWithFixedDelay(runnableThrowsRTE(), 0, 1, TimeUnit.MICROSECONDS).get();
} catch (ExecutionException e) {
assertTraceHasSubmission(getStackTraceAsString(e), submission);
assertTraceHasSubmission(getStackTraceAsString(e.getCause()), submission);
}
}
static Runnable runnableThrowsRTE() {
return new Runnable() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_SCHEDULER_THREADS)).to(1);
super.configure();
public void run() {
throw new RuntimeException();
}
};
Injector i = Guice.createInjector(module);
Closer closer = i.getInstance(Closer.class);
ScheduledExecutorService sched = i.getInstance(Key.get(ScheduledExecutorService.class, Names
.named(Constants.PROPERTY_SCHEDULER_THREADS)));
assert !sched.isShutdown();
closer.close();
assert sched.isShutdown();
}
@Test(groups = "unit")
public void testDescribedFutureToString() throws Exception {
ScheduledExecutorServiceModule module = new ScheduledExecutorServiceModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_SCHEDULER_THREADS)).to(1);
super.configure();
}
};
Injector i = Guice.createInjector(module);
Closer closer = i.getInstance(Closer.class);
ScheduledExecutorService sched = i.getInstance(Key.get(ScheduledExecutorService.class, Names
.named(Constants.PROPERTY_SCHEDULER_THREADS)));
ConfigurableRunner t1 = new ConfigurableRunner();
t1.result = "okay";
ScheduledFuture<Object> esc = performScheduleInSeparateMethod1(sched, t1);
assert esc.toString().indexOf("ConfigurableRunner") >= 0;
assert esc.get().equals("okay");
closer.close();
}
@Test(groups = "unit")
public void testDescribedFutureExceptionIncludesSubmissionTrace() throws Exception {
ScheduledExecutorServiceModule module = new ScheduledExecutorServiceModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_SCHEDULER_THREADS)).to(1);
super.configure();
}
};
Injector i = Guice.createInjector(module);
Closer closer = i.getInstance(Closer.class);
ScheduledExecutorService sched = i.getInstance(Key.get(ScheduledExecutorService.class, Names
.named(Constants.PROPERTY_SCHEDULER_THREADS)));
ConfigurableRunner t1 = new ConfigurableRunner();
t1.failMessage = "foo";
t1.result = "shouldn't happen";
ScheduledFuture<Object> esc = performScheduleInSeparateMethod1(sched, t1);
checkFutureGetFailsWith(esc, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performScheduleInSeparateMethod1");
ScheduledFuture<?> esr = performScheduleInSeparateMethod2(sched, t1);
checkFutureGetFailsWith(esr, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performScheduleInSeparateMethod2");
ScheduledFuture<?> esfr = performScheduleInSeparateMethod3(sched, t1);
checkFutureGetFailsWith(esfr, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performScheduleInSeparateMethod3");
ScheduledFuture<?> esfd = performScheduleInSeparateMethod4(sched, t1);
checkFutureGetFailsWith(esfd, "foo", "testDescribedFutureExceptionIncludesSubmissionTrace", "performScheduleInSeparateMethod4");
closer.close();
}
static ScheduledFuture<Object> performScheduleInSeparateMethod1(ScheduledExecutorService sched, ConfigurableRunner t1) {
return sched.schedule((Callable<Object>)t1, 0, TimeUnit.SECONDS);
}
static ScheduledFuture<?> performScheduleInSeparateMethod2(ScheduledExecutorService sched, ConfigurableRunner t1) {
return sched.schedule((Runnable)t1, 0, TimeUnit.SECONDS);
}
static ScheduledFuture<?> performScheduleInSeparateMethod3(ScheduledExecutorService sched, ConfigurableRunner t1) {
return sched.scheduleAtFixedRate((Runnable)t1, 0, 1, TimeUnit.SECONDS);
}
static ScheduledFuture<?> performScheduleInSeparateMethod4(ScheduledExecutorService sched, ConfigurableRunner t1) {
return sched.scheduleWithFixedDelay((Runnable)t1, 0, 1, TimeUnit.SECONDS);
}
}

View File

@ -46,7 +46,7 @@ public class EventBusModuleTest {
@BeforeClass
public void setup() {
ExecutorServiceModule executorServiceModule = new ExecutorServiceModule() {
ExecutorServiceModule userExecutorModule = new ExecutorServiceModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_IO_WORKER_THREADS)).to(1);
@ -55,7 +55,7 @@ public class EventBusModuleTest {
}
};
EventBusModule eventBusModule = new EventBusModule();
injector = Guice.createInjector(executorServiceModule, eventBusModule);
injector = Guice.createInjector(userExecutorModule, eventBusModule);
}
public void testAsyncExecutorIsProvided() {

View File

@ -24,33 +24,17 @@ import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import org.jclouds.date.internal.DateServiceDateCodecFactory;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.http.BaseJettyTest;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpCommandExecutorService;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.IntegrationTestAsyncClient;
import org.jclouds.http.internal.HttpWire;
import org.jclouds.http.internal.JavaUrlHttpCommandExecutorService;
import org.jclouds.io.ContentMetadataCodec;
import org.jclouds.io.ContentMetadataCodec.DefaultContentMetadataCodec;
import org.jclouds.io.Payloads;
import com.google.common.reflect.Invokable;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.reflect.Invokable;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
@ -96,35 +80,6 @@ public class BackoffLimitedRetryHandlerTest {
}
HttpCommandExecutorService http;
@BeforeTest
void setupExecutorService() throws Exception {
ExecutorService execService = Executors.newCachedThreadPool();
BackoffLimitedRetryHandler backoff = new BackoffLimitedRetryHandler();
HttpUtils utils = new HttpUtils(0, 500, 1, 1);
ContentMetadataCodec contentMetadataCodec = new DefaultContentMetadataCodec(new DateServiceDateCodecFactory(
new SimpleDateFormatDateService()));
RedirectionRetryHandler retry = new RedirectionRetryHandler(backoff);
http = new JavaUrlHttpCommandExecutorService(utils,
contentMetadataCodec, execService,
new DelegatingRetryHandler(backoff, retry), new BackoffLimitedRetryHandler(),
new DelegatingErrorHandler(), new HttpWire(), new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return false;
}
}, new Supplier<SSLContext>() {
@Override
public SSLContext get() {
return null;
}
});
}
@Test
void testClosesInputStream() throws InterruptedException, IOException, SecurityException, NoSuchMethodException {
HttpCommand command = createCommand();

View File

@ -20,8 +20,6 @@ package org.jclouds.http.internal;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.inject.Inject;
import javax.inject.Named;
@ -42,6 +40,8 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.common.reflect.Invokable;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.AbstractModule;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;
@ -88,18 +88,18 @@ public class TrackingJavaUrlHttpCommandExecutorService extends JavaUrlHttpComman
@Inject
public TrackingJavaUrlHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioWorkerExecutor,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire, @Named("untrusted") HostnameVerifier verifier,
@Named("untrusted") Supplier<SSLContext> untrustedSSLContextProvider, List<HttpCommand> commandsInvoked)
throws SecurityException, NoSuchFieldException {
super(utils, contentMetadataCodec, ioWorkerExecutor, retryHandler, ioRetryHandler, errorHandler, wire, verifier,
super(utils, contentMetadataCodec, ioExecutor, retryHandler, ioRetryHandler, errorHandler, wire, verifier,
untrustedSSLContextProvider);
this.commandsInvoked = commandsInvoked;
}
@Override
public Future<HttpResponse> submit(HttpCommand command) {
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
commandsInvoked.add(command);
return super.submit(command);
}

View File

@ -18,24 +18,24 @@
*/
package org.jclouds.lifecycle.config;
import static com.google.inject.name.Names.named;
import static org.jclouds.Constants.PROPERTY_IO_WORKER_THREADS;
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import javax.annotation.PostConstruct;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.lifecycle.Closer;
import org.testng.annotations.Test;
import com.google.common.util.concurrent.ExecutionList;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Provides;
import com.google.inject.name.Names;
/**
*
@ -47,35 +47,17 @@ public class LifeCycleModuleTest {
@Test
void testBindsExecutor() {
Injector i = createInjector();
assert i.getInstance(Key.get(ExecutorService.class, Names
.named(Constants.PROPERTY_USER_THREADS))) != null;
assert i.getInstance(Key.get(ExecutorService.class, Names
.named(Constants.PROPERTY_IO_WORKER_THREADS))) != null;
assert i.getInstance(Key.get(ListeningExecutorService.class, named(PROPERTY_USER_THREADS))) != null;
assert i.getInstance(Key.get(ListeningExecutorService.class, named(PROPERTY_IO_WORKER_THREADS))) != null;
}
private Injector createInjector() {
Injector i = Guice.createInjector(new LifeCycleModule() {
@SuppressWarnings("unused")
@Provides
@Named(Constants.PROPERTY_USER_THREADS)
int p() {
return 1;
Injector i = Guice.createInjector(new AbstractModule() {
protected void configure() {
bindConstant().annotatedWith(named(PROPERTY_IO_WORKER_THREADS)).to(1);
bindConstant().annotatedWith(named(PROPERTY_USER_THREADS)).to(1);
}
@SuppressWarnings("unused")
@Provides
@Named(Constants.PROPERTY_MAX_CONNECTIONS_PER_CONTEXT)
int p2() {
return 1;
}
@SuppressWarnings("unused")
@Provides
@Named(Constants.PROPERTY_IO_WORKER_THREADS)
int p3() {
return 1;
}
}, new ExecutorServiceModule());
}, new LifeCycleModule(), new ExecutorServiceModule());
// TODO: currently have to manually invoke the execution list, as otherwise it may occur
// before everything is wired up
i.getInstance(ExecutionList.class).execute();
@ -91,8 +73,8 @@ public class LifeCycleModuleTest {
@Test
void testCloserClosesExecutor() throws IOException {
Injector i = createInjector();
ExecutorService executor = i.getInstance(Key.get(ExecutorService.class, Names
.named(Constants.PROPERTY_USER_THREADS)));
ListeningExecutorService executor = i.getInstance(Key.get(ListeningExecutorService.class,
named(PROPERTY_USER_THREADS)));
assert !executor.isShutdown();
Closer closer = i.getInstance(Closer.class);
closer.close();
@ -102,16 +84,16 @@ public class LifeCycleModuleTest {
@Test
void testCloserPreDestroyOrder() throws IOException {
Injector i = createInjector();
ExecutorService userThreads = i.getInstance(Key.get(ExecutorService.class, Names
.named(Constants.PROPERTY_USER_THREADS)));
assert !userThreads.isShutdown();
ExecutorService ioThreads = i.getInstance(Key.get(ExecutorService.class, Names
.named(Constants.PROPERTY_IO_WORKER_THREADS)));
assert !ioThreads.isShutdown();
ListeningExecutorService userExecutor = i.getInstance(Key.get(ListeningExecutorService.class,
named(PROPERTY_USER_THREADS)));
assert !userExecutor.isShutdown();
ListeningExecutorService ioExecutor = i.getInstance(Key.get(ListeningExecutorService.class,
named(PROPERTY_IO_WORKER_THREADS)));
assert !ioExecutor.isShutdown();
Closer closer = i.getInstance(Closer.class);
closer.close();
assert userThreads.isShutdown();
assert ioThreads.isShutdown();
assert userExecutor.isShutdown();
assert ioExecutor.isShutdown();
}
static class PostConstructable {

View File

@ -34,7 +34,6 @@ import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger;
@ -84,6 +83,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.InputSupplier;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.inject.AbstractModule;
@ -195,7 +195,7 @@ public abstract class BaseRestApiExpectTest<S> {
@Inject
public ExpectHttpCommandExecutorService(Function<HttpRequest, HttpResponse> fn, HttpUtils utils,
ContentMetadataCodec contentMetadataCodec,
@Named(PROPERTY_IO_WORKER_THREADS) ExecutorService ioExecutor,
@Named(PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
IOExceptionRetryHandler ioRetryHandler, DelegatingRetryHandler retryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire) {
super(utils, contentMetadataCodec, ioExecutor, retryHandler, ioRetryHandler, errorHandler, wire);
@ -230,8 +230,8 @@ public abstract class BaseRestApiExpectTest<S> {
@Override
public void configure() {
bind(ExecutorService.class).annotatedWith(named(PROPERTY_USER_THREADS)).toInstance(sameThreadExecutor());
bind(ExecutorService.class).annotatedWith(named(PROPERTY_IO_WORKER_THREADS)).toInstance(sameThreadExecutor());
bind(ListeningExecutorService.class).annotatedWith(named(PROPERTY_USER_THREADS)).toInstance(sameThreadExecutor());
bind(ListeningExecutorService.class).annotatedWith(named(PROPERTY_IO_WORKER_THREADS)).toInstance(sameThreadExecutor());
bind(new TypeLiteral<Function<HttpRequest, HttpResponse>>() {
}).toInstance(fn);
bind(HttpCommandExecutorService.class).to(ExpectHttpCommandExecutorService.class);

View File

@ -32,7 +32,6 @@ import static org.testng.Assert.assertNull;
import java.io.IOException;
import java.util.Date;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import org.jclouds.concurrent.config.ConfiguresExecutorService;
import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions;
@ -53,6 +52,7 @@ import com.google.common.collect.TreeMultimap;
import com.google.common.reflect.Invokable;
import com.google.common.reflect.TypeParameter;
import com.google.common.reflect.TypeToken;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
import com.google.inject.Key;
@ -82,8 +82,8 @@ public abstract class BaseRestApiTest {
@Override
protected void configure() {
bind(ExecutorService.class).annotatedWith(named(PROPERTY_USER_THREADS)).toInstance(sameThreadExecutor());
bind(ExecutorService.class).annotatedWith(named(PROPERTY_IO_WORKER_THREADS)).toInstance(sameThreadExecutor());
bind(ListeningExecutorService.class).annotatedWith(named(PROPERTY_USER_THREADS)).toInstance(sameThreadExecutor());
bind(ListeningExecutorService.class).annotatedWith(named(PROPERTY_IO_WORKER_THREADS)).toInstance(sameThreadExecutor());
bind(HttpCommandExecutorService.class).toInstance(mock);
}
}

View File

@ -45,7 +45,6 @@ import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import javax.inject.Named;
import javax.inject.Qualifier;
@ -94,7 +93,6 @@ import org.jclouds.logging.config.NullLoggingModule;
import org.jclouds.providers.AnonymousProviderMetadata;
import org.jclouds.reflect.Invocation;
import org.jclouds.reflect.InvocationSuccess;
import com.google.common.reflect.Invokable;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.InvocationContext;
@ -144,6 +142,7 @@ import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.io.Files;
import com.google.common.reflect.Invokable;
import com.google.common.reflect.TypeToken;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
@ -255,7 +254,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override
public Future<HttpResponse> submit(HttpCommand command) {
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(),
"GET http://localhost:9999/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
@ -280,7 +279,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
int callCounter = 0;
@Override
public Future<HttpResponse> submit(HttpCommand command) {
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
if (callCounter == 1)
assertEquals(command.getCurrentRequest().getRequestLine(),
"GET http://localhost:1111/client/1/bar/2 HTTP/1.1");
@ -310,7 +309,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override
public Future<HttpResponse> submit(HttpCommand command) {
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
}
@ -335,7 +334,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override
public Future<HttpResponse> submit(HttpCommand command) {
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(),
"GET http://howdyboys/testing/testing/thepathparam/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
@ -361,7 +360,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override
public Future<HttpResponse> submit(HttpCommand command) {
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
}
@ -386,7 +385,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override
public Future<HttpResponse> submit(HttpCommand command) {
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
}
@ -425,7 +424,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
Injector child = injectorForCaller(new HttpCommandExecutorService() {
@Override
public Future<HttpResponse> submit(HttpCommand command) {
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
return Futures.immediateFuture(HttpResponse.builder().build());
}

View File

@ -24,7 +24,6 @@ import static org.jclouds.io.ByteSources.asByteSource;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.ExecutorService;
import javax.inject.Named;
@ -48,6 +47,7 @@ import org.jclouds.io.Payloads;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.inject.Inject;
/**
@ -62,10 +62,10 @@ public class ApacheHCHttpCommandExecutorService extends BaseHttpCommandExecutorS
@Inject
ApacheHCHttpCommandExecutorService(HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioWorkerExecutor,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire, HttpClient client) {
super(utils, contentMetadataCodec, ioWorkerExecutor, retryHandler, ioRetryHandler, errorHandler, wire);
super(utils, contentMetadataCodec, ioExecutor, retryHandler, ioRetryHandler, errorHandler, wire);
this.client = client;
this.apacheHCUtils = new ApacheHCUtils(contentMetadataCodec);
}

View File

@ -18,14 +18,14 @@
*/
package org.jclouds.enterprise.config;
import java.util.concurrent.ExecutorService;
import org.jclouds.concurrent.config.ConfiguresExecutorService;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.date.joda.config.JodaDateServiceModule;
import org.jclouds.encryption.bouncycastle.config.BouncyCastleCryptoModule;
import org.jclouds.netty.config.NettyPayloadModule;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* Configures Enterprise-grade components
*
@ -35,8 +35,8 @@ import org.jclouds.netty.config.NettyPayloadModule;
@ConfiguresExecutorService
public class EnterpriseConfigurationModule extends ExecutorServiceModule {
public EnterpriseConfigurationModule(ExecutorService userThreads, ExecutorService ioThreads) {
super(userThreads, ioThreads);
public EnterpriseConfigurationModule(ListeningExecutorService userExecutor, ListeningExecutorService ioExecutor) {
super(userExecutor, ioExecutor);
}
public EnterpriseConfigurationModule() {

View File

@ -19,11 +19,12 @@
package org.jclouds.gae;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.util.concurrent.Futures.transform;
import static com.google.common.util.concurrent.JdkFutureAdapters.listenInPoolThread;
import static org.jclouds.http.HttpUtils.checkRequestHasContentLengthOrChunkedEncoding;
import static org.jclouds.http.HttpUtils.wirePayloadIfEnabled;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -31,7 +32,6 @@ import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.concurrent.Futures;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpCommandExecutorService;
import org.jclouds.http.HttpRequest;
@ -50,6 +50,7 @@ import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* Google App Engine version of {@link HttpCommandExecutorService} using their fetchAsync call
@ -58,7 +59,7 @@ import com.google.common.util.concurrent.ListenableFuture;
*/
@Singleton
public class AsyncGaeHttpCommandExecutorService implements HttpCommandExecutorService {
private final ExecutorService service;
private final ListeningExecutorService ioExecutor;
private final URLFetchService urlFetchService;
private final ConvertToGaeRequest convertToGaeRequest;
private final ConvertToJcloudsResponse convertToJcloudsResponse;
@ -75,11 +76,12 @@ public class AsyncGaeHttpCommandExecutorService implements HttpCommandExecutorSe
protected final HttpUtils utils;
@Inject
public AsyncGaeHttpCommandExecutorService(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
public AsyncGaeHttpCommandExecutorService(
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
URLFetchService urlFetchService, ConvertToGaeRequest convertToGaeRequest,
ConvertToJcloudsResponse convertToJcloudsResponse, DelegatingRetryHandler retryHandler,
IOExceptionRetryHandler ioRetryHandler, DelegatingErrorHandler errorHandler, HttpUtils utils, HttpWire wire) {
this.service = service;
this.ioExecutor = ioExecutor;
this.urlFetchService = urlFetchService;
this.convertToGaeRequest = convertToGaeRequest;
this.convertToJcloudsResponse = convertToJcloudsResponse;
@ -109,10 +111,10 @@ public class AsyncGaeHttpCommandExecutorService implements HttpCommandExecutorSe
HTTPRequest nativeRequest = filterLogAndConvertRe(command.getCurrentRequest());
ListenableFuture<HttpResponse> response = Futures.compose(urlFetchService.fetchAsync(nativeRequest),
convertToJcloudsResponse, service);
ListenableFuture<HttpResponse> response = transform(
listenInPoolThread(urlFetchService.fetchAsync(nativeRequest)), convertToJcloudsResponse);
return Futures.compose(response, new Function<HttpResponse, HttpResponse>() {
return transform(response, new Function<HttpResponse, HttpResponse>() {
@Override
public HttpResponse apply(HttpResponse response) {
@ -159,7 +161,7 @@ public class AsyncGaeHttpCommandExecutorService implements HttpCommandExecutorSe
}
return shouldContinue;
}
}, service);
}, ioExecutor);
}

View File

@ -19,7 +19,6 @@
package org.jclouds.gae;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
@ -28,6 +27,7 @@ import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.JcloudsVersion;
import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.http.HttpCommandExecutorService;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
@ -42,6 +42,7 @@ import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.util.concurrent.ListeningExecutorService;
/**
* Google App Engine version of {@link HttpCommandExecutorService}
@ -61,7 +62,7 @@ public class GaeHttpCommandExecutorService extends BaseHttpCommandExecutorServic
@Inject
public GaeHttpCommandExecutorService(URLFetchService urlFetchService, HttpUtils utils,
ContentMetadataCodec contentMetadataCodec,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioExecutor,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ListeningExecutorService ioExecutor,
IOExceptionRetryHandler ioRetryHandler, DelegatingRetryHandler retryHandler,
DelegatingErrorHandler errorHandler, HttpWire wire, ConvertToGaeRequest convertToGaeRequest,
ConvertToJcloudsResponse convertToJcloudsResponse) {

View File

@ -41,8 +41,8 @@ public class AsyncGoogleAppEngineConfigurationModule extends GoogleAppEngineConf
super();
}
public AsyncGoogleAppEngineConfigurationModule(Module executorServiceModule) {
super(executorServiceModule);
public AsyncGoogleAppEngineConfigurationModule(Module userExecutorModule) {
super(userExecutorModule);
}
/**

View File

@ -29,7 +29,7 @@ import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.concurrent.config.ConfiguresExecutorService;
import org.jclouds.concurrent.config.DescribingExecutorService;
import org.jclouds.concurrent.config.WithSubmissionTrace;
import com.google.appengine.api.ThreadManager;
import com.google.apphosting.api.ApiProxy;
@ -99,20 +99,20 @@ public class CurrentRequestExecutorServiceModule extends AbstractModule {
int maxThreads = 10;
long keepAlive = ApiProxy.getCurrentEnvironment().getRemainingMillis();
ExecutorService pool = newScalingThreadPool(0, maxThreads, keepAlive, factory);
return MoreExecutors.listeningDecorator(new DescribingExecutorService(pool));
return WithSubmissionTrace.wrap(MoreExecutors.listeningDecorator(pool));
}
@Provides
@Singleton
@Named(Constants.PROPERTY_USER_THREADS)
protected ExecutorService userThreads() {
protected ListeningExecutorService userExecutor() {
return memoizedCurrentRequestExecutorService.get();
}
@Provides
@Singleton
@Named(Constants.PROPERTY_IO_WORKER_THREADS)
protected ExecutorService ioThreads() {
protected ListeningExecutorService ioExecutor() {
return memoizedCurrentRequestExecutorService.get();
}
}

Some files were not shown because too many files have changed in this diff Show More