Issue 325: massive refactor in order to stop serializing native async http client requests

This commit is contained in:
Adrian Cole 2010-07-30 01:26:55 -07:00
parent 909fc0d79a
commit 34518f54ba
158 changed files with 3866 additions and 2613 deletions

View File

@ -49,6 +49,16 @@
<artifactId>jclouds-vcloud</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-bluelock</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-terremark</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>jclouds-gogrid</artifactId>

View File

@ -43,7 +43,7 @@ public interface ${providerName}Client {
/*
* Note all these delegate to methods in ${providerName}AsyncClient with a specified or inherited timeout.
* The singatures should match those of ${providerName}AsyncClient, except the returnvals should not be
* wrapped in a ListenableFuture
* wrapped in a Future
*/
String list();

View File

@ -82,7 +82,7 @@ public interface AtmosStorageAsyncClient {
@Path("/rest/namespace")
@ResponseParser(ParseDirectoryListFromContentAndHeaders.class)
@Consumes(MediaType.TEXT_XML)
ListenableFuture<? extends BoundedSet<? extends DirectoryEntry>> listDirectories(
ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectories(
ListOptions... options);
/**
@ -93,7 +93,7 @@ public interface AtmosStorageAsyncClient {
@ResponseParser(ParseDirectoryListFromContentAndHeaders.class)
@ExceptionParser(ThrowContainerNotFoundOn404.class)
@Consumes(MediaType.TEXT_XML)
ListenableFuture<? extends BoundedSet<? extends DirectoryEntry>> listDirectory(
ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectory(
@PathParam("directoryName") String directoryName, ListOptions... options);
/**

View File

@ -19,7 +19,8 @@
package org.jclouds.atmosonline.saas.blobstore;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.compose;
import static org.jclouds.concurrent.ConcurrentUtils.compose;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import java.net.URI;
import java.util.Set;
@ -53,7 +54,6 @@ import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
import org.jclouds.blobstore.util.BlobUtils;
import org.jclouds.concurrent.ConcurrentUtils;
import org.jclouds.domain.Location;
import org.jclouds.encryption.EncryptionService;
import org.jclouds.http.options.GetOptions;
@ -79,15 +79,12 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
@Inject
AtmosAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
Location defaultLocation, Set<? extends Location> locations,
AtmosStorageAsyncClient async, AtmosStorageClient sync, ObjectToBlob object2Blob,
ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Location defaultLocation,
Set<? extends Location> locations, AtmosStorageAsyncClient async, AtmosStorageClient sync,
ObjectToBlob object2Blob, ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object,
BlobStoreListOptionsToListOptions container2ContainerListOptions,
DirectoryEntryListToResourceMetadataList container2ResourceList,
EncryptionService encryptionService, BlobToHttpGetOptions blob2ObjectGetOptions,
Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
DirectoryEntryListToResourceMetadataList container2ResourceList, EncryptionService encryptionService,
BlobToHttpGetOptions blob2ObjectGetOptions, Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
super(context, blobUtils, service, defaultLocation, locations);
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
this.sync = checkNotNull(sync, "sync");
@ -99,8 +96,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd");
this.encryptionService = checkNotNull(encryptionService, "encryptionService");
this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider,
"fetchBlobMetadataProvider");
this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider, "fetchBlobMetadataProvider");
}
/**
@ -108,8 +104,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
*/
@Override
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
return compose(async.headFile(container + "/" + key),
new Function<AtmosObject, BlobMetadata>() {
return compose(async.headFile(container + "/" + key), new Function<AtmosObject, BlobMetadata>() {
@Override
public BlobMetadata apply(AtmosObject from) {
return object2BlobMd.apply(from);
@ -130,7 +125,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
return true;
}
});
}, service);
}
/**
@ -144,7 +139,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
return null;// no etag
}
});
}, service);
}
/**
@ -197,8 +192,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
* This implementation invokes {@link AtmosStorageAsyncClient#readFile}
*/
@Override
public ListenableFuture<Blob> getBlob(String container, String key,
org.jclouds.blobstore.options.GetOptions options) {
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 compose(returnVal, object2Blob, service);
@ -208,7 +202,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
* This implementation invokes {@link AtmosStorageAsyncClient#listDirectories}
*/
@Override
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list() {
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
return compose(async.listDirectories(), container2ResourceList, service);
}
@ -216,16 +210,14 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
* This implementation invokes {@link AtmosStorageAsyncClient#listDirectory}
*/
@Override
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(String container,
public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container,
org.jclouds.blobstore.options.ListContainerOptions options) {
container = AtmosStorageUtils.adjustContainerIfDirOptionPresent(container, options);
ListOptions nativeOptions = container2ContainerListOptions.apply(options);
ListenableFuture<? extends BoundedSet<? extends DirectoryEntry>> returnVal = async
.listDirectory(container, nativeOptions);
ListenableFuture<PageSet<? extends StorageMetadata>> list = compose(returnVal,
container2ResourceList, service);
return options.isDetailed() ? compose(list, fetchBlobMetadataProvider.get().setContainerName(
container), service) : list;
ListenableFuture<BoundedSet<? extends DirectoryEntry>> returnVal = async.listDirectory(container, nativeOptions);
ListenableFuture<PageSet<? extends StorageMetadata>> list = compose(returnVal, container2ResourceList, service);
return (ListenableFuture<PageSet<? extends StorageMetadata>>) (options.isDetailed() ? compose(list,
fetchBlobMetadataProvider.get().setContainerName(container), service) : list);
}
/**
@ -235,7 +227,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
*/
@Override
public ListenableFuture<String> putBlob(final String container, final Blob blob) {
return ConcurrentUtils.makeListenable(service.submit(new Callable<String>() {
return makeListenable(service.submit(new Callable<String>() {
@Override
public String call() throws Exception {

View File

@ -26,6 +26,7 @@ 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.TimeUnit;
@ -42,6 +43,7 @@ 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 static org.jclouds.concurrent.ConcurrentUtils.*;
import org.jclouds.logging.Logger;
import com.google.common.base.Throwables;
@ -70,10 +72,8 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
protected Long maxTime;
@Inject
private FindMD5InUserMetadata(
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
ObjectMD5 objectMD5, ListBlobsInContainer getAllBlobMetadata,
AtmosStorageAsyncClient client) {
private FindMD5InUserMetadata(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
ObjectMD5 objectMD5, ListBlobsInContainer getAllBlobMetadata, AtmosStorageAsyncClient client) {
this.objectMD5 = objectMD5;
this.getAllBlobMetadata = getAllBlobMetadata;
this.client = client;
@ -83,10 +83,10 @@ 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, ListenableFuture<?>> responses = Maps.newHashMap();
Map<String, Future<?>> responses = Maps.newHashMap();
for (BlobMetadata md : getAllBlobMetadata.execute(containerName, options)) {
final ListenableFuture<AtmosObject> future = client.headFile(containerName + "/"
+ md.getName());
final ListenableFuture<AtmosObject> future = makeListenable(client.headFile(containerName
+ "/" + md.getName()), userExecutor);
future.addListener(new Runnable() {
public void run() {
try {
@ -97,8 +97,7 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
queue.put(true);
}
} else {
logger.debug("object %s has no content md5", object.getSystemMetadata()
.getObjectID());
logger.debug("object %s has no content md5", object.getSystemMetadata().getObjectID());
}
} catch (InterruptedException e) {
Throwables.propagate(e);
@ -109,11 +108,11 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
}, userExecutor);
responses.put(md.getName(), future);
}
Map<String, Exception> exceptions = awaitCompletion(responses, userExecutor, maxTime, logger,
String.format("searching for md5 in container %s", containerName));
Map<String, Exception> exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, String.format(
"searching for md5 in container %s", containerName));
if (exceptions.size() > 0)
throw new BlobRuntimeException(String.format("searching for md5 in container %s: %s",
containerName, exceptions));
throw new BlobRuntimeException(String.format("searching for md5 in container %s: %s", containerName,
exceptions));
try {
return queue.poll(1, TimeUnit.MICROSECONDS) != null;
} catch (InterruptedException e) {
@ -121,9 +120,8 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
return false;
} catch (Exception e) {
Throwables.propagateIfPossible(e, BlobRuntimeException.class);
throw new BlobRuntimeException(String.format(
"Error searching for ETAG of value: [%s] in container:%s", value, containerName),
e);
throw new BlobRuntimeException(String.format("Error searching for ETAG of value: [%s] in container:%s", value,
containerName), e);
}
}
}

View File

@ -19,15 +19,18 @@
package org.jclouds.atmosonline.saas.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.compose;
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.concurrent.ConcurrentUtils.compose;
import java.net.URI;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
import org.jclouds.atmosonline.saas.blobstore.functions.BlobMetadataToObject;
import org.jclouds.atmosonline.saas.blobstore.functions.BlobToObject;
@ -48,7 +51,6 @@ 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;
/**
@ -65,13 +67,13 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
private final BlobMetadataToObject blob2ObjectInfo;
private final ListOptionsToBlobStoreListOptions container2ContainerListOptions;
private final ResourceMetadataListToDirectoryEntryList resource2ObjectList;
private final ExecutorService service;
@Inject
private StubAtmosStorageAsyncClient(TransientAsyncBlobStore blobStore,
AtmosObject.Factory objectProvider,
HttpGetOptionsListToGetOptions httpGetOptionsConverter, ObjectToBlob object2Blob,
BlobToObject blob2Object, BlobMetadataToObject blob2ObjectInfo,
ListOptionsToBlobStoreListOptions container2ContainerListOptions,
private StubAtmosStorageAsyncClient(TransientAsyncBlobStore blobStore, AtmosObject.Factory objectProvider,
HttpGetOptionsListToGetOptions httpGetOptionsConverter, ObjectToBlob object2Blob, BlobToObject blob2Object,
BlobMetadataToObject blob2ObjectInfo, ListOptionsToBlobStoreListOptions container2ContainerListOptions,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
ResourceMetadataListToDirectoryEntryList resource2ContainerList) {
this.blobStore = blobStore;
this.objectProvider = objectProvider;
@ -82,6 +84,7 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
this.container2ContainerListOptions = checkNotNull(container2ContainerListOptions,
"container2ContainerListOptions");
this.resource2ObjectList = checkNotNull(resource2ContainerList, "resource2ContainerList");
this.service = service;
}
public ListenableFuture<URI> createDirectory(String directoryName) {
@ -94,8 +97,7 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
container = directoryName;
path = null;
}
return Futures.compose(blobStore.createContainerInLocation(null, container),
new Function<Boolean, URI>() {
return compose(blobStore.createContainerInLocation(null, container), new Function<Boolean, URI>() {
public URI apply(Boolean from) {
if (path != null) {
@ -107,12 +109,11 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
return URI.create("http://stub/containers/" + container);
}
});
}, service);
}
public ListenableFuture<URI> createFile(String parent, AtmosObject object) {
final String uri = "http://stub/containers/" + parent + "/"
+ object.getContentMetadata().getName();
final String uri = "http://stub/containers/" + parent + "/" + object.getContentMetadata().getName();
String file = object.getContentMetadata().getName();
String container = parent;
if (parent.indexOf('/') != -1) {
@ -128,7 +129,7 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
return URI.create(uri);
}
});
}, service);
}
public ListenableFuture<Void> deletePath(String path) {
@ -141,7 +142,7 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
return null;
}
});
}, service);
} else {
String container = path.substring(0, path.indexOf('/'));
path = path.substring(path.indexOf('/') + 1);
@ -159,12 +160,11 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
else {
String container = path.substring(0, path.indexOf('/'));
path = path.substring(path.indexOf('/') + 1);
return compose(blobStore.blobMetadata(container, path),
new Function<BlobMetadata, UserMetadata>() {
return compose(blobStore.blobMetadata(container, path), new Function<BlobMetadata, UserMetadata>() {
public UserMetadata apply(BlobMetadata from) {
return blob2ObjectInfo.apply(from).getUserMetadata();
}
});
}, service);
}
}
@ -172,23 +172,21 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
String container = path.substring(0, path.indexOf('/'));
path = path.substring(path.indexOf('/') + 1);
try {
return Futures.compose(blobStore.getBlob(container, path), blob2Object);
return compose(blobStore.getBlob(container, path), blob2Object, service);
} catch (Exception e) {
return immediateFailedFuture(Throwables.getRootCause(e));
}
}
public ListenableFuture<? extends BoundedSet<? extends DirectoryEntry>> listDirectories(
ListOptions... optionsList) {
public ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectories(ListOptions... optionsList) {
// org.jclouds.blobstore.options.ListOptions options = container2ContainerListOptions
// .apply(optionsList);
return Futures.compose(blobStore.list(), resource2ObjectList);
return compose(blobStore.list(), resource2ObjectList, service);
}
public ListenableFuture<? extends BoundedSet<? extends DirectoryEntry>> listDirectory(
String directoryName, ListOptions... optionsList) {
org.jclouds.blobstore.options.ListContainerOptions options = container2ContainerListOptions
.apply(optionsList);
public ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectory(String directoryName,
ListOptions... optionsList) {
org.jclouds.blobstore.options.ListContainerOptions options = container2ContainerListOptions.apply(optionsList);
String container = directoryName;
if (directoryName.indexOf('/') != -1) {
container = directoryName.substring(0, directoryName.indexOf('/'));
@ -196,7 +194,7 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
if (!path.equals(""))
options.inDirectory(path);
}
return compose(blobStore.list(container, options), resource2ObjectList);
return compose(blobStore.list(container, options), resource2ObjectList, service);
}
public AtmosObject newObject() {
@ -224,7 +222,7 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
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);
return compose(blobStore.getBlob(container, blobName, getOptions), blob2Object, service);
}
public ListenableFuture<Void> updateFile(String parent, AtmosObject object) {

View File

@ -18,6 +18,16 @@
*/
package org.jclouds.aws.ec2.compute.config;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Iterables.toArray;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Maps.newLinkedHashMap;
import static com.google.common.collect.Maps.uniqueIndex;
import static com.google.common.collect.Sets.newHashSet;
import static com.google.common.collect.Sets.newLinkedHashSet;
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds;
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.ownedBy;
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
@ -26,17 +36,18 @@ import static org.jclouds.aws.ec2.util.EC2Utils.getAllRunningInstancesInRegion;
import static org.jclouds.aws.ec2.util.EC2Utils.parseHandle;
import static org.jclouds.compute.domain.OsFamily.CENTOS;
import static org.jclouds.compute.domain.OsFamily.UBUNTU;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import static org.jclouds.concurrent.ConcurrentUtils.transformParallel;
import java.net.URI;
import java.security.SecureRandom;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentMap;
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;
@ -61,6 +72,7 @@ import org.jclouds.aws.ec2.compute.functions.RegionAndIdToImage;
import org.jclouds.aws.ec2.compute.functions.RunningInstanceToNodeMetadata;
import org.jclouds.aws.ec2.compute.internal.EC2TemplateBuilderImpl;
import org.jclouds.aws.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.aws.ec2.compute.strategy.DescribeImagesParallel;
import org.jclouds.aws.ec2.compute.strategy.EC2DestroyLoadBalancerStrategy;
import org.jclouds.aws.ec2.compute.strategy.EC2DestroyNodeStrategy;
import org.jclouds.aws.ec2.compute.strategy.EC2LoadBalanceNodesStrategy;
@ -68,8 +80,8 @@ import org.jclouds.aws.ec2.compute.strategy.EC2RunNodesAndAddToSetStrategy;
import org.jclouds.aws.ec2.domain.InstanceType;
import org.jclouds.aws.ec2.domain.KeyPair;
import org.jclouds.aws.ec2.domain.PlacementGroup;
import org.jclouds.aws.ec2.domain.Reservation;
import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.aws.ec2.domain.Image.ImageType;
import org.jclouds.aws.ec2.functions.RunningInstanceToStorageMappingUnix;
import org.jclouds.aws.ec2.options.DescribeImagesOptions;
import org.jclouds.aws.ec2.predicates.InstancePresent;
@ -96,7 +108,6 @@ import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.LoadBalanceNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
import org.jclouds.concurrent.ConcurrentUtils;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
import org.jclouds.domain.internal.LocationImpl;
@ -108,6 +119,7 @@ import org.jclouds.rest.internal.RestContextImpl;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
@ -115,8 +127,6 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.MapMaker;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Scopes;
@ -206,13 +216,13 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final EC2Client client;
private final EC2AsyncClient client;
private final Map<String, URI> regionMap;
private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
private final ExecutorService executor;
@Inject
protected EC2ListNodesStrategy(EC2Client client, @Region Map<String, URI> regionMap,
protected EC2ListNodesStrategy(EC2AsyncClient client, @Region Map<String, URI> regionMap,
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.client = client;
@ -222,31 +232,25 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
}
@Override
public Iterable<? extends ComputeMetadata> list() {
public Set<? extends ComputeMetadata> list() {
return listDetailsOnNodesMatching(NodePredicates.all());
}
@Override
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
final Set<NodeMetadata> nodes = Sets.newHashSet();
public Set<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
Iterable<Set<? extends Reservation<? extends RunningInstance>>> reservations = transformParallel(regionMap
.keySet(), new Function<String, Future<Set<? extends Reservation<? extends RunningInstance>>>>() {
Map<String, ListenableFuture<?>> parallelResponses = Maps.newHashMap();
for (final String region : regionMap.keySet()) {
parallelResponses.put(region, ConcurrentUtils.makeListenable(executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
Iterables.addAll(nodes, Iterables.transform(Iterables.concat(client.getInstanceServices()
.describeInstancesInRegion(region)), runningInstanceToNodeMetadata));
return null;
public Future<Set<? extends Reservation<? extends RunningInstance>>> apply(String from) {
return client.getInstanceServices().describeInstancesInRegion(from);
}
}), executor));
}
Map<String, Exception> exceptions = awaitCompletion(parallelResponses, executor, null, logger, "nodes");
if (exceptions.size() > 0)
throw new RuntimeException(String.format("error parsing nodes in regions: %s", exceptions));
return Iterables.filter(nodes, filter);
}, executor, null, logger, "reservations");
Iterable<? extends RunningInstance> instances = concat(concat(reservations));
Iterable<? extends NodeMetadata> nodes = filter(transform(instances, runningInstanceToNodeMetadata), filter);
return newLinkedHashSet(nodes);
}
}
@ -268,7 +272,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
String region = parts[0];
String instanceId = parts[1];
try {
RunningInstance runningInstance = Iterables.getOnlyElement(getAllRunningInstancesInRegion(client
RunningInstance runningInstance = getOnlyElement(getAllRunningInstancesInRegion(client
.getInstanceServices(), region, instanceId));
return runningInstanceToNodeMetadata.apply(runningInstance);
} catch (NoSuchElementException e) {
@ -305,7 +309,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
protected final Map<RegionAndName, KeyPair> credentialsMap(CreateUniqueKeyPair in) {
// doesn't seem to clear when someone issues remove(key)
// return new MapMaker().makeComputingMap(in);
return Maps.newLinkedHashMap();
return newLinkedHashMap();
}
@Provides
@ -314,7 +318,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
protected final Map<RegionAndName, String> securityGroupMap(CreateSecurityGroupIfNeeded in) {
// doesn't seem to clear when someone issues remove(key)
// return new MapMaker().makeComputingMap(in);
return Maps.newLinkedHashMap();
return newLinkedHashMap();
}
@Provides
@ -323,7 +327,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
protected final Map<RegionAndName, String> placementGroupMap(CreatePlacementGroupIfNeeded in) {
// doesn't seem to clear when someone issues remove(key)
// return new MapMaker().makeComputingMap(in);
return Maps.newLinkedHashMap();
return newLinkedHashMap();
}
@Provides
@ -340,10 +344,10 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
@Provides
@Singleton
Set<? extends Size> provideSizes(Set<? extends Location> locations, @Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis) {
Set<Size> sizes = Sets.newHashSet();
Set<Size> sizes = newHashSet();
for (String ccAmi : ccAmis) {
final String region = ccAmi.split("/")[0];
Location location = Iterables.find(locations, new Predicate<Location>() {
Location location = find(locations, new Predicate<Location>() {
@Override
public boolean apply(Location input) {
@ -362,11 +366,11 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
Set<? extends Location> provideLocations(Map<String, String> availabilityZoneToRegionMap,
@Provider String providerName) {
Location ec2 = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
Set<Location> locations = Sets.newLinkedHashSet();
for (String region : Sets.newLinkedHashSet(availabilityZoneToRegionMap.values())) {
Set<Location> locations = newLinkedHashSet();
for (String region : newLinkedHashSet(availabilityZoneToRegionMap.values())) {
locations.add(new LocationImpl(LocationScope.REGION, region, region, ec2));
}
ImmutableMap<String, Location> idToLocation = Maps.uniqueIndex(locations, new Function<Location, String>() {
ImmutableMap<String, Location> idToLocation = uniqueIndex(locations, new Function<Location, String>() {
@Override
public String apply(Location from) {
return from.getId();
@ -391,7 +395,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
String[] amiOwners(@Named(PROPERTY_EC2_AMI_OWNERS) String amiOwners) {
if (amiOwners.trim().equals(""))
return new String[] {};
return Iterables.toArray(Splitter.on(',').split(amiOwners), String.class);
return toArray(Splitter.on(',').split(amiOwners), String.class);
}
@Provides
@ -400,7 +404,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
String[] ccAmis(@Named(PROPERTY_EC2_CC_AMIs) String ccAmis) {
if (ccAmis.trim().equals(""))
return new String[] {};
return Iterables.toArray(Splitter.on(',').split(ccAmis), String.class);
return toArray(Splitter.on(',').split(ccAmis), String.class);
}
@Provides
@ -416,54 +420,62 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
@Provides
@Singleton
protected Map<RegionAndName, ? extends Image> provideImages(final EC2Client sync,
@Region Map<String, URI> regionMap, final LogHolder holder, Function<ComputeMetadata, String> indexer,
@Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis, @Named(PROPERTY_EC2_AMI_OWNERS) final String[] amiOwners,
final ImageParser parser, final ConcurrentMap<RegionAndName, Image> images,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) throws InterruptedException,
ExecutionException, TimeoutException {
protected Map<RegionAndName, ? extends Image> provideImages(@Region Map<String, URI> regionMap,
DescribeImagesParallel describer, LogHolder holder, @Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis,
@Named(PROPERTY_EC2_AMI_OWNERS) final String[] amiOwners, final ImageParser parser,
final ConcurrentMap<RegionAndName, Image> images) throws InterruptedException, ExecutionException,
TimeoutException {
if (amiOwners.length == 0) {
holder.logger.debug(">> no owners specified, skipping image parsing");
} else {
holder.logger.debug(">> providing images");
Map<String, ListenableFuture<?>> parallelResponses = Maps.newHashMap();
final DescribeImagesOptions options;
if (amiOwners.length == 1 && amiOwners[0].equals("*"))
options = new DescribeImagesOptions();
else
options = ownedBy(amiOwners);
for (final String region : regionMap.keySet()) {
parallelResponses.put(region, ConcurrentUtils.makeListenable(executor.submit(new Callable<Void>() {
Iterable<Entry<String, DescribeImagesOptions>> queries = concat(getDescribeQueriesForOwnersInRegions(
regionMap, amiOwners).entrySet(), ccAmisToDescribeQueries(ccAmis).entrySet());
Iterable<? extends Image> parsedImages = filter(transform(describer.apply(queries), parser), Predicates
.notNull());
images.putAll(Maps.uniqueIndex(parsedImages, new Function<Image, RegionAndName>() {
@Override
public Void call() throws Exception {
Set<org.jclouds.aws.ec2.domain.Image> matchingImages = sync.getAMIServices().describeImagesInRegion(
region, options);
for (final org.jclouds.aws.ec2.domain.Image from : matchingImages) {
Image image = parser.apply(from);
if (image != null)
images.put(new RegionAndName(region, image.getProviderId()), image);
else if (from.getImageType() == ImageType.MACHINE)
holder.logger.trace("<< image(%s) didn't parse", from.getId());
public RegionAndName apply(Image from) {
return new RegionAndName(from.getLocation().getId(), from.getProviderId());
}
return null;
}
}), executor));
}
Map<String, Exception> exceptions = awaitCompletion(parallelResponses, executor, null, holder.logger, "images");
for (String ccAmi : ccAmis) {
String region = ccAmi.split("/")[0];
org.jclouds.aws.ec2.domain.Image from = Iterables.getOnlyElement(sync.getAMIServices()
.describeImagesInRegion(region, imageIds(ccAmi.split("/")[1])));
Image image = parser.apply(from);
if (image != null)
images.put(new RegionAndName(region, image.getProviderId()), image);
}
if (exceptions.size() > 0)
throw new RuntimeException(String.format("error parsing images in regions: %s", exceptions));
}));
holder.logger.debug("<< images(%d)", images.size());
}
return images;
}
private Map<String, DescribeImagesOptions> ccAmisToDescribeQueries(String[] ccAmis) {
Map<String, DescribeImagesOptions> queries = Maps.newLinkedHashMap();
for (String from : ccAmis) {
queries.put(from.split("/")[0], imageIds(from.split("/")[1]));
}
return queries;
}
private Map<String, DescribeImagesOptions> getDescribeQueriesForOwnersInRegions(Map<String, URI> regionMap,
final String[] amiOwners) {
final DescribeImagesOptions options = getOptionsForOwners(amiOwners);
return Maps.transformValues(regionMap, new Function<URI, DescribeImagesOptions>() {
@Override
public DescribeImagesOptions apply(URI from) {
return options;
}
});
}
private DescribeImagesOptions getOptionsForOwners(final String[] amiOwners) {
final DescribeImagesOptions options;
if (amiOwners.length == 1 && amiOwners[0].equals("*"))
options = new DescribeImagesOptions();
else
options = ownedBy(amiOwners);
return options;
}
}

View File

@ -80,7 +80,8 @@ public class EC2TemplateBuilderImpl extends TemplateBuilderImpl {
if (imageId != null) {
String[] regionName = imageId.split("/");
checkArgument(regionName.length == 2,
"amazon image ids must include the region. ex. us-east-1/ami-7ea24a17");
"amazon image ids must include the region ( ex. us-east-1/ami-7ea24a17 ) you specified: "
+ imageId);
RegionAndName key = new RegionAndName(regionName[0], regionName[1]);
try {
return imageMap.get(key);

View File

@ -0,0 +1,79 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.aws.ec2.compute.strategy;
import static com.google.common.collect.Iterables.concat;
import static org.jclouds.concurrent.ConcurrentUtils.transformParallel;
import java.util.Set;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.options.DescribeImagesOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
/**
*
* @author Adrian Cole
*/
@Singleton
public class DescribeImagesParallel implements
Function<Iterable<Entry<String, DescribeImagesOptions>>, Iterable<? extends org.jclouds.aws.ec2.domain.Image>> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final EC2AsyncClient sync;
final ExecutorService executor;
@Inject
public DescribeImagesParallel(EC2AsyncClient sync, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
super();
this.sync = sync;
this.executor = executor;
}
@Override
public Iterable<? extends org.jclouds.aws.ec2.domain.Image> apply(
Iterable<Entry<String, DescribeImagesOptions>> queries) {
return concat(transformParallel(
queries,
new Function<Entry<String, DescribeImagesOptions>, Future<Set<? extends org.jclouds.aws.ec2.domain.Image>>>() {
@Override
public Future<Set<? extends org.jclouds.aws.ec2.domain.Image>> apply(
Entry<String, DescribeImagesOptions> from) {
return sync.getAMIServices().describeImagesInRegion(from.getKey(), from.getValue());
}
}, executor, null, logger, "amis"));
}
}

View File

@ -27,6 +27,7 @@ import static org.jclouds.aws.ec2.compute.util.EC2ComputeUtils.instanceToId;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Inject;
@ -48,7 +49,6 @@ import org.jclouds.logging.Logger;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.util.concurrent.ListenableFuture;
/**
* creates futures that correlate to
@ -56,8 +56,7 @@ import com.google.common.util.concurrent.ListenableFuture;
* @author Adrian Cole
*/
@Singleton
public class EC2RunNodesAndAddToSetStrategy implements
RunNodesAndAddToSetStrategy {
public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrategy {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
@ -79,8 +78,7 @@ public class EC2RunNodesAndAddToSetStrategy implements
EC2Client client,
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
@Named("PRESENT") Predicate<RunningInstance> instancePresent,
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata,
ComputeUtils utils) {
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata, ComputeUtils utils) {
this.client = client;
this.instancePresent = instancePresent;
this.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
@ -89,12 +87,11 @@ public class EC2RunNodesAndAddToSetStrategy implements
}
@Override
public Map<?, ListenableFuture<Void>> execute(String tag, int count,
Template template, Set<NodeMetadata> goodNodes,
public Map<?, Future<Void>> execute(String tag, int count, Template template, Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes) {
Reservation reservation = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(
tag, count, template);
Reservation<? extends RunningInstance> reservation = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(tag,
count, template);
Iterable<String> ids = transform(reservation, instanceToId);
@ -104,28 +101,25 @@ public class EC2RunNodesAndAddToSetStrategy implements
all(reservation, instancePresent);
logger.debug("<< present instances(%s)", idsString);
return utils.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(
template.getOptions(), transform(reservation,
runningInstanceToNodeMetadata), goodNodes, badNodes);
return utils.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(template.getOptions(), transform(
reservation, runningInstanceToNodeMetadata), goodNodes, badNodes);
}
@VisibleForTesting
Reservation createKeyPairAndSecurityGroupsAsNeededThenRunInstances(
String tag, int count, Template template) {
Reservation<? extends RunningInstance> createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String tag, int count,
Template template) {
String region = getRegionFromLocationOrNull(template.getLocation());
String zone = getZoneFromLocationOrNull(template.getLocation());
RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions
.execute(region, tag, template);
RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.execute(region,
tag, template);
if (logger.isDebugEnabled())
logger.debug(
">> running %d instance region(%s) zone(%s) ami(%s) params(%s)",
count, region, zone, template.getImage().getProviderId(),
instanceOptions.buildFormParameters());
logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count, region, zone, template
.getImage().getProviderId(), instanceOptions.buildFormParameters());
return client.getInstanceServices().runInstancesInRegion(region, zone,
template.getImage().getProviderId(), 1, count, instanceOptions);
return client.getInstanceServices().runInstancesInRegion(region, zone, template.getImage().getProviderId(), 1,
count, instanceOptions);
}
}

View File

@ -33,8 +33,8 @@ import com.google.inject.internal.Nullable;
* />
* @author Adrian Cole
*/
public class Reservation extends LinkedHashSet<RunningInstance> implements Comparable<Reservation>,
Set<RunningInstance> {
public class Reservation<T extends RunningInstance> extends LinkedHashSet<T> implements Comparable<Reservation<T>>,
Set<T> {
/** The serialVersionUID */
private static final long serialVersionUID = -9051777593518861395L;
@ -47,9 +47,8 @@ public class Reservation extends LinkedHashSet<RunningInstance> implements Compa
private final @Nullable
String reservationId;
public Reservation(String region, Iterable<String> groupIds,
Iterable<RunningInstance> instances, @Nullable String ownerId,
@Nullable String requesterId, @Nullable String reservationId) {
public Reservation(String region, Iterable<String> groupIds, Iterable<T> instances,
@Nullable String ownerId, @Nullable String requesterId, @Nullable String reservationId) {
this.region = checkNotNull(region, "region");
Iterables.addAll(this.groupIds, checkNotNull(groupIds, "groupIds"));
Iterables.addAll(this, checkNotNull(instances, "instances"));
@ -65,7 +64,7 @@ public class Reservation extends LinkedHashSet<RunningInstance> implements Compa
return region;
}
public int compareTo(Reservation o) {
public int compareTo(Reservation<T> o) {
return (this == o) ? 0 : getReservationId().compareTo(o.getReservationId());
}
@ -117,7 +116,7 @@ public class Reservation extends LinkedHashSet<RunningInstance> implements Compa
return false;
if (getClass() != obj.getClass())
return false;
Reservation other = (Reservation) obj;
Reservation<?> other = (Reservation<?>) obj;
if (groupIds == null) {
if (other.groupIds != null)
return false;

View File

@ -32,7 +32,7 @@ import org.jclouds.aws.ec2.options.internal.BaseEC2RequestOptions;
* import static org.jclouds.aws.ec2.options.CreateImageOptions.Builder.*
* <p/>
* EC2Client connection = // get connection
* ListenableFuture<Set<ImageMetadata>> images = connection.getAMIServices().createImage(withDescription("123125").noReboot());
* Future<Set<ImageMetadata>> images = connection.getAMIServices().createImage(withDescription("123125").noReboot());
* <code>
*
* @author Adrian Cole

View File

@ -33,7 +33,7 @@ import org.jclouds.aws.ec2.options.internal.BaseEC2RequestOptions;
* import static org.jclouds.aws.ec2.options.DescribeAvailabilityZonesOptions.Builder.*
* <p/>
* EC2Client connection = // get connection
* ListenableFuture<Set<ImageMetadata>> images = connection.getAvailabilityZoneAndRegionServices().describeAvailabilityZones(zones("us-east-1a", "us-east-1b"));
* Future<Set<ImageMetadata>> images = connection.getAvailabilityZoneAndRegionServices().describeAvailabilityZones(zones("us-east-1a", "us-east-1b"));
* <code>
*
* @author Adrian Cole

View File

@ -34,7 +34,7 @@ import org.jclouds.aws.ec2.options.internal.BaseEC2RequestOptions;
* import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.*
* <p/>
* EC2Client connection = // get connection
* ListenableFuture<Set<ImageMetadata>> images = connection.getAMIServices().describeImages(executableBy("123125").imageIds(1000, 1004));
* Future<Set<ImageMetadata>> images = connection.getAMIServices().describeImages(executableBy("123125").imageIds(1000, 1004));
* <code>
*
* @author Adrian Cole

View File

@ -34,7 +34,7 @@ import org.jclouds.aws.ec2.options.internal.BaseEC2RequestOptions;
* import static org.jclouds.aws.ec2.options.DescribeRegionsOptions.Builder.*
* <p/>
* EC2Client connection = // get connection
* ListenableFuture<Set<ImageMetadata>> images = connection.getRegionsAndRegionsServices().describeRegions(regions("us-east-1a", "us-east-1b"));
* Future<Set<ImageMetadata>> images = connection.getRegionsAndRegionsServices().describeRegions(regions("us-east-1a", "us-east-1b"));
* <code>
*
* @author Adrian Cole

View File

@ -35,7 +35,7 @@ import org.jclouds.encryption.internal.Base64;
* import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.*
* <p/>
* EC2Client connection = // get connection
* ListenableFuture<ReservationInfo> instances = connection.runInstances(executableBy("123125").imageIds(1000, 1004));
* Future<ReservationInfo> instances = connection.runInstances(executableBy("123125").imageIds(1000, 1004));
* <code>
*
* @author Adrian Cole

View File

@ -23,6 +23,7 @@ import static org.jclouds.aws.ec2.reference.EC2Parameters.VERSION;
import java.util.Map;
import java.util.Set;
import com.google.common.util.concurrent.ListenableFuture;
import javax.annotation.Nullable;
import javax.ws.rs.FormParam;
@ -56,8 +57,6 @@ import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides access to AMI Services.
* <p/>
@ -77,7 +76,7 @@ public interface AMIAsyncClient {
@FormParams(keys = ACTION, values = "DescribeImages")
@XMLResponseParser(DescribeImagesResponseHandler.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<? extends Set<Image>> describeImagesInRegion(
ListenableFuture<Set<? extends Image>> describeImagesInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, DescribeImagesOptions... options);
/**
@ -87,9 +86,8 @@ public interface AMIAsyncClient {
@Path("/")
@FormParams(keys = ACTION, values = "CreateImage")
@XMLResponseParser(ImageIdHandler.class)
ListenableFuture<String> createImageInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, @FormParam("Name") String name,
@FormParam("InstanceId") String instanceId, CreateImageOptions... options);
ListenableFuture<String> createImageInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@FormParam("Name") String name, @FormParam("InstanceId") String instanceId, CreateImageOptions... options);
/**
* @see AMIClient#deregisterImageInRegion
@ -97,8 +95,7 @@ public interface AMIAsyncClient {
@POST
@Path("/")
@FormParams(keys = ACTION, values = "DeregisterImage")
ListenableFuture<Void> deregisterImageInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
ListenableFuture<Void> deregisterImageInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@FormParam("ImageId") String imageId);
/**
@ -181,7 +178,7 @@ public interface AMIAsyncClient {
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeImageAttribute", "productCodes" })
@XMLResponseParser(ProductCodesHandler.class)
ListenableFuture<? extends Set<String>> getProductCodesForImageInRegion(
ListenableFuture<Set<String>> getProductCodesForImageInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@FormParam("ImageId") String imageId);
@ -192,7 +189,7 @@ public interface AMIAsyncClient {
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeImageAttribute", "blockDeviceMapping" })
@XMLResponseParser(BlockDeviceMappingHandler.class)
ListenableFuture<? extends Map<String, EbsBlockDevice>> getBlockDeviceMappingsForImageInRegion(
ListenableFuture<Map<String, EbsBlockDevice>> getBlockDeviceMappingsForImageInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@FormParam("ImageId") String imageId);
@ -203,8 +200,7 @@ public interface AMIAsyncClient {
@Path("/")
@FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifyImageAttribute", "add",
"productCodes" })
ListenableFuture<Void> addProductCodesToImageInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
ListenableFuture<Void> addProductCodesToImageInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@BinderParam(BindProductCodesToIndexedFormParams.class) Iterable<String> productCodes,
@FormParam("ImageId") String imageId);

View File

@ -57,7 +57,7 @@ public interface AMIClient {
* @see DescribeImagesOptions
*/
@Timeout(duration = 300, timeUnit = TimeUnit.SECONDS)
Set<Image> describeImagesInRegion(@Nullable String region, DescribeImagesOptions... options);
Set<? extends Image> describeImagesInRegion(@Nullable String region, DescribeImagesOptions... options);
/**
* Returns the Product Codes of an image.

View File

@ -23,6 +23,7 @@ import static org.jclouds.aws.ec2.reference.EC2Parameters.VERSION;
import java.util.Map;
import java.util.Set;
import com.google.common.util.concurrent.ListenableFuture;
import javax.annotation.Nullable;
import javax.ws.rs.FormParam;
@ -61,8 +62,6 @@ import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides access to EC2 Instance Services via their REST API.
* <p/>
@ -82,7 +81,7 @@ public interface InstanceAsyncClient {
@FormParams(keys = ACTION, values = "DescribeInstances")
@XMLResponseParser(DescribeInstancesResponseHandler.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<? extends Set<Reservation>> describeInstancesInRegion(
ListenableFuture<Set<? extends Reservation<? extends RunningInstance>>> describeInstancesInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
@ -93,8 +92,7 @@ public interface InstanceAsyncClient {
@Path("/")
@FormParams(keys = ACTION, values = "RunInstances")
@XMLResponseParser(RunInstancesResponseHandler.class)
ListenableFuture<Reservation> runInstancesInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
ListenableFuture<Reservation<? extends RunningInstance>> runInstancesInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@Nullable @BinderParam(IfNotNullBindAvailabilityZoneToFormParam.class) String nullableAvailabilityZone,
@FormParam("ImageId") String imageId, @FormParam("MinCount") int minCount,
@FormParam("MaxCount") int maxCount, RunInstancesOptions... options);
@ -105,8 +103,7 @@ public interface InstanceAsyncClient {
@POST
@Path("/")
@FormParams(keys = ACTION, values = "RebootInstances")
ListenableFuture<Void> rebootInstancesInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
ListenableFuture<Void> rebootInstancesInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
/**
@ -116,7 +113,7 @@ public interface InstanceAsyncClient {
@Path("/")
@FormParams(keys = ACTION, values = "TerminateInstances")
@XMLResponseParser(InstanceStateChangeHandler.class)
ListenableFuture<? extends Set<InstanceStateChange>> terminateInstancesInRegion(
ListenableFuture<Set<? extends InstanceStateChange>> terminateInstancesInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
@ -127,7 +124,7 @@ public interface InstanceAsyncClient {
@Path("/")
@FormParams(keys = ACTION, values = "StopInstances")
@XMLResponseParser(InstanceStateChangeHandler.class)
ListenableFuture<? extends Set<InstanceStateChange>> stopInstancesInRegion(
ListenableFuture<Set<? extends InstanceStateChange>> stopInstancesInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, @FormParam("Force") boolean force,
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
@ -138,7 +135,7 @@ public interface InstanceAsyncClient {
@Path("/")
@FormParams(keys = ACTION, values = "StartInstances")
@XMLResponseParser(InstanceStateChangeHandler.class)
ListenableFuture<? extends Set<InstanceStateChange>> startInstancesInRegion(
ListenableFuture<Set<? extends InstanceStateChange>> startInstancesInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
@ -182,8 +179,7 @@ public interface InstanceAsyncClient {
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "kernel" })
@XMLResponseParser(StringValueHandler.class)
ListenableFuture<String> getKernelForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
ListenableFuture<String> getKernelForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@FormParam("InstanceId") String instanceId);
/**
@ -247,8 +243,7 @@ public interface InstanceAsyncClient {
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ResetInstanceAttribute", "kernel" })
ListenableFuture<Void> resetKernelForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
ListenableFuture<Void> resetKernelForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@FormParam("InstanceId") String instanceId);
/**
@ -257,8 +252,7 @@ public interface InstanceAsyncClient {
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "userData" })
ListenableFuture<Void> setUserDataForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
ListenableFuture<Void> setUserDataForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@FormParam("InstanceId") String instanceId,
@FormParam("Value") @ParamParser(ConvertUnencodedBytesToBase64EncodedString.class) byte[] unencodedData);
@ -268,8 +262,7 @@ public interface InstanceAsyncClient {
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "ramdisk" })
ListenableFuture<Void> setRamdiskForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
ListenableFuture<Void> setRamdiskForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@FormParam("InstanceId") String instanceId, @FormParam("Value") String ramdisk);
/**
@ -278,8 +271,7 @@ public interface InstanceAsyncClient {
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "kernel" })
ListenableFuture<Void> setKernelForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
ListenableFuture<Void> setKernelForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
@FormParam("InstanceId") String instanceId, @FormParam("Value") String kernel);
/**

View File

@ -61,7 +61,7 @@ public interface InstanceClient {
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html"
* />
*/
Set<Reservation> describeInstancesInRegion(@Nullable String region,
Set<? extends Reservation<? extends RunningInstance>> describeInstancesInRegion(@Nullable String region,
String... instanceIds);
/**
@ -141,7 +141,7 @@ public interface InstanceClient {
* />
* @see RunInstancesOptions
*/
Reservation runInstancesInRegion(@Nullable String region,
Reservation<? extends RunningInstance> runInstancesInRegion(@Nullable String region,
@Nullable String nullableAvailabilityZone, String imageId,
int minCount, int maxCount, RunInstancesOptions... options);
@ -161,7 +161,7 @@ public interface InstanceClient {
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-TerminateInstances.html"
* />
*/
Set<InstanceStateChange> terminateInstancesInRegion(@Nullable String region,
Set<? extends InstanceStateChange> terminateInstancesInRegion(@Nullable String region,
String... instanceIds);
/**
@ -199,7 +199,7 @@ public interface InstanceClient {
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html"
* />
*/
Set<InstanceStateChange> stopInstancesInRegion(@Nullable String region,
Set<? extends InstanceStateChange> stopInstancesInRegion(@Nullable String region,
boolean force, String... instanceIds);
/**
@ -255,7 +255,7 @@ public interface InstanceClient {
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StartInstances.html"
* />
*/
Set<InstanceStateChange> startInstancesInRegion(@Nullable String region,
Set<? extends InstanceStateChange> startInstancesInRegion(@Nullable String region,
String... instanceIds);
/**

View File

@ -270,11 +270,12 @@ public abstract class BaseReservationHandler<T> extends HandlerForGeneratedReque
currentText.append(ch, start, length);
}
protected Reservation newReservation() {
protected Reservation<? extends RunningInstance> newReservation() {
String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
if (region == null)
region = defaultRegion;
Reservation info = new Reservation(region, groupIds, instances, ownerId, requesterId, reservationId);
Reservation<? extends RunningInstance> info = new Reservation<RunningInstance>(region, groupIds, instances,
ownerId, requesterId, reservationId);
this.groupIds = Sets.newLinkedHashSet();
this.instances = Sets.newLinkedHashSet();
this.ownerId = null;

View File

@ -24,6 +24,7 @@ import javax.inject.Inject;
import org.jclouds.aws.Region;
import org.jclouds.aws.ec2.domain.Reservation;
import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.date.DateService;
import com.google.common.collect.Sets;
@ -37,8 +38,8 @@ import com.google.common.collect.Sets;
* @see <a href="http: />
*/
public class DescribeInstancesResponseHandler extends
BaseReservationHandler<Set<Reservation>> {
private Set<Reservation> reservations = Sets.newLinkedHashSet();
BaseReservationHandler<Set<Reservation<? extends RunningInstance>>> {
private Set<Reservation<? extends RunningInstance>> reservations = Sets.newLinkedHashSet();
@Inject
DescribeInstancesResponseHandler(DateService dateService, @Region String defaultRegion) {
@ -46,7 +47,7 @@ public class DescribeInstancesResponseHandler extends
}
@Override
public Set<Reservation> getResult() {
public Set<Reservation<? extends RunningInstance>> getResult() {
return reservations;
}

View File

@ -22,6 +22,7 @@ import javax.inject.Inject;
import org.jclouds.aws.Region;
import org.jclouds.aws.ec2.domain.Reservation;
import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.date.DateService;
/**
@ -32,7 +33,7 @@ import org.jclouds.date.DateService;
* @author Adrian Cole
* @see <a href="http: />
*/
public class RunInstancesResponseHandler extends BaseReservationHandler<Reservation> {
public class RunInstancesResponseHandler extends BaseReservationHandler<Reservation<? extends RunningInstance>> {
@Inject
RunInstancesResponseHandler(DateService dateService, @Region String defaultRegion) {
@ -40,7 +41,7 @@ public class RunInstancesResponseHandler extends BaseReservationHandler<Reservat
}
@Override
public Reservation getResult() {
public Reservation<? extends RunningInstance> getResult() {
return newReservation();
}

View File

@ -38,14 +38,14 @@ import org.jclouds.aws.s3.options.PutObjectOptions;
import org.jclouds.concurrent.Timeout;
import org.jclouds.http.options.GetOptions;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.concurrent.Future;
/**
* Provides access to S3 via their REST API.
* <p/>
* All commands return a ListenableFuture of the result from S3. Any exceptions incurred during
* All commands return a Future of the result from S3. Any exceptions incurred during
* processing will be wrapped in an {@link ExecutionException} as documented in
* {@link ListenableFuture#get()}.
* {@link Future#get()}.
*
* @author Adrian Cole
* @author James Murty
@ -85,7 +85,7 @@ public interface S3Client {
* namespace of the object you are retrieving
* @param key
* unique key in the s3Bucket identifying the object
* @return ListenableFuture reference to a fully populated S3Object including data stored in S3
* @return Future reference to a fully populated S3Object including data stored in S3
* or {@link S3Object#NOT_FOUND} if not present.
*
* @throws org.jclouds.http.HttpResponseException
@ -231,7 +231,7 @@ public interface S3Client {
*
* @param bucketName
* namespace of the objects you wish to list
* @return ListenableFuture reference to a fully populated S3Bucket including metadata of the
* @return Future reference to a fully populated S3Bucket including metadata of the
* S3Objects it contains or {@link BoundedList<ObjectMetadata>#NOT_FOUND} if not present.
* @see ListBucketOptions
*

View File

@ -19,10 +19,11 @@
package org.jclouds.aws.s3.blobstore;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.compose;
import static org.jclouds.concurrent.ConcurrentUtils.compose;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import com.google.common.util.concurrent.ListenableFuture;
import javax.inject.Inject;
import javax.inject.Named;
@ -60,7 +61,6 @@ import org.jclouds.http.options.GetOptions;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.ListenableFuture;
/**
*
@ -82,41 +82,34 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
@Inject
S3AsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
Location defaultLocation, Set<? extends Location> locations, S3AsyncClient async,
S3Client sync, BucketToResourceMetadata bucket2ResourceMd,
ContainerToBucketListOptions container2BucketListOptions,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Location defaultLocation,
Set<? extends Location> locations, S3AsyncClient async, S3Client sync,
BucketToResourceMetadata bucket2ResourceMd, ContainerToBucketListOptions container2BucketListOptions,
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,
BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object,
ObjectToBlobMetadata object2BlobMd,
BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd,
Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
super(context, blobUtils, service, defaultLocation, locations);
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
this.async = checkNotNull(async, "async");
this.sync = checkNotNull(sync, "sync");
this.bucket2ResourceMd = checkNotNull(bucket2ResourceMd, "bucket2ResourceMd");
this.container2BucketListOptions = checkNotNull(container2BucketListOptions,
"container2BucketListOptions");
this.container2BucketListOptions = checkNotNull(container2BucketListOptions, "container2BucketListOptions");
this.bucket2ResourceList = checkNotNull(bucket2ResourceList, "bucket2ResourceList");
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd");
this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider,
"fetchBlobMetadataProvider");
this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider, "fetchBlobMetadataProvider");
}
/**
* This implementation invokes {@link S3AsyncClient#listOwnedBuckets}
*/
@Override
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list() {
return compose(
async.listOwnedBuckets(),
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
return compose(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 new PageSetImpl<StorageMetadata>(Iterables.transform(from,
bucket2ResourceMd), null);
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(Set<BucketMetadata> from) {
return new PageSetImpl<StorageMetadata>(Iterables.transform(from, bucket2ResourceMd), null);
}
}, service);
}
@ -153,14 +146,13 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
* bucket name
*/
@Override
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(String container,
ListContainerOptions options) {
// TODO get rid of compose, 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 = compose(returnVal,
bucket2ResourceList, service);
return options.isDetailed() ? compose(list, fetchBlobMetadataProvider.get().setContainerName(
container), service) : list;
ListenableFuture<PageSet<? extends StorageMetadata>> list = compose(returnVal, bucket2ResourceList, service);
return (options.isDetailed()) ? compose(list, fetchBlobMetadataProvider.get().setContainerName(container),
service) : list;
}
/**
@ -193,8 +185,7 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
*/
@Override
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
return compose(async.headObject(container, key),
new Function<ObjectMetadata, BlobMetadata>() {
return compose(async.headObject(container, key), new Function<ObjectMetadata, BlobMetadata>() {
@Override
public BlobMetadata apply(ObjectMetadata from) {
@ -213,8 +204,7 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
* object key
*/
@Override
public ListenableFuture<Blob> getBlob(String container, String key,
org.jclouds.blobstore.options.GetOptions options) {
public ListenableFuture<Blob> getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions options) {
GetOptions httpOptions = blob2ObjectGetOptions.apply(options);
return compose(async.getObject(container, key, httpOptions), object2Blob, service);
}

View File

@ -58,7 +58,7 @@ import com.google.common.collect.Multimap;
* <p/>
* // this will copy the object, provided it wasn't modified since yesterday.
* // it will not use metadata from the source, and instead use what we pass in.
* ListenableFuture<S3Object.Metadata> object = connection.copyObject("sourceBucket", "objectName",
* Future<S3Object.Metadata> object = connection.copyObject("sourceBucket", "objectName",
* "destinationBucket", "destinationName",
* overrideMetadataWith(meta).
* ifSourceModifiedSince(new Date().minusDays(1))

View File

@ -33,7 +33,7 @@ import org.jclouds.http.options.BaseHttpRequestOptions;
* import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.*
* <p/>
* S3Client connection = // get connection
* ListenableFuture<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000));
* Future<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000));
* <code>
*
* @author Adrian Cole

View File

@ -46,7 +46,7 @@ import com.google.common.collect.Multimap;
* import org.jclouds.aws.s3.S3Client;
* <p/>
* S3Client connection = // get connection
* ListenableFuture<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU));
* Future<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU));
* <code>
*
* @author Adrian Cole

View File

@ -46,7 +46,7 @@ import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
* import org.jclouds.aws.s3.S3Client;
*
* S3Client connection = // get connection
* ListenableFuture<Boolean> publicly readable = connection.putObject("bucketName",new S3Object("key","value"), withAcl(CannedAccessPolicy.PUBLIC_READ));
* Future<Boolean> publicly readable = connection.putObject("bucketName",new S3Object("key","value"), withAcl(CannedAccessPolicy.PUBLIC_READ));
* <code>
*
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectPUT.html?"

View File

@ -69,8 +69,7 @@ import com.google.inject.Module;
/**
* Follows the book Cloud Application Architectures ISBN: 978-0-596-15636-7
* <p/>
* adds in functionality to boot a lamp instance:
* http://alestic.com/2009/06/ec2-user-data-scripts
* adds in functionality to boot a lamp instance: http://alestic.com/2009/06/ec2-user-data-scripts
* <p/>
* Generally disabled, as it incurs higher fees.
*
@ -92,49 +91,38 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private RetryablePredicate<RunningInstance> runningTester;
@BeforeGroups(groups = { "live" })
public void setupClient() throws InterruptedException, ExecutionException,
TimeoutException,
IOException {
String identity = checkNotNull(System.getProperty("jclouds.test.identity"),
"jclouds.test.identity");
String credential = checkNotNull(System.getProperty("jclouds.test.credential"),
"jclouds.test.credential");
Injector injector = new RestContextFactory().createContextBuilder(
"ec2", identity, credential, ImmutableSet.<Module> of(new Log4JLoggingModule())).buildInjector();
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException, IOException {
String identity = checkNotNull(System.getProperty("jclouds.test.identity"), "jclouds.test.identity");
String credential = checkNotNull(System.getProperty("jclouds.test.credential"), "jclouds.test.credential");
Injector injector = new RestContextFactory().createContextBuilder("ec2", identity, credential,
ImmutableSet.<Module> of(new Log4JLoggingModule())).buildInjector();
client = injector.getInstance(EC2Client.class);
sshFactory = injector.getInstance(SshClient.Factory.class);
runningTester = new RetryablePredicate<RunningInstance>(
new InstanceStateRunning(client), 180, 5, TimeUnit.SECONDS);
hasIpTester = new RetryablePredicate<RunningInstance>(
new InstanceHasIpAddress(client), 180, 5, TimeUnit.SECONDS);
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
socketTester = new RetryablePredicate<IPSocket>(socketOpen, 180, 1,
runningTester = new RetryablePredicate<RunningInstance>(new InstanceStateRunning(client), 180, 5,
TimeUnit.SECONDS);
hasIpTester = new RetryablePredicate<RunningInstance>(new InstanceHasIpAddress(client), 180, 5, TimeUnit.SECONDS);
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
socketTester = new RetryablePredicate<IPSocket>(socketOpen, 180, 1, TimeUnit.SECONDS);
}
@Test(enabled = false)
void testCreateSecurityGroupIngressCidr() throws InterruptedException,
ExecutionException, TimeoutException {
void testCreateSecurityGroupIngressCidr() throws InterruptedException, ExecutionException, TimeoutException {
securityGroupName = instancePrefix + "ingress";
try {
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null,
securityGroupName);
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName);
} catch (Exception e) {
}
client.getSecurityGroupServices().createSecurityGroupInRegion(null,
securityGroupName, securityGroupName);
client.getSecurityGroupServices().createSecurityGroupInRegion(null, securityGroupName, securityGroupName);
for (int port : new int[] { 80, 443, 22 }) {
client.getSecurityGroupServices()
.authorizeSecurityGroupIngressInRegion(null, securityGroupName,
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, securityGroupName,
IpProtocol.TCP, port, port, "0.0.0.0/0");
}
}
@Test(enabled = false)
void testCreateKeyPair() throws InterruptedException, ExecutionException,
TimeoutException {
void testCreateKeyPair() throws InterruptedException, ExecutionException, TimeoutException {
String keyName = instancePrefix + "1";
try {
client.getKeyPairServices().deleteKeyPairInRegion(null, keyName);
@ -143,16 +131,14 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
}
client.getKeyPairServices().deleteKeyPairInRegion(null, keyName);
keyPair = client.getKeyPairServices()
.createKeyPairInRegion(null, keyName);
keyPair = client.getKeyPairServices().createKeyPairInRegion(null, keyName);
assertNotNull(keyPair);
assertNotNull(keyPair.getKeyMaterial());
assertNotNull(keyPair.getKeyFingerprint());
assertEquals(keyPair.getKeyName(), keyName);
}
@Test(enabled = false, dependsOnMethods = { "testCreateKeyPair",
"testCreateSecurityGroupIngressCidr" })
@Test(enabled = false, dependsOnMethods = { "testCreateKeyPair", "testCreateSecurityGroupIngressCidr" })
public void testCreateRunningInstance() throws Exception {
String script = new ScriptBuilder() // lamp install script
.addStatement(exec("runurl run.alestic.com/apt/upgrade"))//
@ -163,10 +149,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
while (instance == null) {
try {
System.out.printf("%d: running instance%n", System
.currentTimeMillis());
Reservation reservation = client.getInstanceServices()
.runInstancesInRegion(null, null, // allow
System.out.printf("%d: running instance%n", System.currentTimeMillis());
Reservation<? extends RunningInstance> reservation = client.getInstanceServices().runInstancesInRegion(null, null, // allow
// ec2
// to
// chose
@ -203,51 +187,36 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
verifyInstanceProperties(script);
tryToChangeStuff();
sshPing(instance);
System.out.printf("%d: %s ssh connection made%n", System
.currentTimeMillis(), instanceId);
System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instanceId);
}
private void verifyInstanceProperties(String script) {
assertEquals(script, client.getInstanceServices()
.getUserDataForInstanceInRegion(null, instanceId));
assertEquals(script, client.getInstanceServices().getUserDataForInstanceInRegion(null, instanceId));
assertEquals(null, client.getInstanceServices()
.getRootDeviceNameForInstanceInRegion(null, instanceId));
assertEquals(null, client.getInstanceServices().getRootDeviceNameForInstanceInRegion(null, instanceId));
assert client.getInstanceServices().getRamdiskForInstanceInRegion(null,
instanceId).startsWith("ari-");
assert client.getInstanceServices().getRamdiskForInstanceInRegion(null, instanceId).startsWith("ari-");
assertEquals(false, client.getInstanceServices()
.isApiTerminationDisabledForInstanceInRegion(null, instanceId));
assertEquals(false, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(null, instanceId));
assert client.getInstanceServices().getKernelForInstanceInRegion(null,
instanceId).startsWith("aki-");
assert client.getInstanceServices().getKernelForInstanceInRegion(null, instanceId).startsWith("aki-");
assertEquals(InstanceType.M1_SMALL, client.getInstanceServices()
.getInstanceTypeForInstanceInRegion(null, instanceId));
assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client
.getInstanceServices()
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
assertEquals(InstanceType.M1_SMALL, client.getInstanceServices().getInstanceTypeForInstanceInRegion(null,
instanceId));
assertEquals(ImmutableMap.<String, EbsBlockDevice> of(), client
.getInstanceServices().getBlockDeviceMappingForInstanceInRegion(
null, instanceId));
assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client.getInstanceServices()
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, instanceId));
assertEquals(ImmutableMap.<String, EbsBlockDevice> of(), client.getInstanceServices()
.getBlockDeviceMappingForInstanceInRegion(null, instanceId));
}
private void setApiTerminationDisabledForInstanceInRegion() {
client.getInstanceServices()
.setApiTerminationDisabledForInstanceInRegion(null, instanceId,
true);
assertEquals(true, client.getInstanceServices()
.isApiTerminationDisabledForInstanceInRegion(null, instanceId));
client.getInstanceServices()
.setApiTerminationDisabledForInstanceInRegion(null, instanceId,
false);
assertEquals(false, client.getInstanceServices()
.isApiTerminationDisabledForInstanceInRegion(null, instanceId));
client.getInstanceServices().setApiTerminationDisabledForInstanceInRegion(null, instanceId, true);
assertEquals(true, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(null, instanceId));
client.getInstanceServices().setApiTerminationDisabledForInstanceInRegion(null, instanceId, false);
assertEquals(false, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(null, instanceId));
}
private void tryToChangeStuff() {
@ -262,8 +231,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setUserDataForInstanceInRegion() {
try {
client.getInstanceServices().setUserDataForInstanceInRegion(null,
instanceId, "test".getBytes());
client.getInstanceServices().setUserDataForInstanceInRegion(null, instanceId, "test".getBytes());
assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode());
@ -272,10 +240,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setRamdiskForInstanceInRegion() {
try {
String ramdisk = client.getInstanceServices()
.getRamdiskForInstanceInRegion(null, instanceId);
client.getInstanceServices().setRamdiskForInstanceInRegion(null,
instanceId, ramdisk);
String ramdisk = client.getInstanceServices().getRamdiskForInstanceInRegion(null, instanceId);
client.getInstanceServices().setRamdiskForInstanceInRegion(null, instanceId, ramdisk);
assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode());
@ -284,10 +250,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setKernelForInstanceInRegion() {
try {
String oldKernel = client.getInstanceServices()
.getKernelForInstanceInRegion(null, instanceId);
client.getInstanceServices().setKernelForInstanceInRegion(null,
instanceId, oldKernel);
String oldKernel = client.getInstanceServices().getKernelForInstanceInRegion(null, instanceId);
client.getInstanceServices().setKernelForInstanceInRegion(null, instanceId, oldKernel);
assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode());
@ -296,8 +260,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setInstanceTypeForInstanceInRegion() {
try {
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null,
instanceId, InstanceType.C1_MEDIUM);
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null, instanceId, InstanceType.C1_MEDIUM);
assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode());
@ -307,8 +270,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setBlockDeviceMappingForInstanceInRegion() {
BlockDeviceMapping blockDeviceMapping = new BlockDeviceMapping();
try {
client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(
null, instanceId, blockDeviceMapping);
client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(null, instanceId, blockDeviceMapping);
assert false : "shouldn't be allowed, as instance needs to be ebs based-ami";
} catch (AWSResponseException e) {
assertEquals("InvalidParameterCombination", e.getError().getCode());
@ -317,9 +279,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private void setInstanceInitiatedShutdownBehaviorForInstanceInRegion() {
try {
client.getInstanceServices()
.setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
instanceId, InstanceInitiatedShutdownBehavior.STOP);
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, instanceId,
InstanceInitiatedShutdownBehavior.STOP);
assert false : "shouldn't be allowed, as instance needs to be ebs based-ami";
} catch (AWSResponseException e) {
assertEquals("UnsupportedInstanceAttribute", e.getError().getCode());
@ -327,22 +288,19 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
}
@Test(enabled = false, dependsOnMethods = "testCreateRunningInstance")
void testReboot() throws InterruptedException, ExecutionException,
TimeoutException, IOException {
void testReboot() throws InterruptedException, ExecutionException, TimeoutException, IOException {
RunningInstance instance = getInstance(instanceId);
System.out.printf("%d: %s rebooting instance %n", System
.currentTimeMillis(), instanceId);
System.out.printf("%d: %s rebooting instance %n", System.currentTimeMillis(), instanceId);
client.getInstanceServices().rebootInstancesInRegion(null, instanceId);
Thread.sleep(1000);
instance = getInstance(instanceId);
blockUntilWeCanSshIntoInstance(instance);
SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(),
22), "root", keyPair.getKeyMaterial().getBytes());
SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(), 22), "root", keyPair.getKeyMaterial()
.getBytes());
try {
ssh.connect();
ExecResponse uptime = ssh.exec("uptime");
assert uptime.getOutput().indexOf("0 min") != -1 : "reboot didn't work: "
+ uptime;
assert uptime.getOutput().indexOf("0 min") != -1 : "reboot didn't work: " + uptime;
} finally {
if (ssh != null)
ssh.disconnect();
@ -350,85 +308,69 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
}
@Test(enabled = false, dependsOnMethods = "testReboot")
void testElasticIpAddress() throws InterruptedException, ExecutionException,
TimeoutException, IOException {
address = client.getElasticIPAddressServices().allocateAddressInRegion(
null);
void testElasticIpAddress() throws InterruptedException, ExecutionException, TimeoutException, IOException {
address = client.getElasticIPAddressServices().allocateAddressInRegion(null);
assertNotNull(address);
PublicIpInstanceIdPair compare = Iterables.getLast(client
.getElasticIPAddressServices().describeAddressesInRegion(null,
address));
PublicIpInstanceIdPair compare = Iterables.getLast(client.getElasticIPAddressServices()
.describeAddressesInRegion(null, address));
assertEquals(compare.getPublicIp(), address);
assert compare.getInstanceId() == null;
client.getElasticIPAddressServices().associateAddressInRegion(null,
address, instanceId);
client.getElasticIPAddressServices().associateAddressInRegion(null, address, instanceId);
compare = Iterables.getLast(client.getElasticIPAddressServices()
.describeAddressesInRegion(null, address));
compare = Iterables.getLast(client.getElasticIPAddressServices().describeAddressesInRegion(null, address));
assertEquals(compare.getPublicIp(), address);
assertEquals(compare.getInstanceId(), instanceId);
Reservation reservation = Iterables.getOnlyElement(client
.getInstanceServices().describeInstancesInRegion(null, instanceId));
Reservation<? extends RunningInstance> reservation = Iterables.getOnlyElement(client.getInstanceServices()
.describeInstancesInRegion(null, instanceId));
assertNotNull(Iterables.getOnlyElement(reservation).getIpAddress());
assertFalse(Iterables.getOnlyElement(reservation).getIpAddress().equals(
address));
assertFalse(Iterables.getOnlyElement(reservation).getIpAddress().equals(address));
doCheckKey(address);
client.getElasticIPAddressServices().disassociateAddressInRegion(null,
address);
client.getElasticIPAddressServices().disassociateAddressInRegion(null, address);
compare = Iterables.getLast(client.getElasticIPAddressServices()
.describeAddressesInRegion(null, address));
compare = Iterables.getLast(client.getElasticIPAddressServices().describeAddressesInRegion(null, address));
assertEquals(compare.getPublicIp(), address);
assert compare.getInstanceId() == null;
reservation = Iterables.getOnlyElement(client.getInstanceServices()
.describeInstancesInRegion(null, instanceId));
reservation = Iterables.getOnlyElement(client.getInstanceServices().describeInstancesInRegion(null, instanceId));
// assert reservation.getRunningInstances().last().getIpAddress() == null;
// TODO
}
private RunningInstance blockUntilWeCanSshIntoInstance(
RunningInstance instance) throws UnknownHostException {
System.out.printf("%d: %s awaiting instance to run %n", System
.currentTimeMillis(), instance.getId());
private RunningInstance blockUntilWeCanSshIntoInstance(RunningInstance instance) throws UnknownHostException {
System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance.getId());
assert runningTester.apply(instance);
instance = getInstance(instance.getId());
System.out.printf("%d: %s awaiting instance to have ip assigned %n",
System.currentTimeMillis(), instance.getId());
System.out
.printf("%d: %s awaiting instance to have ip assigned %n", System.currentTimeMillis(), instance.getId());
assert hasIpTester.apply(instance);
System.out.printf("%d: %s awaiting ssh service to start%n", System
.currentTimeMillis(), instance.getIpAddress());
System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(), instance.getIpAddress());
assert socketTester.apply(new IPSocket(instance.getIpAddress(), 22));
System.out.printf("%d: %s ssh service started%n", System
.currentTimeMillis(), instance.getDnsName());
System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance.getDnsName());
sshPing(instance);
System.out.printf("%d: %s ssh connection made%n", System
.currentTimeMillis(), instance.getId());
System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instance.getId());
System.out.printf("%d: %s awaiting http service to start%n", System
.currentTimeMillis(), instance.getIpAddress());
System.out.printf("%d: %s awaiting http service to start%n", System.currentTimeMillis(), instance.getIpAddress());
assert socketTester.apply(new IPSocket(instance.getIpAddress(), 80));
System.out.printf("%d: %s http service started%n", System
.currentTimeMillis(), instance.getDnsName());
System.out.printf("%d: %s http service started%n", System.currentTimeMillis(), instance.getDnsName());
return instance;
}
private RunningInstance getInstance(String instanceId) {
// search my identity for the instance I just created
Set<Reservation> reservations = client.getInstanceServices()
Set<? extends Reservation<? extends RunningInstance>> reservations = client.getInstanceServices()
.describeInstancesInRegion(null, instanceId); // last parameter
// (ids) narrows the
// search
@ -437,8 +379,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
}
/**
* this tests "personality" as the file looked up was sent during instance
* creation
* this tests "personality" as the file looked up was sent during instance creation
*
* @throws UnknownHostException
*/
@ -454,14 +395,12 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
}
}
private void doCheckKey(RunningInstance newDetails)
throws UnknownHostException {
private void doCheckKey(RunningInstance newDetails) throws UnknownHostException {
doCheckKey(newDetails.getIpAddress());
}
private void doCheckKey(String address) {
SshClient ssh = sshFactory.create(new IPSocket(address, 22), "root",
keyPair.getKeyMaterial().getBytes());
SshClient ssh = sshFactory.create(new IPSocket(address, 22), "root", keyPair.getKeyMaterial().getBytes());
try {
ssh.connect();
ExecResponse hello = ssh.exec("echo hello");
@ -473,20 +412,15 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
}
@AfterTest
void cleanup() throws InterruptedException, ExecutionException,
TimeoutException {
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
if (address != null)
client.getElasticIPAddressServices().releaseAddressInRegion(null,
address);
client.getElasticIPAddressServices().releaseAddressInRegion(null, address);
if (instanceId != null)
client.getInstanceServices().terminateInstancesInRegion(null,
instanceId);
client.getInstanceServices().terminateInstancesInRegion(null, instanceId);
if (keyPair != null)
client.getKeyPairServices().deleteKeyPairInRegion(null,
keyPair.getKeyName());
client.getKeyPairServices().deleteKeyPairInRegion(null, keyPair.getKeyName());
if (securityGroupName != null)
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null,
securityGroupName);
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName);
}
}

View File

@ -81,8 +81,8 @@ import com.google.inject.Module;
import com.google.inject.internal.ImmutableMap;
/**
* Adapted from the following sources: {@link http://gist.github.com/249915},
* {@link http ://www.capsunlock.net/2009/12/create-ebs-boot-ami.html}
* Adapted from the following sources: {@link http://gist.github.com/249915}, {@link http
* ://www.capsunlock.net/2009/12/create-ebs-boot-ami.html}
* <p/>
*
* Generally disabled, as it incurs higher fees.
@ -194,7 +194,8 @@ public class EBSBootEC2ClientLiveTest {
while (instance == null) {
try {
System.out.printf("%d: running instance%n", System.currentTimeMillis());
Reservation reservation = client.getInstanceServices().runInstancesInRegion(null, null, // allow
Reservation<? extends RunningInstance> reservation = client.getInstanceServices().runInstancesInRegion(
null, null, // allow
// ec2
// to
// chose
@ -489,8 +490,7 @@ public class EBSBootEC2ClientLiveTest {
}
/**
* this tests "personality" as the file looked up was sent during instance
* creation
* this tests "personality" as the file looked up was sent during instance creation
*
* @throws UnknownHostException
*/
@ -527,8 +527,8 @@ public class EBSBootEC2ClientLiveTest {
assert runningTester.apply(instance);
// search my identity for the instance I just created
Set<Reservation> reservations = client.getInstanceServices().describeInstancesInRegion(instance.getRegion(),
instance.getId()); // last
Set<? extends Reservation<? extends RunningInstance>> reservations = client.getInstanceServices()
.describeInstancesInRegion(instance.getRegion(), instance.getId()); // last
// parameter
// (ids)
// narrows

View File

@ -43,6 +43,7 @@ import com.google.common.collect.ImmutableSet;
@Test(groups = "unit", testName = "ec2.RegionAndIdToImageTest")
public class RegionAndIdToImageTest {
@SuppressWarnings("unchecked")
@Test
public void testApply() {
@ -51,11 +52,11 @@ public class RegionAndIdToImageTest {
AMIClient client = createMock(AMIClient.class);
org.jclouds.aws.ec2.domain.Image ec2Image = createMock(org.jclouds.aws.ec2.domain.Image.class);
Image image = createNiceMock(Image.class);
Set<org.jclouds.aws.ec2.domain.Image> images = ImmutableSet
Set<? extends org.jclouds.aws.ec2.domain.Image> images = ImmutableSet
.<org.jclouds.aws.ec2.domain.Image> of(ec2Image);
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn(images);
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set)images);
expect(parser.apply(ec2Image)).andReturn(image);
replay(caller);
@ -74,6 +75,7 @@ public class RegionAndIdToImageTest {
}
@SuppressWarnings("unchecked")
@Test
public void testApplyNotFound() {
@ -82,11 +84,11 @@ public class RegionAndIdToImageTest {
AMIClient client = createMock(AMIClient.class);
org.jclouds.aws.ec2.domain.Image ec2Image = createMock(org.jclouds.aws.ec2.domain.Image.class);
Image image = createNiceMock(Image.class);
Set<org.jclouds.aws.ec2.domain.Image> images = ImmutableSet
Set<? extends org.jclouds.aws.ec2.domain.Image> images = ImmutableSet
.<org.jclouds.aws.ec2.domain.Image> of(ec2Image);
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn(images);
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set)images);
expect(parser.apply(ec2Image)).andThrow(new ResourceNotFoundException());
replay(caller);

View File

@ -58,8 +58,7 @@ import com.google.common.collect.ImmutableSet;
*/
@Test(groups = "unit", testName = "ec2.RunningInstanceToNodeMetadataTest")
public class RunningInstanceToNodeMetadataTest {
private static class ImageProvider implements
Provider<Set<? extends org.jclouds.compute.domain.Image>> {
private static class ImageProvider implements Provider<Set<? extends org.jclouds.compute.domain.Image>> {
private final Set<? extends org.jclouds.compute.domain.Image> images;
private ImageProvider(org.jclouds.compute.domain.Image jcImage) {
@ -117,8 +116,8 @@ public class RunningInstanceToNodeMetadataTest {
replay(credentialProvider);
replay(instance);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client,
credentialsMap, credentialProvider, new ImageProvider(jcImage), imageMap, locations,
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, new ImageProvider(jcImage), imageMap, locations,
new RunningInstanceToStorageMappingUnix());
NodeMetadata metadata = parser.apply(instance);
@ -168,8 +167,8 @@ public class RunningInstanceToNodeMetadataTest {
expect(jcImage.getProviderId()).andReturn("notImageId").atLeastOnce();
expect(instance.getRegion()).andReturn("us-east-1").atLeastOnce();
expect(imageMap.get(new RegionAndName("us-east-1", "imageId"))).andThrow(
new NullPointerException()).atLeastOnce();
expect(imageMap.get(new RegionAndName("us-east-1", "imageId"))).andThrow(new NullPointerException())
.atLeastOnce();
expect(instance.getInstanceType()).andReturn(InstanceType.C1_XLARGE).atLeastOnce();
@ -181,8 +180,8 @@ public class RunningInstanceToNodeMetadataTest {
replay(credentialProvider);
replay(instance);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client,
credentialsMap, credentialProvider, new ImageProvider(jcImage), imageMap, locations,
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, new ImageProvider(jcImage), imageMap, locations,
new RunningInstanceToStorageMappingUnix());
NodeMetadata metadata = parser.apply(instance);
@ -234,8 +233,7 @@ public class RunningInstanceToNodeMetadataTest {
org.jclouds.compute.domain.Image lateImage = createMock(org.jclouds.compute.domain.Image.class);
expect(imageMap.get(new RegionAndName("us-east-1", "imageId"))).andReturn(lateImage)
.atLeastOnce();
expect(imageMap.get(new RegionAndName("us-east-1", "imageId"))).andReturn(lateImage).atLeastOnce();
expect(instance.getInstanceType()).andReturn(InstanceType.C1_XLARGE).atLeastOnce();
@ -248,8 +246,8 @@ public class RunningInstanceToNodeMetadataTest {
replay(credentialProvider);
replay(instance);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client,
credentialsMap, credentialProvider, new ImageProvider(jcImage), imageMap, locations,
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, new ImageProvider(jcImage), imageMap, locations,
new RunningInstanceToStorageMappingUnix());
NodeMetadata metadata = parser.apply(instance);
@ -270,8 +268,7 @@ public class RunningInstanceToNodeMetadataTest {
@SuppressWarnings("unchecked")
@Test
public void testApplyWithNoSecurityGroupCreatesTagOfIdPrefixedByTagAndNullCredentials()
throws UnknownHostException {
public void testApplyWithNoSecurityGroupCreatesTagOfIdPrefixedByTagAndNullCredentials() throws UnknownHostException {
EC2Client client = createMock(EC2Client.class);
AMIClient amiClient = createMock(AMIClient.class);
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
@ -312,8 +309,8 @@ public class RunningInstanceToNodeMetadataTest {
replay(credentialProvider);
replay(instance);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client,
credentialsMap, credentialProvider, new ImageProvider(jcImage), imageMap, locations,
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, new ImageProvider(jcImage), imageMap, locations,
new RunningInstanceToStorageMappingUnix());
NodeMetadata metadata = parser.apply(instance);
@ -333,8 +330,7 @@ public class RunningInstanceToNodeMetadataTest {
@SuppressWarnings("unchecked")
@Test
public void testApplyWithNoKeyPairCreatesTagOfParsedSecurityGroupAndNullCredentials()
throws UnknownHostException {
public void testApplyWithNoKeyPairCreatesTagOfParsedSecurityGroupAndNullCredentials() throws UnknownHostException {
EC2Client client = createMock(EC2Client.class);
AMIClient amiClient = createMock(AMIClient.class);
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
@ -374,8 +370,8 @@ public class RunningInstanceToNodeMetadataTest {
replay(credentialProvider);
replay(instance);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client,
credentialsMap, credentialProvider, new ImageProvider(jcImage), imageMap, locations,
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, new ImageProvider(jcImage), imageMap, locations,
new RunningInstanceToStorageMappingUnix());
NodeMetadata metadata = parser.apply(instance);
@ -395,8 +391,7 @@ public class RunningInstanceToNodeMetadataTest {
@SuppressWarnings("unchecked")
@Test
public void testApplyWithKeyPairCreatesTagOfParsedSecurityGroupAndCredentialsBasedOnIt()
throws UnknownHostException {
public void testApplyWithKeyPairCreatesTagOfParsedSecurityGroupAndCredentialsBasedOnIt() throws UnknownHostException {
EC2Client client = createMock(EC2Client.class);
AMIClient amiClient = createMock(AMIClient.class);
expect(client.getAMIServices()).andReturn(amiClient).atLeastOnce();
@ -429,7 +424,7 @@ public class RunningInstanceToNodeMetadataTest {
expect(jcImage.getLocation()).andReturn(location).atLeastOnce();
expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("imageId"))).andReturn(
ImmutableSet.<Image> of(image));
(Set) ImmutableSet.<Image> of(image));
expect(credentialProvider.execute(image)).andReturn(new Credentials("user", "pass"));
@ -448,8 +443,8 @@ public class RunningInstanceToNodeMetadataTest {
replay(instance);
replay(jcImage);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client,
credentialsMap, credentialProvider, new ImageProvider(jcImage), imageMap, locations,
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, new ImageProvider(jcImage), imageMap, locations,
new RunningInstanceToStorageMappingUnix());
NodeMetadata metadata = parser.apply(instance);
@ -483,8 +478,7 @@ public class RunningInstanceToNodeMetadataTest {
Image image = createMock(Image.class);
expect(instance.getId()).andReturn("id").atLeastOnce();
expect(instance.getGroupIds()).andReturn(ImmutableSet.of("jclouds1", "jclouds2"))
.atLeastOnce();
expect(instance.getGroupIds()).andReturn(ImmutableSet.of("jclouds1", "jclouds2")).atLeastOnce();
expect(instance.getKeyName()).andReturn("jclouds#tag#us-east-1#50").atLeastOnce();
expect(instance.getInstanceState()).andReturn(InstanceState.RUNNING);
expect(instance.getVirtualizationType()).andReturn("paravirtual");
@ -505,7 +499,7 @@ public class RunningInstanceToNodeMetadataTest {
expect(jcImage.getLocation()).andReturn(location).atLeastOnce();
expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("imageId"))).andReturn(
ImmutableSet.<Image> of(image));
(Set) ImmutableSet.<Image> of(image));
expect(credentialProvider.execute(image)).andReturn(new Credentials("user", "pass"));
@ -524,8 +518,8 @@ public class RunningInstanceToNodeMetadataTest {
replay(instance);
replay(jcImage);
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client,
credentialsMap, credentialProvider, new ImageProvider(jcImage), imageMap, locations,
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
credentialProvider, new ImageProvider(jcImage), imageMap, locations,
new RunningInstanceToStorageMappingUnix());
NodeMetadata metadata = parser.apply(instance);

View File

@ -60,20 +60,17 @@ public class EC2RunNodesAndAddToSetStrategyTest {
@Test
public void testZoneAsALocation() {
assertRegionAndZoneForLocation(ZONE_AP_SOUTHEAST_1A,
Region.AP_SOUTHEAST_1, AvailabilityZone.AP_SOUTHEAST_1A);
assertRegionAndZoneForLocation(ZONE_AP_SOUTHEAST_1A, Region.AP_SOUTHEAST_1, AvailabilityZone.AP_SOUTHEAST_1A);
}
@Test
public void testRegionAsALocation() {
assertRegionAndZoneForLocation(REGION_AP_SOUTHEAST_1,
Region.AP_SOUTHEAST_1, null);
assertRegionAndZoneForLocation(REGION_AP_SOUTHEAST_1, Region.AP_SOUTHEAST_1, null);
}
// // fixtures
public static Iterable<NodeMetadata> containsNodeMetadata(
final NodeMetadata in) {
public static Iterable<NodeMetadata> containsNodeMetadata(final NodeMetadata in) {
reportMatcher(new IArgumentMatcher() {
@Override
@ -92,8 +89,8 @@ public class EC2RunNodesAndAddToSetStrategyTest {
return null;
}
private void assertRegionAndZoneForLocation(Location location,
String region, String zone) {
@SuppressWarnings("unchecked")
private void assertRegionAndZoneForLocation(Location location, String region, String zone) {
String imageId = "ami1";
String instanceCreatedId = "instance1";
// setup mocks
@ -102,37 +99,28 @@ public class EC2RunNodesAndAddToSetStrategyTest {
InstanceClient instanceClient = createMock(InstanceClient.class);
RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class);
RunningInstance instance = createMock(RunningInstance.class);
Reservation reservation = new Reservation(region, ImmutableSet
.<String> of(), ImmutableSet.<RunningInstance> of(instance),
"ownerId", "requesterId", "reservationId");
Reservation<? extends RunningInstance> reservation = new Reservation<RunningInstance>(region, ImmutableSet
.<String> of(), ImmutableSet.<RunningInstance> of(instance), "ownerId", "requesterId", "reservationId");
NodeMetadata nodeMetadata = createMock(NodeMetadata.class);
// setup expectations
expect(strategy.client.getInstanceServices()).andReturn(instanceClient)
.atLeastOnce();
expect(strategy.client.getInstanceServices()).andReturn(instanceClient).atLeastOnce();
expect(
strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions
.execute(region, input.tag, input.template)).andReturn(
ec2Options);
expect(input.template.getLocation()).andReturn(input.location)
.atLeastOnce();
strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.execute(region, input.tag,
input.template)).andReturn(ec2Options);
expect(input.template.getLocation()).andReturn(input.location).atLeastOnce();
expect(input.template.getImage()).andReturn(input.image).atLeastOnce();
expect(input.image.getProviderId()).andReturn(imageId).atLeastOnce();
expect(
instanceClient.runInstancesInRegion(region, zone, imageId, 1,
input.count, ec2Options)).andReturn(reservation);
expect(instanceClient.runInstancesInRegion(region, zone, imageId, 1, input.count, ec2Options)).andReturn(
(Reservation)reservation);
expect(instance.getId()).andReturn(instanceCreatedId).atLeastOnce();
expect(strategy.instancePresent.apply(instance)).andReturn(true);
expect(input.template.getOptions()).andReturn(input.options)
.atLeastOnce();
expect(input.template.getOptions()).andReturn(input.options).atLeastOnce();
expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(
nodeMetadata);
expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(nodeMetadata);
expect(
strategy.utils
.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(
eq(input.options), containsNodeMetadata(nodeMetadata),
eq(input.nodes), eq(input.badNodes))).andReturn(null);
strategy.utils.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(eq(input.options),
containsNodeMetadata(nodeMetadata), eq(input.nodes), eq(input.badNodes))).andReturn(null);
// replay mocks
replay(instanceClient);
@ -143,8 +131,7 @@ public class EC2RunNodesAndAddToSetStrategyTest {
replayStrategy(strategy);
// run
strategy.execute(input.tag, input.count, input.template, input.nodes,
input.badNodes);
strategy.execute(input.tag, input.count, input.template, input.nodes, input.badNodes);
// verify mocks
verify(instanceClient);
@ -155,12 +142,10 @@ public class EC2RunNodesAndAddToSetStrategyTest {
verifyStrategy(strategy);
}
private static final Location REGION_AP_SOUTHEAST_1 = new LocationImpl(
LocationScope.REGION, Region.AP_SOUTHEAST_1, Region.AP_SOUTHEAST_1,
new LocationImpl(LocationScope.PROVIDER, "ec2", "ec2", null));
private static final Location ZONE_AP_SOUTHEAST_1A = new LocationImpl(
LocationScope.ZONE, AvailabilityZone.AP_SOUTHEAST_1A,
AvailabilityZone.AP_SOUTHEAST_1A, REGION_AP_SOUTHEAST_1);
private static final Location REGION_AP_SOUTHEAST_1 = new LocationImpl(LocationScope.REGION, Region.AP_SOUTHEAST_1,
Region.AP_SOUTHEAST_1, new LocationImpl(LocationScope.PROVIDER, "ec2", "ec2", null));
private static final Location ZONE_AP_SOUTHEAST_1A = new LocationImpl(LocationScope.ZONE,
AvailabilityZone.AP_SOUTHEAST_1A, AvailabilityZone.AP_SOUTHEAST_1A, REGION_AP_SOUTHEAST_1);
// /////////////////////////////////////////////////////////////////////
@SuppressWarnings("unchecked")
@ -213,8 +198,7 @@ public class EC2RunNodesAndAddToSetStrategyTest {
Predicate<RunningInstance> instanceStateRunning = createMock(Predicate.class);
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = createMock(RunningInstanceToNodeMetadata.class);
ComputeUtils utils = createMock(ComputeUtils.class);
return new EC2RunNodesAndAddToSetStrategy(client,
createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
return new EC2RunNodesAndAddToSetStrategy(client, createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
instanceStateRunning, runningInstanceToNodeMetadata, utils);
}

View File

@ -28,6 +28,7 @@ import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.EC2AsyncClient;
import org.jclouds.aws.ec2.EC2Client;
import org.jclouds.aws.ec2.domain.Reservation;
import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.RestContextFactory;
@ -64,9 +65,9 @@ public class InstanceClientLiveTest {
@Test
void testDescribeInstances() {
for (String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1,
Region.US_WEST_1, Region.AP_SOUTHEAST_1)) {
Set<Reservation> allResults = client.describeInstancesInRegion(region);
for (String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1, Region.US_WEST_1,
Region.AP_SOUTHEAST_1)) {
Set<? extends Reservation<? extends RunningInstance>> allResults = client.describeInstancesInRegion(region);
assertNotNull(allResults);
assert allResults.size() >= 0 : allResults.size();
}

View File

@ -66,10 +66,10 @@ public class DescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest {
public void testWhenRunning() throws UnknownHostException {
InputStream is = getClass().getResourceAsStream("/ec2/describe_instances_running.xml");
Set<Reservation> contents = Sets.newLinkedHashSet();
Set<Reservation<? extends RunningInstance>> contents = Sets.newLinkedHashSet();
contents.add(new Reservation(defaultRegion, ImmutableSet.of("adriancole.ec2ingress"), ImmutableSet
.of(new RunningInstance(defaultRegion, ImmutableSet.of("adriancole.ec2ingress"), "0",
contents.add(new Reservation<RunningInstance>(defaultRegion, ImmutableSet.of("adriancole.ec2ingress"),
ImmutableSet.of(new RunningInstance(defaultRegion, ImmutableSet.of("adriancole.ec2ingress"), "0",
"ec2-174-129-81-68.compute-1.amazonaws.com", "ami-1fd73376", "i-0799056f",
InstanceState.RUNNING, InstanceType.M1_SMALL, "174.129.81.68", "aki-a71cf9ce",
"adriancole.ec21", dateService.iso8601DateParse("2009-11-09T03:00:34.000Z"), false,
@ -78,7 +78,7 @@ public class DescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest {
RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of())),
"993194456877", null, "r-a3c508cb"));
Set<Reservation> result = getReservations(is);
Set<Reservation<? extends RunningInstance>> result = getReservations(is);
assertEquals(result, contents);
}
@ -86,23 +86,25 @@ public class DescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest {
public void testApplyInputStream() {
InputStream is = getClass().getResourceAsStream("/ec2/describe_instances.xml");
Set<Reservation> contents = Sets.newLinkedHashSet();
Set<Reservation<? extends RunningInstance>> contents = Sets.newLinkedHashSet();
contents.add(new Reservation(defaultRegion, ImmutableSet.of("default"), ImmutableSet.of(new RunningInstance(
defaultRegion, ImmutableSet.of("default"), "23", "ec2-72-44-33-4.compute-1.amazonaws.com",
"ami-6ea54007", "i-28a64341", InstanceState.RUNNING, InstanceType.M1_LARGE, (String) null,
"aki-ba3adfd3", "example-key-name", dateService.iso8601DateParse("2007-08-07T11:54:42.000Z"), false,
AvailabilityZone.US_EAST_1B, null, "paravirtual", null, "10-251-50-132.ec2.internal", null, ImmutableSet
.of("774F4FF8"), "ari-badbad00", null, null, null, RootDeviceType.INSTANCE_STORE, null,
ImmutableMap.<String, EbsBlockDevice> of()), new RunningInstance(defaultRegion, ImmutableSet
contents.add(new Reservation<RunningInstance>(defaultRegion, ImmutableSet.of("default"), ImmutableSet.of(
new RunningInstance(defaultRegion, ImmutableSet.of("default"), "23",
"ec2-72-44-33-4.compute-1.amazonaws.com", "ami-6ea54007", "i-28a64341", InstanceState.RUNNING,
InstanceType.M1_LARGE, (String) null, "aki-ba3adfd3", "example-key-name", dateService
.iso8601DateParse("2007-08-07T11:54:42.000Z"), false, AvailabilityZone.US_EAST_1B,
null, "paravirtual", null, "10-251-50-132.ec2.internal", null, ImmutableSet.of("774F4FF8"),
"ari-badbad00", null, null, null, RootDeviceType.INSTANCE_STORE, null, ImmutableMap
.<String, EbsBlockDevice> of()), new RunningInstance(defaultRegion, ImmutableSet
.of("default"), "23", "ec2-72-44-33-6.compute-1.amazonaws.com", "ami-6ea54007", "i-28a64435",
InstanceState.RUNNING, InstanceType.M1_LARGE, (String) null, "aki-ba3adfd3", "example-key-name",
dateService.iso8601DateParse("2007-08-07T11:54:42.000Z"), false, AvailabilityZone.US_EAST_1B, null,
"paravirtual", null, "10-251-50-134.ec2.internal", null, ImmutableSet.of("774F4FF8"), "ari-badbad00",
null, null, null, RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of())),
"UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", null, "r-44a5402d"));
InstanceState.RUNNING, InstanceType.M1_LARGE, (String) null, "aki-ba3adfd3",
"example-key-name", dateService.iso8601DateParse("2007-08-07T11:54:42.000Z"), false,
AvailabilityZone.US_EAST_1B, null, "paravirtual", null, "10-251-50-134.ec2.internal", null,
ImmutableSet.of("774F4FF8"), "ari-badbad00", null, null, null, RootDeviceType.INSTANCE_STORE,
null, ImmutableMap.<String, EbsBlockDevice> of())), "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", null,
"r-44a5402d"));
Set<Reservation> result = getReservations(is);
Set<Reservation<? extends RunningInstance>> result = getReservations(is);
assertEquals(result, contents);
}
@ -112,17 +114,17 @@ public class DescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest {
public void testApplyInputStreamEuc() {
InputStream is = getClass().getResourceAsStream("/ec2/describe_instances_euc.xml");
Set<Reservation> contents = Sets.newLinkedHashSet();
Set<Reservation<? extends RunningInstance>> contents = Sets.newLinkedHashSet();
contents.add(new Reservation(defaultRegion, ImmutableSet.of("default"), ImmutableSet.of(new RunningInstance(
defaultRegion, ImmutableSet.of("jclouds#euc"), "1", null, "emi-9ACB1363", "i-3FFA0762",
InstanceState.SHUTTING_DOWN, InstanceType.M1_LARGE, null, "eki-6CBD12F2", "jclouds#euc-17", dateService
.iso8601DateParse("2010-06-16T03:06:19.000Z"), false, "open", null, "paravirtual", null,
"10.7.0.179", null, ImmutableSet.<String> of(), "eri-A97113E4", null, null, null,
RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of())), "jclouds", null,
"r-4D2A08AD"));
contents.add(new Reservation<RunningInstance>(defaultRegion, ImmutableSet.of("default"), ImmutableSet
.of(new RunningInstance(defaultRegion, ImmutableSet.of("jclouds#euc"), "1", null, "emi-9ACB1363",
"i-3FFA0762", InstanceState.SHUTTING_DOWN, InstanceType.M1_LARGE, null, "eki-6CBD12F2",
"jclouds#euc-17", dateService.iso8601DateParse("2010-06-16T03:06:19.000Z"), false, "open",
null, "paravirtual", null, "10.7.0.179", null, ImmutableSet.<String> of(), "eri-A97113E4",
null, null, null, RootDeviceType.INSTANCE_STORE, null, ImmutableMap
.<String, EbsBlockDevice> of())), "jclouds", null, "r-4D2A08AD"));
Set<Reservation> result = getReservations(is);
Set<Reservation<? extends RunningInstance>> result = getReservations(is);
assertEquals(result, contents);
}
@ -130,29 +132,30 @@ public class DescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest {
public void testEBS() throws UnknownHostException {
InputStream is = getClass().getResourceAsStream("/ec2/describe_instances_ebs.xml");
Set<Reservation> contents = Sets.newLinkedHashSet();
Set<Reservation<? extends RunningInstance>> contents = Sets.newLinkedHashSet();
contents.add(new Reservation(defaultRegion, ImmutableSet.of("adriancole.ec2ebsingress"), ImmutableSet
.of(new RunningInstance(defaultRegion, ImmutableSet.of("adriancole.ec2ebsingress"), "0",
contents.add(new Reservation<RunningInstance>(defaultRegion, ImmutableSet.of("adriancole.ec2ebsingress"),
ImmutableSet.of(new RunningInstance(defaultRegion, ImmutableSet.of("adriancole.ec2ebsingress"), "0",
"ec2-75-101-203-146.compute-1.amazonaws.com", "ami-849875ed", "i-e564438d",
InstanceState.RUNNING, InstanceType.M1_SMALL, "75.101.203.146", "aki-a71cf9ce",
"adriancole.ec2ebs1", dateService.iso8601DateParse("2009-12-30T04:06:23.000Z"), false,
AvailabilityZone.US_EAST_1B, "placement","hvm", null, "domU-12-31-39-09-CE-53.compute-1.internal",
"10.210.209.157", ImmutableSet.<String> of(), "ari-a51cf9cc", null, null, null,
RootDeviceType.EBS, "/dev/sda1", ImmutableMap.<String, EbsBlockDevice> of("/dev/sda1",
new EbsBlockDevice("vol-dc6ca8b5", Attachment.Status.ATTACHED, dateService
.iso8601DateParse("2009-12-30T04:06:29.000Z"), true)))), "993194456877",
null, "r-596dd731"));
AvailabilityZone.US_EAST_1B, "placement", "hvm", null,
"domU-12-31-39-09-CE-53.compute-1.internal", "10.210.209.157", ImmutableSet.<String> of(),
"ari-a51cf9cc", null, null, null, RootDeviceType.EBS, "/dev/sda1", ImmutableMap
.<String, EbsBlockDevice> of("/dev/sda1", new EbsBlockDevice("vol-dc6ca8b5",
Attachment.Status.ATTACHED, dateService
.iso8601DateParse("2009-12-30T04:06:29.000Z"), true)))),
"993194456877", null, "r-596dd731"));
Set<Reservation> result = getReservations(is);
Set<Reservation<? extends RunningInstance>> result = getReservations(is);
assertEquals(result, contents);
}
private Set<Reservation> getReservations(InputStream is) {
private Set<Reservation<? extends RunningInstance>> getReservations(InputStream is) {
DescribeInstancesResponseHandler handler = injector.getInstance(DescribeInstancesResponseHandler.class);
addDefaultRegionToHandler(handler);
Set<Reservation> result = factory.create(handler).parse(is);
Set<Reservation<? extends RunningInstance>> result = factory.create(handler).parse(is);
return result;
}

View File

@ -64,28 +64,29 @@ public class RunInstancesResponseHandlerTest extends BaseEC2HandlerTest {
InputStream is = getClass().getResourceAsStream("/ec2/run_instances.xml");
Reservation expected = new Reservation(defaultRegion, ImmutableSet.of("default"), ImmutableSet.of(
new RunningInstance(defaultRegion, ImmutableSet.of("default"), "0", null, "ami-60a54009", "i-2ba64342",
InstanceState.PENDING, InstanceType.M1_SMALL, (String) null, null, "example-key-name",
dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"), true, AvailabilityZone.US_EAST_1B,
null, "paravirtual", null, (String) null, null, Sets.<String> newLinkedHashSet(), null, null,
null, null, RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of()),
new RunningInstance(defaultRegion, ImmutableSet.of("default"), "1", null, "ami-60a54009", "i-2bc64242",
InstanceState.PENDING, InstanceType.M1_SMALL, (String) null, null, "example-key-name",
dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"), true, AvailabilityZone.US_EAST_1B,
null, "paravirtual", null, (String) null, null, Sets.<String> newLinkedHashSet(), null, null,
null, null, RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of()),
new RunningInstance(defaultRegion, ImmutableSet.of("default"), "2", null, "ami-60a54009", "i-2be64332",
InstanceState.PENDING, InstanceType.M1_SMALL, (String) null, null, "example-key-name",
dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"), true, AvailabilityZone.US_EAST_1B,
null, "paravirtual", null, (String) null, null, Sets.<String> newLinkedHashSet(), null, null,
null, null, RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of())
Reservation<? extends RunningInstance> expected = new Reservation<RunningInstance>(defaultRegion, ImmutableSet
.of("default"), ImmutableSet.of(new RunningInstance(defaultRegion, ImmutableSet.of("default"), "0",
null, "ami-60a54009", "i-2ba64342", InstanceState.PENDING, InstanceType.M1_SMALL, (String) null, null,
"example-key-name", dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"), true,
AvailabilityZone.US_EAST_1B, null, "paravirtual", null, (String) null, null, Sets
.<String> newLinkedHashSet(), null, null, null, null, RootDeviceType.INSTANCE_STORE, null,
ImmutableMap.<String, EbsBlockDevice> of()), new RunningInstance(defaultRegion, ImmutableSet
.of("default"), "1", null, "ami-60a54009", "i-2bc64242", InstanceState.PENDING, InstanceType.M1_SMALL,
(String) null, null, "example-key-name", dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"), true,
AvailabilityZone.US_EAST_1B, null, "paravirtual", null, (String) null, null, Sets
.<String> newLinkedHashSet(), null, null, null, null, RootDeviceType.INSTANCE_STORE, null,
ImmutableMap.<String, EbsBlockDevice> of()), new RunningInstance(defaultRegion, ImmutableSet
.of("default"), "2", null, "ami-60a54009", "i-2be64332", InstanceState.PENDING, InstanceType.M1_SMALL,
(String) null, null, "example-key-name", dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"), true,
AvailabilityZone.US_EAST_1B, null, "paravirtual", null, (String) null, null, Sets
.<String> newLinkedHashSet(), null, null, null, null, RootDeviceType.INSTANCE_STORE, null,
ImmutableMap.<String, EbsBlockDevice> of())
), "AIDADH4IGTRXXKCD", null, "r-47a5402e");
RunInstancesResponseHandler handler = injector.getInstance(RunInstancesResponseHandler.class);
addDefaultRegionToHandler(handler);
Reservation result = factory.create(handler).parse(is);
Reservation<? extends RunningInstance> result = factory.create(handler).parse(is);
assertEquals(result, expected);
}

View File

@ -19,9 +19,9 @@
package org.jclouds.aws.s3.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.compose;
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.concurrent.ConcurrentUtils.compose;
import java.util.Date;
import java.util.Map;
@ -67,7 +67,6 @@ import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.concurrent.ConcurrentUtils;
import org.jclouds.date.DateService;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope;
@ -97,20 +96,19 @@ public class StubS3AsyncClient implements S3AsyncClient {
private final BlobToObjectMetadata blob2ObjectMetadata;
private final BucketToContainerListOptions bucket2ContainerListOptions;
private final ResourceToBucketList resource2BucketList;
private final ExecutorService executorService;
private final ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs;
private final ConcurrentMap<String, Location> containerToLocation;
private final ExecutorService service;
@Inject
private StubS3AsyncClient(TransientAsyncBlobStore blobStore,
ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
private StubS3AsyncClient(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
TransientAsyncBlobStore 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,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executorService) {
HttpGetOptionsListToGetOptions httpGetOptionsConverter, ObjectToBlob object2Blob, BlobToObject blob2Object,
BlobToObjectMetadata blob2ObjectMetadata, BucketToContainerListOptions bucket2ContainerListOptions,
ResourceToBucketList resource2BucketList) {
this.service = service;
this.containerToBlobs = containerToBlobs;
this.containerToLocation = containerToLocation;
this.blobStore = blobStore;
@ -121,10 +119,8 @@ public class StubS3AsyncClient implements S3AsyncClient {
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
this.blob2ObjectMetadata = checkNotNull(blob2ObjectMetadata, "blob2ObjectMetadata");
this.bucket2ContainerListOptions = checkNotNull(bucket2ContainerListOptions,
"bucket2ContainerListOptions");
this.bucket2ContainerListOptions = checkNotNull(bucket2ContainerListOptions, "bucket2ContainerListOptions");
this.resource2BucketList = checkNotNull(resource2BucketList, "resource2BucketList");
this.executorService = checkNotNull(executorService, "executorService");
}
public static final String TEST_ACL_ID = "1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c";
@ -141,24 +137,19 @@ public class StubS3AsyncClient implements S3AsyncClient {
public ListenableFuture<Boolean> putBucketInRegion(@Nullable String region, String name,
PutBucketOptions... optionsList) {
region = region == null ? Region.US_STANDARD : region;
final PutBucketOptions options = (optionsList.length == 0) ? new PutBucketOptions()
: optionsList[0];
final PutBucketOptions options = (optionsList.length == 0) ? new PutBucketOptions() : optionsList[0];
keyToAcl.put(name, options.getAcl());
return blobStore.createContainerInLocation(new LocationImpl(LocationScope.REGION, region,
region, null), name);
return blobStore.createContainerInLocation(new LocationImpl(LocationScope.REGION, region, region, null), name);
}
public ListenableFuture<ListBucketResponse> listBucket(final String name,
ListBucketOptions... optionsList) {
public ListenableFuture<ListBucketResponse> listBucket(final String name, ListBucketOptions... optionsList) {
ListContainerOptions options = bucket2ContainerListOptions.apply(optionsList);
return compose(blobStore.list(name, options), resource2BucketList);
return compose(blobStore.list(name, options), resource2BucketList, service);
}
public ListenableFuture<ObjectMetadata> copyObject(final String sourceBucket,
final String sourceObject, final String destinationBucket,
final String destinationObject, CopyObjectOptions... nullableOptions) {
final CopyObjectOptions options = (nullableOptions.length == 0) ? new CopyObjectOptions()
: nullableOptions[0];
public ListenableFuture<ObjectMetadata> copyObject(final String sourceBucket, final String sourceObject,
final String destinationBucket, final String destinationObject, CopyObjectOptions... nullableOptions) {
final CopyObjectOptions options = (nullableOptions.length == 0) ? new CopyObjectOptions() : nullableOptions[0];
ConcurrentMap<String, Blob> source = containerToBlobs.get(sourceBucket);
ConcurrentMap<String, Blob> dest = containerToBlobs.get(destinationBucket);
if (source.containsKey(sourceObject)) {
@ -183,8 +174,7 @@ public class StubS3AsyncClient implements S3AsyncClient {
return immediateFailedFuture(TransientAsyncBlobStore.returnResponseException(412));
}
Blob sourceS3 = source.get(sourceObject);
MutableBlobMetadata newMd = TransientAsyncBlobStore.copy(sourceS3.getMetadata(),
destinationObject);
MutableBlobMetadata newMd = TransientAsyncBlobStore.copy(sourceS3.getMetadata(), destinationObject);
if (options.getAcl() != null)
keyToAcl.put(destinationBucket + "/" + destinationObject, options.getAcl());
@ -192,17 +182,15 @@ public class StubS3AsyncClient implements S3AsyncClient {
Blob newBlob = blobProvider.create(newMd);
newBlob.setPayload(sourceS3.getPayload());
dest.put(destinationObject, newBlob);
return immediateFuture((ObjectMetadata) blob2ObjectMetadata.apply(TransientAsyncBlobStore
.copy(newMd)));
return immediateFuture((ObjectMetadata) blob2ObjectMetadata.apply(TransientAsyncBlobStore.copy(newMd)));
}
return immediateFailedFuture(new KeyNotFoundException(sourceBucket, sourceObject,
sourceBucket + "/" + sourceObject));
return immediateFailedFuture(new KeyNotFoundException(sourceBucket, sourceObject, sourceBucket + "/"
+ sourceObject));
}
public ListenableFuture<String> putObject(final String bucketName, final S3Object object,
PutObjectOptions... nullableOptions) {
final PutObjectOptions options = (nullableOptions.length == 0) ? new PutObjectOptions()
: nullableOptions[0];
final PutObjectOptions options = (nullableOptions.length == 0) ? new PutObjectOptions() : nullableOptions[0];
if (options.getAcl() != null)
keyToAcl.put(bucketName + "/" + object.getMetadata().getKey(), options.getAcl());
return blobStore.putBlob(bucketName, object2Blob.apply(object));
@ -214,12 +202,10 @@ public class StubS3AsyncClient implements S3AsyncClient {
if (aclObj instanceof AccessControlList) {
acl = (AccessControlList) aclObj;
} else if (aclObj instanceof CannedAccessPolicy) {
acl = AccessControlList.fromCannedAccessPolicy((CannedAccessPolicy) aclObj,
DEFAULT_OWNER_ID);
acl = AccessControlList.fromCannedAccessPolicy((CannedAccessPolicy) aclObj, DEFAULT_OWNER_ID);
} else if (aclObj == null) {
// Default to private access policy
acl = AccessControlList.fromCannedAccessPolicy(CannedAccessPolicy.PRIVATE,
DEFAULT_OWNER_ID);
acl = AccessControlList.fromCannedAccessPolicy(CannedAccessPolicy.PRIVATE, DEFAULT_OWNER_ID);
}
return acl;
}
@ -228,8 +214,7 @@ public class StubS3AsyncClient implements S3AsyncClient {
return immediateFuture(getACLforS3Item(bucket));
}
public ListenableFuture<AccessControlList> getObjectACL(final String bucket,
final String objectKey) {
public ListenableFuture<AccessControlList> getObjectACL(final String bucket, final String objectKey) {
return immediateFuture(getACLforS3Item(bucket + "/" + objectKey));
}
@ -248,8 +233,7 @@ public class StubS3AsyncClient implements S3AsyncClient {
for (Grant grant : acl.getGrants()) {
if (grant.getGrantee() instanceof EmailAddressGrantee) {
EmailAddressGrantee emailGrantee = (EmailAddressGrantee) grant.getGrantee();
String id = emailGrantee.getEmailAddress().equals(TEST_ACL_EMAIL) ? TEST_ACL_ID : acl
.getOwner().getId();
String id = emailGrantee.getEmailAddress().equals(TEST_ACL_EMAIL) ? TEST_ACL_ID : acl.getOwner().getId();
grant.setGrantee(new CanonicalUserGrantee(id, acl.getOwner().getDisplayName()));
}
}
@ -286,20 +270,18 @@ public class StubS3AsyncClient implements S3AsyncClient {
return blobStore.removeBlob(bucketName, key);
}
public ListenableFuture<S3Object> getObject(final String bucketName, final String key,
final GetOptions... options) {
public ListenableFuture<S3Object> getObject(final String bucketName, final String key, final GetOptions... options) {
org.jclouds.blobstore.options.GetOptions getOptions = httpGetOptionsConverter.apply(options);
return compose(blobStore.getBlob(bucketName, key, getOptions), blob2Object);
return compose(blobStore.getBlob(bucketName, key, getOptions), blob2Object, service);
}
public ListenableFuture<ObjectMetadata> headObject(String bucketName, String key) {
return compose(ConcurrentUtils.makeListenable(blobStore.blobMetadata(bucketName, key),
executorService), new Function<BlobMetadata, ObjectMetadata>() {
return compose(blobStore.blobMetadata(bucketName, key), new Function<BlobMetadata, ObjectMetadata>() {
@Override
public ObjectMetadata apply(BlobMetadata from) {
return blob2ObjectMetadata.apply(from);
}
});
}, service);
}
public ListenableFuture<? extends Set<BucketMetadata>> listOwnedBuckets() {

View File

@ -72,8 +72,8 @@ public class MainApp {
String name = args[3];
// Init
RestContext<EC2Client, EC2AsyncClient> context = new RestContextFactory().createContext(
"ec2", accesskeyid, secretkey);
RestContext<EC2Client, EC2AsyncClient> context = new RestContextFactory().createContext("ec2", accesskeyid,
secretkey);
// Get a synchronous client
EC2Client client = context.getApi();
@ -107,8 +107,7 @@ public class MainApp {
try {
String id = findInstanceByKeyName(client, name).getId();
System.out.printf("%d: %s terminating instance%n", System.currentTimeMillis(), id);
client.getInstanceServices().terminateInstancesInRegion(null,
findInstanceByKeyName(client, name).getId());
client.getInstanceServices().terminateInstancesInRegion(null, findInstanceByKeyName(client, name).getId());
} catch (NoSuchElementException e) {
} catch (Exception e) {
e.printStackTrace();
@ -129,8 +128,8 @@ public class MainApp {
}
}
private static RunningInstance createSecurityGroupKeyPairAndInstance(EC2Client client,
String name) throws TimeoutException {
private static RunningInstance createSecurityGroupKeyPairAndInstance(EC2Client client, String name)
throws TimeoutException {
// create a new security group
createSecurityGroupAndAuthorizePorts(client, name);
@ -145,8 +144,8 @@ public class MainApp {
System.out.printf("%d: creating security group: %s%n", System.currentTimeMillis(), name);
client.getSecurityGroupServices().createSecurityGroupInRegion(null, name, name);
for (int port : new int[] { 80, 8080, 443, 22 }) {
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, name,
IpProtocol.TCP, port, port, "0.0.0.0/0");
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, name, IpProtocol.TCP, port,
port, "0.0.0.0/0");
}
}
@ -163,7 +162,7 @@ public class MainApp {
.build(OsFamily.UNIX);
System.out.printf("%d: running instance%n", System.currentTimeMillis());
Reservation reservation = client.getInstanceServices().runInstancesInRegion(null, null, // allow
Reservation<? extends RunningInstance> reservation = client.getInstanceServices().runInstancesInRegion(null, null, // allow
// ec2
// to
// chose
@ -182,43 +181,38 @@ public class MainApp {
}
static RunningInstance blockUntilInstanceRunning(EC2Client client, RunningInstance instance)
throws TimeoutException {
static RunningInstance blockUntilInstanceRunning(EC2Client client, RunningInstance instance) throws TimeoutException {
// create utilities that wait for the instance to finish
RetryablePredicate<RunningInstance> runningTester = new RetryablePredicate<RunningInstance>(
new InstanceStateRunning(client), 180, 5, TimeUnit.SECONDS);
System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance
.getId());
System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance.getId());
if (!runningTester.apply(instance))
throw new TimeoutException("timeout waiting for instance to run: " + instance.getId());
instance = findInstanceById(client, instance.getId());
RetryablePredicate<IPSocket> socketTester = new RetryablePredicate<IPSocket>(
new InetSocketAddressConnect(), 300, 1, TimeUnit.SECONDS);
System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(),
instance.getIpAddress());
RetryablePredicate<IPSocket> socketTester = new RetryablePredicate<IPSocket>(new InetSocketAddressConnect(), 300,
1, TimeUnit.SECONDS);
System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(), instance.getIpAddress());
if (!socketTester.apply(new IPSocket(instance.getIpAddress(), 22)))
throw new TimeoutException("timeout waiting for ssh to start: " + instance.getIpAddress());
System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance
.getIpAddress());
System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance.getIpAddress());
System.out.printf("%d: %s awaiting http service to start%n", System.currentTimeMillis(),
instance.getIpAddress());
System.out.printf("%d: %s awaiting http service to start%n", System.currentTimeMillis(), instance.getIpAddress());
if (!socketTester.apply(new IPSocket(instance.getIpAddress(), 80)))
throw new TimeoutException("timeout waiting for http to start: " + instance.getIpAddress());
System.out.printf("%d: %s http service started%n", System.currentTimeMillis(), instance
.getIpAddress());
System.out.printf("%d: %s http service started%n", System.currentTimeMillis(), instance.getIpAddress());
return instance;
}
private static RunningInstance findInstanceById(EC2Client client, String instanceId) {
// search my account for the instance I just created
Set<Reservation> reservations = client.getInstanceServices().describeInstancesInRegion(null,
instanceId); // last parameter (ids) narrows the search
Set<? extends Reservation<? extends RunningInstance>> reservations = client.getInstanceServices()
.describeInstancesInRegion(null, instanceId); // last parameter (ids) narrows the
// search
// since we refined by instanceId there should only be one instance
return Iterables.getOnlyElement(Iterables.getOnlyElement(reservations));
@ -226,11 +220,12 @@ public class MainApp {
private static RunningInstance findInstanceByKeyName(EC2Client client, final String keyName) {
// search my account for the instance I just created
Set<Reservation> reservations = client.getInstanceServices().describeInstancesInRegion(null);
Set<? extends Reservation<? extends RunningInstance>> reservations = client.getInstanceServices()
.describeInstancesInRegion(null);
// extract all the instances from all reservations
Set<RunningInstance> allInstances = Sets.newHashSet();
for (Reservation reservation : reservations) {
for (Reservation<? extends RunningInstance> reservation : reservations) {
allInstances.addAll(reservation);
}
@ -239,8 +234,7 @@ public class MainApp {
@Override
public boolean apply(RunningInstance input) {
return input.getKeyName().equals(keyName)
&& input.getInstanceState() != InstanceState.TERMINATED;
return input.getKeyName().equals(keyName) && input.getInstanceState() != InstanceState.TERMINATED;
}
});

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.aws.sqs;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.concurrent.ConcurrentUtils.sameThreadExecutor;
import static org.jclouds.aws.sqs.options.ListQueuesOptions.Builder.queuePrefix;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
@ -38,7 +38,7 @@ import org.jclouds.rest.RestContextFactory;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.concurrent.Future;
import com.google.inject.Module;
/**
@ -133,7 +133,7 @@ public class SpeedTest {
queue.getName());
// fire off all the messages for the test
Map<QueueMessage, ListenableFuture<byte[]>> responses = Maps.newHashMap();
Map<QueueMessage, Future<byte[]>> responses = Maps.newHashMap();
for (int i = 0; i < messageCount; i++) {
responses.put(new QueueMessage(queue, message), context.getAsyncApi().sendMessage(
queue, message));

View File

@ -68,7 +68,7 @@ public class JCloudsS3Service extends S3Service {
* @param awsCredentials
* - credentials to access S3
* @param modules
* - Module that configures a ListenableFutureHttpClient, if not specified, default is
* - Module that configures a FutureHttpClient, if not specified, default is
* URLFetchServiceClientModule
* @throws S3ServiceException
*/

View File

@ -33,14 +33,14 @@ import org.jclouds.blobstore.ContainerNotFoundException;
import org.jclouds.concurrent.Timeout;
import org.jclouds.http.options.GetOptions;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.concurrent.Future;
/**
* Provides access to Azure Blob via their REST API.
* <p/>
* All commands return a ListenableFuture of the result from Azure Blob. Any exceptions incurred
* All commands return a Future of the result from Azure Blob. Any exceptions incurred
* during processing will be wrapped in an {@link ExecutionException} as documented in
* {@link ListenableFuture#get()}.
* {@link Future#get()}.
*
* @see <a href="http://msdn.microsoft.com/en-us/library/dd135733.aspx" />
* @author Adrian Cole

View File

@ -19,11 +19,12 @@
package org.jclouds.azure.storage.blob.blobstore;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.compose;
import static org.jclouds.concurrent.ConcurrentUtils.compose;
import static org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import com.google.common.util.concurrent.ListenableFuture;
import javax.inject.Inject;
import javax.inject.Named;
@ -58,7 +59,6 @@ import org.jclouds.http.options.GetOptions;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.ListenableFuture;
/**
* @author Adrian Cole
@ -76,21 +76,19 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
@Inject
AzureAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
Location defaultLocation, Set<? extends Location> locations,
AzureBlobAsyncClient async, ContainerToResourceMetadata container2ResourceMd,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Location defaultLocation,
Set<? extends Location> locations, AzureBlobAsyncClient async,
ContainerToResourceMetadata container2ResourceMd,
ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions,
ListBlobsResponseToResourceList azure2BlobStoreResourceList,
AzureBlobToBlob azureBlob2Blob, BlobToAzureBlob blob2AzureBlob,
BlobPropertiesToBlobMetadata blob2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions) {
ListBlobsResponseToResourceList azure2BlobStoreResourceList, AzureBlobToBlob azureBlob2Blob,
BlobToAzureBlob blob2AzureBlob, BlobPropertiesToBlobMetadata blob2BlobMd,
BlobToHttpGetOptions blob2ObjectGetOptions) {
super(context, blobUtils, service, defaultLocation, locations);
this.async = checkNotNull(async, "async");
this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd");
this.blobStore2AzureContainerListOptions = checkNotNull(blobStore2AzureContainerListOptions,
"blobStore2AzureContainerListOptions");
this.azure2BlobStoreResourceList = checkNotNull(azure2BlobStoreResourceList,
"azure2BlobStoreResourceList");
this.azure2BlobStoreResourceList = checkNotNull(azure2BlobStoreResourceList, "azure2BlobStoreResourceList");
this.azureBlob2Blob = checkNotNull(azureBlob2Blob, "azureBlob2Blob");
this.blob2AzureBlob = checkNotNull(blob2AzureBlob, "blob2AzureBlob");
this.blob2BlobMd = checkNotNull(blob2BlobMd, "blob2BlobMd");
@ -102,14 +100,14 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
* {@link org.jclouds.azure.storage.options.ListOptions#includeMetadata} option.
*/
@Override
public ListenableFuture<? extends org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>> list() {
public ListenableFuture<org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>> list() {
return compose(
async.listContainers(includeMetadata()),
new Function<BoundedSet<ContainerProperties>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(
BoundedSet<ContainerProperties> from) {
return new PageSetImpl<StorageMetadata>(Iterables.transform(from,
container2ResourceMd), from.getNextMarker());
return new PageSetImpl<StorageMetadata>(Iterables.transform(from, container2ResourceMd), from
.getNextMarker());
}
}, service);
}
@ -145,11 +143,9 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
* container name
*/
@Override
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(String container,
ListContainerOptions options) {
public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container, ListContainerOptions options) {
ListBlobsOptions azureOptions = blobStore2AzureContainerListOptions.apply(options);
ListenableFuture<ListBlobsResponse> returnVal = async.listBlobs(container, azureOptions
.includeMetadata());
ListenableFuture<ListBlobsResponse> returnVal = async.listBlobs(container, azureOptions.includeMetadata());
return compose(returnVal, azure2BlobStoreResourceList, service);
}
@ -173,8 +169,7 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
* blob key
*/
@Override
public ListenableFuture<Blob> getBlob(String container, String key,
org.jclouds.blobstore.options.GetOptions options) {
public ListenableFuture<Blob> getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions options) {
GetOptions azureOptions = blob2ObjectGetOptions.apply(options);
ListenableFuture<AzureBlob> returnVal = async.getBlob(container, key, azureOptions);
return compose(returnVal, azureBlob2Blob, service);
@ -229,8 +224,7 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
*/
@Override
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
return compose(async.getBlobProperties(container, key),
new Function<BlobProperties, BlobMetadata>() {
return compose(async.getBlobProperties(container, key), new Function<BlobProperties, BlobMetadata>() {
@Override
public BlobMetadata apply(BlobProperties from) {

View File

@ -32,7 +32,7 @@ import org.jclouds.azure.storage.queue.options.PutMessageOptions;
import org.jclouds.concurrent.Timeout;
import org.jclouds.http.HttpResponseException;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.concurrent.Future;
/**
* Provides access to Azure Queue via their REST API.
@ -47,9 +47,9 @@ import com.google.common.util.concurrent.ListenableFuture;
* If you need to store messages larger than 8 KB, you can store message data as a blob or in a
* table, and then store a reference to the data as a message in a queue.
* <p/>
* All commands return a ListenableFuture of the result from Azure Queue. Any exceptions incurred
* All commands return a Future of the result from Azure Queue. Any exceptions incurred
* during processing will be wrapped in an {@link ExecutionException} as documented in
* {@link ListenableFuture#get()}.
* {@link Future#get()}.
*
* @see AzureQueueAsyncClient
* @see <a href="http://msdn.microsoft.com/en-us/library/dd135733.aspx" />

View File

@ -19,6 +19,7 @@
package org.jclouds.blobstore;
import java.util.Set;
import com.google.common.util.concurrent.ListenableFuture;
import javax.annotation.Nullable;
@ -30,8 +31,6 @@ import org.jclouds.blobstore.options.GetOptions;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.domain.Location;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Provides hooks needed to run a blob store asynchronously
*
@ -51,12 +50,12 @@ public interface AsyncBlobStore {
/**
* @see BlobStore#listAssignableLocations
*/
ListenableFuture<? extends Set<? extends Location>> listAssignableLocations();
ListenableFuture<Set<? extends Location>> listAssignableLocations();
/**
* @see BlobStore#list
*/
ListenableFuture<? extends PageSet<? extends StorageMetadata>> list();
ListenableFuture<PageSet<? extends StorageMetadata>> list();
/**
* @see BlobStore#containerExists
@ -71,13 +70,12 @@ public interface AsyncBlobStore {
/**
* @see BlobStore#list(String)
*/
ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(String container);
ListenableFuture<PageSet<? extends StorageMetadata>> list(String container);
/**
* @see BlobStore#list(String, ListContainerOptions)
*/
ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(String container,
ListContainerOptions options);
ListenableFuture<PageSet<? extends StorageMetadata>> list(String container, ListContainerOptions options);
/**
* @see BlobStore#clearContainer(String)
@ -127,12 +125,12 @@ public interface AsyncBlobStore {
/**
* @see BlobStore#getBlob(String, String)
*/
ListenableFuture<? extends Blob> getBlob(String container, String key);
ListenableFuture<Blob> getBlob(String container, String key);
/**
* @see BlobStore#getBlob(String, String, GetOptions)
*/
ListenableFuture<? extends Blob> getBlob(String container, String key, GetOptions options);
ListenableFuture<Blob> getBlob(String container, String key, GetOptions options);
/**
* @see BlobStore#removeBlob

View File

@ -93,6 +93,7 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimaps;
import com.google.common.io.Closeables;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.internal.Nullable;
@ -114,13 +115,12 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
@Inject
protected TransientAsyncBlobStore(BlobStoreContext context, DateService dateService,
EncryptionService encryptionService,
ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
EncryptionService encryptionService, ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
ConcurrentMap<String, Location> containerToLocation,
HttpGetOptionsListToGetOptions httpGetOptionsConverter,
IfDirectoryReturnNameStrategy ifDirectoryReturnName, Blob.Factory blobFactory,
BlobUtils blobUtils, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
Location defaultLocation, Set<Location> locations) {
IfDirectoryReturnNameStrategy ifDirectoryReturnName, Blob.Factory blobFactory, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Location defaultLocation,
Set<Location> locations) {
super(context, blobUtils, service, defaultLocation, locations);
this.blobFactory = blobFactory;
this.dateService = dateService;
@ -137,8 +137,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
* default maxResults is 1000
*/
@Override
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(
final String container, ListContainerOptions options) {
public ListenableFuture<PageSet<? extends StorageMetadata>> list(final String container, ListContainerOptions options) {
final Map<String, Blob> realContents = getContainerToBlobs().get(container);
if (realContents == null)
@ -148,10 +147,9 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
new Function<String, StorageMetadata>() {
public StorageMetadata apply(String key) {
Blob oldBlob = realContents.get(key);
checkState(oldBlob != null, "blob " + key
+ " is not present although it was in the list of " + container);
checkState(oldBlob.getMetadata() != null, "blob " + container + "/" + key
+ " has no metadata");
checkState(oldBlob != null, "blob " + key + " is not present although it was in the list of "
+ container);
checkState(oldBlob.getMetadata() != null, "blob " + container + "/" + key + " has no metadata");
MutableBlobMetadata md = copy(oldBlob.getMetadata());
String directoryName = ifDirectoryReturnName.execute(md);
if (directoryName != null) {
@ -198,13 +196,11 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
final String delimiter = options.isRecursive() ? null : "/";
if (delimiter != null) {
SortedSet<String> commonPrefixes = null;
Iterable<String> iterable = transform(contents, new CommonPrefixes(prefix != null ? prefix
: null, delimiter));
Iterable<String> iterable = transform(contents, new CommonPrefixes(prefix != null ? prefix : null, delimiter));
commonPrefixes = iterable != null ? newTreeSet(iterable) : new TreeSet<String>();
commonPrefixes.remove(CommonPrefixes.NO_PREFIX);
contents = newTreeSet(filter(contents, new DelimiterFilter(prefix != null ? prefix : null,
delimiter)));
contents = newTreeSet(filter(contents, new DelimiterFilter(prefix != null ? prefix : null, delimiter)));
Iterables.<StorageMetadata> addAll(contents, transform(commonPrefixes,
new Function<String, StorageMetadata>() {
@ -224,13 +220,14 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
}
}
return immediateFuture(new PageSetImpl<StorageMetadata>(contents, marker));
return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(contents,
marker));
}
private ContainerNotFoundException cnfe(final String name) {
return new ContainerNotFoundException(name, String.format("container %s not in %s", name,
getContainerToBlobs().keySet()));
return new ContainerNotFoundException(name, String.format("container %s not in %s", name, getContainerToBlobs()
.keySet()));
}
public static MutableBlobMetadata copy(MutableBlobMetadata in) {
@ -318,9 +315,9 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
* {@inheritDoc}
*/
@Override
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list() {
return immediateFuture(new PageSetImpl<StorageMetadata>(transform(getContainerToBlobs()
.keySet(), new Function<String, StorageMetadata>() {
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(transform(
getContainerToBlobs().keySet(), new Function<String, StorageMetadata>() {
public StorageMetadata apply(String name) {
MutableStorageMetadata cmd = create();
cmd.setName(name);
@ -339,8 +336,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
* {@inheritDoc}
*/
@Override
public ListenableFuture<Boolean> createContainerInLocation(final Location location,
final String name) {
public ListenableFuture<Boolean> createContainerInLocation(final Location location, final String name) {
if (!getContainerToBlobs().containsKey(name)) {
getContainerToBlobs().put(name, new ConcurrentHashMap<String, Blob>());
getContainerToLocation().put(name, location != null ? location : defaultLocation);
@ -407,8 +403,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
}
}
public static <T extends Comparable<?>> SortedSet<T> firstSliceOfSize(Iterable<T> elements,
int size) {
public static <T extends Comparable<?>> SortedSet<T> firstSliceOfSize(Iterable<T> elements, int size) {
List<List<T>> slices = partition(newArrayList(elements), size);
return newTreeSet(slices.get(0));
}
@ -463,15 +458,12 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
new RuntimeException("containerName not found: " + containerName);
}
ByteArrayPayload payload = (object.getPayload() instanceof ByteArrayPayload) ? ByteArrayPayload.class
.cast(object.getPayload())
: null;
ByteArrayPayload payload = (object.getPayload() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(object
.getPayload()) : null;
if (payload == null)
payload = (object.getPayload() instanceof DelegatingPayload) ? (DelegatingPayload.class
.cast(object.getPayload()).getDelegate() instanceof ByteArrayPayload) ? ByteArrayPayload.class
.cast(DelegatingPayload.class.cast(object.getPayload()).getDelegate())
: null
: null;
payload = (object.getPayload() instanceof DelegatingPayload) ? (DelegatingPayload.class.cast(
object.getPayload()).getDelegate() instanceof ByteArrayPayload) ? ByteArrayPayload.class
.cast(DelegatingPayload.class.cast(object.getPayload()).getDelegate()) : null : null;
if (payload == null || !(payload instanceof ByteArrayPayload)) {
InputStream input = object.getPayload().getInput();
try {
@ -483,8 +475,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
}
} else {
if (payload.getContentMD5() == null)
payload = (ByteArrayPayload) encryptionService
.generateMD5BufferingIfNotRepeatable(payload);
payload = (ByteArrayPayload) encryptionService.generateMD5BufferingIfNotRepeatable(payload);
}
Blob blob = blobFactory.create(copy(object.getMetadata()));
@ -525,8 +516,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
* {@inheritDoc}
*/
@Override
public ListenableFuture<? extends Blob> getBlob(final String containerName, final String key,
GetOptions options) {
public ListenableFuture<Blob> getBlob(final String containerName, final String key, GetOptions options) {
if (!getContainerToBlobs().containsKey(containerName))
return immediateFailedFuture(cnfe(containerName));
Map<String, Blob> realContents = getContainerToBlobs().get(containerName);
@ -547,9 +537,8 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
Date modifiedSince = options.getIfModifiedSince();
if (object.getMetadata().getLastModified().before(modifiedSince)) {
HttpResponse response = new HttpResponse(304, null, null);
return immediateFailedFuture(new HttpResponseException(String.format(
"%1$s is before %2$s", object.getMetadata().getLastModified(), modifiedSince),
null, response));
return immediateFailedFuture(new HttpResponseException(String.format("%1$s is before %2$s", object
.getMetadata().getLastModified(), modifiedSince), null, response));
}
}
@ -557,9 +546,8 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
Date unmodifiedSince = options.getIfUnmodifiedSince();
if (object.getMetadata().getLastModified().after(unmodifiedSince)) {
HttpResponse response = new HttpResponse(412, null, null);
return immediateFailedFuture(new HttpResponseException(
String.format("%1$s is after %2$s", object.getMetadata().getLastModified(),
unmodifiedSince), null, response));
return immediateFailedFuture(new HttpResponseException(String.format("%1$s is after %2$s", object
.getMetadata().getLastModified(), unmodifiedSince), null, response));
}
}
Blob returnVal = copyBlob(object);
@ -586,8 +574,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
int length = (last < data.length) ? last + 1 : data.length - offset;
out.write(data, offset, length);
} else {
return immediateFailedFuture(new IllegalArgumentException(
"first and last were null!"));
return immediateFailedFuture(new IllegalArgumentException("first and last were null!"));
}
}

View File

@ -19,10 +19,7 @@
package org.jclouds.blobstore.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.Futures.chain;
import static com.google.common.util.concurrent.Futures.immediateFuture;
import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import java.util.Set;
import java.util.concurrent.Callable;
@ -41,11 +38,12 @@ import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.util.BlobUtils;
import org.jclouds.blobstore.util.internal.BlobUtilsImpl;
import static org.jclouds.concurrent.ConcurrentUtils.*;
import org.jclouds.domain.Location;
import org.jclouds.util.Utils;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
/**
@ -62,8 +60,8 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
@Inject
protected BaseAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
Location defaultLocation, Set<? extends Location> locations) {
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Location defaultLocation,
Set<? extends Location> locations) {
this.context = checkNotNull(context, "context");
this.blobUtils = checkNotNull(blobUtils, "blobUtils");
this.service = checkNotNull(service, "service");
@ -92,7 +90,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
* container name
*/
@Override
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(String container) {
public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container) {
return this.list(container, org.jclouds.blobstore.options.ListContainerOptions.NONE);
}
@ -115,8 +113,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
* container name
*/
@Override
public ListenableFuture<Long> countBlobs(final String containerName,
final ListContainerOptions options) {
public ListenableFuture<Long> countBlobs(final String containerName, final ListContainerOptions options) {
return makeListenable(service.submit(new Callable<Long>() {
public Long call() throws Exception {
return blobUtils.countBlobs(containerName, options);
@ -144,8 +141,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
* container name
*/
@Override
public ListenableFuture<Void> clearContainer(final String containerName,
final ListContainerOptions options) {
public ListenableFuture<Void> clearContainer(final String containerName, final ListContainerOptions options) {
return makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception {
@ -182,8 +178,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
* @param directory
* virtual path
*/
public ListenableFuture<Boolean> directoryExists(final String containerName,
final String directory) {
public ListenableFuture<Boolean> directoryExists(final String containerName, final String directory) {
return makeListenable(service.submit(new Callable<Boolean>() {
public Boolean call() throws Exception {
@ -204,18 +199,13 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
public ListenableFuture<Void> createDirectory(final String containerName, final String directory) {
return chain(directoryExists(containerName, directory),
new Function<Boolean, ListenableFuture<Void>>() {
@Override
public ListenableFuture<Void> apply(Boolean from) {
if (!from) {
return blobUtils.directoryExists(containerName, directory) ? Futures.immediateFuture((Void) null)
: makeListenable(service.submit(new Callable<Void>() {
public Void call() throws Exception {
blobUtils.createDirectory(containerName, directory);
return null;
}
return immediateFuture(null);
}
}, service);
}), service);
}
/**
@ -228,7 +218,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
* blob key
*/
@Override
public ListenableFuture<? extends Blob> getBlob(String container, String key) {
public ListenableFuture<Blob> getBlob(String container, String key) {
return getBlob(container, key, org.jclouds.blobstore.options.GetOptions.NONE);
}
@ -271,8 +261,8 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
}
@Override
public ListenableFuture<? extends Set<? extends Location>> listAssignableLocations() {
return immediateFuture(locations);
public ListenableFuture<Set<? extends Location>> listAssignableLocations() {
return Futures.<Set<? extends Location>> immediateFuture(locations);
}
protected abstract boolean deleteAndVerifyContainerGone(String container);

View File

@ -160,8 +160,8 @@ public abstract class BaseBlobMap<V> implements ListableMap<String, V> {
return (int) blobstore.countBlobs(containerName, options);
}
protected Set<? extends Blob> getAllBlobs() {
Set<? extends Blob> returnVal = getAllBlobs.execute(containerName, options);
protected Iterable<Blob> getAllBlobs() {
Iterable<Blob> returnVal = getAllBlobs.execute(containerName, options);
if (options != null) {
for (Blob from : returnVal)
stripPrefix(from);

View File

@ -33,6 +33,8 @@ import org.jclouds.blobstore.strategy.GetBlobsInListStrategy;
import org.jclouds.blobstore.strategy.PutBlobsStrategy;
import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders;
import com.google.common.collect.Sets;
/**
* Map representation of a live connection to a Blob Service.
*
@ -46,10 +48,8 @@ public class BlobMapImpl extends BaseBlobMap<Blob> implements BlobMap {
@Inject
public BlobMapImpl(BlobStore blobstore, GetBlobsInListStrategy getAllBlobs,
ContainsValueInListStrategy containsValueStrategy, PutBlobsStrategy putBlobsStrategy,
ListContainerAndRecurseThroughFolders listStrategy, String containerName,
ListContainerOptions options) {
super(blobstore, getAllBlobs, containsValueStrategy, putBlobsStrategy, listStrategy,
containerName, options);
ListContainerAndRecurseThroughFolders listStrategy, String containerName, ListContainerOptions options) {
super(blobstore, getAllBlobs, containsValueStrategy, putBlobsStrategy, listStrategy, containerName, options);
}
@Override
@ -89,10 +89,9 @@ public class BlobMapImpl extends BaseBlobMap<Blob> implements BlobMap {
return old;
}
@SuppressWarnings("unchecked")
@Override
public Collection<Blob> values() {
return (Collection<Blob>) getAllBlobs.execute(containerName, options);
return Sets.newLinkedHashSet(getAllBlobs.execute(containerName, options));
}
@Override

View File

@ -37,7 +37,7 @@ import java.util.List;
*
*
* // this will get the first megabyte of an object, provided it wasn't modified since yesterday
* ListenableFuture<S3Object> object = client.get("objectName",range(0,1024).ifUnmodifiedSince(new Date().minusDays(1)));
* Future<S3Object> object = client.get("objectName",range(0,1024).ifUnmodifiedSince(new Date().minusDays(1)));
* <code>
*
* @author Adrian Cole

View File

@ -31,7 +31,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
* import static org.jclouds.blobstore.options.ListContainerOptions.Builder.*
* <p/>
* BlobStore connection = // get connection
* ListenableFuture<ListResponse<ResourceMetadata>> list = connection.list("container",inDirectory("home/users").maxResults(1000));
* Future<ListResponse<ResourceMetadata>> list = connection.list("container",inDirectory("home/users").maxResults(1000));
* <code>
*
* @author Adrian Cole

View File

@ -30,7 +30,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
* import static org.jclouds.blobstore.options.ListOptions.Builder.*
* <p/>
* BlobStore connection = // get connection
* ListenableFuture<BoundedSortedSet<ResourceMetadata>> list = connection.list(maxResults(1000));
* Future<BoundedSortedSet<ResourceMetadata>> list = connection.list(maxResults(1000));
* <code>
*
* @author Adrian Cole

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.blobstore.strategy;
import java.util.Set;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.strategy.internal.GetAllBlobsInListAndRetryOnFailure;
@ -34,6 +32,6 @@ import com.google.inject.ImplementedBy;
@ImplementedBy(GetAllBlobsInListAndRetryOnFailure.class)
public interface GetBlobsInListStrategy {
Set<? extends Blob> execute(String containerName, ListContainerOptions options);
Iterable<Blob> execute(String containerName, ListContainerOptions options);
}

View File

@ -18,6 +18,8 @@
*/
package org.jclouds.blobstore.strategy;
import java.util.Set;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders;
@ -32,6 +34,6 @@ import com.google.inject.ImplementedBy;
@ImplementedBy(ListContainerAndRecurseThroughFolders.class)
public interface ListBlobsInContainer {
Iterable<? extends BlobMetadata> execute(String containerName, ListContainerOptions options);
Set<? extends BlobMetadata> execute(String containerName, ListContainerOptions options);
}

View File

@ -43,7 +43,7 @@ import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.concurrent.Future;
import com.google.inject.Inject;
/**
@ -93,7 +93,7 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
Map<StorageMetadata, Exception> exceptions = Maps.newHashMap();
Iterable<? extends StorageMetadata> toDelete = getResourcesToDelete(containerName, options);
for (int i = 0; i < 3; i++) { // TODO parameterize
Map<StorageMetadata, ListenableFuture<?>> responses = Maps.newHashMap();
Map<StorageMetadata, Future<?>> responses = Maps.newHashMap();
try {
for (final StorageMetadata md : toDelete) {
String fullPath = parentIsFolder(options, md) ? options.getDir() + "/"

View File

@ -19,13 +19,10 @@
package org.jclouds.blobstore.strategy.internal;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import static org.jclouds.concurrent.ConcurrentUtils.transformParallel;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.annotation.concurrent.NotThreadSafe;
@ -33,20 +30,18 @@ import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.blobstore.AsyncBlobStore;
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.blobstore.domain.internal.PageSetImpl;
import org.jclouds.blobstore.internal.BlobRuntimeException;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
/**
@ -55,8 +50,7 @@ import com.google.inject.Inject;
* @author Adrian Cole
*/
@NotThreadSafe
public class FetchBlobMetadata implements
Function<PageSet<? extends StorageMetadata>, PageSet<? extends StorageMetadata>> {
public class FetchBlobMetadata implements Function<PageSet<? extends StorageMetadata>, PageSet<? extends StorageMetadata>> {
protected final BackoffLimitedRetryHandler retryHandler;
protected final AsyncBlobStore ablobstore;
@ -74,8 +68,8 @@ public class FetchBlobMetadata implements
protected Long maxTime;
@Inject
FetchBlobMetadata(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
AsyncBlobStore ablobstore, BackoffLimitedRetryHandler retryHandler) {
FetchBlobMetadata(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, AsyncBlobStore ablobstore,
BackoffLimitedRetryHandler retryHandler) {
this.userExecutor = userExecutor;
this.ablobstore = ablobstore;
this.retryHandler = retryHandler;
@ -88,35 +82,23 @@ public class FetchBlobMetadata implements
public PageSet<? extends StorageMetadata> apply(PageSet<? extends StorageMetadata> in) {
checkState(container != null, "container name should be initialized");
Map<? extends StorageMetadata, Exception> exceptions = Maps.newHashMap();
final Set<StorageMetadata> metadata = Sets.newHashSet();
Map<StorageMetadata, ListenableFuture<?>> responses = Maps.newHashMap();
for (StorageMetadata md : in) {
if (md.getType() == StorageType.BLOB) {
final ListenableFuture<? extends StorageMetadata> future = ablobstore.blobMetadata(
container, md.getName());
future.addListener(new Runnable() {
Iterable<BlobMetadata> returnv = transformParallel(Iterables.filter(in, new Predicate<StorageMetadata>() {
@Override
public void run() {
try {
metadata.add(future.get());
} catch (InterruptedException e) {
Throwables.propagate(e);
} catch (ExecutionException e) {
Throwables.propagate(e);
}
}
}, sameThreadExecutor());
responses.put(md, future);
} else {
metadata.add(md);
}
}
exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, String.format(
"getting metadata from containerName: %s", container));
if (exceptions.size() > 0)
throw new BlobRuntimeException(String.format("errors getting from container %s: %s",
container, exceptions));
return new PageSetImpl<StorageMetadata>(metadata, in.getNextMarker());
public boolean apply(StorageMetadata input) {
return input.getType() == StorageType.BLOB;
}
}), new Function<StorageMetadata, Future<BlobMetadata>>() {
@Override
public Future<BlobMetadata> apply(StorageMetadata from) {
return ablobstore.blobMetadata(container, from.getName());
}
}, userExecutor, maxTime, logger, String.format("getting metadata from containerName: %s", container));
return new PageSetImpl<BlobMetadata>(returnv, in.getNextMarker());
}
}

View File

@ -18,13 +18,10 @@
*/
package org.jclouds.blobstore.strategy.internal;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import static org.jclouds.concurrent.ConcurrentUtils.transformParallel;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Named;
@ -34,7 +31,6 @@ import org.jclouds.Constants;
import org.jclouds.blobstore.AsyncBlobStore;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.internal.BlobRuntimeException;
import org.jclouds.blobstore.options.ListContainerOptions;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.blobstore.strategy.GetBlobsInListStrategy;
@ -42,10 +38,7 @@ import org.jclouds.blobstore.strategy.ListBlobsInContainer;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.logging.Logger;
import com.google.common.base.Throwables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.base.Function;
import com.google.inject.Inject;
/**
@ -72,52 +65,24 @@ public class GetAllBlobsInListAndRetryOnFailure implements GetBlobsInListStrateg
protected Long maxTime;
@Inject
GetAllBlobsInListAndRetryOnFailure(
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
ListBlobsInContainer getAllBlobMetadata, AsyncBlobStore ablobstore,
BackoffLimitedRetryHandler retryHandler) {
GetAllBlobsInListAndRetryOnFailure(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
ListBlobsInContainer getAllBlobMetadata, AsyncBlobStore ablobstore, BackoffLimitedRetryHandler retryHandler) {
this.userExecutor = userExecutor;
this.ablobstore = ablobstore;
this.getAllBlobMetadata = getAllBlobMetadata;
this.retryHandler = retryHandler;
}
public Set<? extends Blob> execute(String container, ListContainerOptions options) {
Map<BlobMetadata, Exception> exceptions = Maps.newHashMap();
final Set<Blob> objects = Sets.newHashSet();
Iterable<? extends BlobMetadata> toGet = getAllBlobMetadata.execute(container, options);
for (int i = 0; i < 3; i++) {
Map<BlobMetadata, ListenableFuture<?>> responses = Maps.newHashMap();
for (BlobMetadata md : toGet) {
final ListenableFuture<? extends Blob> future = ablobstore.getBlob(container, md
.getName());
future.addListener(new Runnable() {
public Iterable<Blob> execute(final String container, ListContainerOptions options) {
Iterable<? extends BlobMetadata> list = getAllBlobMetadata.execute(container, options);
return transformParallel(list, new Function<BlobMetadata, Future<Blob>>() {
@Override
public void run() {
try {
objects.add(future.get());
} catch (InterruptedException e) {
Throwables.propagate(e);
} catch (ExecutionException e) {
Throwables.propagate(e);
}
}
}, sameThreadExecutor());
responses.put(md, future);
}
exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, String.format(
"getting from containerName: %s", container));
if (exceptions.size() > 0) {
toGet = exceptions.keySet();
retryHandler.imposeBackoffExponentialDelay(i + 1, String.format("blob %s/%s not found",
container, toGet));
} else {
break;
}
}
if (exceptions.size() > 0)
throw new BlobRuntimeException(String.format("errors getting from container %s: %s",
container, exceptions));
return objects;
public Future<Blob> apply(BlobMetadata from) {
return ablobstore.getBlob(container, from.getName());
}
}, userExecutor, maxTime, logger, String.format("getting from containerName: %s", container), retryHandler, 3);
}
}

View File

@ -18,7 +18,14 @@
*/
package org.jclouds.blobstore.strategy.internal;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Sets.newLinkedHashSet;
import java.util.List;
import java.util.Set;
import javax.inject.Singleton;
@ -31,9 +38,6 @@ import org.jclouds.blobstore.strategy.ListContainerStrategy;
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.collect.Sets;
import com.google.inject.Inject;
/**
@ -52,22 +56,20 @@ public class ListContainerAndRecurseThroughFolders implements ListBlobsInContain
}
@Override
public Iterable<? extends BlobMetadata> execute(final String containerName,
final ListContainerOptions options) {
final List<Iterable<? extends BlobMetadata>> lists = Lists.newArrayList();
public Set<? extends BlobMetadata> execute(final String containerName, final ListContainerOptions options) {
final List<Iterable<? extends BlobMetadata>> lists = newArrayList();
Iterable<? extends StorageMetadata> pwdList = lister.execute(containerName, options);
for (StorageMetadata md : Iterables.filter(pwdList, new Predicate<StorageMetadata>() {
for (StorageMetadata md : filter(pwdList, new Predicate<StorageMetadata>() {
@Override
public boolean apply(StorageMetadata input) {
return (input.getType() == StorageType.FOLDER || input.getType() == StorageType.RELATIVE_PATH)
&& options.isRecursive();
}
})) {
String directory = (options.getDir() != null) ? options.getDir() + "/" + md.getName() : md
.getName();
String directory = (options.getDir() != null) ? options.getDir() + "/" + md.getName() : md.getName();
lists.add(execute(containerName, options.clone().inDirectory(directory)));
}
lists.add(Iterables.transform(Iterables.filter(pwdList, new Predicate<StorageMetadata>() {
lists.add(transform(filter(pwdList, new Predicate<StorageMetadata>() {
@Override
public boolean apply(StorageMetadata input) {
return input.getType() == StorageType.BLOB;
@ -78,6 +80,6 @@ public class ListContainerAndRecurseThroughFolders implements ListBlobsInContain
return (BlobMetadata) from;
}
}));
return Sets.newHashSet(Iterables.concat(lists));
return newLinkedHashSet(concat(lists));
}
}

View File

@ -38,7 +38,7 @@ 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 java.util.concurrent.Future;
import com.google.inject.Inject;
/**
@ -92,7 +92,7 @@ public class MarkersDeleteDirectoryStrategy implements DeleteDirectoryStrategy {
for (String suffix : BlobStoreConstants.DIRECTORY_SUFFIXES) {
names.add(directory + suffix);
}
Map<String, ListenableFuture<?>> responses = Maps.newHashMap();
Map<String, Future<?>> responses = Maps.newHashMap();
for (String name : names) {
responses.put(name, ablobstore.removeBlob(containerName, name));
}

View File

@ -36,7 +36,7 @@ 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 java.util.concurrent.Future;
import com.google.inject.Inject;
/**
@ -67,7 +67,7 @@ public class PutBlobsStrategyImpl implements PutBlobsStrategy {
@Override
public void execute(String containerName, Iterable<? extends Blob> blobs) {
Map<Blob, ListenableFuture<?>> responses = Maps.newHashMap();
Map<Blob, Future<?>> responses = Maps.newHashMap();
for (Blob blob : blobs) {
responses.put(blob, ablobstore.putBlob(containerName, blob));
}

View File

@ -38,6 +38,7 @@ import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.zip.GZIPInputStream;
import javax.ws.rs.core.MediaType;
@ -48,6 +49,7 @@ 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 static org.jclouds.concurrent.ConcurrentUtils.*;
import org.jclouds.encryption.EncryptionService;
import org.jclouds.encryption.internal.JCEEncryptionService;
import org.jclouds.http.BaseJettyTest;
@ -68,8 +70,6 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.io.ByteStreams;
import com.google.common.io.InputSupplier;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
/**
* @author Adrian Cole
@ -108,10 +108,10 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
String key = "constitution.txt";
uploadConstitution(containerName, key);
Map<Integer, ListenableFuture<?>> responses = Maps.newHashMap();
Map<Integer, Future<?>> responses = Maps.newHashMap();
for (int i = 0; i < 10; i++) {
responses.put(i, Futures.compose(context.getAsyncBlobStore().getBlob(containerName, key),
responses.put(i, compose(context.getAsyncBlobStore().getBlob(containerName, key),
new Function<Blob, Void>() {
@Override
@ -121,7 +121,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
return null;
}
}));
}, this.exec));
}
Map<Integer, Exception> exceptions = awaitCompletion(responses, exec, 30000l, Logger.CONSOLE,
"get constitution");
@ -349,8 +349,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
@DataProvider(name = "delete")
public Object[][] createData() {
return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" },
{ "colon:" }, { "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } };
return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" }, { "colon:" },
{ "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } };
}
@Test(groups = { "integration", "live" }, dataProvider = "delete")
@ -376,8 +376,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
});
assertEquals(Iterables.size(listing), 0, String.format(
"deleting %s, we still have %s blobs left in container %s, using encoding %s", key,
Iterables.size(listing), containerName, LOCAL_ENCODING));
"deleting %s, we still have %s blobs left in container %s, using encoding %s", key, Iterables
.size(listing), containerName, LOCAL_ENCODING));
}
@Test(groups = { "integration", "live" })

View File

@ -56,17 +56,13 @@ import com.google.common.io.Files;
public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegrationTest {
public abstract void testPutAll() throws InterruptedException, ExecutionException,
TimeoutException;
public abstract void testPutAll() throws InterruptedException, ExecutionException, TimeoutException;
public abstract void testEntrySet() throws IOException, InterruptedException,
ExecutionException, TimeoutException;
public abstract void testEntrySet() throws IOException, InterruptedException, ExecutionException, TimeoutException;
public abstract void testValues() throws IOException, InterruptedException, ExecutionException,
TimeoutException;
public abstract void testValues() throws IOException, InterruptedException, ExecutionException, TimeoutException;
protected Map<String, byte[]> fiveBytes = Maps.transformValues(fiveStrings,
new Function<String, byte[]>() {
protected Map<String, byte[]> fiveBytes = Maps.transformValues(fiveStrings, new Function<String, byte[]>() {
public byte[] apply(String from) {
return from.getBytes();
}
@ -86,13 +82,13 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
@BeforeClass(groups = { "integration", "live" })
@Parameters( { "basedir" })
protected void setUpTempDir(@Optional String basedir) throws InterruptedException,
ExecutionException, FileNotFoundException, IOException, TimeoutException {
protected void setUpTempDir(@Optional String basedir) throws InterruptedException, ExecutionException,
FileNotFoundException, IOException, TimeoutException {
if (basedir == null) {
basedir = System.getProperty("java.io.tmpdir");
}
tmpDirectory = basedir + File.separator + "target" + File.separator + "testFiles"
+ File.separator + getClass().getSimpleName();
tmpDirectory = basedir + File.separator + "target" + File.separator + "testFiles" + File.separator
+ getClass().getSimpleName();
new File(tmpDirectory).mkdirs();
fiveFiles = Maps.newHashMap();
for (Entry<String, String> entry : fiveStrings.entrySet()) {
@ -123,8 +119,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
}
@Test(groups = { "integration", "live" })
public abstract void testRemove() throws IOException, InterruptedException, ExecutionException,
TimeoutException;
public abstract void testRemove() throws IOException, InterruptedException, ExecutionException, TimeoutException;
@Test(groups = { "integration", "live" })
public void testKeySet() throws InterruptedException, ExecutionException, TimeoutException {
@ -140,8 +135,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
}
}
protected void addTenObjectsUnderPrefix(String containerName, String prefix)
throws InterruptedException {
protected void addTenObjectsUnderPrefix(String containerName, String prefix) throws InterruptedException {
for (int i = 0; i < 10; i++) {
Blob blob = context.getBlobStore().newBlob(prefix + "/" + i);
blob.setPayload(i + "content");
@ -160,14 +154,12 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
@Test(groups = { "integration", "live" })
public void testDirectory() throws InterruptedException, UnsupportedEncodingException {
String containerName = getContainerName();
try {
String directory = "apps";
Map<String, V> rootMap = createMap(context, containerName);
Map<String, V> rootRecursiveMap = createMap(context, containerName, recursive());
Map<String, V> inDirectoryMap = createMap(context, containerName, inDirectory(directory));
Map<String, V> inDirectoryRecursiveMap = createMap(context, containerName, inDirectory(
directory).recursive());
Map<String, V> inDirectoryRecursiveMap = createMap(context, containerName, inDirectory(directory).recursive());
try {
context.getBlobStore().createDirectory(containerName, directory);
addTenObjectsUnderRoot(containerName);
@ -206,24 +198,22 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
}
protected void assertConsistencyAwareKeySetEquals(final Map<String, V> map,
final Set<String> expected) throws InterruptedException {
protected void assertConsistencyAwareKeySetEquals(final Map<String, V> map, final Set<String> expected)
throws InterruptedException {
assertConsistencyAware(new Runnable() {
public void run() {
Set<String> toMatch = map.keySet();
Set<String> shouldBeEmpty = Sets.difference(expected, toMatch);
assert shouldBeEmpty.size() == 0 : "toMatch has less keys than expected. missing: "
+ shouldBeEmpty;
assert shouldBeEmpty.size() == 0 : "toMatch has less keys than expected. missing: " + shouldBeEmpty;
shouldBeEmpty = Sets.difference(toMatch, expected);
assert shouldBeEmpty.size() == 0 : "toMatch has more keys than expected. extras: "
+ shouldBeEmpty;
assert shouldBeEmpty.size() == 0 : "toMatch has more keys than expected. extras: " + shouldBeEmpty;
assertEquals(Sets.newTreeSet(toMatch), Sets.newTreeSet(expected));
}
});
}
protected void assertConsistencyAwareRemoveEquals(final Map<String, V> map, final String key,
final Object equals) throws InterruptedException {
protected void assertConsistencyAwareRemoveEquals(final Map<String, V> map, final String key, final Object equals)
throws InterruptedException {
assertConsistencyAware(new Runnable() {
public void run() {
assertEquals(map.remove(key), equals);
@ -231,8 +221,8 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
});
}
protected void assertConsistencyAwareGetEquals(final Map<String, V> map, final String key,
final Object equals) throws InterruptedException {
protected void assertConsistencyAwareGetEquals(final Map<String, V> map, final String key, final Object equals)
throws InterruptedException {
assertConsistencyAware(new Runnable() {
public void run() {
assertEquals(map.get(key), equals);
@ -240,8 +230,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
});
}
protected void assertConsistencyAwareKeySize(final Map<String, V> map, final int size)
throws InterruptedException {
protected void assertConsistencyAwareKeySize(final Map<String, V> map, final int size) throws InterruptedException {
assertConsistencyAware(new Runnable() {
public void run() {
assertEquals(map.keySet().size(), size);
@ -275,8 +264,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
});
}
protected void assertConsistencyAwareContainsKey(final Map<String, V> map)
throws InterruptedException {
protected void assertConsistencyAwareContainsKey(final Map<String, V> map) throws InterruptedException {
assertConsistencyAware(new Runnable() {
public void run() {
assert map.containsKey("one");
@ -284,8 +272,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
});
}
protected void assertConsistencyAwareDoesntContainKey(final Map<String, V> map)
throws InterruptedException {
protected void assertConsistencyAwareDoesntContainKey(final Map<String, V> map) throws InterruptedException {
assertConsistencyAware(new Runnable() {
public void run() {
assert !map.containsKey("one");
@ -306,8 +293,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
}
}
protected void assertConsistencyAwareNotEmpty(final Map<String, V> map)
throws InterruptedException {
protected void assertConsistencyAwareNotEmpty(final Map<String, V> map) throws InterruptedException {
assertConsistencyAware(new Runnable() {
public void run() {
assert !map.isEmpty();
@ -323,18 +309,16 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
});
}
abstract protected void putStringWithMD5(Map<String, V> map, String key, String value)
throws InterruptedException, ExecutionException, TimeoutException;
abstract protected void putStringWithMD5(Map<String, V> map, String key, String value) throws InterruptedException,
ExecutionException, TimeoutException;
protected void fourLeftRemovingOne(Map<String, V> map) throws InterruptedException {
map.remove("one");
assertConsistencyAwareMapSize(map, 4);
assertConsistencyAwareKeySetEquals(map, new TreeSet<String>(ImmutableSet.of("two", "three",
"four", "five")));
assertConsistencyAwareKeySetEquals(map, new TreeSet<String>(ImmutableSet.of("two", "three", "four", "five")));
}
protected void assertConsistencyAwareMapSize(final Map<String, V> map, final int size)
throws InterruptedException {
protected void assertConsistencyAwareMapSize(final Map<String, V> map, final int size) throws InterruptedException {
assertConsistencyAware(new Runnable() {
public void run() {
assertEquals(map.size(), size);
@ -343,12 +327,10 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
}
@Test(groups = { "integration", "live" })
public abstract void testPut() throws IOException, InterruptedException, ExecutionException,
TimeoutException;
public abstract void testPut() throws IOException, InterruptedException, ExecutionException, TimeoutException;
@Test(groups = { "integration", "live" })
public void testListContainer() throws InterruptedException, ExecutionException,
TimeoutException {
public void testListContainer() throws InterruptedException, ExecutionException, TimeoutException {
String containerNameName = getContainerName();
try {
ListableMap<?, ?> map = (ListableMap<?, ?>) createMap(context, containerNameName);
@ -358,8 +340,8 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
}
}
protected void assertConsistencyAwareListContainer(final ListableMap<?, ?> map,
final String containerNameName) throws InterruptedException {
protected void assertConsistencyAwareListContainer(final ListableMap<?, ?> map, final String containerNameName)
throws InterruptedException {
assertConsistencyAware(new Runnable() {
public void run() {
assertTrue(Iterables.size(map.list()) >= 0);

View File

@ -40,7 +40,7 @@ public interface BoxDotNetClient {
/*
* Note all these delegate to methods in BoxDotNetAsyncClient with a specified or inherited timeout.
* The singatures should match those of BoxDotNetAsyncClient, except the returnvals should not be
* wrapped in a ListenableFuture
* wrapped in a Future
*/
String list();

View File

@ -1,7 +1,5 @@
package org.jclouds.chef;
import java.util.Set;
import org.jclouds.chef.domain.Node;
import org.jclouds.chef.internal.BaseChefService;
@ -26,11 +24,11 @@ public interface ChefService {
void deleteAllClientsAndNodesInList(Iterable<String> names);
Set<Node> getNodes();
Iterable<? extends Node> getNodes();
Set<Node> getNodesWithNamesMatching(Predicate<String> nodeNameSelector);
Iterable<? extends Node> getNodesWithNamesMatching(Predicate<String> nodeNameSelector);
Set<Node> getNodesNamed(Iterable<String> names);
Iterable<? extends Node> getNodesNamed(Iterable<String> names);
void updateAutomaticAttributesOnNode(String nodeName);
}

View File

@ -2,8 +2,6 @@ package org.jclouds.chef.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
@ -72,17 +70,17 @@ public class BaseChefService implements ChefService {
}
@Override
public Set<Node> getNodes() {
public Iterable<? extends Node> getNodes() {
return getNodes.execute();
}
@Override
public Set<Node> getNodesWithNamesMatching(Predicate<String> nodeNameSelector) {
public Iterable<? extends Node> getNodesWithNamesMatching(Predicate<String> nodeNameSelector) {
return getNodes.execute(nodeNameSelector);
}
@Override
public Set<Node> getNodesNamed(Iterable<String> names) {
public Iterable<? extends Node> getNodesNamed(Iterable<String> names) {
return getNodes.execute(names);
}

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.chef.strategy;
import java.util.Set;
import org.jclouds.chef.domain.Node;
import org.jclouds.chef.strategy.internal.GetNodesImpl;
@ -34,9 +32,9 @@ import com.google.inject.ImplementedBy;
@ImplementedBy(GetNodesImpl.class)
public interface GetNodes {
Set<Node> execute();
Iterable<? extends Node> execute();
Set<Node> execute(Predicate<String> nodeNameSelector);
Iterable<? extends Node> execute(Predicate<String> nodeNameSelector);
Set<Node> execute(Iterable<String> toGet);
Iterable<? extends Node> execute(Iterable<String> toGet);
}

View File

@ -68,7 +68,7 @@ public class CleanupStaleNodesAndClientsImpl implements CleanupStaleNodesAndClie
final Calendar expired = Calendar.getInstance();
expired.setTime(new Date());
expired.add(Calendar.SECOND, -secondsStale);
Iterable<Node> staleNodes = filter(getAllNodes.execute(new Predicate<String>() {
Iterable<? extends Node> staleNodes = filter(getAllNodes.execute(new Predicate<String>() {
@Override
public boolean apply(String input) {

View File

@ -35,7 +35,7 @@ import org.jclouds.chef.reference.ChefConstants;
import org.jclouds.chef.strategy.DeleteAllClientsAndNodesInList;
import org.jclouds.logging.Logger;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.concurrent.Future;
import com.google.inject.Inject;
/**
@ -68,7 +68,7 @@ public class DeleteAllClientsAndNodesInListImpl implements DeleteAllClientsAndNo
@Override
public void execute(Iterable<String> names) {
Map<String, Exception> exceptions = newHashMap();
Map<String, ListenableFuture<?>> responses = newHashMap();
Map<String, Future<?>> responses = newHashMap();
for (String name : names) {
responses.put(name, chefAsyncClient.deleteClient(name));
responses.put(name, chefAsyncClient.deleteNode(name));

View File

@ -18,17 +18,11 @@
*/
package org.jclouds.chef.strategy.internal;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Maps.newHashMap;
import static com.google.common.collect.Sets.newHashSet;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import static org.jclouds.concurrent.ConcurrentUtils.transformParallel;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import javax.annotation.Resource;
import javax.inject.Named;
@ -42,8 +36,8 @@ import org.jclouds.chef.reference.ChefConstants;
import org.jclouds.chef.strategy.GetNodes;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Inject;
/**
@ -74,39 +68,26 @@ public class GetNodesImpl implements GetNodes {
}
@Override
public Set<Node> execute() {
public Iterable<? extends Node> execute() {
return execute(chefClient.listNodes());
}
@Override
public Set<Node> execute(Predicate<String> nodeNameSelector) {
public Iterable<? extends Node> execute(Predicate<String> nodeNameSelector) {
return execute(filter(chefClient.listNodes(), nodeNameSelector));
}
@Override
public Set<Node> execute(Iterable<String> toGet) {
Map<String, Exception> exceptions = newHashMap();
final Set<Node> nodes = newHashSet();
Map<String, ListenableFuture<?>> responses = newHashMap();
for (String nodeName : toGet) {
final ListenableFuture<? extends Node> future = chefAsyncClient.getNode(nodeName);
future.addListener(new Runnable() {
public Iterable<? extends Node> execute(Iterable<String> toGet) {
return transformParallel(toGet, new Function<String, Future<Node>>() {
@Override
public void run() {
try {
nodes.add(future.get());
} catch (InterruptedException e) {
propagate(e);
} catch (ExecutionException e) {
propagate(e);
public Future<Node> apply(String from) {
return chefAsyncClient.getNode(from);
}
}, userExecutor, maxTime, logger, "getting nodes");
}
}, sameThreadExecutor());
responses.put(nodeName, future);
}
exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, String.format("getting nodes: %s", toGet));
if (exceptions.size() > 0)
throw new RuntimeException(String.format("errors getting nodes: %s: %s", toGet, exceptions));
return nodes;
}
}

View File

@ -23,6 +23,7 @@
*/
package org.jclouds.chef.strategy.internal;
import static com.google.common.collect.Iterables.size;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
@ -69,24 +70,24 @@ public class GetNodesImplLiveTest extends BaseChefStrategyLiveTest {
@Test
public void testExecute() {
assert strategy.execute().size() > 0;
assert size(strategy.execute()) > 0;
}
@Test
public void testExecutePredicateOfString() {
assertEquals(strategy.execute(new Predicate<String>() {
assertEquals(size(strategy.execute(new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.startsWith(prefix);
}
}).size(), 2);
})), 2);
}
@Test
public void testExecuteIterableOfString() {
assertEquals(strategy.execute(ImmutableSet.of(prefix, prefix + 1)).size(), 2);
assertEquals(size(strategy.execute(ImmutableSet.of(prefix, prefix + 1))), 2);
}
}

View File

@ -27,7 +27,6 @@ import static org.jclouds.chef.reference.ChefConstants.CHEF_NODE;
import static org.jclouds.chef.reference.ChefConstants.CHEF_ROLE;
import static org.jclouds.chef.reference.ChefConstants.CHEF_SERVICE_CLIENT;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Set;
import java.util.Map.Entry;
@ -41,18 +40,18 @@ import org.jclouds.chef.ChefClient;
import org.jclouds.chef.ChefContext;
import org.jclouds.chef.ChefService;
import org.jclouds.chef.reference.ChefConstants;
import org.jclouds.chef.servlet.functions.InitParamsToProperties;
import org.jclouds.logging.Logger;
import org.jclouds.logging.jdk.JDKLogger;
import org.jclouds.rest.RestContextFactory;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.concurrent.Future;
/**
* Registers a new node in Chef and binds its name to
* {@link ChefConstants.CHEF_NODE}, its role to {@link ChefConstants.CHEF_ROLE}
* and the {@link ChefService} for the client to
* {@link ChefConstants.CHEF_SERVICE_CLIENT} upon initialized. Deletes the node
* and client when the context is destroyed.
* Registers a new node in Chef and binds its name to {@link ChefConstants.CHEF_NODE}, its role to
* {@link ChefConstants.CHEF_ROLE} and the {@link ChefService} for the client to
* {@link ChefConstants.CHEF_SERVICE_CLIENT} upon initialized. Deletes the node and client when the
* context is destroyed.
*
* @author Adrian Cole
*/
@ -60,18 +59,11 @@ public class ChefRegistrationListener implements ServletContextListener {
private Logger logger = new JDKLogger.JDKLoggerFactory().getLogger(ChefRegistrationListener.class.getName());
@SuppressWarnings("unchecked")
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
try {
logger.debug("starting initialization");
Properties overrides = new Properties();
Enumeration<String> e = servletContextEvent.getServletContext().getInitParameterNames();
while (e.hasMoreElements()) {
String propertyName = e.nextElement();
overrides.setProperty(propertyName, servletContextEvent.getServletContext().getInitParameter(propertyName));
}
Properties overrides = InitParamsToProperties.INSTANCE.apply(servletContextEvent);
String role = getInitParam(servletContextEvent, CHEF_ROLE);
logger.trace("creating validator connection");
@ -105,8 +97,8 @@ public class ChefRegistrationListener implements ServletContextListener {
}
private String findNextClientAndNodeName(ChefService validatorService, String prefix) {
ListenableFuture<Set<String>> nodes = validatorService.getContext().getAsyncApi().listNodes();
ListenableFuture<Set<String>> clients = validatorService.getContext().getAsyncApi().listClients();
Future<Set<String>> nodes = validatorService.getContext().getAsyncApi().listNodes();
Future<Set<String>> clients = validatorService.getContext().getAsyncApi().listClients();
try {
String nodeName;
Set<String> names = newHashSet(concat(nodes.get(), clients.get()));

View File

@ -0,0 +1,47 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.chef.servlet.functions;
import java.util.Enumeration;
import java.util.Properties;
import javax.inject.Singleton;
import javax.servlet.ServletContextEvent;
import com.google.common.base.Function;
/**
*
* @author Adrian Cole
*/
@Singleton
public class InitParamsToProperties implements Function<ServletContextEvent, Properties> {
public static final InitParamsToProperties INSTANCE = new InitParamsToProperties();
public Properties apply(ServletContextEvent servletContextEvent) {
Properties overrides = new Properties();
Enumeration<?> e = servletContextEvent.getServletContext().getInitParameterNames();
while (e.hasMoreElements()) {
String propertyName = e.nextElement().toString();
overrides.setProperty(propertyName, servletContextEvent.getServletContext().getInitParameter(propertyName));
}
return overrides;
}
}

View File

@ -18,6 +18,8 @@
*/
package org.jclouds.compute.domain;
import java.util.NoSuchElementException;
import org.jclouds.compute.internal.TemplateBuilderImpl;
import org.jclouds.compute.options.TemplateOptions;
@ -73,6 +75,9 @@ public interface TemplateBuilder {
/**
* Configure this template to start in a specific location
*
* @throws NoSuchElementException
* if location matches the id specified
*/
TemplateBuilder locationId(String locationId);

View File

@ -27,12 +27,13 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.compute.util.ComputeServiceUtils.installNewCredentials;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import static org.jclouds.concurrent.ConcurrentUtils.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.Nullable;
import javax.annotation.Resource;
@ -75,7 +76,7 @@ import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
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.Futures;
/**
*
@ -110,7 +111,8 @@ public class BaseComputeService implements ComputeService {
ListNodesStrategy listNodesStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
DestroyNodeStrategy destroyNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
Provider<TemplateOptions> templateOptionsProvider, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated, ComputeUtils utils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.context = checkNotNull(context, "context");
@ -151,8 +153,7 @@ public class BaseComputeService implements ComputeService {
.getProviderId(), template.getOptions());
Set<NodeMetadata> nodes = Sets.newHashSet();
Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
Map<?, ListenableFuture<Void>> responses = runNodesAndAddToSetStrategy.execute(tag, count, template, nodes,
badNodes);
Map<?, Future<Void>> responses = runNodesAndAddToSetStrategy.execute(tag, count, template, nodes, badNodes);
Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger, "starting nodes");
if (executionExceptions.size() > 0 || badNodes.size() > 0) {
throw new RunNodesException(tag, count, template, nodes, executionExceptions, badNodes);
@ -195,21 +196,26 @@ public class BaseComputeService implements ComputeService {
@Override
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> destroying nodes matching(%s)", filter);
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
final Set<NodeMetadata> destroyedNodes = Sets.newLinkedHashSet();
for (final NodeMetadata node : nodesMatchingFilterAndNotTerminated(filter)) {
responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
Set<NodeMetadata> set = Sets.newLinkedHashSet(transformParallel(nodesMatchingFilterAndNotTerminated(filter),
new Function<NodeMetadata, Future<NodeMetadata>>() {
// TODO make an async interface instead of re-wrapping
@Override
public Void call() throws Exception {
destroyNode(node.getId());
destroyedNodes.add(node);
return null;
public Future<NodeMetadata> apply(final NodeMetadata from) {
return executor.submit(new Callable<NodeMetadata>() {
@Override
public NodeMetadata call() throws Exception {
destroyNode(from.getId());
return from;
}
}), executor));
});
}
awaitCompletion(responses, executor, null, logger, "destroying nodes");
logger.debug("<< destroyed");
return destroyedNodes;
}, executor, null, logger, "destroying nodes"));
logger.debug("<< destroyed(%d)", set.size());
return set;
}
private Iterable<? extends NodeMetadata> nodesMatchingFilterAndNotTerminated(Predicate<NodeMetadata> filter) {
@ -220,9 +226,9 @@ public class BaseComputeService implements ComputeService {
* {@inheritDoc}
*/
@Override
public Set<? extends ComputeMetadata> listNodes() {
public Set<ComputeMetadata> listNodes() {
logger.debug(">> listing nodes");
Set<? extends ComputeMetadata> set = Sets.newLinkedHashSet(listNodesStrategy.list());
Set<ComputeMetadata> set = Sets.newLinkedHashSet(listNodesStrategy.list());
logger.debug("<< list(%d)", set.size());
return set;
}
@ -234,7 +240,7 @@ public class BaseComputeService implements ComputeService {
public Set<? extends NodeMetadata> listNodesDetailsMatching(Predicate<ComputeMetadata> filter) {
checkNotNull(filter, "filter");
logger.debug(">> listing node details matching(%s)", filter);
Set<? extends NodeMetadata> set = Sets.newLinkedHashSet(listNodesStrategy.listDetailsOnNodesMatching(filter));
Set<NodeMetadata> set = Sets.newLinkedHashSet(listNodesStrategy.listDetailsOnNodesMatching(filter));
logger.debug("<< list(%d)", set.size());
return set;
}
@ -298,18 +304,15 @@ public class BaseComputeService implements ComputeService {
@Override
public void rebootNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> rebooting nodes matching(%s)", filter);
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
for (final NodeMetadata node : nodesMatchingFilterAndNotTerminated(filter)) {
responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
transformParallel(nodesMatchingFilterAndNotTerminated(filter), new Function<NodeMetadata, Future<Void>>() {
// TODO use native async
@Override
public Void call() throws Exception {
rebootNode(node.getId());
return null;
public Future<Void> apply(NodeMetadata from) {
rebootNode(from.getId());
return Futures.immediateFuture(null);
}
}), executor));
}
awaitCompletion(responses, executor, null, logger, "rebooting nodes");
}, executor, null, logger, "rebooting nodes");
logger.debug("<< rebooted");
}
@ -317,8 +320,8 @@ public class BaseComputeService implements ComputeService {
* {@inheritDoc}
*/
@Override
public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
Payload runScript) throws RunScriptOnNodesException {
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript)
throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE);
}
@ -328,18 +331,18 @@ public class BaseComputeService implements ComputeService {
@Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
final Payload runScript, @Nullable final RunScriptOptions options) throws RunScriptOnNodesException {
Iterable<? extends NodeMetadata> nodes = verifyParametersAndListNodes(filter, runScript,
(options != null) ? options : RunScriptOptions.NONE);
Iterable<NodeMetadata> nodes = verifyParametersAndListNodes(filter, runScript, (options != null) ? options
: RunScriptOptions.NONE);
final Map<NodeMetadata, ExecResponse> execs = Maps.newHashMap();
final Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
Map<NodeMetadata, Future<Void>> responses = Maps.newHashMap();
for (final NodeMetadata node : nodes) {
responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
responses.put(node, executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
try {
@ -363,7 +366,7 @@ public class BaseComputeService implements ComputeService {
}
return null;
}
}), executor));
}));
}
Map<?, Exception> exceptions = awaitCompletion(responses, executor, null, logger, "starting nodes");
@ -374,14 +377,14 @@ public class BaseComputeService implements ComputeService {
}
private Iterable<? extends NodeMetadata> verifyParametersAndListNodes(Predicate<NodeMetadata> filter,
Payload runScript, final RunScriptOptions options) {
private Iterable<NodeMetadata> verifyParametersAndListNodes(Predicate<NodeMetadata> filter, Payload runScript,
final RunScriptOptions options) {
checkNotNull(filter, "Filter must be provided");
checkNotNull(runScript, "The script (represented by bytes array - use \"script\".getBytes() must be provided");
checkNotNull(options, "options");
Iterable<? extends NodeMetadata> nodes = Iterables.filter(detailsOnAllNodes(), filter);
// TODO parallel
return Iterables.transform(nodes, new Function<NodeMetadata, NodeMetadata>() {
@Override
@ -405,8 +408,8 @@ public class BaseComputeService implements ComputeService {
});
}
private Iterable<? extends NodeMetadata> detailsOnAllNodes() {
return listNodesStrategy.listDetailsOnNodesMatching(NodePredicates.all());
private Set<? extends NodeMetadata> detailsOnAllNodes() {
return Sets.newLinkedHashSet(listNodesStrategy.listDetailsOnNodesMatching(NodePredicates.all()));
}
@Override

View File

@ -21,7 +21,6 @@ package org.jclouds.compute.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.and;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Lists.newArrayList;
import static org.jclouds.util.Utils.multiMax;
@ -79,7 +78,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
@VisibleForTesting
protected Architecture arch;
@VisibleForTesting
protected String locationId;
protected Location location;
@VisibleForTesting
protected String imageId;
@VisibleForTesting
@ -115,12 +114,20 @@ public class TemplateBuilderImpl implements TemplateBuilder {
this.defaultTemplateProvider = defaultTemplateProvider;
}
/**
* If the current location id is null, then we don't care where to launch a node.
*
* If the input location is null, then the data isn't location sensitive
*
* If the input location is a parent of the specified location, then we are ok.
*/
private final Predicate<ComputeMetadata> locationPredicate = new Predicate<ComputeMetadata>() {
@Override
public boolean apply(ComputeMetadata input) {
boolean returnVal = true;
if (locationId != null && input.getLocation() != null)
returnVal = locationId.equals(input.getLocation().getId());
if (location != null && input.getLocation() != null)
returnVal = location.equals(input.getLocation()) || location.getParent() != null
&& location.getParent().equals(input.getLocation());
return returnVal;
}
};
@ -286,7 +293,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
@Override
public TemplateBuilder fromSize(Size size) {
if (size.getLocation() != null)
this.locationId = size.getLocation().getId();
this.location = size.getLocation();
this.minCores = size.getCores();
this.minRam = size.getRam();
return this;
@ -298,7 +305,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
@Override
public TemplateBuilder fromImage(Image image) {
if (image.getLocation() != null)
this.locationId = image.getLocation().getId();
this.location = image.getLocation();
if (image.getOsFamily() != null)
this.os = image.getOsFamily();
if (image.getName() != null)
@ -346,7 +353,14 @@ public class TemplateBuilderImpl implements TemplateBuilder {
*/
@Override
public TemplateBuilder locationId(final String locationId) {
this.locationId = locationId;
this.location = Iterables.find(locations.get(), new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(locationId);
}
});
return this;
}
@ -379,12 +393,11 @@ public class TemplateBuilderImpl implements TemplateBuilder {
defaultTemplate.options(options);
return defaultTemplate.build();
}
if (locationId == null)
locationId = defaultLocation.getId();
if (location == null)
location = defaultLocation;
if (options == null)
options = optionsProvider.get();
logger.debug(">> searching params(%s)", this);
Location location = resolveLocation();
Size size = resolveSize(sizeSorter(), getImages());
Image image = resolveImage(size);
logger.debug("<< matched image(%s)", image);
@ -394,19 +407,6 @@ public class TemplateBuilderImpl implements TemplateBuilder {
return new TemplateImpl(image, size, location, options);
}
protected Location resolveLocation() {
Location location = find(locations.get(), new Predicate<Location>() {
@Override
public boolean apply(Location input) {
return input.getId().equals(locationId);
}
});
logger.debug("<< matched location(%s)", location);
return location;
}
protected Size resolveSize(Ordering<Size> sizeOrdering, final Iterable<? extends Image> images) {
Size size;
try {
@ -429,7 +429,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
});
size = sizeOrdering.max(filter(sizesThatAreCompatibleWithOurImages, sizePredicate));
} catch (NoSuchElementException exception) {
throw new NoSuchElementException("size didn't match: " + toString() + "\n" + sizes.get());
throw new NoSuchElementException("sizes don't support any images: " + toString() + "\n" + sizes.get() + "\n"
+ images);
}
logger.debug("<< matched size(%s)", size);
return size;
@ -468,7 +469,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
logger.trace("<< best images(%s)", maxImages);
return maxImages.get(maxImages.size() - 1);
} catch (NoSuchElementException exception) {
throw new NoSuchElementException("image didn't match: " + toString() + "\n" + getImages());
Set<? extends Image> images = getImages();
throw new NoSuchElementException("image didn't match: " + toString() + "\n" + images);
}
}
@ -608,7 +610,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
@VisibleForTesting
boolean nothingChangedExceptOptions() {
return os == null && arch == null && locationId == null && imageId == null && sizeId == null
return os == null && arch == null && location == null && imageId == null && sizeId == null
&& osDescription == null && imageVersion == null && imageName == null && imageDescription == null
&& minCores == 0 && minRam == 0 && !biggest && !fastest;
}
@ -625,7 +627,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
public String toString() {
return "[arch=" + arch + ", biggest=" + biggest + ", fastest=" + fastest + ", imageName=" + imageName
+ ", imageDescription=" + imageDescription + ", imageId=" + imageId + ", imageVersion=" + imageVersion
+ ", location=" + locationId + ", minCores=" + minCores + ", minRam=" + minRam + ", os=" + os
+ ", location=" + location + ", minCores=" + minCores + ", minRam=" + minRam + ", os=" + os
+ ", osDescription=" + osDescription + ", sizeId=" + sizeId + "]";
}

View File

@ -26,7 +26,7 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.strategy.impl.EncodeTagIntoNameRunNodesAndAddToSetStrategy;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.concurrent.Future;
import com.google.inject.ImplementedBy;
/**
@ -37,6 +37,6 @@ import com.google.inject.ImplementedBy;
@ImplementedBy(EncodeTagIntoNameRunNodesAndAddToSetStrategy.class)
public interface RunNodesAndAddToSetStrategy {
Map<?, ListenableFuture<Void>> execute(String tag, int count, Template template,
Map<?, Future<Void>> execute(String tag, int count, Template template,
Set<NodeMetadata> nodes, Map<NodeMetadata, Exception> badNodes);
}

View File

@ -19,13 +19,12 @@
package org.jclouds.compute.strategy.impl;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import java.security.SecureRandom;
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;
@ -47,7 +46,6 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ListenableFuture;
/**
* creates futures that correlate to
@ -55,8 +53,7 @@ import com.google.common.util.concurrent.ListenableFuture;
* @author Adrian Cole
*/
@Singleton
public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements
RunNodesAndAddToSetStrategy {
public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrategy {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@ -67,12 +64,9 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements
protected final ExecutorService executor;
@Inject
protected EncodeTagIntoNameRunNodesAndAddToSetStrategy(
AddNodeWithTagStrategy addNodeWithTagStrategy,
ListNodesStrategy listNodesStrategy,
@Named("NAMING_CONVENTION") String nodeNamingConvention,
ComputeUtils utils,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
protected EncodeTagIntoNameRunNodesAndAddToSetStrategy(AddNodeWithTagStrategy addNodeWithTagStrategy,
ListNodesStrategy listNodesStrategy, @Named("NAMING_CONVENTION") String nodeNamingConvention,
ComputeUtils utils, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.addNodeWithTagStrategy = addNodeWithTagStrategy;
this.listNodesStrategy = listNodesStrategy;
this.nodeNamingConvention = nodeNamingConvention;
@ -81,51 +75,43 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements
}
/**
* This implementation gets a list of acceptable node names to encode the tag
* into, then it simultaneously runs the nodes and applies options to them.
* This implementation gets a list of acceptable node names to encode the tag into, then it
* simultaneously runs the nodes and applies options to them.
*/
@Override
public Map<?, ListenableFuture<Void>> execute(final String tag,
final int count, final Template template,
final Set<NodeMetadata> nodes,
final Map<NodeMetadata, Exception> badNodes) {
Map<String, ListenableFuture<Void>> responses = Maps.newHashMap();
public Map<?, Future<Void>> execute(final String tag, final int count, final Template template,
final Set<NodeMetadata> nodes, final Map<NodeMetadata, Exception> badNodes) {
Map<String, Future<Void>> responses = Maps.newHashMap();
for (final String name : getNextNames(tag, template, count)) {
responses.put(name, makeListenable(executor
.submit(new Callable<Void>() {
responses.put(name, executor.submit(new Callable<Void>() {
@Override
public Void call() throws Exception {
NodeMetadata node = null;
logger.debug(">> starting node(%s) tag(%s)", name, tag);
node = addNodeWithTagStrategy.execute(tag, name, template);
logger.debug("<< %s node(%s)", node.getState(), node
.getId());
utils
.runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(
node, badNodes, nodes, template.getOptions())
.call();
logger.debug("<< %s node(%s)", node.getState(), node.getId());
utils.runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(node, badNodes, nodes,
template.getOptions()).call();
return null;
}
}), executor));
}));
}
return responses;
}
/**
* Find the next node names that can be used. These will be derived from the
* tag and the template. We will pre-allocate a specified quantity, and
* attempt to verify that there is no name conflict with the current service.
* Find the next node names that can be used. These will be derived from the tag and the
* template. We will pre-allocate a specified quantity, and attempt to verify that there is no
* name conflict with the current service.
*
* @param tag
* @param count
* @param template
* @return
*/
protected Set<String> getNextNames(final String tag,
final Template template, int count) {
protected Set<String> getNextNames(final String tag, final Template template, int count) {
Set<String> names = Sets.newHashSet();
Iterable<? extends ComputeMetadata> currentNodes = listNodesStrategy
.list();
Iterable<? extends ComputeMetadata> currentNodes = listNodesStrategy.list();
int maxTries = 100;
int currentTries = 0;
while (names.size() < count && currentTries++ < maxTries) {
@ -145,16 +131,14 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements
}
/**
* Get a name using a random mechanism that still ties all nodes in a tag
* together.
* Get a name using a random mechanism that still ties all nodes in a tag together.
*
* This implementation will pass the tag and a hex formatted random number to
* the configured naming convention.
* This implementation will pass the tag and a hex formatted random number to the configured
* naming convention.
*
*/
protected String getNextName(final String tag, final Template template) {
return String.format(nodeNamingConvention, tag, Integer
.toHexString(new SecureRandom().nextInt(4095)));
return String.format(nodeNamingConvention, tag, Integer.toHexString(new SecureRandom().nextInt(4095)));
}
}

View File

@ -180,12 +180,12 @@ public class StubComputeServiceContextModule extends AbstractModule {
private NodeState state;
private final ExecutorService service;
public StubNodeMetadata(String providerId, String name, String id, Location location,
URI uri, Map<String, String> userMetadata, String tag, Image image, NodeState state,
Iterable<String> publicAddresses, Iterable<String> privateAddresses,
Map<String, String> extra, Credentials credentials, ExecutorService service) {
super(providerId, name, id, location, uri, userMetadata, tag, image, state,
publicAddresses, privateAddresses, extra, credentials);
public StubNodeMetadata(String providerId, String name, String id, Location location, URI uri,
Map<String, String> userMetadata, String tag, Image image, NodeState state,
Iterable<String> publicAddresses, Iterable<String> privateAddresses, Map<String, String> extra,
Credentials credentials, ExecutorService service) {
super(providerId, name, id, location, uri, userMetadata, tag, image, state, publicAddresses, privateAddresses,
extra, credentials);
this.setState(state, 0);
this.service = service;
}
@ -227,12 +227,10 @@ public class StubComputeServiceContextModule extends AbstractModule {
private final String passwordPrefix;
@Inject
public StubAddNodeWithTagStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes,
Location location, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
@Named("NODE_ID") Provider<Integer> idProvider,
@Named("PUBLIC_IP_PREFIX") String publicIpPrefix,
@Named("PRIVATE_IP_PREFIX") String privateIpPrefix,
@Named("PASSWORD_PREFIX") String passwordPrefix) {
public StubAddNodeWithTagStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes, Location location,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
@Named("NODE_ID") Provider<Integer> idProvider, @Named("PUBLIC_IP_PREFIX") String publicIpPrefix,
@Named("PRIVATE_IP_PREFIX") String privateIpPrefix, @Named("PASSWORD_PREFIX") String passwordPrefix) {
this.nodes = nodes;
this.location = location;
this.service = Executors.newCachedThreadPool();
@ -244,14 +242,12 @@ public class StubComputeServiceContextModule extends AbstractModule {
@Override
public NodeMetadata execute(String tag, String name, Template template) {
checkArgument(location.equals(template.getLocation()), "invalid location: "
+ template.getLocation());
checkArgument(location.equals(template.getLocation()), "invalid location: " + template.getLocation());
int id = idProvider.get();
StubNodeMetadata node = new StubNodeMetadata(id + "", name, id + "", location, null,
ImmutableMap.<String, String> of(), tag, template.getImage(), NodeState.PENDING,
ImmutableSet.<String> of(publicIpPrefix + id), ImmutableSet
.<String> of(privateIpPrefix + id), ImmutableMap.<String, String> of(),
new Credentials("root", passwordPrefix + id), service);
StubNodeMetadata node = new StubNodeMetadata(id + "", name, id + "", location, null, ImmutableMap
.<String, String> of(), tag, template.getImage(), NodeState.PENDING, ImmutableSet
.<String> of(publicIpPrefix + id), ImmutableSet.<String> of(privateIpPrefix + id), ImmutableMap
.<String, String> of(), new Credentials("root", passwordPrefix + id), service);
nodes.put(id, node);
node.setState(NodeState.RUNNING, 100);
return node;
@ -289,8 +285,7 @@ public class StubComputeServiceContextModule extends AbstractModule {
}
@Override
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(
Predicate<ComputeMetadata> filter) {
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
return Iterables.filter(nodes.values(), filter);
}
}
@ -363,18 +358,16 @@ public class StubComputeServiceContextModule extends AbstractModule {
@Provides
@Singleton
protected Set<? extends Size> provideSizes() {
return ImmutableSet.of(new StubSize("small", 1, 1740, 160, ImmutableSet
.of(Architecture.X86_32)), new StubSize("medium", 4, 7680, 850, ImmutableSet
.of(Architecture.X86_64)), new StubSize("large", 8, 15360, 1690, ImmutableSet
.of(Architecture.X86_64)));
return ImmutableSet.<Size> of(new StubSize("small", 1, 1740, 160, ImmutableSet.of(Architecture.X86_32)),
new StubSize("medium", 4, 7680, 850, ImmutableSet.of(Architecture.X86_64)), new StubSize("large", 8,
15360, 1690, ImmutableSet.of(Architecture.X86_64)));
}
private static class StubSize extends org.jclouds.compute.domain.internal.SizeImpl {
/** The serialVersionUID */
private static final long serialVersionUID = -1842135761654973637L;
StubSize(String type, int cores, int ram, int disk,
Iterable<Architecture> supportedArchitectures) {
StubSize(String type, int cores, int ram, int disk, Iterable<Architecture> supportedArchitectures) {
super(type, type, type, null, null, ImmutableMap.<String, String> of(), cores, ram, disk,
architectureIn(supportedArchitectures));
}
@ -383,14 +376,14 @@ public class StubComputeServiceContextModule extends AbstractModule {
@Provides
@Singleton
protected Set<? extends Image> provideImages(Location defaultLocation) {
return ImmutableSet.of(new ImageImpl("1", OsFamily.UBUNTU.name(), "1", defaultLocation, null,
ImmutableMap.<String, String> of(), "stub ubuntu 32", "", OsFamily.UBUNTU,
"ubuntu 64", Architecture.X86_64, new Credentials("root", null)), new ImageImpl("2",
OsFamily.UBUNTU.name(), "2", defaultLocation, null, ImmutableMap
.<String, String> of(), "stub ubuntu 64", "", OsFamily.UBUNTU, "ubuntu 64",
Architecture.X86_64, new Credentials("root", null)), new ImageImpl("3",
OsFamily.CENTOS.name(), "3", defaultLocation, null, ImmutableMap
.<String, String> of(), "stub centos 64", "", OsFamily.CENTOS, "centos 64",
String parentId = defaultLocation.getParent().getId();
return ImmutableSet.<Image> of(new ImageImpl("1", OsFamily.UBUNTU.name(), parentId + "/1", defaultLocation
.getParent(), null, ImmutableMap.<String, String> of(), "stub ubuntu 32", "", OsFamily.UBUNTU,
"ubuntu 64", Architecture.X86_64, new Credentials("root", null)), new ImageImpl("2", OsFamily.UBUNTU
.name(), parentId + "/2", defaultLocation.getParent(), null, ImmutableMap.<String, String> of(),
"stub ubuntu 64", "", OsFamily.UBUNTU, "ubuntu 64", Architecture.X86_64, new Credentials("root", null)),
new ImageImpl("3", OsFamily.CENTOS.name(), parentId + "/3", defaultLocation.getParent(), null,
ImmutableMap.<String, String> of(), "stub centos 64", "", OsFamily.CENTOS, "centos 64",
Architecture.X86_64, new Credentials("root", null)));
}
@ -398,7 +391,8 @@ public class StubComputeServiceContextModule extends AbstractModule {
@Singleton
Location getLocation(@org.jclouds.rest.annotations.Provider String providerName) {
Location provider = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
return new LocationImpl(LocationScope.ZONE, providerName, providerName, provider);
Location region = new LocationImpl(LocationScope.REGION, providerName+"region", providerName+"region", provider);
return new LocationImpl(LocationScope.ZONE, providerName+"zone", providerName+"zone", region);
}
@Provides

View File

@ -23,7 +23,6 @@ import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.compute.util.ComputeServiceUtils.installNewCredentials;
import static org.jclouds.compute.util.ComputeServiceUtils.isKeyAuth;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import java.util.List;
import java.util.Map;
@ -31,6 +30,7 @@ import java.util.Set;
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 javax.annotation.Nullable;
@ -49,7 +49,6 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.util.ComputeServiceUtils.SshCallable;
import org.jclouds.concurrent.ConcurrentUtils;
import org.jclouds.io.Payload;
import org.jclouds.logging.Logger;
import org.jclouds.net.IPSocket;
@ -61,7 +60,6 @@ import com.google.common.base.Throwables;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Inject;
/**
@ -84,8 +82,9 @@ public class ComputeUtils {
@Inject
public ComputeUtils(Predicate<IPSocket> socketTester,
@Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning, GetNodeMetadataStrategy getNode,
Timeouts timeouts, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning,
GetNodeMetadataStrategy getNode, Timeouts timeouts,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.nodeRunning = nodeRunning;
this.timeouts = timeouts;
@ -95,19 +94,20 @@ public class ComputeUtils {
this.executor = executor;
}
public Map<?, ListenableFuture<Void>> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(
final TemplateOptions options, Iterable<NodeMetadata> runningNodes, final Set<NodeMetadata> goodNodes,
public Map<?, Future<Void>> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(final TemplateOptions options,
Iterable<NodeMetadata> runningNodes, final Set<NodeMetadata> goodNodes,
final Map<NodeMetadata, Exception> badNodes) {
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
Map<NodeMetadata, Future<Void>> responses = Maps.newHashMap();
for (final NodeMetadata node : runningNodes) {
responses.put(node, makeListenable(executor.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(
node, badNodes, goodNodes, options)), executor));
responses.put(node, executor.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(node, badNodes,
goodNodes, options)));
}
return responses;
}
public Callable<Void> runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(final NodeMetadata node,
final Map<NodeMetadata, Exception> badNodes, final Set<NodeMetadata> goodNodes, final TemplateOptions options) {
final Map<NodeMetadata, Exception> badNodes, final Set<NodeMetadata> goodNodes,
final TemplateOptions options) {
return new Callable<Void>() {
@Override
public Void call() throws Exception {
@ -190,11 +190,12 @@ public class ComputeUtils {
return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script, false);
}
public Map<SshCallable<?>, ?> runCallablesOnNode(NodeMetadata node, Iterable<? extends SshCallable<?>> parallel,
public Map<SshCallable<?>, ?> runCallablesOnNode(NodeMetadata node, Iterable<SshCallable<?>> parallel,
@Nullable SshCallable<?> last) {
checkState(this.sshFactory != null, "runScript requested, but no SshModule configured");
checkNodeHasPublicIps(node);
checkNotNull(node.getCredentials().credential, "credentials.key for node " + node.getId());
checkNotNull(node.getCredentials(), "credentials for node " + node.getId());
checkNotNull(node.getCredentials().credential, "credentials.credential for node " + node.getId());
SshClient ssh = createSshClientOncePortIsListeningOnNode(node);
try {
ssh.connect();
@ -205,8 +206,8 @@ public class ComputeUtils {
}
}
private Map<SshCallable<?>, ?> runTasksUsingSshClient(Iterable<? extends SshCallable<?>> parallel,
SshCallable<?> last, SshClient ssh) {
private Map<SshCallable<?>, ?> runTasksUsingSshClient(Iterable<SshCallable<?>> parallel, SshCallable<?> last,
SshClient ssh) {
Map<SshCallable<?>, Object> responses = Maps.newHashMap();
if (Iterables.size(parallel) > 0) {
responses.putAll(runCallablesUsingSshClient(parallel, ssh));
@ -231,13 +232,13 @@ public class ComputeUtils {
return ssh;
}
private Map<SshCallable<?>, Object> runCallablesUsingSshClient(Iterable<? extends SshCallable<?>> parallel,
SshClient ssh) {
Map<SshCallable<?>, ListenableFuture<?>> parallelResponses = Maps.newHashMap();
// TODO refactor
private Map<SshCallable<?>, Object> runCallablesUsingSshClient(Iterable<SshCallable<?>> parallel, SshClient ssh) {
Map<SshCallable<?>, Future<?>> parallelResponses = Maps.newHashMap();
for (SshCallable<?> callable : parallel) {
callable.setConnection(ssh, logger);
parallelResponses.put(callable, ConcurrentUtils.makeListenable(executor.submit(callable), executor));
parallelResponses.put(callable, executor.submit(callable));
}
Map<SshCallable<?>, Exception> exceptions = awaitCompletion(parallelResponses, executor, null, logger, "ssh");
@ -248,9 +249,9 @@ public class ComputeUtils {
}
@SuppressWarnings("unchecked")
public <T> Map<SshCallable<?>, T> transform(Map<SshCallable<?>, ListenableFuture<?>> responses) {
public <T> Map<SshCallable<?>, T> transform(Map<SshCallable<?>, Future<?>> responses) {
Map<SshCallable<?>, T> actualResponses = Maps.newHashMap();
for (Map.Entry<SshCallable<?>, ListenableFuture<?>> entry : responses.entrySet()) {
for (Map.Entry<SshCallable<?>, Future<?>> entry : responses.entrySet()) {
try {
actualResponses.put(entry.getKey(), (T) entry.getValue().get());
} catch (InterruptedException e) {

View File

@ -26,7 +26,7 @@ import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Sets.filter;
import static com.google.common.collect.Sets.newHashSet;
import static com.google.common.collect.Sets.newLinkedHashSet;
import static com.google.common.collect.Sets.newTreeSet;
import static org.jclouds.compute.options.RunScriptOptions.Builder.overrideCredentialsWith;
import static org.jclouds.compute.predicates.NodePredicates.TERMINATED;
@ -197,8 +197,8 @@ public abstract class BaseComputeServiceLiveTest {
try {
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, options);
Credentials good = nodes.iterator().next().getCredentials();
assert good.identity != null;
assert good.credential != null;
assert good.identity != null : nodes;
assert good.credential != null : nodes;
Image image = get(nodes, 0).getImage();
try {
@ -336,8 +336,9 @@ public abstract class BaseComputeServiceLiveTest {
.append("echo \"name=jdkrepository\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.append(
"echo \"baseurl=http://ec2-us-east-mirror.rightscale.com/epel/5/i386/\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.append("echo \"enabled=1\" >> /etc/yum.repos.d/CentOS-Base.repo\n").append(
"yum --nogpgcheck -y install java-1.6.0-openjdk\n").append(
.append("echo \"enabled=1\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
.append("yum --nogpgcheck -y install java-1.6.0-openjdk\n")
.append(
"echo \"export PATH=\\\"/usr/lib/jvm/jre-1.6.0-openjdk/bin/:\\$PATH\\\"\" >> /root/.bashrc\n")
.toString();
default:
@ -347,8 +348,8 @@ public abstract class BaseComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired")
public void testGet() throws Exception {
Set<? extends NodeMetadata> metadataSet = newHashSet(filter(client.listNodesDetailsMatching(all()), and(
withTag(tag), not(TERMINATED))));
Set<? extends NodeMetadata> nodes = client.listNodesDetailsMatching(all());
Set<? extends NodeMetadata> metadataSet = newLinkedHashSet(filter(nodes, and(withTag(tag), not(TERMINATED))));
for (NodeMetadata node : nodes) {
metadataSet.remove(node);
NodeMetadata metadata = client.getNodeMetadata(node.getId());

View File

@ -32,6 +32,8 @@ import java.io.IOException;
import java.io.Serializable;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
import org.easymock.IArgumentMatcher;
import org.jclouds.compute.domain.Architecture;
@ -86,7 +88,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getArchitecture(), Architecture.X86_64);
assertEquals(defaultTemplate.getImage().getOsFamily(), OsFamily.UBUNTU);
assertEquals(defaultTemplate.getLocation().getId(), provider);
assertEquals(defaultTemplate.getLocation().getId(), provider + "zone");
assertEquals(defaultTemplate.getSize().getCores(), 4.0d);
}
@ -361,4 +363,9 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
super.testTemplateMatch();
}
@Override
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
super.cleanup();
}
}

View File

@ -118,7 +118,6 @@ public class TemplateBuilderImplTest {
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
expect(defaultLocation.getId()).andReturn("locationId").atLeastOnce();
expect(optionsProvider.get()).andReturn(new TemplateOptions());
expect(image.getLocation()).andReturn(defaultLocation).atLeastOnce();
@ -163,7 +162,6 @@ public class TemplateBuilderImplTest {
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
expect(defaultLocation.getId()).andReturn("locationId").atLeastOnce();
expect(optionsProvider.get()).andReturn(new TemplateOptions());
expect(image.getId()).andReturn("imageId").atLeastOnce();
expect(image.getLocation()).andReturn(defaultLocation).atLeastOnce();
@ -208,7 +206,6 @@ public class TemplateBuilderImplTest {
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
expect(defaultLocation.getId()).andReturn("locationId").atLeastOnce();
expect(optionsProvider.get()).andReturn(new TemplateOptions());
expect(image.getId()).andReturn("notImageId").atLeastOnce();
@ -321,8 +318,6 @@ public class TemplateBuilderImplTest {
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
TemplateOptions defaultOptions = createMock(TemplateOptions.class);
expect(optionsProvider.get()).andReturn(defaultOptions);
replay(defaultOptions);
replay(defaultLocation);
replay(optionsProvider);
@ -390,7 +385,6 @@ public class TemplateBuilderImplTest {
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
TemplateOptions defaultOptions = createMock(TemplateOptions.class);
expect(defaultLocation.getId()).andReturn("foo");
expect(optionsProvider.get()).andReturn(defaultOptions);
replay(defaultOptions);
@ -402,7 +396,7 @@ public class TemplateBuilderImplTest {
templateBuilderProvider);
try {
template.imageId("foo").build();
template.imageId("region/ami").build();
assert false;
} catch (NoSuchElementException e) {
@ -430,18 +424,9 @@ public class TemplateBuilderImplTest {
TemplateOptions from = provideTemplateOptions();
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
expect(defaultLocation.getId()).andReturn("foo");
// expect(defaultLocation.getId()).andReturn("foo");
expect(optionsProvider.get()).andReturn(from);
// expect(optionsProvider.get()).andReturn(provideTemplateOptions());
expect(from.getInboundPorts()).andReturn(new int[] { 22 });
// expect(from.getRunScript()).andReturn(null);
// expect(from.getPrivateKey()).andReturn(null);
// expect(from.getPublicKey()).andReturn(null);
// expect(from.getPort()).andReturn(null);
// expect(from.isIncludeMetadata()).andReturn(false);
// expect(from.shouldBlockUntilRunning()).andReturn(true);
replay(defaultLocation);
replay(optionsProvider);
@ -451,7 +436,7 @@ public class TemplateBuilderImplTest {
templateBuilderProvider);
try {
template.imageId("foo").options(provideTemplateOptions()).build();
template.imageId("region/ami").options(provideTemplateOptions()).build();
assert false;
} catch (NoSuchElementException e) {

View File

@ -18,41 +18,111 @@
*/
package org.jclouds.concurrent;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Maps.newHashMap;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.annotation.Nullable;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.logging.Logger;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.ForwardingObject;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.ExecutionList;
import com.google.common.util.concurrent.ForwardingFuture;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.inject.Inject;
/**
* Adapt things missing from Guava.
* Adapt things from Guava.
*
* @author Adrian Cole
*/
@Singleton
public class ConcurrentUtils {
@Resource
private static Logger logger = Logger.CONSOLE;
public static <T> Map<T, Exception> awaitCompletion(Map<T, ? extends ListenableFuture<?>> responses,
ExecutorService executor, @Nullable Long maxTime, final Logger logger, final String logPrefix) {
@Inject(optional = true)
@Named(Constants.PROPERTY_MAX_RETRIES)
private static int maxRetries = 5;
@Inject(optional = true)
private static BackoffLimitedRetryHandler retryHandler = BackoffLimitedRetryHandler.INSTANCE;
public static <F, T> Iterable<T> transformParallel(final Iterable<F> fromIterable,
final Function<? super F, Future<T>> function) {
return transformParallel(fromIterable, function, sameThreadExecutor(), null);
}
public static <F, T> Iterable<T> transformParallel(final Iterable<F> fromIterable,
final Function<? super F, Future<T>> function, ExecutorService exec, @Nullable Long maxTime) {
return transformParallel(fromIterable, function, exec, maxTime, logger, "transforming");
}
public static <F, T> Iterable<T> transformParallel(final Iterable<F> fromIterable,
final Function<? super F, Future<T>> function, ExecutorService exec, @Nullable Long maxTime, Logger logger,
String logPrefix) {
return transformParallel(fromIterable, function, exec, maxTime, logger, logPrefix, retryHandler, maxRetries);
}
public static <F, T> Iterable<T> transformParallel(Iterable<F> fromIterable,
Function<? super F, Future<T>> function, ExecutorService exec, @Nullable Long maxTime, Logger logger,
String logPrefix, BackoffLimitedRetryHandler retryHandler, int maxRetries) {
Map<F, Exception> exceptions = newHashMap();
Map<F, Future<T>> responses = newHashMap();
for (int i = 0; i < maxRetries; i++) {
for (F from : fromIterable) {
responses.put(from, function.apply(from));
}
exceptions = awaitCompletion(responses, exec, maxTime, logger, logPrefix);
if (exceptions.size() > 0) {
fromIterable = exceptions.keySet();
retryHandler.imposeBackoffExponentialDelay(i + 1, String.format("error %s: %s: %s", logPrefix,
fromIterable, exceptions));
} else {
break;
}
}
if (exceptions.size() > 0)
throw new RuntimeException(String.format("error %s: %s: %s", logPrefix, fromIterable, exceptions));
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) {
if (responses.size() == 0)
return ImmutableMap.of();
final int total = responses.size();
@ -61,8 +131,8 @@ public class ConcurrentUtils {
final AtomicInteger errors = new AtomicInteger(0);
final long start = System.currentTimeMillis();
final Map<T, Exception> errorMap = Maps.newHashMap();
for (final Entry<T, ? extends ListenableFuture<?>> future : responses.entrySet()) {
future.getValue().addListener(new Runnable() {
for (final java.util.Map.Entry<T, ? extends Future<?>> future : responses.entrySet()) {
makeListenable(future.getValue(), exec).addListener(new Runnable() {
public void run() {
try {
future.getValue().get();
@ -74,7 +144,7 @@ public class ConcurrentUtils {
}
doneSignal.countDown();
}
}, executor);
}, exec);
}
try {
if (maxTime != null)
@ -99,6 +169,22 @@ public class ConcurrentUtils {
return errorMap;
}
public static <T> Iterable<T> unwrap(Iterable<Future<T>> values) {
return Iterables.transform(values, new Function<Future<T>, T>() {
@Override
public T apply(Future<T> from) {
try {
return from.get();
} catch (InterruptedException e) {
Throwables.propagate(e);
} catch (ExecutionException e) {
Throwables.propagate(e);
}
return null;
}
});
}
private static void logException(Logger logger, String logPrefix, int total, int complete, int errors, long start,
Exception e) {
String message = message(logPrefix, total, complete, errors, start);
@ -123,49 +209,55 @@ public class ConcurrentUtils {
if (future instanceof ListenableFuture<?>) {
return (ListenableFuture<T>) future;
}
return new ListenableFutureAdapter<T>(executorService, future);
return ListenableFutureAdapter.create(future, executorService);
}
/**
* Just like {@code Futures#ListenableFutureAdapter} except that we pass in an executorService.
* <p/>
* Temporary hack until http://code.google.com/p/guava-libraries/issues/detail?id=317 is fixed.
* 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.
*/
private static class ListenableFutureAdapter<T> extends ForwardingFuture<T> implements ListenableFuture<T> {
public static <I, O> ListenableFuture<O> compose(Future<I> future, final Function<? super I, ? extends O> function,
ExecutorService executorService) {
if (future instanceof ListenableFutureAdapter<?>) {
ListenableFutureAdapter<I> lf = (ListenableFutureAdapter<I>) future;
if (lf.futureListener.executor.getClass().isAnnotationPresent(SingleThreaded.class))
return LazyListenableFutureFunctionAdapter.create(((ListenableFutureAdapter<I>) future).futureListener,
function);
else
return Futures.compose(lf, function, executorService);
} else if (executorService.getClass().isAnnotationPresent(SingleThreaded.class)) {
return LazyListenableFutureFunctionAdapter.create(future, function, executorService);
} else {
return Futures.compose(makeListenable(future, executorService), function, executorService);
}
}
private final Executor adapterExecutor;
// The execution list to hold our listeners.
public static class FutureListener<T> {
private final Future<T> future;
private final ExecutorService executor;
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;
ListenableFutureAdapter(ExecutorService executorService, final Future<T> delegate) {
this.adapterExecutor = executorService;
this.delegate = delegate;
static <T> FutureListener<T> create(Future<T> future, ExecutorService executor) {
return new FutureListener<T>(future, executor);
}
@Override
protected Future<T> delegate() {
return delegate;
private FutureListener(Future<T> future, ExecutorService executor) {
this.future = checkNotNull(future, "future");
this.executor = checkNotNull(executor, "executor");
}
/* @Override */
public void addListener(Runnable listener, Executor 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.
// the future to finish, and when it is done will run the listeners.
if (!hasListeners.get() && hasListeners.compareAndSet(false, true)) {
adapterExecutor.execute(new Runnable() {
executor.execute(new Runnable() {
/* @Override */
public void run() {
try {
delegate.get();
future.get();
} catch (CancellationException e) {
// The task was cancelled, so it is done, run the listeners.
} catch (InterruptedException e) {
@ -181,5 +273,289 @@ public class ConcurrentUtils {
}
executionList.add(listener, exec);
}
Future<T> getFuture() {
return future;
}
ExecutorService getExecutor() {
return executor;
}
}
public static class ListenableFutureAdapter<T> extends ForwardingFuture<T> implements ListenableFuture<T> {
private final FutureListener<T> futureListener;
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);
}
}
public static class LazyListenableFutureFunctionAdapter<I, O> extends ForwardingObject implements
ListenableFuture<O> {
private final FutureListener<I> futureListener;
private final Function<? super I, ? extends O> function;
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);
}
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();
}
}
/**
* Taken from {@link MoreExecutors#sameThreadExecutor} as it was hidden and therefore incapable
* of instanceof checks.
*
*
*
* Creates an executor service that runs each task in the thread that invokes {@code
* execute/submit}, as in {@link CallerRunsPolicy} This applies both to individually submitted
* tasks and to collections of tasks submitted via {@code invokeAll} or {@code invokeAny}. In the
* latter case, tasks will run serially on the calling thread. Tasks are run to completion before
* a {@code Future} is returned to the caller (unless the executor has been shutdown).
*
* <p>
* Although all tasks are immediately executed in the thread that submitted the task, this
* {@code ExecutorService} imposes a small locking overhead on each task submission in order to
* implement shutdown and termination behavior.
*
* <p>
* The implementation deviates from the {@code ExecutorService} specification with regards to the
* {@code shutdownNow} method. First, "best-effort" with regards to canceling running tasks is
* implemented as "no-effort". No interrupts or other attempts are made to stop threads executing
* tasks. Second, the returned list will always be empty, as any submitted task is considered to
* have started execution. This applies also to tasks given to {@code invokeAll} or {@code
* invokeAny} which are pending serial execution, even the subset of the tasks that have not yet
* started execution. It is unclear from the {@code ExecutorService} specification if these
* should be included, and it's much easier to implement the interpretation that they not be.
* Finally, a call to {@code shutdown} or {@code shutdownNow} may result in concurrent calls to
* {@code invokeAll/invokeAny} throwing RejectedExecutionException, although a subset of the
* tasks may already have been executed.
*/
public static ExecutorService sameThreadExecutor() {
return new SameThreadExecutorService();
}
// See sameThreadExecutor javadoc for behavioral notes.
@SingleThreaded
public static class SameThreadExecutorService extends AbstractExecutorService {
/**
* Lock used whenever accessing the state variables (runningTasks, shutdown,
* terminationCondition) of the executor
*/
private final Lock lock = new ReentrantLock();
/** Signaled after the executor is shutdown and running tasks are done */
private final Condition termination = lock.newCondition();
private SameThreadExecutorService() {
}
/*
* Conceptually, these two variables describe the executor being in one of three states: -
* Active: shutdown == false - Shutdown: runningTasks > 0 and shutdown == true - Terminated:
* runningTasks == 0 and shutdown == true
*/
private int runningTasks = 0;
private boolean shutdown = false;
@Override
public void execute(Runnable command) {
startTask();
try {
command.run();
} finally {
endTask();
}
}
@Override
public boolean isShutdown() {
lock.lock();
try {
return shutdown;
} finally {
lock.unlock();
}
}
@Override
public void shutdown() {
lock.lock();
try {
shutdown = true;
} finally {
lock.unlock();
}
}
// See sameThreadExecutor javadoc for unusual behavior of this method.
@Override
public List<Runnable> shutdownNow() {
shutdown();
return Collections.emptyList();
}
@Override
public boolean isTerminated() {
lock.lock();
try {
return shutdown && runningTasks == 0;
} finally {
lock.unlock();
}
}
@Override
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
long nanos = unit.toNanos(timeout);
lock.lock();
try {
for (;;) {
if (isTerminated()) {
return true;
} else if (nanos <= 0) {
return false;
} else {
nanos = termination.awaitNanos(nanos);
}
}
} finally {
lock.unlock();
}
}
/**
* Checks if the executor has been shut down and increments the running task count.
*
* @throws RejectedExecutionException
* if the executor has been previously shutdown
*/
private void startTask() {
lock.lock();
try {
if (isShutdown()) {
throw new RejectedExecutionException("Executor already shutdown");
}
runningTasks++;
} finally {
lock.unlock();
}
}
/**
* Decrements the running task count.
*/
private void endTask() {
lock.lock();
try {
runningTasks--;
if (isTerminated()) {
termination.signalAll();
}
} finally {
lock.unlock();
}
}
}
}

View File

@ -18,6 +18,8 @@
*/
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.TimeUnit;
@ -27,30 +29,35 @@ import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
/**
* Transforms the result of a future as soon as it is available.
* Transforms the exceptions in a future upon get
*
* Temporarily here until the following is resolved: <a
* href="http://code.google.com/p/guava-libraries/issues/detail?id=310"> guava issue 310</a>
*
* @author Adrian Cole
*/
public class FutureExceptionParser<T> implements ListenableFuture<T> {
public class ExceptionParsingListenableFuture<T> implements ListenableFuture<T> {
private final ListenableFuture<T> delegate;
private final ListenableFuture<T> future;
private final Function<Exception, T> function;
public FutureExceptionParser(ListenableFuture<T> delegate, Function<Exception, T> function) {
this.delegate = delegate;
this.function = function;
public static <T> ExceptionParsingListenableFuture<T> create(ListenableFuture<T> future,
Function<Exception, T> function) {
return new ExceptionParsingListenableFuture<T>(future, function);
}
public ExceptionParsingListenableFuture(ListenableFuture<T> future, Function<Exception, T> function) {
this.future = checkNotNull(future);
this.function = checkNotNull(function);
}
public boolean cancel(boolean mayInterruptIfRunning) {
return delegate.cancel(mayInterruptIfRunning);
return future.cancel(mayInterruptIfRunning);
}
public T get() throws InterruptedException, ExecutionException {
try {
return delegate.get();
return future.get();
} catch (Exception e) {
return attemptConvert(e);
}
@ -60,26 +67,24 @@ public class FutureExceptionParser<T> implements ListenableFuture<T> {
return function.apply(e instanceof ExecutionException ? (Exception) e.getCause() : e);
}
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException,
TimeoutException {
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
try {
return delegate.get(timeout, unit);
return future.get(timeout, unit);
} catch (Exception e) {
return attemptConvert(e);
}
}
public boolean isCancelled() {
return delegate.isCancelled();
return future.isCancelled();
}
public boolean isDone() {
return delegate.isDone();
return future.isDone();
}
@Override
public void addListener(Runnable listener, Executor exec) {
delegate.addListener(listener, exec);
future.addListener(listener, exec);
}
}

View File

@ -18,13 +18,12 @@
*/
package org.jclouds.concurrent;
import static com.google.common.base.Throwables.propagate;
import static org.jclouds.util.Utils.getFirstThrowableOfType;
import java.util.concurrent.TimeoutException;
import org.jclouds.util.Utils;
import com.google.common.base.Supplier;
import com.google.common.base.Throwables;
/**
*
* @author Adrian Cole
@ -44,15 +43,15 @@ public class RetryOnTimeOutExceptionSupplier<T> implements Supplier<T> {
ex = null;
return delegate.get();
} catch (Exception e) {
if ((ex = Utils.getFirstThrowableOfType(e, TimeoutException.class)) != null)
if ((ex = getFirstThrowableOfType(e, TimeoutException.class)) != null)
continue;
Throwables.propagate(e);
propagate(e);
assert false;
return null;
}
}
if (ex != null)
Throwables.propagate(ex);
propagate(ex);
assert false;
return null;
}

View File

@ -32,6 +32,8 @@ import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import static org.jclouds.concurrent.ConcurrentUtils.*;
import org.jclouds.concurrent.SingleThreaded;
import org.jclouds.lifecycle.Closer;
import org.jclouds.logging.Logger;
@ -65,8 +67,7 @@ public class ExecutorServiceModule extends AbstractModule {
public void close() throws IOException {
List<Runnable> runnables = service.shutdownNow();
if (runnables.size() > 0)
logger.warn("when shutting down executor %s, runnables outstanding: %s", service,
runnables);
logger.warn("when shutting down executor %s, runnables outstanding: %s", service, runnables);
}
}
@ -74,11 +75,22 @@ public class ExecutorServiceModule extends AbstractModule {
private final ExecutorService ioExecutorFromConstructor;
@Inject
public ExecutorServiceModule(
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
public ExecutorServiceModule(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads) {
this.userExecutorFromConstructor = userThreads;
this.ioExecutorFromConstructor = ioThreads;
this.userExecutorFromConstructor = checkNotGuavaSameThreadExecutor(userThreads);
this.ioExecutorFromConstructor = checkNotGuavaSameThreadExecutor(ioThreads);
}
private ExecutorService checkNotGuavaSameThreadExecutor(ExecutorService executor) {
// we detect behavior based on the class
if (executor != null && !(executor.getClass().isAnnotationPresent(SingleThreaded.class))
&& executor.getClass().getSimpleName().indexOf("SameThread") != -1) {
Logger.CONSOLE.warn(
"please switch from %s to %s or annotate your same threaded executor with @SingleThreaded", executor
.getClass().getName(), SameThreadExecutorService.class.getName());
return sameThreadExecutor();
}
return executor;
}
public ExecutorServiceModule() {
@ -92,8 +104,7 @@ public class ExecutorServiceModule extends AbstractModule {
@Provides
@Singleton
@Named(Constants.PROPERTY_USER_THREADS)
ExecutorService provideExecutorService(@Named(Constants.PROPERTY_USER_THREADS) int count,
Closer closer) {
ExecutorService provideExecutorService(@Named(Constants.PROPERTY_USER_THREADS) int count, Closer closer) {
if (userExecutorFromConstructor != null)
return shutdownOnClose(userExecutorFromConstructor, closer);
return shutdownOnClose(newThreadPoolNamed("user thread %d", count), closer);
@ -102,8 +113,7 @@ public class ExecutorServiceModule extends AbstractModule {
@Provides
@Singleton
@Named(Constants.PROPERTY_IO_WORKER_THREADS)
ExecutorService provideIOExecutor(@Named(Constants.PROPERTY_IO_WORKER_THREADS) int count,
Closer closer) {
ExecutorService provideIOExecutor(@Named(Constants.PROPERTY_IO_WORKER_THREADS) int count, Closer closer) {
if (ioExecutorFromConstructor != null)
return shutdownOnClose(ioExecutorFromConstructor, closer);
return shutdownOnClose(newThreadPoolNamed("i/o thread %d", count), closer);
@ -117,20 +127,19 @@ public class ExecutorServiceModule extends AbstractModule {
@VisibleForTesting
static ExecutorService newCachedThreadPoolNamed(String name) {
return Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat(name)
.setThreadFactory(Executors.defaultThreadFactory()).build());
return Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat(name).setThreadFactory(
Executors.defaultThreadFactory()).build());
}
@VisibleForTesting
static ExecutorService newThreadPoolNamed(String name, int maxCount) {
return maxCount == 0 ? newCachedThreadPoolNamed(name) : newScalingThreadPoolNamed(name,
maxCount);
return maxCount == 0 ? newCachedThreadPoolNamed(name) : newScalingThreadPoolNamed(name, maxCount);
}
@VisibleForTesting
static ExecutorService newScalingThreadPoolNamed(String name, int maxCount) {
return newScalingThreadPool(1, maxCount, 60L * 1000, new ThreadFactoryBuilder()
.setNameFormat(name).setThreadFactory(Executors.defaultThreadFactory()).build());
return newScalingThreadPool(1, maxCount, 60L * 1000, new ThreadFactoryBuilder().setNameFormat(name)
.setThreadFactory(Executors.defaultThreadFactory()).build());
}
}

View File

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

View File

@ -20,7 +20,7 @@ package org.jclouds.http;
import java.util.concurrent.SynchronousQueue;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.concurrent.Future;
/**
* Used for passing objects for response processing
@ -32,11 +32,11 @@ public class HttpCommandRendezvous<T> {
private final HttpCommand command;
@SuppressWarnings("unchecked")
private final SynchronousQueue rendezvous;
private final ListenableFuture<T> future;
private final Future<T> future;
@SuppressWarnings("unchecked")
public HttpCommandRendezvous(HttpCommand command, SynchronousQueue rendezvous,
ListenableFuture<T> future) {
Future<T> future) {
this.command = command;
this.rendezvous = rendezvous;
this.future = future;
@ -53,14 +53,14 @@ public class HttpCommandRendezvous<T> {
}
public void cancel() {
getListenableFuture().cancel(true);
getFuture().cancel(true);
}
public HttpCommand getCommand() {
return command;
}
public ListenableFuture<T> getListenableFuture() {
public Future<T> getFuture() {
return future;
}

View File

@ -18,6 +18,8 @@
*/
package org.jclouds.http;
import java.util.concurrent.Future;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
@ -30,7 +32,7 @@ import com.google.common.util.concurrent.ListenableFuture;
public interface TransformingHttpCommandExecutorService {
/**
*
* Submits the command and transforms the result before requested via {@link ListenableFuture#get()}.
* Submits the command and transforms the result before requested via {@link Future#get()}.
*
* @param <T>
* type that is required from the value.

View File

@ -18,10 +18,13 @@
*/
package org.jclouds.http;
import static com.google.common.util.concurrent.Futures.compose;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.Constants;
import static org.jclouds.concurrent.ConcurrentUtils.*;
import com.google.common.base.Function;
import com.google.common.util.concurrent.ListenableFuture;
@ -32,21 +35,22 @@ import com.google.common.util.concurrent.ListenableFuture;
*
* @author Adrian Cole
*/
public class TransformingHttpCommandExecutorServiceImpl implements
TransformingHttpCommandExecutorService {
public class TransformingHttpCommandExecutorServiceImpl implements TransformingHttpCommandExecutorService {
private final HttpCommandExecutorService client;
private final ExecutorService userThreads;
@Inject
public TransformingHttpCommandExecutorServiceImpl(HttpCommandExecutorService client) {
public TransformingHttpCommandExecutorServiceImpl(HttpCommandExecutorService client,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads) {
this.client = client;
this.userThreads = userThreads;
}
/**
* {@inheritDoc}
*/
public <T> ListenableFuture<T> submit(HttpCommand command,
Function<HttpResponse, T> responseTransformer) {
return compose(client.submit(command), responseTransformer, sameThreadExecutor());
public <T> ListenableFuture<T> submit(HttpCommand command, Function<HttpResponse, T> responseTransformer) {
return compose(client.submit(command), responseTransformer, userThreads);
}
}

View File

@ -79,6 +79,9 @@ import com.google.inject.Inject;
*/
@Singleton
public class BackoffLimitedRetryHandler implements HttpRetryHandler, IOExceptionRetryHandler {
public static BackoffLimitedRetryHandler INSTANCE = new BackoffLimitedRetryHandler();
@Inject(optional = true)
@Named(Constants.PROPERTY_MAX_RETRIES)
private int retryCountLimit = 5;
@ -102,13 +105,11 @@ public class BackoffLimitedRetryHandler implements HttpRetryHandler, IOException
logger.warn("Cannot retry after server error, command is not replayable: %1$s", command);
return false;
} else if (command.getFailureCount() > retryCountLimit) {
logger.warn(
"Cannot retry after server error, command has exceeded retry limit %1$d: %2$s",
retryCountLimit, command);
logger.warn("Cannot retry after server error, command has exceeded retry limit %1$d: %2$s", retryCountLimit,
command);
return false;
} else {
imposeBackoffExponentialDelay(command.getFailureCount(), "server error: "
+ command.toString());
imposeBackoffExponentialDelay(command.getFailureCount(), "server error: " + command.toString());
return true;
}
}
@ -117,11 +118,9 @@ public class BackoffLimitedRetryHandler implements HttpRetryHandler, IOException
imposeBackoffExponentialDelay(50L, 2, failureCount, retryCountLimit, commandDescription);
}
public void imposeBackoffExponentialDelay(long period, int pow, int failureCount, int max,
String commandDescription) {
public void imposeBackoffExponentialDelay(long period, int pow, int failureCount, int max, String commandDescription) {
long delayMs = (long) (period * Math.pow(failureCount, pow));
logger.debug("Retry %d/%d: delaying for %d ms: %s", failureCount, retryCountLimit, delayMs,
commandDescription);
logger.debug("Retry %d/%d: delaying for %d ms: %s", failureCount, retryCountLimit, delayMs, commandDescription);
try {
Thread.sleep(delayMs);
} catch (InterruptedException e) {

View File

@ -19,7 +19,6 @@
package org.jclouds.http.internal;
import static com.google.common.io.ByteStreams.copy;
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
import static org.jclouds.http.HttpUtils.checkRequestHasContentLengthOrChunkedEncoding;
import static org.jclouds.http.HttpUtils.wirePayloadIfEnabled;
import static org.jclouds.util.Utils.getFirstThrowableOfType;
@ -29,6 +28,7 @@ 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;
@ -49,7 +49,6 @@ import org.jclouds.http.handlers.DelegatingRetryHandler;
import org.jclouds.logging.Logger;
import com.google.common.io.NullOutputStream;
import com.google.common.util.concurrent.ListenableFuture;
/**
*
@ -123,11 +122,12 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
}
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
public Future<HttpResponse> submit(HttpCommand command) {
HttpRequest request = command.getRequest();
checkRequestHasContentLengthOrChunkedEncoding(request,
"if the request has a payload, it must be set to chunked encoding or specify a content length: " + request);
return makeListenable(ioWorkerExecutor.submit(new HttpResponseCallable(command)), ioWorkerExecutor);
"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));
}
public class HttpResponseCallable implements Callable<HttpResponse> {

View File

@ -25,13 +25,20 @@ import java.lang.reflect.Type;
*/
public interface Json {
/**
* Serialize the object into json.
* Serialize the object into json. If the object is a generic type, use
* {@link #toJson(Object, Type)}
*/
String toJson(Object src);
/**
* Deserialize the generic object from json. If the object is not a generic
* type, use {@link #fromJson(Object, Class)}
* Serialize the generic object into json. If the object is not a generic, use
* {@link #toJson(Object, Type)}
*/
String toJson(Object src, Type type);
/**
* Deserialize the generic object from json. If the object is not a generic type, use
* {@link #fromJson(Object, Class)}
*/
<T> T fromJson(String json, Type type);

View File

@ -56,4 +56,9 @@ public class GsonWrapper implements Json {
return gson.toJson(src);
}
@Override
public String toJson(Object src, Type type) {
return gson.toJson(src, type);
}
}

View File

@ -22,7 +22,7 @@ import java.net.URI;
import org.jclouds.rest.internal.RestContextImpl;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.concurrent.Future;
import com.google.inject.ImplementedBy;
/**
@ -41,7 +41,7 @@ public interface RestContext<S, A> {
/**
* low-level api to the cloud. Threadsafe implementations will return a singleton.
*
* @return a connection to the cloud where all methods return {@link ListenableFuture}s
* @return a connection to the cloud where all methods return {@link Future}s
*/
A getAsyncApi();

View File

@ -19,7 +19,7 @@
package org.jclouds.rest;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.concurrent.ConcurrentUtils.sameThreadExecutor;
import static org.jclouds.Constants.PROPERTY_API;
import static org.jclouds.Constants.PROPERTY_API_VERSION;
import static org.jclouds.Constants.PROPERTY_CREDENTIAL;

View File

@ -20,16 +20,17 @@ package org.jclouds.rest;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Splitter.on;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.size;
import static com.google.common.collect.Iterables.transform;
import static java.util.Collections.EMPTY_LIST;
import static org.jclouds.util.Utils.initContextBuilder;
import static org.jclouds.util.Utils.modulesForProviderInProperties;
import static org.jclouds.util.Utils.propagateAuthorizationOrOriginalException;
import static org.jclouds.util.Utils.resolveContextBuilderClass;
import static org.jclouds.util.Utils.resolvePropertiesBuilderClass;
import static org.jclouds.util.Utils.toStringAndClose;
import java.io.File;
import java.io.IOException;
@ -43,14 +44,12 @@ import org.jclouds.PropertiesBuilder;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.Files;
import com.google.inject.Module;
/**
* Helper class to instantiate {@code RestContext} instances.
* "blobstore.properties"
* Helper class to instantiate {@code RestContext} instances. "blobstore.properties"
*
* At least one property is needed needed per context:
* <ul>
@ -216,8 +215,8 @@ public class RestContextFactory {
private final Properties properties;
/**
* Initializes with the default properties built-in to jclouds. This is
* typically stored in the classpath resource {@code rest.properties}
* Initializes with the default properties built-in to jclouds. This is typically stored in the
* classpath resource {@code rest.properties}
*
* @see RestContextFactory#getPropertiesFromResource
*/
@ -226,8 +225,8 @@ public class RestContextFactory {
}
/**
* Initializes with the default properties built-in to jclouds. This is
* typically stored in the classpath resource {@code filename}
* Initializes with the default properties built-in to jclouds. This is typically stored in the
* classpath resource {@code filename}
*
* @param filename
* name of the properties file to initialize from
@ -240,8 +239,8 @@ public class RestContextFactory {
}
/**
* Loads the default properties that define the {@code RestContext} objects.
* <h3>properties file format</h3>
* Loads the default properties that define the {@code RestContext} objects. <h3>properties file
* format</h3>
*
* Two properties are needed per context:
* <ul>
@ -271,8 +270,7 @@ public class RestContextFactory {
}
/**
* Initializes the {@code RestContext} definitions from the specified
* properties.
* Initializes the {@code RestContext} definitions from the specified properties.
*/
@Inject
public RestContextFactory(Properties properties) {
@ -284,16 +282,16 @@ public class RestContextFactory {
}
/**
* @see RestContextFactory#createContextBuilder(String, Properties,
* Iterable<? extends Module>, Properties)
* @see RestContextFactory#createContextBuilder(String, Properties, Iterable<? extends Module>,
* Properties)
*/
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, Properties overrides) {
return createContextBuilder(provider, null, null, ImmutableSet.<Module> of(), overrides);
}
/**
* @see RestContextFactory#createContextBuilder(String, Properties,
* Iterable<? extends Module>, Properties)
* @see RestContextFactory#createContextBuilder(String, Properties, Iterable<? extends Module>,
* Properties)
*/
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, Iterable<Module> modules) {
return createContextBuilder(provider, null, null, modules, NO_PROPERTIES);
@ -301,21 +299,20 @@ public class RestContextFactory {
/**
*
* Identity will be found by searching {@code jclouds.identity} failing that
* {@code provider.identity} where provider corresponds to the parameter.
* Same pattern is used for credential ({@code jclouds.credential} failing
* that {@code provider.credential}).
* Identity will be found by searching {@code jclouds.identity} failing that {@code
* provider.identity} where provider corresponds to the parameter. Same pattern is used for
* credential ({@code jclouds.credential} failing that {@code provider.credential}).
*
* @param <S>
* Type of the provider specific client
* @param <A>
* Type of the provide specific async client (same as above, yet
* all methods return {@code Future} results)
* Type of the provide specific async client (same as above, yet all methods return
* {@code Future} results)
* @param provider
* name of the provider (ex. s3, bluelock, etc.)
* @param wiring
* defines how objects are bound to interfaces, pass in here to
* override this, or specify service implementations.
* defines how objects are bound to interfaces, pass in here to override this, or
* specify service implementations.
* @param overrides
* properties to pass to the context.
*/
@ -344,8 +341,8 @@ public class RestContextFactory {
* @param credential
* nullable, if credentials are present in the overrides
* @param wiring
* Configuration you'd like to pass to the context. Ex.
* ImmutableSet.<Module>of(new ExecutorServiceModule(myexecutor))
* Configuration you'd like to pass to the context. Ex. ImmutableSet.<Module>of(new
* ExecutorServiceModule(myexecutor))
* @param overrides
* properties to override defaults with.
* @return initialized context ready for use
@ -415,8 +412,7 @@ public class RestContextFactory {
"jclouds.credential", credential));
String syncClassName = props.getProperty(providerName + ".sync", null);
String asyncClassName = props.getProperty(providerName + ".async", null);
Iterable<Module> modules = concat(modulesFromProperty(props, "jclouds.modules"), modulesFromProperty(props,
providerName + ".modules"), wiring);
Iterable<Module> modules = concat(modulesForProviderInProperties(providerName, props), wiring);
Class<RestContextBuilder<S, A>> contextBuilderClass;
Class<PropertiesBuilder> propertiesBuilderClass;
@ -442,8 +438,8 @@ public class RestContextFactory {
return properties.getProperty(property);
else if (properties.containsKey(property + ".resource"))
try {
return org.jclouds.util.Utils.toStringAndClose(RestContextFactory.class.getResourceAsStream(properties
.getProperty(property + ".resource")));
return toStringAndClose(RestContextFactory.class.getResourceAsStream(properties.getProperty(property
+ ".resource")));
} catch (IOException e) {
throw new RuntimeException("error reading resource: " + properties.getProperty(property + ".resource"));
}
@ -457,31 +453,6 @@ public class RestContextFactory {
return credential;
}
static Iterable<Module> modulesFromProperty(Properties props, String property) {
String moduleClasses = props.getProperty(property, null);
Iterable<Module> modules = ImmutableSet.of();
if (moduleClasses != null) {
Iterable<String> transformer = ImmutableList.copyOf(on(',').split(moduleClasses));
modules = transform(transformer, new Function<String, Module>() {
@Override
public Module apply(String from) {
try {
return (Module) Class.forName(from).newInstance();
} catch (InstantiationException e) {
throw new RuntimeException("error instantiating " + from, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("error instantiating " + from, e);
} catch (ClassNotFoundException e) {
throw new RuntimeException("error instantiating " + from, e);
}
}
});
}
return modules;
}
public static <S, A> RestContextBuilder<S, A> createContextBuilder(ContextSpec<S, A> contextSpec) {
return createContextBuilder(contextSpec, NO_PROPERTIES);
}
@ -556,8 +527,7 @@ public class RestContextFactory {
}
/**
* @see RestContextFactory#createContextBuilder(String, String,String,
* Properties)
* @see RestContextFactory#createContextBuilder(String, String,String, Properties)
*/
public <S, A> RestContext<S, A> createContext(String provider, @Nullable String identity,
@Nullable String credential, Properties properties) {
@ -566,8 +536,7 @@ public class RestContextFactory {
}
/**
* @see RestContextFactory#createContextBuilder(String, String,String,
* Iterable)
* @see RestContextFactory#createContextBuilder(String, String,String, Iterable)
*/
public <S, A> RestContext<S, A> createContext(String provider, @Nullable String identity,
@Nullable String credential, Iterable<? extends Module> wiring) {
@ -576,8 +545,7 @@ public class RestContextFactory {
}
/**
* @see RestContextFactory#createContextBuilder(String, String,String,
* Iterable, Properties)
* @see RestContextFactory#createContextBuilder(String, String,String, Iterable, Properties)
*/
public <S, A> RestContext<S, A> createContext(String provider, @Nullable String identity,
@Nullable String credential, Iterable<? extends Module> wiring, Properties overrides) {
@ -610,8 +578,7 @@ public class RestContextFactory {
}
/**
* @see RestContextFactory#createContextBuilder(ContextSpec, Iterable,
* Properties)
* @see RestContextFactory#createContextBuilder(ContextSpec, Iterable, Properties)
*/
public static <S, A> RestContext<S, A> createContext(ContextSpec<S, A> contextSpec, Iterable<Module> modules,
Properties overrides) {

View File

@ -33,7 +33,7 @@ import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.Constants;
import org.jclouds.concurrent.FutureExceptionParser;
import org.jclouds.concurrent.ExceptionParsingListenableFuture;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.TransformingHttpCommand;
@ -91,14 +91,14 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
return delegateMap.get(new ClassMethodArgs(method.getReturnType(), method, args));
} else if (annotationProcessor.getDelegateOrNull(method) != null
&& ListenableFuture.class.isAssignableFrom(method.getReturnType())) {
return createFuture(method, args);
return createListenableFuture(method, args);
} else {
throw new RuntimeException("method is intended solely to set constants: " + method);
}
}
@SuppressWarnings("unchecked")
private ListenableFuture<?> createFuture(Method method, Object[] args) throws ExecutionException {
private ListenableFuture<?> createListenableFuture(Method method, Object[] args) throws ExecutionException {
method = annotationProcessor.getDelegateOrNull(method);
logger.trace("Converting %s.%s", declaring.getSimpleName(), method.getName());
Function<Exception, ?> exceptionParser = annotationProcessor
@ -136,7 +136,7 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
if (exceptionParser != null) {
logger.trace("Exceptions from %s.%s are parsed by %s", declaring.getSimpleName(), method.getName(),
exceptionParser.getClass().getSimpleName());
result = new FutureExceptionParser(result, exceptionParser);
result = new ExceptionParsingListenableFuture(result, exceptionParser);
}
return result;
}

View File

@ -22,8 +22,10 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.base.Predicates.notNull;
import static com.google.common.base.Splitter.on;
import static com.google.common.base.Throwables.getCausalChain;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.get;
@ -64,9 +66,11 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.io.OutputSupplier;
import com.google.inject.Module;
import com.google.inject.ProvisionException;
import com.google.inject.spi.Message;
@ -241,15 +245,14 @@ public class Utils {
}
/**
* Encode the given string with the given encoding, if possible. If the
* encoding fails with {@link UnsupportedEncodingException}, log a warning
* and fall back to the system's default encoding.
* Encode the given string with the given encoding, if possible. If the encoding fails with
* {@link UnsupportedEncodingException}, log a warning and fall back to the system's default
* encoding.
*
* @param str
* what to encode
* @param charsetName
* the name of a supported {@link java.nio.charset.Charset
* </code>charset<code>}
* the name of a supported {@link java.nio.charset.Charset </code>charset<code>}
* @return properly encoded String.
*/
public static byte[] encodeString(String str, String charsetName) {
@ -263,10 +266,9 @@ public class Utils {
}
/**
* Encode the given string with the UTF-8 encoding, the sane default. In the
* very unlikely event the encoding fails with
* {@link UnsupportedEncodingException}, log a warning and fall back to the
* system's default encoding.
* Encode the given string with the UTF-8 encoding, the sane default. In the very unlikely event
* the encoding fails with {@link UnsupportedEncodingException}, log a warning and fall back to
* the system's default encoding.
*
* @param str
* what to encode
@ -317,8 +319,7 @@ public class Utils {
}
/**
* Will throw an exception if the argument is null or empty. Accepts a custom
* error message.
* Will throw an exception if the argument is null or empty. Accepts a custom error message.
*
* @param nullableString
* string to verify. Can be null or empty.
@ -330,8 +331,8 @@ public class Utils {
}
/**
* Gets a set of supported providers. Idea stolen from pallets
* (supported-clouds). Uses rest.properties to populate the set.
* Gets a set of supported providers. Idea stolen from pallets (supported-clouds). Uses
* rest.properties to populate the set.
*
*/
public static Iterable<String> getSupportedProviders() {
@ -339,8 +340,8 @@ public class Utils {
}
/**
* Gets a set of supported providers. Idea stolen from pallets
* (supported-clouds). Uses rest.properties to populate the set.
* Gets a set of supported providers. Idea stolen from pallets (supported-clouds). Uses
* rest.properties to populate the set.
*
*/
@SuppressWarnings("unchecked")
@ -430,4 +431,37 @@ public class Utils {
return PropertiesBuilder.class;
}
}
public static Iterable<Module> modulesForProviderInProperties(String providerName, Properties props) {
return concat(modulesFromProperty(props, "jclouds.modules"),
modulesFromProperty(props, providerName + ".modules"));
}
public static Iterable<Module> modulesFromProperty(Properties props, String property) {
return modulesFromCommaDelimitedString(props.getProperty(property, null));
}
public static Iterable<Module> modulesFromCommaDelimitedString(String moduleClasses) {
Iterable<Module> modules = ImmutableSet.of();
if (moduleClasses != null) {
Iterable<String> transformer = ImmutableList.copyOf(on(',').split(moduleClasses));
modules = transform(transformer, new Function<String, Module>() {
@Override
public Module apply(String from) {
try {
return (Module) Class.forName(from).newInstance();
} catch (InstantiationException e) {
throw new RuntimeException("error instantiating " + from, e);
} catch (IllegalAccessException e) {
throw new RuntimeException("error instantiating " + from, e);
} catch (ClassNotFoundException e) {
throw new RuntimeException("error instantiating " + from, e);
}
}
});
}
return modules;
}
}

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.concurrent;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.concurrent.ConcurrentUtils.sameThreadExecutor;
import static java.util.concurrent.Executors.newCachedThreadPool;
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
import static org.jclouds.concurrent.FuturesTestingUtils.CALLABLE_DURATION;
@ -35,7 +35,7 @@ import java.util.concurrent.ExecutorService;
import org.jclouds.logging.Logger;
import org.testng.annotations.Test;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.concurrent.Future;
/**
* Tests behavior of ConcurrentUtils
@ -54,7 +54,7 @@ public class ConcurrentUtilsTest {
ExecutorService chainExecutor = sameThreadExecutor();
long start = System.currentTimeMillis();
Map<String, ListenableFuture<Long>> responses = runCallables(callableExecutor, chainExecutor);
Map<String, Future<Long>> responses = runCallables(callableExecutor, chainExecutor);
checkTimeThresholds(expectedMin, expectedMax, expectedOverhead, start, responses);
}
@ -68,7 +68,7 @@ public class ConcurrentUtilsTest {
ExecutorService chainExecutor = sameThreadExecutor();
long start = System.currentTimeMillis();
Map<String, ListenableFuture<Long>> responses = runCallables(callableExecutor, chainExecutor);
Map<String, Future<Long>> responses = runCallables(callableExecutor, chainExecutor);
Map<String, Exception> exceptions = awaitCompletion(responses, sameThreadExecutor(), null, Logger.CONSOLE,
"test same thread");
assertEquals(exceptions.size(), 0);

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